Documentation
¶
Overview ¶
Package housekeeping is the housekeeping service: the default cron triggers that keep a harness host's disk healthy. Each trigger is one operation of a Housekeeper, mounted with the cron service, and every operation obeys one ownership rule: it deletes only what the harness records as created by a session that has ended, plus the Docker classes the docker trigger names (exited runner containers, dangling images, the build cache). Paths are never matched by pattern; anything the harness cannot attribute to an ended session is reported as a finding with its size and survives. Volumes and running containers are never touched.
The service crosses no boundary itself: it reads through the file capability (the state directory and the process table), runs programs through the process capability and reaches the Docker Engine through the container capability. Every deletion is logged with its path, size and owning session before it happens and recorded afterwards as a typed Record through the sink the binary grants.
Index ¶
- Constants
- Variables
- type Housekeeper
- func (housekeeper *Housekeeper) DiskFloor(ctx context.Context, occurrence cronservice.Occurrence) error
- func (housekeeper *Housekeeper) Docker(ctx context.Context, occurrence cronservice.Occurrence) error
- func (housekeeper *Housekeeper) Run(ctx context.Context, trigger string) error
- func (housekeeper *Housekeeper) Sessions(ctx context.Context, occurrence cronservice.Occurrence) error
- func (housekeeper *Housekeeper) SharedCache(ctx context.Context, occurrence cronservice.Occurrence) error
- func (housekeeper *Housekeeper) Triggers() ([]cronservice.Option, error)
- type HousekeeperOption
- func WithAdmission(admission IAdmission) HousekeeperOption
- func WithClock(source clock.IClock) HousekeeperOption
- func WithContainers(containers IContainers) HousekeeperOption
- func WithDryRun() HousekeeperOption
- func WithLauncher(launcher proc.ILauncher) HousekeeperOption
- func WithLogger(logger *slog.Logger) HousekeeperOption
- func WithProcessTable(processes IProcessTable) HousekeeperOption
- func WithRecordSink(sink RecordSink) HousekeeperOption
- func WithSandboxImage(image string) HousekeeperOption
- func WithScratch(directory string, files ipcfs.IFiles) HousekeeperOption
- func WithSessions(list SessionList) HousekeeperOption
- func WithState(directory string, files ipcfs.IFiles) HousekeeperOption
- type IAdmission
- type IContainers
- type IProcessTable
- type Kind
- type Record
- type RecordSink
- type RecordType
- type SessionList
Constants ¶
const ( // TriggerDiskFloor measures free disk every five minutes and, below the // derived floor, reclaims until it is above it. TriggerDiskFloor = "housekeeping.disk_floor" // TriggerSessions reclaims what ended sessions left, every 15 minutes. TriggerSessions = "housekeeping.sessions" // TriggerDocker removes the Docker leftovers it names, hourly. TriggerDocker = "housekeeping.docker" TriggerSharedCache = "housekeeping.shared_cache" // ScheduleLocation is the time zone the triggers are declared in. ScheduleLocation = "America/Los_Angeles" )
The default triggers, as csfcron declares them.
const ( // RunnerContainerPrefix names the CI runner containers whose exited // leftovers are removed. RunnerContainerPrefix = "candace-docker-runner" )
The Docker classes the docker trigger removes, and nothing else.
Variables ¶
var ( // ErrInvalidOption reports a nil option or a value the service cannot use. ErrInvalidOption = errors.New("housekeeping: invalid option") // ErrMissingCapability reports a housekeeper built without a required // capability. ErrMissingCapability = errors.New("housekeeping: a required capability is missing") // ErrUnknownTrigger reports a Run of a trigger this service does not // declare. ErrUnknownTrigger = errors.New("housekeeping: unknown trigger") // ErrBelowFloor reports a disk_floor occurrence that ended with free disk // still below the floor. ErrBelowFloor = errors.New("housekeeping: free disk is below the floor") )
Functions ¶
This section is empty.
Types ¶
type Housekeeper ¶
type Housekeeper struct {
// contains filtered or unexported fields
}
Housekeeper runs the housekeeping operations. It holds no state between occurrences: each one measures the host again.
func NewHousekeeper ¶
func NewHousekeeper(options ...HousekeeperOption) (*Housekeeper, error)
NewHousekeeper validates the whole option set and returns the service. The state directory, session list, launcher, containers, process table and record sink are required.
func (*Housekeeper) DiskFloor ¶
func (housekeeper *Housekeeper) DiskFloor(ctx context.Context, occurrence cronservice.Occurrence) error
DiskFloor measures free disk against the derived floor. Below it, it holds the harness's admission and runs the reclaim steps in order (the sessions, Docker, the shared cache), measuring again after each, until free disk is above the floor; it releases admission once it is.
func (*Housekeeper) Docker ¶
func (housekeeper *Housekeeper) Docker(ctx context.Context, occurrence cronservice.Occurrence) error
Docker removes the exited CI runner containers, the dangling images and the unused build cache. It never removes a volume (the capability it is granted has no volume operation), a running container or an image a container uses.
func (*Housekeeper) Run ¶
func (housekeeper *Housekeeper) Run(ctx context.Context, trigger string) error
Run invokes one trigger's operation once, outside the scheduler, as a manual occurrence.
func (*Housekeeper) Sessions ¶
func (housekeeper *Housekeeper) Sessions(ctx context.Context, occurrence cronservice.Occurrence) error
Sessions reclaims what each ended session left: its leftover processes, its worktree, its Bazel output base and the branch of its merged or closed pull request. Everything else in the state directory, and every entry of a granted scratch directory, is reported as a finding.
func (*Housekeeper) SharedCache ¶
func (housekeeper *Housekeeper) SharedCache(ctx context.Context, occurrence cronservice.Occurrence) error
SharedCache trims the shared Bazel disk cache to its derived size, oldest entries first.
func (*Housekeeper) Triggers ¶
func (housekeeper *Housekeeper) Triggers() ([]cronservice.Option, error)
Triggers declares the four default triggers for the cron service, in ScheduleLocation.
type HousekeeperOption ¶
type HousekeeperOption func(housekeeper *Housekeeper) error
HousekeeperOption configures a Housekeeper.
func WithAdmission ¶
func WithAdmission(admission IAdmission) HousekeeperOption
WithAdmission grants the harness's admission, which disk_floor holds while free disk is below the floor.
func WithClock ¶
func WithClock(source clock.IClock) HousekeeperOption
WithClock replaces the host's clock, which stamps every record.
func WithContainers ¶
func WithContainers(containers IContainers) HousekeeperOption
WithContainers grants the container capability. Required.
func WithDryRun ¶
func WithDryRun() HousekeeperOption
WithDryRun measures and records the plan without deleting anything or holding admission.
func WithLauncher ¶
func WithLauncher(launcher proc.ILauncher) HousekeeperOption
WithLauncher grants the process capability. Required.
func WithLogger ¶
func WithLogger(logger *slog.Logger) HousekeeperOption
WithLogger receives the line logged before every deletion.
func WithProcessTable ¶
func WithProcessTable(processes IProcessTable) HousekeeperOption
WithProcessTable grants the process table. Required.
func WithRecordSink ¶
func WithRecordSink(sink RecordSink) HousekeeperOption
WithRecordSink grants where records go. Required.
func WithSandboxImage ¶
func WithSandboxImage(image string) HousekeeperOption
WithSandboxImage names the image the root-owned remainder of an output base is removed in, through a container that mounts only that path.
func WithScratch ¶
func WithScratch(directory string, files ipcfs.IFiles) HousekeeperOption
WithScratch grants a scratch directory whose entries the sessions trigger reports, with their sizes, as findings. Nothing in it is ever deleted.
func WithSessions ¶
func WithSessions(list SessionList) HousekeeperOption
WithSessions grants the harness's session list. Required.
type IAdmission ¶
type IAdmission interface {
HoldAdmission(reason string)
ReleaseAdmission()
}
IAdmission is the harness's session admission: held while free disk is below the floor, so no new session starts on a full disk.
type IContainers ¶
type IContainers interface {
ContainerList(ctx context.Context, options client.ContainerListOptions) (client.ContainerListResult, error)
ContainerRemove(ctx context.Context, id string, options client.ContainerRemoveOptions) (client.ContainerRemoveResult, error)
ImageList(ctx context.Context, options client.ImageListOptions) (client.ImageListResult, error)
ImagePrune(ctx context.Context, options client.ImagePruneOptions) (client.ImagePruneResult, error)
BuildCachePrune(ctx context.Context, options client.BuildCachePruneOptions) (client.BuildCachePruneResult, error)
DiskUsage(ctx context.Context, options client.DiskUsageOptions) (client.DiskUsageResult, error)
RunSandboxed(ctx context.Context, spec docker.SandboxSpec) (docker.SandboxResult, error)
}
IContainers is the part of the container capability housekeeping uses. It has no volume operation, so no trigger can remove a volume.
type IProcessTable ¶
IProcessTable is the host's process table, granted as /proc.
type Record ¶
type Record struct {
Time time.Time `json:"time"`
Type RecordType `json:"type"`
Trigger string `json:"trigger"`
Occurrence string `json:"occurrence"`
Kind Kind `json:"kind,omitempty"`
What string `json:"what"`
Session string `json:"owner_session,omitempty"`
Bytes uint64 `json:"bytes"`
DryRun bool `json:"dry_run,omitempty"`
Detail string `json:"detail,omitempty"`
}
Record is one typed receipt in the harness state directory: a deletion, a finding or a floor measurement, with the trigger and occurrence that wrote it.
type RecordSink ¶
RecordSink receives every record an operation writes.
type RecordType ¶
type RecordType string
RecordType says what a Record reports.
const ( // RecordDeletion is one deletion, or in a dry run one planned deletion: // Bytes is what it freed. RecordDeletion RecordType = "deletion" // RecordFinding is something measured and left because the harness // cannot attribute it to an ended session: Bytes is what it holds. RecordFinding RecordType = "finding" // RecordFloor is a disk_floor measurement: Bytes is the free disk and // Detail the floor's derivation. RecordFloor RecordType = "floor" )
type SessionList ¶
type SessionList func(ctx context.Context) (*harnessv1.ListAgentSessionsResponse, error)
SessionList reports the harness's sessions and the process they run in: the session service's List in the host, its client elsewhere.