cloudiac

package
v1.1.0 Latest Latest
Warning

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

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

Documentation

Overview

Package cloudiac defines the engine contract for cloud provisioning. It holds types only: nothing runs until an implementation is wired in.

Index

Constants

View Source
const (
	CodeIAMForbidden    = "cloud_iam_forbidden"
	CodeProtectedDelete = "cloud_protected_delete"
	CodeDestroyCap      = "cloud_destroy_cap"
	CodeCostUnpriced    = "cloud_cost_unpriced"
	CodeCostLimit       = "cloud_cost_limit"
)

Stable refusal codes for cloud policy and cost guards.

View Source
const (
	ActionCreate  = "create"
	ActionUpdate  = "update"
	ActionDelete  = "delete"
	ActionReplace = "replace"
	ActionNoop    = "no-op"
)

Resource change actions as reported by a rendered plan.

View Source
const (
	RunSharedSubdir = "shared"
	RunWorkSubdir   = "work"
	RunStateSubdir  = "state"
)

Layout of the private per-run directory. Only Shared is mounted, read-write, into steps.

View Source
const (
	SandboxModuleDir     = "/module"
	SandboxWorkDir       = "/work"
	SandboxStateDir      = "/state"
	SandboxTofuPath      = "/opt/tofu/tofu"
	SandboxPluginDir     = "/opt/tofu/plugins"
	SandboxCredentialDir = "/run/lr-cred" //nolint:gosec // a mount path, not a credential
)

Fixed paths inside the step container.

View Source
const DefaultStack = "default"

DefaultStack names the module when an apply source carries no name.

View Source
const MainFile = "main.tf.json"

MainFile is the one configuration file a rendered module carries.

View Source
const StatePurpose = "cloud-state"

StatePurpose names the master derived key that wraps every per record state key.

View Source
const TofuVersion = "1.13.2"

TofuVersion is the OpenTofu release this Levelrail release pins.

Variables

View Source
var (
	ErrFetchConfig          error = &unavailableError{msg: "cloudiac: fetch is not configured, check the cloud.fetch_* settings"}
	ErrUnpinnedVersion            = errors.New("cloudiac: OpenTofu version has no compiled checksum")
	ErrUnsupportedPlatform        = errors.New("cloudiac: no compiled checksum for this platform")
	ErrPlaceholderDigest          = errors.New("cloudiac: compiled checksum is a placeholder, refusing to run")
	ErrSignatureUnverified        = errors.New("cloudiac: release signature verification is not available")
	ErrLowDisk                    = errors.New("cloudiac: not enough free disk for the OpenTofu download")
	ErrTooLarge                   = errors.New("cloudiac: OpenTofu download exceeds the size cap")
	ErrChecksumMismatch           = errors.New("cloudiac: OpenTofu checksum mismatch")
	ErrBadArchive                 = errors.New("cloudiac: OpenTofu archive is malformed")
	ErrFreeSpaceUnsupported       = errors.New("cloudiac: free space probe is not supported on this platform")
)

Fetch errors. Every one is a hard stop: there is no retry with another URL.

View Source
var (
	ErrStateConfig         = errors.New("cloudiac: state store is not configured")
	ErrStateKeyUnavailable = errors.New("cloudiac: state key is unavailable, the master key is not loaded")
	ErrStateTooLarge       = errors.New("cloudiac: state exceeds the size cap")
	ErrStateTampered       = errors.New("cloudiac: sealed state failed authentication")
)

State errors. Messages never carry state bytes or key material.

View Source
var (
	ErrStateLocked         = errors.New("cloudiac: cloud state is locked by another run")
	ErrNotImplemented      = errors.New("cloudiac: step is not implemented yet")
	ErrPlanMismatch        = errors.New("cloudiac: the saved plan does not match the approved plan hash")
	ErrPlanExpired         = errors.New("cloudiac: the saved plan is older than cloud.plan_max_age_minutes")
	ErrPlanStale           = errors.New("cloudiac: the state changed after the plan was made")
	ErrDestroyNotConfirmed = errors.New("cloudiac: destroy needs an explicit confirmation")
	ErrStateWriteRejected  = errors.New("cloudiac: state write was rejected, the cloud and the stored state may differ")
	// ErrStateQuarantined fails closed: a plan against stale state could recreate resources that exist.
	ErrStateQuarantined = errors.New("cloudiac: the stack has quarantined state that must be recovered first")
)

