Skip to main content

KopiaClient

Struct KopiaClient 

Source
pub struct KopiaClient { /* private fields */ }
Expand description

A kopia client backed by the real kopia binary via tokio::process.

Construction is pure — building a client never spawns a process. Only the async methods invoke kopia. The builder defaults the binary to kopia (resolved via PATH); inject a path for tests or non-standard images:

use std::path::PathBuf;
use kopiur_kopia::KopiaClient;

let client = KopiaClient::builder().build();
assert_eq!(client.binary(), &PathBuf::from("kopia"));

let custom = KopiaClient::builder()
    .binary("/usr/local/bin/kopia")
    .env("KOPIA_PASSWORD", "s3cr3t")
    .build();
assert_eq!(custom.binary(), &PathBuf::from("/usr/local/bin/kopia"));

Implementations§

Source§

impl KopiaClient

Source

pub fn builder() -> KopiaClientBuilder

Start building a client.

Source

pub fn binary(&self) -> &PathBuf

The configured binary path (useful for diagnostics / tests).

Source

pub fn common_env(&self) -> &BTreeMap<String, String>

The environment applied to every invocation (useful for tests asserting that the cache/log/config dirs were injected).

Source

pub fn common_args(&self) -> &[String]

The global args appended after the subcommand on every invocation (useful for tests asserting e.g. --no-auto-maintenance is always present).

Source

pub fn default_timeout(&self) -> Option<Duration>

The timeout applied to every invocation when set (useful for tests asserting a caller time-bounds its subprocesses).

Source

pub async fn repository_connect( &self, spec: &ConnectSpec, cache: CacheTuning, ) -> Result<(), KopiaError>

Connect to an existing repository (kopia repository connect <backend>). cache sizes this connection’s local kopia cache; pass CacheTuning::default to leave kopia’s defaults.

Source

pub async fn repository_connect_readonly( &self, spec: &ConnectSpec, cache: CacheTuning, ) -> Result<(), KopiaError>

Connect to an existing repository read-only (kopia repository connect <backend> --readonly). The read-only bit persists in kopia’s client config, so every subsequent invocation on this connection is structurally unable to mutate the repository — the connect mode for browse sessions. Every other mover flow stays on the read-write Self::repository_connect.

Source

pub async fn repository_create( &self, spec: &ConnectSpec, cache: CacheTuning, create_opts: &CreateOptions, ) -> Result<(), KopiaError>

Create a new repository (kopia repository create <backend>). cache sizes the creating connection’s local cache; pass CacheTuning::default to leave kopia’s defaults. create_opts carries the create-time-fixed knobs (encryption/splitter/hash algorithms, ECC) baked into the repository format.

Source

pub async fn repository_throttle_set( &self, throttle: &ThrottleArgs, ) -> Result<(), KopiaError>

Set the repository’s throttling limits (kopia repository throttle set). Caps upload/download bytes-per-sec and read/list/upload ops-per-sec so a run doesn’t saturate a link or hammer an object store (ADR-0005 §13(e)). A no-op (skips the call) when nothing is set.

Source

pub async fn repository_set_parameters( &self, params: &SetParametersArgs, ) -> Result<(), KopiaError>

Rewrite mutable repository parameters on the CONNECTED repository (kopia repository set-parameters [flags]), issue #258. No-op when nothing is set.

Two properties the caller must respect:

  • Never on a read-only connection. kopia hard-errors (unable to write blobcfg blob: PutBlob() failed for "kopia.blobcfg": storage is read-only), so a mode: ReadOnly repository must not reach here.
  • This invalidates every other client’s cached format blob. kopia says so itself (“you must disconnect and re-connect all other Kopia clients”) and drops the local kopia.repository/kopia.blobcfg cache. Other clients re-read within formatBlobCacheDuration (15m) on their own, but this is why the caller applies only on observed drift rather than unconditionally.

Needs no maintenance ownership/lease.

Source

pub async fn repository_sync_to( &self, destination: &ConnectSpec, opts: &SyncToOptions, ) -> Result<(), KopiaError>

Mirror the connected repository’s blobs to a destination backend (kopia repository sync-to <destination> [flags]), ADR-0005 §13(d) / issue #216. The caller must already be connected to the source repository; this copies its blobs to destination. The destination’s backend args are built by ConnectSpec::backend_args (the same builder connect/create use), so a new backend variant is wired through automatically. opts carries the tuning knobs (parallelism, --delete, the must-exist/times/update tri-states, throughput caps) — see SyncToOptions. Destination credentials are supplied via the environment, never on argv, exactly like connect/create. Success is exit code 0.

Source

pub async fn repository_sync_to_with_env( &self, destination: &ConnectSpec, opts: &SyncToOptions, dest_env: &BTreeMap<String, Option<String>>, ) -> Result<(), KopiaError>

