Skip to main content

Client

Struct Client 

Source
pub struct Client(/* private fields */);
Expand description

The Incus API client. Cheap to clone (Arc-backed) - share one instance across tasks rather than constructing a new one per call.

Implementations§

Source§

impl Client

Source

pub async fn wait_for_operation( &self, id: Uuid, timeout: Option<Duration>, ) -> Result<Operation>

Waits for operation id to reach a terminal status, using Incus’s .../wait?timeout=<seconds> long-poll endpoint.

  • timeout = Some(duration): bounds a single long-poll call. If the operation is still in-progress when that window elapses, this returns Ok(Operation) with the in-progress snapshot - it does not re-poll, since the caller explicitly chose how long they’re willing to wait.
  • timeout = None: waits indefinitely by transparently re-issuing the long-poll call as many times as needed until a terminal status is reached. Each individual call is still bounded server-side; this just means the method as a whole doesn’t return until completion.

A terminal status in the 400-599 (failure) range returns Err(Error::OperationFailed { .. }), not Ok(Operation) - callers don’t need to inspect status_code themselves to detect failure.

Source

pub async fn cancel_operation(&self, op: &Operation) -> Result<()>

Cancels operation op if it’s cancellable. Short-circuits with Error::NotCancellable (no network call) when op.may_cancel is false, since the server would reject it anyway and there’s no reason to round-trip to find that out.

Source§

impl Client

Source

pub async fn list_images(&self, recursion: bool) -> Result<Vec<Value>>

recursion = true fetches every image’s full object in one call; recursion = false returns lightweight fingerprint/URL references.

Source

pub async fn get_image(&self, fingerprint: &str) -> Result<WithEtag<Image>>

Fetches one image by fingerprint, along with its ETag for use as a later If-Match precondition.

Source

pub async fn create_image(&self, params: &Value) -> Result<Operation>

Always async: image import/creation is documented as a long-running operation (fetching/unpacking a source, which can be a remote URL or a large upload).

Source

pub async fn update_image( &self, fingerprint: &str, new_definition: &Value, etag: Option<&str>, ) -> Result<Operation>

Full replacement update (PUT). etag, if provided, is sent as If-Match for optimistic concurrency; a stale ETag surfaces as Error::PreconditionFailed, not the generic Error::Api.

Source

pub async fn update_image_guarded( &self, fetched: &WithEtag<Image>, new_definition: &Value, ) -> Result<Operation>

Same as Client::update_image, but takes the WithEtag from a prior Client::get_image call directly instead of a bare etag: Option<&str> - see instances::Client::update_instance_guarded’s doc comment for why this exists alongside the raw-etag version.

Source

pub async fn delete_image(&self, fingerprint: &str) -> Result<Operation>

Source§

impl Client

Source

pub async fn list_instances(&self, recursion: bool) -> Result<Vec<Value>>

Lists instances. recursion = true fetches every instance’s full object (config/devices/state) in one call and can be expensive on hosts with many instances; recursion = false returns lightweight name/URL references only.

Source

pub async fn get_instance(&self, name: &str) -> Result<WithEtag<Instance>>

Fetches one instance by name, along with its ETag for use as a later If-Match precondition.

Source

pub async fn create_instance( &self, params: &CreateInstanceParams, ) -> Result<Operation>

Creates an instance. Always async, per Incus’s documented behavior for instance creation.

Source

pub async fn update_instance( &self, name: &str, new_definition: &Value, etag: Option<&str>, ) -> Result<Operation>

Full replacement update (PUT). etag, if provided, is sent as If-Match for optimistic concurrency; a stale ETag surfaces as Error::PreconditionFailed, not the generic Error::Api.

Source

pub async fn update_instance_guarded( &self, fetched: &WithEtag<Instance>, new_definition: &Value, ) -> Result<Operation>

Same as Client::update_instance, but takes the WithEtag from a prior Client::get_instance call directly instead of a bare etag: Option<&str> - the “pit of success” version of the fetch-then-guarded-update workflow, since it makes threading a genuinely-fetched ETag the natural path rather than something a caller has to remember to do by hand. update_instance remains available directly for callers with a legitimate reason to supply their own ETag (e.g. one persisted from a previous process).

Source

pub async fn patch_instance( &self, name: &str, patch: &Value, etag: Option<&str>, ) -> Result<Operation>

Partial update (PATCH) - use this instead of update_instance for small config changes, to avoid a GET-then-PUT round trip.

Source

pub async fn patch_instance_guarded( &self, fetched: &WithEtag<Instance>, patch: &Value, ) -> Result<Operation>

