backupexec

package
v0.41.0 Latest Latest
Warning

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

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

Documentation

Overview

Package backupexec holds the Kopia backup engine primitives shared by the `stackkit backup` CLI and the node-local StackAction endpoints. The CLI and the server must call the same argv definitions — "CLI == Web UI == server" honesty depends on there being exactly one implementation.

Index

Constants

View Source
const (
	// DefaultContainer is the name of the local Kopia agent container. It
	// matches the StackKit local backup runtime contract.
	DefaultContainer = "kopia-agent"

	// LongOperationTimeout is the global StackKits phase policy: no workflow,
	// release gate, restore, or backup wait may run longer than 15 minutes.
	// Longer work must be split into visible phases.
	LongOperationTimeout = 15 * time.Minute

	// QuickOperationTimeout bounds engine calls issued without a context
	// deadline of their own.
	QuickOperationTimeout = 30 * time.Second
)
View Source
const (
	DefaultVolumeSource   = localbackuppolicy.SourcePath
	DefaultRepositoryPath = localbackuppolicy.RepositoryPath
	DefaultConfigFile     = localbackuppolicy.ConfigPath + "/repository.config"
	DefaultCacheDirectory = localbackuppolicy.CachePath
)

DefaultVolumeSource is the canonical snapshot source covering the Docker volumes mount inside the kopia-agent container.

View Source
const (
	HookStatusOK      = "ok"
	HookStatusSkipped = "skipped"
	HookStatusFailed  = "failed"
)
View Source
const OffsiteConfigFile = localbackuppolicy.ConfigPath + "/offsite-repository.config"

Variables

View Source
var ErrContainerNotPresent = errors.New("container not present on this node")

ErrContainerNotPresent marks a hook target container that does not exist on this node. Hook execution classifies it as skipped — as opposed to a command failing INSIDE a running container, which must fail the run.

Functions

func CleanupCloudVerificationRestore

func CleanupCloudVerificationRestore(ctx context.Context, policy localbackuppolicy.Policy, operation string) error

CleanupCloudVerificationRestore removes only the disposable Cloud verification operation, after revalidating the exact Kopia container and staging mount. Owner recovery operation IDs cannot cross this closed namespace.

func IsSuccessfulOneShotCompletion

func IsSuccessfulOneShotCompletion(container QuiesceContainer) bool

IsSuccessfulOneShotCompletion reports the only stopped state that is safe to treat as already completed during recovery. It deliberately requires the graph-bound lifecycle marker so a Core container's exit is never mistaken for application initialization completion.

func LoadHookManifest

func LoadHookManifest(tofuDir string) (*backuphooks.Manifest, error)

LoadHookManifest reads the generated manifest from the deployed stack's tofu_dir. A missing manifest is not an error: stacks generated before the manifest existed simply run without quiesce hooks.

func NewDockerV2SnapshotSettler

func NewDockerV2SnapshotSettler(source localbackuppolicy.Source) func(context.Context) error

NewDockerV2SnapshotSettler ends a possibly orphaned docker-exec snapshot before its writers may resume. Killing the docker CLI alone cannot prove that the daemon-side Kopia process stopped. The dedicated idle backup container is restarted only on this explicit mutation/recovery path.

func OutputLooksNotConfigured

func OutputLooksNotConfigured(out string, err error) bool

OutputLooksNotConfigured classifies "repository not connected/initialized" answers so callers can distinguish first-run from real failures. Ported verbatim from the CLI (`backupOutputLooksNotConfigured`).

func OutputLooksRepoExists

func OutputLooksRepoExists(out string, err error) bool

OutputLooksRepoExists classifies "repository already exists" answers from `kopia repository create` so callers can connect instead. Ported verbatim from the CLI (`backupOutputLooksRepoExists`).

func SafeDiagnostic

func SafeDiagnostic(err error) (string, bool)

