cleanup

package
v0.0.0-...-03ac62e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 21, 2026 License: Zlib Imports: 21 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewHandler

NewHandler returns a HandlerFactory for cleanup-docker policies. The reporter is shared across all handlers produced by this factory and is included as a PollHook in Registration().

func Registration

func Registration() policyreconcile.Registration

Registration returns a policyreconcile.Registration for cleanup-docker policies. Call this from edge.go inside the Docker/Podman platform guard.

Types

type CleanupHandler

type CleanupHandler struct {
	// contains filtered or unexported fields
}

CleanupHandler implements policyreconcile.PolicyHandler for cleanup-docker policies. One instance is created per active policy ID by the factory returned from NewHandler.

func (*CleanupHandler) Apply

func (h *CleanupHandler) Apply(ctx context.Context, raw json.RawMessage) error

Apply implements policyreconcile.PolicyHandler. It decodes and validates the config, performs a non-fatal disk-stat pre-flight check when storage-limit cleanup is requested, then starts (or replaces) the CleanupService. Returns nil on success.

Disk-stat failures are intentionally non-fatal: age-based cleanup (CleanOldImages) works regardless of whether the host filesystem is accessible, so the service is started and the limitation is surfaced as a warning in Status().Message instead of causing Apply to fail and leaving the policy in a perpetual retry loop.

func (*CleanupHandler) Remove

func (h *CleanupHandler) Remove(_ context.Context) error

Remove implements policyreconcile.PolicyHandler. It stops the background cleanup service and deregisters this handler from the reporter so that Tick() no longer emits status entries for this policy.

func (*CleanupHandler) Status

Status implements policyreconcile.PolicyHandler. Returns the handler's current ActualState for direct observation (e.g. in tests). The reconciler itself does not call this — it manages its own r.actual map.

type CleanupService

type CleanupService struct {
	// contains filtered or unexported fields
}

CleanupService is a background service that periodically garbage-collects Docker images. It runs two cleanup phases per interval:

  1. Old-image cleanup: removes any image older than ImageMaximumAgeForGC, regardless of disk usage.
  2. Storage-limit cleanup: when disk usage exceeds CleanupStartHostThresholdPercent it removes images aged >= MinAge, stopping when usage drops below CleanupEndHostThresholdPercent or MaximumImagesPerInterval is reached.

Both phases respect the configured exclusion lists and never remove images that are in use by any container (running or stopped).

func NewCleanupService

func NewCleanupService(cfg Config) *CleanupService

NewCleanupService constructs a CleanupService with the given config. Exclusion patterns are compiled once at construction time. Injectable dependencies (newClient, statfs, imageLayersSize) default to production implementations and can be overridden in tests.

func (*CleanupService) Snapshot

func (s *CleanupService) Snapshot() CleanupStatusSnapshot

Snapshot returns the most recent cycle status. Safe to call concurrently.

func (*CleanupService) Start

func (s *CleanupService) Start(ctx context.Context)

Start launches the background ticker loop. The first cycle fires after one full CleanupInterval — this is intentional to avoid a burst of cleanup work immediately after a rolling restart. Calling Start on an already-running service is a no-op.

func (*CleanupService) Stop

func (s *CleanupService) Stop()

Stop cancels the ticker loop. Any cleanup cycle that is currently in progress will run to completion before the goroutine exits.

type CleanupStatusReporter

type CleanupStatusReporter struct {
	// contains filtered or unexported fields
}

CleanupStatusReporter tracks active CleanupHandlers and emits snapshot-enriched ActualState entries on each poll cycle, overriding the reconciler's empty "applied" message with live data from each cleanup service.

It implements policyreconcile.PollHook and is automatically registered as a hook via Registration().

The hook's statuses are appended to reconciler.Statuses() before being sent to the server. The server upserts by policy ID in order, so the hook's richer message (last in the slice) overwrites the reconciler's empty success message for the same policy.

func NewCleanupStatusReporter

func NewCleanupStatusReporter() *CleanupStatusReporter

NewCleanupStatusReporter returns a reporter ready for use as a PollHook.

func (*CleanupStatusReporter) Tick

Tick implements policyreconcile.PollHook. For each active cleanup handler it returns a snapshot-enriched ActualState.

type CleanupStatusSnapshot

type CleanupStatusSnapshot struct {
	LastRun              time.Time `json:"lastRun"`
	OldImagesRemoved     int       `json:"oldImagesRemoved"`
	SpaceImagesRemoved   int       `json:"spaceImagesRemoved"`
	BytesFreed           int64     `json:"bytesFreed"`
	BuildCacheBytesFreed int64     `json:"buildCacheBytesFreed,omitempty"`
	DiskUsedPercent      float64   `json:"diskUsedPercent"`
	Errors               []string  `json:"errors,omitempty"`
}

CleanupStatusSnapshot is a point-in-time view of what the last cleanup cycle did.

type Config

