githubEdit

Provider API Reference

Complete reference for the Provider trait and associated types.

Provider Trait

The Provider trait defines the contract that all cloud providers must implement:

#[async_trait]
pub trait Provider: Send + Sync {
    /// Returns the provider name for logging and identification
    fn name(&self) -> &'static str;

    /// Creates a new cloud instance
    async fn create_instance(&self, request: &InstanceRequest) -> ProviderResult<ProviderInstance>;

    /// Destroys an instance by ID (must be idempotent)
    async fn destroy_instance(&self, id: &str) -> ProviderResult<()>;

    /// Gets instance details by ID, returns None if not found
    async fn get_instance(&self, id: &str) -> ProviderResult<Option<ProviderInstance>>;

    /// Lists all spuff-managed instances
    async fn list_instances(&self) -> ProviderResult<Vec<ProviderInstance>>;

    /// Waits for instance to be ready (running + has IP)
    async fn wait_ready(&self, id: &str) -> ProviderResult<ProviderInstance>;

    /// Creates a snapshot of an instance
    async fn create_snapshot(&self, instance_id: &str, name: &str) -> ProviderResult<Snapshot>;

    /// Lists all spuff-managed snapshots
    async fn list_snapshots(&self) -> ProviderResult<Vec<Snapshot>>;

    /// Deletes a snapshot by ID (must be idempotent)
    async fn delete_snapshot(&self, id: &str) -> ProviderResult<()>;

    /// Returns SSH key identifiers (optional, default returns empty)
    async fn get_ssh_keys(&self) -> ProviderResult<Vec<String>> { Ok(vec![]) }

    /// Returns whether this provider supports snapshots
    fn supports_snapshots(&self) -> bool { true }
}

Core Types

InstanceRequest

Configuration for creating a new instance. This is provider-agnostic - each provider translates it to their API format.

Notes:

  • name should be unique within the account

  • user_data is raw cloud-init YAML - providers handle encoding if needed

  • labels should include identifiers for filtering (e.g., managed-by: spuff)

ImageSpec

Provider-agnostic image specification:

Provider Mapping Examples:

ImageSpec
DigitalOcean
Hetzner
AWS

Ubuntu("24.04")

ubuntu-24-04-x64

ubuntu-24.04

ami-xxx (lookup)

Debian("12")

debian-12-x64

debian-12

ami-xxx (lookup)

Custom(id)

pass through

pass through

pass through

Snapshot(id)

pass through

pass through

pass through

ProviderInstance

Represents a cloud instance:

InstanceStatus

Enum representing instance states:

Status Mapping Guidelines:

Provider State
Spuff Status

new, initializing, starting, pending

New

active, running

Active

stopping, off, stopped

Off

archive, terminated

Archive

(anything else)

Unknown(state)

Snapshot

Represents a saved instance state:

ProviderTimeouts

Configurable timeout values for provider operations:

Helper Methods:


Error Types

ProviderError

Structured error types for proper handling and retry logic:

Helper Constructors:

Retry Logic:


Method Specifications

name

Returns the provider name for logging and identification.

Returns: Static string with provider name (e.g., "digitalocean", "hetzner")


create_instance

Creates a new cloud instance with the specified configuration.

Parameters:

  • request: &InstanceRequest - Instance configuration

Returns:

  • ProviderResult<ProviderInstance> - Created instance (may not be ready yet)

Behavior:

  1. Translate InstanceRequest to provider-specific API request

  2. Resolve ImageSpec to provider-specific image ID/slug

  3. Send API request to create instance

  4. Return immediately with instance metadata

  5. Instance may still be initializing - use wait_ready() to wait

Error Cases:

  • Authentication - Invalid API token

  • InvalidConfig - Invalid region, size, or image

  • QuotaExceeded - Account limit reached

  • Api - Other API errors

Example:


destroy_instance

Destroys an instance by ID.

Parameters:

  • id: &str - Instance ID to destroy

Returns:

  • ProviderResult<()> - Success or error

Behavior:

  1. Send delete request to provider API

  2. Do not wait for deletion to complete

  3. MUST be idempotent: Return Ok(()) if instance doesn't exist (404)

Example:


get_instance

Gets instance details by ID.

Parameters:

  • id: &str - Instance ID

Returns:

  • ProviderResult<Option<ProviderInstance>> - Instance if found, None if not exists

Behavior:

  1. Query provider API for instance

  2. Return None if instance doesn't exist (404)

  3. Return instance details if found

Example:


list_instances

Lists all spuff-managed instances.

Returns:

  • ProviderResult<Vec<ProviderInstance>> - List of instances

Behavior:

  1. Query provider API with spuff label/tag filter

  2. Return only instances tagged with spuff identifiers

  3. Handle pagination if needed

Filter Requirements:

  • Only return instances with managed-by: spuff label (or equivalent)

  • This prevents listing unrelated instances in the account


wait_ready

Waits for instance to be fully ready.

Parameters:

  • id: &str - Instance ID

Returns:

  • ProviderResult<ProviderInstance> - Ready instance with IP address

Behavior:

  1. Poll get_instance() periodically

  2. Check for Active status AND non-unspecified IP

  3. Return when both conditions are met

  4. Timeout after ProviderTimeouts::instance_ready

Ready Conditions:

  • status == InstanceStatus::Active

  • ip.is_unspecified() == false (not 0.0.0.0)

Example:


create_snapshot

Creates a snapshot of an instance.

Parameters:

  • instance_id: &str - Instance to snapshot

  • name: &str - Snapshot name/description

Returns:

  • ProviderResult<Snapshot> - Created snapshot

Behavior:

  1. Initiate snapshot creation

  2. Wait for completion if the operation is async (using action polling)

  3. Tag snapshot with spuff identifiers for filtering

  4. Return snapshot metadata

Note: Some providers (like Hetzner) have async snapshot creation that returns an action ID. The implementation should wait for the action to complete before returning.


list_snapshots

Lists all spuff-managed snapshots.

Returns:

  • ProviderResult<Vec<Snapshot>> - List of snapshots

Behavior:

  1. Query provider API with spuff filter

  2. Return only spuff-tagged snapshots

  3. Handle pagination if needed


delete_snapshot

Deletes a snapshot by ID.

Parameters:

  • id: &str - Snapshot ID

Returns:

  • ProviderResult<()> - Success or error

Behavior:

  • MUST be idempotent: Return Ok(()) if snapshot doesn't exist (404)


ProviderFactory Trait

The factory trait for creating provider instances:


ProviderRegistry

Registry for managing provider factories:

Usage:


Type Aliases

Last updated

Was this helpful?