Skip to main content

Module identity

Module identity 

Source
Expand description

Kopia identity resolution (ADR §4.2).

Kopia records every snapshot under username@hostname:sourcePath. Kopiur makes that identity an explicit, overridable part of the API rather than an accident of metadata.name/metadata.namespace (ADR §2.2 principle 9). This module is the single place the defaulting + templating rules live. The webhook calls it at admission (so a bad expression/component is rejected on kubectl apply) and the controller calls it again on every reconcile, resolving from the LIVE SnapshotPolicy.spec.identity and the LIVE referenced repository’s identityDefaultsnot a value pinned once and frozen. status.resolved.identity mirrors the most recent resolution for observability; it is not the source of truth a later run reads back. What actually keeps an already-snapshotted policy stable is the fork guard (ValidationError::IdentityWouldFork/ RepositoryIdentityWouldFork): an edit that would change the resolved identity on a policy (or repository) with existing history is rejected at admission unless acknowledged with the allow-identity-change annotation.

§Defaults (ADR §4.2)

  • usernameSnapshotPolicy.metadata.name
  • hostname ← namespace
  • sourcePath/pvc/<pvcName>

§Repository/ClusterRepository identity expressions (CEL)

A crate::common::IdentityDefaults (Repository.spec.identityDefaults or ClusterRepository.spec.identityDefaults) supplies hostnameExpr/ usernameExpr, CEL expressions ([cel]) validated (compiled + trial-evaluated via validate_identity_expr) at admission, then actually rendered against the LIVE consumer + LIVE repository on every reconcile (ADR-0004 §5) — so editing identityDefaults re-renders every consumer that resolves through it on its next backup (guarded by ValidationError::RepositoryIdentityWouldFork, see the module intro above). A consumer’s explicit Identity override always wins over the expression.

§CEL environment

Each expression returns a string and is evaluated against: namespace (the consumer’s namespace), policyName (the SnapshotPolicy’s name), labels and annotations (its metadata maps), and cluster (IdentityDefaults::cluster, or "" when unset — see [identity_context]). Examples: hostnameExpr: "namespace", usernameExpr: "namespace + '-' + policyName", "'team' in labels ? labels['team'] : namespace", "namespace + '.' + cluster". CEL is sandboxed (no I/O, no arbitrary code); a syntax error or out-of-scope variable is rejected at kubectl apply via validate_identity_expr, and a non-string result is a typed error. Expressions are length-capped (MAX_EXPR_LEN) as the cost-budget surrogate.

§Multi-cluster hostname default

When a repository’s IdentityDefaults::cluster is set, the default (no override, no hostnameExpr) kopia identity hostname becomes <namespace>.<cluster> instead of bare <namespace>, so N clusters sharing one repository never collide on a same-named namespace. classify_hostname recovers the namespace/cluster split on the read path (retention, discovered Snapshot placement).

Structs§

IdentityInputs
Inputs to identity resolution. Grouped into a struct so call sites are readable and future inputs slot in without churning the signature.

Enums§

HostClass
Classification of a snapshot identity hostname relative to THIS cluster. Kubernetes namespace names cannot contain ., so the FIRST . unambiguously ends the namespace part of a <namespace>.<cluster> hostname. Total: with no cluster identity every hostname is Bare; an empty namespace part (“.east”) or empty suffix (“ns.”) also classifies Bare (never a panic, never an invalid empty namespace). Suffix comparison is case-sensitive.

Constants§

MAX_EXPR_LEN
Maximum CEL expression length accepted at admission (the cost-budget surrogate; cel 0.13 has no built-in cost API). 1 KiB is far beyond any real identity expression and bounds parse/eval work on adversarial input.

Functions§

classify_hostname
Classify a kopia identity hostname against my_cluster (IdentityDefaults::cluster, resolved from the consuming repository), so a reader (retention pruning, discovered-Snapshot placement) can tell whether a hostname it sees was written by this cluster, another cluster sharing the same repository, or predates cluster identity entirely.
identity_string
Format a kopia identity string. With a source path: username@hostname:path; without one: username@hostname (kopia’s identity-only form, used for catalog queries that aren’t pinned to a path).
resolve_identity
Resolve a ResolvedIdentity from defaults, an optional Repository/ ClusterRepository identity expression set, and explicit consumer overrides (ADR §4.2 / ADR-0004 §5).
validate_identity_expr
Validate a Repository/ClusterRepository identityDefaults CEL expression at admission (ADR-0004 §5): it must compile, and — because CEL reports an out-of-scope variable only at evaluation time — it must also evaluate against a representative context without referencing an undeclared variable. A non-string result is rejected. Missing map keys (e.g. labels['env'] when the trial data lacks env) are tolerated: they are data-dependent, not a structural error.