Documentation
¶
Overview ¶
Package fixit turns failing readiness and diagnostic checks into typed, previewable, verifiable fixes with attempt memory and loop protection.
Index ¶
- Constants
- Variables
- func ExplainIDs() []string
- func Fingerprint(checkID string, a Applicability) string
- func ValidAdvertiseHost(h string) error
- type Applicability
- type Attempt
- type BackupDeps
- type Change
- type CheckState
- type DatabasePoolerDeps
- type DiskDeps
- type DiskReclaim
- type Engine
- func (e *Engine) Apply(ctx context.Context, id, actor string, params map[string]string) (Result, error)
- func (e *Engine) List(ctx context.Context, subject string, includeHealthy bool) ([]View, error)
- func (e *Engine) Preview(ctx context.Context, id string) (View, error)
- func (e *Engine) Register(f Fix) error
- type EngineOption
- type Explanation
- type Finding
- type Fix
- func ControlPlaneBackupFix(d BackupDeps) Fix
- func DatabasePoolerFix(d DatabasePoolerDeps) Fix
- func DiskFix(d DiskDeps) Fix
- func GuidedCheckFix(d GuidedDeps) Fix
- func LegacyTokensFix(d LegacyTokensDeps) Fix
- func NetworkPoolFix(d NetworkPoolDeps) Fix
- func NextjsFixes(app string, d NextjsDeps) []Fix
- func OrphansFix(d OrphansDeps) Fix
- func PublicAddressFix(d PublicAddressDeps) Fix
- func UDPPortFix(d UDPPortDeps) Fix
- func WireGuardPrivilegeFix(d WireGuardDeps) Fix
- type GuidedDeps
- type HostEnv
- type HostReader
- type Input
- type Kind
- type LegacyTokensDeps
- type NetworkPoolDeps
- type NextjsDeps
- type NextjsFacts
- type Option
- type OrphansDeps
- type OutcomeStatus
- type Param
- type PoolerCandidate
- type PortHolder
- type PublicAddressDeps
- type Result
- type Risk
- type State
- type Store
- type UDPPortDeps
- type View
- type WireGuardDeps
Constants ¶
const ( RunSystemd = "systemd" RunDocker = "docker" RunDev = "dev" )
Run modes the control plane can be started in.
const DefaultMaxPerHour = 3
DefaultMaxPerHour caps mutating applies per fix per hour.
Variables ¶
var ErrCannotFixHere = errors.New("fixit: cannot be fixed from here")
ErrCannotFixHere is returned by a fix's Run when this host cannot be repaired from inside the control plane.
var ErrUnknownFix = errors.New("fixit: unknown fix")
ErrUnknownFix is returned for an id that is not registered.
Functions ¶
func ExplainIDs ¶
func ExplainIDs() []string
ExplainIDs lists every check id that has an explanation, sorted.
func Fingerprint ¶
func Fingerprint(checkID string, a Applicability) string
Fingerprint identifies one failing check result.
func ValidAdvertiseHost ¶
ValidAdvertiseHost accepts a hostname or a non-loopback IP, never a URL or port.
Types ¶
type Applicability ¶
type Applicability struct {
// Failing is true while the originating check does not pass.
Failing bool `json:"failing"`
// Detail is the check result as a person reads it.
Detail string `json:"detail"`
// Signature feeds the fingerprint; empty means Detail. Set it when Detail
// carries volatile numbers that should not re-arm a demoted fix.
Signature string `json:"-"`
// Kind lowers the fix's tier for this host; empty keeps Fix.Kind.
Kind Kind `json:"kind,omitempty"`
Reason string `json:"reason,omitempty"`
Changes []Change `json:"changes"`
Command string `json:"command,omitempty"`
Param *Param `json:"param,omitempty"`
}
Applicability is what a fix's Detect found out about the host right now. It doubles as the re-verification result after an apply.
type Attempt ¶
type Attempt struct {
FixID string `json:"fix_id"`
Subject string `json:"subject"`
At time.Time `json:"at"`
Actor string `json:"actor"`
Outcome OutcomeStatus `json:"outcome"`
Detail string `json:"detail"`
Fingerprint string `json:"fingerprint"`
}
Attempt is one persisted apply or re-check.
type BackupDeps ¶
type BackupDeps struct {
Check func(ctx context.Context) (CheckState, error)
// Create takes a snapshot and returns its name; nil means backups are not configured.
Create func(ctx context.Context) (string, error)
}
BackupDeps are the facts and the action the stale-backup fix uses.
type Change ¶
type Change struct {
Label string `json:"label"`
Detail string `json:"detail,omitempty"`
Bytes int64 `json:"bytes,omitempty"`
}
Change is one thing an apply would do, shown before it happens.
type CheckState ¶
CheckState is a check result reduced to what a fix needs.
type DatabasePoolerDeps ¶
type DatabasePoolerDeps struct {
// Candidates lists databases with the connections alert firing and no pooler.
Candidates func(ctx context.Context) ([]PoolerCandidate, error)
// Enable turns the pooler on through the same path as the enable-pooler API; nil means unsupported here.
Enable func(ctx context.Context, name string) error
// Blocked returns why the pooler cannot be started on this server, or "".
Blocked func() string
}
DatabasePoolerDeps are the facts and the action the enable-pooler fix uses.
type DiskDeps ¶
type DiskDeps struct {
Free func(ctx context.Context) (free, total int64, err error)
Reclaimable func(ctx context.Context) (DiskReclaim, error)
Prune func(ctx context.Context) (freed int64, err error)
// WarnFreePercent is the free-space percentage below which the check fails.
WarnFreePercent float64
}
DiskDeps are the facts and the pruner the disk fix uses.
type DiskReclaim ¶
type DiskReclaim struct {
ContainersBytes int64
ImagesBytes int64
VolumesBytes int64
BuildCacheBytes int64
OrphanNetworks []string
}
DiskReclaim is what a cleanup would free, by category.
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine is the registry plus the apply state machine.
func NewEngine ¶
func NewEngine(store Store, opts ...EngineOption) *Engine
NewEngine builds an engine over an attempt store.
func (*Engine) Apply ¶
func (e *Engine) Apply(ctx context.Context, id, actor string, params map[string]string) (Result, error)
Apply runs the fix (auto tier) or re-checks it (guided and manual tiers), then re-verifies by re-running the originating check. It never runs a mutation the demotion or rate limit has withdrawn.
func (*Engine) List ¶
List returns fixes for a subject ("" for all). Healthy fixes are left out unless includeHealthy is set. Listing re-runs each check but never mutates.
type EngineOption ¶
type EngineOption func(*Engine)
EngineOption configures an Engine.
func WithClock ¶
func WithClock(now func() time.Time) EngineOption
WithClock overrides the time source, for tests.
func WithMaxPerHour ¶
func WithMaxPerHour(n int) EngineOption
WithMaxPerHour overrides the per-fix hourly apply cap; zero keeps the default.
type Explanation ¶
type Explanation struct {
ID string `json:"id"`
Plain string `json:"plain"`
Why string `json:"why"`
// Next names the dashboard button or guided step first; a CLI command is only ever secondary.
Next string `json:"next"`
// FixID is the typed fix registered for the check, empty when there is none.
FixID string `json:"fix_id,omitempty"`
Kind Kind `json:"kind"`
}
Explanation is the fixed plain-language text for one doctor check. It is a lookup table, not generated text, so it works offline and never changes between runs.
func Explain ¶
func Explain(id string) (Explanation, bool)
Explain returns the explanation for a check id.
type Finding ¶
type Finding struct {
Failing bool
Detail string
// Command is the exact host command; empty means there is no single command.
Command string
// Reason is prose guidance shown when there is no command.
Reason string
}
Finding is a check result plus what the operator must do elsewhere.
type Fix ¶
type Fix struct {
ID string
CheckID string
// Aliases and CodePrefixes name the doctor row codes that differ from
// CheckID but report the same fact, so the fix reaches those rows too.
Aliases []string
CodePrefixes []string
Subject string
Kind Kind
Title string
Why string
Risk Risk
Reversible bool
// Needs is the API ability the caller must hold to apply.
Needs string
// Detect re-runs the originating check and plans the fix.
Detect func(ctx context.Context) (Applicability, error)
// Run performs the change; nil for guided and manual fixes.
Run func(ctx context.Context, in Input) error
}
Fix is one registered remedy for one check.
func ControlPlaneBackupFix ¶
func ControlPlaneBackupFix(d BackupDeps) Fix
ControlPlaneBackupFix takes a fresh control plane snapshot when the newest one is stale.
func DatabasePoolerFix ¶
func DatabasePoolerFix(d DatabasePoolerDeps) Fix
DatabasePoolerFix enables the connection pooler on Postgres databases running out of connections.
func GuidedCheckFix ¶
func GuidedCheckFix(d GuidedDeps) Fix
GuidedCheckFix offers Re-check as the action and the host command as the secondary option.
func LegacyTokensFix ¶
func LegacyTokensFix(d LegacyTokensDeps) Fix
LegacyTokensFix migrates pending pre-upgrade API tokens now instead of on first use.
func NetworkPoolFix ¶
func NetworkPoolFix(d NetworkPoolDeps) Fix
NetworkPoolFix prunes orphaned app networks when the subnet pool runs high.
func NextjsFixes ¶
func NextjsFixes(app string, d NextjsDeps) []Fix
NextjsFixes returns one guided fix per Next.js check for an app. None of them change the app: each shows what to do and re-checks afterwards.
func OrphansFix ¶
func OrphansFix(d OrphansDeps) Fix
OrphansFix previews and prunes unreferenced Docker data for the docker_orphans check.
func PublicAddressFix ¶
func PublicAddressFix(d PublicAddressDeps) Fix
PublicAddressFix persists the address agents dial, overriding the env var.
func UDPPortFix ¶
func UDPPortFix(d UDPPortDeps) Fix
UDPPortFix names the holder of the mesh UDP port and how to free it. The port is a compiled default today, so there is no "pick another port" tier.
func WireGuardPrivilegeFix ¶
func WireGuardPrivilegeFix(d WireGuardDeps) Fix
WireGuardPrivilegeFix returns the guided fix for a mesh blocked by privileges.
func (Fix) ServesCode ¶
ServesCode reports whether a doctor row code is this fix's check id, one of its declared or registered aliases, or under one of its declared prefixes.
type GuidedDeps ¶
type GuidedDeps struct {
ID string
CheckID string
Subject string
Title string
Why string
Risk Risk
Check func(ctx context.Context) (Finding, error)
}
GuidedDeps describes a fix for a host-level step the control plane cannot do.
type HostEnv ¶
type HostEnv struct {
Mode string
Unit string
Root bool
TunPresent bool
CapNetAdmin bool
Executable string
}
HostEnv is how this process is running, read from /proc and the filesystem.
func DetectHostEnv ¶
func DetectHostEnv(r HostReader) HostEnv
DetectHostEnv classifies the run mode and the privileges the process has.
type HostReader ¶
type HostReader struct {
ReadFile func(path string) ([]byte, error)
Exists func(path string) bool
Getenv func(key string) string
Geteuid func() int
Executable func() string
}
HostReader is the injectable view of the host DetectHostEnv reads.
type LegacyTokensDeps ¶
type LegacyTokensDeps struct {
// Pending counts pre-upgrade tokens not yet migrated.
Pending func(ctx context.Context) (int, error)
// Migrate imports every pending token; nil means the auth library is not configured.
Migrate func(ctx context.Context) error
}
LegacyTokensDeps are the facts and the importer the legacy-token fix uses.
type NetworkPoolDeps ¶
type NetworkPoolDeps struct {
Usage func(ctx context.Context) (enabled bool, inUse, capacity int, err error)
// Orphans lists networks a prune would remove.
Orphans func(ctx context.Context) ([]string, error)
Prune func(ctx context.Context) (removed []string, err error)
// WarnPercent is the usage above which the check fails.
WarnPercent int
// PoolEnv names the env var that widens the pool.
PoolEnv string
}
NetworkPoolDeps are the facts and the pruner the pool fix uses.
type NextjsDeps ¶
type NextjsDeps struct {
Facts func(ctx context.Context, app string) (facts NextjsFacts, found bool, err error)
}
NextjsDeps loads the facts for one app; found is false when it is not Next.js.
type NextjsFacts ¶
type NextjsFacts struct {
// App is the app name, used as the fix subject.
App string
// Standalone is true when the build produced the standalone server.
Standalone bool
// StaticCopied is true when .next/static and public sit beside the server.
StaticCopied bool
// SharpAvailable is true when the image optimizer can load sharp.
SharpAvailable bool
// ActionsKeySet is true when the Server Actions key reaches the runtime.
ActionsKeySet bool
// MemoryMB is the app memory limit; zero means unlimited.
MemoryMB int
// MinMemoryMB is the floor to warn under, supplied from settings or env.
MinMemoryMB int
// Replicas is the desired replica count.
Replicas int
SharedCache bool
}
NextjsFacts are the per-app observations the Next.js doctor checks read. The caller fills them from the app spec, build output and linked services.
type OrphansDeps ¶
type OrphansDeps struct {
Check func(ctx context.Context) (CheckState, error)
Reclaimable func(ctx context.Context) (DiskReclaim, error)
Prune func(ctx context.Context) (freed int64, err error)
}
OrphansDeps are the facts and the pruner the orphaned-Docker-data fix uses.
type OutcomeStatus ¶
type OutcomeStatus string
OutcomeStatus is the result of one apply or re-check.
const ( OutcomeFixed OutcomeStatus = "fixed" OutcomeStillFailing OutcomeStatus = "still_failing" OutcomeCannotFixHere OutcomeStatus = "cannot_fix_here" OutcomeSkipped OutcomeStatus = "skipped" )
Outcome values for an apply or re-check.
type Param ¶
type Param struct {
Name string `json:"name"`
Options []Option `json:"options"`
Default string `json:"default,omitempty"`
Free bool `json:"free"`
}
Param is the one input a fix may ask for.
type PoolerCandidate ¶
PoolerCandidate is a Postgres database whose connections alert fires while it runs without the pooler.
type PortHolder ¶
PortHolder names what is bound to a port.
type PublicAddressDeps ¶
type PublicAddressDeps struct {
Check func(ctx context.Context) (CheckState, error)
Candidates func(ctx context.Context) []Option
Save func(ctx context.Context, host, actor string) error
}
PublicAddressDeps are the facts and the setter the address fix uses.
type Result ¶
type Result struct {
FixID string `json:"fix_id"`
Outcome OutcomeStatus `json:"outcome"`
Detail string `json:"detail"`
View View `json:"view"`
}
Result is the outcome of Apply.
type Store ¶
type Store interface {
RecentAttempts(ctx context.Context, fixID, subject string, limit int) ([]Attempt, error)
CountAttemptsSince(ctx context.Context, fixID string, since time.Time) (int, error)
RecordAttempt(ctx context.Context, a Attempt) error
}
Store persists attempt memory.
type UDPPortDeps ¶
type UDPPortDeps struct {
Check func(ctx context.Context) (CheckState, error)
Port int
Holder func(ctx context.Context, port int) (PortHolder, bool)
}
UDPPortDeps are the facts the busy-port fix needs.
type View ¶
type View struct {
ID string `json:"id"`
CheckID string `json:"check_id"`
Subject string `json:"subject"`
Title string `json:"title"`
Why string `json:"why"`
Risk Risk `json:"risk"`
Reversible bool `json:"reversible"`
Needs string `json:"needs"`
State State `json:"state"`
BaseKind Kind `json:"base_kind"`
Kind Kind `json:"kind"`
Failing bool `json:"failing"`
Detail string `json:"detail"`
Reason string `json:"reason,omitempty"`
Changes []Change `json:"changes"`
Command string `json:"command,omitempty"`
Param *Param `json:"param,omitempty"`
LastTried *Attempt `json:"last_attempt,omitempty"`
Attempts []Attempt `json:"attempts"`
Blocked string `json:"blocked,omitempty"`
RetryAfter time.Duration `json:"-"`
// contains filtered or unexported fields
}
View is a fix as the API and UI show it.
func (View) ServesCode ¶
ServesCode reports whether a doctor row code is this fix's check id, one of its aliases, or under one of its declared prefixes.
type WireGuardDeps ¶
type WireGuardDeps struct {
Check func(ctx context.Context) (CheckState, error)
Host func() HostEnv
// FallbackUnit names the systemd unit when the cgroup does not.
FallbackUnit string
}
WireGuardDeps are the host facts the privilege fix reasons over.