Skip to main content

Module common

Module common 

Source
Expand description

Shared sub-objects reused across multiple CRDs.

Per ADR-0003 §2.2 (principle 10) and §4.11, every credential, policy, and identity surface is modeled as a sub-object so future fields slot in without API breakage. Leaf Kubernetes types (LabelSelector, ResourceRequirements, PodSecurityContext) are reused from k8s-openapi rather than re-invented.

Structs§

CacheDefaults
kopia cache defaults inherited by every mover unless overridden per-recipe.
CatalogBounds
Bounds on materialization of origin: discovered Snapshot CRs.
CatalogRetain
Bounds on the number of discovered Snapshot CRs kept materialized.
ConfigMapKeyRef
Reference to a key within a ConfigMap (e.g. a CA bundle).
CreateBehavior
Behavior when the repository does not yet exist.
CredentialProjection
Opt-in projection of a repository’s credential Secret(s) into each mover Job’s namespace.
CronSpec
A single cron entry with optional deterministic jitter.
DeletionProtectionSpec
Mass-deletion circuit breaker for this repository’s Snapshots.
Ecc
Reed-Solomon error-correcting-code parity for a freshly-created repository.
Encryption
Repository encryption settings.
FailureBlock
A structured terminal-failure block written by the mover to status.failure.
FailurePolicy
Per-run failure controls passed through to the mover Job.
Identity
Identity overrides — what kopia records as username@hostname:path.
IdentityDefaults
CEL expressions evaluated at admission to derive consumer identity when a SnapshotPolicy doesn’t override. Shared by Repository and ClusterRepository (M5 gave the namespaced kind the same surface the cluster-scoped kind has had since M1) — both mean the same thing: this repository’s backend is (or may be) shared, so its consumers need a hostname/username recipe beyond the bare per-namespace default.
MoverDefaults
Repository-wide mover defaults inherited by every mover, overridable per-recipe via mover.
MoverSpec
Per-recipe mover overrides (resources, cache, security context).
ObjectRef
Generic name/namespace reference to another namespaced object (e.g. a Snapshot CR or PVC).
PodSelector
Selects workload pods by label.
PolicyRef
Reference to a SnapshotPolicy CR.
PvcConsumerInherit
Tuning for InheritSecurityContextFrom::PvcConsumer.
RepositoryRef
Reference from a consumer CR to a Repository or ClusterRepository.
ResolvedIdentity
Fully-resolved identity pinned into status; never re-rendered after admission.
ResolvedMover
The fully-resolved mover configuration for a single run, after the 3-layer field-wise merge hardened ⊂ repo.moverDefaults ⊂ recipe.mover (ADR-0004 §1/§2). security_context is ALWAYS present (the hardened base guarantees it); the rest are Some only when some layer set them. The privileged-mover gate (§4.11/§G16) runs on security_context/pod_security_context here — the merged result — not on the raw recipe, so an elevation introduced by moverDefaults is still gated.
Retention
GFS retention policy — how many snapshots to keep per time bucket.
ScheduleDefaults
Repo-level scheduling defaults, inherited at reconcile time by consumers that don’t set their own equivalent field (ADR §2.2 principle 10: sub-object, not a leaf field, so future defaults — e.g. jitter — slot in without API breakage).
ScratchDefaults
Defaults for the deep-verification scratch volume — the throwaway restore-test target.
SecretKeyRef
Reference to a key within a Secret.
SecretRef
Reference to an entire Secret (the operator reads well-known keys from it).
SnapshotInherit
Tuning for InheritSecurityContextFrom::Snapshot. Empty today; a sub-object (like PopulatorTarget) so future knobs slot in without API breakage.
SourceColocation
Controls mover/source-PVC node co-location (RWO Multi-Attach avoidance).
Throttle
Repository-wide throttling for a mover’s kopia connection; each None leaves kopia’s current limit.
TimezoneAmbiguity
Matched SnapshotSchedule target policies disagreed on their repositories’ scheduleDefaults.timezone, so effective_timezone could not pick one unambiguously and fell back to UTC. The controller surfaces this as a status condition recommending an explicit spec.schedule.timezone.
TlsConfig
TLS settings for object-store backends.

Enums§