SafeDiagnostic returns an operator-safe diagnostic only when the error originated behind the native-v2 redaction boundary. Wrapping context added by this package is retained; arbitrary executor or test-double errors are deliberately rejected.

func StatusConfigured

func StatusConfigured(out string) bool

StatusConfigured reports whether `kopia repository status --json` output describes a connected repository. Semantics are ported verbatim from the CLI (`backupStatusConfigured`).

func ValidateCleanDockerStop

func ValidateCleanDockerStop(container QuiesceContainer) error

ValidateCleanDockerStop verifies the observed post-stop state before a journal retry may treat a previously running writer as crash-consistent. It is a Docker-level check and does not prove application or database shutdown semantics. Containers that were already stopped are excluded from the journal and do not need this operation result.

func ValidateS3Repository

func ValidateS3Repository(repo S3Repository, password []byte) error

ValidateS3Repository validates owner-supplied material without runtime effects.

Types

type ApplicationContainerCustodyVerifier

type ApplicationContainerCustodyVerifier func(context.Context, localbackuppolicy.ApplicationRuntime) (map[string]string, error)

ApplicationContainerCustodyVerifier is the adapter-owned identity boundary for a selected Standalone-Compose graph. It must return one exact Docker daemon identity per policy component after checking the persisted Compose artifact. Health/readiness is deliberately outside this callback so stopped containers remain addressable during snapshot recovery.

type ContainerExecutor

type ContainerExecutor func(ctx context.Context, container string, command []string) (string, error)

ContainerExecutor runs a command inside an arbitrary container — unlike Executor it is not bound to the kopia-agent. Hook commands run against the database containers themselves.

func DockerContainerExecutor

func DockerContainerExecutor() ContainerExecutor

DockerContainerExecutor runs pre-snapshot hook commands against arbitrary containers (the database containers themselves, not the kopia-agent). A missing container surfaces as ErrContainerNotPresent so hook execution can classify it as skipped rather than failed.

type ContainerQuiescer

type ContainerQuiescer interface {
	ManagedContainers(context.Context) ([]QuiesceContainer, error)
	InspectContainer(context.Context, string) (QuiesceContainer, error)
	StopContainer(context.Context, string) error
	StartContainer(context.Context, string) error
}

ContainerQuiescer is the narrow Docker control boundary used by the local backup lifecycle. Implementations must use the policy's fixed local daemon; no caller supplied socket or container command crosses this interface.

func NewDockerV2Quiescer

func NewDockerV2Quiescer(source localbackuppolicy.Source) ContainerQuiescer

NewDockerV2Quiescer returns the rootful, local Docker controller governed by the same source policy as the native Kopia executor.

func NewDockerV2QuiescerWithApplicationCustody

func NewDockerV2QuiescerWithApplicationCustody(source localbackuppolicy.Source, verifier ApplicationContainerCustodyVerifier) ContainerQuiescer

NewDockerV2QuiescerWithApplicationCustody is the production constructor for a source containing Standalone-Compose applications. The caller must pass the already admitted adapter authority; a nil verifier deliberately rejects application quiescence rather than treating mutable Docker labels as a substitute for persisted Compose custody.

type Engine

type Engine struct {
	Exec Executor
}

Engine exposes granular Kopia operations. Orchestration (messages, retry, sequencing) stays with the caller so the CLI keeps its exact behavior.

func NewDockerEngine

func NewDockerEngine(container string) Engine

NewDockerEngine wires Engine to the shared docker exec adapter.

func (Engine) ConnectFilesystemRepository

func (e Engine) ConnectFilesystemRepository(ctx context.Context, path string) (string, error)

func (Engine) ConnectS3Repository

func (e Engine) ConnectS3Repository(ctx context.Context, repo S3Repository, password string) (string, error)

func (Engine) CreateFilesystemRepository

func (e Engine) CreateFilesystemRepository(ctx context.Context, path string) (string, error)

func (Engine) CreateS3Repository

