advancedrollback

package
v0.46.6 Latest Latest
Warning

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

Go to latest
Published: Sep 25, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package advancedrollback runs the Advanced operation `rollback.coordinated`: it restores the OpenTofu state and payload of every local Terramate stack to one verified executor-state checkpoint, in reverse run order (ADR-0045 section 1 and section 3, docs/ARCHITECTURE.md "Coordinated rollback across stacks (Stage 1)").

The package owns the per-stack plan, its resumable journal and the `stackkit.rollback-result/v1` report. Checkpoint verification, lifecycle authority and the StackSpec restore stay with the command and internal/upgradelifecycle.

Index

Constants

View Source
const (
	// ResultSchemaVersion identifies the rollback report
	// (schemas/stackkit-rollback-result-v1.schema.json).
	ResultSchemaVersion = "stackkit.rollback-result/v1"
	// JournalSchemaVersion identifies the per-checkpoint rollback journal.
	JournalSchemaVersion = "stackkit.rollback-journal/v1"
	// JournalDir holds one journal per target checkpoint.
	JournalDir = ".stackkit/advanced/rollbacks"
)
View Source
const (
	// ActionDestroyed: the stack is absent from the checkpoint's stack graph
	// (added after it). Its root is destroyed through OpenTofu, which runs the
	// wrapper's destroy-time `docker compose down` without volumes, and then
	// removed.
	ActionDestroyed = "destroyed"
	// ActionRestored: the root exists and differs from the checkpoint. Its
	// state, configuration and payload are restored and convergence is
	// forced with `tofu apply -replace` on the wrapper trigger.
	ActionRestored = "restored"
	// ActionRecreated: the checkpoint has the root but the workspace has no
	// applied root (the stack was removed after the checkpoint). Restored
	// and forced like a restored stack.
	ActionRecreated = "recreated"
	// ActionUnchanged: the root already equals the checkpoint, or the
	// checkpoint captured no root for a stack both graphs share.
	ActionUnchanged = "unchanged"
)

Per-stack actions, decided once when the rollback is planned.

View Source
const (
	StackConverged = "converged"
	StackFailed    = "failed"
	StackPending   = "pending"
	StackSkipped   = "skipped"
)

Per-stack statuses.

View Source
const (
	StatusConverged = "converged"
	StatusFailed    = "failed"
)

Overall statuses.

View Source
const (
	SealSealed       = "sealed"
	SealUnsupported  = "unsupported"
	SealFailed       = "failed"
	SealNotAttempted = "not_attempted"
)

Seal statuses.

Variables

This section is empty.

Functions

func JournalPath

func JournalPath(snapshotID string) (string, error)

JournalPath is the workspace-relative journal of one target checkpoint.

func SaveJournal

func SaveJournal(workspaceRoot string, journal Journal) error

SaveJournal atomically replaces the journal of journal.TargetSnapshotID.

Types

type Error

type Error struct {
	Code   ErrorCode
	Stacks []string
	Detail string
	Err    error
}

Error is the structured rollback failure.

func (*Error) Error

func (e *Error) Error() string

func (*Error) Unwrap

func (e *Error) Unwrap() error

type ErrorCode

type ErrorCode string

ErrorCode classifies a failed rollback.

const (
	// ErrNotConverged: at least one stack could not be destroyed, restored
	// or proven converged.
	ErrNotConverged ErrorCode = "advanced_rollback_not_converged"
	// ErrInvalid: the rollback request or journal is inconsistent.
	ErrInvalid ErrorCode = "advanced_rollback_invalid"
)

func Reason

func Reason(err error) (ErrorCode, bool)

Reason returns the structured code of a rollback error.

type Journal

type Journal struct {
	SchemaVersion        string                `json:"schemaVersion"`
	RollbackID           string                `json:"rollbackId"`
	TargetSnapshotID     string                `json:"targetSnapshotId"`
	ChangeSetID          string                `json:"changeSetId,omitempty"`
	LifecycleOperationID string                `json:"lifecycleOperationId"`
	Status               string                `json:"status"`
	Steps                []Step                `json:"steps"`
	Results              map[string]StepResult `json:"results"`
	CreatedAt            time.Time             `json:"createdAt"`
	UpdatedAt            time.Time             `json:"updatedAt"`
}

Journal is the durable plan and progress of one rollback to one checkpoint. A second invocation for the same checkpoint resumes it and skips every step already converged.

func LoadJournal

func LoadJournal(workspaceRoot, snapshotID string) (Journal, bool, error)

LoadJournal returns the journal of the rollback to snapshotID, if any.

func Prepare

func Prepare(request Request) (Journal, bool, error)

Prepare returns the unfinished journal of the rollback to the target checkpoint (resumed), or plans a new rollback and persists its journal before any runtime side effect. The plan is computed once: a resumed rollback executes the original plan, so a stack destroyed by the first invocation is never classified again.

