client

package
v1.0.0-beta.19 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 29, 2026 License: Apache-2.0 Imports: 39 Imported by: 0

Documentation

Overview

Package client - a High-level Incus API wrapper with resource management and parallel execution.

This package provides a compose-spec friendly interface for managing Incus resources: instances, networks, volumes, profiles, and images.

It also adds support for container image building by using `podman`.

Package client provides a high-level wrapper around the Incus client library.

This package abstracts the complexities of interacting with Incus servers and provides a compose-spec friendly interface for managing instances, networks, volumes, and projects.

For detailed documentation, see: https://github.com/lxc/incus-compose/tree/main/docs/architecture/client

Index

Constants

View Source
const (
	HealthStatusUnknown   = "unknown"
	HealthStatusHealthy   = "healthy"
	HealthStatusUnhealthy = "unhealthy"
	HealthStatusStopped   = "stopped"

	HealthKeyPrefix = "user.healthcheck."

	// HealthStatusKey is the instance config key used to store health status.
	HealthStatusKey = HealthKeyPrefix + "status"

	// HealthStoppedKey when "true" means healthchecking is stopped.
	HealthStoppedKey = HealthKeyPrefix + "stopped"
)

Health check status constants written to HealthConfigKey by ic-healthd.

View Source
const (
	PriorityProject  = 1 << 8  // Infrastructure (created first, deleted last)
	PriorityProfile  = 1 << 9  // Base config
	PriorityImage    = 1 << 10 // Images (own batch for parallel downloads)
	PriorityNetwork  = 1 << 11 // Networks
	PriorityVolume   = 1 << 12 // Storage
	PriorityInstance = 1 << 13 // Instance depends on everything above
)

Resource creation priorities using powers of 2 for clear separation. Lower priority values are created first and deleted last.

View Source
const (
	InstanceDeviceTypeProxy = "proxy"
	InstanceDeviceTypeDisk  = "disk"
	InstanceDeviceTypeNic   = "nic"
	InstanceDeviceTypeTmpfs = "tmpfs"
)

Device type constants.

View Source
const MaxIncusNameLen = 63

MaxIncusNameLen is the maximum length for Incus instance names. Incus allows up to 63 characters (DNS hostname limit).

Variables

View Source
var (
	// ErrUnsupportedAction indicates the resource does not support the action.
	ErrUnsupportedAction = NewError("resource does not support action")

	// ErrUnknown indicates an unknown error occurred.
	ErrUnknown = NewError("unknown")

	// ErrNotRunning indicates a command on a not running instance.
	ErrNotRunning = NewError("not running")

	// ErrUnknownConfig indicates an unknown config for a resource.
	ErrUnknownConfig = NewError("unknown config for resource")

	// ErrNilPointer indicates something is a nil pointer.
	ErrNilPointer = NewError("found a nil pointer")

	// ErrOperation is returned within an operation.
	ErrOperation = NewError("in an operation")

	// ErrBadDeviceConfig indicates a bad device config.
	ErrBadDeviceConfig = NewError("bad config for device")

	// ErrDependencyNotEnsured indicates a dependency is not ensured.
	ErrDependencyNotEnsured = NewError("dependency not ensured")

	// ErrDisconnected indicates an operation was attempted on a disconnected client.
	ErrDisconnected = NewError("client is not connected")

	// ErrConnectionFailed indicates a connection attempt failed.
	ErrConnectionFailed = NewError("connection failed")

	// ErrServerNotListening indicates the Incus server has no core.https_address
	// set. incus-compose copies cached images between projects using pull mode,
	// which needs the server reachable over the network.
	ErrServerNotListening = NewError("the incus server is not listening on the network (core.https_address is not set); incus-compose needs it for image caching, set it with `incus config set core.https_address=:8443`, see https://github.com/lxc/incus-compose/blob/main/docs/getting-started.md")

	// ErrAborted indicates an operation was aborted (e.g., by BeforeAny hook).
	ErrAborted = NewError("operation aborted")

	// ErrNotFound indicates a resource was not found.
	ErrNotFound = NewError("resource not found")

	// ErrNotEnsured indicates an operation requires the resource to be ensured first.
	ErrNotEnsured = NewError("resource not ensured")

	// ErrImageRequired indicates an instance requires an image.
	ErrImageRequired = NewError("instances without an image are not yet supported")

	// ErrUnknownResource indicates an unknown resource kind.
	ErrUnknownResource = NewError("unknown resource kind")

	// ErrInvalidFormat indicates invalid format or syntax.
	ErrInvalidFormat = NewError("invalid format")

	// ErrImageSource indicates an image source error.
	ErrImageSource = NewError("image source error")

	// ErrDeviceConflict indicates a device name conflict.
	ErrDeviceConflict = NewError("device conflict")

	// ErrVolumeMismatch indicates volume configuration mismatch.
	ErrVolumeMismatch = NewError("volume configuration mismatch")

	// ErrCreate indicates a resource creation error.
	ErrCreate = NewError("create failed")
)
View Source
var ErrDNSWatcher = NewError("DNSWatcher")

ErrDNSWatcher is used as wrapper to indicate an error happened in the DNSWatcher.

Functions

func ByKind

func ByKind[T Resource](resources []Resource, kind Kind) ([]T, error)

ByKind filters resources by kind and returns them as the specified type.

func DNSmasqParse

func DNSmasqParse(raw string) map[string][]string

DNSmasqParse parses raw.dnsmasq address lines into a service->[]IP map.

func RandString

func RandString(n int) string

RandString is a helper that creates a random string for the given size (n). It is from https://stackoverflow.com/a/31832326 -- RandStringBytesMaskImprSrcSB.

func RunAction

func RunAction(ctx context.Context, r Resource, action Action, opts ...Option) error

RunAction runs a action on a resource.

func SanitizeIncusName

func SanitizeIncusName(name string, maxLength int) string

SanitizeIncusName converts a string to a valid Incus instance name. Converts to lowercase, replaces special chars and underscores with hyphens. Names exceeding 63 chars are replaced with a 32-char hex hash for DNS compatibility.

func SupportsAction

func SupportsAction(r Resource, action Action) bool

SupportsAction returns if the Resource supports the action.

Types

type Action

type Action string

Action identifies a resource action.

const (
	ActionEnsure Action = "ensure"
	ActionDelete Action = "delete"
	ActionStart  Action = "start"
	ActionStop   Action = "stop"
	ActionLog    Action = "log"
)

Action constants for resource actions.

type BaseResource

type BaseResource struct {
	// contains filtered or unexported fields
}

BaseResource provides common fields for all Incus resources.

func NewBaseResource

func NewBaseResource(kind Kind, name string, priority int) *BaseResource

NewBaseResource creates a new BaseResource.

func (*BaseResource) Kind

func (r *BaseResource) Kind() Kind

Kind returns the resource kind.

func (*BaseResource) Name

func (r *BaseResource) Name() string

Name returns the resource name.

func (*BaseResource) Priority

func (r *BaseResource) Priority() int

Priority returns the resource priority.

type BuildConfig

type BuildConfig struct {
	// Context is the build context directory (absolute path).
	Context string

	// Dockerfile is an optional path to the Containerfile/Dockerfile.
	// Empty means the builder uses its default (Containerfile or Dockerfile in Context).
	Dockerfile string

	// DockerfileInline is inline Dockerfile content from compose build.dockerfile_inline.
	DockerfileInline string

	// Target is the Dockerfile stage to build.
	Target string

	// Platform is the OCI platform to build for, for example linux/amd64.
	Platform string

	// Args are build-time variables (--build-arg).
	Args map[string]string

	// NoCache disables layer caching during the build.
	NoCache bool

	// Pull always attempts to pull a newer version of the base image.
	Pull bool
}

BuildConfig holds the parameters read from a compose service's build: block.

type BuildInfo

type BuildInfo struct {
	// Mode controls rebuild behaviour.
	Mode BuildMode

	// PreferredBuilder is the container builder binary name or absolute path.
	// Empty means auto-detect (tries podman, then docker).
	PreferredBuilder string
}

BuildInfo carries the rebuild mode and optional builder selection for ActionEnsure.

type BuildMode

type BuildMode int

BuildMode controls how build-configured images are treated during Ensure.

const (
	// BuildAuto builds the image only when it is missing (default).
	BuildAuto BuildMode = iota
	// BuildForce rebuilds the image even if an existing one is present.
	BuildForce
	// BuildNever never builds; returns an error if the image is missing.
	BuildNever
)

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client wraps a project-scoped Incus client with resource management.

func NewOfflineClient

func NewOfflineClient(ctx context.Context, name string) *Client

NewOfflineClient creates a disconnected project client for resource planning. It can create in-memory resources, but cannot run Incus operations.

func (*Client) AddHookAfter

func (c *Client) AddHookAfter(hook func(ctx context.Context, action Action, r Resource, args Options, err error) error)

AddHookAfter adds a hook that will be executed after any action (LIFO order).

func (*Client) AddHookBefore

func (c *Client) AddHookBefore(hook func(ctx context.Context, action Action, r Resource, args Options, err error) error)

AddHookBefore adds a hook that will be executed before any action. You may use it for abort control.

func (*Client) AddHookConnected

func (c *Client) AddHookConnected(hook func(err error) error)

AddHookConnected adds a hook that will be executed when the client connects (FIFO order).

func (*Client) AddHookDone

func (c *Client) AddHookDone(hook func(err error) error)

AddHookDone adds a hook that will be executed when the client's work is complete (LIFO order).

func (*Client) Config

func (c *Client) Config() ClientConfig

Config returns a copy of the clients config.

func (*Client) Connection

func (c *Client) Connection() (*incusClient.ProtocolIncus, error)

Connection returns a fresh, event-isolated project-scoped client.

Each call returns its own *ProtocolIncus (with its own event-listener state) that shares the underlying HTTP transp^ort, which is safe for concurrent use.

func (*Client) Done

func (c *Client) Done() error

Done fires the done hooks. Call when the client's work is complete.

func (*Client) FindHealthd

func (c *Client) FindHealthd() (string, error)

FindHealthd returns the name of the healthd instance in the project, identified by user.healthcheck.daemon=true.

func (*Client) Global

func (c *Client) Global() *GlobalClient

Global returns the GlobalClient associated with this project client.

func (*Client) GlobalConnection

func (c *Client) GlobalConnection() (*incusClient.ProtocolIncus, error)

GlobalConnection returns the global incus connection (with the default project).

func (*Client) IncusProject

func (c *Client) IncusProject() string

IncusProject returns the sanitized Incus project name.

func (*Client) InstanceExists

func (c *Client) InstanceExists(name string) (bool, error)

InstanceExists reports whether an instance with the given name exists in Incus.

func (*Client) InstanceIPs

func (c *Client) InstanceIPs(incusName string) (ips []InterfaceIPs, err error)

InstanceIPs fetches the global IPv4 and IPv6 addresses of a named instance directly from Incus, without going through an Instance resource.

func (*Client) IsConnected

func (c *Client) IsConnected() bool

IsConnected reports whether the project client can run Incus operations.

func (*Client) IsDebugging

func (c *Client) IsDebugging() bool

IsDebugging returns if debugging is enabled.

func (*Client) IsRemote

func (c *Client) IsRemote() bool

IsRemote returns true if connected via network (not unix socket).

func (*Client) LogDebug

func (c *Client) LogDebug(msg string, args ...any)

LogDebug logs an debug message. The `any` here is ok.

func (*Client) LogError

func (c *Client) LogError(msg string, args ...any)