func (e Engine) CreateS3Repository(ctx context.Context, repo S3Repository, password string) (string, error)

func (Engine) DeleteSnapshots

func (e Engine) DeleteSnapshots(ctx context.Context, ids []string) (string, error)

DeleteSnapshots removes the given snapshot manifests. Kopia requires the --delete flag to confirm destructive intent (kopia.io command-line reference, snapshot-delete).

func (Engine) Disconnect

func (e Engine) Disconnect(ctx context.Context) (string, error)

Disconnect detaches the agent from the repository without deleting remote data. backup_wipe calls it last so a wiped node no longer holds repository credentials in its Kopia config.

func (Engine) EnsureFilesystemRepository

func (e Engine) EnsureFilesystemRepository(ctx context.Context, path string) (string, error)

EnsureFilesystemRepository connects to (or first creates) a local filesystem repository: status pre-check, mkdir, create, and connect when the repository already exists. CLI configure and the backup_run local branch share this single sequence.

func (Engine) EnsureS3Repository

func (e Engine) EnsureS3Repository(ctx context.Context, repo S3Repository, password string) (string, error)

EnsureS3Repository connects to (or first creates) the S3-compatible repository. It mirrors the filesystem sequence the CLI uses: create, and when the repository already exists, connect instead.

func (Engine) ListSnapshotsJSON

func (e Engine) ListSnapshotsJSON(ctx context.Context) (string, error)

func (Engine) MaintenanceRunFull

func (e Engine) MaintenanceRunFull(ctx context.Context) (string, error)

MaintenanceRunFull compacts and garbage-collects the repository after bulk snapshot deletion so wiped data actually leaves the store.

func (Engine) Mkdir

func (e Engine) Mkdir(ctx context.Context, path string) (string, error)

func (Engine) RepositoryStatusJSON

func (e Engine) RepositoryStatusJSON(ctx context.Context) (string, error)

func (Engine) Restore

func (e Engine) Restore(ctx context.Context, snapshotID, target string) (string, error)

func (Engine) Snapshot

func (e Engine) Snapshot(ctx context.Context, source, description string) (string, error)

func (Engine) ValidateProvider

func (e Engine) ValidateProvider(ctx context.Context) (string, error)

type Executor

type Executor func(ctx context.Context, command []string) (string, error)

Executor runs a command inside the kopia-agent container (or a fake in tests). It matches the CLI's historical `backupExecutor` seam so existing fakes plug in unchanged.

func DockerExecutor

func DockerExecutor(container string) Executor

DockerExecutor returns an Executor that runs commands inside the named kopia-agent container via the local docker daemon. The CLI and the StackAction endpoints share this adapter so both speak identical argv against the same container. Per-call client timeouts derive from the context deadline, capped at LongOperationTimeout.

func DockerExecutorUncapped

func DockerExecutorUncapped(container string) Executor

DockerExecutorUncapped derives the per-call client timeout solely from the context deadline. It exists for detached node-side runs (first content snapshots can legitimately exceed the 15-minute wait policy — the wait is split into backup_status polls, the underlying snapshot is not).

type HookResult

type HookResult struct {
	Container string `json:"container"`
	Engine    string `json:"engine"`
	Status    string `json:"status"` // ok | skipped | failed
	Detail    string `json:"detail,omitempty"`
}

HookResult reports one hook execution for run-state and backup_status.

func RunPreSnapshotHooks

func RunPreSnapshotHooks(ctx context.Context, exec ContainerExecutor, manifest *backuphooks.Manifest) ([]HookResult, error)

RunPreSnapshotHooks executes every hook whose container exists on this node. A postgres or sqlite dump failure fails the run (the database class would be inconsistent without it); redis cache-only hooks and unsupported engines are reported as skipped.

type QuiesceContainer