CacheVolumeMode
How a mover’s kopia cache volume is provisioned.
DeletionPolicy
Lifecycle of the underlying kopia snapshot when its Snapshot CR is deleted. Produced backups default to Delete; discovered snapshots are forced to Retain.
ForeignSnapshots
How catalog discovery treats snapshots written by ANOTHER cluster. status.catalog.foreignSnapshotCount counts an identity hostname carrying a different .<cluster> suffix ALWAYS, under either value below, plus — under Ignore only — a bare hostname naming no allowed namespace here. Under Fallback, that same disallowed bare host is NOT counted foreign: it materializes into catalog.fallbackNamespace exactly like a disallowed OwnCluster host would, so it is placed rather than dropped-and-counted (see classify_hostname/decide_cluster_placement). Meaningful only when identityDefaults.cluster is set: without a cluster identity there is no notion of “foreign” and the legacy hostname-names-a-namespace placement applies (validators enforce this).
InheritSecurityContextFrom
Where the mover copies its security context from instead of an explicit context.
NamespaceDeletePolicy
What happens to a repository’s snapshots when a consuming namespace is deleted; default Orphan.
PolicyDeletePolicy
What the deletion of a SnapshotPolicy does to the Snapshot CRs carrying its config label (the recipe’s produced/adopted rows — NOT its kopia snapshot history in the abstract, which is exactly what Retain preserves). Default Retain: the CRs are removed but every kopia snapshot survives (rediscoverable/adoptable by a future SnapshotPolicy, including this one re-created). Delete opts into the cascade: each CR’s own deletionPolicy applies, as EXTERNAL deletions subject to the per-repository mass-deletion breaker (deletionProtection.threshold).
PvcAccessMode
A PersistentVolumeClaim access mode as a closed set — ReadWriteOnce, ReadOnlyMany, ReadWriteMany, ReadWriteOncePod — so a typo is rejected by the CRD schema itself instead of surfacing as a provisioner error at the first backup or restore run.
RepositoryKind
Which kind of repository a consumer CR references (Repository or ClusterRepository).
RepositoryMode
Repository access mode; ReadOnly serves restores only (no backups, no maintenance).
ScheduleDeletePolicy
What the deletion of a SnapshotSchedule does to the Snapshot CRs it produced (which Kubernetes GC cascade-deletes via their ownerReference). Default Retain: the CRs are removed but their kopia snapshots survive and the catalog rediscovers them as origin: discovered. Delete opts into the cascade: each Snapshot’s own deletionPolicy applies.
SnapshotAdoption
Whether a discovered snapshot whose resolved identity matches a live SnapshotPolicy is automatically adopted — re-attached (stamped with that policy’s config label, status.origin flipped to Adopted) so GFS retention governs it and eventually prunes it, instead of it sitting in the catalog forever as an immortal discovered row.
SourceColocationMode
How the mover co-locates with the node an RWO source/destination PVC is attached to.

Constants§

DEFAULT_JOB_TTL_SECONDS
Built-in default Job.spec.ttlSecondsAfterFinished (1h) applied to a mover Job when neither moverDefaults.ttlSecondsAfterFinished nor the recipe’s mover.ttlSecondsAfterFinished sets one, so finished backup/restore Jobs and their pods self-GC instead of lingering (ADR-0005 §12).
DEFAULT_POD_STARTUP_DEADLINE_SECONDS
Default grace before a non-starting (wedged) mover pod fails its run — 5 minutes. Long enough to absorb a slow image pull or a brief Unschedulable while an RWO volume detaches from another node, short enough that a genuinely-broken pod (e.g. an impossible securityContext, a missing image) surfaces as Failed fast instead of hanging for hours.
MAX_LOG_TAIL_BYTES
Byte cap for status.logTail (and the stderr tail inside FailureBlock): the mover truncates to the LAST MAX_LOG_TAIL_BYTES bytes before patching status, so a noisy kopia run can’t bloat etcd. Full logs live in the mover Job’s pod. ADR §3.4/§4.10.
MOVER_NONROOT_ID
The nonroot UID/GID baked into the mover image (docker/Dockerfile.mover: USER 65532:65532, distroless nonroot). The hardened pod context defaults fsGroup to this so the kubelet group-owns every mounted volume to the gid the mover actually runs as — most importantly the operator-managed kopia cache, which is otherwise created root:root on PVC-backed storage and unwritable by the unprivileged mover. Centralized here (the single source of the hardened defaults) so the value can never drift from the image.

Traits§

PhaseLabel
A lifecycle-phase enum that can be rendered as a metric label.

Functions§

