Documentation
¶
Overview ¶
Package inputs assembles one Wavefront evaluation from live cluster state: discovery, selector-overlap detection, source resolution, graph derivation and the engine evaluation over them.
It is read-only and side-effect free — no writes, no events, no metrics, no poller — so the reconciler and the CLI derive the *same* picture from the same reads: the reconciler adds execution, status and telemetry on top, while the CLI renders the Result directly. Every pass is a full recalculation from live inputs; nothing here reads back previously published status.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Capped ¶
func Capped[T any](list []T) []T
Capped bounds an exceptional-state list; the counts stay authoritative.
func HeldSources ¶
func HeldSources(res *Result) []wavefrontv1alpha1.HeldNode
HeldSources builds the capped, source-sorted hold ledger. It is the ONE list: consumers write exactly this to status.held and edge-trigger against exactly this, so the ledger written and the ledger diffed are byte-identical. A source beyond StatusListCap is counted in status.Nodes.Held but neither listed nor announced until a freed slot promotes it into the cap.
Types ¶
type GraphVerdict ¶
GraphVerdict is the structural verdict on one pass: the GraphValid condition in all but name.
type Hold ¶
Hold is one source's entry in the unified ledger that treats a hand-pin and a suspend alike: Manager is "" for a Suspend hold, which names no owning actor.
type HoldKind ¶
type HoldKind string
HoldKind distinguishes how a source is held: a foreign field manager owning spec.ref.commit, or spec.suspend. Both are reported identically by the engine (NodeResult.Held, engine.go SelfHeld/AncestorHeld) and must be reported identically by consumers.
const ( HoldHandPin HoldKind = wavefrontv1alpha1.HoldReasonHandPin HoldSuspend HoldKind = wavefrontv1alpha1.HoldReasonSuspend )
type Params ¶
type Params struct {
Wavefront *wavefrontv1alpha1.Wavefront
Adapter adapter.Adapter
Strategy selection.Strategy
// Observations is the caller's own coherent snapshot of the poller; nil
// (or a missing entry) means unobserved. Strict ordering for co-arriving
// changes is only structural if every node is evaluated against the same
// sweep, so the snapshot is taken by the caller — once, before anything
// reconfigures the poller — never re-read per source here.
Observations map[types.NamespacedName]gitpoll.Observation
}
Params is everything Build needs beyond the cluster reader.
type Result ¶
type Result struct {
// discovery
Nodes map[adapter.NodeRef]adapter.Node // selected set plus dependsOn closure
Selected map[adapter.NodeRef]bool
Missing map[adapter.NodeRef]bool // dependsOn targets that do not exist
// source resolution
Inputs map[adapter.NodeRef]engine.NodeInput
Repos map[types.NamespacedName]*sourcev1.GitRepository
// NodeBySource lists every selected, pinned node referencing a source,
// each slice in compareRefs order: a shared source's events and status
// attribution need every referencing node, not just whichever last
// overwrote a single value.
NodeBySource map[types.NamespacedName][]adapter.NodeRef
// Holds is the unified hold ledger: every source the engine reports Held
// for, whether a hand-pin (a foreign field manager owns spec.ref.commit)
// or a suspend (spec.suspend). It feeds counts.Held, status.held[], the
// HoldDetected/HoldReleased edge-trigger and the admission gate alike. A
// caller that discovers a further hold while executing (an SSA conflict,
// pin.ErrHeld) may add to it after Build returns.
Holds map[types.NamespacedName]Hold
Targets []gitpoll.Target
// UnsupportedSources lists managed sources whose ref style (currently:
// semver tracking, which only a future SemverWindow strategy could
// sequence) selection.TrackRef cannot resolve, demoted to gates.
// Recorded once per source and sorted, so a caller can announce each
// exactly once.
UnsupportedSources []types.NamespacedName
// fleet
Wavefronts *wavefrontv1alpha1.WavefrontList
Overlap string // name of the Wavefront whose selector overlaps this one
// graph and evaluation
Graph *graph.Graph
Cycles [][]adapter.NodeRef
Eval engine.Evaluation
// Resolved and GraphChecked record how far the pass got: an aborted pass
// has proven nothing about the fleet (Resolved false) and, before
// derivation, nothing about the graph either (GraphChecked false).
Resolved bool
GraphChecked bool
}
Result is one pass's complete read-only derivation.
It is returned non-nil even when Build fails, so a caller can still report whatever the pass managed to prove: Resolved and GraphChecked record how far it got, and every consumer must respect them rather than mistake a partial Result for a proven-empty fleet.
func Build ¶
Build performs one full read-only pass: discovery, overlap detection, source resolution, graph derivation and evaluation.
The Result is always non-nil, populated as far as the pass got, even when an error is returned.
func (*Result) GraphVerdict ¶
func (res *Result) GraphVerdict() GraphVerdict
GraphVerdict renders the structural verdict. A selector overlap outranks a cycle: overlap suppresses admissions fleet-wide and is the more urgent configuration error to report.
func (*Result) SkipAdmissions ¶
SkipAdmissions reports whether every write must be suppressed for the pass, without suppressing status: selector overlap is a configuration error, not a reason to go blind.
type Summary ¶
type Summary struct {
Counts wavefrontv1alpha1.NodeCounts
Phase wavefrontv1alpha1.Phase
// Blocked and Held are the capped status lists; Held is exactly
// HeldSources(res): the same capped, source-sorted list that both becomes
// status.held and is diffed pass-to-pass to edge-trigger the
// HoldDetected/HoldReleased events, rather than an unbounded internal
// ledger.
Blocked []wavefrontv1alpha1.BlockedNode
Held []wavefrontv1alpha1.HeldNode
// Members is every evaluated node's derived state, sorted by
// kind/namespace/name and capped at MembersCap; MembersOmitted counts the
// remainder. Write-only output: nothing here or in the reconciler ever
// reads it back — admissibility is re-derived from live cluster state on
// every pass, never from a previous status write.
Members []wavefrontv1alpha1.Member
MembersOmitted int
// BlockedByReason is uncapped, unlike Blocked: a gauge must count every
// blocked node, not just the ones that fit the status list.
BlockedByReason map[engine.BlockedReason]int
FetchFailures int
}
Summary is the whole publishable picture of one resolved pass: everything status carries, plus the uncapped by-reason tallies a caller may want for gauges. Deriving it here rather than in the reconciler is what lets the CLI re-derive byte-identical numbers from the same Result: summarisation is a pure function of the already-resolved evaluation, with no hidden state of its own to diverge from a live pass.
func Summarise ¶
Summarise derives the fleet counts, exceptional-state lists, members and phase from a completed evaluation. now supplies the fallback timestamp for a blocked node with no observation of its own; it is never used to make a decision, so a caller's clock choice cannot change what is reported.
Callers must only call this for a resolved Result: an aborted pass has derived nothing, and its zero values would claim a settled, empty fleet.