Documentation
¶
Overview ¶
Package install holds the shared control-plane bootstrap engine used by both `clrk dev` (against a local k3d cluster) and `clrk install`/`clrk upgrade` (against a customer's existing cluster). It owns the typed-object manifest builders, the cluster-agnostic apply/verify helpers, the cluster preflight, the plan/diff/confirm flow, the progress orchestration, the readiness gate, cert wiring, and the upgrade version gate.
The package is deliberately k3d-free: it imports only controller-runtime and the leaf constant packages (internal/clickhouse, internal/nats, internal/ports, internal/otelemit, internal/eg, internal/crds, api/clrk/v1alpha1). The dependency edge points one way — internal/drivers (which pulls the heavy k3d v5 tree) imports internal/install, never the reverse — so the install/upgrade code path links and tests without any docker/k3d toolchain.
Index ¶
- Constants
- func ApplyAndVerify[T client.Object](ctx context.Context, a Applier, obj T, verify func(got T) error) error
- func ApplyControllerManager(ctx context.Context, a Applier, p Profile) error
- func ApplyWorkerPool(ctx context.Context, a Applier, p Profile) error
- func BuildControllerManager(p Profile) []client.Object
- func BuildWorkerPool(p Profile) []client.Object
- func CurrentWorkerCount(ctx context.Context, c client.Client, ns, name string) (count int, ok bool, err error)
- func DeriveAPIServerCIDRs(ctx context.Context, c client.Client) ([]string, error)
- func DetectCertManager(disco discovery.DiscoveryInterface) bool
- func DetectInstall(ctx context.Context, c client.Client, ns string) (exists bool, version string, err error)
- func LoadRESTConfig(kubeconfigPath, contextName string) (cfg *rest.Config, resolvedContext string, err error)
- func PrepareTLS(ctx context.Context, c client.Client, p *Profile) ([]client.Object, error)
- func RenderManifests(in RenderInput) ([]byte, error)
- func Rollout(ctx context.Context, c client.Client, ns, name string) (int64, error)
- func RolloutWorkerPool(ctx context.Context, c client.Client, ns, name string) (int64, error)
- func RunSteps(ctx context.Context, steps []Step, log StepLogger) error
- func StepNames(steps []Step) []string
- func WaitAPIDiscoverable(ctx context.Context, cfg *rest.Config, timeout time.Duration) error
- func WaitDeploymentRolledOut(ctx context.Context, c client.Client, ns, name string, wantGeneration int64, ...) error
- func WaitReady(ctx context.Context, cfg *rest.Config, p Profile, interval time.Duration, ...) error
- func WaitServingSecret(ctx context.Context, a Applier, ns string, timeout time.Duration) error
- func WaitWorkerPoolConverged(ctx context.Context, c client.Client, ns, name string, wantGeneration int64, ...) error
- type Action
- type Applier
- type Level
- type Orchestration
- type PreflightResult
- type Profile
- type RemoteCluster
- func (r *RemoteCluster) ApplyObjects(ctx context.Context, objs ...client.Object) error
- func (r *RemoteCluster) Context() string
- func (r *RemoteCluster) Discovery() (discovery.CachedDiscoveryInterface, error)
- func (r *RemoteCluster) EnsureNamespace(ctx context.Context, ns string) error
- func (r *RemoteCluster) KubeClient(ctx context.Context) (client.Client, error)
- func (r *RemoteCluster) RESTConfig() *rest.Config
- func (r *RemoteCluster) RESTMapper() (*restmapper.DeferredDiscoveryRESTMapper, error)
- func (r *RemoteCluster) WaitDeploymentAvailable(ctx context.Context, ns, name string, timeout time.Duration) error
- type RenderInput
- type ResourcePlan
- type Step
- type StepLogger
- type TLSMode
- type UpgradeDecision
- type UpgradeVerdict
Constants ¶
const ( // ControllerManagerName is shared by the cm ServiceAccount, // (Cluster)RoleBinding, Deployment, and Service. ControllerManagerName = "clrk-controller-manager" // WorkerAccountName is the ServiceAccount the worker Pods run under. It // aliases the API package's constant so the value is defined once (the pod // builder defaults spec.template.serviceAccountName to it). WorkerAccountName = clrkv1alpha1.WorkerServiceAccountName // EnvoyGatewayServiceName fronts the cm's in-process envoy-gateway xDS // listener under the well-known name the EG data-plane bootstrap dials. EnvoyGatewayServiceName = "envoy-gateway" // ConsoleServiceName fronts the cm's embedded web console port. It's a // dedicated single-port Service (not a port on the cm Service) so the // `clrk dev` auto-forwarder — which forwards a Service's first TCP port — // targets the console rather than the apiserver. ConsoleServiceName = "clrk-console" // APIServiceName is the aggregated APIService routing // clrk.apoxy.dev/v1alpha1 to the cm. APIServiceName = "v1alpha1.clrk.apoxy.dev" // MetricsAPIServiceName is the aggregated APIService routing the // Tier-1 metrics group (metrics.clrk.apoxy.dev/v1alpha1) to the cm. // Served by the same apiserver as APIServiceName; kube-aggregator // keys one APIService per group, so the metrics group needs its own. MetricsAPIServiceName = "v1alpha1.metrics.clrk.apoxy.dev" // DefaultWorkerPoolName is the name of the WorkerPool the installer creates // (its Deployment is WorkerDeploymentName, "default-workers"). DefaultWorkerPoolName = "default" // DefaultNamespace is the control-plane namespace used by both `clrk dev` // and `clrk install` when none is specified. Same name in dev + prod. DefaultNamespace = "clrk" )
Canonical object names shared by every component of the control plane. Kept here as the single source of truth so the cm Service/APIService/Deployment wiring and the downstream advertise URIs can't drift, and so callers outside this package (e.g. dev.go waiting on the cm Deployment) reference one name.
const WorkerDeploymentName = "default-workers"
WorkerDeploymentName is the Deployment WorkerPoolDeploymentReconciler creates for the `default` WorkerPool.
Variables ¶
This section is empty.
Functions ¶
func ApplyAndVerify ¶
func ApplyAndVerify[T client.Object](ctx context.Context, a Applier, obj T, verify func(got T) error) error
ApplyAndVerify SSAs obj through the Applier (so it inherits the implementation's field manager), then re-GETs the stored object and runs verify against it. Returns nil iff the apply succeeded *and* verify saw the field it cares about. This catches the "SSA returned 200 but the spec didn't change" case that left a stale WorkerPool image in kine across multiple applies — the embedded apiserver (kine) is the failure surface, which is why the WorkerPool apply goes through here.
A free function with a type parameter (Go forbids generic methods) so the verify callback is typed at the call site. The freshly-zeroed verify target is built via the registered scheme rather than reusing obj, because SSA mutates obj (clears TypeMeta) in ways that confuse a subsequent GET.
func ApplyControllerManager ¶
ApplyControllerManager applies the cm control-plane objects through a, then applies-and-verifies the cm Deployment (env-count/image stripping guard). Mirrors the previous dev bootstrap: plain SSA for SA/RBAC/Services/APIService/ PVCs, ApplyAndVerify for the Deployment. Idempotent.
func ApplyWorkerPool ¶
ApplyWorkerPool applies the worker SA + ClusterRoleBinding, then applies-and-verifies the `default` WorkerPool CR (image + privileged SecurityContext stripping guard). WorkerPoolDeploymentReconciler in the cm turns the CR into the worker Deployment + Service. Idempotent.
func BuildControllerManager ¶
BuildControllerManager returns the full ordered control-plane object set (SA, RBAC, Services, APIService, PVCs, Deployment) for rendering/planning. The Deployment is last so callers that apply-and-verify it can split the slice if they prefer; ApplyControllerManager does that split internally.
func BuildWorkerPool ¶
BuildWorkerPool returns the worker RBAC + WorkerPool CR for rendering/planning.
func CurrentWorkerCount ¶
func CurrentWorkerCount(ctx context.Context, c client.Client, ns, name string) (count int, ok bool, err error)
CurrentWorkerCount returns the replica count of the existing default WorkerPool in ns so `clrk upgrade` can carry it forward instead of resetting the fleet to the --workers flag default. ForceOwnership SSA would otherwise overwrite spec.replicas back to the default, silently scaling down an operator's fleet (set at install or scaled later). ok is false when the WorkerPool is absent or carries no explicit replica count, in which case the caller keeps its default.
func DeriveAPIServerCIDRs ¶
DeriveAPIServerCIDRs collects the host-network source CIDRs the aggregation proxy can originate from: the kube-apiserver Endpoint addresses (default/ kubernetes) plus every node InternalIP, each as a single-host CIDR (/32 or /128). Aggregation requests reach the cm SNAT'd to one of these, so admitting them keeps the API reachable while excluding the pod network. Returns the (deduplicated) CIDRs; an error only if neither source can be read.
func DetectCertManager ¶
func DetectCertManager(disco discovery.DiscoveryInterface) bool
DetectCertManager reports whether the cert-manager.io API group is served, which selects the cert-manager TLS path over the self-signed one.
func DetectInstall ¶
func DetectInstall(ctx context.Context, c client.Client, ns string) (exists bool, version string, err error)
DetectInstall reports whether a clrk control plane already exists in namespace ns and, if so, the version stamped on its controller-manager Deployment (empty if unstamped). Used by preflight (install-vs-upgrade hint) and by the upgrade version gate.
func LoadRESTConfig ¶
func LoadRESTConfig(kubeconfigPath, contextName string) (cfg *rest.Config, resolvedContext string, err error)
LoadRESTConfig resolves a *rest.Config for a customer cluster from an operator-supplied kubeconfig + context. Precedence for the kubeconfig file: explicit kubeconfigPath, else the KUBECONFIG env var, else ~/.kube/config — the standard client-go loading rules. contextName, when set, overrides the kubeconfig's current-context. Returns the config and the resolved context name (so the installer can show the operator exactly which cluster it is about to touch).
func PrepareTLS ¶
PrepareTLS produces the serving-cert objects for the chosen TLS mode and configures p so the builders wire the APIService caBundle (or cert-manager CA-injection annotation) and the cm cert mount. It reads the cluster to reuse an existing self-signed CA, so re-runs don't rotate the cert.
- TLSCertManager: returns a selfSigned Issuer + a Certificate; cert-manager mints servingCertSecretName and injects the CA into the APIService via the cert-manager.io/inject-ca-from annotation (p.CertManagerCertRef).
- TLSSelfSigned: mints (or reuses) a CA + serving cert, returns the serving Secret + the CA Secret, and sets p.CABundle for APIService.caBundle.
- TLSInsecureSkipVerify: no objects (dev posture).
func RenderManifests ¶
func RenderManifests(in RenderInput) ([]byte, error)
RenderManifests serializes the full ordered control-plane manifest set to a multi-document YAML stream for `clrk install/upgrade --dry-run -o yaml`. It is the GitOps/audit counterpart to the live apply: the same objects the orchestration would lay down, in the same order — namespaces, serving-cert objects, the Gateway-API + Envoy-Gateway CRDs, the controller-manager set, and the WorkerPool set — emitted as `kubectl apply -f -`-able YAML.
It is pure (no cluster access): every object is already built from the resolved Profile, so the output is deterministic except for the self-signed key material PrepareTLS minted (the CA + serving-cert Secrets). For that posture the stream is prefixed with a sensitive-material warning, since the emitted Secrets carry private keys.
func Rollout ¶
Rollout bumps the clrk.apoxy.dev/restartedAt annotation on a Deployment's pod template, triggering the same rolling restart as `kubectl rollout restart`. A strategic-merge patch (no Get+Update) means concurrent reconciles can't lose the rollout to a 409. Returns the Deployment's post-patch metadata.generation so the caller can wait for status.observedGeneration to catch up (WaitDeploymentRolledOut) instead of racing a stale Available condition. Ported from drivers.ClusterDriver.Rollout so the install/upgrade path can roll the controller-manager through its RemoteCluster client without pulling in the k3d driver.
func RolloutWorkerPool ¶
RolloutWorkerPool triggers a rolling restart of a WorkerPool's worker Deployment by bumping RestartedAtAnnotation on the WorkerPool's spec.template.metadata.annotations — NOT on the Deployment. The Deployment is controller-owned: WorkerPoolDeploymentReconciler rebuilds its pod template from wp.spec.template every reconcile, so an annotation patched straight onto the Deployment is wiped on the next pass and the rollout silently no-ops. Patching the WorkerPool makes the controller propagate the annotation into the Deployment template itself. Returns the WorkerPool's post-patch metadata.generation so the caller can wait for status.observedGeneration to catch up (WaitWorkerPoolConverged). Ported from drivers.ClusterDriver.RolloutWorkerPool.
func RunSteps ¶
func RunSteps(ctx context.Context, steps []Step, log StepLogger) error
RunSteps executes steps in order, emitting lifecycle events. It stops on the first error (the control plane is a dependency chain — a failed cm makes the WorkerPool apply meaningless).
func StepNames ¶
StepNames returns the ordered Step.Name values, for seeding the TUI sidebar so it matches the steps actually run (including the conditional serving-cert).
func WaitAPIDiscoverable ¶
WaitAPIDiscoverable polls discovery until clrk.apoxy.dev/v1alpha1 appears. The aggregated APIService is registered as soon as the cm is up, but kube-aggregator still has to probe the backend's TLS and mark the service Available before REST mappings for clrk kinds resolve.
func WaitDeploymentRolledOut ¶
func WaitDeploymentRolledOut(ctx context.Context, c client.Client, ns, name string, wantGeneration int64, timeout time.Duration) error
WaitDeploymentRolledOut blocks until ns/name has reconciled at least wantGeneration and its pods are fully rolled over to the new ReplicaSet (updated == replicas == available == spec.replicas). Gating on observedGeneration is what makes this safe after a Rollout: immediately after the restartedAt patch the Deployment's Available condition still reflects the OLD generation, so a bare Available=True poll would return before the Recreate even begins (reporting an upgrade "done" while the old cm pod is still up). The updated==replicas==available equality also closes the Recreate gap, where the old pod is torn down (replicas drops to 0) before the new one is created.
func WaitReady ¶
func WaitReady(ctx context.Context, cfg *rest.Config, p Profile, interval time.Duration, log func(string)) error
WaitReady blocks until every post-install signal on the target cluster has flipped green, or ctx is cancelled. Adapted from `clrk dev wait-ready`: drops the k3s-specific /livez probe and adds the controller-manager + worker Deployment Available checks the dev path did inline. log receives one line per state transition (green tick or pending) so the caller can route it to stdout or a TUI pane.
Signals (all required, each monotonic once green):
- clrk.apoxy.dev/v1alpha1 APIService is Available
- the ClickHouse-backed Invocation store answers a List
- Gateway API CRDs are installed
- <namespace>/envoy-gateway Secret exists (EG certgen ran)
- controller-manager Deployment is Available
- worker Deployment is Available
func WaitServingSecret ¶
WaitServingSecret blocks until the cm serving-cert Secret carries a tls.crt, or timeout elapses. Used on the cert-manager path, where the Secret is minted asynchronously after the Certificate is applied; the cm pod can't mount it (or pass its readiness probe) until it exists.
func WaitWorkerPoolConverged ¶
func WaitWorkerPoolConverged(ctx context.Context, c client.Client, ns, name string, wantGeneration int64, timeout time.Duration) error
WaitWorkerPoolConverged blocks until the WorkerPool has reconciled at least wantGeneration and reports its workers rolled out and ready (Available=True and Progressing=False). Waiting on the WorkerPool's status — which the controller derives from the Deployment — rather than polling the Deployment directly can't observe the pre-reconcile converged state; the observedGeneration floor ensures we read the controller's verdict on THIS rollout. Ported from drivers.ClusterDriver.WaitWorkerPoolConverged.
Types ¶
type Applier ¶
type Applier interface {
// ApplyObjects server-side-applies one or more typed objects with
// ForceOwnership under the implementation's field manager.
ApplyObjects(ctx context.Context, objs ...client.Object) error
// KubeClient returns the underlying controller-runtime client (and its
// scheme) for Get/List/Watch outside the SSA-only path.
KubeClient(ctx context.Context) (client.Client, error)
// EnsureNamespace idempotently applies a Namespace.
EnsureNamespace(ctx context.Context, ns string) error
// WaitDeploymentAvailable blocks until ns/name reports
// DeploymentAvailable=True or timeout elapses.
WaitDeploymentAvailable(ctx context.Context, ns, name string, timeout time.Duration) error
}
Applier is the cluster-agnostic surface the bootstrap engine needs to apply and wait on Kubernetes objects. It is satisfied by both *drivers.ClusterDriver (dev/k3d) and *install.RemoteCluster (customer cluster), so the same builders + orchestration run against either. The implementation owns the server-side-apply field manager (dev uses "clrk-dev", install uses "clrk-install"), so callers never thread it through.
type Level ¶
type Level int
Level is the severity of a preflight result. FAIL aborts the install; WARN is confirmable (auto-accepted under --yes with a logged warning); PASS is informational.
type Orchestration ¶
type Orchestration struct {
Applier Applier
Config *rest.Config
Profile Profile
CRDMode crds.Mode
// CertObjects are the serving-cert objects (cert-manager Issuer+Certificate,
// or self-signed CA+serving Secret) applied before the cm so its --cert-dir
// mount and the APIService caBundle are satisfied. Empty for the insecure
// (dev-equivalent) posture, which skips the serving-cert step.
CertObjects []client.Object
// WaitCertSecret waits for the serving-cert Secret to be populated after
// applying CertObjects. Needed on the cert-manager path (the Secret is minted
// asynchronously); the self-signed path applies the Secret directly.
WaitCertSecret bool
// Upgrade marks an in-place upgrade (vs a fresh install). It makes the
// worker-pool step force a WorkerPool rollout and wait for convergence, so
// the workers reliably pick up a new image even when only the image digest
// (not the tag) moved. `clrk install` leaves it false.
Upgrade bool
WaitTimeout time.Duration
ReadyInterval time.Duration
Log func(string)
}
Orchestration carries everything the install/upgrade bring-up needs. Bundled in a struct (rather than a long parameter list) because the serving-cert step is conditional and the cluster path threads cert objects + an async wait through it. The TUI derives its sidebar from Steps(), so a conditional step is reflected in the rendered component list without a parallel hardcoded slice.
func (Orchestration) Steps ¶
func (o Orchestration) Steps() []Step
Steps builds the ordered bring-up: namespaces -> [serving-cert] -> CRDs -> controller-manager (apply + wait Available) -> aggregated-api (wait discoverable) -> WorkerPool -> readiness. The cm must be Available and its aggregated API discoverable before the WorkerPool apply, which goes through that API. The serving-cert step is present only when CertObjects is non-empty.
type PreflightResult ¶
PreflightResult is one cluster-readiness finding. Detail says what was found; Hint is the actionable fix (empty on PASS).
func Preflight ¶
func Preflight(ctx context.Context, c client.Client, disco discovery.DiscoveryInterface, p Profile, upgrade bool) []PreflightResult
Preflight runs every cluster-readiness check against the target cluster and returns the findings (collect-all-then-report). The caller decides policy: any LevelFail aborts; LevelWarn is confirmable. upgrade flips the existing- install check from a WARN ("an install exists; use `clrk upgrade`") to an informational PASS, since on the upgrade path an existing install is exactly what is expected. The Profile shapes namespace-scoped checks (worker-ns PSA, RBAC on the install namespace, named StorageClass).
type Profile ¶
type Profile struct {
// Namespace holds the control-plane objects (cm Deployment/Service/
// APIService/PVCs/RBAC). WorkerNamespace holds the WorkerPool + worker
// RBAC.
Namespace string
WorkerNamespace string
// Images + pull behaviour.
ControllerImage string
WorkerImage string
PullPolicy string // "always" | "missing" | "never"; "" => IfNotPresent
// ImagePullSecret, when set, is attached to the cm + worker PodSpecs.
// Cluster-only (M4).
ImagePullSecret string
// Sizing.
Replicas int32 // cm replicas; v1 is always 1 (single-writer embedded stores).
Workers int32 // worker replicas.
// StorageClass for the three cm PVCs. Empty => the cluster default
// (k3d local-path in dev).
StorageClass string
// RBACScoped selects a scoped ClusterRole (cluster) vs the cluster-admin
// dev shortcut. Cluster-only (M4).
RBACScoped bool
// APIServerCIDRs, when non-empty, emits a NetworkPolicy admitting the
// unauthenticated aggregated API (cm:8443) only from these CIDRs — the
// host-network sources the aggregation proxy can originate from (the
// kube-apiserver Endpoint IPs plus node InternalIPs, since aggregation
// requests are commonly SNAT'd to a node IP). Pods live on the pod network,
// so they are excluded. Derived by DeriveAPIServerCIDRs with an
// --apiserver-cidr override; empty (dev, or undetected, or --network-policy=
// false) emits no policy. Cluster-only (M4).
APIServerCIDRs []string
// TLS holds the APIService serving-cert posture. CABundle is the PEM the
// installer sets on APIService.spec.caBundle for TLSSelfSigned;
// CertManagerCertRef ("<ns>/<name>") drives the inject-ca-from annotation
// for TLSCertManager. Cluster cert objects are built in M4.
TLS TLSMode
CABundle []byte
CertManagerCertRef string
// Version is stamped onto the cm Deployment + namespace for upgrade
// gating (M5). Empty in dev.
Version string
// Console gates the embedded web console: its clrk-console Service, the
// cm containerPort, and the --console-addr arg. nil/true installs it
// (the default); false disables it entirely (--console-addr= empty, no
// Service/port). The console proxies the unauthenticated apiserver, so an
// operator who doesn't want that surface sets --console=false. Reached in
// prod via `kubectl port-forward` -- the NetworkPolicy deliberately does
// not open 8086 (see controllerManagerNetworkPolicy).
Console *bool
// Dev marks the local k3d profile and gates the dev-only knobs below.
Dev bool
// HostAliasIP, when set, plants a host.docker.internal HostAlias on the cm
// pod (dev: k3d-nested pods don't inherit Docker Desktop's /etc/hosts).
HostAliasIP string
// OTLPFallbackEndpoint, when set, becomes --dev-otlp-fallback-endpoint so
// every captured signal is mirrored to the dev TUI receiver.
OTLPFallbackEndpoint string
// EnableTestWrites opens the header-gated Invocation Create/Update door
// (--enable-invocation-test-writes). Dev/CI only.
EnableTestWrites bool
// EgressBackendHost, when set, becomes --dev-egress-backend-host (k3d
// NodePort routing). Empty on a cluster (in-cluster Service DNS).
EgressBackendHost string
}
Profile is the single parameterization the manifest builders consume. The same struct drives `clrk dev` (Dev=true reproduces today's dev bootstrap byte-for-byte) and `clrk install`/`upgrade` (Dev=false, cluster-shaped fields set). Dev-only knobs are zero-valued and inert on a cluster profile.
type RemoteCluster ¶
type RemoteCluster struct {
// contains filtered or unexported fields
}
RemoteCluster is the customer-cluster implementation of Applier: it server- side-applies and waits on objects through a controller-runtime client built from an operator-supplied kubeconfig + context. It holds no k3d state, so the install/upgrade code path links and tests without the k3d toolchain.
func NewRemoteCluster ¶
func NewRemoteCluster(kubeconfigPath, contextName string) (*RemoteCluster, error)
NewRemoteCluster resolves the kubeconfig + context and builds the typed client. The returned RemoteCluster satisfies Applier.
func (*RemoteCluster) ApplyObjects ¶
ApplyObjects server-side-applies one or more typed objects with ForceOwnership under the install field manager. Same semantics as the dev driver, so the shared builders + ApplyAndVerify behave identically against either.
func (*RemoteCluster) Context ¶
func (r *RemoteCluster) Context() string
Context returns the resolved kubeconfig context name (for operator-facing "about to install into <context>" messaging).
func (*RemoteCluster) Discovery ¶
func (r *RemoteCluster) Discovery() (discovery.CachedDiscoveryInterface, error)
Discovery returns a memory-cached discovery client for the target cluster, used by preflight to detect API groups, CRDs, and the aggregation layer.
func (*RemoteCluster) EnsureNamespace ¶
func (r *RemoteCluster) EnsureNamespace(ctx context.Context, ns string) error
EnsureNamespace idempotently applies a Namespace.
func (*RemoteCluster) KubeClient ¶
KubeClient returns the controller-runtime client.
func (*RemoteCluster) RESTConfig ¶
func (r *RemoteCluster) RESTConfig() *rest.Config
RESTConfig returns the resolved rest.Config (e.g. for crds.Install, discovery, or SelfSubjectAccessReview clients).
func (*RemoteCluster) RESTMapper ¶
func (r *RemoteCluster) RESTMapper() (*restmapper.DeferredDiscoveryRESTMapper, error)
RESTMapper returns a deferred discovery REST mapper, used by the plan engine to resolve REST mappings for arbitrary objects.
func (*RemoteCluster) WaitDeploymentAvailable ¶
func (r *RemoteCluster) WaitDeploymentAvailable(ctx context.Context, ns, name string, timeout time.Duration) error
WaitDeploymentAvailable blocks until ns/name reports DeploymentAvailable=True or timeout elapses.
type RenderInput ¶
RenderInput parameterizes RenderManifests. Profile is the fully resolved install/upgrade profile (TLS posture, version stamp, NetworkPolicy CIDRs, and for the cert-manager path CertManagerCertRef / for self-signed CABundle all already set by PrepareTLS + the CIDR derivation). CertObjects are the serving-cert objects PrepareTLS produced for that posture (empty for the insecure/dev posture). CRDMode mirrors the apply path: ModeSkip emits no CRD documents, otherwise the embedded Gateway-API + Envoy-Gateway bundle is included.
type ResourcePlan ¶
type ResourcePlan struct {
Kind string
Name string // "<ns>/<name>" or "<name>" for cluster-scoped
Action Action
Diff string
Risky bool
Why string
Note string
}
ResourcePlan is the planned effect of applying one object, computed by a server-side-apply dry-run diffed against the live object. Risky flags cluster-wide or destructive changes the operator should see before confirming; Why explains it. Note carries a caveat (e.g. an API not yet served at plan time).
func BuildPlan ¶
func BuildPlan(ctx context.Context, c client.Client, fieldManager string, objs []client.Object) []ResourcePlan
BuildPlan computes, for each object, what applying it would do — via an SSA dry-run compared against the live object. It never mutates the cluster. Objects whose API isn't served yet at plan time (e.g. the WorkerPool before the controller-manager is up) can't be dry-run-applied; they're reported as creates with a note rather than failing the whole plan.
type Step ¶
Step is one unit of the install/upgrade bring-up. Why is a one-line rationale rendered before Run executes, so the operator always understands what is about to happen and why. Risky marks steps that mutate cluster-wide or existing state (gated behind confirmation by the caller).
type StepLogger ¶
StepLogger receives lifecycle events for a step. status is one of "start", "done", "error". Callers route this to stdout or a TUI pane.
type TLSMode ¶
type TLSMode int
TLSMode selects how the aggregated APIService verifies the cm's serving cert.
const ( // TLSInsecureSkipVerify sets APIService.spec.insecureSkipTLSVerify=true and // lets the cm serve a self-signed in-memory cert (empty --cert-dir). The // dev default; never used on a customer cluster. TLSInsecureSkipVerify TLSMode = iota // TLSSelfSigned mounts an installer-minted serving-cert Secret at // --cert-dir and sets APIService.spec.caBundle to the installer CA. TLSSelfSigned // TLSCertManager mounts a cert-manager-issued serving-cert Secret at // --cert-dir and annotates the APIService with // cert-manager.io/inject-ca-from so the CA injector fills caBundle. TLSCertManager )
type UpgradeDecision ¶
type UpgradeDecision struct {
Verdict UpgradeVerdict
Reason string
}
UpgradeDecision is GateUpgrade's verdict plus an operator-facing reason.
func GateUpgrade ¶
func GateUpgrade(installed, target string, allowDowngrade, force bool) UpgradeDecision
GateUpgrade decides whether an in-place upgrade from the installed version to the target version may proceed. `installed` is the version stamped on the existing control plane (DetectInstall; may be "" when an older install never recorded one); `target` is the version being applied (the upgrading binary's version.Current(), or an explicit --version).
When both are valid semver they are ordered with golang.org/x/mod/semver: equal is a repair re-apply, newer proceeds (a major jump asks for an extra confirm), older is refused unless --allow-downgrade. When either side isn't orderable semver the gate degrades to equal/not-equal and any change requires --force. --force overrides every refusal and confirm.
type UpgradeVerdict ¶
type UpgradeVerdict int
UpgradeVerdict is GateUpgrade's top-level decision.
const ( // VerdictProceed: apply under the normal plan + single confirm gate; no // extra acknowledgement is required. VerdictProceed UpgradeVerdict = iota // VerdictConfirm: proceed only after an explicit acknowledgement beyond the // plan confirm (a major-version jump, or an install whose version can't be // read/ordered). The caller auto-accepts this under --yes/--force. VerdictConfirm // VerdictRefuse: do not proceed (a downgrade without --allow-downgrade, or a // non-orderable version change without --force). VerdictRefuse )
func (UpgradeVerdict) String ¶
func (v UpgradeVerdict) String() string