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 ¶
- Variables
- type Action
- type AppActionResult
- type AppService
- type DeployResult
- type ImportResult
- type ImportSkip
- type Input
- type NetworkManager
- type PortConflict
- type PortRequester
- type Service
- func (s *Service) AddApp(workspaceID, stackID, appID uint) (*models.Stack, error)
- func (s *Service) AggregateStatus(stackID uint) (StatusCounts, error)
- func (s *Service) AppCount(stackID uint) (int64, error)
- func (s *Service) Create(ctx context.Context, workspaceID uint, in Input) (*models.Stack, error)
- func (s *Service) Delete(ctx context.Context, workspaceID, id uint, withApps bool) error
- func (s *Service) DeleteEnvVar(workspaceID, stackID uint, key string) error
- func (s *Service) DeployAll(workspaceID, stackID uint) ([]DeployResult, error)
- func (s *Service) Events(workspaceID, stackID uint, limit int) ([]models.AppEvent, error)
- func (s *Service) Get(workspaceID, id uint) (*models.Stack, error)
- func (s *Service) IDByUID(uid string) (uint, error)
- func (s *Service) ImportCompose(ctx context.Context, workspaceID, userID uint, name, composeYAML string) (*ImportResult, error)
- func (s *Service) ImportEnvVars(workspaceID, stackID uint, content string, isSecret bool) (int, error)
- func (s *Service) Lifecycle(ctx context.Context, workspaceID, stackID uint, action Action, rolling bool) ([]AppActionResult, error)
- func (s *Service) List(workspaceID uint) ([]models.Stack, error)
- func (s *Service) ListEnvVars(workspaceID, stackID uint) ([]models.StackEnvVar, error)
- func (s *Service) Reencrypt(ctx context.Context, workspaceID uint) (int, error)
- func (s *Service) RemoveApp(workspaceID, stackID, appID uint) (*models.Stack, error)
- func (s *Service) SetAllocator(a *netalloc.Service)
- func (s *Service) SetEnvVar(workspaceID, stackID uint, key, value string, isSecret bool) error
- func (s *Service) Update(workspaceID, id uint, in UpdateInput) (*models.Stack, error)
- type StatusCounts
- type UpdateInput
- type VolumeCreator
Constants ¶
This section is empty.
Variables ¶
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") )
var ErrComposeInvalid = errors.New("invalid docker-compose content")
Functions ¶
This section is empty.
Types ¶
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 ¶
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 NewService ¶
func NewService(repo *repositories.StackRepository, apps *repositories.ApplicationRepository, env *repositories.StackEnvVarRepository, events *repositories.AppEventRepository, app AppService, volumes VolumeCreator, docker NetworkManager, ports PortRequester) *Service
func (*Service) AddApp ¶
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) Delete ¶
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 ¶
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) 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) 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 ¶
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 ¶
RemoveApp clears an application's stack assignment (no-op if it is not a member of this stack).
func (*Service) SetAllocator ¶
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).
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 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.