stack

package
v1.6.3 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2026 License: AGPL-3.0 Imports: 16 Imported by: 0

Documentation

Overview

Package stack groups related applications in a workspace. A stack carries a user-facing name and a platform-managed Docker Compose project name; member containers are labeled with that project name so Docker tooling groups them. Stacks are purely organizational — deleting one detaches its apps (which keep running), it never destroys workloads.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNameRequired    = errors.New("stack name is required")
	ErrNameTaken       = errors.New("a stack with this name already exists")
	ErrNotFound        = errors.New("stack not found")
	ErrAppNotFound     = errors.New("application not found in workspace")
	ErrAppInOtherStack = errors.New("application already belongs to another stack")
	ErrInvalidAction   = errors.New("invalid stack action")
	ErrKeyRequired     = errors.New("environment variable key is required")
)
View Source
var ErrComposeInvalid = errors.New("invalid docker-compose content")

Functions

This section is empty.

Types

type Action

type Action string

Action is a stack-wide container lifecycle operation.

const (
	ActionStart   Action = "start"
	ActionStop    Action = "stop"
	ActionRestart Action = "restart"
)

type AppActionResult

type AppActionResult struct {
	AppID   uint   `json:"app_id"`
	AppName string `json:"app_name"`
	Status  string `json:"status"`
	Error   string `json:"error,omitempty"`
}

AppActionResult reports the outcome of a lifecycle action for one member app. Status is "ok" (acted), "skipped" (no active release to act on), or "failed".

type AppService

type AppService interface {
	Start(ctx context.Context, app *models.Application) (*models.Deployment, error)
	Stop(ctx context.Context, app *models.Application) error
	Restart(ctx context.Context, app *models.Application) (*models.Deployment, error)
	WaitRunning(ctx context.Context, app *models.Application) error
	Deploy(app *models.Application, registryOverride *uint, tagOverride string, strategy models.DeployStrategy) (*models.Deployment, error)
	MarkRedeployRequired(app *models.Application) (bool, error)
	Delete(ctx context.Context, app *models.Application) error
	Create(workspaceID uint, in application.CreateInput) (*models.Application, error)
	SetEnvVar(appID uint, key, value string, isSecret bool) error
	AttachVolume(app *models.Application, volumeID uint, path string) error
}

AppService is the slice of *application.Service the stack service drives: per-app container lifecycle, deploy, delete, create (for compose import), and env management. An interface keeps the stack service unit-testable with a fake.

type DeployResult

type DeployResult struct {
	AppID        uint   `json:"app_id"`
	AppName      string `json:"app_name"`
	Status       string `json:"status"` // queued | failed
	DeploymentID uint   `json:"deployment_id,omitempty"`
	Error        string `json:"error,omitempty"`
}

DeployResult reports the outcome of a deploy for one member app.

type ImportResult

type ImportResult struct {
	Stack         *models.Stack  `json:"stack"`
	Created       []string       `json:"created"`
	Volumes       []string       `json:"volumes"`
	PortRequests  int            `json:"port_requests"`
	PortConflicts []PortConflict `json:"port_conflicts"`
	Skipped       []ImportSkip   `json:"skipped"`
}

ImportResult summarizes a compose import.

type ImportSkip

type ImportSkip struct {
	Service string `json:"service"`
	Reason  string `json:"reason"`
}

ImportSkip records a service that could not be imported.

type Input

type Input struct {
	// Name is the desired unique slug handle; it is normalized to canonical slug
	// form. DisplayName is the free-text label (falls back to Name when blank).
	Name        string
	DisplayName string
	Description string
	// Metadata is the stack's initial metadata. Callers may set reserved
	// "miabi.io/" keys (provenance); a missing managed-by defaults to "user".
	Metadata models.Metadata
	// Annotations is the stack's initial annotations: free-form descriptive notes
	// with no reserved keys (the manifest's metadata.annotations).
	Annotations models.Metadata
}

type NetworkManager

type NetworkManager interface {
	EnsureNetwork(ctx context.Context, name string) (string, error)
	RemoveNetwork(ctx context.Context, name string) error
	// EnsureNetworkSpec / ListNetworks let the subnet allocator drive network
	// creation (satisfies netalloc.NetworkProvisioner).
	EnsureNetworkSpec(ctx context.Context, spec docker.NetworkSpec) (string, error)
	ListNetworks(ctx context.Context) ([]docker.Network, error)
}

NetworkManager creates/removes the Docker network that backs a stack's service-name discovery. Satisfied by docker.Client.

type PortConflict

type PortConflict struct {
	Service  string `json:"service"`
	HostPort int    `json:"host_port"`
	Protocol string `json:"protocol"`
	UsedBy   string `json:"used_by"`
}

PortConflict records a published compose port whose host port was already in use on the node at import time. The binding is still filed (pending), so the stack imports cleanly; the user can remap the port or have an admin review it.

type PortRequester

type PortRequester interface {
	Request(workspaceID, userID uint, in portbinding.RequestInput) (*models.PortBinding, error)
	// RequestImport files a binding during import, tolerating host-port conflicts
	// (filed pending) and returning the conflicting owner instead of failing.
	RequestImport(workspaceID, userID uint, in portbinding.RequestInput) (*models.PortBinding, string, error)
}

PortRequester files admin-validated host port-binding requests, used by compose import to capture published ports. Satisfied by *portbinding.Service.

type Service

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

func (*Service) AddApp

func (s *Service) AddApp(workspaceID, stackID, appID uint) (*models.Stack, error)

AddApp assigns an application (in the same workspace) to a stack. An app already in a different stack is rejected rather than silently moved.

func (*Service) AggregateStatus

func (s *Service) AggregateStatus(stackID uint) (StatusCounts, error)

AggregateStatus summarizes the statuses of a stack's member apps.

func (*Service) AppCount

func (s *Service) AppCount(stackID uint) (int64, error)

AppCount returns the number of applications in a stack.

func (*Service) Create

func (s *Service) Create(ctx context.Context, workspaceID uint, in Input) (*models.Stack, error)

func (*Service) Delete

func (s *Service) Delete(ctx context.Context, workspaceID, id uint, withApps bool) error

Delete removes a stack. By default its applications are detached and keep running; when withApps is set, the member applications (and their containers) are deleted too.

func (*Service) DeleteEnvVar

func (s *Service) DeleteEnvVar(workspaceID, stackID uint, key string) error

DeleteEnvVar removes a shared env var from the stack.

func (*Service) DeployAll

func (s *Service) DeployAll(workspaceID, stackID uint) ([]DeployResult, error)

DeployAll enqueues a deploy for every application in the stack, returning a per-app summary. Best-effort: one app's failure to enqueue doesn't stop the others.

func (*Service) Events

func (s *Service) Events(workspaceID, stackID uint, limit int) ([]models.AppEvent, error)

Events returns the combined recent activity feed across the stack's apps.

func (*Service) Get

func (s *Service) Get(workspaceID, id uint) (*models.Stack, error)

func (*Service) IDByUID

func (s *Service) IDByUID(uid string) (uint, error)

IDByUID resolves a stack's portable uid to its numeric id.

func (*Service) ImportCompose

func (s *Service) ImportCompose(ctx context.Context, workspaceID, userID uint, name, composeYAML string) (*ImportResult, error)

ImportCompose creates a stack and one application per Compose service (image-source only). Named volumes are provisioned and mounted; published host ports become pending port-binding requests (an admin approves them). Apps join the stack network and resolve each other by service name. Bind mounts and build-only services are skipped and reported.

func (*Service) ImportEnvVars

func (s *Service) ImportEnvVars(workspaceID, stackID uint, content string, isSecret bool) (int, error)

ImportEnvVars bulk-upserts shared env vars from .env-style content, encrypting them when isSecret. Returns the number set.

func (*Service) Lifecycle

func (s *Service) Lifecycle(ctx context.Context, workspaceID, stackID uint, action Action, rolling bool) ([]AppActionResult, error)

Lifecycle applies a start/stop/restart action to every application in the stack. It is best-effort: an app with no active release is skipped and one that errors is recorded as failed, but neither aborts the others — so the caller gets a full per-app summary. When rolling is set (restart only), each app is restarted and waited until it reports running before the next, so the stack is never fully down at once.

func (*Service) List

func (s *Service) List(workspaceID uint) ([]models.Stack, error)

func (*Service) ListEnvVars

func (s *Service) ListEnvVars(workspaceID, stackID uint) ([]models.StackEnvVar, error)

ListEnvVars returns the stack's shared env vars (secret values masked).

func (*Service) Reencrypt

func (s *Service) Reencrypt(ctx context.Context, workspaceID uint) (int, error)

Reencrypt re-encrypts every secret env var of the workspace's stacks under the workspace's active DEK. Non-secret vars are skipped. Idempotent.

func (*Service) RemoveApp

func (s *Service) RemoveApp(workspaceID, stackID, appID uint) (*models.Stack, error)

RemoveApp clears an application's stack assignment (no-op if it is not a member of this stack).

func (*Service) SetAllocator

func (s *Service) SetAllocator(a *netalloc.Service)

SetAllocator wires the subnet allocator so a stack's network gets a Miabi-carved subnet instead of Docker's default pool (nil-safe; nil = Docker default pool).

func (*Service) SetEnvVar

func (s *Service) SetEnvVar(workspaceID, stackID uint, key, value string, isSecret bool) error

SetEnvVar upserts a shared env var on the stack (secret values encrypted).

func (*Service) Update

func (s *Service) Update(workspaceID, id uint, in UpdateInput) (*models.Stack, error)

type StatusCounts

type StatusCounts struct {
	Total   int `json:"total"`
	Running int `json:"running"`
	Stopped int `json:"stopped"`
	Failed  int `json:"failed"`
	Other   int `json:"other"`
}

StatusCounts is an aggregate of member-app statuses for the health badge.

type UpdateInput

type UpdateInput struct {
	Name        *string
	Description *string
	// Annotations, when non-nil, replaces the stack's annotations wholesale.
	Annotations models.Metadata
}

type VolumeCreator

type VolumeCreator interface {
	Create(ctx context.Context, workspaceID, serverID uint, name string, sizeBytes int64, meta, annotations models.Metadata) (*models.Volume, error)
}

VolumeCreator provisions managed volumes, used by compose import to back the named volumes a compose file declares. Satisfied by *storage.Service.

Jump to

Keyboard shortcuts

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