Skip to main content

Module consts

Module consts 

Source
Expand description

Well-known wire-contract strings: the finalizer, labels, annotations, and condition types that form kopiur’s public Kubernetes surface (ADR §4.5, ADR-0005 §2/§14(c)).

These live in kopiur-api — not the controller — because they are part of the API contract itself: external tooling (the kubectl kopiur plugin, GitOps health checks, user automation) must agree on them byte-for-byte with the operator. Controller-internal reasons/actions/deadlines stay in kopiur-controller’s own consts module.

Constants§

ALLOW_IDENTITY_CHANGE_ANNOTATION
Acknowledges an intentional identity-affecting change on UPDATE. Two surfaces share it:
ALLOW_MASS_DELETION_ANNOTATION
Acknowledges a mass-deletion wave on a Repository/ClusterRepository. Value: an RFC3339 timestamp. A HELD external deletion is released iff its Snapshot’s metadata.deletionTimestamp <= this value — “I approve what is pending NOW”. Deliberately VALUED (unlike the presence-only allow-identity-change ack, consumed at a single admission instant): this annotation is read continuously by the controller, so a presence-only ack left behind (or committed to Git) would disarm the breaker forever. With the timestamp, a stale ack is inert against any LATER wave, nothing ever needs to remove it, and the operator never edits user metadata. The controller clamps the effective value to <= its own now (clock-skew guard); an unparseable value is ignored (Warning event on the repository).
ALLOW_REINITIALIZE_ANNOTATION
Acknowledges a deliberate RE-INITIALIZATION of a Repository/ClusterRepository whose backend was wiped: kopiur refuses to auto-create a fresh kopia repository over a once-Ready one (the pinned status.uniqueId), and this annotation is the human “yes, I know the history is gone — make a new one”.
ALREADY_INITIALIZED_REASON
reason for SEEDED_CONDITION = True when spec.seed was a standing no-op: the repository was already initialized, so nothing was copied. This is the steady state of a seed block left in a GitOps manifest forever.
API_VERSION
The API version string for kopiur CRDs (used in mover TargetRefs and kubectl -o name-style output).
AZURE_WORKLOAD_IDENTITY_LABEL
Pod label opting a mover pod into the azure-workload-identity mutating webhook: pods carrying azure.workload.identity/use: "true" and running as a federated ServiceAccount get AZURE_TENANT_ID/AZURE_CLIENT_ID/ AZURE_FEDERATED_TOKEN_FILE (and the projected token volume) injected — exactly the env kopia’s azure backend binds its credential flags to. Stamped by the operator (and the CLI’s browse sessions) on every mover pod for a repository whose azure backend uses auth.workloadIdentity. Lives here because the operator and kubectl kopiur must agree on it byte-for-byte.
AZURE_WORKLOAD_IDENTITY_LABEL_VALUE
The AZURE_WORKLOAD_IDENTITY_LABEL value opting the pod in.
BLOCKED_ON_UNREADABLE_RUN_REASON
reason/Event reason for SCHEDULE_RUNNABLE_CONDITION = False: a previous run of this schedule sits at a phase string written by a NEWER kopiur, so this build can never observe it reach a terminal phase. Under the default concurrencyPolicy: Forbid that stops the schedule permanently, and nothing about the SnapshotSchedule itself would otherwise say so — the silent-wedge shape of #359, one kind removed.
CONFIG_LABEL
Label naming the SnapshotPolicy a Snapshot was produced from.
CREDENTIALS_AVAILABLE_CONDITION
Snapshot/Restore condition surfaced when the mover Job’s credential Secret is absent from the workload namespace — False carries the actionable message (which Secret, which namespace, why, and how to fix). ADR §4.12.
DEFAULT_CATALOG_REFRESH_INTERVAL
Default catalog re-scan cadence when spec.catalog.refreshInterval is unset: how often a Ready repository re-lists its kopia snapshots to materialize (and expire) origin: discovered Snapshot CRs. Part of the documented API contract (field-reference), so it lives here rather than in the controller.
DEFAULT_CA_BUNDLE_KEY
Default key within a tls.caBundleRef ConfigMap when key is unset — the conventional filename cert-manager and trust-manager emit CA bundles under. Lives here (not in the controller) because the kubectl-plugin resolves the same reference client-side and must agree on the default (centralize-config).
DEFAULT_FAILED_JOBS_HISTORY_LIMIT
Default SnapshotSchedule.spec.failedJobsHistoryLimit when unset: how many Failed Snapshot CRs from a schedule to retain (the rest are pruned). Bounds failure history so a schedule firing against a persistently-failing precondition or backend doesn’t accumulate Failed CRs forever. GFS retention applies only to successful snapshots, so this is the only bound on failures (ADR-0003). Part of the documented API contract, so it lives here, not in the controller.
DEFAULT_HEALTH_PROBE_ENABLED
Default spec.health.probe.enabled when unset: the periodic backend health probe is ON by default (#345). The probe is the sensor for the repository circuit breaker — with the default onFailure: Degrade, a sustained backend failure moves the repository to Degraded and pauses backups until a re-connect succeeds — so it must run unless the user explicitly opts out with enabled: false. Part of the documented API contract, so it lives here, not in the controller.
DEFAULT_HEALTH_PROBE_FAILURE_THRESHOLD
Default spec.health.probe.failureThreshold: how many consecutive failing probes must accumulate before the loud RepositoryVanished / BackendReachable=False condition is raised, an event fired, and — under the default onFailure: Degrade — the repository moved to Degraded (pausing backups). Debounces a single transient blip (an S3 list-after-delete race, a NAS reboot, a credential-rotation moment) from alarming on-call, tripping the breaker, or nudging a destructive manual recreate.
DEFAULT_HEALTH_PROBE_INTERVAL
Default spec.health.probe.interval when unset: how often the backend health probe re-connects a Ready repository to confirm the kopia repository still exists at the backend. Conservative — a vanished/unreachable repository is rare and the probe runs a short mover Job — so it leans long. Part of the documented API contract, so it lives here, not in the controller.
DEFAULT_INDEX_BLOB_WARN_THRESHOLD
Default spec.health.indexBlobWarnThreshold: the index-blob count above which the reconciler warns that maintenance isn’t keeping up. A freshly-compacted repo sits near zero; a wedged-maintenance repo climbs unbounded (a real one reached 1448). Conservative so it only fires when maintenance is clearly behind. Overridable per-repo; 0 disables the warning. Part of the documented API contract, so it lives here rather than in the controller.
DEFAULT_MASS_DELETION_THRESHOLD
Default spec.deletionProtection.threshold (0 disables). 10 pending external destructive deletions is far above legitimate manual cleanup but far below a tooling-driven cascade (the motivating incident was ~600).
DELETION_HELD_CONDITION
Snapshot condition: this deletion is HELD by the mass-deletion breaker (Repository/ClusterRepository spec.deletionProtection.threshold) until acknowledged via ALLOW_MASS_DELETION_ANNOTATION on the repository.
FANOUT_TOO_LARGE_REASON
reason for SCHEDULE_FANOUT_CAPPED_CONDITION = True.
GROUP_LABEL
Label naming the shared CSI VolumeGroupSnapshot a fanned-out Snapshot stages from — carried by BOTH the member Snapshot CRs and the VolumeGroupSnapshot object itself.
INDEX_BLOB_HEALTH_CONDITION
Repository/ClusterRepository condition reporting content-index-blob health (ADR-0005 §13). True = healthy (count under threshold); False with reason TooManyIndexBlobs = the index is growing unbounded because maintenance isn’t compacting. NON-BLOCKING: the repository stays Ready and GitOps health gates are not tripped — it’s a degradation warning, not an outage. Wire-visible (the kubectl plugin’s status reads it).
MAINTENANCE_CONFIGURED_CONDITION
Repository/ClusterRepository condition recording whether a Maintenance covers it (ADR §3.7). Wire-visible: GitOps health checks and the kubectl plugin’s status read it.
MANAGED_BY_LABEL
The standard app.kubernetes.io/managed-by label key. Stamped on every operator-created object (mover Jobs, work-spec ConfigMaps, cache PVC, minted mover SA/RoleBinding, projected credential Secret, CSI VolumeSnapshots) so Argo/Flux recognize them as controller-owned and neither prune nor report them OutOfSync (ADR-0005 §14(c)).
MANAGED_BY_VALUE
The MANAGED_BY_LABEL value identifying kopiur-managed objects.
MASS_DELETION_BREAKER_REASON
reason for DELETION_HELD_CONDITION = True.
MASS_DELETION_HELD_CONDITION
Repository/ClusterRepository condition: pending external destructive deletions for this repository are at/above the breaker threshold and held.
MASS_DELETION_THRESHOLD_EXCEEDED_REASON
reason for MASS_DELETION_HELD_CONDITION = True on a Repository/ClusterRepository: pending external destructive deletions for this repository are at/above its breaker threshold.
MIN_CATALOG_REFRESH_INTERVAL
Floor for spec.catalog.refreshInterval, enforced at admission. Each re-scan of an object-store repository runs a short mover Job; anything faster than this is Job churn with no operational value.
MIN_HEALTH_PROBE_INTERVAL
Floor for spec.health.probe.interval, enforced at admission. Each probe runs a short mover Job (object-store / volume-backed) or an in-process connect; anything faster than this is Job churn with no operational value. Shares the 30s floor with the catalog re-scan for the same reason.
MISSING_CA_BUNDLE_REASON
reason/Event reason for CREDENTIALS_AVAILABLE_CONDITION = False when the missing dependency is the backend’s tls.caBundleRef ConfigMap (or its key): the PEM CA bundle the mover needs to verify a private-CA S3 endpoint. The user creates it; a ConfigMap that never appears never self-heals, so this is a structural gate (crate::gates::MISSING_CA_BUNDLE_GATE), not just a transient retry.
MISSING_CREDENTIALS_REASON
reason/Event reason for CREDENTIALS_AVAILABLE_CONDITION = False.
MISSING_SERVICE_ACCOUNT_REASON
reason/Event reason for CREDENTIALS_AVAILABLE_CONDITION = False when the missing dependency is the workload-identity ServiceAccount the backend’s auth.workloadIdentity names (the user creates it; kopiur never does — its cloud annotations are the user’s federation contract).
MOVER_PERMITTED_CONDITION
Snapshot/Restore condition surfaced when a privileged mover is requested in a namespace that has not opted in — False carries the actionable message.
OP_LABEL
Label naming the operation a mover Job performs, for Jobs whose owning CR doesn’t record the Job name in status (e.g. Restore). Values: OP_RESTORE, OP_RESTORE_TARGET.
OP_RESTORE
OP_LABEL value for a Restore’s mover Job.
OP_RESTORE_TARGET
OP_LABEL value for a Restore’s operator-created target PVC.
ORIGIN_LABEL
Label mirroring a Snapshot’s origin (scheduled/manual/discovered).
PRIVILEGED_MOVERS_ANNOTATION
Namespace annotation a cluster admin sets to allow elevated (root/privileged) movers in that namespace (ADR §4.11/§G16). Without it, a SnapshotPolicy whose spec.mover requests privilege is refused — a tenant could otherwise reuse the minted mover ServiceAccount at that privilege. Mirrors VolSync’s volsync.backube/privileged-movers.
PRIVILEGED_MOVER_NOT_PERMITTED_REASON
reason/Event reason for MOVER_PERMITTED_CONDITION = False.
PRUNED_BY_ANNOTATION
Marks a Snapshot the OPERATOR is deleting as part of its own lifecycle, stamped immediately before the delete call. Values: PrunedBy annotation values (retention, failed-history, policy-cascade, replication-retention). The Snapshot finalizer uses it to distinguish Kopiur’s own prunes from external deletions (GC cascades, kubectl, third-party controllers); external destructive deletions are subject to the schedule-cascade guard and the mass-deletion breaker, operator prunes are not. Any unrecognized value is treated as EXTERNAL (fail-safe). Wire-visible: users and tooling may read it on terminating CRs.
READY_CONDITION
kstatus-compliant standard condition types (ADR-0005 §2) so kubectl wait --for=condition=Ready and Flux/Argo health checks work natively against every reconciled kopiur CRD. The headline readiness condition.
RECONCILING_CONDITION
Set True while a reconcile is making progress toward Ready.
REPLACEMENT_NOT_HELD_REASON
reason for SCHEDULE_REPLACEMENT_HELD_CONDITION = False (not held).
REPLICATION_LABEL
Label tying a blob-replication mover Job back to its owning RepositoryReplication — the single-flight selector the controller uses, and the selector kubectl kopiur replication run prints when a requested run fails and the user needs the Job’s logs. Lives here, next to SNAPSHOT_REPLICATION_LABEL, because the controller and the CLI must agree on it byte-for-byte; a copy in either would drift silently.
REPOSITORIES_READY_CONDITION
SnapshotPolicy condition recording whether every repository the policy targets is Ready. Set False (with REPOSITORY_NOT_READY_REASON) when at least one referenced Repository/ClusterRepository is not Ready: backups, retention, adoption and verification against the not-ready subset are deferred (the ready subset keeps processing), and nothing about the policy’s phase-less surface would otherwise say so — the silent-wedge shape of #359 for the recipe kind. Structural (crate::gates::POLICY_REPOSITORY_NOT_READY_GATE): a repository that never recovers never self-heals this condition.
REPOSITORY_NOT_READY_REASON
reason for REPOSITORIES_READY_CONDITION = False — the same string the Snapshot reconciler stamps on a child parked behind a not-Ready repository (one string, both surfaces; the controller re-exports it).
REPOSITORY_READ_ONLY_REASON
reason/Event reason when a backup or maintenance is refused on a ReadOnly repository (ADR-0005 §11).
REPOSITORY_SLOT_AVAILABLE_CONDITION
Condition recording whether this run holds a slot in its repository’s mover-Job pool (spec.concurrency.maxConcurrentJobs). False with WAITING_FOR_SLOT_REASON means the run is parked at phase: Pending because the pool is full; True with SLOT_ACQUIRED_REASON means it was admitted and its Job launched.
REPOSITORY_UID_LABEL
Label keying a discovered Snapshot to the owning Repository UID (dedup).
REPOSITORY_WRITABLE_CONDITION
Snapshot condition recording whether its repository accepts writes (§11). Set False (with REPOSITORY_READ_ONLY_REASON) when a backup is refused because the repository is mode: ReadOnly.
REPO_POOL_LABEL
Pool-membership label stamped on every mover Job that counts toward its repository’s spec.concurrency.maxConcurrentJobs: backup, restore, and the SOURCE side of a RepositoryReplication/SnapshotReplication. One selector therefore counts a repository’s whole in-flight pool.
RESTORE_REFERENT_AVAILABLE_CONDITION
Restore condition recording whether the object this restore’s repository is DERIVED from exists. Set False (with RESTORE_REFERENT_MISSING_REASON) when the readiness gate cannot even look up the repository because a referent is absent: the explicit spec.repository object itself, or the source.fromPolicy SnapshotPolicy the repository ref is read from (issue #393).
RESTORE_REFERENT_FOUND_REASON
reason for RESTORE_REFERENT_AVAILABLE_CONDITION = True: the referent appeared on a later pass (the clear-side counterpart of RESTORE_REFERENT_MISSING_REASON; controller-internal remediation copy, like the Snapshot gate’s SourcePvcFound). Written ONLY when the condition already exists — the healthy wire never grows the condition.
RESTORE_REFERENT_MISSING_REASON
reason/Event reason for RESTORE_REFERENT_AVAILABLE_CONDITION = False. Distinct from REPOSITORY_NOT_READY_REASON on purpose: that one means “the repository object exists and its backend is unreachable”, which would be a lie for a SnapshotPolicy that was never applied.
RUN_MODE_ANNOTATION
Companion annotation selecting the run kind: quick (default) or full (see kopiur_api::maintenance::ManualRunMode).
RUN_REQUESTED_ANNOTATION
Annotation requesting an out-of-band Maintenance run NOW (Flux-style reconcile trigger). Value: an RFC3339 timestamp; a NEW timestamp requests a new run (re-applying the same value is a no-op once handled). Usable from bare kubectl annotate or kubectl kopiur maintenance run.
SCHEDULE_FANOUT_CAPPED_CONDITION
SnapshotSchedule condition recording whether a fired slot minted its full members × repositories fan-out. True (with FANOUT_TOO_LARGE_REASON) = the cross-product exceeded the fan-out cap and the slot was SKIPPED — and it will keep skipping every slot until the selector is narrowed or the repository list shrunk, which is squarely “needs a human”. Structural (crate::gates::SCHEDULE_FANOUT_CAPPED_GATE, promoted here by the #368 M10 gates/doctor checklist from a controller-internal condition).
SCHEDULE_LABEL
Label naming the SnapshotSchedule that fired a scheduled Snapshot (selector for a schedule’s own children, distinct from CONFIG_LABEL under policySelector fan-out).
SCHEDULE_REPLACEMENT_HELD_CONDITION
SnapshotSchedule condition recording that concurrencyPolicy: Replace is holding a due slot because the run it would replace is itself parked behind its repository’s mover-Job concurrency cap (REPOSITORY_SLOT_AVAILABLE_CONDITION = False). Cancelling a queued run frees no capacity and the replacement would re-queue behind it, so Replace degrades to Forbid-like waiting until the pool drains.
SCHEDULE_RUNNABLE_CONDITION
SnapshotSchedule condition recording whether the schedule is able to fire its next slot. Set False (with BLOCKED_ON_UNREADABLE_RUN_REASON) when the concurrency gate is held by a Snapshot whose status.phase this build cannot interpret.
SEEDED_CONDITION
Repository/ClusterRepository condition reporting the state of spec.seed — initializing a brand-new repository from an existing replica (issue #380).
SEEDED_REASON
reason for SEEDED_CONDITION = True when this repository’s content was actually copied in from spec.seed.from.
SEEDING_REASON
reason for SEEDED_CONDITION = False while the seeding bootstrap Job is in flight. Bounded by spec.seed.failurePolicy (default 24h), but a seed legitimately runs for hours, so anything reporting on a repository must be able to say “seeding” rather than “stuck”.
SEED_FAILURE_REASONS
Every Seeded=False reason that means “the last seed attempt FAILED”, as opposed to the park/progress reasons (WAITING_FOR_SEED_SOURCE_REASON, SEEDING_REASON).
SEED_INCOMPLETE_REASON
reason for SEEDED_CONDITION = False when a migrate-mode seed’s post-verify found snapshots missing at the destination (kopia snapshot migrate exits 0 on a per-source failure, so the destination listing is the only honest success signal). The next attempt resumes the copy.
SEED_LEFT_EMPTY_REASON
reason for SEEDED_CONDITION = False when a seed was armed and the repository ended the bootstrap holding ZERO snapshots — an attempt that initialized the backend and then died. The next attempt resumes the copy; nothing at the backend should be deleted.
SEED_MOVER_TOO_OLD_REASON
reason for SEEDED_CONDITION = False when the running mover image predates spec.seed: it dropped the unknown field, fell into the create fallback, and initialized an EMPTY repository. Terminal — only an image upgrade changes it.
SEED_SOURCE_AUTH_CONFLICT_REASON
reason for SEEDED_CONDITION = False when a migrate-mode seed’s LOCAL backend and its resolved SOURCE repository disagree on workload identity: one seeding pod runs as exactly one ServiceAccount, so one of the two backends would authenticate as the wrong identity (or not at all).
SEED_SOURCE_EMPTY_REASON
reason for SEEDED_CONDITION = False when the seed source IS a kopia repository but holds zero snapshots and spec.seed.allowEmptySource is false. Retried automatically, so a mirror that fills up later seeds itself.
SEED_SOURCE_NOT_FOUND_REASON
reason for SEEDED_CONDITION = False when the seed SOURCE answered but holds no kopia repository (a mis-pointed bucket/prefix, or a mirror that was never written). Retried automatically.
SESSION_BROWSE
SESSION_LABEL value for a read-only browse session.
SESSION_LABEL
Label marking a mover Job as an interactive data-plane session pod (spawned by kubectl kopiur browse/ls/cat/download, not by the operator). Value: SESSION_BROWSE. Wire-visible: the CLI finds (and reuses) a warm session by this selector, and session end deletes by it.
SESSION_REPO_LABEL
Label keying a session Job to the repository it holds open, as <kind>-<name> (e.g. Repository-nas). One warm session per repository: the CLI selects on this so two snapshots in the same repository share a pod.
SKIP_SNAPSHOT_CLEANUP_ANNOTATION
Repo-offline escape hatch: when present, the finalizer is removed without contacting the repository, the snapshot is recorded orphaned, and a SnapshotOrphaned event is emitted (ADR §4.5).
SLOT_ACQUIRED_REASON
reason for REPOSITORY_SLOT_AVAILABLE_CONDITION = True: this run holds a slot in the repository’s mover-Job pool (or the pool is uncapped).
SNAPSHOT_CLEANUP_FINALIZER
The finalizer every Snapshot carries so the operator can run snapshot cleanup before the CR is removed (ADR §4.5 / SKILL “Snapshot lifecycle = CR lifecycle”).
SNAPSHOT_ID_LABEL
Label keying a discovered Snapshot to its kopia snapshot id (dedup, §2.1).
SNAPSHOT_REPLICATION_LABEL
Label naming the SnapshotReplication CR that minted an origin: replicated dest-side copy Snapshot — the selector a replication run (and its pruning pass) uses to find its own copies. Stamped at CREATE, alongside ORIGIN_LABEL/SNAPSHOT_ID_LABEL/REPOSITORY_UID_LABEL. Lives in kopiur-api because the CLI and user automation must agree on it byte-for-byte. (Nothing stamps it yet — reserved by the shared-foundations milestone of #368.)
SOURCE_PVC_AVAILABLE_CONDITION
Snapshot condition recording whether the backup’s DIRECT source PVC (spec.sources[].pvc) exists. Set False (with SOURCE_PVC_MISSING_REASON) when the PVC named by the recipe is absent at launch time: the backup parks (phase: Pending) and, after the controller’s deadline, fails terminally — a PVC that never reappears never self-heals, the silent-wedge shape of #359. Structural (crate::gates::SOURCE_PVC_MISSING_GATE); only the direct source PVC earns this gate — a vanished operator-staged claim is a restage race and stays a transient retry.
SOURCE_PVC_MISSING_REASON
reason/Event reason for SOURCE_PVC_AVAILABLE_CONDITION = False.
STALLED_CONDITION
Set True when the resource is stuck and won’t progress without intervention (mapped from a terminal ErrorClass::Terminal failure).
WAITING_FOR_REPOSITORY_SLOT_REASON
reason/Event reason for SCHEDULE_REPLACEMENT_HELD_CONDITION = True.
WAITING_FOR_SEED_SOURCE_REASON
reason for SEEDED_CONDITION = False when a migrate-mode seed is parked because its source Repository/ClusterRepository is not Ready (or does not exist). The repository stays Pending and re-checks until the source comes up — an out-of-band change nothing in kopiur can make.
WAITING_FOR_SLOT_REASON
reason for REPOSITORY_SLOT_AVAILABLE_CONDITION = False: the repository’s mover-Job pool is at its cap and this run is queued behind it.

Functions§

effective_failed_jobs_history_limit
The effective failed-history limit: failedJobsHistoryLimit when set, else DEFAULT_FAILED_JOBS_HISTORY_LIMIT. Some(0) keeps no failed snapshots.
effective_mass_deletion_threshold
The effective mass-deletion breaker threshold: deletionProtection.threshold when set, else DEFAULT_MASS_DELETION_THRESHOLD. Some(0) disables the breaker.
effective_max_concurrent_jobs
The effective per-repository mover-Job concurrency cap: concurrency.maxConcurrentJobs when set to a NON-ZERO value, else None (uncapped). An absent concurrency block, an absent maxConcurrentJobs, and an explicit 0 all mean the same thing — no limit — so all three collapse to None.