Documentation
¶
Overview ¶
Package janitor runs bounded, level-triggered cleanup passes on the control plane's own node: unused Docker data, build cache over budget, orphaned volumes (quarantined first) and old failed deploy attempts.
Index ¶
Constants ¶
const ( ActionRemoved = "removed" ActionWouldRemove = "would_remove" ActionQuarantined = "quarantined" ActionWouldQuarantine = "would_quarantine" ActionKept = "kept" StatusRan = "ran" StatusSkipped = "skipped" StatusFailed = "failed" TriggerScheduled = "scheduled" TriggerManual = "manual" TriggerDiskFix = "disk_fix" )
Item actions a stage reports.
Variables ¶
var AllStages = []Stage{StageContainers, StageImages, StageBuildCache, StageVolumes, StageAttempts}
AllStages lists every stage in the order a pass runs them.
var ErrBusy = errors.New("janitor: a cleanup pass is already running")
ErrBusy means another pass is already running.
Functions ¶
func SavePolicy ¶
SavePolicy validates and stores p.
Types ¶
type Controller ¶
type Controller struct {
// contains filtered or unexported fields
}
Controller runs scheduled passes from the reconcile loop.
type Deps ¶
type Deps struct {
Store Store
Docker Docker
// DiskFree reports free and total bytes of the volume Docker data lives on.
DiskFree func(ctx context.Context) (free, total int64, err error)
// DesiredContainers lists container names the reconciler still wants, which a prune must keep.
DesiredContainers func(ctx context.Context) ([]string, error)
// OrphanVolumes lists named volumes no desired state or container references.
OrphanVolumes func(ctx context.Context) ([]docker.NamedVolume, error)
RemoveVolume func(ctx context.Context, name string) error
Logger *slog.Logger
Now func() time.Time
}
Deps are the engine's collaborators.
type Docker ¶
type Docker interface {
DiskUsage(ctx context.Context) (docker.DiskUsage, error)
ListAllImages(ctx context.Context) ([]docker.ImageRecord, error)
PruneContainers(ctx context.Context, keep []string) (docker.PruneContainersResult, error)
PruneDanglingImages(ctx context.Context) (docker.PruneImagesResult, error)
PruneAnonymousVolumes(ctx context.Context) (docker.PruneVolumesResult, error)
BuildCacheRecords(ctx context.Context) ([]docker.BuildCacheRecord, error)
PruneBuildCacheOlderThan(ctx context.Context, olderThan time.Duration) (docker.PruneBuildCacheResult, error)
}
Docker is the daemon surface a pass uses. *docker.Client satisfies it.
type Engine ¶
type Engine struct {
Deps
// contains filtered or unexported fields
}
Engine runs cleanup passes one at a time.
type Item ¶
type Item struct {
Name string `json:"name"`
Detail string `json:"detail,omitempty"`
SizeBytes int64 `json:"size_bytes"`
Action string `json:"action"`
}
Item is one thing a stage removed, would remove, or deliberately kept.
type Options ¶
type Options struct {
Trigger string
DryRun bool
// Force runs the size-driven stages even when free space is above budget.
Force bool
}
Options say how one pass runs.
type Policy ¶
type Policy struct {
Enabled bool `json:"enabled"`
// DryRun makes scheduled passes report without removing anything.
DryRun bool `json:"dry_run"`
IntervalMinutes int `json:"interval_minutes"`
// DiskFreeBudgetPercent is the free space below which size-driven stages run on a schedule.
DiskFreeBudgetPercent float64 `json:"disk_free_budget_percent"`
BuildCacheBudgetMB int64 `json:"build_cache_budget_mb"`
BuildCacheMaxAgeHours int `json:"build_cache_max_age_hours"`
// VolumeQuarantineDays is how long an orphaned volume is held before it may be deleted.
VolumeQuarantineDays int `json:"volume_quarantine_days"`
// DeleteOrphanVolumes lets a pass delete volumes whose quarantine ended; off keeps them listed only.
DeleteOrphanVolumes bool `json:"delete_orphan_volumes"`
AttemptRetentionDays int `json:"attempt_retention_days"`
AttemptKeepPerApp int `json:"attempt_keep_per_app"`
DisabledStages []Stage `json:"disabled_stages"`
}
Policy is the operator-editable cleanup configuration.
func DefaultPolicy ¶
func DefaultPolicy() Policy
DefaultPolicy reports only until an operator turns removal on.
func LoadPolicy ¶
func LoadPolicy(ctx context.Context, s PolicyStore) (Policy, error)
LoadPolicy returns the saved policy, or the default when none was saved.
type PolicyStore ¶
type PolicyStore interface {
GetJanitorPolicy(ctx context.Context) (string, bool, error)
SetJanitorPolicy(ctx context.Context, body, actor string, now time.Time) error
}
PolicyStore persists the policy as JSON.
type Report ¶
type Report struct {
ID string `json:"id"`
StartedAt time.Time `json:"started_at"`
Trigger string `json:"trigger"`
DryRun bool `json:"dry_run"`
FreePercent float64 `json:"free_percent"`
Pressure bool `json:"pressure"`
Stages []StageResult `json:"stages"`
ReclaimedBytes int64 `json:"reclaimed_bytes"`
Error string `json:"error,omitempty"`
}
Report is one pass.
type StageResult ¶
type StageResult struct {
Stage Stage `json:"stage"`
Status string `json:"status"`
Reason string `json:"reason,omitempty"`
Items []Item `json:"items"`
ReclaimedBytes int64 `json:"reclaimed_bytes"`
Error string `json:"error,omitempty"`
}
StageResult is what one stage did in a pass.
type Store ¶
type Store interface {
PolicyStore
InsertJanitorRun(ctx context.Context, r store.JanitorRun, keep int) error
ListJanitorRuns(ctx context.Context, limit int) ([]store.JanitorRun, error)
UpsertJanitorQuarantine(ctx context.Context, q store.JanitorQuarantine) error
ListJanitorQuarantine(ctx context.Context, kind string) ([]store.JanitorQuarantine, error)
DeleteJanitorQuarantine(ctx context.Context, kind, name string) error
ListPrunableDeployAttempts(ctx context.Context, cutoff time.Time, keep, limit int) ([]store.PrunableAttempt, error)
DeleteDeployAttempts(ctx context.Context, ids []string) error
}
Store is the persistence a pass needs. *store.DB satisfies it.