type Config struct {
	// CleanupInterval is required: the cleanup service does not start if this
	// is non-positive.
	CleanupInterval Duration `json:"cleanupInterval"`

	// CleanOldImages enables removal of images older than ImageMaximumAgeForGC.
	CleanOldImages       bool     `json:"cleanOldImages"`
	ImageMaximumAgeForGC Duration `json:"imageMaximumAgeForGC"`

	// CleanImagesAtStorageLimit enables disk-threshold-driven image removal.
	CleanImagesAtStorageLimit bool `json:"cleanImagesAtStorageLimit"`
	// CleanupStartHostThresholdPercent must be in (0, 100] and
	// strictly greater than CleanupEndHostThresholdPercent when CleanImagesAtStorageLimit is true.
	CleanupStartHostThresholdPercent float64 `json:"cleanupStartHostThresholdPercent"`
	// CleanupEndHostThresholdPercent must be in (0, 100) and
	// strictly less than CleanupStartHostThresholdPercent when CleanImagesAtStorageLimit is true.
	CleanupEndHostThresholdPercent float64 `json:"cleanupEndHostThresholdPercent"`

	// MinAge is the minimum image age for phase-2 candidates. 0 = any age.
	MinAge Duration `json:"minAge"`

	// MaximumImagesPerInterval caps phase-2 removals per cycle. 0 = unlimited.
	// This cap does NOT apply to phase 1.
	MaximumImagesPerInterval int `json:"maximumImagesPerInterval"`

	// ExcludedImages lists image references never removed by either phase.
	// Each entry is matched against the image's "repository:tag" reference:
	//   - An entry with ":" is an exact match (e.g. "nginx:1.25.3").
	//   - An entry without ":" matches any tag of that repository (e.g. "nginx").
	//
	// All entries are normalised before matching, so "docker.io/library/nginx"
	// and "nginx" are equivalent. To protect an image from a private registry,
	// include the registry hostname: "harbor.example.com/myorg/myapp".
	// A bare name like "nginx" does NOT protect "harbor.example.com/nginx:latest".
	ExcludedImages []string `json:"excludedImages"`

	// ClearBuildCache controls whether the Docker build cache is pruned during
	// the storage-limit cleanup phase when disk usage exceeds the start threshold.
	// Build cache pruning runs before image removal; if it brings disk usage below
	// the threshold, image removal is skipped entirely for that cycle.
	ClearBuildCache bool `json:"clearBuildCache"`
}

Config holds all cleanup service configuration.

func DecodeConfig

func DecodeConfig(raw json.RawMessage) (Config, error)

DecodeConfig deserialises a JSON blob into a Config and validates the result. Duration fields must be millisecond integers (e.g. 86400000 for 24h). Fields absent from the JSON are left at their zero values.

func (Config) Validate

func (c Config) Validate() error

Validate returns an error if the config contains invalid field values.

type Duration

type Duration time.Duration

Duration is a time.Duration that serialises to/from a JSON millisecond integer. The server always sends durations as int64 milliseconds in PolicyDesiredState.Config; using the same format here keeps the wire contract unambiguous.

func (Duration) MarshalJSON

func (d Duration) MarshalJSON() ([]byte, error)

MarshalJSON serialises the duration as a millisecond integer.

func (Duration) Std

func (d Duration) Std() time.Duration

Std returns the underlying time.Duration.

func (*Duration) UnmarshalJSON

func (d *Duration) UnmarshalJSON(b []byte) error

UnmarshalJSON parses a millisecond integer (e.g. 86400000 for 24h).

type StorageUsage

type StorageUsage struct {
	// RootDir is the path used to determine disk capacity (always dockerDataPath).
	RootDir string
	// DockerBytes is the total bytes consumed by Docker artifacts:
	// images, container writable layers, volumes, and build cache.
	// This is NOT total disk used — other processes on the same disk are excluded.
	// See sumDockerBytes for the exact accounting.
	DockerBytes uint64
	// ImageBytes is the deduplicated image layer data (LayersSize from docker system df).
	ImageBytes uint64
	// ContainerBytes is the sum of writable-layer sizes across all containers (SizeRw).
	// Image layers are excluded to avoid double-counting with ImageBytes.
	ContainerBytes uint64
	// VolumeBytes is the sum of known volume sizes. Volumes with unknown sizes
	// (e.g. non-local drivers) are excluded.
	VolumeBytes uint64
	// BuildCacheBytes is the sum of all build cache entry sizes.
	BuildCacheBytes uint64
	// TotalBytes is the total capacity of the partition hosting the Docker data directory.
	TotalBytes uint64
	// AvailableBytes is the bytes available to unprivileged processes on that partition.
	// Total non-Docker disk used = TotalBytes - AvailableBytes - DockerBytes.
	AvailableBytes uint64
}

StorageUsage is a point-in-time view of Docker storage relative to the disk that backs the Docker data directory.

func GetDockerStorageUsage

func GetDockerStorageUsage(ctx context.Context, newClient agentdocker.CleanupClientFactory) (StorageUsage, error)

GetDockerStorageUsage returns a StorageUsage snapshot combining:

  • disk capacity from statfs on dockerDataPath (always bind-mounted in standard deployments)
  • Docker's own byte accounting via "docker system df" (through the Docker socket)

func GetDockerStorageUsageForPath

func GetDockerStorageUsageForPath(ctx context.Context, newClient agentdocker.CleanupClientFactory, diskPath string) (StorageUsage, error)

GetDockerStorageUsageForPath is like GetDockerStorageUsage but scopes disk metrics to the filesystem containing diskPath instead of the default SystemVolumePath. It is used by the HTTP handler so the disk path can be overridden in tests.

Directories

Path Synopsis
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL