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.
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.