Same as Client::patch_instance, but takes the WithEtag from a prior Client::get_instance call directly - see Client::update_instance_guarded’s doc comment for why this exists alongside the raw-etag version.

Source

pub async fn delete_instance(&self, name: &str) -> Result<Operation>

Source

pub async fn start_instance(&self, name: &str) -> Result<Operation>

Source

pub async fn stop_instance(&self, name: &str) -> Result<Operation>

Source

pub async fn restart_instance(&self, name: &str) -> Result<Operation>

Source

pub async fn pause_instance(&self, name: &str) -> Result<Operation>

Source

pub async fn list_snapshots( &self, instance_name: &str, recursion: bool, ) -> Result<Vec<Value>>

Source

pub async fn create_snapshot( &self, instance_name: &str, snapshot_name: &str, ) -> Result<Operation>

Source

pub async fn delete_snapshot( &self, instance_name: &str, snapshot_name: &str, ) -> Result<Operation>

Source§

impl Client

Source

pub async fn list_networks(&self, recursion: bool) -> Result<Vec<Value>>

Source

pub async fn get_network(&self, name: &str) -> Result<WithEtag<Network>>

Fetches one network by name, along with its ETag for use as a later If-Match precondition.

Source

pub async fn create_network(&self, params: &Value) -> Result<()>

Creates a network. Synchronous: the network exists by the time this returns, with no operation to wait on. Verified against cmd/incusd/networks.go’s networksPost on the lxc/incus main branch, which always returns response.SyncResponseLocation - there is no code path that returns an async operation response, for any network type/backend.

Source

pub async fn update_network( &self, name: &str, new_definition: &Value, etag: Option<&str>, ) -> Result<()>

Full replacement update (PUT). etag, if provided, is sent as If-Match for optimistic concurrency; a stale ETag surfaces as Error::PreconditionFailed, not the generic Error::Api.

Synchronous, like Client::create_network - verified against cmd/incusd/networks.go’s doNetworkUpdate, which always returns response.EmptySyncResponse.

Source

pub async fn update_network_guarded( &self, fetched: &WithEtag<Network>, new_definition: &Value, ) -> Result<()>

Same as Client::update_network, but takes the WithEtag from a prior Client::get_network call directly instead of a bare etag: Option<&str> - see instances::Client::update_instance_guarded’s doc comment for why this exists alongside the raw-etag version.

Source

pub async fn delete_network(&self, name: &str) -> Result<()>

Synchronous - verified against cmd/incusd/networks.go’s networkDelete, which always returns response.EmptySyncResponse.

Source§

impl Client

Source

pub async fn list_projects(&self, recursion: bool) -> Result<Vec<Value>>

Source

pub async fn get_project(&self, name: &str) -> Result<WithEtag<Project>>

Fetches one project by name, along with its ETag for use as a later If-Match precondition.

Source

pub async fn create_project(&self, params: &Value) -> Result<()>

Creates a project. Synchronous: the project exists by the time this returns, with no operation to wait on. Verified against cmd/incusd/api_project.go’s projectsPost on the lxc/incus main branch, which always returns response.SyncResponseLocation.

Source

pub async fn update_project( &self, name: &str, new_definition: &Value, etag: Option<&str>, ) -> Result<()>

Full replacement update (PUT). etag, if provided, is sent as If-Match for optimistic concurrency; a stale ETag surfaces as Error::PreconditionFailed, not the generic Error::Api.

Synchronous, like Client::create_project - verified against cmd/incusd/api_project.go’s projectChange, which always returns response.EmptySyncResponse.

Source

pub async fn update_project_guarded( &self, fetched: &WithEtag<Project>, new_definition: &Value, ) -> Result<()>

Same as Client::update_project, but takes the WithEtag from a prior Client::get_project call directly instead of a bare etag: Option<&str> - see instances::Client::update_instance_guarded’s doc comment for why this exists alongside the raw-etag version.

Source

pub async fn delete_project(&self, name: &str) -> Result<()>

Synchronous - verified against cmd/incusd/api_project.go’s projectDelete, which always returns response.EmptySyncResponse.

Source§

impl Client

Source

pub async fn list_storage_pools(&self, recursion: bool) -> Result<Vec<Value>>

Source

pub async fn get_storage_pool( &self, name: &str, ) -> Result<WithEtag<StoragePool>>

Fetches one storage pool by name, along with its ETag for use as a later If-Match precondition.

Source

pub async fn create_storage_pool(&self, params: &Value) -> Result<()>

Creates a storage pool. Synchronous: the pool exists by the time this returns, with no operation to wait on. Verified against cmd/incusd/storage_pools.go’s storagePoolsPost on the lxc/incus main branch, which always returns response.SyncResponseLocation.

