Documentation
¶
Overview ¶
Package release implements the stateful runeset release model: the 3-way reconcile plan that turns a rendered cast into create/update/prune/adopt actions against the cluster.
Design: _docs/plugins/RUNESET_STATEFUL_RELEASES.md and CAST_REFACTOR_PLAN.md. This package is the pure planning core — it computes WHAT a cast will do; the server-side ReleaseController executes the plan (apply, verify, prune-last).
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrConflicts = errors.New("release plan has unresolved conflicts; pass --adopt or resolve ownership")
ErrConflicts is returned when a plan cannot be applied because it contains unresolved ownership conflicts (resource owned elsewhere, no --adopt).
var ErrDetachWouldPrune = errors.New("--detach is not allowed for a plan that prunes resources")
ErrDetachWouldPrune is returned when --detach is requested for a plan that would delete resources (Decision C3: detach is create/update-only).
Functions ¶
This section is empty.
Types ¶
type Action ¶
type Action string
Action is the reconcile verb planned for a single resource.
const ( // ActionCreate — resource is desired and does not exist; create and own it. ActionCreate Action = "create" // ActionUpdate — resource is desired and already owned by this release. ActionUpdate Action = "update" // ActionPrune — resource was owned by the previous revision but is no longer // desired; delete it (runs last, after verify — Decision D3). ActionPrune Action = "prune" // ActionAdopt — resource exists but is unmanaged or owned elsewhere, and // --adopt was given; take ownership. ActionAdopt Action = "adopt" // ActionReference — inherently-shared cluster-scoped kind (StorageClass, // Namespace): ensure it exists but never own or prune it (Decision D2). ActionReference Action = "reference" )
type Applier ¶
type Applier interface {
// Apply materializes a create / update / adopt / reference change.
Apply(ctx context.Context, change PlannedChange) error
// Prune deletes a no-longer-desired owned resource, honoring reclaim policy.
Prune(ctx context.Context, ref types.OwnerRef) error
// Verify blocks until the given owned resources are healthy (or errors).
Verify(ctx context.Context, refs []types.OwnerRef) error
// Revert restores a resource to the pre-image captured before this cast
// first touched it (via Apply or Prune): a resource that did not exist is
// deleted, one that did is restored to that prior state. Used only by
// atomic rollback; must tolerate the change having half-applied or not
// applied at all.
Revert(ctx context.Context, ref types.OwnerRef) error
}
Applier executes individual plan actions against the cluster. Implemented server-side against the orchestrator + repos; faked in tests.
type Conflict ¶
Conflict marks a planned change that cannot be applied as-is: the live resource is owned by a different release (or unmanaged) and adoption was not requested. A plan containing any Conflict is not applyable.
type DesiredResource ¶
type DesiredResource struct {
Ref types.OwnerRef
// ContentHash optionally lets the planner skip no-op updates. Empty means
// "always treat as a potential update" (a finer no-op check is a TODO).
ContentHash string
}
DesiredResource is one resource the rendered release wants to exist.
type LiveLookup ¶
LiveLookup reports the live state of a resource. Implemented server-side against the store/orchestrator; faked in tests.
type LiveState ¶
type LiveState struct {
Exists bool
// OwnedBy is the OwnedBy stamp found on the live resource, or nil if the
// resource is unmanaged (exists but carries no release ownership).
OwnedBy *types.OwnedBy
}
LiveState is the observed live state of a single resource.
type Options ¶
type Options struct {
// Adopt allows taking over resources that exist but are unmanaged or owned
// by a different release (the --adopt flag).
Adopt bool
}
Options tune planning.
type Plan ¶
type Plan struct {
Release string
Namespace string
Changes []PlannedChange
}
Plan is the full set of changes a cast revision will make, in apply order (desired resources in input order, then prunes).
func BuildPlan ¶
func BuildPlan(releaseName, namespace string, desired []DesiredResource, current *types.Release, live LiveLookup, opts Options) (*Plan, error)
BuildPlan computes the 3-way reconcile between the desired set, the current release record (nil for a first install), and live state.
Rules:
- Shared cluster-scoped kinds (StorageClass, Namespace) are ActionReference: ensured-present, never owned or pruned.
- A desired resource already in current.Owns → ActionUpdate.
- A desired resource that doesn't exist live → ActionCreate.
- A desired resource that exists live but isn't ours → ActionAdopt if opts.Adopt, else a Conflict.
- A resource in current.Owns no longer desired → ActionPrune.
func Reconcile ¶
func Reconcile(ctx context.Context, spec ReleaseSpec, recs ReleaseRecords, live LiveLookup, applier Applier) (*types.Release, *Plan, error)
Reconcile executes a release spec end to end (synchronous):
plan → write pending intent → apply (ordered) → verify → prune-last → deployed
It is Prepare followed by Execute. On apply/verify failure it records the release as failed and returns; nothing is pruned (Decision D3). With spec.Atomic, the failure path additionally reverts every change this revision made before recording `failed`. Detach callers use Prepare + a background Execute instead (see releasectl.Controller.Cast).
type PlannedChange ¶
PlannedChange pairs a resource ref with its planned action.
type PreparedCast ¶
type PreparedCast struct {
Release *types.Release
Plan *Plan
// Execute applies the prepared change set and returns the final release
// record (deployed, or failed with the cause). Safe to call from a
// background goroutine with a detached context.
Execute func(ctx context.Context, applier Applier) (*types.Release, error)
}
PreparedCast is the outcome of planning a cast and recording its pending intent: the pending release, the computed plan, and an Execute closure that performs apply → verify → prune-last → deployed against the cluster.
Synchronous callers run Execute inline (see Reconcile). Detach callers (C3-a) return the pending release immediately and run Execute in the background with a detached context.
func Prepare ¶
func Prepare(ctx context.Context, spec ReleaseSpec, recs ReleaseRecords, live LiveLookup) (*PreparedCast, error)
Prepare runs the 3-way plan, validates it (conflicts, detach-prune), and writes the pending release intent. It does NOT mutate the cluster — that is the returned PreparedCast.Execute closure's job. On a validation error it still returns a PreparedCast carrying the Plan (Release nil) so callers can surface it.
type ReleaseRecords ¶
type ReleaseRecords interface {
Get(ctx context.Context, namespace, name string) (rel *types.Release, found bool, err error)
Save(ctx context.Context, rel *types.Release) error
}
ReleaseRecords is the persistence the reconciler needs (satisfied by ReleaseRepo). Get returns found=false when no record exists yet.
type ReleaseSpec ¶
type ReleaseSpec struct {
Name string
Namespace string
Source types.ReleaseSource
Manifest types.RunesetManifest
Values map[string]interface{}
RenderedDigest string
Resources []DesiredResource
Options Options
// Detach requests create/update-only async completion (Decision C3). A
// detach spec whose plan prunes is rejected with ErrDetachWouldPrune.
Detach bool
// Atomic opts into rollback-on-failure (Decision D3, Helm parity): if any
// apply, verify, or prune step fails, every change this revision already
// made is reverted — creates deleted, updates and prunes restored from
// their pre-cast state — so the cast lands fully applied or not at all.
// The release is still recorded `failed` (the rollback is noted in the
// cause); the default (false) keeps today's leave-as-failed behavior.
Atomic bool
}
ReleaseSpec is the rendered, ready-to-apply description of a release. It is produced client-side (resolve → render → lint) and executed by the server-side reconciler. Resource payloads are carried by the Applier implementation, keyed by ref; this spec holds identity, provenance, and the desired ref set.