func (Journal) InProgress

func (journal Journal) InProgress() bool

InProgress reports whether the journal belongs to an unfinished rollback.

type Report

type Report struct {
	SchemaVersion        string        `json:"schemaVersion"`
	RollbackID           string        `json:"rollbackId"`
	TargetSnapshotID     string        `json:"targetSnapshotId"`
	ChangeSetID          string        `json:"changeSetId,omitempty"`
	LifecycleOperationID string        `json:"lifecycleOperationId,omitempty"`
	Resumed              bool          `json:"resumed"`
	Order                []string      `json:"order"`
	Stacks               []StackReport `json:"stacks"`
	// AuthorityRestored: the checkpoint's StackSpec and Inventory were
	// restored through the executor-state recovery path.
	AuthorityRestored bool `json:"authorityRestored"`
	// PriorReleaseExecuted: the checkpoint's release differs from the
	// running one, so its captured executable regenerated and verified.
	PriorReleaseExecuted bool `json:"priorReleaseExecuted"`
	// RuntimeVerified: the native verify of the restored plan passed.
	RuntimeVerified bool `json:"runtimeVerified"`
	// SealedSnapshotID is the executor-state checkpoint sealed after a
	// converged rollback. SealStatus explains an absent one.
	SealedSnapshotID string `json:"sealedSnapshotId,omitempty"`
	SealStatus       string `json:"sealStatus"`
	SealDetail       string `json:"sealDetail,omitempty"`
	Status           string `json:"status"`
}

Report is the `stackkit.rollback-result/v1` document.

func Execute

func Execute(ctx context.Context, request Request, journal Journal, resumed bool) (Report, error)

Execute runs the journal's plan, persisting each step's outcome. Steps a previous invocation already converged are skipped. The first failing step stops the rollback; the journal stays in progress so a second invocation resumes at that step.

type Request

type Request struct {
	WorkspaceRoot        string
	RollbackID           string
	TargetSnapshotID     string
	ChangeSetID          string
	LifecycleOperationID string
	// Current are the local stacks of the current generation, Target those
	// of the checkpoint, each in host run order.
	Current []Stack
	Target  []Stack
	// TargetRoots are the verified OpenTofu roots of the checkpoint.
	TargetRoots []TargetRoot
	Tools       terramatehost.Tools
	// Environment adds process environment for one stack's OpenTofu run,
	// such as the Compose interpolation environment of a Core payload.
	Environment func(Stack) ([]string, error)
	Timeout     time.Duration
	// Event receives `stack` progress with the per-stack status.
	Event func(phase, status string, attributes map[string]string)
	Now   func() time.Time
}

Request is one coordinated rollback of the local host to one verified checkpoint.

type RootFiles

type RootFiles struct {
	State          []byte
	Config         []byte
	Compose        []byte
	HasCompose     bool
	Environment    []byte
	HasEnvironment bool
}

RootFiles are the captured bytes of one OpenTofu root: the local-backend state and configuration inside the root, and the runtime Compose file and workload .env one level up when the root owns them.

type Stack

type Stack struct {
	ID          string
	Role        string
	RuntimeRoot string
}

Stack is one local stack of a host project in graph run order.

type StackReport

type StackReport struct {
	StackID      string `json:"stackId"`
	Role         string `json:"role"`
	RuntimeRoot  string `json:"runtimeRoot"`
	Action       string `json:"action"`
	Status       string `json:"status"`
	PlanExitCode *int   `json:"planExitCode,omitempty"`
	DurationMS   int64  `json:"durationMs"`
	Detail       string `json:"detail,omitempty"`
}

StackReport is one stack of the rollback report.

type Step

type Step struct {
	StackID     string `json:"stackId"`
	Role        string `json:"role"`
	RuntimeRoot string `json:"runtimeRoot"`
	Action      string `json:"action"`
}

Step is one planned per-stack action in execution order.

func Plan

func Plan(request Request) ([]Step, error)

Plan decides one action per local stack. Stacks of the current graph run first in reverse run order, so every dependent is destroyed or restored before the stacks it runs after; stacks only the checkpoint has are recreated afterwards in run order, because they run after the restored cores.

type StepResult

type StepResult struct {
	Status       string `json:"status"`
	PlanExitCode *int   `json:"planExitCode,omitempty"`
	DurationMS   int64  `json:"durationMs"`
	Detail       string `json:"detail,omitempty"`
	// FilesRestored marks a restored or recreated root whose checkpoint
	// files are written but whose forced apply has not converged yet.
	FilesRestored bool `json:"filesRestored,omitempty"`
}

StepResult is the recorded outcome of one step.

type TargetRoot

type TargetRoot struct {
	RuntimeRoot string
	Files       RootFiles
}

TargetRoot is one root of the target checkpoint.

Jump to

Keyboard shortcuts

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