Documentation
¶
Index ¶
- Constants
- func NewInstallTokenRoundTripper(token, clientName, clientVersion, installID string, inner http.RoundTripper) http.RoundTripper
- func NewNamedTokenRoundTripper(token, clientName, clientVersion string, inner http.RoundTripper) http.RoundTripper
- func NewTokenRoundTripper(token, clientVersion string, inner http.RoundTripper) http.RoundTripper
- type APIError
- type AddProviderRequest
- type Addon
- type AddonBackups
- type AddonListing
- type AddonSetting
- type AddonSettingsResult
- type AttachResult
- type AuditEntry
- type AuditFilter
- type AutoDeployResult
- type AutoscaleRequest
- type AutoscaleResult
- type Backup
- type BackupDestinationHealth
- type BackupHealth
- type BackupObservation
- type BackupResult
- type BearerTransport
- type BuildRequest
- type BuildResult
- type CapacityReport
- type CertManagerCapability
- type ChecksResult
- type Client
- func (c *Client) AddDomain(ctx context.Context, host, provider, address, app string, confirm bool) (DomainResult, error)
- func (c *Client) AddEnvironment(ctx context.Context, name, namespace string) error
- func (c *Client) AddProvider(ctx context.Context, req AddProviderRequest) (Provider, error)
- func (c *Client) AddonList(ctx context.Context) (AddonListing, error)
- func (c *Client) AddonSQL(ctx context.Context, addonType, app, env, instance, statement string, ...) (SQLResult, error)
- func (c *Client) AddonSettings(ctx context.Context, addonType, env, instance string) (AddonSettingsResult, error)
- func (c *Client) Addons(ctx context.Context) ([]Addon, error)
- func (c *Client) Apps(ctx context.Context, env string) ([]WorkloadStatus, error)
- func (c *Client) AttachAddon(ctx context.Context, addonType, app, env, instance, envKey string) (AttachResult, error)
- func (c *Client) Audit(ctx context.Context, f AuditFilter) ([]AuditEntry, error)
- func (c *Client) AutoDeploy(ctx context.Context, app, env string) (AutoDeployResult, error)
- func (c *Client) Autoscale(ctx context.Context, app string, req AutoscaleRequest) (AutoscaleResult, error)
- func (c *Client) BackupAddon(ctx context.Context, addonType, app, env, instance, destination string) (BackupResult, error)
- func (c *Client) BackupHealth(ctx context.Context, addonType, app, env string) (BackupHealth, error)
- func (c *Client) BackupInstance(ctx context.Context, addonType, env, instance, destination string) (BackupResult, error)
- func (c *Client) Backups(ctx context.Context, addonType, app, env string) ([]Backup, error)
- func (c *Client) Build(ctx context.Context, app string, req BuildRequest) (BuildResult, error)
- func (c *Client) Capacity(ctx context.Context) (CapacityReport, error)
- func (c *Client) Checks(ctx context.Context, app, env string) (ChecksResult, error)
- func (c *Client) ClaimFirstPrincipal(ctx context.Context, name string) (ClusterCredential, error)
- func (c *Client) Cluster(ctx context.Context) (ClusterCapabilities, error)
- func (c *Client) Config(ctx context.Context, app, env string) (map[string]string, error)
- func (c *Client) ConfigureAddon(ctx context.Context, addonType, env, instance, setting, value string, ...) (ConfigureAddonResult, error)
- func (c *Client) ConnectAddon(ctx context.Context, backend, endpoint, secretKey, token string) (Addon, error)
- func (c *Client) DeleteApp(ctx context.Context, app, env string, confirm bool) error
- func (c *Client) Deploy(ctx context.Context, app string, req DeployRequest) (DeployResult, error)
- func (c *Client) DetachAddon(ctx context.Context, addonType, app, env string, opts DetachAddonOptions) error
- func (c *Client) DisableAutoscale(ctx context.Context, app, env string, confirm bool) error
- func (c *Client) Expose(ctx context.Context, app, env, host string, port int32, tls bool, ...) (ExposeResult, error)
- func (c *Client) Failures(ctx context.Context, f FailureQuery) (FailureReport, error)
- func (c *Client) Guardrails(ctx context.Context, scope GuardScope) ([]Guardrail, error)
- func (c *Client) Health(ctx context.Context, app, env string) (HealthResult, error)
- func (c *Client) History(ctx context.Context, app, env string) ([]Release, error)
- func (c *Client) Hooks(ctx context.Context, app, env string) ([]Hook, error)
- func (c *Client) InstallAddon(ctx context.Context, addonType, env string, opts InstallAddonOptions) (Addon, error)
- func (c *Client) InvitePrincipal(ctx context.Context, name string, admin bool) (ClusterCredential, error)
- func (c *Client) IssueAgentCredential(ctx context.Context) (ClusterCredential, error)
- func (c *Client) Limits(ctx context.Context, env string) ([]Limit, error)
- func (c *Client) ListEnvironments(ctx context.Context) ([]Environment, error)
- func (c *Client) Logs(ctx context.Context, app, env string, tail int) ([]LogLine, error)
- func (c *Client) MountSecret(ctx context.Context, app, env, key, filename, dir string, noEnv *bool) (SecretMounts, error)
- func (c *Client) NextTag(ctx context.Context, app, env string) (NextTagResult, error)
- func (c *Client) Providers(ctx context.Context) ([]Provider, error)
- func (c *Client) Publish(ctx context.Context, app string, req PublishRequest) (PublishResult, error)
- func (c *Client) QueryLogs(ctx context.Context, query string, limit int, backend string) ([]LogEntry, error)
- func (c *Client) QueryMetrics(ctx context.Context, query string, backend string) ([]MetricSample, error)
- func (c *Client) Reachability(ctx context.Context, app, env string) (ReachabilityResult, error)
- func (c *Client) RedeemInvitation(ctx context.Context) (ClusterCredential, error)
- func (c *Client) RemoveAddon(ctx context.Context, name string, opts RemoveAddonOptions) (RemoveAddonResult, error)
- func (c *Client) RemoveDomain(ctx context.Context, host, provider string, confirm bool) (DomainResult, error)
- func (c *Client) RestoreAddon(ctx context.Context, addonType, app, backupID, env, instance string, ...) error
- func (c *Client) RestoreInstance(ctx context.Context, addonType, env string, opts RestoreInstanceOptions) (RestoreInstanceResult, error)
- func (c *Client) Rollback(ctx context.Context, app, env string, opts RollbackOptions) (RollbackResult, error)
- func (c *Client) Run(ctx context.Context, app string, req RunRequest) (RunResult, error)
- func (c *Client) Scale(ctx context.Context, app, env string, replicas int32, confirm bool) (ScaleResult, error)
- func (c *Client) SecretMounts(ctx context.Context, app, env string) (SecretMounts, error)
- func (c *Client) Secrets(ctx context.Context, app, env string) ([]string, error)
- func (c *Client) SetAutoDeploy(ctx context.Context, app, env, level string) (AutoDeployResult, error)
- func (c *Client) SetChecks(ctx context.Context, app, env string, enabled bool) (ChecksResult, error)
- func (c *Client) SetConfig(ctx context.Context, app, env, key, value string, noRestart bool) error
- func (c *Client) SetGuardrail(ctx context.Context, scope GuardScope, code, disposition string) ([]Guardrail, error)
- func (c *Client) SetHealth(ctx context.Context, app, env, path string, port int32) (HealthResult, error)
- func (c *Client) SetHook(ctx context.Context, app, env, phase string, command []string) (Hook, error)
- func (c *Client) SetLimit(ctx context.Context, env, code, value string) ([]Limit, error)
- func (c *Client) SetSecret(ctx context.Context, app, env, key, value string, noRestart bool) error
- func (c *Client) Status(ctx context.Context, app, env string) (StatusResult, error)
- func (c *Client) Unexpose(ctx context.Context, app, env string) error
- func (c *Client) UnmountSecret(ctx context.Context, app, env, key string) (SecretMounts, error)
- func (c *Client) UnsetConfig(ctx context.Context, app, env, key string, noRestart bool) error
- func (c *Client) UnsetHealth(ctx context.Context, app, env string) (HealthResult, error)
- func (c *Client) UnsetHook(ctx context.Context, app, env, phase string) error
- func (c *Client) UnsetSecret(ctx context.Context, app, env, key string, noRestart bool) error
- func (c *Client) WaitReachable(ctx context.Context, app, env string, timeout time.Duration, ...) (ReachabilityResult, error)
- type CloudNativePGCapability
- type ClusterCapabilities
- type ClusterCredential
- type ConfigureAddonResult
- type Consumer
- type ControlPlaneDatabaseCapability
- type Coverage
- type CoverageGap
- type DNSCapability
- type Dependency
- type DependencyResult
- type DeployProgress
- type DeployRequest
- type DeployResult
- type DetachAddonOptions
- type DirectTransport
- type DomainResult
- type Environment
- type ExposeResult
- type Failure
- type FailureKind
- type FailureQuery
- type FailureReport
- type GuardScope
- type Guardrail
- type HealthResult
- type Hook
- type IngressCapability
- type InstallAddonOptions
- type LifecycleCheck
- type Limit
- type LoadBalancerCapability
- type LogEntry
- type LogLine
- type MetricSample
- type MetricsServerCapability
- type NextTagResult
- type NextTags
- type NodeCapacity
- type ObjectRef
- type ObjectStoreConfig
- type ObservationWindow
- type PgBackRestCapability
- type Provider
- type ProviderCapability
- type ProviderVerification
- type PublishRequest
- type PublishResult
- type ReachabilityResult
- type ReadAddressChange
- type Release
- type RemoveAddonOptions
- type RemoveAddonResult
- type RestoreInstanceOptions
- type RestoreInstanceResult
- type RestoreVerification
- type RetainedVolume
- type RollbackOptions
- type RollbackResult
- type RolloutReport
- type RunRequest
- type RunResult
- type SQLError
- type SQLResult
- type ScaleResult
- type SecretMount
- type SecretMounts
- type SourceRef
- type StatusResult
- type StorageCapability
- type StrandedApp
- type Transport
- type WorkloadStatus
Constants ¶
const ( ControlPlaneDatabaseCloudNativePG = "cloudnativepg" ControlPlaneDatabasePlain = "plain" )
The values ControlPlaneDatabaseCapability.Kind takes.
const ( // AddonBackupsArchiving: the instance's own wiring says it archives to object storage. AddonBackupsArchiving = "archiving" // AddonBackupsNone: it archives nowhere, or the add-on type has no backup path at all. AddonBackupsNone = "none" // AddonBackupsUnknown: the wiring could not be read back, so Burrow does not claim either way. AddonBackupsUnknown = "unknown" )
The values AddonBackups.State takes. A caller deciding whether backups are on switches on one of these rather than reading a sentence.
const ( // AddonBaseBackupPresent: the repository holds at least one full backup. AddonBaseBackupPresent = "present" // AddonBaseBackupRequested: this install asked for the first one; it has not landed yet. AddonBaseBackupRequested = "requested" // AddonBaseBackupNone: the repository holds none and none was requested. AddonBaseBackupNone = "none" // AddonBaseBackupUnknown: the repository's own count could not be read. AddonBaseBackupUnknown = "unknown" )
The values AddonBackups.BaseBackup takes, for an archiving instance. Archived write-ahead log with no base backup under it cannot be restored, so this is the half of the answer "archiving" does not give.
const ( // DefaultTimeout bounds a call that does not wait on the cluster. It is the bound this package // has always applied; what changed is that it no longer applies to the calls that wait. DefaultTimeout = 60 * time.Second // TimeoutMargin is added to every derived budget to cover what the server's own bound does not: // TLS and connection setup, the API-server proxy hop, reading a large response body, and the // difference between two clocks. It is deliberately one flat number — a percentage of a // ceiling would be minutes of slack on the long calls and no help on the short ones. TimeoutMargin = time.Minute // DeployTimeout bounds a deploy or a rollback. Both run lifecycle hooks and wait for the rollout // to settle; a rollback's phases are a subset of a deploy's, so the deploy budget covers it. DeployTimeout = controlplane.MaxDeployWait + TimeoutMargin // BuildTimeout bounds an in-cluster build, which is a build Job followed by the deploy the built // image rejoins (ADR-0053 §4) — so it is the longest call in the API by some way. BuildTimeout = controlplane.MaxBuildWait + TimeoutMargin // RunTimeout bounds a one-off command (ADR-0048). RunTimeout = controlplane.MaxRunWait + TimeoutMargin // BackupTimeout bounds a backup, a restore, and the add-on removal that takes a final backup // before destroying a volume (ADR-0064 §5). BackupTimeout = controlplane.MaxBackupWait + TimeoutMargin // RestoreInstanceTimeout bounds a physical restore of a whole Postgres instance (ADR-0066 §4): // the safety backup, the wait for the pre-restore volume to go, and the recovery. RestoreInstanceTimeout = controlplane.MaxRestoreInstanceWait + TimeoutMargin // SQLTimeout bounds one statement against an app's database (ADR-0087 §7): opening the connection // plus the statement at the largest bound an operator may set addon.sql_timeout to. It is derived // from that ceiling rather than from the default, for the rule this file holds — a client sized to // the typical case is how the bug comes back the first time an operator raises a limit. SQLTimeout = controlplane.MaxAddonSQLWait + TimeoutMargin // PublishTimeout bounds a publish, which waits on four links in turn: an external address, DNS // pointing at it, the pre-flight's plain-HTTP probe, and the certificate (ADR-0041 §3). PublishTimeout = controlplane.MaxPublishWait + TimeoutMargin // ProviderTimeout bounds registering a provider, which for an object store verifies the // destination with a run of calls to the vendor before it answers (ADR-0063 §2-§4). ProviderTimeout = controlplane.MaxProviderWait + TimeoutMargin )
How long a request may take, per request rather than per client.
A blanket bound cannot be right for both halves of this API. Most calls read something and answer in milliseconds, and a minute is a generous ceiling for them. A few WAIT ON THE CLUSTER before they answer — a deploy waits for its rollout to settle, a build waits for a build Job, a run waits for a one-off Job — and for those a minute is shorter than the work the control plane is entitled to do. The blanket sixty seconds this replaces was chosen before any call legitimately took minutes; once a deploy started waiting, it turned a deploy that burrowd went on to complete into a reported failure, and the natural response to a failed deploy is to deploy again (issue #404).
So the long budgets are DERIVED, never chosen: each is the control plane's own declared bound for that call (controlplane/apiwait.go) plus one margin. Nothing here restates a duration the server owns, which is what stops the two drifting apart the next time a limit's ceiling moves — raise deploy.settle_timeout's ceiling and DeployTimeout follows it in the same compile.
const ( // ClientNameCLI is the human admin CLI (ADR-0049 §1). ClientNameCLI = "burrow" // ClientNameAgent is the agent's scoped control channel (ADR-0049 §1). ClientNameAgent = "burrow-agent" )
The binary names a client identifies itself by in the X-Burrow-Client half of the handshake (ADR-0039). burrowd needs the NAME as well as the version because Burrow ships two client binaries that are installed together but can drift apart on disk, and the remedy for a stale one differs: refusing `burrow-agent` and telling the user to update the `burrow` CLI sends them somewhere that cannot fix it. The values are the executable names, so what the message prints is what the user types.
const CodeAlreadyClaimed = "already_claimed"
CodeAlreadyClaimed is the machine-readable code burrowd returns when an install already has a first principal. It is a conflict rather than a failure: the caller's existing access is untouched and the way in is to be issued a credential by an admin, so a client branches on this to say that rather than reporting that signing in broke.
const CodeClientTooOld = "client_too_old"
CodeClientTooOld is the machine-readable code burrowd returns when it refuses a client outside the compatibility window (ADR-0039). A client matches on it to replace the server's necessarily generic remedy with one it can establish locally — which binary it is, and where it is installed.
const CodeCredentialNotLive = "credential_not_live"
CodeCredentialNotLive is what burrowd returns for a credential that WAS real and no longer authenticates: revoked, or expired. It is separate from CodeUnauthorized because the remedy is different — a credential that was never issued means the wrong install or a stale file, and one that has expired means asking for another.
const CodeInstallMismatch = "install_mismatch"
CodeInstallMismatch is the machine-readable code burrowd returns when the caller named an install id and this control plane is a different install (ADR-0084 §5) — the kube context resolved, the credential was accepted, and the Burrow on the other end is not the one the target was pointed at.
const CodeInvitationNotRedeemed = "invitation_not_redeemed"
CodeInvitationNotRedeemed is what burrowd returns when an invitation is presented anywhere but the exchange. It is not a failed authentication: the invitation is real and the identity behind it is known, and what has not happened yet is the one thing it is for.
const CodeScopeUnsupported = "scope_unsupported"
CodeScopeUnsupported is the machine-readable code on a refusal this CLIENT raises: the caller asked for a scope the control plane on the other end cannot express, so the call was not performed at a wider one. It is not a code any control plane returns — it is the client naming a gap it detected from the server's own unknown-route refusal (ADR-0039) — and it is an APIError like every other refusal so a --json caller and an agent branch on it the same way.
CodeUnauthorized is what burrowd returns for a token it did not issue, or one it no longer knows.
const CodeUnknownOperation = "unknown_operation"
CodeUnknownOperation is the machine-readable code burrowd returns for a route it does not have (ADR-0039): a newer client calling a feature the server lacks, told as a structured refusal naming both versions and the upgrade rather than as a bare 404. A client matches on it to say which of ITS features the gap corresponds to, since the server can only name the route.
const InstallHeader = "X-Burrow-Install"
InstallHeader carries the install id the caller expects the control plane to be (ADR-0084 §5). It is the request half of the install check: burrowd knows its own id, the client sends the one its target recorded, and a difference is refused with a message naming both instead of a command quietly acting on a cluster nobody meant to reach.
It is a header rather than part of the credential for the same reason X-Burrow-Client and X-Burrow-Client-Version are: it says something about the CALL, not about who is making it. The id authorises nothing — it identifies an install — and Authorization is unavailable on the API-server proxy path in any case, where client-go owns that header to authenticate to the API server itself (ADR-0015). Like the rest of the X-Burrow- family it survives the proxy untouched.
It is exported because both round trippers in this package set it and the control plane's middleware reads it; keeping one spelling in one place is the point.
const ReachabilityPollInterval = 3 * time.Second
ReachabilityPollInterval is how often WaitReachable re-checks reachability while polling.
Variables ¶
This section is empty.
Functions ¶
func NewInstallTokenRoundTripper ¶
func NewInstallTokenRoundTripper(token, clientName, clientVersion, installID string, inner http.RoundTripper) http.RoundTripper
NewInstallTokenRoundTripper is NewNamedTokenRoundTripper plus the install the caller expects to be talking to, sent in X-Burrow-Install (ADR-0084 §5). A target that records an install id supplies it here, and the control plane refuses a request that names an install it is not, so a cluster rebuilt under a name a provider generates deterministically is caught on arrival rather than deployed into.
An empty installID omits the header, which is the ordinary case and must stay served: a target recorded before install ids existed has none, and a control plane older than this check ignores the header if one is sent. Skew in both directions keeps working.
func NewNamedTokenRoundTripper ¶
func NewNamedTokenRoundTripper(token, clientName, clientVersion string, inner http.RoundTripper) http.RoundTripper
NewNamedTokenRoundTripper is NewTokenRoundTripper plus the client-NAME half of the ADR-0039 handshake: it also sets X-Burrow-Client to clientName (ClientNameCLI or ClientNameAgent) so burrowd's too-old refusal can name the binary that is actually stale rather than guessing. Both the kubeconfig transport and the direct-URL transport wrap their http.Client's transport with this, so every self-host request carries the same headers on the wire (ADR-0015, ADR-0039).
This is the single place every outbound control-plane request passes through, which is why the handshake headers live here alongside the credential. An empty name or version omits its header, so a transport that does not know what it is (or a test) sends nothing rather than something misleading; burrowd treats an absent header as a pre-handshake client and serves it (ADR-0039).
func NewTokenRoundTripper ¶ added in v0.10.0
func NewTokenRoundTripper(token, clientVersion string, inner http.RoundTripper) http.RoundTripper
NewTokenRoundTripper returns an http.RoundTripper that sets X-Burrow-Token to token — and, when clientVersion is non-empty, X-Burrow-Client-Version to it (ADR-0039) — before delegating to inner. It sends no client NAME; a client that knows which binary it is should use NewNamedTokenRoundTripper so burrowd can name the right binary when it refuses a stale one. A nil inner uses http.DefaultTransport.
Types ¶
type APIError ¶
type APIError struct {
StatusCode int
Code string
Message string
// NeedsConfirmation is true when a guardrail held the operation for confirmation
// rather than refusing it: retrying with confirm set lets it proceed (ADR-0020).
NeedsConfirmation bool
// ServerVersion is the control plane's release version, set on a CodeClientTooOld refusal so a
// client can name the version it must reach in an install-aware remedy of its own (ADR-0039).
ServerVersion string
// ServerInstallID is the id of the install that answered, set on a CodeInstallMismatch refusal
// (ADR-0084 §5). It is the counterpart of ServerVersion: the refusal message already names both
// ids, and carrying the answering one structurally lets a caller re-point a target at the install
// that is actually there without parsing prose.
ServerInstallID string
}
APIError is a non-2xx response from the control plane, carrying its structured error (a machine-readable code and a human message) so a tool can surface both.
type AddProviderRequest ¶ added in v0.2.0
type AddProviderRequest struct {
Name string `json:"name,omitempty"`
Type string `json:"type"`
SecretKey string `json:"secret_key,omitempty"`
Token string `json:"token,omitempty"`
// The fields below configure an OBJECT-STORAGE provider (ADR-0063), whose credential is a PAIR
// and whose configuration names a destination. AccessKeyID and SecretAccessKey are credential
// VALUES and are held to exactly the same rules as Token: body only, never logged, never
// echoed back.
Endpoint string `json:"endpoint,omitempty"`
Region string `json:"region,omitempty"`
Bucket string `json:"bucket,omitempty"`
CreateBucket bool `json:"create_bucket,omitempty"`
RetentionDays int `json:"retention_days,omitempty"`
AccessKeyID string `json:"access_key_id,omitempty"`
SecretAccessKey string `json:"secret_access_key,omitempty"`
Confirm bool `json:"confirm,omitempty"`
}
AddProviderRequest registers a vendor credential. The token VALUE travels in this request over burrowd's authenticated, TLS-protected control-plane API; burrowd validates it and writes it into the burrow-credentials Secret (ADR-0030). The value is never logged, never stored in Postgres, never echoed back, and still never carried over MCP — provider add is a human/CLI operation.
type Addon ¶ added in v0.4.0
type Addon struct {
// Name is the instance's name IN THE CLUSTER — what `kubectl get` shows. For an environment's
// first instance it is the same string as Label; for every later one it is a generated
// `burrow-<type>-<id>` the operator never types (ADR-0091 §2).
Name string `json:"name"`
Type string `json:"type"`
// Label is what a person calls this instance: what `--name` takes and what a guardrail key holds
// (ADR-0091 §1). Empty on a row from a control plane that predates labels, where the name is the
// answer.
Label string `json:"label,omitempty"`
// Environment is the environment this instance serves (ADR-0067 §1): each environment gets its
// own instance, so this is what distinguishes two rows of the same type.
Environment string `json:"environment,omitempty"`
Mode string `json:"mode"`
// Backend is the concrete implementation serving this instance: "victorialogs" for logs,
// "cloudnative-pg" for the Postgres add-on, whose instance is a CloudNativePG Cluster the
// operator reconciles (ADR-0066 §1).
Backend string `json:"backend,omitempty"`
Image string `json:"image,omitempty"`
Endpoint string `json:"endpoint"`
Capabilities []string `json:"capabilities"`
Ready bool `json:"ready"`
// Warning is a non-blocking note about the install, not persisted anywhere: today, that the
// instance was created WITHOUT write-ahead-log archiving because the cluster has no pgBackRest
// plugin, even though an object-storage destination is registered (ADR-0066 §3). Empty when
// there is nothing to say.
Warning string `json:"warning,omitempty"`
// Backups is what this instance does about backups, read back from the instance itself at install
// time. Nil on a row read from the registry: it is a fact about one moment, not a property of the
// add-on, so it is never persisted.
Backups *AddonBackups `json:"backups,omitempty"`
}
Addon is one installed (and, later, connected) add-on instance.
type AddonBackups ¶
type AddonBackups struct {
State string `json:"state"`
// Provider is the registry name of the object store, reported only when the instance's own
// repository is demonstrably the one that provider names.
Provider string `json:"provider,omitempty"`
// Bucket and RepoPath come from the instance's pgBackRest stanza, not from what the install
// resolved.
Bucket string `json:"bucket,omitempty"`
RepoPath string `json:"repo_path,omitempty"`
// RetentionDays is how long a full backup is kept; 0 when the repository declares no window.
RetentionDays int `json:"retention_days,omitempty"`
// Schedule is the base backup's cron expression in CloudNativePG's six-field form (leading field
// is seconds).
Schedule string `json:"schedule,omitempty"`
// BaseBackup is one of the AddonBaseBackup* values, empty when the instance does not archive.
BaseBackup string `json:"base_backup,omitempty"`
// Detail is one line elaborating the state, safe to print.
Detail string `json:"detail,omitempty"`
}
AddonBackups is what one installed add-on instance does about backups: whether it archives, where, on what schedule, and whether anything exists for the archived write-ahead log to be replayed onto. Names and numbers only — never a credential.
type AddonListing ¶
type AddonListing struct {
Addons []Addon `json:"addons"`
RetainedVolumes []RetainedVolume `json:"retained_volumes,omitempty"`
}
AddonListing is the whole answer to `addon list`: the registered add-ons, plus the volumes an earlier removal left behind. They are separate fields because they are different kinds of thing — one is a running backing service, the other is storage with nothing attached to it.
type AddonSetting ¶
type AddonSetting struct {
Setting string `json:"setting"`
Value string `json:"value"`
Description string `json:"description"`
// Consequence is what changing this setting does — that adding a standby restarts every attached
// app, that a grown volume never shrinks. It rides the listing rather than living in help text
// because the listing is where somebody is deciding whether to change the value.
Consequence string `json:"consequence"`
}
AttachAddon gives an app its own database on ENVIRONMENT env's Postgres instance and wires it in (ADR-0031/0067 §1). The caller supplies only the add-on type, app name, and environment; burrowd generates the connection string server-side and writes it into the app's Secret in that environment's namespace — no secret value crosses this API or the agent control channel. The result carries the environment and the KEY name, never the value.
envKey names the environment variable to write it under. EMPTY IS NOT "DATABASE_URL" — it is "whatever this attachment already uses", which burrowd resolves, so omitting it keeps today's behaviour for an app that never named one and does not move the variable of an app that did.
THE NAME RIDES THE ROUTE (see narrowing), and it is the one narrowing here that does not narrow scope: the same database on the same instance in the same namespace, whatever the variable is called. What it aims is the KEY, and a control plane that predates it drops the field and writes DATABASE_URL — over whatever the app was keeping there — then answers 200 reporting a name the caller never asked for. That is the failure #485 describes with the target one level in, so it takes the same form: an older control plane refuses a route it does not serve, having written nothing. AddonSetting is one row of `burrow addon config <type>`: a property of an existing instance, what it is set to now, and what changing it does (ADR-0082 §1).
type AddonSettingsResult ¶
type AddonSettingsResult struct {
Addon string `json:"addon"`
Environment string `json:"environment"`
Instance string `json:"instance"`
Settings []AddonSetting `json:"settings"`
}
AddonSettingsResult is what one environment's add-on instance can be told, and what it is set to.
type AttachResult ¶ added in v0.6.0
type AttachResult struct {
App string `json:"app"`
Addon string `json:"addon"`
// Environment is the environment whose instance the database was provisioned on (ADR-0067 §1) —
// which is what says WHICH database the app was given, since databases keep their simple names.
Environment string `json:"environment,omitempty"`
SecretKey string `json:"secret_key"`
// PreviousSecretKey is the name the attachment used before this call, present only when this
// attach RENAMED it: the connection string moved to SecretKey and this key was removed, because
// the attach rotated the password and the old name would otherwise hold a dead one (issue #462).
PreviousSecretKey string `json:"previous_secret_key,omitempty"`
// ReadSecretKey is the variable the READ ADDRESS was written under, present only when the
// instance has a standby for it to point at (ADR-0081 §2). An instance with none has no `-ro`
// endpoint, so the variable is absent rather than present and resolving to nothing.
ReadSecretKey string `json:"read_secret_key,omitempty"`
}
AttachResult is the non-secret outcome of attaching an app to an add-on (ADR-0031): the KEY NAME the generated connection string was written under in the app's Secret — never the value.
type AuditEntry ¶ added in v0.5.0
type AuditEntry struct {
ID int64 `json:"id,omitempty"`
Timestamp time.Time `json:"timestamp"`
Operation string `json:"operation"`
Target string `json:"target,omitempty"`
Args map[string]string `json:"args,omitempty"`
GuardrailCode string `json:"guardrail_code,omitempty"`
Disposition string `json:"disposition,omitempty"`
Outcome string `json:"outcome"`
Result string `json:"result,omitempty"`
Caller string `json:"caller,omitempty"`
// Principal is the acting identity (the actor), distinct from Caller (the control-plane
// boundary). The json tag must match the engine's AuditEntry.Principal tag exactly — the two
// structs serialize/deserialize across the API, and a mismatched tag would silently drop the
// field (ADR-0038).
Principal string `json:"principal,omitempty"`
// ClientVersion is the release version of the client that drove the operation, from the
// X-Burrow-Client-Version handshake (ADR-0039). Empty for a pre-handshake client. The json tag
// must match the engine's AuditEntry.ClientVersion tag exactly, or the field would silently drop.
ClientVersion string `json:"client_version,omitempty"`
}
AuditEntry mirrors a control-plane audit row (ADR-0027): a guarded mutating operation and the guardrail decision and outcome that applied. Args is redacted at the source — it carries only safe metadata (names, image reference, replica count, env/secret key NAMES), never a value.
type AuditFilter ¶ added in v0.5.0
AuditFilter narrows an audit query. A zero value lists the latest rows across all apps.
type AutoDeployResult ¶ added in v0.13.0
type AutoDeployResult struct {
App string `json:"app"`
Env string `json:"env"`
Level string `json:"level"`
Repository string `json:"repository,omitempty"`
Current string `json:"current,omitempty"`
Target string `json:"target,omitempty"`
Upgrade string `json:"upgrade,omitempty"`
Checked bool `json:"checked,omitempty"`
Note string `json:"note,omitempty"`
// DisabledReason is why auto-deploy is off when the safety stop turned it off (ADR-0052 §5):
// "disabled by rollback" or "disabled by downgrade". Empty when the level was human-set or is not off.
DisabledReason string `json:"disabled_reason,omitempty"`
}
AutoDeployResult is the auto-deploy configuration for an app in one environment (ADR-0052 §2): the app, the canonical environment name, and the effective auto-deploy level, plus the enriched read-only upgrade view a show returns (ADR-0052 §3) — the current running version, the tag auto-deploy would move to within the level, the highest available upgrade above the level's cap, whether the registry upgrade check ran, and a short note when it could not. The upgrade fields are omitempty, so a set (which reports the level only) carries just app/env/level.
type AutoscaleRequest ¶ added in v0.8.0
type AutoscaleRequest struct {
Env string `json:"env,omitempty"`
Min int32 `json:"min"`
Max int32 `json:"max"`
CPU int32 `json:"cpu"`
Memory int32 `json:"memory,omitempty"`
Confirm bool `json:"confirm,omitempty"`
}
AutoscaleRequest carries a desired autoscaling shape for an app (ADR-0006): the replica band and the CPU (and optional memory) utilization targets, plus the target environment. Env names the environment whose namespace the app lives in (ADR-0035 phase 2b).
type AutoscaleResult ¶ added in v0.8.0
type AutoscaleResult struct {
App string `json:"app"`
Env string `json:"env,omitempty"`
MinReplicas int32 `json:"min_replicas"`
MaxReplicas int32 `json:"max_replicas"`
CPUPercent int32 `json:"cpu_percent"`
MemoryPercent int32 `json:"memory_percent,omitempty"`
MetricsAvailable bool `json:"metrics_available"`
Warning string `json:"warning,omitempty"`
}
AutoscaleResult reports the applied autoscaling shape, the app and environment it acted in, and whether metrics-server is present. When it is absent, MetricsAvailable is false and Warning explains the autoscaler is set but will not scale until metrics-server is installed.
type Backup ¶ added in v0.6.0
type Backup struct {
ID string `json:"id"`
// Kind is which mechanism took it: "logical" (one app's `pg_dump`) or "physical" (a
// CloudNativePG base backup of the whole instance). A physical backup has no App.
Kind string `json:"kind,omitempty"`
App string `json:"app"`
// Environment is the environment whose instance the dump was taken from (ADR-0067 §1). A dump is
// only a valid source for the environment it came from.
Environment string `json:"environment,omitempty"`
CreatedAt string `json:"created_at"`
Path string `json:"path,omitempty"`
// Volume is the claim the dump was written to — this environment's backup claim. Each
// environment holds its dumps on its own volume, so the path alone does not address a dump.
Volume string `json:"volume,omitempty"`
SizeBytes int64 `json:"size_bytes,omitempty"`
Status string `json:"status"`
// Destination is where this backup's bytes ended up: "object-store" for one that left the
// cluster, "cluster" for one that did not (ADR-0063). It is recorded per backup rather than
// derived from the current configuration, so registering a destination today does not make
// yesterday's in-cluster dumps read as durable.
Destination string `json:"destination,omitempty"`
// Provider and ObjectKey address the dump at the vendor. Names and a key, never a credential.
Provider string `json:"provider,omitempty"`
ObjectKey string `json:"object_key,omitempty"`
// FailureReason is why a failed backup failed, from a closed set a caller can branch on;
// FailureDetail is one Burrow-authored line. Neither carries a vendor response body.
FailureReason string `json:"failure_reason,omitempty"`
FailureDetail string `json:"failure_detail,omitempty"`
}
Backup is one recorded per-app database backup (ADR-0032): the control-plane index row for a dump on the backup PVC. It names the app, the on-PVC path, the size, and the status — never a credential.
type BackupDestinationHealth ¶
type BackupDestinationHealth struct {
Provider string `json:"provider"`
Endpoint string `json:"endpoint,omitempty"`
Bucket string `json:"bucket,omitempty"`
Reachable bool `json:"reachable"`
// Detail is one Burrow-authored line describing what was observed. Never a vendor response body
// and never a credential.
Detail string `json:"detail,omitempty"`
}
BackupDestinationHealth is one registered object-storage destination and whether it answered when the report was assembled. It is probed on demand and never cached — a stored verdict goes stale while continuing to read as current.
type BackupHealth ¶
type BackupHealth struct {
Addon string `json:"addon"`
App string `json:"app,omitempty"`
Environment string `json:"environment,omitempty"`
ObservedAt string `json:"observed_at"`
// State is "never", "cluster-only" or "durable" — what kind of coverage exists, not a verdict
// against a threshold.
State string `json:"state"`
// LastSuccess is the newest completed backup wherever it went; LastDurableSuccess is the newest
// one that reached an object store, which is the age ADR-0063 §7 is about.
LastSuccess *BackupObservation `json:"last_success,omitempty"`
LastDurableSuccess *BackupObservation `json:"last_durable_success,omitempty"`
LastFailure *BackupObservation `json:"last_failure,omitempty"`
// Pending counts rows still recorded as pending. A pending row never reads as a success.
Pending int `json:"pending,omitempty"`
Destinations []BackupDestinationHealth `json:"destinations,omitempty"`
Summary string `json:"summary"`
}
BackupHealth is what Burrow observed about an add-on's backups (ADR-0063 §7, ADR-0066 §5): the last successful backup, the last one that left the cluster, the last failure, and whether each registered destination answers.
type BackupObservation ¶
type BackupObservation struct {
ID string `json:"id"`
App string `json:"app"`
Environment string `json:"environment,omitempty"`
At string `json:"at"`
// AgeSeconds is how long ago the backup was recorded. Seconds, not a rendered duration, so a
// caller compares a number rather than parsing prose.
AgeSeconds int64 `json:"age_seconds"`
Status string `json:"status"`
Destination string `json:"destination,omitempty"`
Provider string `json:"provider,omitempty"`
SizeBytes int64 `json:"size_bytes,omitempty"`
// Reason and Detail are set on a failure only. Neither carries a vendor response body.
Reason string `json:"reason,omitempty"`
Detail string `json:"detail,omitempty"`
}
BackupObservation is one recorded backup as the health surface reports it, with its age already computed against the moment the report was assembled.
type BackupResult ¶ added in v0.6.0
type BackupResult struct {
Backup Backup `json:"backup"`
}
BackupResult is the outcome of an on-demand backup (ADR-0032): the recorded backup row.
type BearerTransport ¶
type BearerTransport struct {
// BaseURL is the control plane's origin, e.g. https://burrow-cloud.dev. It must be HTTPS: a
// bearer credential is a password on every request, and Connect refuses to put one on the wire in
// the clear.
BaseURL string
// Token is the stored credential. It is never rendered — not by Connect, not by an error from
// this file, and not by the client this returns.
Token string
// Name is the calling binary (ClientNameCLI or ClientNameAgent), sent as X-Burrow-Client so a
// too-old refusal names the binary the user must actually update (ADR-0039). Empty omits it.
Name string
// Version is this client's release version, sent as X-Burrow-Client-Version so the control plane
// can make version skew legible instead of opaque (ADR-0039). Empty omits the header.
Version string
// InstallID is the install this caller expects to reach, sent as X-Burrow-Install (ADR-0084 §5).
// It is empty for the managed product, which is one control plane rather than an install someone
// stood up and could stand up again — there is no id to record and nothing to confuse it with.
// The field is here because this is the second of the two places every outbound request passes
// through, and a self-hosted burrowd given a front door of its own (ADR-0084 §7) is reached over
// exactly this transport. Leaving the header out of one choke point would make the check hold
// only for whichever route a caller happened to take.
InstallID string
// Rejected is what the caller is told when the control plane refuses the credential. It exists
// because a bare 401 is the least useful thing a signed-in person can be shown: the credential
// was accepted an hour ago, so what changed is worth naming — it was revoked from the console, or
// the sign-in it came from no longer exists. Each binary supplies its own wording because the
// remedy differs. Empty falls back to a generic sentence rather than showing the raw refusal.
Rejected string
}
BearerTransport reaches a control plane directly over HTTPS with a bearer credential (ADR-0045). It is the managed product's path: a tenant has no cluster and no kubeconfig, so there is no API-server proxy to route through and no install Secret to read a token out of — the credential signing in produced is presented on the request itself.
The credential rides `Authorization: Bearer`, not X-Burrow-Token. The two headers are not interchangeable on this path: the managed control plane reads the bearer header to decide which tenant is calling, and strips X-Burrow-Token from the request before it reaches the per-tenant handler, precisely so a client-supplied value cannot reach an inner authorization check. Sending the credential in the header that gets stripped would authenticate nothing.
It lives beside DirectTransport rather than in the connect package because it needs no client-go, which keeps this package importable by both binaries and by a private module.
func (BearerTransport) Connect ¶
func (t BearerTransport) Connect(_ context.Context) (*Client, error)
Connect returns a client for the configured URL, presenting the bearer credential on every request. It needs no context because the credential is already resolved; the parameter satisfies the Transport interface.
type BuildRequest ¶ added in v0.13.0
type BuildRequest struct {
Env string `json:"env,omitempty"`
Source SourceRef `json:"source"`
TargetImage string `json:"target_image"`
Confirm bool `json:"confirm,omitempty"`
// Progress receives the build's stages as the control plane reports them (issue #503): the build's
// own stages and then the deploy stages it hands off to, as one continuous sequence. Setting it is
// what asks for them: Build then negotiates the streaming response, and a control plane that does
// not offer one is handled transparently. Nil — the default, and the shape that goes on the wire,
// since json ignores this field — is the build this package has always issued.
//
// It is called from Build's own goroutine as each line arrives, so a slow reporter slows the read.
// It is never called after Build returns.
Progress func(DeployProgress) `json:"-"`
}
BuildRequest describes an in-cluster build-then-deploy (ADR-0053): the git source to clone and build inside the cluster and the target image reference the built image is pushed to. On success the built image rejoins the guarded deploy path, so a build is a front-end that ends where deploy begins. Env names the target environment (ADR-0035); empty or "default" targets the default environment. TargetImage is optional: when empty, the build pushes to the in-cluster registry if one is installed (ADR-0054), else the server rejects it. Confirm acknowledges the app.deploy guardrail so a held deploy proceeds.
type BuildResult ¶ added in v0.13.0
type BuildResult struct {
Digest string `json:"digest"`
Deploy DeployResult `json:"deploy"`
}
BuildResult reports the outcome of a successful build-then-deploy (ADR-0053 §4): the digest of the image the builder produced and the deploy that shipped it. Because the build ends where deploy begins, Deploy carries the same release, rollback handle, and hints an explicit deploy returns.
type CapacityReport ¶ added in v0.13.0
type CapacityReport struct {
Nodes []NodeCapacity `json:"nodes"`
Cluster NodeCapacity `json:"cluster"`
TopCPU []Consumer `json:"top_cpu"`
TopMemory []Consumer `json:"top_memory"`
BuildCPUMillis int64 `json:"build_cpu_millis"`
BuildMemBytes int64 `json:"build_mem_bytes"`
BuildFits bool `json:"build_fits"`
BuildFitsNode string `json:"build_fits_node,omitempty"`
Verdict string `json:"verdict"`
UtilizationNote string `json:"utilization_note"`
}
CapacityReport mirrors the control plane's cluster capacity/headroom surface (issue #275): per node and cluster-total allocatable / committed (sum of pod requests) / free headroom, the top CPU and memory consumers, and a plain-language verdict on whether a typical in-cluster build fits and whether another node is needed. It is scheduling headroom from the Kubernetes API alone — no metrics-server. CPU figures are milli-CPU (1000 = one core); memory figures are bytes. It carries no secret value.
type CertManagerCapability ¶ added in v0.6.0
type CertManagerCapability struct {
Present bool `json:"present"`
}
CertManagerCapability reports whether cert-manager is installed (detected via its API group).
type ChecksResult ¶
type ChecksResult struct {
App string `json:"app"`
Environment string `json:"environment,omitempty"`
Enabled bool `json:"enabled"`
Dependencies []Dependency `json:"dependencies"`
Note string `json:"note,omitempty"`
}
ChecksResult is what `burrow app checks` reports: whether the deploy-time dependency check runs for an app, and what Burrow derived from what it provisioned that it would check (ADR-0076 §4).
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a thin HTTP client for the control-plane API (ADR-0005). The caller holds the API bearer token to authenticate to the control plane, but never any cluster credentials — those live only in the control plane. These DTOs mirror the API's JSON CONTRACT rather than the control plane's Go types, so the client stays decoupled across the module boundary (LICENSING.md): the one thing it takes from the control-plane package is the declared bound on how long a call may take (see timeouts below), because two independently chosen bounds is exactly the defect that made a successful deploy report as failed.
The Client is auth-agnostic (ADR-0045): it holds no credential and sets no auth header. Authentication is the job of the supplied *http.Client's RoundTripper — for self-host that is NewTokenRoundTripper, which adds X-Burrow-Token (ADR-0015). This lets a Transport swap in a different credential scheme while reusing the request methods unchanged.
func NewClient ¶
NewClient returns a control-plane API client for baseURL authenticating with token over X-Burrow-Token, using a default HTTP client whose transport is NewTokenRoundTripper. It sends no client-version header; use NewClientVersion to include the ADR-0039 handshake.
func NewClientVersion ¶ added in v0.10.0
NewClientVersion is NewClient plus the ADR-0039 client-version handshake: it sends clientVersion in X-Burrow-Client-Version on every request so burrowd can turn version skew into an actionable error rather than an opaque one. An empty clientVersion behaves exactly like NewClient. It sends no client NAME; a binary that knows which of Burrow's two clients it is should use NewNamedClient so a too-old refusal can name the binary the user must actually update.
func NewClientWithHTTP ¶
NewClientWithHTTP builds a client on the supplied *http.Client, which owns authentication through its RoundTripper. The connect package uses this to route requests through the Kubernetes API-server proxy with a kubeconfig-authenticated transport wrapped in NewTokenRoundTripper (ADR-0014). A nil hc gets a default, unauthenticated client.
The per-request budgets apply whatever transport is supplied, so both paths are bounded the same way: the API-server proxy path previously had no client-side bound at all, which made a hung request hang forever rather than misreport, and one place now decides how long a call may take. An hc that carries its OWN http.Client.Timeout keeps it, and it wins where it is shorter — that is the caller's deliberate choice, and it is the one way a bound too short for a deploy can still exist.
func NewNamedClient ¶
NewNamedClient is NewClientVersion plus the client-NAME half of the ADR-0039 handshake: it sends clientName (ClientNameCLI or ClientNameAgent) in X-Burrow-Client alongside the version. It is the constructor the direct-URL transport uses, passing the binary's own name and release version.
func (*Client) AddDomain ¶ added in v0.2.0
func (c *Client) AddDomain(ctx context.Context, host, provider, address, app string, confirm bool) (DomainResult, error)
AddDomain points host at an address through the named DNS provider (ADR-0018). Give either an explicit address or the name of an exposed app whose ingress address the control plane reads.
func (*Client) AddEnvironment ¶ added in v0.7.0
AddEnvironment registers a named environment mapping name to namespace (ADR-0035 phase 2). The namespace and burrowd's Role there are created kubeconfig-side by `burrow env add` before this call; this records the registry entry. A duplicate name is rejected.
func (*Client) AddProvider ¶ added in v0.2.0
AddProvider registers a vendor credential in the control-plane registry and returns the recorded provider (ADR-0023).
func (*Client) AddonList ¶
func (c *Client) AddonList(ctx context.Context) (AddonListing, error)
AddonList returns the add-on listing: the registered instances and the retained volumes.
func (*Client) AddonSQL ¶
func (c *Client) AddonSQL(ctx context.Context, addonType, app, env, instance, statement string, confirm bool) (SQLResult, error)
AddonSQL runs one statement against an app's database on a relational add-on and returns its columns and rows (ADR-0087). burrowd runs it, connecting as the app's own role with the credential it already minted — no connection to the database leaves the cluster, and the statement runs independently of the application, so a database whose app will not start is still queryable.
It is gated by the addon.sql guardrail, DENIED by default: a refusal comes back as a guardrail outcome naming the operator command that would relax it per environment. Passing confirm satisfies a disposition an operator has moved to confirm and does nothing to a deny.
A statement the database refuses is NOT an error here: it comes back in the result's Error with its SQLSTATE. An error from this call means the statement did not run.
The ENVIRONMENT RIDES THE ROUTE, for the reason RestoreAddon's does, and more sharply: a statement aimed at staging, against a control plane that drops the field, runs against the app of that name on the default environment's instance — and the statement may write (issue #485).
func (*Client) AddonSettings ¶
func (c *Client) AddonSettings(ctx context.Context, addonType, env, instance string) (AddonSettingsResult, error)
AddonSettings reports what can be configured on environment env's instance of an add-on and what each setting is currently set to (ADR-0082 §1). Read-only.
func (*Client) Addons ¶ added in v0.4.0
Addons lists the installed add-on instances. It is the add-ons alone, for callers that only ask what is running; AddonList also carries the retained volumes.
func (*Client) Apps ¶ added in v0.3.0
Apps lists the workload status of every Burrow-managed app in the target environment (ADR-0035 phase 2b). An empty env lists the default environment's namespace.
func (*Client) AttachAddon ¶ added in v0.6.0
func (*Client) Audit ¶ added in v0.5.0
func (c *Client) Audit(ctx context.Context, f AuditFilter) ([]AuditEntry, error)
Audit lists audit rows newest-first, optionally filtered by app, operation, and outcome (ADR-0027). It is read-only — the audit log has no write or delete path through the API.
func (*Client) AutoDeploy ¶ added in v0.13.0
AutoDeploy returns the auto-deploy level configured for app in env (ADR-0052 §2). An empty env reads the default environment. A missing configuration reads as the default level (minor).
func (*Client) Autoscale ¶ added in v0.8.0
func (c *Client) Autoscale(ctx context.Context, app string, req AutoscaleRequest) (AutoscaleResult, error)
Autoscale configures autoscaling for an app: it applies a HorizontalPodAutoscaler on the app's Deployment with the requested replica band and utilization targets (ADR-0006). The result reports the applied shape and, when metrics-server is absent, a warning that the autoscaler will not scale until it is installed.
func (*Client) BackupAddon ¶ added in v0.6.0
func (c *Client) BackupAddon(ctx context.Context, addonType, app, env, instance, destination string) (BackupResult, error)
BackupAddon backs up an app's database on the installed Postgres add-on (ADR-0032, ADR-0063 §7). burrowd runs an in-cluster Job that pg_dumps to the backup PVC and, when an object-storage destination is registered, writes it on to the store and reads it back before recording the backup as completed — so a returned completed backup is one whose bytes actually arrived. destination names the provider to write to; empty resolves it, which works when exactly one is registered. No secret value crosses this API; the result is the recorded backup, never a credential.
BOTH NARROWINGS RIDE THE ROUTE (see narrowing). The environment says which instance is dumped; the destination says whether the bytes leave the cluster at all. This route is older than object storage, so a control plane in between drops the destination, writes the dump to the in-cluster volume, and records a COMPLETED backup — a backup that reads as durable and is on the same disk as the database it is insurance against. Nobody finds out until they need it (issue #485).
func (*Client) BackupHealth ¶
func (c *Client) BackupHealth(ctx context.Context, addonType, app, env string) (BackupHealth, error)
BackupHealth reports what Burrow observed about an add-on's backups (ADR-0063 §7, ADR-0066 §5). An empty app spans every app and an empty env every environment. Read-only; it moves no secret.
func (*Client) BackupInstance ¶
func (c *Client) BackupInstance(ctx context.Context, addonType, env, instance, destination string) (BackupResult, error)
BackupInstance takes a PHYSICAL base backup of one environment's whole Postgres instance (ADR-0066 §2): every database on it, restorable to any point in the write-ahead-log window, taken by CloudNativePG through the pgBackRest plugin and written to the object store. It is not interchangeable with BackupAddon, which dumps ONE app's database and can be restored into that app alone; a physical backup restores the whole instance and cannot be applied per app.
destination names the object-storage provider holding the repository; empty resolves it, which works when exactly one is registered. No secret value crosses this API.
func (*Client) Backups ¶ added in v0.6.0
Backups lists recorded backups from the control-plane database (ADR-0032). An empty app lists every app's backups and an empty env every environment's; a non-empty value restricts to that app or environment (ADR-0067 §1). Read-only; no secret value.
THE ENVIRONMENT RIDES THE ROUTE, WHICH IS THE WRITE RULE ON A READ, and this is the only read that gets it. What comes back here is not something a person reads and moves on from: it is the picker for RestoreAddon and RestoreInstance, and the id chosen from it is handed to a call that overwrites a live database. An id chosen from the wrong environment's list cannot be caught at the restore — an id is an opaque string, and the restore has no way to know which listing produced it. So the list itself has to be refused rather than answered one environment out (issue #485).
`addon` and `app` stay query parameters: neither aims a write, and an absent one widens a listing rather than pointing it somewhere else.
func (*Client) Build ¶ added in v0.13.0
func (c *Client) Build(ctx context.Context, app string, req BuildRequest) (BuildResult, error)
Build builds an app's image from a git source reference inside the cluster and, on success, hands the resulting digest-pinned reference into the guarded deploy path (ADR-0053): the returned BuildResult carries the built digest and the deploy that shipped it. It is gated by the app.deploy guardrail — a held deploy returns a guardrail error the caller surfaces for confirmation, re-invoking with Confirm set only on explicit human approval.
Setting req.Progress asks the control plane to report the build's stages over the same call (issue #503), which is what makes a build that runs for minutes survivable across a proxy with a read timeout. It changes nothing else: the same endpoint, the same body, the same budget, and the same errors — a guardrail hold included, which arrives as an *APIError with NeedsConfirmation either way, because a build's hold is decided after its stages are already on the wire and therefore travels in the stream carrying the status it would have been written with.
func (*Client) Capacity ¶ added in v0.13.0
func (c *Client) Capacity(ctx context.Context) (CapacityReport, error)
Capacity reports the cluster's scheduling capacity and headroom, read live (issue #275). It is read-only — it changes nothing and carries no secret value.
func (*Client) Checks ¶
Checks reports the deploy-time dependency check for an app (ADR-0076 §4). An empty env reads the default environment. It runs no check — it reports what one would do.
func (*Client) ClaimFirstPrincipal ¶
ClaimFirstPrincipal records this install's first principal under name and returns the credential issued to them (ADR-0084 §1, §2). The first claimant becomes the install's admin.
It is refused with CodeAlreadyClaimed on an install that already has a principal, which is the ordinary answer for anybody but the first person and is not a failure of anything: the caller's existing access is untouched, and an admin issues them a credential of their own.
func (*Client) Cluster ¶ added in v0.6.0
func (c *Client) Cluster(ctx context.Context) (ClusterCapabilities, error)
Cluster reports the cluster's capabilities, read live (ADR-0034). It is read-only — it changes nothing and carries no secret value.
func (*Client) Config ¶ added in v0.7.0
Config returns the app's non-secret config store (ADR-0028). env names the target environment (ADR-0035 phase 2b).
func (*Client) ConfigureAddon ¶
func (c *Client) ConfigureAddon(ctx context.Context, addonType, env, instance, setting, value string, confirm bool) (ConfigureAddonResult, error)
ConfigureAddon changes one setting on an add-on instance that already exists (ADR-0082) — its standby count or its volume size.
Growing proceeds. A shrink of the standby count is held until confirm is true, and a shrink of the volume is refused whatever confirm says, because a volume cannot shrink: the refusal comes back here rather than being written into a `Cluster` that then sits in a failed state.
func (*Client) ConnectAddon ¶ added in v0.4.0
func (c *Client) ConnectAddon(ctx context.Context, backend, endpoint, secretKey, token string) (Addon, error)
ConnectAddon registers an existing backend the user already runs (e.g. an in-cluster Loki) as a queryable add-on, recording its endpoint (ADR-0026). Unlike install it deploys nothing. secretKey, when non-empty, names the key in the burrow-credentials Secret under which the backend's bearer token lives; token is the bearer token VALUE for an authenticated backend, which travels over burrowd's authenticated, TLS-protected API and is written to the Secret (ADR-0030) — never logged, never stored in Postgres, never echoed back, never over MCP. Pass an empty token (and empty secretKey) for an unauthenticated backend.
func (*Client) DeleteApp ¶ added in v0.4.0
DeleteApp removes an app entirely — its workload, routing, and release history — in the target environment (ADR-0035 phase 2b). The delete is guarded and held for confirmation by default; pass confirm=true to proceed past the hold.
The ENVIRONMENT RIDES THE ROUTE (see guardPath). It is the one parameter on this call that decides WHICH app is destroyed, and against a control plane that predates named environments a query parameter naming staging is dropped and the PRODUCTION app is deleted instead — workload, routing and release history — under a line that says staging (issue #485).
func (*Client) Deploy ¶
func (c *Client) Deploy(ctx context.Context, app string, req DeployRequest) (DeployResult, error)
Deploy applies an image to an app. It takes the DEPLOY budget, not the default one: a deploy runs the app's lifecycle hooks and waits for the rollout to settle whenever there is something to wait for — a `post-deploy` hook to tell (ADR-0072 §4), or a dependency Burrow derived from an attached database or a published port to check (ADR-0076 §4) — and that wait is bounded by an operational limit, not by anything this client picked (issue #404).
Setting req.Progress asks the control plane to report the deploy's stages over the same call (issue #480). It changes nothing else: the same endpoint, the same body, the same budget, and the same errors — including a guardrail hold, which still arrives status-coded because the control plane writes the stream's header only once it has committed to doing work. The ENVIRONMENT RIDES THE ROUTE (see narrowing). It was a body field, and a control plane that predates named environments drops a body field it does not know exactly as it drops an unknown query parameter, so a deploy aimed at staging replaces what is RUNNING IN PRODUCTION and reports the release as staging's (issue #485).
func (*Client) DetachAddon ¶ added in v0.6.0
func (c *Client) DetachAddon(ctx context.Context, addonType, app, env string, opts DetachAddonOptions) error
DetachAddon detaches an app from an add-on: it removes the variable the connection string was written under and drops the app's login role, and KEEPS the database (ADR-0090 §1). With opts.DeleteData the database is destroyed as well. It is held for confirmation by a guardrail by default; opts.Confirm proceeds past the hold.
WHAT HAPPENS TO THE DATA RIDES THE ROUTE, and both dispositions are routes, because on this call too it is the ABSENCE of the parameter that would destroy. ADR-0090 inverted the default — before it, a detach dropped the database unconditionally — so a current client that says nothing, MEANING KEEP MY DATA, is exactly the request an older control plane answers by destroying it. A query parameter cannot express that: its absence is indistinguishable from a caller that never had it. A control plane that has neither route refuses both detaches with nothing touched (issue #485).
The ENVIRONMENT RIDES THE ROUTE too (see guardPath). A control plane that predates per-environment add-ons drops the body field it does not know exactly as it drops an unknown query parameter, so a detach aimed at staging would land on the default environment's instance — production's database, reached, reported as staging's.
func (*Client) DisableAutoscale ¶ added in v0.8.0
DisableAutoscale turns autoscaling off for an app by removing its HorizontalPodAutoscaler (ADR-0006). It is idempotent: removing autoscaling from an app that has none succeeds.
func (*Client) Expose ¶ added in v0.2.0
func (c *Client) Expose(ctx context.Context, app, env, host string, port int32, tls bool, issuer string, confirm bool) (ExposeResult, error)
Expose publishes an app at a hostname in one environment. It is the primitive beneath Publish — routing only, with no DNS, no pre-flight and no wait — and stays available as one.
The ENVIRONMENT RIDES THE ROUTE (see narrowing): against a control plane that drops it, a hostname meant for staging is pointed at PRODUCTION's workload, and a certificate is issued for it (issue #485).
func (*Client) Failures ¶
func (c *Client) Failures(ctx context.Context, f FailureQuery) (FailureReport, error)
Failures lists what is broken across everything Burrow manages, with the observation coverage behind the answer (ADR-0074 §8). It is read-only, it reads the ledger rather than the cluster, and it never claims a cause: two rows sharing a reason and a minute are a correlation the caller may act on, not a diagnosis Burrow asserts.
func (*Client) Guardrails ¶ added in v0.2.0
Guardrails lists the control-plane guardrails and their current dispositions. An empty scope lists the global policy; a named environment lists its effective policy under the env to global to default fallback, and a name narrows that to one app or add-on instance, each entry marking which tier its disposition came from (ADR-0035 phase 2c, ADR-0085 §4).
A control plane too old to know the name tier answers the name-scoped route with a 404, which becomes a refusal rather than the environment's policy relabelled as one app's (see guardPath).
func (*Client) Health ¶
Health returns an app's declared health endpoint and the readiness probe Burrow authors from it (ADR-0076). An empty env reads the default environment.
func (*Client) History ¶ added in v0.13.0
History returns an app's deploy timeline: the releases recorded for it, newest first — what versions the app has been rolled to, when, and whether each landed (the release Status conveys success or failure). It is read-only; the release records have no write or delete path through this client. env names the target environment (ADR-0035 phase 2b); empty is the default.
func (*Client) Hooks ¶
Hooks returns the lifecycle hooks configured for an app in the target environment (ADR-0072 §1). A phase with no hook is absent from the result: unset means no hook and today's behaviour exactly.
func (*Client) InstallAddon ¶ added in v0.4.0
func (c *Client) InstallAddon(ctx context.Context, addonType, env string, opts InstallAddonOptions) (Addon, error)
InstallAddon installs the vetted backing service for an add-on type (e.g. "logs") in one environment. Each environment gets its own instance (ADR-0067 §1); an empty env targets the default environment `prod`, which keeps the instance an existing install already has.
BOTH NARROWINGS RIDE THE ROUTE (see narrowing), because both decide what gets created rather than how the call is answered. Against a control plane that drops the environment, the instance stands up as the DEFAULT environment's — and if one is already there, an install meant to give staging its own Postgres lands on production's. Against one that drops the archive destination, the instance is created with NO write-ahead-log archiving and reported as installed: a database with no way back, indistinguishable from one with a repository behind it until the day it is needed (issue #485).
func (*Client) InvitePrincipal ¶
func (c *Client) InvitePrincipal(ctx context.Context, name string, admin bool) (ClusterCredential, error)
InvitePrincipal records a principal on this install, if they are not recorded already, and returns an INVITATION for them: a credential whose only power is to be exchanged, once, for the one they will carry (ADR-0084 §2). It is an admin action.
The returned Token is what is handed over. It expires, it is spent on first use, and burrowd refuses it at every route but the exchange — which is what makes handing it over a different act from handing over a working credential.
func (*Client) IssueAgentCredential ¶
func (c *Client) IssueAgentCredential(ctx context.Context) (ClusterCredential, error)
IssueAgentCredential asks for a credential for the calling person's AGENT (ADR-0084 §3): the same principal, a separate row, revocable on its own — so cutting the agent off does not sign the person out, and the audit trail records which of the two acted.
It sends no body. The principal is whoever this client is authenticated as, and the kind is the route's rather than the request's: a caller that could name a kind could ask to be issued the credential whose guardrails suit it.
func (*Client) Limits ¶
Limits lists the operational limits and their effective values. An empty env reads the cluster tier; a named environment reads its effective configuration under the environment to cluster to default fallback, each entry marking which tier its value came from (ADR-0068 §3).
func (*Client) ListEnvironments ¶ added in v0.7.0
func (c *Client) ListEnvironments(ctx context.Context) ([]Environment, error)
ListEnvironments lists the environments the cluster's burrowd knows about (ADR-0035 phase 2): the default environment `prod` first, then the ones added later in name order.
func (*Client) MountSecret ¶
func (c *Client) MountSecret(ctx context.Context, app, env, key, filename, dir string, noEnv *bool) (SecretMounts, error)
MountSecret projects one of an app's secret keys into a file and rolls the running workload so the file reaches its pods (ADR-0089 §1). filename is empty for "name the file after the key"; dir is empty unless the app moves its whole secrets directory, which is per app and never per key (§2).
The key must ALREADY BE SET or the control plane refuses: mounting a key that was never set produces an app that starts, finds no file, and fails at the moment it needs the credential.
noEnv marks the key file-only (§4) and is nil for "leave that as it is", so a mount that only renames a file does not put a credential back into the environment. Passing true here is what takes the app off the envFrom fast path.
func (*Client) NextTag ¶ added in v0.13.0
NextTag returns the suggested next semver release tags for app in env, from its current running tag (ADR-0052 §8). It is read-only: it reads the running tag the control plane already knows and computes the next patch/minor/major, so the agent can apply the number to its build. An empty env reads the default environment.
func (*Client) Publish ¶
func (c *Client) Publish(ctx context.Context, app string, req PublishRequest) (PublishResult, error)
Publish makes an app reachable at a hostname in one call: the Service and Ingress, the DNS record when a provider is configured, the pre-flight that proves the path before a certificate is asked for, and the wait for that certificate (ADR-0041 §3). The result is the converged verdict — a publish that did not end live carries Reachable false with the link it is blocked on, never a bare URL.
It waits on the cluster, so it carries the publish budget rather than the default one: the control plane's own bound for the call plus a margin (see timeouts.go).
func (*Client) QueryLogs ¶ added in v0.4.0
func (c *Client) QueryLogs(ctx context.Context, query string, limit int, backend string) ([]LogEntry, error)
QueryLogs queries the installed logs add-on with a LogsQL query (empty matches everything). A non-empty backend targets a specific logs add-on (by its concrete backend or registry name) when more than one serves the logs capability; empty picks the first.
func (*Client) QueryMetrics ¶ added in v0.4.0
func (c *Client) QueryMetrics(ctx context.Context, query string, backend string) ([]MetricSample, error)
QueryMetrics runs an instant PromQL query against the connected metrics add-on (e.g. Prometheus). A non-empty backend targets a specific metrics add-on (by its concrete backend or registry name) when more than one serves the metrics capability; empty picks the first.
func (*Client) Reachability ¶ added in v0.2.0
Reachability reports whether an app is reachable at its hostname, link by link, in the target environment (ADR-0035 phase 2b).
func (*Client) RedeemInvitation ¶
func (c *Client) RedeemInvitation(ctx context.Context) (ClusterCredential, error)
RedeemInvitation exchanges the invitation this client is carrying for the credential its holder will use (ADR-0084 §2). It sends no body: the invitation is on the request, and what it is worth is burrowd's record rather than anything the caller could say about it.
THE CREDENTIAL IT RETURNS WAS GENERATED FOR THIS CALL, on this machine, which is why the exchange exists at all.
func (*Client) RemoveAddon ¶ added in v0.4.0
func (c *Client) RemoveAddon(ctx context.Context, name string, opts RemoveAddonOptions) (RemoveAddonResult, error)
RemoveAddon removes the named add-on instance. With opts.DeleteData the add-on's data volume is destroyed too, and — where an object-storage provider is registered — burrowd takes a final backup of every attached database first and refuses the whole removal if it does not reach the store (ADR-0064 §5).
WHAT HAPPENS TO THE DATA RIDES THE ROUTE, and unlike every other case that follows the rule (see guardPath) there is no unnarrowed form to fall back to: BOTH dispositions are routes, because on this call it is the ABSENCE of the parameter that destroys. `delete_data` inverted the default (issue #323) — before it, a removal destroyed the volume unconditionally — so a current client that says nothing, MEANING KEEP MY DATA, is the request an older control plane answers by destroying the volume, with no final backup to fall back on because it takes none. A query parameter cannot express that: its absence is indistinguishable from a caller that never had it. A route can, and a control plane that has neither route refuses both removals with nothing touched (issue #485).
func (*Client) RemoveDomain ¶ added in v0.2.0
func (c *Client) RemoveDomain(ctx context.Context, host, provider string, confirm bool) (DomainResult, error)
RemoveDomain removes the DNS record the provider holds for host.
func (*Client) RestoreAddon ¶ added in v0.6.0
func (c *Client) RestoreAddon(ctx context.Context, addonType, app, backupID, env, instance string, confirm bool) error
RestoreAddon restores an app's database from a recorded backup, overwriting its live contents (ADR-0032). It is held for confirmation by a guardrail by default; pass confirm=true to proceed.
The ENVIRONMENT RIDES THE ROUTE, for the reason DetachAddon's does: a restore aimed at staging, against a control plane that drops the field, overwrites the live database of whatever app of that name is on the default environment's instance (issue #485).
func (*Client) RestoreInstance ¶
func (c *Client) RestoreInstance(ctx context.Context, addonType, env string, opts RestoreInstanceOptions) (RestoreInstanceResult, error)
RestoreInstance rewinds one environment's WHOLE Postgres instance to a point in its object-storage repository (ADR-0066 §4): every database on it goes back together, the instance is replaced by one recovered from the repository, and every attached app is re-pointed at it and restarted.
It is NOT the same operation as RestoreAddon, and the difference is the blast radius rather than the mechanism. RestoreAddon replaces one app's database from that app's own dump and touches no other app; this replaces the instance every app in the environment shares. It is held for confirmation by the addon.restore_instance guardrail by default.
It takes its own budget: a recovery waits for a base backup to be restored and write-ahead log replayed, which is bounded by how much data there is rather than by a Job's timeout.
func (*Client) Rollback ¶
func (c *Client) Rollback(ctx context.Context, app, env string, opts RollbackOptions) (RollbackResult, error)
Rollback returns an app to its previous release. It takes the deploy budget: a rollback runs the `pre-rollback` hook and then waits for the rollout to settle, reports what it observed, and tells the `post-deploy` hook the same way a deploy does (ADR-0072 §8, ADR-0093 §1), so it waits on the same server-side bounds.
The ENVIRONMENT RIDES THE ROUTE (see narrowing): a rollback aimed at staging, against a control plane that drops the parameter, replaces what is running in PRODUCTION with production's previous release (issue #485). `confirm` and `skip_hooks` stay parameters — neither decides what the rollback touches, and an ignored `confirm` makes an older server HOLD, never proceed.
func (*Client) Run ¶ added in v0.12.0
Run executes a one-off command in an app's own current image and environment (ADR-0048). It returns a structured result carrying the command's captured output and exit code; a non-zero exit is a normal outcome, not an error. It is gated by the app.run guardrail (confirm by default): a held run returns a guardrail error the caller surfaces for confirmation, re-invoking with Confirm set only on explicit human approval.
func (*Client) Scale ¶
func (c *Client) Scale(ctx context.Context, app, env string, replicas int32, confirm bool) (ScaleResult, error)
Scale sets an app's replica count in one environment.
The ENVIRONMENT RIDES THE ROUTE (see narrowing). It was a body field, and against a control plane that drops it a scale aimed at staging resizes PRODUCTION — and a scale to zero stops production serving (issue #485).
func (*Client) SecretMounts ¶
SecretMounts returns which of an app's secret keys are projected into files, and where (ADR-0089 §1). It is a read of key names and filenames; a value never appears on this path.
func (*Client) Secrets ¶ added in v0.5.0
Secrets returns the KEYS in an app's per-app Secret, never the values (ADR-0028/0004). Secret values live only in the Kubernetes Secret; a list reads keys only and never returns a value. env names the target environment (ADR-0035 phase 2b), whose namespace holds the per-app Secret.
func (*Client) SetAutoDeploy ¶ added in v0.13.0
func (c *Client) SetAutoDeploy(ctx context.Context, app, env, level string) (AutoDeployResult, error)
SetAutoDeploy sets the auto-deploy level for app in env and returns the updated configuration (ADR-0052 §6). Setting the level is a human operator action, so it lives on this admin client only — there is no agent verb for it.
func (*Client) SetChecks ¶
func (c *Client) SetChecks(ctx context.Context, app, env string, enabled bool) (ChecksResult, error)
SetChecks turns the deploy-time dependency check on or off for app in env (ADR-0076 §4).
func (*Client) SetConfig ¶ added in v0.7.0
SetConfig upserts one non-secret config var for an app (ADR-0028). By default the running workload rolls so the app picks the value up; noRestart only persists, landing the change on the next deploy.
func (*Client) SetGuardrail ¶ added in v0.2.0
func (c *Client) SetGuardrail(ctx context.Context, scope GuardScope, code, disposition string) ([]Guardrail, error)
SetGuardrail sets a guardrail's disposition and returns the updated policy. An empty scope sets the global disposition; a named environment scopes it to that environment, storing the env-prefixed code (ADR-0035 phase 2c); a name scopes it to one app or add-on instance in that environment, storing env.name.code (ADR-0085 §1).
A control plane too old to know the name tier answers the name-scoped route with a 404, so the write is refused instead of landing one tier wider than it was meant to (see guardPath).
func (*Client) SetHealth ¶
func (c *Client) SetHealth(ctx context.Context, app, env, path string, port int32) (HealthResult, error)
SetHealth declares the health endpoint app serves in env and re-applies the running workload so the probe reaches its pods (ADR-0076 §5). A zero port means "the port the app is published on".
func (*Client) SetHook ¶
func (c *Client) SetHook(ctx context.Context, app, env, phase string, command []string) (Hook, error)
SetHook configures the command an app runs at a phase, replacing any command already set there (ADR-0072 §1). A pre-deploy hook runs on EVERY deploy of the app in that environment, automated ones included, so a command that starts failing blocks deploys until someone changes it.
func (*Client) SetLimit ¶
SetLimit sets an operational limit's value and returns the updated configuration. An empty env sets the cluster value; a named environment scopes it to that environment, storing the env-prefixed code (ADR-0068 §3). It is on this client because it is on the operator CLI: `burrow-agent` carries no command that reaches it (ADR-0068 §4).
func (*Client) SetSecret ¶ added in v0.5.0
SetSecret upserts one secret key=value for an app (ADR-0029). The value travels over burrowd's authenticated, TLS-protected control-plane API, which writes it to the per-app Kubernetes Secret; it is never logged, never stored in Postgres, and is still never carried over MCP (there is no secret-set MCP tool). By default the running workload rolls so it picks the value up; with noRestart the change only persists and lands on the next deploy.
The ENVIRONMENT RIDES THE ROUTE (see narrowing). The secrets route is older than named environments, so against a control plane in between, a value meant for staging is written into PRODUCTION's Secret and the production workload is rolled to pick it up — and a secret cannot be unwritten from the place it should never have reached (issue #485). The refusal names the KEY and never the value, like everything else on this path.
func (*Client) Unexpose ¶ added in v0.2.0
Unexpose withdraws an app's published hostname in one environment.
The ENVIRONMENT RIDES THE ROUTE (see narrowing): against a control plane that drops it, unexposing staging takes PRODUCTION's ingress and routing down (issue #485).
func (*Client) UnmountSecret ¶
UnmountSecret stops projecting one key as a file and rolls the running workload so the file leaves its pods (ADR-0089 §1). The value is untouched: the key stays in the Secret and stays in the app's environment, so an unmount is not a way to lose a credential.
func (*Client) UnsetConfig ¶ added in v0.7.0
UnsetConfig removes one config var for an app (ADR-0028). By default the running workload rolls; with noRestart the removal only persists and lands on the next deploy. env names the target environment (ADR-0035 phase 2b).
func (*Client) UnsetHealth ¶
UnsetHealth removes app's declared endpoint, returning it to the conservative default — a TCP check on the published port, or no probe when the app is not published (ADR-0076 §3).
func (*Client) UnsetHook ¶
UnsetHook removes an app's hook at a phase. Unsetting a phase with no hook succeeds; afterwards that phase runs nothing.
func (*Client) UnsetSecret ¶ added in v0.5.0
UnsetSecret removes one key from an app's per-app Secret (ADR-0028). Removing a key carries no value, so it is allowed over the API/MCP. By default the running workload rolls so it drops the value; with noRestart the change only persists and lands on the next deploy. env names the target environment (ADR-0035 phase 2b).
The ENVIRONMENT RIDES THE ROUTE, for the reason SetSecret's does: against a control plane that drops it, removing staging's key takes the value PRODUCTION is running on out from under it and rolls the workload (issue #485).
func (*Client) WaitReachable ¶ added in v0.6.0
func (c *Client) WaitReachable(ctx context.Context, app, env string, timeout time.Duration, after func(time.Duration) <-chan time.Time) (ReachabilityResult, error)
WaitReachable polls Reachability until the app converges to live (Reachable) or timeout elapses, then returns the last verdict. It is the thin-client wait-until-live behind `burrow app reachability --wait` and the burrow_reachability MCP tool's wait mode; the control-plane engine stays point-in-time, so the polling and the clock live here, never in the engine (ADR-0034 slice 3).
A returned result with Reachable true means the app is live at result.URL; a returned result with Reachable false means the timeout elapsed and result.BlockedOn names the link to fix. after supplies the poll clock as a one-shot timer channel so tests can drive the loop without real time; pass nil for the real clock (time.After).
type CloudNativePGCapability ¶
type CloudNativePGCapability struct {
Present bool `json:"present"`
Ready bool `json:"ready"`
Version string `json:"version,omitempty"`
Pinned string `json:"pinned,omitempty"`
}
CloudNativePGCapability reports the CloudNativePG operator (ADR-0066 §1). Present is whether its API group is served (the CRDs are installed); Ready is whether a controller is actually running, which is separate because a CRD outlives the operator that installed it; Version is the running operator's release and Pinned the release Burrow targets.
type ClusterCapabilities ¶ added in v0.6.0
type ClusterCapabilities struct {
Ingress IngressCapability `json:"ingress"`
Storage StorageCapability `json:"storage"`
LoadBalancer LoadBalancerCapability `json:"load_balancer"`
CertManager CertManagerCapability `json:"cert_manager"`
MetricsServer MetricsServerCapability `json:"metrics_server"`
CloudNativePG CloudNativePGCapability `json:"cloudnative_pg"`
PgBackRest PgBackRestCapability `json:"pgbackrest"`
// ControlPlaneDatabase is which shape the control plane's own database runs in (ADR-0086 §2).
ControlPlaneDatabase ControlPlaneDatabaseCapability `json:"control_plane_database"`
Provider ProviderCapability `json:"provider"`
DNS DNSCapability `json:"dns"`
}
ClusterCapabilities mirrors the control plane's neutral, read-only report of what the cluster can do (ADR-0034): an ingress controller and its IngressClass, a default StorageClass, LoadBalancer support, cert-manager, the cloud provider, and whether a DNS provider is configured. It carries no secret value.
type ClusterCredential ¶
type ClusterCredential struct {
// PrincipalID is the opaque, stable identity this credential authenticates as.
PrincipalID string `json:"principal_id"`
// Principal is that principal's human-readable handle.
Principal string `json:"principal"`
// Admin is whether the principal may issue a credential for somebody else.
Admin bool `json:"admin"`
// CredentialID is which credential this is, so a revocation can name it.
CredentialID string `json:"credential_id"`
// Kind is what the credential is held by, as burrowd STORED it. It is reported, never chosen:
// a caller-declared kind would make a `deny` that binds the agent cooperative (ADR-0084 §3).
Kind string `json:"kind"`
// ExpiresAt is when the credential stops authenticating, RFC 3339, or empty when it does not.
ExpiresAt string `json:"expires_at,omitempty"`
// InstallID is the id of the install that issued this. It is what lets the caller record, in the
// same round trip, which Burrow the credential belongs to (ADR-0084 §5) — a fact a second person
// has no other authenticated way to learn before they hold a credential.
InstallID string `json:"install_id,omitempty"`
// Token is the secret. See the type's own note.
Token string `json:"token"`
}
ClusterCredential is one credential a self-hosted install issued, as it comes back over the wire.
IT CARRIES THE TOKEN IN THE CLEAR, exactly once. burrowd stored only a hash and will not produce the token again, so a caller that drops this value has to be issued another credential. Nothing should log it, put it in an error, or return it in a message; the fields around it — the ids, the name, the kind — are the ones that are safe to print.
type ConfigureAddonResult ¶
type ConfigureAddonResult struct {
Addon string `json:"addon"`
Environment string `json:"environment"`
Instance string `json:"instance"`
Setting string `json:"setting"`
From string `json:"from"`
To string `json:"to"`
// Changed is false when the instance was already in the shape that was asked for; nothing was
// written and nothing was restarted.
Changed bool `json:"changed"`
ReadAddress ReadAddressChange `json:"read_address"`
}
ConfigureAddonResult is what one change to an instance's shape did, with the values either side of it: "standbys is 1" does not say whether anything happened, and "0 -> 1" does.
type Consumer ¶ added in v0.13.0
type Consumer struct {
Namespace string `json:"namespace"`
Name string `json:"name"`
Node string `json:"node,omitempty"`
CPUMillis int64 `json:"cpu_millis"`
MemBytes int64 `json:"mem_bytes"`
}
Consumer is one pod's contribution (its resource request, not live usage) to the committed total, for the top-consumers lists. CPUMillis is milli-CPU; MemBytes is bytes.
type ControlPlaneDatabaseCapability ¶
type ControlPlaneDatabaseCapability struct {
Kind string `json:"kind,omitempty"`
Ready bool `json:"ready"`
BackedUp bool `json:"backed_up"`
}
ControlPlaneDatabaseCapability reports which of the two shapes the control plane's own database runs in (ADR-0086 §2). Kind is "cloudnativepg" or "plain", empty when the control plane could not read it; Ready is whether an instance is serving; BackedUp is whether it archives off-cluster, which a "plain" database never does and a "cloudnativepg" one does once an object-storage provider is registered.
type Coverage ¶
type Coverage struct {
Since time.Time `json:"since"`
Until time.Time `json:"until"`
Windows []ObservationWindow `json:"windows"`
Gaps []CoverageGap `json:"gaps"`
DegradedSweeps int64 `json:"degraded_sweeps,omitempty"`
Detail string `json:"detail,omitempty"`
}
Coverage is what the observer was doing over the period an answer describes. It travels with every answer rather than being available on request, because an empty failure list means "nothing broke" only when something was watching (ADR-0074's consequences).
type CoverageGap ¶
CoverageGap is a stretch of time no observer was recording — a literal gap between two runs of the observer, not an inference. Failures that began and ended inside it were never seen.
func (CoverageGap) Duration ¶
func (g CoverageGap) Duration() time.Duration
Duration is how long the gap lasted.
type DNSCapability ¶ added in v0.6.0
type DNSCapability struct {
Configured bool `json:"configured"`
Providers []string `json:"providers,omitempty"`
}
DNSCapability reports whether a DNS provider is configured in the registry (ADR-0023).
type Dependency ¶
type Dependency struct {
Kind string `json:"kind"`
Provisioned string `json:"provisioned"`
EnvKey string `json:"env_key,omitempty"`
Endpoint string `json:"endpoint,omitempty"`
}
Dependency is one thing Burrow provisioned for an app and can therefore check at deploy time (ADR-0076 §4). It carries no credential: EnvKey is a key NAME the app already reads, and Endpoint is an in-cluster address Burrow composed.
type DependencyResult ¶
type DependencyResult struct {
Kind string `json:"kind"`
Outcome string `json:"outcome"`
Reason string `json:"reason,omitempty"`
Detail string `json:"detail,omitempty"`
Status int `json:"status,omitempty"`
}
DependencyResult is what one deploy-time dependency check found: passed, failed, or skipped, with a reason from a closed set and one bounded Burrow-authored line. A failed result never means the deploy failed — the check is reported, never fatal (ADR-0076 §4).
type DeployProgress ¶
DeployProgress is one stage transition of a running deploy or build: which stage the control plane is in, and what happened to it. Both are members of the control plane's closed vocabularies (controlplane.DeployStages or controlplane.BuildStages, and controlplane.DeployStatuses); a value outside them is a newer control plane's, and a caller renders it rather than failing on it.
type DeployRequest ¶
type DeployRequest struct {
Env string `json:"env,omitempty"`
Image string `json:"image"`
Command []string `json:"command,omitempty"`
MetricsPort int32 `json:"metrics_port,omitempty"`
Replicas int32 `json:"replicas"`
Confirm bool `json:"confirm,omitempty"`
// NoWait asks the control plane to answer at submission instead of at outcome (ADR-0092 §3): the
// Deployment is written and the deploy returns without observing whether the new pods became
// ready, so DeployResult.Rollout is nil. The default — waiting — is the zero value.
NoWait bool `json:"no_wait,omitempty"`
// Progress receives the deploy's stages as the control plane reports them (issue #480). Setting
// it is what asks for them: Deploy then negotiates the streaming response, and a control plane
// that does not offer one is handled transparently. Nil — the default, and the shape that goes on
// the wire, since json ignores this field — is the deploy this package has always issued.
//
// It is called from Deploy's own goroutine as each line arrives, so a slow reporter slows the
// read. It is never called after Deploy returns.
Progress func(DeployProgress) `json:"-"`
}
DeployRequest carries a deploy's code-free metadata. The non-secret config is deliberately absent: an app's config is an independently-managed store, set with SetConfig and sourced at apply time rather than passed per deploy (ADR-0028). Env names the target environment (ADR-0035 phase 2b): empty or "prod" targets the default environment's namespace, a name added later targets that environment's namespace.
type DeployResult ¶
type DeployResult struct {
Release Release `json:"release"`
SupersededReleaseID string `json:"superseded_release_id,omitempty"`
// Hints are non-blocking notes about the deploy (ADR-0052 §8): today, a nudge toward semver when
// the deployed tag cannot be classified for auto-update. They never gate the deploy.
Hints []string `json:"hints,omitempty"`
// Dependencies is what the deploy-time dependency check found (ADR-0076 §4): for each thing
// Burrow provisioned for this app, whether the app could reach it from inside its own container.
// A failed entry sits on a SUCCESSFUL deploy — the check is reported, never fatal.
Dependencies []DependencyResult `json:"dependencies,omitempty"`
// Rollout is what the deploy observed of its own rollout (ADR-0092): whether the new replicas
// became ready, and if not, why. NIL MEANS UNOBSERVED and never "fine" — a deploy that was asked
// not to wait (DeployRequest.NoWait), or a control plane older than the field.
Rollout *RolloutReport `json:"rollout,omitempty"`
}
type DetachAddonOptions ¶
type DetachAddonOptions struct {
// Instance is the LABEL of the instance to detach from (ADR-0091 §3). Empty is the environment's
// default instance; detaching one attachment leaves every other one the app holds alone.
Instance string
// DeleteData also DESTROYS the app's database, with its rows (ADR-0090 §2). Without it the detach
// takes the app's access away and keeps the data, so re-attaching gets it back.
DeleteData bool
// Confirm satisfies the addon.detach guardrail hold. It is not the data-loss acknowledgement.
Confirm bool
}
DetachAddonOptions is everything a detach carries beyond the add-on and the app. It is a struct rather than two positional booleans because one of them destroys an application's database and the other does not, and a reader of `DetachAddon(ctx, "postgres", "web", "", true, true)` cannot tell which is which.
type DirectTransport ¶ added in v0.10.0
type DirectTransport struct {
BaseURL string
Token string
// Name is the calling binary (ClientNameCLI or ClientNameAgent), sent as X-Burrow-Client so a
// too-old refusal names the binary the user must actually update (ADR-0039). Empty omits it.
Name string
// Version is this client's release version, sent as X-Burrow-Client-Version so burrowd can make
// version skew legible instead of opaque (ADR-0039). Empty omits the header.
Version string
// InstallID is the install this caller expects to reach, sent as X-Burrow-Install so a control
// plane that is a different install refuses the request and says so (ADR-0084 §5). Empty omits
// the header, and is served.
InstallID string
}
DirectTransport talks to a control-plane URL directly (e.g. an ingress) with an API token, selected by --control-plane/--token (or BURROW_CONTROL_PLANE_URL/BURROW_API_TOKEN). NewClient wires the X-Burrow-Token RoundTripper, so the direct path sends the same header as the kubeconfig proxy path (ADR-0015, ADR-0045).
It lives here rather than in the connect package because it needs only NewClient and no client-go, keeping this package client-go-free while remaining importable by both binaries and a private module (ADR-0045).
type DomainResult ¶ added in v0.2.0
type DomainResult struct {
Host string `json:"host"`
Provider string `json:"provider"`
Type string `json:"type,omitempty"`
Address string `json:"address,omitempty"`
}
DomainResult mirrors the control plane's DNS-record outcome (ADR-0018).
type Environment ¶ added in v0.7.0
type Environment struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
Default bool `json:"default"`
}
Environment mirrors a control-plane environment (ADR-0035 phase 2): a namespace-per-environment target. Name is the handle (a DNS-1123 label), Namespace the Kubernetes namespace its apps deploy into, and Default marks the default environment `prod` (the app namespace burrowd runs against).
type ExposeResult ¶ added in v0.2.0
type Failure ¶
type Failure struct {
ID int64 `json:"id,omitempty"`
Object ObjectRef `json:"object"`
// Reason is a member of the ledger's closed vocabulary — the field to branch on, in preference
// to parsing Detail.
Reason string `json:"reason"`
// Detail is one bounded, Burrow-authored line of context. It never carries a secret value.
Detail string `json:"detail,omitempty"`
// FirstSeen is when the failure began: the answer to "when did it start".
FirstSeen time.Time `json:"first_seen"`
// LastSeen is when it was last observed: the answer to "is it still happening".
LastSeen time.Time `json:"last_seen"`
// ResolvedAt is when it stopped being observed, nil while it is still active.
ResolvedAt *time.Time `json:"resolved_at,omitempty"`
// Occurrences is how many observations found it present, counting the one that opened the row.
Occurrences int64 `json:"occurrences"`
}
Failure is one ledger row: a failure with a lifetime rather than an event (ADR-0074 §4).
type FailureKind ¶
type FailureKind = string
FailureKind names the class of managed object a ledger row is about.
const ( FailureApp FailureKind = "app" FailureAddon FailureKind = "addon" FailureBackup FailureKind = "backup" FailureExposure FailureKind = "exposure" )
The classes of object the ledger records against (controlplane.FailureKind).
func FailureKinds ¶
func FailureKinds() []FailureKind
FailureKinds returns every kind the --kind filter accepts, in the order they are documented.
type FailureQuery ¶
type FailureQuery struct {
// Kind restricts to one class of object (app, addon, backup, exposure); empty matches any.
Kind FailureKind
// Name restricts to one object name; empty matches any.
Name string
// Env restricts to one environment; empty matches any.
Env string
// Reason restricts to one reason from the ledger's closed vocabulary; empty matches any.
Reason string
// Since bounds the answer to failures last seen within this much of now and widens it to
// history. It is sent as a duration and resolved against the CONTROL PLANE's clock, which is the
// clock that wrote the rows.
Since time.Duration
// All widens the answer to resolved failures with no time bound beyond the ledger's retention.
All bool
// Limit caps the rows returned. Zero applies the server's default cap.
Limit int
}
FailureQuery narrows the failure listing. A zero value lists every ACTIVE failure across everything Burrow manages — the question a reader has during an incident, which is "what is broken", not "what ever broke".
type FailureReport ¶
type FailureReport struct {
Failures []Failure `json:"failures"`
Coverage Coverage `json:"coverage"`
}
FailureReport is one answer from the ledger: the rows, and the coverage behind them. It is rows and NOT groups — grouping by shared reason is a presentation heuristic the human listing applies, and ADR-0074 §5 keeps it out of the wire format so a caller correlates on its own terms.
type GuardScope ¶
GuardScope selects whose guardrail policy is read or written: an environment, or one app or add-on instance within it (ADR-0085 §1). The zero value is the global policy. Which combinations are legal is the control plane's decision, not this client's — a name without an environment is refused there, so every client hears the same reason.
type Guardrail ¶ added in v0.2.0
type Guardrail struct {
Code string `json:"code"`
Disposition string `json:"disposition"`
Description string `json:"description"`
// Source reports where a guardrail's effective disposition came from when listed for something
// narrower than the whole cluster (ADR-0035 phase 2c, ADR-0085 §2): "name" (set for the one app
// or add-on instance asked about), "env" (an environment-specific override), "global" (the
// global policy), or "default" (the built-in default). It is empty in the global listing.
Source string `json:"source,omitempty"`
}
type HealthResult ¶
type HealthResult struct {
App string `json:"app"`
Environment string `json:"environment,omitempty"`
// Path and Port are the DECLARED endpoint; empty and zero when none was declared.
Path string `json:"path,omitempty"`
Port int32 `json:"port,omitempty"`
// Probe is what Burrow authors: "http", "tcp", or "none".
Probe string `json:"probe"`
ProbePort int32 `json:"probe_port,omitempty"`
ProbePath string `json:"probe_path,omitempty"`
// Source is where the probe came from: "endpoint", "exposure" (the conservative TCP default on
// the published port), or "none".
Source string `json:"source"`
// Liveness is always false: Burrow never sets a liveness probe by default (ADR-0076 §1). It is
// reported anyway because "does this restart my container?" is the first question a reader has.
Liveness bool `json:"liveness"`
// Hint is the ADR-0076 §5 guidance, present when no endpoint has been declared.
Hint string `json:"hint,omitempty"`
// AppliesOn says when the reported probe reaches the running pods, when it is not there yet.
AppliesOn string `json:"applies_on,omitempty"`
}
HealthResult is an app's health configuration (ADR-0076): the endpoint the user or their agent declared, and — the part that actually matters — the readiness probe Burrow authors on the container as a result, which is not the same fact. An endpoint declared before the app was published resolves to no probe at all, and a surface that reported only the declaration would let that gap sit unnoticed.
type Hook ¶
type Hook struct {
App string `json:"app"`
Environment string `json:"environment"`
Phase string `json:"phase"`
Command []string `json:"command"`
}
Hook is one configured lifecycle command: the phase it fires at and the command it runs, for one app in one environment (ADR-0072 §1). Phase is `pre-deploy` (before a deploy's image reaches the cluster, from that image) or `pre-rollback` (before a rollback's older image does, from the image being left). Command is an argv, so argument boundaries survive the round trip.
type IngressCapability ¶ added in v0.6.0
type IngressCapability struct {
Present bool `json:"present"`
Classes []string `json:"classes,omitempty"`
}
IngressCapability reports the ingress-controller situation. Present is true only when an ingress controller is actually running (not merely when an IngressClass exists — a cluster-scoped class can outlive its controller); Classes are the IngressClass names, reported independently of Present.
type InstallAddonOptions ¶
type InstallAddonOptions struct {
// Name is the LABEL of the instance to install: naming one stands a SECOND instance up beside the
// environment's own (ADR-0091 §1). Empty is the environment's default instance, which is what
// every add-on command has always meant.
Name string
// Confirm satisfies the addon.install guardrail's confirmation hold.
Confirm bool
// ArchiveDestination names the object-storage provider a Postgres instance archives to
// (ADR-0066 §3). Only needed when more than one is registered.
ArchiveDestination string
}
InstallAddonOptions is everything `addon install` carries beyond the add-on's type and its environment.
type LifecycleCheck ¶
type LifecycleCheck struct {
Status string `json:"status"`
Detail string `json:"detail"`
Rule string `json:"rule,omitempty"`
Backup string `json:"backup,omitempty"`
}
LifecycleCheck mirrors the outcome of reconciling a bucket's lifecycle rules against backup retention (ADR-0063 §3). Status is "ok", "conflict", or "unknown" — and "unknown" means the configuration could not be READ, so the invariant is not verified and must not be reported as though it were.
type Limit ¶
type Limit struct {
Code string `json:"code"`
Value string `json:"value"`
Description string `json:"description"`
Kind string `json:"kind"`
Scope string `json:"scope"`
EnvScoped bool `json:"env_scoped"`
Default string `json:"default"`
}
Limit is one operational limit and its effective value (ADR-0068): a bound a human sets, which is not a guardrail — there is no disposition on it, and exceeding it is refused rather than held. Scope reports which tier the effective value came from ("environment", "cluster", or "default"), EnvScoped whether it may be set for one environment at all, and Default the built-in value it reverts to.
type LoadBalancerCapability ¶ added in v0.6.0
type LoadBalancerCapability struct {
Supported bool `json:"supported"`
Inferred bool `json:"inferred"`
Provider string `json:"provider,omitempty"`
}
LoadBalancerCapability reports whether Service type=LoadBalancer is likely supported and by what: a cloud provider (billable), k3s's servicelb, or MetalLB. Provider names the mechanism (a cloud id, "servicelb", or "metallb"), empty when none is detected.
type LogEntry ¶ added in v0.4.0
type LogEntry struct {
Time string `json:"time,omitempty"`
Message string `json:"message"`
Pod string `json:"pod,omitempty"`
}
LogEntry is one record from a logs query.
type LogLine ¶
type LogLine struct {
Pod string `json:"pod"`
Timestamp time.Time `json:"timestamp"`
Message string `json:"message"`
}
LogLine is a single line of application log output. Timestamp is the instant the cluster recorded the line, in UTC, and is zero only when no time could be read for it; Message is the application's own output with that timestamp stripped off.
type MetricSample ¶ added in v0.4.0
type MetricSample struct {
Labels map[string]string `json:"labels,omitempty"`
Value string `json:"value"`
Time string `json:"time,omitempty"`
}
MetricSample is one sample from a metrics query. Value is the metric's value as a string so PromQL's exact numeric formatting is preserved.
type MetricsServerCapability ¶ added in v0.13.0
type MetricsServerCapability struct {
Present bool `json:"present"`
}
MetricsServerCapability reports whether metrics-server is serving the Kubernetes Metrics API (detected via the metrics.k8s.io API group). It powers `kubectl top`, HPA autoscaling, and the utilization layer of capacity reporting.
type NextTagResult ¶ added in v0.13.0
type NextTagResult struct {
App string `json:"app"`
Env string `json:"env"`
Current string `json:"current,omitempty"`
Next *NextTags `json:"next,omitempty"`
Note string `json:"note,omitempty"`
}
NextTagResult is the read-only next-semver-tag suggestion for an app in one environment (ADR-0052 §8): the current running tag plus the suggested next patch/minor/major tags. When there is no running release or the current tag is not semver, Next is nil and Note carries a short human reason — the suggestion degrades gracefully rather than erroring (ADR-0040).
type NextTags ¶ added in v0.13.0
type NextTags struct {
Patch string `json:"patch"`
Minor string `json:"minor"`
Major string `json:"major"`
}
NextTags are the suggested next release tags after a current semver tag (ADR-0052 §8).
type NodeCapacity ¶ added in v0.13.0
type NodeCapacity struct {
Name string `json:"name,omitempty"`
Pods int `json:"pods"`
AllocCPUMillis int64 `json:"alloc_cpu_millis"`
UsedCPUMillis int64 `json:"committed_cpu_millis"`
FreeCPUMillis int64 `json:"free_cpu_millis"`
AllocMemBytes int64 `json:"alloc_mem_bytes"`
UsedMemBytes int64 `json:"committed_mem_bytes"`
FreeMemBytes int64 `json:"free_mem_bytes"`
}
NodeCapacity is the allocatable / committed / free-headroom breakdown for one node, or the cluster-wide total when Name is empty. CPU figures are milli-CPU; memory figures are bytes.
type ObjectRef ¶
type ObjectRef struct {
Kind FailureKind `json:"kind"`
Name string `json:"name"`
Environment string `json:"environment,omitempty"`
}
ObjectRef identifies one object Burrow manages. The environment is part of the identity: the same app name in staging and in production is two objects.
type ObjectStoreConfig ¶
type ObjectStoreConfig struct {
Endpoint string `json:"endpoint"`
Region string `json:"region,omitempty"`
Bucket string `json:"bucket"`
Created bool `json:"created,omitempty"`
AccessKeyIDKey string `json:"access_key_id_key"`
SecretAccessKeyKey string `json:"secret_access_key_key"`
RetentionDays int `json:"retention_days,omitempty"`
}
ObjectStoreConfig mirrors the non-secret object-storage configuration on a provider row (ADR-0063 §1). It carries key NAMES, never key values.
type ObservationWindow ¶
type ObservationWindow struct {
ID int64 `json:"id,omitempty"`
StartedAt time.Time `json:"started_at"`
Until time.Time `json:"until"`
Sweeps int64 `json:"sweeps"`
DegradedSweeps int64 `json:"degraded_sweeps,omitempty"`
Detail string `json:"detail,omitempty"`
}
ObservationWindow is one continuous run of the observer.
type PgBackRestCapability ¶
type PgBackRestCapability struct {
Present bool `json:"present"`
Ready bool `json:"ready"`
Pinned string `json:"pinned,omitempty"`
}
PgBackRestCapability reports the CloudNativePG pgBackRest plugin (ADR-0066 §3), the component a Postgres instance archives its write-ahead log and takes its base backups through. Present is whether its API group is served; Ready is whether its controller is actually running; Pinned is the release Burrow targets. No running version is reported: the plugin's release artifact does not carry one Burrow can read back.
type Provider ¶ added in v0.2.0
type Provider struct {
Name string `json:"name"`
Type string `json:"type"`
Capabilities []string `json:"capabilities"`
SecretKey string `json:"secret_key"`
CreatedAt time.Time `json:"created_at"`
// ObjectStore is the non-secret destination an object-storage provider was registered with —
// endpoint, region, the RECORDED bucket, and the NAMES of the two burrow-credentials keys
// holding the credential pair (ADR-0063 §1). Nil for every other provider type.
ObjectStore *ObjectStoreConfig `json:"object_store,omitempty"`
// Verification is what configuration-time verification observed: the probe object written and
// deleted, the bucket, and the lifecycle reconciliation (ADR-0063 §2-§4). It is present on the
// registration that performed the checks and absent from a listing, because it describes one
// moment rather than a stored fact.
Verification *ProviderVerification `json:"verification,omitempty"`
}
Provider mirrors a control-plane provider registry entry (ADR-0023). It carries no token — only the non-secret registry: the vendor type, the capabilities it serves, and the key under which its token lives in the burrow-credentials Secret.
type ProviderCapability ¶ added in v0.6.0
type ProviderCapability struct {
Cloud string `json:"cloud,omitempty"`
Name string `json:"name,omitempty"`
}
ProviderCapability reports the detected cloud provider.
type ProviderVerification ¶
type ProviderVerification struct {
Bucket string `json:"bucket"`
BucketCreated bool `json:"bucket_created"`
ProbeObject bool `json:"probe_object"`
Lifecycle LifecycleCheck `json:"lifecycle"`
}
ProviderVerification mirrors what the control plane observed while registering an object-storage provider: it wrote and deleted a probe object, it created or was pointed at a bucket, and it reconciled the bucket's lifecycle rules against backup retention (ADR-0063 §2-§4).
type PublishRequest ¶
type PublishRequest struct {
Env string `json:"env,omitempty"`
Host string `json:"host"`
Port int32 `json:"port"`
NoTLS bool `json:"no_tls,omitempty"`
Issuer string `json:"issuer,omitempty"`
SkipDNS bool `json:"skip_dns,omitempty"`
Provider string `json:"provider,omitempty"`
Confirm bool `json:"confirm,omitempty"`
}
PublishRequest asks the control plane to make an app reachable at a hostname in one operation (ADR-0041 §3). It mirrors controlplane.PublishRequest, including the two NEGATIVE fields: an absent field arrives as its zero value, so the zero request is the complete publish — TLS and the DNS record — and asking for less is something a caller has to say.
type PublishResult ¶
type PublishResult struct {
App string `json:"app"`
Env string `json:"env,omitempty"`
Host string `json:"host"`
Port int32 `json:"port"`
URL string `json:"url,omitempty"`
Address string `json:"address,omitempty"`
Exposed bool `json:"exposed"`
DNSProvider string `json:"dns_provider,omitempty"`
DNSRecordType string `json:"dns_record_type,omitempty"`
DNSPointsAtCluster bool `json:"dns_points_at_cluster"`
HTTPVerified bool `json:"http_verified"`
TLSRequested bool `json:"tls_requested"`
TLSAttached bool `json:"tls_attached"`
CertReady bool `json:"cert_ready"`
Reachable bool `json:"reachable"`
BlockedOn string `json:"blocked_on,omitempty"`
Next string `json:"next,omitempty"`
Summary string `json:"summary"`
}
PublishResult is the converged verdict of a publish: what each link achieved, whether the app is live, and — when it is not — the one link to fix and the action that fixes it.
type ReachabilityResult ¶ added in v0.2.0
type ReachabilityResult struct {
App string `json:"app"`
Deployed bool `json:"deployed"`
Ready bool `json:"ready"`
Exposed bool `json:"exposed"`
Host string `json:"host,omitempty"`
Address string `json:"address,omitempty"`
TLS bool `json:"tls"`
CertReady bool `json:"cert_ready"`
DNSPointsAtCluster bool `json:"dns_points_at_cluster"`
DNSAddresses []string `json:"dns_addresses,omitempty"`
Reachable bool `json:"reachable"`
URL string `json:"url,omitempty"`
BlockedOn string `json:"blocked_on,omitempty"`
Summary string `json:"summary"`
}
type ReadAddressChange ¶
type ReadAddressChange struct {
Action string `json:"action"`
Apps []string `json:"apps"`
Stranded []StrandedApp `json:"stranded,omitempty"`
Note string `json:"note,omitempty"`
}
ReadAddressChange is what a shape change did to ADR-0081 §2's read address: written when the first standby appears, withdrawn when the last one goes, unchanged otherwise. It carries KEY names and app names, never a connection string.
type Release ¶
type Release struct {
ID string `json:"id"`
App string `json:"app"`
Environment string `json:"environment,omitempty"`
Image string `json:"image"`
Digest string `json:"digest,omitempty"`
Env map[string]string `json:"env,omitempty"`
Command []string `json:"command,omitempty"`
Replicas int32 `json:"replicas"`
Status string `json:"status"`
Supersedes string `json:"supersedes,omitempty"`
// Trigger is how the deploy was triggered (ADR-0052 §5): "manual" for an explicit CLI or agent
// deploy, "auto" for the pull-based passive watcher. AutoLevel and AutoTag are set only for auto.
Trigger string `json:"trigger,omitempty"`
AutoLevel string `json:"auto_level,omitempty"`
AutoTag string `json:"auto_tag,omitempty"`
// Rollout is what the deploy observed of this release's rollout (ADR-0092 §4): "settled",
// "unsettled", or empty when the deploy did not wait. It sits BESIDE Status, which records what
// Burrow applied rather than what the cluster then did with it. RolloutReason names why an
// unsettled rollout did not settle.
Rollout string `json:"rollout,omitempty"`
RolloutReason string `json:"rollout_reason,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
type RemoveAddonOptions ¶
type RemoveAddonOptions struct {
// Environment scopes a removal that names an instance by its LABEL rather than by its registry
// name (ADR-0091 §2): a label is unique within an environment, so `analytics` needs to know which
// one. A removal that names a registry name needs none of it and keeps its old shape.
Environment string
// DeleteData is the explicit opt-in that also DESTROYS the add-on's data volume — for Postgres,
// every attached app's database. Without it the removal tears down the workload and leaves the
// volume, so a reinstall picks the data back up.
DeleteData bool
// SkipFinalBackup destroys the data without the final backup ADR-0064 §5 otherwise takes first.
// It exists because an add-on is often removed BECAUSE it is wedged, and a wedged instance
// cannot be dumped — without it a broken add-on would be undeletable.
SkipFinalBackup bool
// BackupDestination names the object-storage provider the final backup goes to, needed only when
// several are registered.
BackupDestination string
// Confirm satisfies the addon.remove guardrail hold. It is not the data-loss acknowledgement.
Confirm bool
}
RemoveAddonOptions is everything `addon remove` carries beyond the add-on's name. It is a struct rather than a run of positional booleans because this is the most destructive call in the API.
type RemoveAddonResult ¶
type RemoveAddonResult struct {
// Instance is the LABEL the operator addressed the instance by (ADR-0091 §1). Empty from a
// control plane that predates labels, where Name is the answer.
Instance string `json:"instance,omitempty"`
Name string `json:"name"`
Type string `json:"type"`
// Namespace is where the add-on's resources, and any retained volume, live.
Namespace string `json:"namespace,omitempty"`
// DataDeleted reports whether the add-on's data volume was destroyed.
DataDeleted bool `json:"data_deleted"`
// RetainedDataVolume is the PVC left in place; empty when the add-on had no volume or it was
// deleted.
RetainedDataVolume string `json:"retained_data_volume,omitempty"`
// RetainedBackupVolume is the backup PVC left in place; empty when no backup volume exists.
RetainedBackupVolume string `json:"retained_backup_volume,omitempty"`
// AttachedApps are the apps that held a database on this instance at removal time.
AttachedApps []string `json:"attached_apps,omitempty"`
// FinalBackups are the backups taken before the data volume was destroyed, one per attached
// database (ADR-0064 §5). Each reached an object store — the removal is abandoned otherwise — so
// this is the list of copies that outlived the instance.
FinalBackups []Backup `json:"final_backups,omitempty"`
// FinalBackupSkipped reports that the data was destroyed with no off-cluster copy, and
// FinalBackupNote says why. Reported rather than inferred from an empty FinalBackups: "nothing
// was backed up" and "nothing needed backing up" must not look the same.
FinalBackupSkipped bool `json:"final_backup_skipped,omitempty"`
FinalBackupNote string `json:"final_backup_note,omitempty"`
}
RemoveAddonResult is the outcome of removing an add-on: what was torn down, and what was deliberately LEFT IN PLACE. Removal keeps the add-on's data volume unless deleteData is passed, so this reports the retained volume names — the data volume a reinstall would reuse and the Postgres backup volume, which outlives the database either way (ADR-0025/0031/0032).
type RestoreInstanceOptions ¶
type RestoreInstanceOptions struct {
// Instance is the LABEL of the instance to rewind (ADR-0091 §4). Empty is the environment's
// default instance.
Instance string
Backup string
ToTime string
Latest bool
SkipSafetyBackup bool
// Destination names the object-storage provider holding this instance's repository; empty
// resolves it when exactly one is registered.
Destination string
Confirm bool
}
RestoreInstanceOptions is everything `addon restore-instance` needs beyond the add-on type and the environment. Exactly one recovery target is required — the server refuses zero and refuses several.
type RestoreInstanceResult ¶
type RestoreInstanceResult struct {
Addon string `json:"addon"`
Environment string `json:"environment"`
Instance string `json:"instance"`
// RecoveryTarget is the point that was recovered to. It is deliberately not `target`, which is
// the control plane the command acted on (ADR-0078 §4).
RecoveryTarget string `json:"recovery_target"`
// SafetyBackup is the physical backup taken of the pre-restore state, which is the way back from
// a restore to the wrong point. SafetyBackupNote says why there is none when there is none.
SafetyBackup string `json:"safety_backup,omitempty"`
SafetyBackupNote string `json:"safety_backup_note,omitempty"`
// Apps is every app that was on the instance, by name — the blast radius, recorded rather than
// counted. Reconnected is those now pointing at the recovered instance; Stranded is those the
// cutover could not finish for.
Apps []string `json:"apps"`
Reconnected []string `json:"reconnected"`
Stranded []StrandedApp `json:"stranded,omitempty"`
// Verification is what the recovered instance was found to hold before any app was reconnected
// to it — the answer to "is the data actually there", which is the only question a restore is
// asked. A recovery that came up holding none of it is an ERROR rather than a result carrying a
// bad status, so what arrives here is confirmed or unknown.
Verification RestoreVerification `json:"verification"`
}
RestoreInstanceResult is what a physical restore did (ADR-0066 §4). It names the instance, the point it was rewound to, the backup taken of what was there, and every app that was on it — never a credential and never a connection string.
type RestoreVerification ¶
type RestoreVerification struct {
Status string `json:"status"`
Databases []string `json:"databases"`
Missing []string `json:"missing,omitempty"`
Note string `json:"note,omitempty"`
}
RestoreVerification is what the recovered instance was found to hold: the status Burrow could establish, the app databases it saw, and the attached apps it did not see one for. Names only — never a row and never a credential.
type RetainedVolume ¶
type RetainedVolume struct {
// Name is the claim name — what `kubectl delete pvc` takes to reclaim the storage.
Name string `json:"name"`
// Namespace is the add-on namespace the claim lives in.
Namespace string `json:"namespace,omitempty"`
// Addon is the add-on type the volume belonged to.
Addon string `json:"addon"`
// Environment is the environment the claim served (ADR-0067 §1). Empty for a claim created
// before add-ons were per-environment, which is the default environment's.
Environment string `json:"environment,omitempty"`
// Role is what the claim holds: "data" (the add-on's own volume) or "backup" (its dumps).
Role string `json:"role"`
// Size is the claim's capacity, e.g. "10Gi". Size, not cost: cost needs the provider's pricing.
Size string `json:"size,omitempty"`
// ReinstallAdopts reports whether reinstalling the add-on picks this volume back up with its
// data intact.
ReinstallAdopts bool `json:"reinstall_adopts"`
}
RetainedVolume is an add-on volume an earlier `addon remove` deliberately left in place: storage that is still allocated, and on a managed provider still billed, with no add-on left to use it (ADR-0064 §6). Reporting it is what makes keeping data by default defensible — an invisible leftover claim is a silent bill.
type RollbackOptions ¶
type RollbackOptions struct {
// Confirm satisfies a guardrail whose disposition holds the rollback for confirmation.
Confirm bool
// SkipHooks rolls back without running the app's `pre-rollback` hook. The hook stays configured
// and the control plane records the skip. It is set by the operator CLI's `--skip-hooks` and by
// nothing on the agent surface (ADR-0080 §3).
SkipHooks bool
// NoWait returns at submission instead of waiting for the restored image's rollout, and reports
// the outcome as unknown rather than as good (ADR-0093 §2). The zero value waits, so a caller that
// does not set it gets the report; it is set by the operator CLI's `--wait=false` and by nothing
// on the agent surface.
NoWait bool
}
RollbackOptions carries the caller's choices for a rollback: the guardrail confirmation, and the operator-only override that rolls back around a broken `pre-rollback` hook (ADR-0080).
type RollbackResult ¶
type RollbackResult struct {
Release Release `json:"release"`
RolledBackToReleaseID string `json:"rolled_back_to_release_id"`
// SupersededReleaseID is the release being rolled back AWAY FROM, which is the one still serving
// when the rollback's rollout does not become ready (ADR-0093 §2).
SupersededReleaseID string `json:"superseded_release_id"`
// Rollout is what the rollback observed of its own rollout (ADR-0093 §1): whether the restored
// image's replicas became ready, and if not, why. NIL MEANS UNOBSERVED and never "fine" — a
// rollback asked not to wait (RollbackOptions.NoWait), or a control plane older than the field.
Rollout *RolloutReport `json:"rollout,omitempty"`
// Hints are the control plane's non-blocking notes about the rollback: that a `pre-rollback` hook
// was skipped and which command did not run (ADR-0080 §4), and what a `post-deploy` hook made of
// the rollout (ADR-0072 §4). The field must exist here or the notes are decoded away before any
// caller sees them — a skip that is reported to nobody is the silence the flag exists to avoid.
Hints []string `json:"hints,omitempty"`
}
type RolloutReport ¶
type RolloutReport struct {
Settled bool `json:"settled"`
Reason string `json:"reason,omitempty"`
Detail string `json:"detail,omitempty"`
Issue string `json:"issue,omitempty"`
}
RolloutReport is the deploy's account of its rollout (ADR-0092 §2): the verdict, the reason from the closed set controlplane.LedgerReasons() enumerates when it is negative, one line of what the wait observed, and the live status surface's actionable explanation of the same workload.
func (*RolloutReport) Failed ¶
func (r *RolloutReport) Failed() bool
Failed reports that a rollout was observed and did not settle. A nil report is an unobserved rollout, which is not a failure and does not read as one.
type RunRequest ¶ added in v0.12.0
type RunRequest struct {
Env string `json:"env,omitempty"`
Command []string `json:"command"`
TTLSeconds *int32 `json:"ttl_seconds,omitempty"`
Confirm bool `json:"confirm,omitempty"`
}
RunRequest is a one-off command to run in an app's own current image and environment (ADR-0048). Command is the argv (non-empty); TTLSeconds overrides the finished-Job TTL (nil applies the default of one hour, 0 deletes it as soon as the output is captured); Confirm acknowledges the app.run guardrail so a held run proceeds.
type RunResult ¶ added in v0.12.0
type RunResult struct {
App string `json:"app"`
ExitCode int `json:"exit_code"`
Stdout string `json:"stdout,omitempty"`
Stderr string `json:"stderr,omitempty"`
TimedOut bool `json:"timed_out,omitempty"`
}
RunResult reports the outcome of a one-off command (ADR-0048). A non-zero ExitCode is a normal structured outcome, not a transport error. Stdout carries the command's captured output (Kubernetes interleaves stdout and stderr into one stream); Stderr is reserved for a future separation.
type SQLError ¶
type SQLError struct {
Message string `json:"message"`
SQLState string `json:"sqlstate,omitempty"`
Detail string `json:"detail,omitempty"`
Hint string `json:"hint,omitempty"`
Position int32 `json:"position,omitempty"`
}
SQLError is the database's own refusal of a statement, carried unmodified. The SQLSTATE is what makes it something to branch on rather than prose to match against.
type SQLResult ¶
type SQLResult struct {
Addon string `json:"addon"`
App string `json:"app"`
Environment string `json:"environment"`
Columns []string `json:"columns"`
// Rows are the result's rows, aligned with Columns. A NULL is a nil entry (JSON null), which is
// the distinction a plain string per cell would lose.
Rows [][]*string `json:"rows"`
RowCount int `json:"row_count"`
// Truncated reports the result had more rows than RowLimit and the rest were not read — reported
// rather than silent (ADR-0087 §7).
Truncated bool `json:"truncated"`
RowLimit int `json:"row_limit"`
// Command is Postgres's command tag ("SELECT 3", "UPDATE 2"), absent for a truncated read.
Command string `json:"command,omitempty"`
RowsAffected int64 `json:"rows_affected"`
Error *SQLError `json:"error,omitempty"`
}
SQLResult is what one statement against an app's database produced (ADR-0087 §4): columns and rows, so a caller composes on the result rather than parsing a rendering of it.
A statement that returned no row set carries its command tag and the number of rows it affected instead. A statement the database REFUSED carries Error, with Postgres's own message and SQLSTATE unmodified — a database error is an outcome, not a call that failed.
type ScaleResult ¶
type SecretMount ¶
type SecretMount struct {
Key string `json:"key"`
Filename string `json:"filename"`
Path string `json:"path"`
// NoEnv is true when the key is FILE-ONLY: read from the file above and kept out of the app's
// environment (ADR-0089 §4). False is the default a mount arrives with — it adds a file and
// leaves the variable alone.
NoEnv bool `json:"no_env"`
}
SecretMount is one secret key projected into a file (ADR-0089 §1): the key, the filename it lands under, and the full path in the container. It carries no value and there is no field here that could — the value stays in the per-app Kubernetes Secret, and a mount is a reference to it.
type SecretMounts ¶
type SecretMounts struct {
Dir string `json:"dir"`
Enumerated bool `json:"enumerated"`
Mounts []SecretMount `json:"mounts"`
}
SecretMounts is an app's whole file projection in one environment: the directory its mounted keys land in — already resolved, so it is the real path whether or not the app overrode it — and one entry per mounted key.
Enumerated says the app has left the envFrom fast path, which is true exactly when one of its keys is file-only. It is a behaviour the caller owns from then on: `secret set` of a new key re-applies the workload rather than restarting it, because an enumerated pod template names each key.
type SourceRef ¶ added in v0.13.0
SourceRef names the git source an in-cluster build clones and checks out inside the cluster (ADR-0053 §3): a repository URL plus the commit or tag to build. It is the only thing a build carries over the control channel — never source bytes (ADR-0004). The field names are capitalized to match the control-plane's SourceRef JSON shape, which carries no struct tags.
type StatusResult ¶
type StatusResult struct {
App string `json:"app"`
HasRelease bool `json:"has_release"`
Release Release `json:"release,omitempty"`
Running bool `json:"running"`
Workload WorkloadStatus `json:"workload,omitempty"`
// Failures is the app's recent failure history from the ledger (ADR-0074 §8), oldest first,
// resolved episodes included. Workload above is the live present tense; this is the part
// nothing can reconstruct afterwards — whether it crash-looped at 02:00 and recovered.
Failures []Failure `json:"failures,omitempty"`
// Coverage is what the observer was doing over that window. An empty Failures list means
// "nothing broke" only if Coverage says something was watching.
Coverage Coverage `json:"coverage"`
}
type StorageCapability ¶ added in v0.6.0
type StorageCapability struct {
DefaultPresent bool `json:"default_present"`
DefaultClass string `json:"default_class,omitempty"`
Classes []string `json:"classes,omitempty"`
}
StorageCapability reports the default-StorageClass situation.
type StrandedApp ¶
StrandedApp is one app a physical restore's DATABASE_URL cutover did not finish for, and why.
type Transport ¶ added in v0.10.0
type Transport interface {
// Connect returns a control-plane API client, resolving any credential it needs.
Connect(ctx context.Context) (*Client, error)
}
Transport builds an authenticated control-plane API client (ADR-0045). It is the seam that decouples HOW the CLI reaches and authenticates to burrowd from WHAT it does once connected: the Client's ~40 request methods are auth-agnostic and reused unchanged, while each Transport implementation owns the endpoint and the credential.
The open-source implementations are the kubeconfig API-server proxy (ADR-0014) and a direct control-plane URL with an API token; a separate private module can add other transports (for example a managed HTTPS endpoint behind SSO) by supplying an *http.Client whose RoundTripper carries the right credential — no fork of the request methods.
type WorkloadStatus ¶
type WorkloadStatus struct {
App string `json:"app"`
Kind string `json:"kind"`
Image string `json:"image"`
DesiredReplicas int32 `json:"desired_replicas"`
ReadyReplicas int32 `json:"ready_replicas"`
UpdatedReplicas int32 `json:"updated_replicas"`
Available bool `json:"available"`
// Issue is a human- and agent-actionable explanation of why an unavailable workload is
// blocked — an image the cluster cannot pull (naming the registry and the
// `burrow config registry login` fix), a pod no node can run (naming the taint or the
// resource), a container crash-looping (naming the exit code); empty when the workload is
// healthy. IssueReason is the machine-usable reason behind it, a member of the closed set
// controlplane.IssueReasons() enumerates (e.g. "ImagePullBackOff", "Unschedulable",
// "CrashLoopBackOff"), for branching without parsing the prose. See ADR-0006, ADR-0074 §2.
Issue string `json:"issue,omitempty"`
IssueReason string `json:"issue_reason,omitempty"`
}