Source

pub async fn update_storage_pool( &self, name: &str, new_definition: &Value, etag: Option<&str>, ) -> Result<()>

Full replacement update (PUT). etag, if provided, is sent as If-Match for optimistic concurrency; a stale ETag surfaces as Error::PreconditionFailed, not the generic Error::Api.

Synchronous, like Client::create_storage_pool - verified against cmd/incusd/storage_pools.go’s doStoragePoolUpdate, which always returns response.EmptySyncResponse.

Source

pub async fn update_storage_pool_guarded( &self, fetched: &WithEtag<StoragePool>, new_definition: &Value, ) -> Result<()>

Same as Client::update_storage_pool, but takes the WithEtag from a prior Client::get_storage_pool call directly instead of a bare etag: Option<&str> - see instances::Client::update_instance_guarded’s doc comment for why this exists alongside the raw-etag version.

Source

pub async fn delete_storage_pool(&self, name: &str) -> Result<()>

Synchronous - verified against cmd/incusd/storage_pools.go’s storagePoolDelete, which always returns response.EmptySyncResponse.

Source

pub async fn list_storage_volumes( &self, pool_name: &str, recursion: bool, ) -> Result<Vec<Value>>

Lists volumes within one pool. See the module doc comment for why there’s no “list all volumes across all pools” convenience method.

Per the Incus REST API, recursion = false returns an array of bare URL strings (not typed volume objects), so - like every other list_* method in this crate - this returns untyped serde_json::Values rather than Vec<StorageVolume>. Use recursion = true to get full volume objects in one call, or get_storage_volume to fetch one volume’s full object by name.

Source

pub async fn create_storage_volume( &self, pool_name: &str, params: &Value, ) -> Result<Option<Operation>>

Creates a volume. Unlike every other create/update/delete method in this crate, volume creation is genuinely conditional on the request payload: creating a blank volume (params has no source.name) is synchronous, but creating one by copying another volume (params has a source.name) is asynchronous. Verified against cmd/incusd/storage_volumes.go’s doVolumeCreateOrCopy on the lxc/incus main branch: it returns response.EmptySyncResponse when req.Source.Name == "", and operations.OperationResponse(op) otherwise. Returns None for the synchronous case (nothing to wait for) and Some(operation) for the asynchronous one.

Source

pub async fn get_storage_volume( &self, pool_name: &str, volume_type: &str, volume_name: &str, ) -> Result<WithEtag<StorageVolume>>

Fetches one volume’s full object by pool, type, and name, along with its ETag for use as a later If-Match precondition.

Source

pub async fn update_storage_volume( &self, pool_name: &str, volume_type: &str, volume_name: &str, new_definition: &Value, etag: Option<&str>, ) -> Result<()>

Full replacement update (PUT). etag, if provided, is sent as If-Match for optimistic concurrency; a stale ETag surfaces as Error::PreconditionFailed, not the generic Error::Api.

Synchronous - verified against cmd/incusd/storage_volumes.go’s storagePoolVolumePut, which always returns response.EmptySyncResponse.

Source

pub async fn update_storage_volume_guarded( &self, pool_name: &str, fetched: &WithEtag<StorageVolume>, new_definition: &Value, ) -> Result<()>

Same as Client::update_storage_volume, but takes the WithEtag from a prior Client::get_storage_volume call directly instead of a bare etag: Option<&str> - volume_type and the volume’s own name are derived from the fetched value; pool_name is still required explicitly since a volume’s pool isn’t part of its own returned object. See instances::Client::update_instance_guarded’s doc comment for why this exists alongside the raw-etag version.

Source

pub async fn delete_storage_volume( &self, pool_name: &str, volume_type: &str, volume_name: &str, ) -> Result<()>

Synchronous - verified against cmd/incusd/storage_volumes.go’s storagePoolVolumeDelete, which always returns response.EmptySyncResponse.

Source§

impl Client

Source

pub fn new(config: ClientConfig) -> Self

Builds a client from config. No I/O happens here - connection attempts happen lazily, once per request, when a method is called.

Source§

impl Client

Source

pub async fn subscribe_events(&self, filter: EventFilter) -> Result<EventStream>

Subscribes to Incus’s /1.0/events WebSocket stream, filtered per filter. The connection is made over the same Unix socket as every other request - see the module doc comment for why the resulting stream is exposed directly rather than through a buffering channel.

Trait Implementations§

Source§

impl Clone for Client

Source§

fn clone(&self) -> Client

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 Client

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.

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> Same for T

Source§

type Output = T

Should always be Self
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.