Skip to main content

kopia_lease_identity

Function kopia_lease_identity 

Source
pub fn kopia_lease_identity(lease: &str) -> (String, String)
Expand description

The STABLE kopia client identity a maintenance mover assumes for lease ((username, hostname)); the mover sets it with kopia repository set-client so kopia’s designated-owner check compares something stable — the pod’s own identity is ephemeral (a new hostname every run), which is why comparing kopia’s recorded owner against it can never work.

The derivation forks on the lease’s own shape (the mover only ever sees the lease STRING, never the CR it came from, so the rule must be derivable from the string alone):

  • Exactly 4 /-separated segments, AND the first is literally "kopiur"managed_lease’s two cluster-qualified formats (kopiur/{cluster}/{namespace}/{name}, kopiur/{cluster}/clusterrepository/{name}) — sanitize each segment INDEPENDENTLY (the same character rule, but with no per-segment cap and without ever crossing a segment boundary) and join with .. Every generated segment is already a lowercase, dot-free RFC 1123 label (the cluster name is validated as such; Kubernetes namespace/resource names are too), so for a generated lease this is verbatim kopiur.{cluster}.{namespace}.{name} — and CRITICALLY, injective: two leases can only produce the same hostname if they were /-split identically, because a - inside one segment can no longer be forged into a fake . boundary the way collapsing everything to - allowed (kopiur/east-prod/db/x and kopiur/east/prod-db/x used to collide). No per-segment cap also means a long cluster/namespace/name no longer collides via truncation — capped defensively only on the TOTAL, at [CLUSTER_HOSTNAME_MAX] (253, the identity-hostname byte cap enforced by crate::validate::validate_identity_component), which cluster (≤32) + two Kubernetes names + "kopiur" cannot reach in practice.

    The "kopiur"-first-segment check matters because managed_lease is NOT the only source of lease strings: Ownership.owner is a free-form field a user can hand-author, and a hand-authored value that HAPPENS to have 4 /-separated segments (e.g. a/b/c/d) is not one of our generated formats at all. Gating the dot-join on the reserved "kopiur" prefix — which managed_lease always emits and a user has no reason to — guarantees a hand-authored owner’s derivation can never change across an operator upgrade merely because it happens to split into 4 segments; it always falls to the legacy whole-string sanitizer below, exactly as it did pre-M6. Without this gate, such an owner would silently switch from its a-b-c-d identity to a.b.c.d, and with takeoverPolicy: Never the repository’s maintenance would then yield forever.

  • Any other shape (the legacy 3-segment formats, a 4-segment lease NOT "kopiur"-prefixed, or any other hand-authored Ownership.owner/alias) — the ORIGINAL whole-string sanitizer: collapse the entire lease through the same character rule and cap at [LEGACY_HOSTNAME_MAX] (63, a DNS label). Byte-identical to every pre-M6 lease this function has ever produced.

use kopiur_api::maintenance::kopia_lease_identity;

// Legacy (3-segment / hand-authored): unchanged.
assert_eq!(
    kopia_lease_identity("kopiur/media/nas"),
    ("kopiur".to_string(), "kopiur-media-nas".to_string())
);

// Cluster-qualified (4-segment, "kopiur"-prefixed): dot-joined, segment-preserving.
assert_eq!(
    kopia_lease_identity("kopiur/east/media/nas"),
    ("kopiur".to_string(), "kopiur.east.media.nas".to_string())
);

// A hand-authored 4-segment owner that is NOT "kopiur"-prefixed: legacy
// sanitization, byte-identical to pre-M6 — never dot-joined.
assert_eq!(
    kopia_lease_identity("a/b/c/d"),
    ("kopiur".to_string(), "a-b-c-d".to_string())
);

// Injective: a '-' inside a segment can no longer masquerade as a boundary.
assert_ne!(
    kopia_lease_identity("kopiur/east-prod/db/x").1,
    kopia_lease_identity("kopiur/east/prod-db/x").1
);