Documentation
¶
Overview ¶
Package iac turns multi-document YAML resource files into a plan of changes against a control plane and applies it through the ordinary REST API, so per-resource authorization applies to every item.
Index ¶
- Constants
- Variables
- func Build(docs []*Document, opts Options) ([]*Resource, []Issue)
- func CheckHashVersion(expected string) error
- func CheckPlanHash(expected string, plan Plan) error
- func CleanComposePath(p string) (string, error)
- func CleanSyncPath(p string) (string, error)
- func CloudPlannerInstalled() bool
- func ComposeCreated(res []*Resource, out ApplyResult) []string
- func ComposeEnvDigests(files []Source, project string) map[string]string
- func ComposeRefPaths(files []Source) []string
- func ComposeRefsEnabled() bool
- func IsCloudKind(k Kind) bool
- func IsDenied(err error) bool
- func IsFeatureOff(err error) bool
- func IsNotFound(err error) bool
- func IsSettingWeaken(c Change) bool
- func IsUnavailable(err error) bool
- func KindStability(k Kind) string
- func LeakedSecret(docs []byte, secrets map[string]string) (string, bool)
- func LedgerConflicts(p Plan) []string
- func LooksSecret(key, value string) bool
- func MassPruneBlocked(p Plan) bool
- func ParseDocuments(sources []Source) ([]*Document, []Issue)
- func PlanHashV1(p Plan) string
- func PlanValueMax() int
- func RemoveCompose(ctx context.Context, d Doer, name string) error
- func SchemaJSON() ([]byte, error)
- func SetCloudPlanner(p CloudPlanner)
- func SetCloudPolicy(c PolicyChecker)
- func SetComposeSource(fn func() ComposeLimits)
- func SetPlanHashKey(key []byte)
- func SetPlanValueSource(fn func() int)
- func SetPruneGuardSource(fn func() PruneGuard)
- func SetV1HashAcceptedSource(fn func() bool)
- func SplitComposeRefs(files []Source) (docs []Source, attachments map[string][]byte, issues []Issue)
- func StrictComposeCheck(data []byte, file string, declared map[string]string) (*compose.File, error)
- func ValidateStackLevel(scope StackLevel, project, environment string) error
- func ValidateStackName(name string) error
- func WithAllowWeaken(ctx context.Context) context.Context
- func WithCloudReport(ctx context.Context, rep *CloudReport) context.Context
- func WithLedger(ctx context.Context, l *Ledger) context.Context
- func WithStackScope(ctx context.Context, s StackScope) context.Context
- type Action
- type ApplyResult
- type Change
- type CloudApplier
- type CloudApplyRequest
- type CloudApplyResult
- type CloudApproval
- type CloudAttr
- type CloudChange
- type CloudDiff
- type CloudOutcome
- type CloudPlanner
- type CloudReadiness
- type CloudRefusal
- type CloudReport
- type CloudResource
- type CloudRun
- type CloudStackPlanner
- type ComposeBody
- type ComposeLimits
- type ComposeServiceRow
- type CoverageRow
- type CoverageStatus
- type Document
- type Doer
- type DriftPolicy
- type ExportFile
- type ExportOptions
- type ExportResult
- type FieldChange
- type GitMeta
- type Issue
- type ItemResult
- type Kind
- type Ledger
- type LedgerEntry
- type LedgerRef
- type LedgerUpdate
- type Options
- type Plan
- type PolicyChecker
- type PruneGuard
- type Resource
- type Revision
- type RevisionStatus
- type Source
- type Stack
- type StackDeleteMode
- type StackLevel
- type StackLock
- type StackScope
- type StackSpec
- type StackSync
- type State
- type StatusError
- type Summary
Constants ¶
const ( StatusApplied = "applied" StatusFailed = "failed" StatusDenied = "denied" StatusSkipped = "skipped" StatusNoop = "noop" )
Item outcomes.
const ( // CodeItemFailed is the fallback for a failure with no more specific code. CodeItemFailed = "item_failed" // CodePermissionDenied means the token may not read or write the resource. CodePermissionDenied = "permission_denied" CodeUnavailable = "unavailable" // CodeReadFailed means the live state could not be read. CodeReadFailed = "read_failed" // CodeProtectedResource means the resource is protected from this change. CodeProtectedResource = "protected_resource" // CodeImmutableField means a declared field cannot change in place. CodeImmutableField = "immutable_field" // CodeSyncedExternally means the resource is owned by an outside source. CodeSyncedExternally = "synced_externally" )
Plan item codes, set on Change.Code when an item cannot be planned.
const ( CodeRefProjectMissing = "ref_project_missing" CodeRefEnvironmentMissing = "ref_environment_missing" CodeRefAppMissing = "ref_app_missing" CodeRefSecretMissing = "ref_secret_missing" )
Reference codes, for a declared resource that points at one that is absent.
const ( CodeSchemaUnknownField = "schema_unknown_field" CodeSchemaVersionUnsupported = "schema_version_unsupported" CodeOwnershipConflict = "ownership_conflict" CodePlanStale = "plan_stale" CodePlanHashVersion = "plan_hash_version" CodeStackLocked = "stack_locked" CodeStackSourceSync = "stack_source_sync" CodePruneGuard = "prune_guard" CodeApplyDisabled = "apply_disabled" CodeInvalidRequest = "invalid_request" CodeInvalidDocument = "invalid_document" // CodeInvalidName means a resource name breaks the rule the API enforces at creation. CodeInvalidName = "invalid_name" )
Document and request codes, set outside planning (schema, stacks, apply).
const ( // CodeComposePathInvalid means spec.compose.path is not a clean relative path. CodeComposePathInvalid = "compose_path_invalid" // CodeComposeRefMissing means a referenced compose file was not sent with the request. CodeComposeRefMissing = "compose_ref_missing" // CodeComposeTooLarge means a compose file or the attachment total is over its cap. CodeComposeTooLarge = "compose_too_large" // CodeComposeTooManyFiles means the request holds more compose files than the cap. CodeComposeTooManyFiles = "compose_too_many_files" // CodeComposeModeConflict means an App sets both spec.compose and spec.service. CodeComposeModeConflict = "compose_mode_conflict" // CodeComposeUnsupportedKey means a compose file uses a key strict mode refuses, such as build or env_file. CodeComposeUnsupportedKey = "compose_unsupported_key" // CodeComposeRejected means a compose file breaks a strict guard rule, such as privileged or a host bind. CodeComposeRejected = "compose_rejected" // CodeComposeSecretLiteral means a compose file holds what looks like a literal secret. CodeComposeSecretLiteral = "compose_secret_literal" // CodeComposeVarMissing means a compose ${VAR} is not declared in spec.compose.env. CodeComposeVarMissing = "compose_var_missing" // CodeComposeNoDeployUnsupported means no_deploy was asked for a compose App, which deploys on save. CodeComposeNoDeployUnsupported = "compose_no_deploy_unsupported" // CodeComposeApplyFailed means a step after a compose deploy failed; a first deploy is removed again. CodeComposeApplyFailed = "compose_apply_failed" )
Compose reference codes (ADR 081).
const ( // CodeApprovalPending means a cloud plan would replace the saved engine plan of a pending approval. CodeApprovalPending = "approval_pending" // CodePlanSuperseded means a later plan replaced the saved engine plan an approval named. CodePlanSuperseded = "plan_superseded" // CodeInterrupted means the control plane stopped while the plan job ran. CodeInterrupted = "interrupted" // CodePlanJobNotFound means no plan job has this id for the stack, or it was pruned. CodePlanJobNotFound = "plan_job_not_found" // CodePlanTimeout means the plan job ran past cloud.engine_timeout_seconds. CodePlanTimeout = "plan_timeout" )
Async cloud plan job and approval race codes.
const ( // CodeSyncRepoUnreachable means the sync repository could not be fetched. CodeSyncRepoUnreachable = "sync_repo_unreachable" // CodeSyncPathInvalid means the sync path leaves the checkout or holds a symlink. CodeSyncPathInvalid = "sync_path_invalid" // CodeSyncLimitsExceeded means the repository or its files passed a sync limit. CodeSyncLimitsExceeded = "sync_limits_exceeded" // CodeSyncPlanFailed means the synced documents could not be planned. CodeSyncPlanFailed = "sync_plan_failed" // CodeSyncSecretInRepo means a synced document holds a literal secret value. CodeSyncSecretInRepo = "sync_secret_in_repo" // CodeSyncDiskLow means free disk was below stacks.sync_min_free_mb, so nothing was fetched. CodeSyncDiskLow = "sync_disk_low" // CodeSyncApplyFailed means a sync apply was refused or failed; the stack is unchanged. CodeSyncApplyFailed = "sync_apply_failed" )
Git sync codes. They never carry repository content or credentials.
const ( OpAdd = "add" OpChange = "change" OpRemove = "remove" OpKeep = "keep" )
Field operations shown in a plan.
const ( CodeApprovalRequired = "approval_required" CodeDestroyNotConfirmed = "destroy_not_confirmed" CodeCloudPlanExpired = "cloud_plan_expired" CodeStateDiverged = "state_diverged" )
Frozen codes of the cloud apply path.
const ( StabilityStable = "stable" StabilityBeta = "beta" )
Kind stability levels published in the schema as x-stability.
const DefaultDriftPolicy = DriftWarn
DefaultDriftPolicy is warn so hand edits keep working until an owner opts in.
const HashV2Prefix = "v2:"
HashV2Prefix marks a plan hash computed by planHashV2.
const (
LabelManagedBy = "managed-by"
)
Labels with a meaning of their own.
const MaxSyncIntervalSeconds = 86400
MaxSyncIntervalSeconds bounds a per stack interval to one day.
const MinSecretMatchLen = 4
MinSecretMatchLen is the shortest secret value matched by substring. Shorter values would match ordinary document text; plans warn about them instead.
const NodeTaintWeakenReason = "weakens a protected taint; allowed by allow_weaken"
NodeTaintWeakenReason starts the reason of a Node change that drops or loosens a protected taint under allow_weaken, so reviewers can find it.
const SchemaVersion = 1
SchemaVersion is the only resource document version this package accepts.
const SettingWeakenReason = "weakens a security protection; allowed by allow_weaken"
SettingWeakenReason starts the reason of every Setting change that weakens a protection under allow_weaken, so reviewers and the audit can find it.
const ShortSecretWarning = "secret value too short to be checked against the documents"
ShortSecretWarning is the plan warning for values under MinSecretMatchLen.
Variables ¶
var ( ErrStackPinned = errors.New("stack is pinned; only a rollback to the pinned revision may apply") ErrStackLocked = errors.New("stack is locked by another apply") ErrLedgerConflict = errors.New("resource is owned by another stack") ErrPruneNotAllowed = errors.New("prune needs both the manifest request and the stack allow_prune setting") )
Sentinel errors the store and API map to 409 or 422 responses.
var AllCodes = []string{ CodeItemFailed, CodePermissionDenied, CodeUnavailable, CodeReadFailed, CodeProtectedResource, CodeImmutableField, CodeSyncedExternally, CodeRefProjectMissing, CodeRefEnvironmentMissing, CodeRefAppMissing, CodeRefSecretMissing, CodeSchemaUnknownField, CodeSchemaVersionUnsupported, CodeOwnershipConflict, CodePlanStale, CodePlanHashVersion, CodeStackLocked, CodeStackSourceSync, CodePruneGuard, CodeApplyDisabled, CodeInvalidRequest, CodeInvalidDocument, CodeInvalidName, CodeApprovalPending, CodePlanSuperseded, CodeInterrupted, CodePlanJobNotFound, CodePlanTimeout, CodeSyncRepoUnreachable, CodeSyncPathInvalid, CodeSyncLimitsExceeded, CodeSyncPlanFailed, CodeComposePathInvalid, CodeComposeRefMissing, CodeComposeTooLarge, CodeComposeTooManyFiles, CodeComposeModeConflict, CodeComposeUnsupportedKey, CodeComposeRejected, CodeComposeSecretLiteral, CodeComposeVarMissing, CodeComposeNoDeployUnsupported, CodeComposeApplyFailed, CodeSyncSecretInRepo, CodeSyncDiskLow, CodeSyncApplyFailed, }
AllCodes lists every frozen code, for docs and guard tests.
ErrCloudUnavailable marks a planner error caused by missing configuration (a stored connection, an engine setting, a binary source); the item fails as unavailable.
var ErrPlanChanged = errors.New("the plan changed since it was reviewed; plan again")
ErrPlanChanged means live state moved between the plan a user reviewed and the apply that followed.
var ErrPlanHashVersion = errors.New(CodePlanHashVersion + ": the plan hash is from an older release; plan again")
ErrPlanHashVersion means the submitted hash has the old unkeyed shape and the install no longer accepts it; plan again to get a current hash.
var Kinds = []Kind{KindProject, KindEnvironment, KindTag, KindCloudAccount, KindCloudNetwork, KindCloudInstance, KindCloudBucket, KindNode, KindSetting, KindDatabase, KindApp, KindDomain, KindLoadBalancer, KindPipeline, KindAlertRule}
Kinds lists every kind in the order changes are applied.
Functions ¶
func Build ¶
Build validates every document (schema first, then semantics) and turns them into canonical resources. It returns no resources when any issue exists, so nothing is planned from a partly valid input.
func CheckHashVersion ¶
CheckHashVersion refuses a v1 shaped hash while the setting disallows it. It needs no plan, so a caller can run it before any short circuit.
func CheckPlanHash ¶
CheckPlanHash compares a submitted hash with the recomputed plan. Empty means no pin. A v1 shaped hash passes only while the setting allows it.
func CleanComposePath ¶
CleanComposePath validates a compose path and returns its cleaned form. It never touches the disk; callers refuse symlinks where they read files.
func CleanSyncPath ¶
CleanSyncPath returns the slash path under the repository root; "" is the root.
func CloudPlannerInstalled ¶
func CloudPlannerInstalled() bool
CloudPlannerInstalled reports whether a planner and a policy checker are both set.
func ComposeCreated ¶
func ComposeCreated(res []*Resource, out ApplyResult) []string
ComposeCreated lists the compose Apps an apply deployed for the first time, so a caller that cannot record their ownership can remove them.
func ComposeEnvDigests ¶
ComposeEnvDigests returns the env digest of every compose App the files declare, so a stack can record what its last applied revision set.
func ComposeRefPaths ¶
ComposeRefPaths lists the cleaned compose paths the documents reference.
func ComposeRefsEnabled ¶
func ComposeRefsEnabled() bool
ComposeRefsEnabled reports the live iac.compose_refs gate.
func IsCloudKind ¶
IsCloudKind reports whether a kind is provisioned through the cloud engine.
func IsFeatureOff ¶
IsFeatureOff reports whether err is the 404 a gated endpoint answers while its beta feature is disabled.
func IsSettingWeaken ¶
IsSettingWeaken reports whether c is a Setting change that weakens a protection.
func IsUnavailable ¶
IsUnavailable reports whether err says the feature is not configured.
func KindStability ¶
KindStability returns the declared stability of a kind; an unlisted kind is stable.
func LeakedSecret ¶
LeakedSecret returns the name of a secret whose value appears in docs, so a revision can be refused before it is stored. Values under MinSecretMatchLen are skipped.
func LedgerConflicts ¶
LedgerConflicts returns the keys a plan refused for ownership reasons.
func LooksSecret ¶
LooksSecret is the literal detector resolveLiteral applies to spec env, exported so compose attachment scans share it instead of copying patterns.
func MassPruneBlocked ¶
MassPruneBlocked reports whether the guard held back any delete.
func ParseDocuments ¶
ParseDocuments splits sources into documents and decodes each envelope. It reports YAML syntax errors and missing kind or name, nothing deeper; Validate does the schema and semantic checks.
func PlanHashV1 ¶
PlanHashV1 recomputes the v1 hash of a plan's changes.
func PlanValueMax ¶
func PlanValueMax() int
PlanValueMax is the longest before or after value a plan shows.
func RemoveCompose ¶
RemoveCompose tears a compose App down through its delete path. It never asks for volumes=true, so named volumes are kept.
func SchemaJSON ¶
SchemaJSON returns the published JSON Schema: the resource envelope schema with the app.yaml schema definitions merged in unchanged, except that an env value may also be a { secretRef } or a { from: { database, field } } object.
func SetCloudPlanner ¶
func SetCloudPlanner(p CloudPlanner)
SetCloudPlanner installs the planner; nil restores the unconfigured failure.
func SetCloudPolicy ¶
func SetCloudPolicy(c PolicyChecker)
SetCloudPolicy installs the policy checker; nil disables the extra checks.
func SetComposeSource ¶
func SetComposeSource(fn func() ComposeLimits)
SetComposeSource makes the gate and caps follow runtime settings.
func SetPlanHashKey ¶
func SetPlanHashKey(key []byte)
SetPlanHashKey sets the HMAC key for plan hashes; the caller derives it from the server master key so hashes are per install.
func SetPlanValueSource ¶
func SetPlanValueSource(fn func() int)
SetPlanValueSource makes PlanValueMax follow a live setting.
func SetPruneGuardSource ¶
func SetPruneGuardSource(fn func() PruneGuard)
SetPruneGuardSource makes new ledgers follow a live setting.
func SetV1HashAcceptedSource ¶
func SetV1HashAcceptedSource(fn func() bool)
SetV1HashAcceptedSource follows the iac.v1_hash_accepted setting live; unset means v1 hashes are refused.
func SplitComposeRefs ¶
func SplitComposeRefs(files []Source) (docs []Source, attachments map[string][]byte, issues []Issue)
SplitComposeRefs separates compose files referenced by App documents from resource documents, so a compose file in a stack folder is never parsed as a document. Source names are paths relative to the document set root.
func StrictComposeCheck ¶
func StrictComposeCheck(data []byte, file string, declared map[string]string) (*compose.File, error)
StrictComposeCheck runs the strict parser, the secret literal scan and the declared variable check; errors carry codes, names and lines, never values.
func ValidateStackLevel ¶
func ValidateStackLevel(scope StackLevel, project, environment string) error
ValidateStackLevel checks the project and environment fit the scope.
func ValidateStackName ¶
ValidateStackName checks the stack name shape.
func WithAllowWeaken ¶
WithAllowWeaken lets the Setting plan confirm a weakening change. Only the API sets it, after it has checked the caller is a human root session.
func WithCloudReport ¶
func WithCloudReport(ctx context.Context, rep *CloudReport) context.Context
WithCloudReport makes an apply record its engine runs into rep.
func WithLedger ¶
WithLedger makes Load and the planner enforce l. It is a server-side value; nothing a client sends can set it.
func WithStackScope ¶
func WithStackScope(ctx context.Context, s StackScope) context.Context
WithStackScope returns ctx carrying the stack apply scope.
Types ¶
type ApplyResult ¶
type ApplyResult struct {
Plan Plan `json:"plan"`
Results []ItemResult `json:"results"`
Applied int `json:"applied"`
Failed int `json:"failed"`
Skipped int `json:"skipped"`
}
ApplyResult is the outcome of an apply.
func Apply ¶
func Apply(ctx context.Context, d Doer, res []*Resource, opts Options, expectedHash string) (ApplyResult, error)
Apply plans and executes resources through doer. Validation and reading happen before any write; a plan holding an error item applies nothing unless ContinueOnError is set. Items run in dependency order and each goes through the ordinary endpoint, so a denied write is reported on its own item and the rest proceed only when ContinueOnError is set.
func (ApplyResult) OK ¶
func (r ApplyResult) OK() bool
OK reports whether every item that had to change did.
type Change ¶
type Change struct {
Kind Kind `json:"kind"`
Name string `json:"name"`
Scope string `json:"scope,omitempty"`
Action Action `json:"action"`
Fields []FieldChange `json:"fields,omitempty"`
Kept []FieldChange `json:"kept,omitempty"`
Warnings []string `json:"warnings,omitempty"`
// Services are display only compose preview rows; the plan hash never reads them.
Services []ComposeServiceRow `json:"services,omitempty"`
Reason string `json:"reason,omitempty"`
// Code is the frozen machine code of a failed item; empty otherwise.
Code string `json:"code,omitempty"`
// DependsOn lists the resources this item reads from, applied first.
DependsOn []string `json:"dependsOn,omitempty"`
Denied bool `json:"denied,omitempty"`
// LiveID is the live identifier a ledger records; it never leaves the process.
LiveID string `json:"-"`
File string `json:"file,omitempty"`
Line int `json:"line,omitempty"`
// CloudPlanHash names the sealed engine plan a cloud item runs; approval binds to it.
CloudPlanHash string `json:"cloudPlanHash,omitempty"`
// ComposeDigest covers a compose App's file bytes and inputs; it never leaves the process.
ComposeDigest string `json:"-"`
}
Change is one line of a plan.
type CloudApplier ¶
type CloudApplier interface {
ApplyCloud(ctx context.Context, req CloudApplyRequest) (CloudApplyResult, error)
}
CloudApplier runs a saved engine plan; a planner with an engine implements it.
type CloudApplyRequest ¶
type CloudApplyRequest struct {
Stack string
Target CloudResource
Group []CloudResource
PlanHash string
Destroy bool
}
CloudApplyRequest asks the engine to run one approved saved plan of a stack.
type CloudApplyResult ¶
CloudApplyResult reports a state the engine could not store; it never carries state.
type CloudApproval ¶
CloudApproval is the approved plan an apply runs. Pins map an item key to the approved change, so apply never re-plans and so never replaces the saved engine plan.
type CloudChange ¶
CloudChange is one entry handed to a PolicyChecker.
type CloudDiff ¶
type CloudDiff struct {
Action string
// Type is the provider resource type, used by policy checks only.
Type string
Attrs []CloudAttr
// PlanHash is the sealed engine plan this diff came from.
PlanHash string
}
CloudDiff is a planner answer: action is create, update, delete or noop.
type CloudOutcome ¶
CloudOutcome is the answer for one document of a stack plan.
type CloudPlanner ¶
type CloudPlanner interface {
PlanCloud(ctx context.Context, r CloudResource) (CloudDiff, error)
}
CloudPlanner computes the proposed change for a cloud document. The engine implements it; with none set every cloud item fails loudly.
type CloudReadiness ¶
type CloudReadiness interface {
CloudReady() bool
}
CloudReadiness is optional on a planner: false means it has no engine yet, so even record-only kinds such as CloudAccount must not report unchanged.
type CloudRefusal ¶
CloudRefusal is a policy verdict with a frozen code. An empty Address applies to every delete item (the destroy cap).
type CloudReport ¶
type CloudReport struct {
// contains filtered or unexported fields
}
CloudReport collects the engine runs of one apply.
func (*CloudReport) Runs ¶
func (r *CloudReport) Runs() []CloudRun
Runs returns a copy of the recorded runs.
type CloudResource ¶
CloudResource is what a planner is asked about, taken from a document.
type CloudRun ¶
type CloudRun struct {
PlanHash string
Items []string
Diverged bool
QuarantineID int64
Failed bool
}
CloudRun is one engine run of an apply, for events: names and ids only.
type CloudStackPlanner ¶
type CloudStackPlanner interface {
PlanCloudStack(ctx context.Context, stack string, rs []CloudResource) []CloudOutcome
}
CloudStackPlanner plans every cloud document of one stack together, so documents that refer to each other land in one module. The outcomes line up with the input order.
type ComposeBody ¶
ComposeBody is sent as the raw compose file instead of JSON. Env feeds ${VAR} interpolation on the server and never reaches the stored revision.
type ComposeLimits ¶
ComposeLimits are the live gate and caps for compose references.
type ComposeServiceRow ¶
type ComposeServiceRow struct {
Service string `json:"service"`
Action Action `json:"action"`
Image string `json:"image,omitempty"`
}
ComposeServiceRow is one display only preview row of a compose App.
type CoverageRow ¶
type CoverageRow struct {
Kind Kind
Feature string
Status CoverageStatus
// Code is the frozen machine code of the rejection, empty when the
// rejection is a plain builder message identified by Reason.
Code string
// Reason is the rejection text a user sees (a substring of it).
Reason string
Probe string
}
CoverageRow is one feature of a kind. A not-yet row names the rejection a user sees when they try it; Probe is a minimal document that triggers it.
func CoverageMatrix ¶
func CoverageMatrix() []CoverageRow
CoverageMatrix returns a copy of the matrix, ordered by kind then row.
type CoverageStatus ¶
type CoverageStatus string
CoverageStatus tells whether a product feature can be written in files.
const ( CoverageInFiles CoverageStatus = "in_files" CoverageNotYet CoverageStatus = "not_in_files_yet" )
Coverage statuses of a matrix row.
type Document ¶
type Document struct {
File string
Line int
Kind Kind
Name string
Labels map[string]string
Root *yaml.Node
SpecNode *yaml.Node
}
Document is one parsed YAML document with its envelope decoded.
func FilterProject ¶
FilterProject keeps the documents that belong to one project: the project itself, its environments, apps and databases, the domains, load balancers, pipelines and alert rules of those apps, and the tags those apps use.
type Doer ¶
Doer performs one JSON request against the control plane REST API. The CLI implements it over HTTP with the caller's token; the server implements it in process with the caller's own credentials, so per resource authorization applies to every call either way.
type DriftPolicy ¶
type DriftPolicy string
DriftPolicy says what happens when live state diverges from the stack.
const ( DriftWarn DriftPolicy = "warn" DriftLock DriftPolicy = "lock" )
Drift policies; revert is deliberately not offered.
func ParseDriftPolicy ¶
func ParseDriftPolicy(s string) (DriftPolicy, error)
ParseDriftPolicy maps an empty value to the default and rejects unknown ones.
type ExportFile ¶
type ExportFile struct {
Name string `json:"name"`
Kind Kind `json:"kind"`
Content string `json:"content"`
}
ExportFile is one exported document.
type ExportOptions ¶
type ExportOptions struct {
Project string
App string
// Database and Node each export that one resource alone.
Database string
Node string
// Settings exports only the saved, non-sensitive runtime settings.
Settings bool
// IncludeEnvValues writes literal env values; when false every value
// becomes a ${{ env.NAME }} placeholder.
IncludeEnvValues bool
}
ExportOptions select what to export.
type ExportResult ¶
type ExportResult struct {
Files []ExportFile `json:"files"`
Warnings []string `json:"warnings,omitempty"`
}
ExportResult is the exported documents in stable order plus warnings for live settings the documents cannot express.
func Export ¶
func Export(ctx context.Context, d Doer, opts ExportOptions) (ExportResult, error)
Export reads live state and renders it as documents. Output is stable: no timestamps or generated ids, sorted keys and a fixed document order.
func (ExportResult) Join ¶
func (r ExportResult) Join() string
Join concatenates exported files into one multi-document stream.
type FieldChange ¶
type FieldChange struct {
Path string `json:"path"`
Op string `json:"op"`
Old string `json:"old,omitempty"`
New string `json:"new,omitempty"`
}
FieldChange is one leaf difference. Values under env are never shown.
type GitMeta ¶
type GitMeta struct {
Repo string `json:"git_repo,omitempty"`
Ref string `json:"git_ref,omitempty"`
SHA string `json:"git_sha,omitempty"`
CIRunURL string `json:"ci_run_url,omitempty"`
}
GitMeta links a revision to the commit and CI run that produced it.
type Issue ¶
type Issue struct {
File string `json:"file,omitempty"`
Path string `json:"path,omitempty"`
Line int `json:"line"`
Message string `json:"message"`
// Code is a frozen machine code when the issue has one.
Code string `json:"code,omitempty"`
}
Issue is one validation problem, located by file, line and dotted path.
func ComposeStrictIssues ¶
ComposeStrictIssues turns a strict check error into coded issues. An error that is not a strict refusal gets a fixed message, since parser text can quote content.
func SyncSecretIssue ¶
SyncSecretIssue returns the first issue that refused a literal secret, so a sync can report its file and line without the value.
type ItemResult ¶
type ItemResult struct {
Change
Status string `json:"status"`
Error string `json:"error,omitempty"`
}
ItemResult is one plan item's outcome.
type Kind ¶
type Kind string
Kind names a resource document type.
const ( KindProject Kind = "Project" KindEnvironment Kind = "Environment" KindTag Kind = "Tag" KindCloudAccount Kind = "CloudAccount" KindCloudNetwork Kind = "CloudNetwork" KindCloudInstance Kind = "CloudInstance" KindCloudBucket Kind = "CloudBucket" KindNode Kind = "Node" KindSetting Kind = "Setting" KindDatabase Kind = "Database" KindApp Kind = "App" KindDomain Kind = "Domain" KindLoadBalancer Kind = "LoadBalancer" KindPipeline Kind = "Pipeline" KindAlertRule Kind = "AlertRule" )
Resource kinds, in dependency order.
const KindStack Kind = "Stack"
KindStack is the optional stack document. It is not in Kinds because it configures the apply instead of describing a resource.
type Ledger ¶
type Ledger struct {
StackID string
StackName string
// Scope is the stack scope; empty means project.
Scope StackLevel
// ScopeProject is the stack's own project; an admin bound it to the stack,
// so declaring it claims it without an explicit adopt.
ScopeProject string
// Owned maps resource keys this stack owns to their entries.
Owned map[string]LedgerEntry
// Foreign maps keys owned by some other stack to that stack's id.
Foreign map[string]string
// Adopt lets the stack claim existing resources no stack owns.
Adopt bool
// AllowMassPrune confirms a prune above the guard thresholds.
AllowMassPrune bool
Guard PruneGuard
}
Ledger is the stack ownership view a plan is checked against (ADR 042). With a ledger, ownership and prune come from it alone, never from tags.
func NewInstallLedger ¶
func NewInstallLedger(stackID, stackName string, owned []LedgerEntry) *Ledger
NewInstallLedger builds the view for an install stack, which may own only Node and Setting documents and has no project to claim.
func NewLedger ¶
func NewLedger(stackID, stackName, scopeProject string, owned []LedgerEntry) *Ledger
NewLedger builds the view for one stack from its own ledger rows.
type LedgerEntry ¶
type LedgerEntry struct {
StackID string `json:"stack_id"`
Kind Kind `json:"kind"`
Key string `json:"key"`
LiveID string `json:"live_id"`
SinceRevision int `json:"since_revision"`
}
LedgerEntry records the single stack that owns a resource. Key is the resourceKey (kind/scope/name), unique per kind across all stacks.
type LedgerRef ¶
LedgerRef is one (kind, key) whose owner a caller must look up.
func LedgerRefs ¶
LedgerRefs lists every key the plan checks ownership of: each resource plus the parent app of Domain, LoadBalancer, Pipeline and AlertRule documents.
type LedgerUpdate ¶
type LedgerUpdate struct {
Claim []LedgerEntry
Release []LedgerEntry
}
LedgerUpdate is what one apply changes in the ledger.
func LedgerChanges ¶
func LedgerChanges(stackID string, rev int, res []*Resource, out ApplyResult) LedgerUpdate
LedgerChanges derives claims and releases from an apply. Only declared resources are claimed, and nothing is claimed from a plan refused for errors.
type Options ¶
type Options struct {
// Vars resolve ${{ env.NAME }} placeholders.
Vars map[string]string
// Source names this apply source; apps it creates carry a managed-by
// tag and only those are ever pruned.
Source string
// Secrets maps "NAME" or "app/NAME" to a value to store at apply time.
// Values never appear in a plan, result or export.
Secrets map[string]string
// Project limits prune to managed apps of this project, matching the
// project filter applied to the files.
Project string
// BelowRoot is set by a caller whose token is under the root tier; job
// writes then fail the plan instead of stopping partway.
BelowRoot bool
// Prune deletes managed resources absent from the files.
Prune bool
// NoDeploy skips the restart that applies an env change to a running app.
NoDeploy bool
// ContinueOnError keeps applying after an item fails.
ContinueOnError bool
// Cloud is the approved cloud plan; without it every cloud write is refused.
Cloud *CloudApproval
// Attachments holds referenced compose files by cleaned relative path.
Attachments map[string][]byte
// ComposeEnvApplied maps a compose App to the env digest its stack last
// applied, since a compose revision never stores env values.
ComposeEnvApplied map[string]string
// ConfirmDestroy is set server side when the caller typed the stack name;
// a prune never removes a compose App without it.
ConfirmDestroy bool
}
Options carry apply-time inputs that never live in a resource file.
type Plan ¶
type Plan struct {
Source string `json:"source,omitempty"`
Prune bool `json:"prune,omitempty"`
Changes []Change `json:"changes"`
Summary Summary `json:"summary"`
Hash string `json:"hash"`
// Warnings are plan-wide notes; the hash never reads them.
Warnings []string `json:"warnings,omitempty"`
}
Plan is the ordered set of changes needed to reach the desired state.
func PlanForContext ¶
PlanForContext is PlanFor with a context that cancels or times out the cloud engine calls.
type PolicyChecker ¶
type PolicyChecker interface {
CheckCloud(changes []CloudChange) []CloudRefusal
}
PolicyChecker judges a whole cloud change set (cost, IAM, protected delete, destroy cap).
type PruneGuard ¶
PruneGuard bounds how much of a stack one prune may delete without an explicit confirmation.
func PruneGuardFromEnv ¶
func PruneGuardFromEnv() PruneGuard
PruneGuardFromEnv reads APP_STACK_PRUNE_MAX_PERCENT and APP_STACK_PRUNE_MAX_COUNT; zero is valid and means any prune needs the flag.
type Resource ¶
type Resource struct {
Kind Kind
Name string
Scope string
Doc *Document
Fields map[string]any
// SecretRefs are app env names backed by the secrets store.
SecretRefs []string
// ExistingSecrets are SecretRefs that must already be in the store.
ExistingSecrets []string
Warnings []string
// ComposeDigest is set for compose Apps and feeds the plan hash.
ComposeDigest string
// contains filtered or unexported fields
}
Resource is one desired object in canonical form, ready to compare with live state.
type Revision ¶
type Revision struct {
StackID string `json:"stack_id"`
Number int `json:"number"`
Status RevisionStatus `json:"status"`
PlanHash string `json:"plan_hash"`
PlanJSON []byte `json:"plan,omitempty"`
RenderedDocs []byte `json:"rendered_docs,omitempty"`
RollbackOf int `json:"rollback_of,omitempty"`
IdempotencyKey string `json:"idempotency_key,omitempty"`
Actor string `json:"actor"`
TokenID string `json:"token_id,omitempty"`
Git GitMeta `json:"git"`
CreatedAt time.Time `json:"created_at"`
FinishedAt *time.Time `json:"finished_at,omitempty"`
ResultJSON []byte `json:"result,omitempty"`
}
Revision is one numbered apply of a stack. RenderedDocs holds documents after env substitution only; secret values are never part of it.
type RevisionStatus ¶
type RevisionStatus string
RevisionStatus is the lifecycle of one stack apply.
const ( RevisionPendingApproval RevisionStatus = "pending_approval" RevisionApplying RevisionStatus = "applying" RevisionApplied RevisionStatus = "applied" RevisionPartial RevisionStatus = "partial" RevisionFailed RevisionStatus = "failed" RevisionSuperseded RevisionStatus = "superseded" )
Revision statuses, in lifecycle order.
func (RevisionStatus) CanTransition ¶
func (s RevisionStatus) CanTransition(next RevisionStatus) bool
CanTransition reports whether a revision may move from s to next.
func (RevisionStatus) Terminal ¶
func (s RevisionStatus) Terminal() bool
Terminal statuses never change again, except applied becoming superseded.
func (RevisionStatus) Valid ¶
func (s RevisionStatus) Valid() bool
Valid reports whether s is a known status.
type Stack ¶
type Stack struct {
ID string `json:"id"`
Name string `json:"name"`
ProjectID string `json:"project_id"`
EnvironmentID string `json:"environment_id,omitempty"`
Scope StackLevel `json:"scope,omitempty"`
AllowPrune bool `json:"allow_prune"`
DriftPolicy DriftPolicy `json:"drift_policy"`
PinnedRevision int `json:"pinned_revision,omitempty"` // 0 means not pinned
RequireApproval bool `json:"require_approval"`
CreatedAt time.Time `json:"created_at"`
CreatedBy string `json:"created_by"`
}
Stack is the server-side stack object. Settings here are admin-owned; a manifest can request but never grant them.
func (*Stack) CheckPin ¶
CheckPin returns ErrStackPinned unless the apply is a rollback to the pin. rollbackOf is 0 for an ordinary apply.
func (*Stack) PruneAllowed ¶
PruneAllowed needs both sides so a manifest cannot grant itself prune.
type StackDeleteMode ¶
type StackDeleteMode string
StackDeleteMode picks what deleting a stack does to its resources.
const ( // StackForget releases the ledger and leaves every resource in place. StackForget StackDeleteMode = "forget" // StackDestroy deletes ledger apps, and databases only with delete_data; never from CI. StackDestroy StackDeleteMode = "destroy" )
func ParseStackDeleteMode ¶
func ParseStackDeleteMode(s string) (StackDeleteMode, error)
ParseStackDeleteMode defaults to forget, the mode that cannot lose data.
type StackLevel ¶
type StackLevel string
StackLevel says whether a stack belongs to one project or to the install.
const ( LevelProject StackLevel = "project" LevelInstall StackLevel = "install" )
Stack scopes; an empty scope means project.
func ParseStackLevel ¶
func ParseStackLevel(s string) (StackLevel, error)
ParseStackLevel maps an empty value to project and rejects unknown ones.
type StackLock ¶
type StackLock struct {
StackID string `json:"stack_id"`
Holder string `json:"holder"`
Revision int `json:"revision"`
ExpiresAt time.Time `json:"expires_at"`
}
StackLock is the per-stack lease. Its length comes from APP_STACK_LOCK_TTL.
type StackScope ¶
StackScope is the apply context a stack handler attaches to loopback sub-requests. IAM trusts only this server-side value, never a header.
func StackScopeFrom ¶
func StackScopeFrom(ctx context.Context) (StackScope, bool)
StackScopeFrom returns the stack apply scope, if the request runs inside one.
type StackSpec ¶
type StackSpec struct {
Scope StackLevel `json:"scope,omitempty" yaml:"scope,omitempty"`
Project string `json:"project,omitempty" yaml:"project,omitempty"`
Environment string `json:"environment,omitempty" yaml:"environment,omitempty"`
Prune bool `json:"prune,omitempty" yaml:"prune,omitempty"`
Drift DriftPolicy `json:"drift,omitempty" yaml:"drift,omitempty"`
}
StackSpec is the spec of a kind: Stack document.
type StackSync ¶
type StackSync struct {
RepoURL string `json:"repo_url"`
Branch string `json:"branch"`
Path string `json:"path,omitempty"`
// CredentialRef names a stored credential ("app:<name>"), never a secret value.
CredentialRef string `json:"credential_ref,omitempty"`
IntervalSeconds int `json:"interval_seconds,omitempty"`
WebhookOnly bool `json:"webhook_only,omitempty"`
Enabled bool `json:"enabled"`
Apply bool `json:"apply"`
Prune bool `json:"prune"`
Deploy bool `json:"deploy"`
}
StackSync is the opt-in git source of a stack. Apply, prune and deploy on sync are separate flags, all off unless the PUT names each one.
type State ¶
type State struct {
// contains filtered or unexported fields
}
State is the live control plane data a plan needs, read through the API with the caller's own permissions. A read the caller may not perform is recorded in denied instead of failing the whole plan.
func (*State) ManagedApps ¶
ManagedApps lists the apps this apply owns: the ledger's apps for a stack, otherwise those carrying the source's managed-by tag.
type StatusError ¶
StatusError is a non-2xx API answer.
func (*StatusError) Error ¶
func (e *StatusError) Error() string
Source Files
¶
- app.go
- app_refs.go
- apply.go
- apply_app.go
- build.go
- cloud_kinds.go
- codes.go
- compose_refs.go
- coverage.go
- diff.go
- doc.go
- export.go
- filter.go
- hash.go
- ledger.go
- model.go
- node.go
- plan.go
- plan_alert.go
- plan_app.go
- plan_app_refs.go
- plan_cloud.go
- plan_compose.go
- plan_kinds.go
- schema.go
- secret_guard.go
- setting.go
- stack_sync.go
- stack_types.go
- state.go
- wire.go