status

package
v1.0.0-beta.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 1, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package status contains release condition, digest, and history helpers.

Index

Constants

View Source
const (
	ReadyCondition          = meta.ReadyCondition       // "Ready"
	ReconcilingCondition    = meta.ReconcilingCondition // "Reconciling"
	StalledCondition        = meta.StalledCondition     // "Stalled"
	ModuleResolvedCondition = "ModuleResolved"
	DriftedCondition        = "Drifted"

	// ActiveCondition reports whether an accepted TransformerRegistration's
	// provider is serving, the second of the three states 0015:D3
	// defines. It is a separate condition from Ready because the two axes are
	// independent: Ready carries the acceptance verdict, and a claim can be
	// accepted and not yet active. Once Active=True it never goes False again
	// (see the latch in transformerregistration_controller.go).
	ActiveCondition = "Active"

	// ContractsFulfilledCondition reports whether every provider-fulfilled
	// contract the effective platform package defines has a provider
	// (0015:D18). It is a separate condition from Ready because
	// 0015:D18 makes an unfulfilled contract a report and never a refusal: the
	// package is generated, recorded and rendered against either way, so
	// folding this into Ready would turn a report into a gate. It describes
	// the package renders consume, which is why it is written on both
	// success paths and left untouched by a failure or a refusal.
	ContractsFulfilledCondition = "ContractsFulfilled"
)

Condition types. Ready, Reconciling, and Stalled are reexported from Flux meta for consistency.