Sentinels callers match with errors.Is.

View Source
var ErrChecksumNotListed = errors.New("cloudiac: archive is not listed in the signed checksum file")

ErrChecksumNotListed means the signed checksum file has no line for the downloaded archive.

View Source
var ErrNotConfigured error = &unavailableError{msg: "cloudiac: no engine configured"}

ErrNotConfigured is returned when no engine implementation is wired in.

View Source
var ErrPlanNotFound = errors.New("cloudiac: no saved plan for this stack")

ErrPlanNotFound means the stack has no saved plan to apply.

View Source
var ErrSandboxSpec = errors.New("cloudiac: unsafe sandbox spec")

ErrSandboxSpec marks a step spec the builder refuses to produce.

Functions

func FetchLimitsFrom

func FetchLimitsFrom(get func() SettingsReader) func() FetchLimits

FetchLimitsFrom reads the fetch limits per call; a nil reader yields zeros, which NewFetcher refuses.

func FreeBytes

func FreeBytes(dir string) (int64, error)

FreeBytes reports the space an unprivileged process may still write under dir.

func InstallInto

func InstallInto(enabled bool, planner iac.CloudPlanner, policy iac.PolicyChecker) bool

InstallInto wires the planner and policy into iac only when the cloud flag is on. With it off nothing is installed and cloud documents keep failing loudly.

func IsIAMType

func IsIAMType(t string) bool

IsIAMType reports whether a resource type creates or changes identity or access.

func IsProtectedType

func IsProtectedType(t string) bool

IsProtectedType reports whether deleting a resource type needs an opt in.

func LiveSandbox

func LiveSandbox(get func() SettingsReader, runtime string) func(TofuConfig) TofuConfig

LiveSandbox returns a TofuConfig.Live that reads image, user, network and limits per run. An empty image or network leaves the field empty, so the plan fails as not configured.

func LoadSigstoreTrustedRoot

func LoadSigstoreTrustedRoot(cacheDir string) (*root.TrustedRoot, error)

LoadSigstoreTrustedRoot fetches the public Sigstore trust root over TUF, caching it under cacheDir.

func PlanHash

func PlanHash(plan []byte) string

PlanHash is the digest a reviewer approves; apply refuses any other.

func RedactLog

func RedactLog(log string, secrets ...string) string

RedactLog masks every secret in a step log, including each line of a multi-line key. Short fragments are skipped so ordinary words are not blanked out.

func RedactStepOutput

func RedactStepOutput(out string, limit int, credRedact func(string) string, sensitive []string, state []byte) string

RedactStepOutput masks credential lines, the whole state blob and each sensitive value, then keeps the tail within limit. Masking runs first so a cut never exposes half a secret.

func RefusalsError

func RefusalsError(rs []Refusal) error

RefusalsError joins refusals into one error, or returns nil when empty.

func SensitiveValues

func SensitiveValues(raws ...[]byte) []string

SensitiveValues collects every string under an attribute that plan or state JSON marks sensitive.

func StackName

func StackName(source string) string

StackName maps an apply source to a module name; the state key is the account plus this name.

func StepArgs

func StepArgs(step Step) ([]string, error)

StepArgs returns the tofu arguments for a step. Apply only runs the saved plan, never a fresh diff.

Types

type AccountInfo

type AccountInfo struct {
	Region          string
	CompartmentOCID string
	Namespace       string
	Credential      CredentialHandle
}

AccountInfo is what a CloudAccount document resolves to; secrets stay behind the handle.

type AccountResolver

type AccountResolver interface {
	ResolveAccount(ctx context.Context, name string) (AccountInfo, error)
}

AccountResolver looks up a CloudAccount by name.

type ApplyRequest

type ApplyRequest struct {
	Spec     ModuleSpec
	Cred     CredentialHandle
	PlanHash string
	// ConfirmDestroy must be set to run a destroy plan.
	ConfirmDestroy bool
}

ApplyRequest names the approved saved plan. The module must be the one the plan was made from.

type BinaryEnsurer

type BinaryEnsurer interface {
	Ensure(ctx context.Context) (string, error)
}

BinaryEnsurer returns a verified OpenTofu binary path; *Fetcher implements it.

type BucketSpec

type BucketSpec struct {
	Name        string
	Namespace   string
	Unprotected bool
}

BucketSpec is an object storage bucket in its object storage namespace. Buckets are protected from destroy unless Unprotected is set.

type Change

type Change struct {
	Address string
	Action  string
}

Change is one redacted resource change reported by a step.

type CloudPlannerAdapter

type CloudPlannerAdapter struct {
	Engine   DetailedPlanner
	Accounts AccountResolver
}

CloudPlannerAdapter implements iac.CloudStackPlanner: every cloud document of one Levelrail stack and account is rendered into one module with one sealed state.

func (CloudPlannerAdapter) ApplyCloud

ApplyCloud re-renders the account group of the target exactly as planned and runs the saved plan the approval names; the engine refuses any other hash.

func (CloudPlannerAdapter) CloudReady

func (a CloudPlannerAdapter) CloudReady() bool

CloudReady reports false until both the engine and the account resolver are set, so even record-only kinds fail as unavailable instead of reporting unchanged.

func (CloudPlannerAdapter) PlanCloud

PlanCloud plans one document as a stack of its own; apply uses PlanCloudStack.

func (CloudPlannerAdapter) PlanCloudStack

func (a CloudPlannerAdapter) PlanCloudStack(ctx context.Context, stack string, rs []iac.CloudResource) []iac.CloudOutcome

PlanCloudStack groups the documents by account, plans one module per group and splits the changes back to the documents by resource address.

type ConnectionAccounts

type ConnectionAccounts struct {
	Conns  ConnectionGetter
	Sealed cloudconn.SealedReader
}

ConnectionAccounts maps a CloudAccount name to the stored connection of the same name, and opens that connection's sealed credential only when a step needs it.

func (ConnectionAccounts) ResolveAccount

func (c ConnectionAccounts) ResolveAccount(ctx context.Context, name string) (AccountInfo, error)

ResolveAccount implements AccountResolver.

func (ConnectionAccounts) ResolveOracle

ResolveOracle implements OracleResolver; the handle id is the connection name.

type ConnectionGetter

type ConnectionGetter interface {
	Get(ctx context.Context, name string) (cloudconn.Connection, error)
}

ConnectionGetter loads a stored cloud connection by name; *cloudconn.Service implements it.

type CostEstimate

type CostEstimate struct {
	MonthlyMicros int64
	Unpriced      []string
	AsOf          string
	Refusals      []Refusal
}

CostEstimate is the outcome of pricing a change set.

func (CostEstimate) Allowed

func (e CostEstimate) Allowed() bool

Allowed reports whether the estimate has no refusals.

type CostPolicy

type CostPolicy struct {
	// MonthlyLimitMicros is the account limit. Zero means nothing billable is allowed.
	MonthlyLimitMicros int64
	// AllowUnpriced lets resources without a price through, not estimated.
	AllowUnpriced bool
}

CostPolicy bounds the estimated monthly spend of one account.

func NewCostPolicy

func NewCostPolicy(limitMicros int64, requireFullEstimate bool) CostPolicy

NewCostPolicy builds a cost policy from runtime setting values read by the caller. requireFullEstimate true blocks resources without a price.

func (CostPolicy) Estimate

func (c CostPolicy) Estimate(table PriceTable, changes []ResourceChange, existingMicros int64) CostEstimate

Estimate prices the resources a change set leaves in place plus the existing monthly spend, and returns the verdict against the account limit.

type CredentialFile

type CredentialFile struct {
	// HostPath is a file on a host tmpfs, written for this step and removed after it.
	HostPath string
	// EnvName names the variable that tells the provider where the file is.
	EnvName string
}

CredentialFile is the one short-lived credential file of a step. Only its path enters the spec.

type CredentialHandle

type CredentialHandle struct {
	ID        string
	ExpiresAt int64
}

CredentialHandle refers to a short-lived credential for one step. The engine resolves it at run time so secrets never sit in specs or results.

type DetailedPlanner

type DetailedPlanner interface {
	PlanDetailed(ctx context.Context, spec ModuleSpec, cred CredentialHandle) (PlanResult, error)
}

DetailedPlanner is the engine surface the adapter needs; TofuEngine implements it.

type Engine

type Engine interface {
	Plan(ctx context.Context, spec ModuleSpec, cred CredentialHandle) (Result, error)
	Apply(ctx context.Context, req ApplyRequest) (Result, error)
	Destroy(ctx context.Context, req ApplyRequest) (Result, error)
}

Engine runs provisioning steps. Other engines can implement it later.

type Error

type Error struct {
	Kind    ErrorKind
	Step    Step
	Message string
	Err     error
}

Error is a step failure with a redacted message.

func (*Error) Error

func (e *Error) Error() string

func (*Error) Unwrap

func (e *Error) Unwrap() error

type ErrorKind

type ErrorKind string

ErrorKind classifies a step failure so callers can react without parsing text.

const (
	ErrInvalidSpec ErrorKind = "invalid_spec"
	ErrCredential  ErrorKind = "credential"
	ErrProvider    ErrorKind = "provider"
	ErrCanceled    ErrorKind = "canceled"
	// ErrTimeout matches iac.CodePlanTimeout so a job can report it without parsing text.
	ErrTimeout  ErrorKind = "plan_timeout"
	ErrInternal ErrorKind = "internal"
)

The failure classes an engine reports.

const (
	ErrLockHeld      ErrorKind = "lock_held"
	ErrPolicyRefused ErrorKind = "policy_refused"
	ErrUnsupported   ErrorKind = "not_implemented"
	// ErrPlanRejected means the saved plan is missing, does not match the approved hash, expired or is stale.
	ErrPlanRejected ErrorKind = "plan_rejected"
	// ErrStateDiverged means apply ran but its state could not be written under the fence.
	ErrStateDiverged ErrorKind = "state_diverged"
	// ErrQuarantineHeld means the stack has unrecovered quarantined state, so no run may start.
	ErrQuarantineHeld ErrorKind = "state_quarantined"
)

Extra failure classes of the OpenTofu engine.

type ExecRunner

type ExecRunner struct {
	// MaxBytes caps each stream; zero uses the env seeded default.
	MaxBytes int64
	// contains filtered or unexported fields
}

ExecRunner shells to docker or podman with the argv BuildSandboxSpec produced.

func (ExecRunner) Run

func (r ExecRunner) Run(ctx context.Context, spec SandboxSpec) (RunOutput, error)

Run starts the container and waits; the caller's context carries the timeout. A cancelled step is interrupted, killed after the wait delay, and its named container removed.

type FetchConfig

type FetchConfig struct {
	DataDir      string
	Version      string
	MaxBytes     int64
	MinFreeBytes int64
	Timeout      time.Duration
	// FreeBytes reports free space under DataDir; the caller supplies it per platform.
	FreeBytes  func(dir string) (int64, error)
	HTTPClient *http.Client
	BaseURL    string
	Verifier   SignatureVerifier
	// AllowChecksumOnly accepts a release without a signature check. Default off.
	AllowChecksumOnly bool
	GOOS, GOARCH      string
}

FetchConfig holds the fetch limits. Values come from runtime settings; zero values refuse.

func (*FetchConfig) ApplyLimits

func (c *FetchConfig) ApplyLimits(l FetchLimits)

ApplyLimits copies the runtime settings into the config and installs the platform free space probe.

type FetchLimits

type FetchLimits struct {
	MaxMB, MinFreeMB, TimeoutSeconds int
	AllowChecksumOnly                bool
}

FetchLimits are the runtime settings that bound a fetch; NewFetcher refuses zero values.

type Fetcher

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

Fetcher downloads and caches the pinned OpenTofu binary. It does no I/O until Ensure.

func NewFetcher

func NewFetcher(cfg FetchConfig) (*Fetcher, error)

NewFetcher validates the config without touching the network or disk.

func (*Fetcher) Ensure

func (f *Fetcher) Ensure(ctx context.Context) (string, error)

Ensure returns the path of a verified OpenTofu binary, downloading it on first use.

type InstanceSpec

type InstanceSpec struct {
	Name               string
	Network            string
	Shape              string
	OCPUs              int
	MemoryGB           int
	AvailabilityDomain string
	ImageOCID          string
}

InstanceSpec is a compute instance placed in a rendered network.

type KeyDeriver

type KeyDeriver interface {
	DeriveKey(purpose string) []byte
}

KeyDeriver is the part of secrets.Manager the state store needs.

type LiveFetcher

type LiveFetcher struct {
	Base   FetchConfig
	Limits func() FetchLimits
	// contains filtered or unexported fields
}

LiveFetcher builds a Fetcher per call so changed fetch settings apply to the next download.

func (*LiveFetcher) Ensure

func (l *LiveFetcher) Ensure(ctx context.Context) (string, error)

Ensure implements BinaryEnsurer.

type MaterialSource

type MaterialSource func(ctx context.Context, version string) (ReleaseMaterial, error)

MaterialSource loads the release material for a version, for example from a fetched bundle.

type ModuleSpec

type ModuleSpec struct {
	Name      string
	Provider  string
	Files     map[string][]byte
	Variables map[string]string
}

ModuleSpec is a rendered module the engine runs, never raw user input.

func RenderOCI

func RenderOCI(s OCISpec) (ModuleSpec, error)

RenderOCI renders the spec to a ModuleSpec holding Terraform JSON configuration. Output is deterministic and never carries credentials.

type Mount

type Mount struct {
	Source    string
	Target    string
	ReadWrite bool
}

Mount is a bind mount, read-only unless ReadWrite is set for the run directory.

type NetworkPolicy

type NetworkPolicy struct {
	Network   string
	DenyCIDRs []string
}

NetworkPolicy is the egress rule set for step containers, applied to a pre-created network.

func NewNetworkPolicy

func NewNetworkPolicy(network string, controlPlane []string) (NetworkPolicy, error)

NewNetworkPolicy adds the control plane addresses to the builtin deny list. The network itself is created and firewalled outside this package from DenyCIDRs.

func (NetworkPolicy) Denies

func (p NetworkPolicy) Denies(addr string) bool

Denies reports whether addr falls in the deny list; the firewall step and tests share it.

func (NetworkPolicy) RunFlags

func (p NetworkPolicy) RunFlags() []string

RunFlags returns the container flags that attach a step to the policy network.

type NetworkSpec

type NetworkSpec struct {
	Name         string
	CIDR         string
	IngressPorts []int
}

NetworkSpec is a VCN with one public subnet.

type OCISpec

type OCISpec struct {
	Name            string
	Region          string
	CompartmentOCID string
	Networks        []NetworkSpec
	Buckets         []BucketSpec
	Instances       []InstanceSpec
}

OCISpec is every cloud resource of one stack, rendered as one module so references resolve inside it. Provider credentials are not part of it; the engine supplies them per step.

type OracleResolver

type OracleResolver interface {
	ResolveOracle(ctx context.Context, h CredentialHandle) (cloudconn.OracleCredential, error)
}

OracleResolver turns a credential handle into the materializable Oracle credential.

type PlanAttr

type PlanAttr struct {
	Path      string
	Old, New  string
	Sensitive bool
}

PlanAttr is one top level attribute change; sensitive values are already masked.

type PlanChange

type PlanChange struct {
	Address string
	Type    string
	Action  string
	Attrs   []PlanAttr
}

PlanChange is one managed resource change from the saved plan.

type PlanResult

type PlanResult struct {
	Changes  []PlanChange
	Cost     CostEstimate
	Warnings []string
	Hash     string
}

PlanResult is the typed plan with its cost verdict and the hash a reviewer approves.

func (PlanResult) Summary

func (p PlanResult) Summary() string

Summary is a one line count that never carries values.

type Policy

type Policy struct {
	// MaxDestroys is the number of destroys allowed without an override.
	MaxDestroys int
	// AllowProtectedDelete is the explicit opt in to delete data resources.
	AllowProtectedDelete bool
}

Policy holds the knobs for the change set checks.

func NewPolicy

func NewPolicy(maxDestroys int, allowProtectedDelete bool) Policy

NewPolicy builds a policy from runtime setting values read by the caller. A negative cap is treated as zero so a bad value stays strict.

func (Policy) Check

func (p Policy) Check(changes []ResourceChange) []Refusal

Check returns every refusal for the change set, ordered by address then code.

type PolicyAdapter

type PolicyAdapter struct {
	Policy func() Policy
}

PolicyAdapter exposes Policy.Check as an iac.PolicyChecker, reading the policy per call.

func (PolicyAdapter) CheckCloud

func (p PolicyAdapter) CheckCloud(changes []iac.CloudChange) []iac.CloudRefusal

CheckCloud implements iac.PolicyChecker. A nil policy func stays strict.

type PriceTable

type PriceTable interface {
	// Monthly returns the monthly price for one resource and whether it is priced.
	Monthly(resourceType string) (micros int64, ok bool)
	// AsOf names the table version date shown next to every estimate.
	AsOf() string
}

PriceTable maps a resource type to a monthly list price in micro units. Implementations are static: no network lookups.

type Refusal

type Refusal struct {
	Code    string
	Address string
	Type    string
	Message string
}

Refusal is a typed policy refusal with a stable code.

func (Refusal) Error

func (r Refusal) Error() string

type ReleaseMaterial

type ReleaseMaterial struct {
	Sums   []byte
	Entity verify.SignedEntity
}

ReleaseMaterial is the checksum file of one release plus its Sigstore bundle. A bare .sig and .pem pair carries no transparency log proof, so a bundle is required.

func ParseReleaseBundle

func ParseReleaseBundle(sums, bundleJSON []byte) (ReleaseMaterial, error)

ParseReleaseBundle pairs the checksum file with a Sigstore bundle in its JSON form.

type ReleaseVerifier

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

ReleaseVerifier checks the keyless signature of the OpenTofu checksum file and then the archive against it.

func NewReleaseVerifier

func NewReleaseVerifier(version string, trusted root.TrustedMaterial, material MaterialSource) *ReleaseVerifier

NewReleaseVerifier binds the verifier to the pinned version, whose minor branch fixes the signing identity.

func (*ReleaseVerifier) Verify

func (v *ReleaseVerifier) Verify(ctx context.Context, archiveName, archivePath string) error

Verify implements SignatureVerifier. Anything missing fails closed with ErrSignatureUnverified.

type ResourceChange

type ResourceChange struct {
	Address string
	Type    string
	Action  string
}

ResourceChange is one entry of a rendered change set.

type Result

type Result struct {
	Step    Step
	Changes []Change
	Outputs map[string]string
	Log     string
	// PlanHash names the saved plan a plan produced or an apply ran.
	PlanHash string
	// StateVersion is the stored state version after the step.
	StateVersion int64
	// Partial means the apply failed but the state it reached was stored.
	Partial bool
	// Diverged means the new state could not be stored under the fence.
	Diverged bool
}

Result is the typed outcome of a step. Output is already redacted.

type RunDir

type RunDir struct {
	Root    string
	OnTmpfs bool
}

RunDir is the private host directory of one engine run. It holds the module, the plaintext state copy, the credential files and the plan; all of it lives on the host only for the run.

func NewRunDir

func NewRunDir(base, user string) (*RunDir, error)

NewRunDir creates a 0700 run dir under base and hands the shared subdirs to the step user.

func (*RunDir) Cleanup

func (r *RunDir) Cleanup()

Cleanup overwrites every regular file best effort, then removes the tree.

func (*RunDir) ModuleDir

func (r *RunDir) ModuleDir() string

ModuleDir is the read-only module location, outside the shared mount.

func (*RunDir) Shared

func (r *RunDir) Shared() string

Shared is the directory mounted into every step of the run.

func (*RunDir) StateDir

func (r *RunDir) StateDir() string

StateDir is where the plan step leaves the saved plan for show and apply.

type RunOutput

type RunOutput struct {
	Stdout    []byte
	Stderr    []byte
	Truncated bool
}

RunOutput is what one sandboxed step printed, each stream capped.

type Runner

type Runner interface {
	Run(ctx context.Context, spec SandboxSpec) (RunOutput, error)
}

Runner executes one sandboxed step. Tests swap in a fake so no container, binary or cloud is ever touched.

type SandboxInput

type SandboxInput struct {
	Runtime   string
	Image     string
	User      string
	Name      string
	Step      Step
	ModuleDir string
	// RunDir is the private per-run host directory; its work and state subdirs are shared by every step.
	RunDir     string
	TofuBinary string
	PluginDir  string
	Credential CredentialFile
	Network    NetworkPolicy
	Limits     SandboxLimits
	Env        map[string]string
}

SandboxInput describes one step. Nothing in it may carry a secret value.

type SandboxLimits

type SandboxLimits struct {
	MemoryMB   int
	CPUs       float64
	Pids       int
	WorkTmpMB  int
	StateTmpMB int
}

SandboxLimits bound one step. Values come from runtime settings; zero refuses. WorkTmpMB is the free space the run directory filesystem must have; StateTmpMB sizes /tmp.

type SandboxSpec

type SandboxSpec struct {
	Runtime      string
	Image        string
	Name         string
	User         string
	ReadOnlyRoot bool
	CapDrop      []string
	SecurityOpt  []string
	PidsLimit    int
	MemoryMB     int
	CPUs         string
	NetworkFlags []string
	Mounts       []Mount
	Tmpfs        []Tmpfs
	Env          []string
	Workdir      string
	Entrypoint   string
	Args         []string
}

SandboxSpec is the typed run spec for one step container.

func BuildSandboxSpec

func BuildSandboxSpec(in SandboxInput) (SandboxSpec, error)

BuildSandboxSpec validates the input and returns the hardened run spec.

func (SandboxSpec) Argv

func (s SandboxSpec) Argv() []string

Argv returns the full container command line, starting with the runtime binary.

type SavedPlan

type SavedPlan struct {
	Hash         string           `json:"-"`
	Plan         []byte           `json:"plan"`
	Changes      []ResourceChange `json:"changes"`
	StateVersion int64            `json:"state_version"`
	Destroy      bool             `json:"destroy"`
	CreatedAt    time.Time        `json:"-"`
}

SavedPlan is the reviewed plan of one stack. Changes are kept beside the bytes, sealed with them, so policy and cost are re-checked before any step runs.

type SavedPlanRunner

type SavedPlanRunner interface {
	Apply(ctx context.Context, req ApplyRequest) (Result, error)
	Destroy(ctx context.Context, req ApplyRequest) (Result, error)
}

SavedPlanRunner runs an approved saved plan; TofuEngine implements it.

type SettingsReader

type SettingsReader interface {
	Int(ctx context.Context, key string) int
	Bool(ctx context.Context, key string) bool
}

SettingsReader is the runtime settings surface the engine reads per run.

type SignatureVerifier

type SignatureVerifier interface {
	Verify(ctx context.Context, archiveName, archivePath string) error
}

SignatureVerifier checks the release signature of a downloaded archive.

type StateDB

type StateDB interface {
	GetCloudState(ctx context.Context, account, stack string) (store.CloudState, error)
	PutCloudState(ctx context.Context, lock store.CloudStateLock, expectVersion int64, sealed []byte, now time.Time) (int64, error)
	PutCloudPlan(ctx context.Context, p store.CloudPlan) error
	GetCloudPlan(ctx context.Context, account, stack string) (store.CloudPlan, error)
	DeleteCloudPlan(ctx context.Context, account, stack, hash string) error
	InsertCloudStateQuarantine(ctx context.Context, q store.CloudStateQuarantine) (int64, error)
	ListCloudStateQuarantine(ctx context.Context, account, stack string) ([]store.CloudStateQuarantine, error)
}

StateDB is the part of the store the state store needs.

type StateLocker

type StateLocker interface {
	AcquireCloudStateLock(ctx context.Context, account, stack, holder string, ttl time.Duration, now time.Time) (store.CloudStateLock, error)
	ReleaseCloudStateLock(ctx context.Context, lock store.CloudStateLock) error
}

StateLocker is the fenced lease part of the store.

type StateQuarantine

type StateQuarantine struct{ ID int64 }

StateQuarantine carries the id of the quarantine row an apply wrote; match it with errors.As.

func (*StateQuarantine) Error

func (q *StateQuarantine) Error() string

type StateStore

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

StateStore seals state before it reaches the DB. It never logs and has no method that serves state over an API.

func NewStateStore

func NewStateStore(db StateDB, keys KeyDeriver, maxBytes int64) (*StateStore, error)

NewStateStore needs the size cap from runtime settings; zero refuses.

func (*StateStore) DropPlan

func (s *StateStore) DropPlan(ctx context.Context, account, stack, hash string) error

DropPlan removes the saved plan if it is still the one with this hash.

func (*StateStore) Load

func (s *StateStore) Load(ctx context.Context, account, stack string) ([]byte, int64, error)

Load returns the plaintext state and its version. A stack with no state yet returns nil and version 0.

func (*StateStore) LoadPlan

func (s *StateStore) LoadPlan(ctx context.Context, account, stack string) (SavedPlan, error)

LoadPlan opens the saved plan and checks its bytes still match the recorded hash.

func (*StateStore) OpenQuarantine

func (s *StateStore) OpenQuarantine(q store.CloudStateQuarantine) ([]byte, error)

OpenQuarantine returns the plaintext of a quarantine row for an operator recovery step.

func (*StateStore) Quarantine

func (s *StateStore) Quarantine(ctx context.Context, account, stack string, fence int64, reason string, state []byte) (int64, error)

Quarantine seals state that could not be stored live and returns the row id. It takes no lease and no size cap, since the blob describes real resources and losing it would orphan them.

func (*StateStore) Quarantined

func (s *StateStore) Quarantined(ctx context.Context, account, stack string) ([]store.CloudStateQuarantine, error)

Quarantined lists the unresolved quarantine rows of a stack; any row means the stack must not run.