LogError logs an error. The `any` here is ok.

func (*Client) LogInfo

func (c *Client) LogInfo(msg string, args ...any)

LogInfo logs an info message. The `any` here is ok.

func (*Client) LogWarn

func (c *Client) LogWarn(msg string, args ...any)

LogWarn logs an warning message. The `any` here is ok.

func (*Client) Open

func (c *Client) Open() error

Open fires the connected hooks. Call once after registering all hooks, before running any stack actions.

func (*Client) Project

func (c *Client) Project() string

Project returns the user-facing project name.

func (*Client) RegisterDNSWatcher

func (c *Client) RegisterDNSWatcher() error

RegisterDNSWatcher wires service-name DNS records into the project's managed networks via the client lifecycle hooks. On each instance create/start/stop/ delete it reads raw.dnsmasq from Incus, updates only the records for services seen in this run (identified via IncusName), preserves all other records, and writes back. Multiple projects can coexist in the same network without clobbering each other's records.

func (*Client) ResetResources

func (c *Client) ResetResources()

ResetResources resets the resource store to start fresh.

func (*Client) ResolveImageFingerprint

func (c *Client) ResolveImageFingerprint(fingerprint string) string

ResolveImageFingerprint returns the first alias name for the given fingerprint, or the fingerprint itself if no alias is found or the lookup fails.

func (*Client) Resource

func (c *Client) Resource(kind Kind, name string, config Config) (Resource, error)

Resource returns an existing resource or creates a new one. Deduplication uses IncusName so differently-formatted inputs that resolve to the same Incus resource (e.g. "nginx:alpine" vs "docker.io/library/nginx:alpine") return the same object.

type ClientConfig

type ClientConfig struct {
	// URL is the Incus server URL to connect to.
	URL string

	// Logger to use within this client.
	Logger *slog.Logger

	// NetworkPrefix is the prefix for new networks (default: "ic-").
	NetworkPrefix string

	// DefaultStoragePool is the storage pool to use for volumes (default: "default").
	DefaultStoragePool string

	// DescriptionFormat is the format string for resource descriptions (default: "incus-compose: %s").
	DescriptionFormat string

	// ProvidedInstanceServer allows injecting an existing connection (for testing).
	ProvidedInstanceServer incusClient.InstanceServer

	// CacheProject is the project name to use as image cache.
	// If set, the project will be created if it doesn't exist.
	CacheProject string
}

ClientConfig holds configuration options for the Client.

type ClientOption

type ClientOption func(*ClientConfig)

ClientOption is a functional option for configuring the Client.

func ClientCacheProject

func ClientCacheProject(n string) ClientOption

ClientCacheProject sets the project name to use as image cache.

func ClientDefaultStoragePool

func ClientDefaultStoragePool(n string) ClientOption

ClientDefaultStoragePool sets the default storage pool name.

func ClientDescriptionFormat

func ClientDescriptionFormat(n string) ClientOption

ClientDescriptionFormat sets the format string for resource descriptions.

func ClientLogger

func ClientLogger(l *slog.Logger) ClientOption

ClientLogger sets the client to use within the created client.

func ClientNetworkPrefix

func ClientNetworkPrefix(n string) ClientOption

ClientNetworkPrefix sets the prefix for network names.

func ClientProvideConnection

func ClientProvideConnection(instances incusClient.InstanceServer) ClientOption

ClientProvideConnection injects existing connections (for testing).

func ClientProvideInstanceServer

func ClientProvideInstanceServer(server incusClient.InstanceServer) ClientOption

ClientProvideInstanceServer injects an existing instance server connection.

func ClientURL

func ClientURL(u string) ClientOption

ClientURL sets the Incus server ClientURL.

type Config

type Config interface {
	GetConfig() any
}

Config is implemented by resource configuration types.

type DeleteAble

type DeleteAble interface {
	Delete(ctx context.Context, opts ...Option) error
}

DeleteAble is implemented by resources that can be deleted.

type EnsureAble

type EnsureAble interface {
	// Ensure fetches an existing Resource or creates a new one.
	// If a Resource with the same name exists, it is returned.
	Ensure(ctx context.Context, opts ...Option) error
}

EnsureAble is implemented by resources that can be ensured.

type EnsureProjectOption

type EnsureProjectOption func(*ensureProjectOptions)

EnsureProjectOption is a functional option for configuring project creation.

func EnsureProjectWithConfig

func EnsureProjectWithConfig(config map[string]string) EnsureProjectOption

EnsureProjectWithConfig sets configuration options to apply when creating the project. These options are merged with default features configuration.

func EnsureProjectWithCreate

func EnsureProjectWithCreate() EnsureProjectOption

EnsureProjectWithCreate enables project creation if the project doesn't exist.

type Error

type Error struct {
	// contains filtered or unexported fields
}

Error is a sentinel-based error type that supports context enrichment.

func NewError

func NewError(text string) *Error

NewError creates a new sentinel error.

func (*Error) As

func (e *Error) As(target any) bool

As implements errors.As() support by copying to target if it's *Error.

func (*Error) Error

func (e *Error) Error() string

Error implements the error interface.

func (*Error) Is

func (e *Error) Is(target error) bool

Is implements errors.Is() support by comparing sentinel pointers.

func (*Error) Unwrap

func (e *Error) Unwrap() error

Unwrap returns the wrapped error for errors.Unwrap() support.

func (*Error) WithAction

func (e *Error) WithAction(action Action) *Error

WithAction adds action context to the error.

func (*Error) WithKindName

func (e *Error) WithKindName(kind Kind, name string) *Error

WithKindName adds resource kind and name context to the error.

func (*Error) WithResource

func (e *Error) WithResource(resource Resource) *Error

WithResource adds resource context to the error.

func (*Error) WithText

func (e *Error) WithText(text string) *Error

WithText adds text context to the error.

func (*Error) Wrap

func (e *Error) Wrap(wrapped error) *Error

Wrap wraps another error, preserving the sentinel identity.

type GlobalClient

type GlobalClient struct {
	// contains filtered or unexported fields
}

GlobalClient provides a high-level interface to Incus operations.

func New

func New(ctx context.Context, opts ...ClientOption) *GlobalClient

New creates a new Client with the provided context and logger.

func NewTestClient

func NewTestClient(ctx context.Context) (*GlobalClient, error)

NewTestClient creates a new GlobalClient for testing.

func (*GlobalClient) AddHookAfter

func (c *GlobalClient) AddHookAfter(hook func(ctx context.Context, action Action, r Resource, args Options, err error) error)

AddHookAfter adds a hook that will be executed after any action (LIFO order).

func (*GlobalClient) AddHookBefore

func (c *GlobalClient) AddHookBefore(hook func(ctx context.Context, action Action, r Resource, args Options, err error) error)

AddHookBefore adds a hook that will be executed before any action (FIFO order). You may use it for abort control.

func (*GlobalClient) CliConfig

func (c *GlobalClient) CliConfig() *cliconfig.Config

CliConfig returns the CLI config for image server resolution.

func (*GlobalClient) Connect

func (c *GlobalClient) Connect() error

Connect establishes a connection to the Incus server.

func (*GlobalClient) Connection

func (c *GlobalClient) Connection() (*incusClient.ProtocolIncus, error)

Connection returns a fresh, event-isolated connection scoped to the default project.

Like Client.Connection, each call returns its own *ProtocolIncus (with its own event-listener state) sharing the underlying HTTP transport, so concurrent workers never race on the library's skipEvents field.

func (*GlobalClient) ConnectionIPs

func (c *GlobalClient) ConnectionIPs() ([]net.IP, error)

ConnectionIPs returns the IP of the current connection, this function is cached by GlobalClient.connectionIP.

func (*GlobalClient) DeleteProject

func (c *GlobalClient) DeleteProject(name string, force bool) error

DeleteProject deletes a project and removes it from the cache.

func (*GlobalClient) EnsureProject

func (c *GlobalClient) EnsureProject(name string, opts ...EnsureProjectOption) (*Client, error)

EnsureProject ensures a project exists and returns a Client for it. Options control whether the project is created if it doesn't exist and what config to apply.

func (*GlobalClient) HTTPSAddress

func (c *GlobalClient) HTTPSAddress() (string, error)

HTTPSAddress returns the core.https_address of the incus server.

func (*GlobalClient) IsConnected

func (c *GlobalClient) IsConnected() bool

IsConnected returns true if the client is connected.

func (*GlobalClient) IsDebugging

func (c *GlobalClient) IsDebugging() bool

IsDebugging returns true if debug logging is enabled.

func (*GlobalClient) IsRemote

func (c *GlobalClient) IsRemote() bool

IsRemote returns true if connected via network (not unix socket).

func (*GlobalClient) LogDebug

func (c *GlobalClient) LogDebug(msg string, args ...any)

LogDebug logs a debug message. The `any` here is ok.

func (*GlobalClient) LogError

func (c *GlobalClient) LogError(msg string, args ...any)

LogError logs an error. The `any` here is ok.

func (*GlobalClient) LogInfo

func (c *GlobalClient) LogInfo(msg string, args ...any)

LogInfo logs an info message. The `any` here is ok.

func (*GlobalClient) LogWarn

func (c *GlobalClient) LogWarn(msg string, args ...any)

LogWarn logs a warning. The `any` here is ok.

func (*GlobalClient) NetworkBridgeIPs

func (c *GlobalClient) NetworkBridgeIPs(networkName string) (ipv4 []string, ipv6 []string, err error)

NetworkBridgeIPs returns the IPv4 and IPv6 bridge addresses of an Incus network. The addresses are returned without CIDR notation. Addresses for which the network config key is absent or set to "none" are omitted.

func (*GlobalClient) SameHost

func (c *GlobalClient) SameHost() error

SameHost returns nil of the connected incus and the current host share the same ip else an error.

func (*GlobalClient) SetOutputHandler

func (c *GlobalClient) SetOutputHandler(handler func(action Action, r Resource, data []byte))

SetOutputHandler sets the handler for resource output (e.g., logs). The handler receives raw bytes - formatting is the caller's responsibility.

func (*GlobalClient) SetProgressHandler

func (c *GlobalClient) SetProgressHandler(handler func(action Action, r Resource, args Options, p Progress))

SetProgressHandler sets the handler for live operation progress. Pass nil to disable. Operations run in parallel, so the handler may be called concurrently and must be safe for concurrent use.

func (*GlobalClient) URL

func (c *GlobalClient) URL() (*url.URL, error)

URL returns the URL of the connection.

type Image

type Image struct {
	*BaseResource

	Config ImageConfig

	// State - nil means not ensured.
	IncusAlias *incusApi.ImageAliasesEntry
	ETag       string

	// OCI metadata extracted from the image (empty/0 for native Incus images).
	UID        uint64
	GID        uint64
	Entrypoint string
	Cwd        string
	// contains filtered or unexported fields
}

Image represents an OCI or native Incus image copied to the Incus image cache.

func (*Image) Created

func (r *Image) Created() bool

Created returns true if the image was created during the last Ensure call.

func (*Image) Delete

func (r *Image) Delete(ctx context.Context, opts ...Option) error

Delete removes the per-project copy of the image from the active project.