Self::repository_sync_to with a per-invocation environment overlay applied to the sync-to subprocess only. The replication mover uses this to give the destination backend its own credentials: it maps each of the destination backend’s env-delivered credential vars (AWS_*, AZURE_*, …) from the KOPIUR_DEST_-prefixed copy in its environment, and unsets any that the destination doesn’t provide so a source credential cannot leak. The source repository is read from the persisted connection config (kopia bakes the source storage credentials in at repository connect), so overlaying the plain credential names here cannot disturb the source read. Some(v) sets a var, None removes it. Credentials travel via env, never argv.

Source

pub async fn snapshot_create( &self, source_path: &str, tags: &BTreeMap<String, String>, override_source: Option<&str>, ) -> Result<SnapshotCreateResult, KopiaError>

Create a snapshot of source_path with the given tags (key:value) and kopia’s own defaults for snapshot create’s tuning knobs. Returns the parsed create result.

override_source, when set, is passed to kopia as --override-source (format username@hostname:path). This is how Kopiur records snapshots under the operator-resolved identity (ADR §4.2 / anchoring principle 9) rather than the mover pod’s ambient user@host. Without it kopia would attribute the snapshot to the pod, breaking the identity model that the whole catalog/retention/restore machinery keys on.

Source

pub async fn snapshot_create_with( &self, source_path: &str, tags: &BTreeMap<String, String>, override_source: Option<&str>, opts: &SnapshotCreateOptions, ) -> Result<SnapshotCreateResult, KopiaError>

