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 Fingerprint(checkID string, a Applicability) string
- func ValidAdvertiseHost(h string) error
- type Applicability
- type Attempt
- type Change
- type CheckState
- 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 Fix
- type HostEnv
- type HostReader
- type Input
- type Kind
- type NetworkPoolDeps
- type Option
- type OutcomeStatus
- type Param
- 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 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 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 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 Fix ¶
type Fix struct {
ID string
CheckID 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 NetworkPoolFix ¶
func NetworkPoolFix(d NetworkPoolDeps) Fix
NetworkPoolFix prunes orphaned app networks when the subnet pool runs high.
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.
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 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 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 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:"-"`
}
View is a fix as the API and UI show it.
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.