View Source
const (
	SuspendedReason        = "Suspended"
	ResolutionFailedReason = "ResolutionFailed"
	RenderFailedReason     = "RenderFailed"
	// SkewRefusedReason: Ready=False, the platform's skew policy is Refuse and
	// the module requires a newer catalog build than the platform pins
	// (0019:D7/D18). The fix is a platform pin bump or a module
	// downgrade, so it is distinct from RenderFailed.
	SkewRefusedReason = "SkewRefused"
	// DuplicateIdentitiesReason: Ready=False, two or more rendered objects
	// share one Kubernetes apply identity (apiVersion, kind, namespace,
	// name), so the render is refused before apply and the message names
	// each identity and every producing component and transformer
	// (0015:D15). Distinct from RenderFailed because nothing failed to
	// evaluate and the platform is not at fault: the module author removes
	// or renames a component.
	DuplicateIdentitiesReason = "DuplicateIdentities"

	ApplyFailedReason             = "ApplyFailed"
	PruneFailedReason             = "PruneFailed"
	ImpersonationFailedReason     = "ImpersonationFailed"
	DeletionSAMissingReason       = "DeletionSAMissing"
	OrphanedOnDeletionReason      = "OrphanedOnDeletion"
	ReconciliationSucceededReason = "ReconciliationSucceeded"
	DriftDetectedReason           = "DriftDetected"
	ManagedExternallyReason       = "ManagedExternally"

	// Platform-specific reasons (0019:D6: the reconciler generates
	// and builds the platform module).
	GeneratedReason      = "Generated"      // Ready=True: the platform module was generated and built.
	GenerateFailedReason = "GenerateFailed" // Ready=False: the module could not be written to disk.
	BuildFailedReason    = "BuildFailed"    // Ready=False: a dependency did not resolve, the module did not build, or its contract inventory could not be read.

	// ContractCollisionsReason: Ready=False, the built platform's inventory
	// reports contract keys that more than one enabled registry entry
	// defines (two majors of one catalog sharing keys), so the platform is
	// not routable: core folds only keys with exactly one enabled definer,
	// and a colliding key is absent from the defined, required and
	// comparable reports. The message names each colliding key and the
	// registry entries defining it, read from the inventory, never counted.
	// Reported ahead of OverSubscribedContracts and ComparablePredicates,
	// with every finding in the message, because a collision distorts the
	// other reports and its fix reshapes them.
	ContractCollisionsReason = "ContractCollisions"

	// OverSubscribedContractsReason: Ready=False, the built platform's
	// inventory is not routable — a provider-fulfilled contract is provided
	// by more than one enabled registry entry (counted per entry, so two
	// majors of one catalog are two, whether or not the defining catalog is
	// enabled), so no routing exists for it; the message names each
	// contract, its defining catalog when one is enabled and the providing
	// registry entries (0010:D37, kept by 0015:D2; D18 makes this the one
	// inventory report that refuses generation). Reported after
	// ContractCollisions and ahead of ComparablePredicates, with every
	// finding in the message, so one fix pass sees them all. Also the
	// fail-closed reason for an inventory that reads not routable while
	// naming neither an over-subscribed nor a colliding contract.
	OverSubscribedContractsReason = "OverSubscribedContracts"

	// ComparablePredicatesReason: Ready=False, the built platform's
	// inventory is not discriminated — two enabled transformers have
	// comparable match predicates over a shared catalog-fulfilled contract,
	// so every component the narrower matches is also matched by the
	// broader and both would render (0015:D5). Distinct from
	// OverSubscribedContracts because nothing is over-subscribed: the
	// catalogs route fine and the transformers cannot be told apart.
	// Refused rather than arbitrated: 0015:D5 takes no most-specific-wins rule.
	ComparablePredicatesReason = "ComparablePredicates"

	// UnfulfilledContractsReason: ContractsFulfilled=False, the effective
	// package defines provider-fulfilled contracts nothing on the platform
	// implements (0015:D18). Never moves Ready — it names what
	// a future module demanding the contract would wait for, not a fault in
	// the package that was generated.
	UnfulfilledContractsReason = "UnfulfilledContracts"

	// ContractsFulfilledReason: ContractsFulfilled=True, the effective
	// package defines provider-fulfilled contracts and every one has a
	// provider.
	ContractsFulfilledReason = "ContractsFulfilled"

	// NoContractsDefinedReason: ContractsFulfilled=True, the enabled
	// catalogs list no contract at all, so nothing was verified. Distinct
	// from ContractsFulfilled because the two are not the same statement:
	// this one is vacuous, and 0015's operational notes warn against
	// reading it as a pass. True rather than Unknown because a
	// raw-passthrough-only platform legitimately defines nothing, and an
	// Unknown there would read as a fault forever.
	NoContractsDefinedReason = "NoContractsDefined"

	// ModulePackage-specific reasons.
	SourceNotReadyReason       = "SourceNotReady"
	FetchFailedReason          = "FetchFailed"
	PathNotFoundReason         = "PathNotFound"
	InstanceFileNotFoundReason = "InstanceFileNotFound"
	UnsupportedKindReason      = "UnsupportedKind"
	DependenciesNotReadyReason = "DependenciesNotReady"
	PlatformNotReadyReason     = "PlatformNotReady"

	// TransformerRegistration-specific reasons (0015:D3: a claim
	// carries a verdict). Every refusal gets a reason of its own: a claimant
	// acts on the reason, and collapsing two causes into one sends them to
	// the wrong fix.
	// AcceptedReason: Ready=True, the claim passed every check. It is not
	// active: acceptance changes what a claim reports, not what it does.
	AcceptedReason = "Accepted"

	// CatalogUnresolvedReason: the claimed coordinate resolves to nothing. A
	// registry or coordinate problem, distinct from CatalogWrongKind, which
	// is an authoring one — collapsing the two sends the claimant to the
	// wrong fix (0015:D10).
	CatalogUnresolvedReason = "CatalogUnresolved"
	CatalogWrongKindReason  = "CatalogWrongKind"

	// ProvidesMismatchReason: the contract set re-derived from the catalog is
	// not exactly what the claim lists (0015:D11).
	ProvidesMismatchReason = "ProvidesMismatch"

	// ProviderMismatchReason: the claim did not come from the ModuleInstance
	// its providerRef names — the instance is absent, or its inventory
	// settled without this claim (0015:D11).
	ProviderMismatchReason = "ProviderMismatch"

	// ProviderInventoryPendingReason: Ready=Unknown, the naming instance has
	// not written an inventory yet. A race, not a verdict.
	ProviderInventoryPendingReason = "ProviderInventoryPending"

	// BuildIncompatibleReason: the claimed catalog requires a shared
	// OPM-namespace path at a version the platform did not resolve to
	// (0015:D8). Refused at acceptance rather than at render,
	// where the failure would name an unrelated module instance.
	BuildIncompatibleReason = "BuildIncompatible"

	// ProviderReadyReason: Active=True, the provider ModuleInstance the claim
	// names reports Ready=True, so its CRDs exist and its transformers can be
	// rendered against (0015:D3). Latched: the claim keeps this
	// condition through a later provider outage.
	ProviderReadyReason = "ProviderReady"

	// ProviderNotReadyReason: Active=False, the claim is accepted and its
	// provider has not reported Ready yet. An install-ordering state, not a
	// health report — a claim only ever waits here before its first
	// activation.
	ProviderNotReadyReason = "ProviderNotReady"

	// ContractSubscribedReason: the claim provides a contract an enabled
	// Platform.spec.registry subscription's catalog already provides
	// (0015:D2). Distinct from ContractClaimed because the fix is
	// a different object: a platform edit, not a module removal.
	ContractSubscribedReason = "ContractSubscribed"

	// ContractClaimedReason: the claim provides a contract another ACTIVE
	// claim already provides. An accepted but inactive claim holds nothing,
	// so it never produces this refusal.
	ContractClaimedReason = "ContractClaimed"

	// DuplicateClaimReason: another claim already holds this provider catalog
	// (0015:D12). The message names the holder, so an operator
	// can see which object to remove.
	DuplicateClaimReason = "DuplicateClaim"

	// DependentsRemainReason: the claim's deletion is blocked because
	// instances still demand contracts it provides (0015:D3).
	// The message names how many, so the operator's next action is to
	// remove those instances rather than to guess what is holding the
	// object. It is not an acceptance verdict: a blocked claim stays
	// accepted and active, because it is still serving the dependents the
	// block exists to protect.
	//
	// The same reason reports a refused provider upgrade on the provider's
	// ModuleInstance (0015:D16): a re-rendered claim dropping a
	// still-demanded contract is withheld from apply, and the instance is
	// Ready=False naming the claim, the contracts and the count. Both doors
	// refuse the same act — taking a contract away from instances that
	// depend on it — so they report it under one reason.
	DependentsRemainReason = "DependentsRemain"

	// Event-only reasons (no corresponding condition).
	AppliedReason = "Applied"
	PrunedReason  = "Pruned"
	ResumedReason = "Resumed"
	NoOpReason    = "NoOp"
	// RenderWarningReason is the Warning event a successful render's advisory
	// messages (catalog skew under Warn, unhandled optional traits) are
	// emitted under, once per distinct message when the object's warning set
	// changes.
	RenderWarningReason = "RenderWarning"
)

Condition reasons.

View Source
const (
	CounterReconcile = "reconcile"
	CounterApply     = "apply"
	CounterPrune     = "prune"
	CounterDrift     = "drift"
)

Counter field names used by IncrementCounter and ResetCounter.

View Source
const (
	// MaxHistoryEntries is the maximum number of history entries retained.
	// Matches docs/design/module-release-reconcile-loop.md retention policy
	// (design decision 1).
	MaxHistoryEntries = 10
)

Variables

This section is empty.

Functions

func ClearDrifted

func ClearDrifted(obj conditions.Setter)

ClearDrifted removes the Drifted condition (drift resolved by successful apply).

func ConfigDigest

func ConfigDigest(values *releasesv1alpha1.RawValues) string

ConfigDigest computes a deterministic SHA-256 digest of the release values. Serializes RawValues to canonical JSON (sorted keys), then hashes. Returns the SHA-256 of empty input if values is nil (nil = no config), consistent with inventory.ComputeDigest(nil). Format: "sha256:<hex>"

func EnsureCounters

EnsureCounters initializes status.FailureCounters if nil and returns the pointer. Callers can safely use the returned pointer without nil checks.

func EnsureModulePackageCounters

func EnsureModulePackageCounters(status *releasesv1alpha1.ModulePackageStatus) *releasesv1alpha1.FailureCounters

EnsureModulePackageCounters is the ModulePackage equivalent of EnsureCounters.

func IncrementCounter

func IncrementCounter(counters *releasesv1alpha1.FailureCounters, field string)

IncrementCounter increments the named failure counter by one. Unknown field names are silently ignored.

func IsNoOp

func IsNoOp(current, lastApplied DigestSet) bool

IsNoOp returns true if all four digests in current match lastApplied. Returns false if any lastApplied field is empty (handles first reconcile).

func MarkDrifted

func MarkDrifted(obj conditions.Setter, count int)

MarkDrifted sets Drifted=True with a message indicating the number of drifted resources. Drift is informational only — does not affect Ready condition.

func MarkManagedExternally

func MarkManagedExternally(obj conditions.Setter)

MarkManagedExternally sets Ready=Unknown with reason ManagedExternally and removes Reconciling and Stalled conditions. Used by the owner-skip gate for CLI-owned instances the operator deliberately does not reconcile. The static message keeps the write idempotent: re-acknowledging an already-marked instance produces an empty patch diff.

func MarkModuleResolved

func MarkModuleResolved(obj conditions.Setter, moduleRef string)