Create a snapshot honoring the operator’s SnapshotCreateOptions (failFast, uploadLimitMb, description — M4 flag sweep, issue #216). Same identity/tags contract as Self::snapshot_create, which now delegates here with an all-default opts (byte-for-byte the same argv as before this option struct existed).

Source

pub async fn snapshot_list( &self, filter: Option<&SnapshotSource>, ) -> Result<Vec<SnapshotListEntry>, KopiaError>

List snapshots, optionally filtered by source identity. With no filter this lists all snapshots in the repository.

Source

pub async fn snapshot_delete(&self, id: &str) -> Result<(), KopiaError>

Delete a single snapshot by manifest id. kopia’s snapshot delete requires --delete to actually remove (otherwise it dry-runs) and does not support --json; success is signaled by exit code 0.

IDEMPOTENT: an already-absent snapshot (no snapshots matched <id> on stderr) is success — that IS the goal state. kopia dedups identical-content snapshot manifests, so several Snapshot CRs can legitimately pin the SAME kopia id; when GFS retention prunes more than one of them, the first finalizer’s delete removes the manifest and the rest would otherwise fail terminally, wedging their CRs in Deleting forever (caught by the retention e2e under suite load).

Source

pub async fn snapshot_restore( &self, id: &str, target_dir: &str, ) -> Result<(), KopiaError>

Restore a snapshot’s contents to a target directory with kopia’s default options. kopia’s snapshot restore does not emit JSON; success is exit code 0.

Source

pub async fn snapshot_restore_with( &self, id: &str, target_dir: &str, opts: &RestoreOptions, ) -> Result<(), KopiaError>

Restore a snapshot honoring the operator’s RestoreOptions (enableFileDeletion, ignorePermissionErrors, writeFilesAtomically, …). Success is exit code 0.

Source

pub async fn snapshot_verify( &self, opts: &VerifyOptions, ) -> Result<(), KopiaError>

Verify repository/snapshot integrity (kopia snapshot verify). Success is exit code 0; a verification failure surfaces as a non-zero exit.

Source

pub async fn snapshot_estimate( &self, source_path: &str, ) -> Result<(), KopiaError>

Estimate the size/scope of snapshotting source_path (kopia snapshot estimate). Best-effort; success is exit code 0.

Source

pub async fn snapshot_pin(&self, id: &str, pin: &str) -> Result<(), KopiaError>

Add a pin to a snapshot so maintenance/expiration never deletes it (kopia snapshot pin <id> --add <pin>). Used to protect snapshots whose Snapshot carries deletionPolicy: Retain.

Source

pub async fn snapshot_unpin( &self, id: &str, pin: &str, ) -> Result<(), KopiaError>

Remove a pin from a snapshot (kopia snapshot pin <id> --remove <pin>).

Source

pub async fn snapshot_expire(&self, delete: bool) -> Result<(), KopiaError>

Expire snapshots per the repository’s policy (kopia snapshot expire --all). When delete is false this is a dry-run (kopia requires --delete to actually remove). Success is exit code 0.

Source

pub async fn repository_validate_provider(&self) -> Result<(), KopiaError>

Validate that the connected storage provider behaves correctly (kopia repository validate-provider). A good Repository-readiness preflight for object-store backends. Success is exit code 0.

Source

pub async fn policy_set( &self, target: &str, policy: &PolicyArgs, ) -> Result<(), KopiaError>

Apply a policy to target (an identity string, a path, or --global) via kopia policy set. The operator calls this before the first snapshot so SnapshotPolicy.spec.policy (compression/splitter/ignore) is honored.

Source

pub async fn policy_show(&self, target: &str) -> Result<Value, KopiaError>

Show the effective policy for target (kopia policy show <target> --json), parsed as a generic JSON value.

Source

pub async fn repository_status(&self) -> Result<RepositoryStatus, KopiaError>

Get repository status (kopia repository status --json).

This spawns kopia, so the example is no_run (it would need a real binary + connected repository):

use kopiur_kopia::KopiaClient;

let client = KopiaClient::builder()
    .env("KOPIA_PASSWORD", "s3cr3t")
    .build();
let status = client.repository_status().await?;
println!("repository unique id: {}", status.unique_id_hex);
Source

pub async fn maintenance_info(&self) -> Result<MaintenanceInfo, KopiaError>

Get maintenance info (kopia maintenance info --json).

Source

pub async fn index_blob_count(&self) -> Result<i64, KopiaError>

Count the repository’s content-index blobs (kopia index list --json, array length). kopia’s index is compacted by periodic maintenance; when maintenance stops (e.g. a stale lease owner), this grows unbounded and kopia eventually warns “Found too many index blobs (N), ensure periodic repository maintenance”. The operator surfaces a Kubernetes Warning when this crosses a configurable threshold. Cheap — lists index-blob metadata only, no content read. Verified against kopia 0.23 (index list --[no-]json).

Source

pub async fn maintenance_set_owner_me(&self) -> Result<(), KopiaError>

Claim the repository’s maintenance ownership for the currently connected identity (kopia maintenance set --owner me). kopia ties “who may run maintenance” to the connected user@hostname and rejects a maintenance run from anyone but the designated owner (“maintenance must be run by designated user: …”). A repo bootstrapped by the controller in-process is owned by the controller’s identity, so a mover Job (a different pod) MUST claim ownership before it can run maintenance. Idempotent; no JSON, success is exit 0.

Source

pub async fn maintenance_set_owner(&self, owner: &str) -> Result<(), KopiaError>

Set the repository’s maintenance owner to an EXPLICIT user@hostname (kopia maintenance set --owner <owner>). Used by the bootstrap mover right after repository create to stamp the stable, lease-derived owner (kopiur_api::maintenance::kopia_owner_for_lease) instead of the creating pod’s ephemeral identity — without this, every later maintenance mover sees a foreign owner and takeoverPolicy: Never yields forever. Verified against kopia 0.23 maintenance set --help (--owner=OWNER Set maintenance owner user@hostname).

Source

pub async fn repository_set_client_identity( &self, username: &str, hostname: &str, ) -> Result<(), KopiaError>

Switch the CONNECTED client identity (kopia repository set-client --username … --hostname …). The maintenance mover assumes the stable lease-derived identity this way (kopia 0.23 has no identity override on repository connect; the OS user@pod-hostname is ephemeral), so maintenance set --owner me records a stable string and the designated-user check passes on every later run. Verified against kopia 0.23 repository set-client --help.

Source

pub async fn maintenance_run( &self, mode: MaintenanceMode, ) -> Result<(), KopiaError>

Run a maintenance pass. kopia’s maintenance run does not emit JSON; success is exit code 0. The caller must already be the designated maintenance owner (see maintenance_set_owner_me).

Source

pub async fn run_raw_streaming( &self, args: &[String], sink: &mut (dyn AsyncWrite + Unpin + Send), ) -> Result<u64, KopiaError>

Run kopia with args and stream stdout byte-for-byte into sink (no line splitting, no UTF-8 assumption), returning the byte count on a zero exit. This is the file-content path for kopia show <file-oid> (the browse data-plane’s cat/download), where stdout is the raw object bytes — buffering it whole or splitting it into lines would corrupt/clamp arbitrarily large binary files.

stderr is accumulated like every other invocation; a non-zero exit yields KopiaError::NonZeroExit with the stderr tail. NOTE: bytes already streamed before a late failure have reached the sink — callers writing to a file should verify the count and discard partial output on error (kopia’s show either streams the object or fails up front, so in practice a failure produces no payload). Honors default_timeout.

Source

pub fn server_start( &self, spec: &ServerStartSpec, password: Option<&str>, ) -> KopiaError

Run kopia server start, replacing this process with kopia via exec.

On success this never returns (kopia takes over the PID and runs until it is signalled). It returns a KopiaError only if exec itself fails (e.g. the binary is missing). The repository must already be connected (call KopiaClient::repository_connect first) — the server reads the connected repo from the kopia config file.

password is the UI password for ServerAuthMode::Password; it is appended to argv here, inside the server pod, so it never reaches the controller, a ConfigMap, or the pure [server_start_args] builder. For ServerAuthMode::None it is ignored.

Trait Implementations§

Source§

impl Clone for KopiaClient

Source§

fn clone(&self) -> KopiaClient

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for KopiaClient

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more