create_enabled
Whether the operator should create the repository when it does not yet exist.
effective_adoption
The effective adoption policy for a SnapshotPolicy: its own spec.adoption wins; else the target repository’s catalog.adoption; else SnapshotAdoption::Adopt. Neither link is context-free (the repository link resolves per-repo, the policy link per-policy), so neither field carries a schema default — every read goes through this resolver.
effective_run_as_group
The effective runAsGroup following kubelet precedence — the gid peer of effective_run_as_user: container securityContext.runAsGroup if set, else the pod one. None when neither pins a group (image-determined).
effective_run_as_user
The effective runAsUser following kubelet precedence: the container securityContext.runAsUser if set, else the pod securityContext.runAsUser. None when neither pins a UID — the UID is then image-determined (the USER line) and unknowable from the spec.
effective_timezone
Pure. Decide the effective timezone a SnapshotSchedule’s cron is evaluated in, given the schedule’s own spec.schedule.timezone (own) and the scheduleDefaults.timezone of each matched target policy’s repository (policy_repo_defaults, one entry per matched policy; None = that repo sets no default). Mirrors resolve_tz fallback semantics (an unparseable name degrades to UTC — the webhook rejects bad names up front).
hardened_pod_security_context
The restricted-PSA-compatible hardened pod security context — the pod-level peer of hardened_security_context. Defaults fsGroup to MOVER_NONROOT_ID so every mover pod’s volumes (notably the cache) are writable by the unprivileged mover; fsGroupChangePolicy: OnRootMismatch skips the recursive chown when the volume root already matches, so it does not needlessly rewrite ownership on every run.
hardened_security_context
The restricted-PSA-compatible hardened container security context (§4.11/G16): non-root, no privilege escalation, drop ALL caps, seccomp RuntimeDefault.
merge_capabilities
Deep-merge two [Capabilities]: each of add/drop is taken from over when set, else from base. So an over that sets only add keeps base.drop — an add-only override never silently drops the hardened drop:[ALL] (the bug ADR-0004 §2 cites).
merge_context_pair
THE layer merge: overlay one (container, pod) security-context layer pair onto another. Every layer fold — resolve_mover’s hardened ⊂ moverDefaults ⊂ recipe and the controller’s inherited ⊂ explicit pre-fold — MUST go through this function; a lone per-dimension merge_security_context/merge_pod_security_context reintroduces cross-dimension identity shadowing.
merge_pod_security_context
Field-wise overlay of pod [PodSecurityContext] over onto base. Exhaustive literal for the same reason as merge_security_context.
merge_pod_security_context_opt
Option-aware merge_pod_security_context.
merge_resources
Field-wise overlay of [ResourceRequirements]: limits/requests merge per-key (via merge_quantity_map); claims is taken from over when set, else base.
merge_resources_opt
Option-aware merge_resources.
merge_security_context
Field-wise overlay of container [SecurityContext] over onto base: each Some field in over wins, unset fields inherit base; capabilities deep-merge via merge_capabilities (ADR-0004 §2).
merge_security_context_opt
Option-aware merge_security_context (handles the four None/Some cases).
pod_security_context_is_elevated
Whether a pod PodSecurityContext requests root. Pod-level only carries a subset of the container knobs — runAsUser / runAsNonRoot are the ones that can make the mover root (capabilities/privileged are container-only). fsGroup and friends are NOT elevation. Pure helper for requires_privilege_resolved.
pod_startup_deadline_seconds
The effective pod-startup deadline (seconds) for a mover Job: the recipe’s failurePolicy.podStartupDeadlineSeconds, or DEFAULT_POD_STARTUP_DEADLINE_SECONDS when unset. Shared by every reconciler that fast-fails a wedged mover (Snapshot, Restore, Maintenance) so the same default is applied identically on all three.
requires_privilege_resolved
Whether a mover with the given effective container security context (the explicit securityContext, or the one resolved from inheritSecurityContextFrom), pod security context, and privilegedMode is privileged. The controller resolves an inherited context to a concrete SecurityContext and gates on that — so an inherited root context is caught exactly like an explicit one — and inspects the pod-level context too so a pod-level runAsUser: 0 can’t slip past. Pure + exhaustive: the single definition of “privileged” for both the spec-only ([MoverSpec::requires_privilege]) and the resolved paths.
resolve_mover
Resolve the effective mover configuration via the layer merge hardened ⊂ moverDefaults ⊂ recipe (ADR-0004 §1/§2).
resolve_tz
Resolve an optional IANA timezone name to a concrete zone, defaulting to UTC. An unparseable name falls back to UTC defensively — the admission webhook rejects bad names up front via validate::validate_timezone, so reconcile-time resolution should never see one.
resolve_tz_with_default
Resolve a consuming cron’s own optional IANA timezone against a repository-level default, falling back to UTC (mirrors resolve_tz): own wins when set, else repo_default (typically Repository/ClusterRepository spec.scheduleDefaults.timezone), else UTC. An unparseable name at whichever level is selected falls back to UTC defensively, same as resolve_tz — the admission webhook rejects bad names up front for both levels via validate::validate_timezone, so reconcile-time resolution should never see one.
security_context_is_elevated
Whether a container SecurityContext requests privileges beyond a normal unprivileged user (root UID, privileged, escalation, added capabilities, or an explicit runAsNonRoot: false). Pure helper for [MoverSpec::requires_privilege].