Documentation
¶
Overview ¶
Package apply contains server-side apply and prune integration points.
Index ¶
- Constants
- func IsServiceAccountNotFound(err error) bool
- func NewImpersonatedClient(ctx context.Context, cfg *rest.Config, reader client.Reader, ...) (client.Client, error)
- func NewResourceManager(c client.Client, owner string) *fluxssa.ResourceManager
- type ApplyResult
- type DriftResult
- type DriftedResource
- type PruneResult
Constants ¶
const ( // FieldManager is the SSA field manager name used by the controller. // Distinguishes from "opm-cli", "kubectl", "helm", etc. // From docs/design/ssa-ownership-and-drift-policy.md. FieldManager = "opm-controller" )
Variables ¶
This section is empty.
Functions ¶
func IsServiceAccountNotFound ¶ added in v0.6.0
IsServiceAccountNotFound reports whether err was produced by NewImpersonatedClient because the target ServiceAccount did not exist. The wrapping chain preserves the apiserver's NotFound status so callers can branch deletion-cleanup behavior without introducing a sentinel type.
func NewImpersonatedClient ¶
func NewImpersonatedClient( ctx context.Context, cfg *rest.Config, reader client.Reader, scheme *runtime.Scheme, namespace, saName string, ) (client.Client, error)
NewImpersonatedClient builds a controller-runtime client that impersonates the given ServiceAccount for all API calls. The SA must exist in the specified namespace; if it does not, an error is returned so the caller can stall the reconcile.
reader is used only for the SA existence check. Pass an uncached reader (e.g. manager.GetAPIReader()) so that a single Get does not provision a cluster-wide ServiceAccount informer and thereby require list/watch RBAC. scheme is used to build the impersonated client.
The returned client is suitable for Apply and Prune operations scoped to the SA's RBAC bindings.
func NewResourceManager ¶
func NewResourceManager(c client.Client, owner string) *fluxssa.ResourceManager
NewResourceManager constructs a Flux SSA ResourceManager with the opm-controller field manager. The owner string is used for SSA ownership labels.
A StatusPoller is wired in because fluxssa.ApplyAllStaged internally calls WaitForSet after applying cluster-scoped resources (CRDs, ClusterRoles, Namespaces); a nil poller there nil-derefs on the first module whose render contains any such resource.
Types ¶
type ApplyResult ¶
type ApplyResult struct {
// Created is the number of resources created (did not exist before).
Created int
// Updated is the number of resources updated (existed, fields changed).
Updated int
// Unchanged is the number of resources unchanged (existed, no field diff).
Unchanged int
}
ApplyResult carries counts of apply outcomes.
func Apply ¶
func Apply( ctx context.Context, rm *fluxssa.ResourceManager, resources []*unstructured.Unstructured, force bool, ) (*ApplyResult, error)
Apply applies the given resources to the cluster using Server-Side Apply. Staging is handled by Flux's ApplyAllStaged, which applies cluster definitions (CRDs, Namespaces, ClusterRoles) first with readiness waits, then class definitions, then everything else. See docs/design/flux-ssa-staging.md.
When force is true, immutable field conflicts are resolved by recreating the object (maps to ApplyOptions.Force, not SSA field-ownership conflicts — Flux always applies with ForceOwnership).
Returns an ApplyResult with counts, or an error on any apply failure.
type DriftResult ¶
type DriftResult struct {
// Drifted is true if any resource has drifted from desired state.
Drifted bool
// Resources lists the resources that have drifted.
Resources []DriftedResource
}
DriftResult holds the outcome of drift detection across a resource set.
func DetectDrift ¶
func DetectDrift( ctx context.Context, rm *fluxssa.ResourceManager, resources []*unstructured.Unstructured, ) (*DriftResult, error)
DetectDrift performs SSA dry-run diffs for each resource and returns which resources have drifted from desired state. Uses Flux's ResourceManager.Diff which performs a server-side apply dry-run and compares the result.
A resource is considered drifted when the dry-run result differs from the desired state (Flux returns ConfiguredAction). Resources that don't exist yet (CreatedAction) or are unchanged are not considered drifted.
Returns an error only when the dry-run API call itself fails (transient). Drift detection results are not errors — drift is an expected operational signal.
type DriftedResource ¶
DriftedResource identifies a single resource that has drifted from desired state.
type PruneResult ¶
type PruneResult struct {
// Deleted is the number of stale resources successfully deleted.
Deleted int
// Skipped is the number of stale resources skipped due to safety exclusions.
Skipped int
}
PruneResult carries counts of prune outcomes.
func Prune ¶
func Prune( ctx context.Context, c client.Client, ownerUUID string, stale []releasesv1alpha1.InventoryEntry, ) (*PruneResult, error)
Prune deletes stale resources from the cluster. Uses direct client.Delete per resource rather than Flux's DeleteAll to allow per-resource error control and safety exclusion logic (design decision 1).
Safety exclusions (design decision 3: hard-coded, not configurable):
- Namespace: never auto-deleted (cascades to all resources inside)
- CustomResourceDefinition: never auto-deleted (deletes all instances globally)
Live-state ownership guard (defense-in-depth): before each delete, Prune GETs the live object and skips the delete if the live object is not OPM-managed (missing/unrecognized app.kubernetes.io/managed-by label) or carries a module-release.opmodel.dev/uuid label that disagrees with ownerUUID. An empty live UUID label is tolerated (legacy resources predate UUID stamping). An empty ownerUUID disables the UUID comparison — callers that cannot supply a UUID (e.g. the Release reconciler, or a freshly-created ModuleRelease whose Status.ReleaseUUID is not yet persisted) fall back to the managed-by check alone.
Skipped resources are logged as warnings and counted in PruneResult.Skipped.
If a stale resource is already gone (NotFound), it is treated as success. Individual failures (Get or Delete) are collected and returned as a joined error; remaining entries continue (design decision 2: continue-on-error / fail-slow).
The caller is responsible for:
- Computing the stale set via internal/inventory.ComputeStaleSet
- Checking spec.prune before calling this function
- Ensuring apply succeeded before calling prune
- Supplying ownerUUID from the freshly-rendered resources or ModuleReleaseStatus.ReleaseUUID