Skip to content

Add cache management API: List, GC, Purge#51

Merged
JAORMX merged 2 commits intomainfrom
cache-management-api
Mar 24, 2026
Merged

Add cache management API: List, GC, Purge#51
JAORMX merged 2 commits intomainfrom
cache-management-api

Conversation

@JAORMX
Copy link
Contributor

@JAORMX JAORMX commented Mar 24, 2026

Summary

Add cache management methods to image.Cache to support the bbox cache CLI subcommand (stacklok/brood-box#84).

  • List() ([]CacheEntry, error) — enumerate all cached rootfs entries with digest, size, last-used time, and which image refs point to each
  • GC() (int, error) — reachability-based garbage collection: removes rootfs entries not referenced by any ref index entry
  • Purge() error — removes the entire cache directory
  • LayerCache.Size() (int64, error) — reports total layer cache disk usage

Ref index enhancement

putRef now stores imageRef\tdigest\n (extended format) so List can report human-readable image references. getRef handles both legacy (digest-only) and extended formats for backward compatibility.

Safety

  • GC aborts (returns error) if the refs directory exists but is unreadable, preventing accidental deletion of all entries
  • pathFor now validates digests and rejects path separators and .. components (defense-in-depth)
  • pathFor uses Replace(..., 1) to match dirNameToDigest for symmetric round-trips
  • TOCTOU race between GC and concurrent Pull is documented — consequence is a cache miss, not data loss

Test plan

  • 99 tests pass (CGO_ENABLED=0 go test -v ./image/)
  • GC: removes orphans, preserves live entries, handles multiple refs to same digest, corrupt ref files, non-existent dirs
  • List: entries with refs, orphans, legacy ref format, skips non-rootfs dirs
  • Purge: removes everything, handles nil cache and non-existent dirs
  • Ref format: extended format write/read, backward-compatible read of legacy format
  • LayerCache.Size: empty, nil, non-existent, with entries
  • Security review: path traversal defense, TOCTOU analysis, symlink handling
  • Go quality review: error handling, API design, backward compatibility
  • QA review: test coverage gaps addressed

🤖 Generated with Claude Code

JAORMX and others added 2 commits March 24, 2026 11:04
Add CacheEntry type and three new methods to image.Cache:

- List() returns metadata for all cached rootfs entries including
  digest, size, last-used time, and which image refs point to each.
- GC() removes rootfs entries not referenced by any ref index entry
  (reachability-based, unlike the time-based Evict).
- Purge() removes the entire cache directory.

Extend the ref index format to store the original image reference
alongside the digest (imageRef\tdigest), enabling List to report
human-readable ref names. getRef handles both legacy and extended
formats for backward compatibility.

Add LayerCache.Size() for reporting total layer cache disk usage.

Ref: stacklok/brood-box#84

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- GC now aborts instead of deleting everything when the refs directory
  is unreadable (liveDigests returns error instead of nil map)
- Filter empty imageRef from Refs in buildRefMap (legacy-format refs
  no longer produce empty strings in CacheEntry.Refs)
- Harmonize pathFor to use Replace(..., 1) matching dirNameToDigest
- Add path traversal defense in pathFor rejecting digests with / or ..
- Fix ModTime doc comment to be more precise
- Add tests: GC with non-existent dir, multiple refs to same digest,
  corrupt ref files
- Tighten List size assertion to exact byte count

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@JAORMX JAORMX merged commit 48e3692 into main Mar 24, 2026
7 checks passed
@JAORMX JAORMX deleted the cache-management-api branch March 24, 2026 11:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant