instance

package
v1.5.2 Latest Latest
Warning

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

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

Documentation

Overview

Package instance defines the Instance domain entity, lifecycle management service interface, persistence store interface, and state machine for instance state transitions.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ValidateTransition

func ValidateTransition(current, target provider.InstanceState) error

ValidateTransition checks whether moving from the current state to the target state is allowed. It returns ctrlplane.ErrInvalidState if not.

Types

type CreateRequest

type CreateRequest struct {
	Name         string                 `json:"name"                    validate:"required"`
	DatacenterID id.ID                  `json:"datacenter_id,omitzero"`
	ProviderName string                 `json:"provider_name,omitempty"`
	Region       string                 `json:"region,omitempty"`
	Kind         provider.WorkloadKind  `json:"kind,omitempty"`
	Services     []provider.ServiceSpec `json:"services,omitempty"`
	Labels       map[string]string      `json:"labels,omitempty"`

	// Source describes a non-services deployment. When empty, Services is
	// projected onto a services Source.
	Source provider.DeploymentSource `json:"source,omitzero"`

	// Variables and VariableValues are resolved against derived instance
	// context and injected into the rendered Source.
	Variables      []vars.Definition `json:"variables,omitempty"`
	VariableValues map[string]any    `json:"variable_values,omitempty"`
}

CreateRequest holds the parameters for creating a new instance.

A non-services deployment is described via Source (helm | manifests | argocd) plus optional Variables/VariableValues resolved at provision time. For backward compatibility, callers may instead populate Services alone — Create projects them onto a services Source.

type DatacenterResolver added in v1.3.0

type DatacenterResolver interface {
	// ResolveProvider returns the provider name for a given datacenter.
	ResolveProvider(ctx context.Context, datacenterID id.ID) (string, error)
}

DatacenterResolver resolves a datacenter's provider name without introducing a circular import between the instance and datacenter packages.

type Instance

type Instance struct {
	ctrlplane.Entity

	TenantID     string `db:"tenant_id"     json:"tenant_id"`
	Name         string `db:"name"          json:"name"`
	Slug         string `db:"slug"          json:"slug"`
	DatacenterID id.ID  `db:"datacenter_id" json:"datacenter_id,omitzero"`
	ProviderName string `db:"provider_name" json:"provider_name"`

	// ProviderRef is the workload-level handle (Pod name on k8s,
	// Compose project name on Docker, Allocation ID on Nomad).
	ProviderRef string `db:"provider_ref" json:"provider_ref"`

	// ServiceRefs maps a service's Name to its provider-specific
	// per-container ref (container ID on Docker, container name within
	// the Pod on k8s, Task name on Nomad). Used for per-service
	// log/exec/restart operations.
	ServiceRefs map[string]string `db:"service_refs" json:"service_refs,omitempty"`

	Region string                 `db:"region" json:"region"`
	State  provider.InstanceState `db:"state"  json:"state"`

	// Kind is inherited from the Workload at provision time and locked
	// for the instance's lifetime. Mirrors Workload.Kind so per-replica
	// teardown doesn't have to look the workload up.
	Kind provider.WorkloadKind `db:"kind" json:"kind"`

	// Services is a snapshot of the spec the replica was provisioned
	// with. Mutating Workload.Services does not retroactively change
	// running replicas — the next Deploy bumps each replica's snapshot
	// to the new Release.
	Services []provider.ServiceSpec `db:"services" json:"services"`

	// Source records what was deployed (services | helm | manifests |
	// argocd) so teardown and status route to the right provider engine.
	// Empty on legacy instances, which are treated as services.
	Source provider.DeploymentSource `db:"source" json:"source,omitzero"`

	// Endpoints is the union of every service's accessible endpoints,
	// each tagged with ServiceName.
	Endpoints []provider.Endpoint `db:"endpoints" json:"endpoints,omitempty"`

	// Labels is workload-level metadata (mirrors Workload.Labels) plus
	// the per-replica `ctrlplane.replica_index=<N>` label.
	Labels map[string]string `db:"labels" json:"labels,omitempty"`

	CurrentRelease id.ID      `db:"current_release" json:"current_release,omitzero"`
	SuspendedAt    *time.Time `db:"suspended_at"    json:"suspended_at,omitempty"`
}

Instance is one replica of a Workload — a single co-scheduling unit (k8s Pod, Nomad allocation, Docker Compose project) running every service in the workload's Services slice.

func (*Instance) MainService added in v1.5.1

func (i *Instance) MainService() *provider.ServiceSpec

MainService returns the Main service from the instance's snapshot. Convenience for callers that want "the instance's primary image" — e.g. dashboard summaries.

type ListOptions

type ListOptions struct {
	State      string `json:"state,omitempty"`
	Label      string `json:"label,omitempty"`
	Provider   string `json:"provider,omitempty"`
	Datacenter string `json:"datacenter,omitempty"`
	Cursor     string `json:"cursor,omitempty"`
	Limit      int    `json:"limit,omitempty"`
}

ListOptions configures instance listing with optional filters and pagination.

type ListResult

type ListResult struct {
	Items      []*Instance `json:"items"`
	NextCursor string      `json:"next_cursor,omitempty"`
	Total      int         `json:"total"`
}

ListResult holds a page of instances with cursor-based pagination.

type LogsOptions added in v1.5.1

type LogsOptions struct {
	ServiceName string    `json:"service_name,omitempty"`
	Follow      bool      `json:"follow"`
	Since       time.Time `json:"since,omitzero"`
	Tail        int       `json:"tail,omitempty"`
}

LogsOptions mirrors provider.LogOptions on the public Service surface so callers don't need to import the provider package.

ServiceName picks one service inside the instance — empty defaults to the Main service. Per-service log streaming lets a caller tail a sidecar without merging it into the main container's stream.

type ScaleRequest

type ScaleRequest struct {
	CPUMillis *int `json:"cpu_millis,omitempty"`
	MemoryMB  *int `json:"memory_mb,omitempty"`
	Replicas  *int `json:"replicas,omitempty"`
}

ScaleRequest holds the parameters for scaling an instance.

type Service

type Service interface {
	// Create provisions a new instance on the specified provider.
	Create(ctx context.Context, req CreateRequest) (*Instance, error)

	// Get returns an instance by ID, scoped to the tenant in context.
	Get(ctx context.Context, instanceID id.ID) (*Instance, error)

	// GetBySlug returns an instance by slug within the caller's tenant.
	// Returns ctrlplane.ErrNotFound when no row matches. Used by
	// callers (notably workload.spawnReplica) that need to check
	// whether the unique (tenant, slug) namespace is already
	// occupied before attempting an insert that would otherwise
	// trip the database unique index.
	GetBySlug(ctx context.Context, slug string) (*Instance, error)

	// List returns instances for the current tenant with filtering.
	List(ctx context.Context, opts ListOptions) (*ListResult, error)

	// Update modifies instance configuration (env, labels, resources).
	Update(ctx context.Context, instanceID id.ID, req UpdateRequest) (*Instance, error)

	// Delete deprovisions and removes an instance.
	Delete(ctx context.Context, instanceID id.ID) error

	// Start starts a stopped instance.
	Start(ctx context.Context, instanceID id.ID) error

	// Stop gracefully stops an instance.
	Stop(ctx context.Context, instanceID id.ID) error

	// Restart performs a stop+start cycle.
	Restart(ctx context.Context, instanceID id.ID) error

	// Scale adjusts resource allocation.
	Scale(ctx context.Context, instanceID id.ID, req ScaleRequest) error

	// Suspend marks an instance as suspended (billing/abuse).
	Suspend(ctx context.Context, instanceID id.ID, reason string) error

	// Unsuspend restores a suspended instance.
	Unsuspend(ctx context.Context, instanceID id.ID) error

	// Logs returns a stream of log events from the instance's
	// container/pod via the underlying provider. Caller closes the
	// returned ReadCloser to stop. opts.Follow=true keeps the
	// stream open as new lines arrive.
	Logs(ctx context.Context, instanceID id.ID, opts LogsOptions) (io.ReadCloser, error)

	// Resources returns a one-shot resource-usage sample for the
	// instance via the underlying provider (e.g., docker stats).
	// Used by the metrics package's poller. Returns a zero-valued
	// usage (no error) when the underlying container has gone away
	// — the poller treats that as a missing sample, not a failure.
	Resources(ctx context.Context, instanceID id.ID) (*provider.ResourceUsage, error)
}

Service manages instance lifecycle operations.

func NewService

func NewService(store Store, providers *provider.Registry, events event.Bus, auth auth.Provider, dcResolver DatacenterResolver) Service

NewService creates a new instance service. The dcResolver parameter is optional and may be nil when datacenters are not in use.

type Store

type Store interface {
	// Insert persists a new instance.
	Insert(ctx context.Context, inst *Instance) error

	// GetByID retrieves an instance by its ID within a tenant.
	GetByID(ctx context.Context, tenantID string, instanceID id.ID) (*Instance, error)

	// GetBySlug retrieves an instance by its slug within a tenant.
	GetBySlug(ctx context.Context, tenantID string, slug string) (*Instance, error)

	// List returns a filtered, paginated list of instances for a tenant.
	List(ctx context.Context, tenantID string, opts ListOptions) (*ListResult, error)

	// Update persists changes to an existing instance.
	Update(ctx context.Context, inst *Instance) error

	// Delete removes an instance from the store.
	Delete(ctx context.Context, tenantID string, instanceID id.ID) error

	// CountByTenant returns the total number of instances for a tenant.
	CountByTenant(ctx context.Context, tenantID string) (int, error)
}

Store is the persistence interface for instances.

type UpdateRequest

type UpdateRequest struct {
	Name     *string                `json:"name,omitempty"`
	Services []provider.ServiceSpec `json:"services,omitempty"`
	Labels   map[string]string      `json:"labels,omitempty"`
}

UpdateRequest holds the parameters for updating an instance.

Jump to

Keyboard shortcuts

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