Documentation
¶
Overview ¶
Package status contains release condition, digest, and history helpers.
Index ¶
- Constants
- func ClearDrifted(obj conditions.Setter)
- func ConfigDigest(values *releasesv1alpha1.RawValues) string
- func EnsureCounters(status *releasesv1alpha1.ModuleInstanceStatus) *releasesv1alpha1.FailureCounters
- func EnsureModulePackageCounters(status *releasesv1alpha1.ModulePackageStatus) *releasesv1alpha1.FailureCounters
- func IncrementCounter(counters *releasesv1alpha1.FailureCounters, field string)
- func IsNoOp(current, lastApplied DigestSet) bool
- func MarkDrifted(obj conditions.Setter, count int)
- func MarkManagedExternally(obj conditions.Setter)
- func MarkModuleResolved(obj conditions.Setter, moduleRef string)
- func MarkNotReady(obj conditions.Setter, reason, messageFormat string, messageArgs ...any)
- func MarkReady(obj conditions.Setter, messageFormat string, messageArgs ...any)
- func MarkReadyWithReason(obj conditions.Setter, reason, messageFormat string, messageArgs ...any)
- func MarkReconciling(obj conditions.Setter, reason, messageFormat string, messageArgs ...any)
- func MarkStalled(obj conditions.Setter, reason, messageFormat string, messageArgs ...any)
- func MarkSuspended(obj conditions.Setter)
- func ModuleSourceDigest(modulePath, moduleVersion string) string
- func NewFailureEntry(action string, message string, digests DigestSet) releasesv1alpha1.HistoryEntry
- func NewSuccessEntry(action string, phase string, digests DigestSet, inventoryCount int64) releasesv1alpha1.HistoryEntry
- func RecordHistory(status *releasesv1alpha1.ModuleInstanceStatus, ...)
- func RecordModulePackageHistory(status *releasesv1alpha1.ModulePackageStatus, ...)
- func RenderDigest(resources []*core.Resource) (string, error)
- func ResetCounter(counters *releasesv1alpha1.FailureCounters, field string)
- type DigestSet
Constants ¶
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.
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. // OverSubscribedContractsReason: Ready=False, the built platform's // inventory is not routable — a provider-fulfilled contract is required // by transformers from more than one enabled catalog, so no routing // exists for it (0010:D37, kept by 0015:D2; D18 makes this the one // inventory report that refuses generation). Reported first when the // inventory is also undiscriminated, with both findings in the message, // so one fix pass sees both. 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.
const ( CounterReconcile = "reconcile" CounterApply = "apply" CounterPrune = "prune" CounterDrift = "drift" )
Counter field names used by IncrementCounter and ResetCounter.
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 ¶
func EnsureCounters(status *releasesv1alpha1.ModuleInstanceStatus) *releasesv1alpha1.FailureCounters
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 ¶
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 ¶
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 ¶
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