MarkModuleResolved sets ModuleResolved=True indicating the CUE module was successfully resolved from the OCI registry.

func MarkNotReady

func MarkNotReady(obj conditions.Setter, reason, messageFormat string, messageArgs ...any)

MarkNotReady sets Ready=False with the given reason and message.

func MarkReady

func MarkReady(obj conditions.Setter, messageFormat string, messageArgs ...any)

MarkReady sets Ready=True and removes Reconciling and Stalled conditions.

func MarkReadyWithReason added in v0.7.0

func MarkReadyWithReason(obj conditions.Setter, reason, messageFormat string, messageArgs ...any)

MarkReadyWithReason sets Ready=True with an explicit reason and removes Reconciling and Stalled conditions. Used where the success reason is not the generic ReconciliationSucceeded (e.g. the Platform's Generated reason).

func MarkReconciling

func MarkReconciling(obj conditions.Setter, reason, messageFormat string, messageArgs ...any)

MarkReconciling sets Reconciling=True, removes Stalled, and sets Ready=Unknown.

func MarkStalled

func MarkStalled(obj conditions.Setter, reason, messageFormat string, messageArgs ...any)

MarkStalled sets Stalled=True, removes Reconciling, and sets Ready=False.

func MarkSuspended

func MarkSuspended(obj conditions.Setter)

MarkSuspended sets Ready=False with reason Suspended and removes Reconciling and Stalled conditions.

func ModuleSourceDigest

func ModuleSourceDigest(modulePath, moduleVersion string) string

ModuleSourceDigest computes a deterministic source digest from a CUE module path and version. Replaces SourceDigest for the CUE-native module resolution path where there is no Flux artifact digest.

func NewFailureEntry

func NewFailureEntry(
	action string,
	message string,
	digests DigestSet,
) releasesv1alpha1.HistoryEntry

NewFailureEntry creates a HistoryEntry for a failed reconcile attempt. Populates timestamps via metav1.Now(). Digests may be partially filled depending on which phase failed.

func NewSuccessEntry

func NewSuccessEntry(
	action string,
	phase string,
	digests DigestSet,
	inventoryCount int64,
) releasesv1alpha1.HistoryEntry

NewSuccessEntry creates a HistoryEntry for a successful reconcile action. Populates timestamps via metav1.Now() automatically (design decision 2: typed helpers). Digest fields are populated from the DigestSet (change 6).

func RecordHistory

func RecordHistory(
	status *releasesv1alpha1.ModuleInstanceStatus,
	entry releasesv1alpha1.HistoryEntry,
)

RecordHistory prepends entry to status.History and trims to MaxHistoryEntries. The entry's Sequence is set to nextSequence(status.History) before prepending. Newest entry is at index 0 after prepend.

Does not record periodic no-ops (caller responsibility — design doc explicitly excludes recording every periodic no-op).

func RecordModulePackageHistory

func RecordModulePackageHistory(
	status *releasesv1alpha1.ModulePackageStatus,
	entry releasesv1alpha1.HistoryEntry,
)

RecordModulePackageHistory is the ModulePackage equivalent of RecordHistory.

func RenderDigest

func RenderDigest(resources []*core.Resource) (string, error)

RenderDigest computes a deterministic SHA-256 digest of the rendered resource set. Sorts resources by GVK + namespace + name (same order as inventory.ComputeDigest for consistency), serializes each via core.Resource.MarshalJSON(), and hashes the concatenation. Format: "sha256:<hex>"

func ResetCounter

func ResetCounter(counters *releasesv1alpha1.FailureCounters, field string)

ResetCounter sets the named failure counter to zero. Unknown field names are silently ignored.

Types

type DigestSet

type DigestSet struct {
	// Source is the artifact content digest from Flux OCIRepository.status.artifact.
	Source string

	// Config is the SHA-256 of normalized user values.
	Config string

	// Render is the SHA-256 of the sorted, serialized rendered resource set.
	Render string

	// Inventory is the SHA-256 of the owned resource inventory
	// (computed via internal/inventory.ComputeDigest).
	Inventory string
}

DigestSet holds the four reconcile digests tracked in ModuleInstance.status. Uses named fields rather than a map for type safety (design decision 3).

Maps to status fields:

Source    → lastAttemptedSourceDigest / lastAppliedSourceDigest
Config    → lastAttemptedConfigDigest / lastAppliedConfigDigest
Render    → lastAttemptedRenderDigest / lastAppliedRenderDigest
Inventory → status.inventory.digest

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL