Documentation
¶
Overview ¶
Package docker provides Docker lifecycle orchestration for StageFreight. The Compose backend uses docker compose as the execution engine. This is Docker lifecycle orchestration, not a docker-compose wrapper.
Index ¶
- func AllowDestructiveOrphanAction(trust DiscoveryTrust, knownCount, runningCount, orphanCount, threshold int) (bool, string)
- func ComputeBundleHash(stack StackInfo, rootDir string, secrets SecretsProvider) string
- func RenderPlan(w io.Writer, plan *runtime.LifecyclePlan, elapsed time.Duration, color bool)
- func RenderResult(w io.Writer, plan *runtime.LifecyclePlan, result *runtime.LifecycleResult, ...)
- func SaveHashStamps(rootDir string, stamps *HashStamps) error
- type ActionDetail
- type AnomalyEntry
- type AnsibleInventory
- type ComposeBackend
- func (c *ComposeBackend) Capabilities() []runtime.Capability
- func (c *ComposeBackend) Cleanup(rctx *runtime.RuntimeContext)
- func (c *ComposeBackend) Execute(ctx context.Context, plan *runtime.LifecyclePlan, rctx *runtime.RuntimeContext) (*runtime.LifecycleResult, error)
- func (c *ComposeBackend) Name() string
- func (c *ComposeBackend) Plan(ctx context.Context, cfg *config.Config, rctx *runtime.RuntimeContext) (*runtime.LifecyclePlan, error)
- func (c *ComposeBackend) Prepare(ctx context.Context, cfg *config.Config, rctx *runtime.RuntimeContext) error
- func (c *ComposeBackend) Validate(ctx context.Context, cfg *config.Config, rctx *runtime.RuntimeContext) error
- type DeployResult
- type DiscoveryTrust
- type DockerPlanMeta
- type DriftDetail
- type DriftPolicy
- type DriftResult
- type EnvFile
- type ExecResult
- type HashStamps
- type Hook
- type HostTarget
- type HostTransport
- type InventorySource
- type LocalTransport
- func (l *LocalTransport) Close() error
- func (l *LocalTransport) ExecuteAction(ctx context.Context, action StackAction) (ExecResult, error)
- func (l *LocalTransport) InspectStack(ctx context.Context, project string) (StackInspection, error)
- func (l *LocalTransport) ListProjects(ctx context.Context) ([]string, error)
- type OrphanPlan
- type PlanOutput
- type PlanSummary
- type SOPSProvider
- type SSHTransport
- func (s *SSHTransport) Close() error
- func (s *SSHTransport) ExecuteAction(ctx context.Context, action StackAction) (ExecResult, error)
- func (s *SSHTransport) InspectStack(ctx context.Context, project string) (StackInspection, error)
- func (s *SSHTransport) ListProjects(ctx context.Context) ([]string, error)
- type SecretsProvider
- type ServiceRuntimeState
- type StackAction
- type StackInfo
- type StackInspection
- type StackPlan
- type StackStamp
- type TargetPlan
- type TargetSelector
- type TrustChecks
- type TrustFailureReason
- type TrustLevel
- type TrustOutput
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AllowDestructiveOrphanAction ¶
func AllowDestructiveOrphanAction(trust DiscoveryTrust, knownCount, runningCount, orphanCount, threshold int) (bool, string)
AllowDestructiveOrphanAction checks if the trust level and anomaly guards permit destructive orphan actions (down/prune).
func ComputeBundleHash ¶
func ComputeBundleHash(stack StackInfo, rootDir string, secrets SecretsProvider) string
ComputeBundleHash computes a deterministic SHA256 hash of a stack's rendered desired state. SOPS-encrypted files are decrypted in-memory before hashing — never persisted. Env files are normalized (sorted keys, trimmed whitespace, normalized line endings) for deterministic drift detection. Files are sorted before hashing.
Pipeline: IaC → [SOPS decrypt] → normalize → hash → discard
func RenderPlan ¶
RenderPlan renders a Docker lifecycle plan to the writer. Shows all stacks with drift status, grouped by scope.
func RenderResult ¶
func RenderResult(w io.Writer, plan *runtime.LifecyclePlan, result *runtime.LifecycleResult, elapsed time.Duration, color bool)
RenderResult renders the execution outcome.
func SaveHashStamps ¶
func SaveHashStamps(rootDir string, stamps *HashStamps) error
SaveHashStamps writes the hash stamps to .stagefreight-state.yml.
Types ¶
type ActionDetail ¶
type ActionDetail struct {
Requested string `json:"requested"`
Effective string `json:"effective"`
Allowed bool `json:"allowed"`
BlockedReason string `json:"blocked_reason,omitempty"`
}
ActionDetail shows requested vs effective action.
type AnomalyEntry ¶
type AnomalyEntry struct {
Type string `json:"type"`
Severity string `json:"severity"`
Message string `json:"message"`
}
AnomalyEntry represents a detected anomaly on a target.
type AnsibleInventory ¶
type AnsibleInventory struct {
Path string
}
AnsibleInventory implements InventorySource by parsing Ansible inventory files. Supports YAML and INI formats. Resolves hosts by group membership. DD-UI proven patterns carried forward.
func (*AnsibleInventory) Name ¶
func (a *AnsibleInventory) Name() string
func (*AnsibleInventory) Resolve ¶
func (a *AnsibleInventory) Resolve(_ context.Context, selector TargetSelector) ([]HostTarget, error)
Resolve parses the inventory and returns hosts matching the selector's groups.
type ComposeBackend ¶
type ComposeBackend struct {
// contains filtered or unexported fields
}
ComposeBackend implements runtime.LifecycleBackend for Docker lifecycle orchestration using docker compose as the execution engine.
func (*ComposeBackend) Capabilities ¶
func (c *ComposeBackend) Capabilities() []runtime.Capability
func (*ComposeBackend) Cleanup ¶
func (c *ComposeBackend) Cleanup(rctx *runtime.RuntimeContext)
Cleanup closes transports and removes staged secrets.
func (*ComposeBackend) Execute ¶
func (c *ComposeBackend) Execute(ctx context.Context, plan *runtime.LifecyclePlan, rctx *runtime.RuntimeContext) (*runtime.LifecycleResult, error)
Execute consumes the plan — applies only actions marked "up". Does NOT rediscover state. Plan decides; execute applies. Idempotent: no drifted actions → no mutations.
func (*ComposeBackend) Name ¶
func (c *ComposeBackend) Name() string
func (*ComposeBackend) Plan ¶
func (c *ComposeBackend) Plan(ctx context.Context, cfg *config.Config, rctx *runtime.RuntimeContext) (*runtime.LifecyclePlan, error)
Plan scans IaC, computes drift for each stack on each target. Deterministic: identical config + inputs → identical output.
func (*ComposeBackend) Prepare ¶
func (c *ComposeBackend) Prepare(ctx context.Context, cfg *config.Config, rctx *runtime.RuntimeContext) error
Prepare resolves targets from inventory and establishes transports.
func (*ComposeBackend) Validate ¶
func (c *ComposeBackend) Validate(ctx context.Context, cfg *config.Config, rctx *runtime.RuntimeContext) error
Validate checks prerequisites: inventory parseable, secrets provider available, at least one target resolvable.
type DeployResult ¶
type DeployResult struct {
Host string
Stack string
Success bool
Duration time.Duration
Message string
}
DeployResult describes the outcome of deploying a single stack.
type DiscoveryTrust ¶
type DiscoveryTrust struct {
Level TrustLevel
Sentinel bool // .stagefreight.yml exists
IaCRootExists bool // expected IaC directory exists
ScanSucceeded bool // scan completed without error
RepoIdentityMatch bool // origin URL matches expected
DeclaredTargets bool // host resolution succeeded
StackCount int // stacks discovered
Reasons []TrustFailureReason // why trust failed
}
DiscoveryTrust captures whether the repo discovery is authoritative enough for destructive operations (orphan cleanup, prune). Never destroy from absence unless the source of truth is positively validated.
func EvaluateTrust ¶
func EvaluateTrust(rootDir, iacPath, expectedMode string) DiscoveryTrust
EvaluateTrust determines how authoritative the repository discovery is. Destructive actions (orphan down/prune) require TrustAuthoritative. Never destroy from absence unless the source of truth is positively validated.
func (*DiscoveryTrust) MarkDeclaredTargets ¶
func (t *DiscoveryTrust) MarkDeclaredTargets(resolved bool)
MarkDeclaredTargets records whether host target resolution succeeded.
func (*DiscoveryTrust) MarkScanResult ¶
func (t *DiscoveryTrust) MarkScanResult(succeeded bool, stackCount int)
MarkScanResult records whether the IaC scan succeeded and how many stacks were found.
type DockerPlanMeta ¶
type DockerPlanMeta struct {
Scope string
ScopeKind string
Stack string
Path string
BundleHash string
StoredHash string
DriftTier int
DeployKind string
// Signals for truthful output (not inferred from action).
DriftDetected bool // true if drift was found (independent of action taken)
DriftReason string // human-readable drift reason
IsOrphan bool // true if this is an orphaned project
RequestedAction string // what policy wanted (before trust/safety gates)
BlockedReason string // structured reason if action was degraded/blocked (empty = allowed)
}
DockerPlanMeta is the typed metadata for a Docker plan action. Internally, backends operate on this. Serialized to Metadata map for transport. Carries ALL signals needed for truthful output — no inference from action type.
func ParseDockerPlanMeta ¶
func ParseDockerPlanMeta(m map[string]string) DockerPlanMeta
ParseDockerPlanMeta deserializes from the generic transport map.
func (DockerPlanMeta) ToMetadata ¶
func (m DockerPlanMeta) ToMetadata() map[string]string
ToMetadata serializes to the generic transport map.
type DriftDetail ¶
type DriftDetail struct {
Detected bool `json:"detected"`
Kind string `json:"kind"` // tier1 | tier2 | none | unknown
Reason string `json:"reason"`
}
DriftDetail provides structured drift information.
type DriftPolicy ¶
type DriftPolicy struct {
Tier2Action string `yaml:"tier2_action"` // report | reconcile
OrphanAction string `yaml:"orphan_action"` // report | down | prune
OrphanThreshold int `yaml:"orphan_threshold"` // block if more than N orphans
PruneRequiresConfirmation bool `yaml:"prune_requires_confirmation"` // require --force for prune
}
DriftPolicy configures drift detection behavior.
func DefaultDriftPolicy ¶
func DefaultDriftPolicy() DriftPolicy
DefaultDriftPolicy returns safe defaults.
type DriftResult ¶
type DriftResult struct {
Host string
Stack string
Drifted bool
Tier int // 1 = bundle hash, 2 = container config hash
Reason string
BundleHash string // current computed hash
StoredHash string // last known hash
}
DriftResult describes the drift state of a single stack on a host.
func DetectDrift ¶
func DetectDrift(ctx context.Context, stack StackInfo, rootDir string, stamps *HashStamps, secrets SecretsProvider, transport HostTransport) DriftResult
DetectDrift computes drift state for a stack against stored hash stamps. Two-tier detection:
- Tier 1: bundle hash comparison (local, fast, no remote calls)
- Tier 2: container config hash via transport (remote, only if Tier 1 passes)
If transport is nil, Tier 2 is skipped (read-only/local mode).
type EnvFile ¶
type EnvFile struct {
Path string // relative to stack dir
FullPath string // absolute path
Encrypted bool // SOPS-encrypted (detected by naming or content)
}
EnvFile describes a discovered environment file within a stack.
type ExecResult ¶
type ExecResult struct {
Success bool
ExitCode int
Stdout string
Stderr string
Duration time.Duration
}
ExecResult is the structured outcome of a transport execution. All transports (local, SSH, future agents) return the same shape. Full stderr captured — renderer decides how to tail/truncate.
type HashStamps ¶
type HashStamps struct {
Stacks map[string]StackStamp `yaml:"stacks"` // key: "scope/stack"
}
HashStamps tracks last-known hashes for drift detection. Stored in .stagefreight-state.yml (git-tracked).
func LoadHashStamps ¶
func LoadHashStamps(rootDir string) (*HashStamps, error)
LoadHashStamps reads the .stagefreight-state.yml file. Returns empty stamps if file doesn't exist.
type HostTarget ¶
type HostTarget struct {
Name string
Address string
Groups []string // populated from inventory group membership
Vars map[string]string // host variables from inventory
Transport HostTransport // established during Prepare phase
}
HostTarget represents a resolved Docker reconciliation target.
type HostTransport ¶
type HostTransport interface {
ExecuteAction(ctx context.Context, action StackAction) (ExecResult, error)
// InspectStack queries runtime state for a compose project.
// Read-only. Returns structured runtime facts, not CLI output.
// Selects containers by Compose project label, not name.
InspectStack(ctx context.Context, project string) (StackInspection, error)
// ListProjects returns all compose project names running on this host.
// Uses -a to include stopped containers (stopped = still logically exists).
ListProjects(ctx context.Context) ([]string, error)
Close() error
}
HostTransport executes typed stack actions on a target host. Transport compiles the intent to whatever execution form it needs. It does NOT know compose lifecycle semantics — it executes steps.
func ResolveTransport ¶
func ResolveTransport(target HostTarget) HostTransport
ResolveTransport creates the appropriate transport for a host target.
type InventorySource ¶
type InventorySource interface {
Name() string
Resolve(ctx context.Context, selector TargetSelector) ([]HostTarget, error)
}
InventorySource resolves candidate hosts from an external source. Adapter boundary: no source-specific concepts (Ansible, etc.) leak past this.
type LocalTransport ¶
type LocalTransport struct{}
LocalTransport executes stack actions directly on the local host. Compiles StackAction → local exec commands.
func (*LocalTransport) Close ¶
func (l *LocalTransport) Close() error
func (*LocalTransport) ExecuteAction ¶
func (l *LocalTransport) ExecuteAction(ctx context.Context, action StackAction) (ExecResult, error)
func (*LocalTransport) InspectStack ¶
func (l *LocalTransport) InspectStack(ctx context.Context, project string) (StackInspection, error)
InspectStack queries running containers for a compose project by label. Thin: lists container IDs, delegates parsing to inspect.go.
func (*LocalTransport) ListProjects ¶
func (l *LocalTransport) ListProjects(ctx context.Context) ([]string, error)
ListProjects returns all compose project names on the local host.
type OrphanPlan ¶
type OrphanPlan struct {
Project string `json:"project"`
Scope string `json:"scope"`
Reason string `json:"reason"`
Action ActionDetail `json:"action"`
}
OrphanPlan represents a running project with no IaC declaration.
type PlanOutput ¶
type PlanOutput struct {
Mode string `json:"mode"`
Backend string `json:"backend"`
Generated time.Time `json:"generated_at"`
Summary PlanSummary `json:"summary"`
Trust TrustOutput `json:"trust"`
Targets []TargetPlan `json:"targets"`
}
PlanOutput is the stable external schema for Docker lifecycle plan data. Designed for DD-UI consumption, CI artifacts, and --output json. Backend decides; frontend renders. No frontend guesswork.
func BuildPlanOutput ¶
func BuildPlanOutput(plan *runtime.LifecyclePlan, trust DiscoveryTrust, targets []HostTarget) PlanOutput
BuildPlanOutput converts internal plan + trust into the stable external schema. Uses DockerPlanMeta signals directly — no inference from action type.
func (PlanOutput) JSON ¶
func (p PlanOutput) JSON() ([]byte, error)
JSON produces the stable JSON output.
type PlanSummary ¶
type PlanSummary struct {
Total int `json:"total"`
Drifted int `json:"drifted"`
Orphans int `json:"orphans"`
Blocked int `json:"blocked"`
Actions map[string]int `json:"actions"`
}
PlanSummary provides top-level counts.
type SOPSProvider ¶
type SOPSProvider struct{}
SOPSProvider implements SecretsProvider using the sops CLI.
func (*SOPSProvider) IsEncrypted ¶
func (s *SOPSProvider) IsEncrypted(path string) bool
IsEncrypted checks if a file path matches SOPS naming conventions.
func (*SOPSProvider) Name ¶
func (s *SOPSProvider) Name() string
type SSHTransport ¶
SSHTransport executes stack actions on a remote host via SSH. Copies bundle to remote tmpdir, executes, cleans up.
func (*SSHTransport) Close ¶
func (s *SSHTransport) Close() error
func (*SSHTransport) ExecuteAction ¶
func (s *SSHTransport) ExecuteAction(ctx context.Context, action StackAction) (ExecResult, error)
func (*SSHTransport) InspectStack ¶
func (s *SSHTransport) InspectStack(ctx context.Context, project string) (StackInspection, error)
InspectStack queries running containers for a compose project on the remote host. Thin: lists container IDs via SSH, delegates parsing to inspect.go.
func (*SSHTransport) ListProjects ¶
func (s *SSHTransport) ListProjects(ctx context.Context) ([]string, error)
ListProjects returns all compose project names on the remote host.
type SecretsProvider ¶
type SecretsProvider interface {
Name() string
Decrypt(ctx context.Context, path string) ([]byte, error)
Encrypt(ctx context.Context, path string, data []byte) error
IsEncrypted(path string) bool
}
SecretsProvider handles encryption/decryption for stack secret files. SOPS today, Vault/Infisical later.
func ResolveSecretsProvider ¶
func ResolveSecretsProvider(name string) (SecretsProvider, error)
ResolveSecretsProvider returns the appropriate provider by name.
type ServiceRuntimeState ¶
type ServiceRuntimeState struct {
Service string
ConfigHash string // com.docker.compose.config-hash label
Image string
Running bool
State string // running, exited, dead, etc.
ContainerID string
}
ServiceRuntimeState is the canonical runtime state of a single compose service. Primary Tier 2 signal: ConfigHash.
type StackAction ¶
type StackAction struct {
Target string // host identity
Stack string // scope/name
Action string // "up", "down", "restart"
ProjectName string // docker compose -p flag
WorkDir string // working directory (relative to bundle or host-resolved)
// Staged bundle: transport decides how to materialize this.
// SSH copies it to remote tmpdir. Agent receives it as payload.
BundleDir string // local staging root containing all needed files
// Compose file and env files — relative to BundleDir.
ComposeFile string // e.g. "compose.yaml"
EnvFiles []string // e.g. [".env", "app_secret.env"]
// Hooks as ordered execution steps, not raw paths.
Hooks []Hook
}
StackAction is a typed execution intent for the transport layer. Represents WHAT to execute, not HOW today's transport executes it. Transport receives this, compiles it to whatever form it needs. No absolute paths, no filesystem assumptions, no transport coupling.
type StackInfo ¶
type StackInfo struct {
Scope string // host name or group name
ScopeKind string // "host" or "group"
Name string // stack directory name
Path string // relative path from repo root
ComposeFile string // detected compose filename
ComposeProject string // canonical compose project name (for container identity)
EnvFiles []EnvFile
Scripts []string // pre.sh, deploy.sh, post.sh
DeployKind string // "compose", "script", "unmanaged"
}
StackInfo describes a discovered IaC stack.
type StackInspection ¶
type StackInspection struct {
Project string
Services []ServiceRuntimeState
}
StackInspection is the canonical runtime state of a compose project. Reduced model — only the signals needed for drift detection.
type StackPlan ¶
type StackPlan struct {
Name string `json:"name"`
Project string `json:"project"`
Scope string `json:"scope"`
Status string `json:"status"` // in_sync | drift | blocked | unknown
Drift DriftDetail `json:"drift"`
Action ActionDetail `json:"action"`
}
StackPlan is the resolved state of a declared stack.
type StackStamp ¶
type StackStamp struct {
BundleHash string `yaml:"bundle_hash"`
ConfigHash string `yaml:"config_hash"` // runtime compose config hash from last apply
DeployedAt time.Time `yaml:"deployed_at"`
}
StackStamp records the hash state of a stack after successful deployment.
type TargetPlan ¶
type TargetPlan struct {
Name string `json:"name"`
Transport string `json:"transport"`
Stacks []StackPlan `json:"stacks"`
Orphans []OrphanPlan `json:"orphans,omitempty"`
Anomalies []AnomalyEntry `json:"anomalies,omitempty"`
}
TargetPlan groups stacks and orphans per host.
type TargetSelector ¶
type TargetSelector struct {
Groups []string `yaml:"groups"`
}
TargetSelector declares which hosts are eligible for reconciliation. Group-based initially (existing Ansible groups). Extensible later only if groups become insufficient.
type TrustChecks ¶
type TrustChecks struct {
Sentinel bool `json:"sentinel"`
IaCRoot bool `json:"iac_root"`
Scan bool `json:"scan"`
RepoIdentity bool `json:"repo_identity"`
DeclaredTargets bool `json:"declared_targets"`
}
TrustChecks shows individual trust gate results.
type TrustFailureReason ¶
type TrustFailureReason string
TrustFailureReason is a typed, machine-meaningful reason for trust failure.
const ( ReasonNoSentinel TrustFailureReason = "no_sentinel" ReasonIaCRootMissing TrustFailureReason = "iac_root_missing" ReasonScanFailed TrustFailureReason = "scan_failed" ReasonRepoMismatch TrustFailureReason = "repo_identity_mismatch" ReasonTargetNotDeclared TrustFailureReason = "target_not_declared" ReasonLifecycleMismatch TrustFailureReason = "lifecycle_mode_mismatch" )
type TrustLevel ¶
type TrustLevel string
TrustLevel indicates how authoritative the repository discovery is. Destructive actions require Authoritative. Uncertain → observe only.
const ( TrustNone TrustLevel = "none" TrustPartial TrustLevel = "partial" TrustAuthoritative TrustLevel = "authoritative" )
type TrustOutput ¶
type TrustOutput struct {
Level string `json:"level"`
Checks TrustChecks `json:"checks"`
Reasons []string `json:"reasons,omitempty"`
}
TrustOutput is the external representation of DiscoveryTrust.