func (*StateStore) Save

func (s *StateStore) Save(ctx context.Context, lock store.CloudStateLock, expectVersion int64, state []byte) (int64, error)

Save seals and writes state under a live lease. expectVersion is the version Load returned.

func (*StateStore) SavePlan

func (s *StateStore) SavePlan(ctx context.Context, account, stack string, p SavedPlan) (string, error)

SavePlan seals the plan and replaces the stack's saved plan.

type StaticPrices

type StaticPrices struct {
	Date   string
	Prices map[string]int64
}

StaticPrices is an in-memory PriceTable.

func (StaticPrices) AsOf

func (s StaticPrices) AsOf() string

AsOf implements PriceTable.

func (StaticPrices) Monthly

func (s StaticPrices) Monthly(t string) (int64, bool)

Monthly implements PriceTable.

type Step

type Step string

Step names one engine operation.

const (
	StepPlan    Step = "plan"
	StepApply   Step = "apply"
	StepDestroy Step = "destroy"
)

The steps an engine can run.

type StringSettings

type StringSettings interface {
	String(ctx context.Context, key string) string
}

StringSettings is the string part of the runtime settings service.

type Tmpfs

type Tmpfs struct {
	Target  string
	Options string
}

Tmpfs is an in-memory mount private to the step.

type TofuConfig

type TofuConfig struct {
	Runtime   string
	Image     string
	User      string
	PluginDir string
	// WorkBase holds the private run dirs; prefer a tmpfs, since the plaintext state and plan
	// sit there for the run. A disk backed base is allowed but reported as a plan warning.
	WorkBase string
	// Live refreshes the sandbox knobs from runtime settings at the start of every run.
	Live    func(TofuConfig) TofuConfig
	Holder  string
	Network NetworkPolicy
	Limits  SandboxLimits
	Timeout func() time.Duration
	// PlanMaxAge caps how old a saved plan may be when it is applied; zero refuses every apply.
	PlanMaxAge func() time.Duration
	Policy     func() Policy
	Cost       func() CostPolicy
	Prices     PriceTable
	// ExistingSpend reports the account's current monthly micros; nil means zero.
	ExistingSpend func(ctx context.Context, account string) int64
}

TofuConfig holds the engine knobs. Funcs are read per run so runtime settings apply live.

func SettingsConfig

func SettingsConfig(cfg TofuConfig, get func() SettingsReader) TofuConfig

SettingsConfig fills the live knobs of a TofuConfig from runtime settings. A nil reader keeps every guard at its strictest value.

type TofuDeps

type TofuDeps struct {
	Runner Runner
	Binary BinaryEnsurer
	Locks  StateLocker
	State  *StateStore
	Creds  OracleResolver
}

TofuDeps are the collaborators; any nil one makes Plan fail with ErrNotConfigured.

type TofuEngine

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

TofuEngine is the OpenTofu Engine. Apply and destroy only ever run a saved, approved plan.

func NewTofuEngine

func NewTofuEngine(cfg TofuConfig, deps TofuDeps) *TofuEngine

NewTofuEngine builds the engine; missing pieces surface at run time, not here.

func (*TofuEngine) Apply

func (e *TofuEngine) Apply(ctx context.Context, req ApplyRequest) (Result, error)

Apply runs the saved plan whose hash the caller approved, never a fresh diff.

func (*TofuEngine) Destroy

func (e *TofuEngine) Destroy(ctx context.Context, req ApplyRequest) (Result, error)

Destroy runs a saved destroy plan; it needs the explicit confirmation and passes the destroy cap.

func (*TofuEngine) Plan

func (e *TofuEngine) Plan(ctx context.Context, spec ModuleSpec, cred CredentialHandle) (Result, error)

Plan implements Engine.

func (*TofuEngine) PlanDestroy

func (e *TofuEngine) PlanDestroy(ctx context.Context, spec ModuleSpec, cred CredentialHandle) (PlanResult, error)

PlanDestroy saves a destroy plan; only Destroy with an explicit confirmation can run it.

func (*TofuEngine) PlanDetailed

func (e *TofuEngine) PlanDetailed(ctx context.Context, spec ModuleSpec, cred CredentialHandle) (PlanResult, error)

PlanDetailed runs init, plan and show under the state lease, saves the sealed plan and returns it typed. The account is the credential handle id and the stack is the module name.

Jump to

Keyboard shortcuts

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