Documentation
¶
Index ¶
- Constants
- func CacheDir() (string, error)
- func FormatBytes(b int64) string
- func FormatMode(m fs.FileMode) string
- func FormatSignedBytes(b int64) string
- func IsBinary(data []byte) bool
- func TreeLiveFileBytes(tree *FileTree) int64
- type Analysis
- func Analyze(ctx context.Context, resolver Resolver, imageRef string) (*Analysis, error)
- func AnalyzeWithOptions(ctx context.Context, resolver Resolver, imageRef string, opts AnalyzeOptions) (*Analysis, error)
- func AnalyzeWithProgress(ctx context.Context, resolver Resolver, imageRef string, ...) (*Analysis, error)
- type AnalyzeOptions
- type DiffType
- type DockerExtractor
- type DockerResolver
- func (r *DockerResolver) ImageID(ctx context.Context, imageRef string) (string, error)
- func (r *DockerResolver) Inspect(ctx context.Context, imageRef string) (*ImageMeta, error)
- func (r *DockerResolver) NewExtractor() Extractor
- func (r *DockerResolver) Resolve(ctx context.Context, imageRef string) ([]Layer, error)
- func (r *DockerResolver) ResolveWithProgress(ctx context.Context, imageRef string, progress chan<- ProgressEvent) ([]Layer, error)
- type EfficiencyResult
- type ErrDaemonNotRunning
- type ErrImageNotFound
- type ErrPullFailed
- type Extractor
- type ExtractorSource
- type FileContent
- type FileNode
- type FileTree
- type ImageMeta
- type Layer
- type Option
- type ProgressEvent
- type ProgressPhase
- type Resolver
- type WastedFile
Constants ¶
const MaxViewSize = 1 << 20 // 1 MB
const SchemaVersion = 1
SchemaVersion is the on-disk schema version for cached analysis files. Bump when the cacheEnvelope, cachedLayer, or cachedNode shape changes (or when the parse output produced by docker.go/parseLayers changes in a way that affects what we persist). Do NOT bump for stack.go or size.go changes — those run on every load and are not persisted.
Variables ¶
This section is empty.
Functions ¶
func CacheDir ¶ added in v1.2.0
CacheDir returns the directory where layerx persists analysis caches. Resolution order:
- LAYERX_CACHE_DIR (if set and usable as a directory)
- os.UserCacheDir() joined with "layerx"
CacheDir does not create the directory; saveCache creates digest subdirectories on demand with mode 0700.
func FormatBytes ¶
func FormatMode ¶
func FormatSignedBytes ¶
FormatSignedBytes formats b like FormatBytes but with an explicit sign for non-zero values: "+12 MB", "-3.0 MB", "0 B". Used for net deltas.
func IsBinary ¶
IsBinary reports whether data appears to be binary content. Uses net/http content detection plus null-byte scanning.
func TreeLiveFileBytes ¶
TreeLiveFileBytes returns the sum of file sizes in tree, excluding directories and any nodes marked Removed (their subtrees are not descended). Returns 0 for nil tree or nil root.
Types ¶
type Analysis ¶
Analysis holds the complete result of inspecting an image.
func Analyze ¶
Analyze resolves an image and computes stacked file trees. Backwards-compatible shim around AnalyzeWithOptions; caching is enabled, no progress channel.
func AnalyzeWithOptions ¶ added in v1.2.0
func AnalyzeWithOptions(ctx context.Context, resolver Resolver, imageRef string, opts AnalyzeOptions) (*Analysis, error)
AnalyzeWithOptions is the cache-aware entry point.
Flow:
- Try to obtain image content digest via Resolver.ImageID. On error (e.g. image not local yet, daemon hiccup) we skip the cache lookup and proceed to a cold resolve; ResolveWithProgress will pull as needed.
- If !opts.NoCache and the digest is known, try loadCache. On hit we skip ResolveWithProgress entirely; emit PhaseCacheLoad.
- Otherwise call ResolveWithProgress (existing pull/export/parse path).
- After a successful resolve, re-read ImageID and require the result to match the pre-resolve digest before persisting the cache. A mismatch means the tag flipped during the run (concurrent docker pull) — caching either set of layers under either digest would lie.
- Stack + assignNetDeltas + TotalSize, build Analysis, return.
Hit and miss paths converge at step 5: the same Analysis assembly runs either way. ImageRef is taken from imageRef (the current arg), never from the envelope.
func AnalyzeWithProgress ¶
func AnalyzeWithProgress(ctx context.Context, resolver Resolver, imageRef string, progress chan<- ProgressEvent) (*Analysis, error)
AnalyzeWithProgress is preserved for callers that already pass a progress channel. Equivalent to AnalyzeWithOptions{Progress: progress}.
type AnalyzeOptions ¶ added in v1.2.0
type AnalyzeOptions struct {
// NoCache forces a cold resolve. The cache is still written on success
// so the next default-mode run is a hit.
NoCache bool
// Progress, if non-nil, receives ProgressEvents during the run. Same
// semantics as AnalyzeWithProgress; sending PhaseCacheLoad on hit.
Progress chan<- ProgressEvent
// CacheRoot overrides CacheDir() for this call. Empty = use CacheDir().
// Tests can also set LAYERX_CACHE_DIR; this field exists for callers
// that want explicit control without environment.
CacheRoot string
}
AnalyzeOptions controls the analyze pipeline. Zero value is valid: caching enabled, no progress channel, default cache directory.
type DiffType ¶
type DiffType int
DiffType indicates how a file changed relative to previous layers.
type DockerExtractor ¶
type DockerExtractor struct {
// contains filtered or unexported fields
}
DockerExtractor extracts files from images via the Docker daemon.
func NewDockerExtractor ¶
func NewDockerExtractor(cli client.APIClient) *DockerExtractor
NewDockerExtractor creates an extractor using the provided Docker client.
func (*DockerExtractor) Extract ¶
func (e *DockerExtractor) Extract(ctx context.Context, imageRef string, filePath string) (*FileContent, error)
Extract creates a temporary container, copies the file out, and removes the container.
func (*DockerExtractor) ExtractRaw ¶
func (e *DockerExtractor) ExtractRaw(ctx context.Context, imageRef string, filePath string) ([]byte, error)
ExtractRaw extracts a file's raw bytes without truncation or binary detection.
type DockerResolver ¶
type DockerResolver struct {
// contains filtered or unexported fields
}
DockerResolver resolves image layers via the Docker daemon.
func (*DockerResolver) ImageID ¶ added in v1.2.0
ImageID returns the image content digest from the Docker daemon. It does not pull; the caller is expected to ensure the image is local first (AnalyzeWithProgress does this).
func (*DockerResolver) Inspect ¶
Inspect returns lightweight image metadata without exporting the full tar. It does not pull the image — if the image is not local, it returns an error.
func (*DockerResolver) NewExtractor ¶
func (r *DockerResolver) NewExtractor() Extractor
NewExtractor creates an Extractor using this resolver's Docker client.
func (*DockerResolver) Resolve ¶
Resolve fetches the image, exports it as a tar, and parses the layer list.
func (*DockerResolver) ResolveWithProgress ¶
func (r *DockerResolver) ResolveWithProgress(ctx context.Context, imageRef string, progress chan<- ProgressEvent) ([]Layer, error)
ResolveWithProgress fetches the image with progress reporting via the channel.
type EfficiencyResult ¶
type EfficiencyResult struct {
Score float64
WastedBytes int64
WastedFiles []WastedFile
}
EfficiencyResult holds the efficiency analysis output.
func Efficiency ¶
func Efficiency(layers []Layer) *EfficiencyResult
Efficiency computes how much space is wasted by files appearing in multiple layers. A file at the same path in N layers means N-1 occurrences are redundant overwrites.
type ErrDaemonNotRunning ¶
type ErrDaemonNotRunning struct {
Cause error
}
func (*ErrDaemonNotRunning) Error ¶
func (e *ErrDaemonNotRunning) Error() string
func (*ErrDaemonNotRunning) Unwrap ¶
func (e *ErrDaemonNotRunning) Unwrap() error
type ErrImageNotFound ¶
func (*ErrImageNotFound) Error ¶
func (e *ErrImageNotFound) Error() string
func (*ErrImageNotFound) Unwrap ¶
func (e *ErrImageNotFound) Unwrap() error
type ErrPullFailed ¶
func (*ErrPullFailed) Error ¶
func (e *ErrPullFailed) Error() string
func (*ErrPullFailed) Unwrap ¶
func (e *ErrPullFailed) Unwrap() error
type Extractor ¶
type Extractor interface {
Extract(ctx context.Context, imageRef string, filePath string) (*FileContent, error)
ExtractRaw(ctx context.Context, imageRef string, filePath string) ([]byte, error)
}
Extractor retrieves file contents from a container image.
type ExtractorSource ¶
type ExtractorSource interface {
NewExtractor() Extractor
}
ExtractorSource is implemented by resolvers that can produce an Extractor.
type FileContent ¶
type FileContent struct {
Path string
Data []byte
Size int64 // actual file size (may exceed len(Data) if truncated)
Truncated bool
Binary bool
}
FileContent holds the result of extracting a file from an image.
type FileNode ¶
type FileNode struct {
Name string
Path string
Size int64
Mode fs.FileMode
UID int
GID int
DiffType DiffType
IntroducedInLayer int
Children []*FileNode
IsDir bool
}
FileNode represents a single file or directory in a layer's filesystem.
func (*FileNode) RemoveChild ¶
type FileTree ¶
type FileTree struct {
Root *FileNode
}
FileTree represents the filesystem state of one or more stacked layers.
func NewFileTree ¶
func NewFileTree() *FileTree
func ParseLayerTar ¶
ParseLayerTar reads a tar archive (a single layer) and builds a FileTree.
type ImageMeta ¶
type ImageMeta struct {
Size int64
}
ImageMeta holds lightweight metadata obtainable without exporting the full image.
type Layer ¶
type Layer struct {
Index int
ID string // short digest (first 12 chars of sha256)
Size int64
Command string // Dockerfile instruction that created this layer
Tree *FileTree // nil until M05 populates it
// NetDelta is the merged-filesystem change at this step.
// [0] = live file bytes after the first layer (full size, not 0).
// [i>0] = live bytes in stacked[i] minus stacked[i-1]. Negative when
// a layer net-removes more than it adds (cleanup, whiteout deletes).
NetDelta int64
}
Layer holds metadata for a single image layer.
type Option ¶
type Option func(*DockerResolver)
Option configures a DockerResolver.
func WithClient ¶
WithClient injects a Docker API client (used for testing).
type ProgressEvent ¶
type ProgressEvent struct {
Phase ProgressPhase
LayersDone int
LayersTotal int
BytesCurr int64
BytesTotal int64
// Message carries human-readable diagnostic text for PhaseCacheWarn.
// Empty for normal phases.
Message string
}
ProgressEvent reports loading progress back to the caller.
type ProgressPhase ¶
type ProgressPhase int
ProgressPhase identifies what the resolver is currently doing.
const ( // PhaseUnknown is the zero value, used by callers to mean "no phase // observed yet" so a UI can avoid rendering a stale default phase // before the first event arrives. PhaseUnknown ProgressPhase = iota PhasePulling PhaseExporting PhaseParsing PhaseCacheLoad // emitted on cache hit; no live Docker work follows // PhaseCacheWarn is a non-fatal diagnostic: the cache load or save // failed with an unexpected I/O error. The run continues with live // data; UIs typically render Message in a status bar. PhaseCacheWarn )
type Resolver ¶
type Resolver interface {
Resolve(ctx context.Context, imageRef string) ([]Layer, error)
ResolveWithProgress(ctx context.Context, imageRef string, progress chan<- ProgressEvent) ([]Layer, error)
Inspect(ctx context.Context, imageRef string) (*ImageMeta, error)
// ImageID returns the image content digest (e.g. "sha256:abc...") for ref.
// Implementations may return an error if the image is not local; callers
// that want pull-on-miss must call ensure-image semantics first.
ImageID(ctx context.Context, imageRef string) (string, error)
}
Resolver fetches image layer information from a container runtime.
func NewDockerResolver ¶
NewDockerResolver creates a resolver connected to the local Docker daemon.
type WastedFile ¶
WastedFile records a file path that appears redundantly across multiple layers.