type QuiesceContainer struct {
	ID             string         `json:"id"`
	Name           string         `json:"name"`
	Status         string         `json:"status"`
	Running        bool           `json:"running"`
	Paused         bool           `json:"paused"`
	Restarting     bool           `json:"restarting"`
	ExitCode       int            `json:"exitCode"`
	OOMKilled      bool           `json:"oomKilled"`
	Error          string         `json:"error,omitempty"`
	StopSignal     string         `json:"stopSignal,omitempty"`
	WorkloadRef    string         `json:"workloadRef,omitempty"`
	SiteRef        string         `json:"siteRef,omitempty"`
	NodeRef        string         `json:"nodeRef,omitempty"`
	ComposeProject string         `json:"composeProject,omitempty"`
	ComposeService string         `json:"composeService,omitempty"`
	ComponentRef   string         `json:"componentRef,omitempty"`
	Lifecycle      string         `json:"lifecycle,omitempty"`
	Image          string         `json:"image,omitempty"`
	StopOrder      int            `json:"stopOrder,omitempty"`
	Mounts         []QuiesceMount `json:"mounts"`
}

QuiesceContainer is the Docker identity needed to stop and restore one container without falling back to a mutable name lookup.

type QuiesceMount

type QuiesceMount struct {
	Type        string `json:"type"`
	Name        string `json:"name"`
	Source      string `json:"source"`
	Destination string `json:"destination"`
	RW          bool   `json:"rw"`
	Propagation string `json:"propagation"`
}

QuiesceMount is the immutable Docker mount identity retained in the snapshot operation journal before any container is stopped.

type RepositoryStatus

type RepositoryStatus struct {
	Configured  bool   `json:"configured"`
	ConfigFile  string `json:"configFile"`
	Storage     string `json:"storage"`
	StoragePath string `json:"storagePath"`
	S3Endpoint  string `json:"s3Endpoint,omitempty"`
	S3Bucket    string `json:"s3Bucket,omitempty"`
	S3Prefix    string `json:"s3Prefix,omitempty"`
	S3Region    string `json:"s3Region,omitempty"`
	InsecureTLS bool   `json:"insecureTLS,omitempty"`
}

RepositoryStatus is the structured native-v2 projection of Kopia repository status. Raw Kopia output never crosses the V2Engine boundary.

type RestoreRequest

type RestoreRequest struct {
	SnapshotID  string
	OperationID string
	StagingPath string
}

RestoreRequest is the closed native-v2 staged-restore input. StagingPath must be derived from OperationID below the governed isolated volume.

type RestoreResult

type RestoreResult struct {
	SnapshotID                string `json:"snapshotId"`
	OperationID               string `json:"operationId"`
	StagingPath               string `json:"stagingPath"`
	RepositoryContentVerified bool   `json:"repositoryContentVerified"`
}

type S3Repository

type S3Repository struct {
	Endpoint        string
	Bucket          string
	Region          string
	Prefix          string
	AccessKeyID     string
	SecretAccessKey string
}

S3Repository describes an S3-compatible repository target (kombify-managed R2 or bring-your-own). Credentials travel by value and must never be logged or persisted by callers.

func CanonicalS3Repository

func CanonicalS3Repository(repo S3Repository, password []byte) (S3Repository, error)

CanonicalS3Repository returns the exact endpoint representation used by Kopia.

type SecretExecutor

type SecretExecutor func(ctx context.Context, command []string, sensitiveInput []byte) (string, error)

SecretExecutor is the native-v2 invocation seam. Sensitive input is delivered separately from argv so the Docker adapter can pass it only on stdin and redact it from every observable result.

func DockerV2Executor

func DockerV2Executor() SecretExecutor

DockerV2Executor binds the native-v2 secret executor to docker exec -i. Kopia 0.18.2 reads KOPIA_PASSWORD before attempting its terminal-only password prompt. A fixed shell adapter reads exactly one secret line from stdin into that child-process environment and then execs the closed Kopia argv. The secret is never present in Docker argv, the container definition, or a persistent environment. No caller can supply a free-form shell command.

type Snapshot

type Snapshot struct {
	ID          string    `json:"id"`
	SourcePath  string    `json:"sourcePath"`
	SourceHost  string    `json:"sourceHost"`
	Description string    `json:"description,omitempty"`
	OperationID string    `json:"operationId,omitempty"`
	Pins        []string  `json:"pins,omitempty"`
	StartTime   time.Time `json:"startTime"`
	EndTime     time.Time `json:"endTime"`
	TotalSize   int64     `json:"totalSize"`
}

func ParseSnapshotCreate

func ParseSnapshotCreate(raw string) (Snapshot, error)

ParseSnapshotCreate decodes the single object emitted by `kopia snapshot create --json`.

func ParseSnapshots

func ParseSnapshots(raw string) ([]Snapshot, error)

ParseSnapshots decodes Kopia's `snapshot list --json` output into the engine's snapshot shape. Unknown fields are ignored so Kopia schema drift degrades gracefully.

type SnapshotRequest

type SnapshotRequest struct {
	Source      string
	Description string
	OperationID string
	// Recovery protection is set before Kopia assigns the manifest ID. Pinning
	// an existing manifest would replace that ID and invalidate signed anchors.
	ProtectRecovery bool
}

SnapshotRequest is the closed native-v2 snapshot input. OperationID is materialized as a Kopia tag so lifecycle evidence can bind the result without accepting arbitrary caller-supplied argv.

type SourcePolicy

type SourcePolicy struct {
	Source       string   `json:"source"`
	ExcludePaths []string `json:"excludePaths"`
	Exact        bool     `json:"exact"`
}

SourcePolicy is the typed effective-policy verdict for the governed source. Exact is true only for the CUE-owned ignore set and manual-only behavior.

type V2Engine

type V2Engine struct {
	Exec SecretExecutor
	// contains filtered or unexported fields
}

V2Engine is the fail-closed native-v2 Kopia path. It deliberately does not reuse Engine because the historical Executor contract permits credentials in argv and must remain compatible until its callers migrate.

func NewDockerV2Engine

func NewDockerV2Engine() V2Engine

NewDockerV2Engine wires the native-v2 engine to its fixed Docker adapter.

func NewDockerV2EngineForPolicy

func NewDockerV2EngineForPolicy(policy localbackuppolicy.Policy) (V2Engine, error)

NewDockerV2EngineForPolicy binds the native-v2 engine to one already validated, immutable local Kopia policy. The canonical codec both validates the policy and detaches all caller-owned slices before the source reaches the Docker runtime validator.

func NewDockerV2OffsiteEngineForPolicy

func NewDockerV2OffsiteEngineForPolicy(policy localbackuppolicy.Policy) (V2Engine, error)

NewDockerV2OffsiteEngineForPolicy admits only the finite Cloud outbound profile and retains the same source mounts, image and single-peer checks.

func NewV2Engine

func NewV2Engine(exec SecretExecutor) V2Engine

NewV2Engine binds native-v2 operations to explicit persistent config and cache locations in the local Kopia runtime.

func NewV2OffsiteEngineForPolicy

func NewV2OffsiteEngineForPolicy(exec SecretExecutor, policy localbackuppolicy.Policy) (V2Engine, error)

NewV2OffsiteEngineForPolicy uses a separate fixed Kopia configuration in the existing governed config volume. Connecting S3 never replaces the local repository.

func (V2Engine) ConfigureSourcePolicy

func (e V2Engine) ConfigureSourcePolicy(ctx context.Context, source string, excludePaths []string, password []byte) error

ConfigureSourcePolicy applies the CUE-resolved exclusions to the exact snapshot source using a closed argv construction.

func (V2Engine) ConnectFilesystemRepository

func (e V2Engine) ConnectFilesystemRepository(ctx context.Context, repositoryPath string, password []byte) error

ConnectFilesystemRepository connects the native-v2 runtime to an existing local repository without placing its password in argv or environment.

func (V2Engine) ConnectS3Repository

func (e V2Engine) ConnectS3Repository(ctx context.Context, repo S3Repository, password []byte) (RepositoryStatus, error)

ConnectS3Repository connects only to an existing repository. A different configured target is rejected without disconnecting, creating or adopting it. Kopia owns its repository configuration; this method never creates a bucket.

func (V2Engine) CreateFilesystemRepository

func (e V2Engine) CreateFilesystemRepository(ctx context.Context, repositoryPath string, password []byte) error

CreateFilesystemRepository initializes a native-v2 local repository. The repository password is supplied only to the fixed per-process password adapter over sensitive stdin; it is never part of Docker argv or persistent container configuration.

func (V2Engine) CreateSnapshot

func (e V2Engine) CreateSnapshot(ctx context.Context, request SnapshotRequest, password []byte) (Snapshot, error)

CreateSnapshot creates one native-v2 snapshot and parses Kopia's JSON result into the stable StackKits snapshot shape. Missing or malformed identity is rejected rather than being reported as a successful snapshot.

func (V2Engine) EnsureFilesystemRepository

func (e V2Engine) EnsureFilesystemRepository(ctx context.Context, repositoryPath string, password []byte) (RepositoryStatus, error)

EnsureFilesystemRepository idempotently creates or connects a local repository and returns only its structured final status.

func (V2Engine) FindSnapshot

func (e V2Engine) FindSnapshot(ctx context.Context, request SnapshotRequest, password []byte) (Snapshot, bool, error)

FindSnapshot returns the exact typed receipt for a prior operation without creating a snapshot. Pending lifecycle recovery uses this read-only seam before deciding whether a create side effect is still required.

func (V2Engine) MaintenanceRunFull

func (e V2Engine) MaintenanceRunFull(ctx context.Context, password []byte) (string, error)

MaintenanceRunFull compacts and garbage-collects the repository, releasing the storage held by snapshots that retention has dropped. See MaintenanceRunQuick for why this is the only admissible deletion path.

func (V2Engine) MaintenanceRunQuick

func (e V2Engine) MaintenanceRunQuick(ctx context.Context, password []byte) (string, error)

MaintenanceRunQuick performs index compaction without full garbage collection. It is the cheap, frequent half of Kopia's maintenance pair.

Retention is a policy, not a deletion: keepDaily and its siblings decide which snapshots stay referenced, and only maintenance frees the blobs the dropped ones held. A repository that snapshots on a schedule but never runs maintenance grows without bound no matter what the retention policy says.

Deletion must happen here and nowhere else. An object-store expiry or lifecycle rule over a Kopia bucket removes pack blobs the index still references, which corrupts the repository silently: nothing fails until a restore needs one of the removed blobs.

func (V2Engine) RepositoryStatus

func (e V2Engine) RepositoryStatus(ctx context.Context, password []byte) (RepositoryStatus, error)

RepositoryStatus returns typed status. A clean first-run "not configured" answer is represented as Configured=false rather than an operation error.

func (V2Engine) RestoreSnapshot

func (e V2Engine) RestoreSnapshot(
	ctx context.Context,
	request RestoreRequest,
	password []byte,
) (RestoreResult, error)

RestoreSnapshot performs a full repository-content verification before and after an atomic restore into the fixed isolated staging volume. It never receives or writes the live Docker volume root.

func (V2Engine) SourcePolicy

func (e V2Engine) SourcePolicy(ctx context.Context, source string, excludePaths []string, password []byte) (SourcePolicy, error)

SourcePolicy reads back Kopia's complete effective source policy. Exact is true only for the governed ignores, explicit retention, and manual-only scheduling. Every other effective field is drift: inherited retention, dot-ignore files such as .kopiaignore, traversal/error filters, timers, actions, and future fields all fail closed instead of changing selection or autonomous behavior.

Jump to

Keyboard shortcuts

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