Projects are created with features.images=true, so creating an instance copies the image into the active project. Those copies are removed here on down; without it they accumulate and go stale relative to the auto-updated cache (see issue #29). The cache lives in a separate project and is left untouched, so cached images persist across down/up cycles.

Delete is idempotent: a missing per-project copy is not an error.

func (*Image) Ensure

func (r *Image) Ensure(ctx context.Context, opts ...Option) error

Ensure retrieves an existing image from cache or copies it if Create option is set. With the Pull option, a cached image is refreshed from its source registry. When ImageConfig.Build is set the image is built locally via podman/docker.

func (*Image) IncusName

func (r *Image) IncusName() string

IncusName returns the image alias name used in Incus.

func (*Image) IsEnsured

func (r *Image) IsEnsured() bool

IsEnsured returns true if the image has been fetched/copied to cache.

func (*Image) NativeIncus

func (r *Image) NativeIncus() bool

NativeIncus returns true if this is a native Incus image.

func (*Image) Remote

func (r *Image) Remote() string

Remote returns the image remote.

func (*Image) Size

func (r *Image) Size() int64

Size returns the total image size in bytes as reported by the source server, or 0 when unknown. It is resolved best-effort before a download starts.

func (*Image) Status

func (r *Image) Status() string

Status returns the image status: "Unknown" or "Cached".

func (*Image) String

func (r *Image) String() string

String is for debugging.

type ImageConfig

type ImageConfig struct {
	// CacheServer is an image server to use as cache (for library users).
	// Takes precedence over CacheProject.
	CacheServer incusClient.InstanceServer

	// CacheProject is the project name to use as cache (for CLI users).
	// The project will be created if it doesn't exist.
	// Ignored if CacheServer is set.
	CacheProject string

	// Build, when set, marks this image as locally built rather than pulled
	// from a registry. Ensure will shell out to podman/docker instead of
	// calling CopyImage.
	Build *BuildConfig

	// A list of service dependencies for log output.
	Services []string
}

ImageConfig contains the source and cache configuration for an image.

func (*ImageConfig) GetConfig

func (c *ImageConfig) GetConfig() any

GetConfig returns the configuration.

type Instance

type Instance struct {
	*BaseResource

	Config InstanceConfig

	// State - nil means not ensured.
	IncusInstance *incusApi.Instance
	ETag          string

	// UID/GID extracted from container (for volume shifting).
	UID uint64
	GID uint64

	IncusInstanceFull *incusApi.InstanceFull
	// contains filtered or unexported fields
}

Instance represents an Incus container or virtual machine.

func (*Instance) Created

func (r *Instance) Created() bool

Created returns true if the instance was created during the last Ensure call.

func (*Instance) Delete

func (r *Instance) Delete(ctx context.Context, opts ...Option) error

Delete removes the instance from Incus.

func (*Instance) Ensure

func (r *Instance) Ensure(ctx context.Context, opts ...Option) error

Ensure retrieves an existing instance or creates a new one if args.Create is true.

func (*Instance) HasFull

func (r *Instance) HasFull() bool

HasFull returns true if the instance has a full instance.

func (*Instance) IncusName

func (r *Instance) IncusName() string

IncusName returns the sanitized instance name used in Incus.

func (*Instance) IsEnsured

func (r *Instance) IsEnsured() bool

IsEnsured returns true if the instance has been fetched/created.

func (*Instance) Log

func (r *Instance) Log(ctx context.Context, opts ...Option) error

Log streams the instance console log to the outputHandler.

func (*Instance) MarkDelete

func (r *Instance) MarkDelete()

MarkDelete marks a instance to be deleted after Ensure(), this is for down scaling instances.

func (*Instance) PushFiles

func (r *Instance) PushFiles(ctx context.Context) error

PushFiles pushes files into the instance.

func (*Instance) PushSecrets

func (r *Instance) PushSecrets(ctx context.Context) error

PushSecrets pushes secrets into the running instance. Secrets are only pushed if they don't already exist with the same content.

func (*Instance) Running

func (r *Instance) Running() bool

Running returns true if the instance is running.

func (*Instance) ServiceName

func (r *Instance) ServiceName() string

ServiceName returns the compose service name by stripping the trailing "-{index}" from the instance name ("database-1" -> "database").

func (*Instance) Start

func (r *Instance) Start(ctx context.Context, opts ...Option) error

Start starts the instance.

func (*Instance) Stop

func (r *Instance) Stop(ctx context.Context, opts ...Option) error

Stop stops the instance.

func (*Instance) String

func (r *Instance) String() string

String is for debugging.

func (*Instance) WaitIPs

func (r *Instance) WaitIPs(ctx context.Context, timeout time.Duration) (ips []InterfaceIPs, err error)

WaitIPs polls the instance state until it reports at least one global address or the timeout elapses. A freshly started container may not have its DHCP lease yet, so this gives it time. On timeout it returns whatever was found (possibly empty).

type InstanceConfig

type InstanceConfig struct {
	// ServiceName represents the compose service name.
	ServiceName string

	// Type is the instance type (container or VM).
	Type incusApi.InstanceType

	// Full fetches the full instance.
	Full bool

	// Image is the OCI image to create the instance from.
	Image string

	// Ensured Resources that this instance depends on.
	Resources []Resource

	// Devices are devices attached before instance creation (networks, proxies).
	Devices []InstanceDevice

	// PostStartDevices are devices attached after the instance is started.
	// Use for devices that require a running instance, e.g. NAT proxy (needs container IP).
	PostStartDevices []InstanceDevice

	// Secrets are files pushed into the instance after start.
	Secrets []InstanceSecret

	// Files are files pushed into the instance after creation.
	// Map key is the target path in the instance.
	Files map[string]InstanceFile

	// Extensions contains Incus instance configuration options.
	Extensions map[string]string

	// ExtraDevices contains additional raw device configurations.
	ExtraDevices map[string]map[string]string

	// Dependencies maps dependency Incus instance names to the required health
	// status (HealthStatusHealthy, HealthStatusStarting, HealthStatusUnhealthy).
	// Instance.Start() blocks until all dependencies reach the required status.
	Dependencies map[string]string

	// Priority if set sets the instance priority to this instead PriorityInstance.
	Priority int
}

InstanceConfig configures instance creation.

func (*InstanceConfig) GetConfig

func (c *InstanceConfig) GetConfig() any

GetConfig returns the configuration.

type InstanceDevice

type InstanceDevice struct {
	// Name is the device name.
	Name string

	// Config holds the device configuration.
	Config InstanceDeviceConfig
}

InstanceDevice represents an instance device configuration.

func (*InstanceDevice) ToIncusDevice

func (d *InstanceDevice) ToIncusDevice() (string, map[string]string, *Error)

ToIncusDevice converts the device to Incus API format. Returns the device name and configuration map.

type InstanceDeviceConfig

type InstanceDeviceConfig struct {
	// DeviceType identifies the device type (nic, disk, proxy, tmpfs).
	DeviceType string

	// Network is the network resource for nic devices (compose-managed).
	Network Resource

	// NetworkName is a raw Incus network name for nic devices that reference an
	// existing bridge directly, without a compose-managed Resource.
	// Only one of Network or NetworkName should be set.
	NetworkName string

	// Ipv4Address assigns a static IPv4 address to the NIC via the bridge DHCP server.
	Ipv4Address string

	// Ipv6Address assigns a static IPv6 address to the NIC via the bridge DHCP server.
	Ipv6Address string

	// Proxy contains proxy device configuration.
	Proxy InstanceDeviceProxyConfig

	// Disk contains disk device configuration.
	Disk InstanceDeviceDiskConfig

	// Tmpfs contains tmpfs device configuration.
	Tmpfs InstanceDeviceTmpfsConfig

	ExtraConfig map[string]string
}

InstanceDeviceConfig configures an instance device.

type InstanceDeviceDiskConfig

type InstanceDeviceDiskConfig struct {
	StorageVolumeConfig *StorageVolumeConfig

	// Source is the volume name or host path.
	Source string

	// Path is the mount point inside the instance.
	Path string

	// Shift enables UID/GID shifting for the mount.
	Shift bool

	// ReadOnly makes the mount read-only.
	ReadOnly bool
}

InstanceDeviceDiskConfig configures a disk device (volume or bind mount).

type InstanceDeviceProxyConfig

type InstanceDeviceProxyConfig struct {
	// ListenType is the protocol type for the listen side (e.g., "tcp").
	ListenType string

	// ListenAddr is the address to listen on.
	ListenAddr string

	// ListenPort is the port to listen on.
	ListenPort uint32

	// ConnectType is the protocol type for the connect side (e.g., "tcp").
	ConnectType string

	// ConnectAddr is the address to connect to.
	ConnectAddr string

	// ConnectPort is the port to connect to.
	ConnectPort uint32

	// Nat enables NAT mode for the proxy.
	Nat bool
}

InstanceDeviceProxyConfig configures a proxy device for port forwarding.

type InstanceDeviceTmpfsConfig

type InstanceDeviceTmpfsConfig struct {
	// Path is the mount point inside the instance.
	Path string

	// Size is the optional size limit in bytes.
	Size string
}

InstanceDeviceTmpfsConfig configures a tmpfs device.

type InstanceFile

type InstanceFile struct {
	// Give either "File" or "Content"
	File    string
	Content io.ReadSeekCloser

	UID     int64
	GID     int64
	Mode    int
	NoMKDir bool
	DirMode int
}

InstanceFile represents a file to push to an instance after creation.

type InstanceSecret

type InstanceSecret struct {
	Source  string // secret name
	Target  string // path in container (default: /run/secrets/{source})
	Content []byte // file content
	UID     int64
	GID     int64
	Mode    int // default: 0400
}

InstanceSecret represents a secret to be pushed into the instance.

type InterfaceIPs

type InterfaceIPs struct {
	Network string
	IPv4s   []string
	IPv6s   []string
}

InterfaceIPs represents interface ips.

type Kind

type Kind string

Kind identifies a resource type.

const (
	KindProject       Kind = "project"
	KindProfile       Kind = "profile"
	KindImage         Kind = "image"
	KindStorageVolume Kind = "storage-volume"
	KindNetwork       Kind = "network"
	KindInstance      Kind = "instance"
)

Resource kind identifiers.

type LogAble

type LogAble interface {
	Log(ctx context.Context, opts ...Option) error
}

LogAble is implemented by resources that can stream logs.

type Network

type Network struct {
	*BaseResource

	Config NetworkConfig

	// State - nil means not ensured.
	IncusNetwork *incusApi.Network
	ETag         string
	// contains filtered or unexported fields
}

Network represents an Incus bridge network.

func (*Network) Created

func (r *Network) Created() bool

Created returns true if the network was created during the last Ensure call.

func (*Network) Delete

func (r *Network) Delete(ctx context.Context, opts ...Option) error

Delete removes the network from Incus. External networks are never deleted.

func (*Network) Ensure

func (r *Network) Ensure(ctx context.Context, opts ...Option) error

Ensure retrieves an existing network or creates a new one if args.Create is true.

func (*Network) IncusName

func (r *Network) IncusName() string

IncusName returns the sanitized network name used in Incus.

func (*Network) IsEnsured

func (r *Network) IsEnsured() bool

IsEnsured returns true if the network state has been fetched from Incus.

func (*Network) String

func (r *Network) String() string

String is for debugging.

func (*Network) UpdateDNSAliases

func (r *Network) UpdateDNSAliases(ownedServices []string, newIPs map[string][]string) error

UpdateDNSAliases reads raw.dnsmasq from Incus, replaces records for ownedServices with newIPs (preserving all other records), and writes back. Setting raw.dnsmasq disables AppArmor for the dnsmasq process (not containers). The update is idempotent: if the resulting config is unchanged, dnsmasq is not restarted.

type NetworkConfig

type NetworkConfig struct {
	// Type is the network type (default: "bridge").
	Type string

	// External marks the network as externally managed.
	// External networks must already exist and won't be created or deleted.
	External bool

	// Extensions are Incus network config key-value pairs sourced from the
	// x-incus compose extension. All entries pass through verbatim to the
	// Incus network config on creation.
	Extensions map[string]string

	// OverrideName is the x-incus-compose.network override. For external networks
	// it is probed raw then sanitized before falling back to the compose name.
	OverrideName string
}

NetworkConfig configures network creation.

func (*NetworkConfig) GetConfig

func (c *NetworkConfig) GetConfig() any

GetConfig returns the configuration.

type Option

type Option func(o *Options)

Option configures action arguments.

func OptionBuild

func OptionBuild(info BuildInfo) Option

OptionBuild sets the build info for build-configured images (for ActionEnsure).

func OptionCreate

func OptionCreate() Option

OptionCreate creates resources if they don't exist (for ActionEnsure).

func OptionDependencyTimeout

func OptionDependencyTimeout(t time.Duration) Option

OptionDependencyTimeout sets the max time to wait for dependency health checks. Falls back to OptionTimeout when zero.

func OptionFollow

func OptionFollow() Option

OptionFollow enables continuous streaming (for ActionLog).

func OptionForce

func OptionForce() Option

OptionForce forces deletion/stop even if resource is in use.

func OptionNoHealthd

func OptionNoHealthd() Option

OptionNoHealthd indicates that we dont use healthd features.

func OptionOutput

func OptionOutput(stdout io.Writer, stderr io.Writer) Option

OptionOutput sets the stdout/stderr to use for all output.

func OptionPull

func OptionPull() Option

OptionPull forces cached images to refresh from their source registry (for ActionEnsure).

func OptionTimeout

func OptionTimeout(t time.Duration) Option

OptionTimeout sets the timeout for actions.

type Options

type Options struct {
	// Stdout / Stderr to use for all output.
	Stdout io.Writer
	Stderr io.Writer

	// Create resources if they don't exist (for ActionEnsure).
	Create bool

	// Force deletion/stop even if resource is in use.
	Force bool

	// Timeout for actions (0 = default).
	Timeout time.Duration

	// DependencyTimeout is the max time to wait for dependency health checks.
	// Falls back to Timeout when zero.
	DependencyTimeout time.Duration

	// Follow enables continuous streaming (for ActionLog).
	Follow bool

	// Pull forces cached images to refresh from their source registry (for ActionEnsure).
	Pull bool

	// Build controls rebuild behaviour for build-configured images (for ActionEnsure).
	Build BuildInfo

	// Healthd indicates that we use healthd features.
	Healthd bool
}

Options holds arguments for resource actions.

func NewOptions

func NewOptions(opts ...Option) Options

NewOptions makes a ActionArgs struct from ActionO* options.

type PoolRunArgs

type PoolRunArgs struct {
	// FailFast stops processing on first error (default: true).
	FailFast bool
}

PoolRunArgs contains options for WorkerPool.Run.

type Profile

type Profile struct {
	*BaseResource

	Config ProfileConfig

	// State - nil means not ensured.
	IncusProfile *incusApi.Profile
	ETag         string
	// contains filtered or unexported fields
}

Profile represents an Incus profile resource.

func (*Profile) Created

func (r *Profile) Created() bool

Created returns true if the profile was created during the last Ensure call.

func (*Profile) Delete

func (r *Profile) Delete(ctx context.Context, opts ...Option) error

Delete removes the profile from Incus.

func (*Profile) Ensure

func (r *Profile) Ensure(ctx context.Context, opts ...Option) error

Ensure retrieves an existing resource or creates a new one if args.Create is true.

func (*Profile) HasDevice

func (r *Profile) HasDevice(name string) bool

HasDevice returns true if the profile has a device with the given name.

func (*Profile) IncusName

func (r *Profile) IncusName() string

IncusName returns the sanitized profile name used in Incus.

func (*Profile) IsEnsured

func (r *Profile) IsEnsured() bool

IsEnsured returns true if the profile state has been fetched from Incus.

func (*Profile) String

func (r *Profile) String() string

String is for debugging.

type ProfileConfig

type ProfileConfig struct {
	// SourceServer is the Incus server to copy the profile from.
	// If nil, uses the global Incus client.
	SourceServer *incusClient.ProtocolIncus

	// SourceProject is the project containing the source profile.
	SourceProject string

	// SourceProfile is the name of the profile to copy from.
	SourceProfile string

	// NetworkOnly copies only NIC devices from the source profile.
	NetworkOnly bool
}

ProfileConfig configures profile creation from a source profile.

func (*ProfileConfig) GetConfig

func (c *ProfileConfig) GetConfig() any

GetConfig returns the configuration.

type Progress

type Progress struct {
	// Percent is 0-100, or -1 when the operation reports no percentage.
	Percent int

	// Text is the raw status text from Incus, empty when none was reported.
	Text string
}

Progress describes the live state of a long-running resource operation.

Native Incus images report a real percentage ("rootfs: 42% (3.10MB/s)"), so Percent is set. OCI image pulls only emit status text ("Retrieving OCI image from registry"); for those Percent is -1 and only Text is meaningful, because the registry download runs as an opaque skopeo subprocess with no byte or percentage feedback.

type Resource

type Resource interface {
	// Kind returns the resource type identifier (e.g., "instance", "network").
	Kind() Kind

	// Name returns the user-facing resource name.
	Name() string

	// IncusName returns the sanitized name for incus.
	IncusName() string

	// Priority returns the creation/deletion priority for dependency ordering.
	// Lower values are created first and deleted last.
	Priority() int

	// IsEnsured returns wherever the resource has been ensured.
	IsEnsured() bool

	// Created returns true if the resource was created during the last Ensure call.
	// Returns false if the resource already existed or hasn't been ensured yet.
	Created() bool
}

Resource defines the common interface for all Incus resources.

type ResourceStore

type ResourceStore struct {
	// contains filtered or unexported fields
}

ResourceStore provides storage for any BasicResource type.

func (*ResourceStore) Add

func (s *ResourceStore) Add(r Resource)

Add appends a resource to the store.

func (*ResourceStore) All

func (s *ResourceStore) All() []Resource

All returns all resources.

func (*ResourceStore) Get

func (s *ResourceStore) Get(kind Kind, incusName string) Resource

Get retrieves a resource by kind and its Incus-normalized name. Returns nil if not found.

func (*ResourceStore) Remove

func (s *ResourceStore) Remove(r Resource)

Remove removes a resource from the store by kind and name.

type Stack

type Stack struct {
	// contains filtered or unexported fields
}

Stack manages a collection of resource operations. Resources are executed in priority order with proper dependency handling.

func NewStack

func NewStack(c *Client, opts ...StackOption) *Stack

NewStack creates a new Stack for the given project.

func (*Stack) Add

func (s *Stack) Add(resources ...Resource) *Stack

Add appends resources to the stack, skipping nil and already-added pointers. Since Client.Resource() deduplicates by IncusName, pointer identity is the right key: the same resource object must not run twice in parallel.

func (*Stack) All

func (s *Stack) All() []Resource

All returns all tasks in the stack.

func (*Stack) ForAction

func (s *Stack) ForAction(action Action) *Stack

ForAction returns a new stack with resources filtered for the given action.

func (*Stack) ForActionF

func (s *Stack) ForActionF(action Action, filter func(r Resource) bool) *Stack

ForActionF returns a new stack with resources filtered for the given action, it allows custom filtering with the filter hook.

func (*Stack) Run

func (s *Stack) Run(ctx context.Context, action Action, stdout io.Writer, stderr io.Writer, opts ...Option) error

Run executes all tasks in priority order. Returns aggregated errors from all failed operations.

Image tasks are executed in parallel using a worker pool. All other tasks are executed sequentially to respect potential dependencies.

func (*Stack) Sort

func (s *Stack) Sort(desc bool)

Sort sets the sort order.

type StackOption

type StackOption func(*StackOptions)

StackOption configures stack options.

func StackSortDescending

func StackSortDescending() StackOption

StackSortDescending sorts resources in descending priority order.

func StackWorkers

func StackWorkers(w int) StackOption

StackWorkers sets the number of parallel workers.

type StackOptions

type StackOptions struct {
	Workers        int
	SortDescending bool
}

StackOptions configures stack execution.

type StackRunArgs

type StackRunArgs struct {
	Options

	// Workers is the number of parallel workers per batch (default: 4).
	Workers int
}

StackRunArgs holds arguments for Stack.Run().

type StartAble

type StartAble interface {
	Start(ctx context.Context, opts ...Option) error
}

StartAble is implemented by resources that can be started.

type StopAble

type StopAble interface {
	Stop(ctx context.Context, opts ...Option) error
}

StopAble is implemented by resources that can be stopped.

type StorageVolume

type StorageVolume struct {
	*BaseResource

	Config StorageVolumeConfig

	// State - nil means not ensured.
	IncusVolume *incusApi.StorageVolume
	ETag        string
	// contains filtered or unexported fields
}

StorageVolume represents a custom storage volume with optional UID/GID shifting. Storage volumes provide persistent storage that can be attached to instances.

func (*StorageVolume) Created

func (r *StorageVolume) Created() bool

Created returns true if the volume was created during the last Ensure call.

func (*StorageVolume) Delete

func (r *StorageVolume) Delete(ctx context.Context, opts ...Option) error

Delete removes the storage volume from Incus.

func (*StorageVolume) Ensure

func (r *StorageVolume) Ensure(ctx context.Context, opts ...Option) error

Ensure retrieves an existing storage volume or creates a new one if Create option is set.

func (*StorageVolume) IncusName

func (r *StorageVolume) IncusName() string

IncusName returns the prefixed volume name used in Incus.

func (*StorageVolume) IsEnsured

func (r *StorageVolume) IsEnsured() bool

IsEnsured returns true if the volume has been fetched/created.

func (*StorageVolume) Start

func (r *StorageVolume) Start(_ context.Context, _ ...Option) error

Start validates the storage volume.

func (*StorageVolume) String

func (r *StorageVolume) String() string

String is for debugging.

type StorageVolumeConfig

type StorageVolumeConfig struct {
	// Pool is the storage pool to create the volume in.
	// Defaults to ClientProject.Config.DefaultStoragePool.
	Pool string

	// Shifted enables UID/GID shifting for the volume.
	Shifted bool

	// UID/GID for shifting ImageResource will overwrite this if given.
	UID uint64
	GID uint64

	// ImageResource to take UID/GID from for shifting, only
	// needed if shifting is true.
	ImageResource Resource

	// HostPath, when set, seeds the volume with the local directory contents on first creation.
	HostPath string

	// Extensions contains additional volume configuration options.
	Extensions map[string]string
}

StorageVolumeConfig configures storage volume creation.

func (*StorageVolumeConfig) GetConfig

func (c *StorageVolumeConfig) GetConfig() any

GetConfig returns the configuration.

type WorkerPool

type WorkerPool struct {
	// contains filtered or unexported fields
}

WorkerPool executes tasks concurrently with a limited number of workers.

func NewWorkerPool

func NewWorkerPool(workers int) *WorkerPool

NewWorkerPool creates a new WorkerPool with the specified number of workers.

func (*WorkerPool) Run

func (p *WorkerPool) Run(args PoolRunArgs) error

Run executes all submitted tasks using the worker pool. Returns aggregated errors from all failed tasks.

func (*WorkerPool) Submit

func (p *WorkerPool) Submit(fn func() error)

Submit adds a task to the pool.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL