Documentation
¶
Overview ¶
Package oci freezes a block volume image into an immutable, content-addressed OCI artifact (Freeze, push to a registry) and re-opens it as a read-only block backing (OpenReadOnly, pull from a registry).
A volume is sliced into fixed-size chunks; each chunk is sha256-addressed and pushed once. Identical chunks — most importantly the all-zero holes of a sparse image — collapse to a single blob, so a mostly-empty disk freezes to a handful of blobs regardless of its logical size. The recovered *Image serves reads by pulling chunks on demand (with an LRU byte cache) and rejects every write, so it can be handed to pool.OpenWith as a genuinely immutable backing.
Index ¶
- Constants
- Variables
- func Freeze(ctx context.Context, src volume.ReadOnly, dst *registry.Client, ref string, ...) (string, error)
- type Config
- type Image
- type Options
- type Overlay
- func (o *Overlay) Close() error
- func (o *Overlay) Commit(ctx context.Context, dst *registry.Client, ref string) (string, error)
- func (o *Overlay) ReadAt(p []byte, off int64) (int, error)
- func (o *Overlay) Size() (int64, error)
- func (o *Overlay) Sync() error
- func (o *Overlay) Truncate(size int64) error
- func (o *Overlay) WriteAt(p []byte, off int64) (int, error)
Constants ¶
const ChunkMediaType = "application/vnd.go-volumes.pool-image.chunk.v1"
ChunkMediaType is the media type of each chunk layer descriptor.
const ConfigMediaType = "application/vnd.go-volumes.pool-image.v1+json"
ConfigMediaType is the artifact type carried by the manifest config blob, marking this image as a go-volumes frozen pool image rather than a runnable container.
const DefaultChunkSize = 4 << 20 // 4 MiB
DefaultChunkSize is the chunk window used when Options.ChunkSize is zero.
Variables ¶
var ErrReadOnly = errors.New("oci: read-only frozen image")
ErrReadOnly is returned by every mutating method of an *Image: it is a frozen, content-addressed artifact and cannot be written through.
Functions ¶
func Freeze ¶
func Freeze(ctx context.Context, src volume.ReadOnly, dst *registry.Client, ref string, opts Options) (string, error)
Freeze reads src in fixed-size chunk windows, pushes each UNIQUE chunk to dst once (deduplicating by content — all-zero holes collapse to nothing stored), builds a config blob carrying the geometry and ordered chunk-digest index, and pushes an OCI image manifest tagged ref whose layers are the deduped chunk blobs. It returns the manifest digest.
Types ¶
type Config ¶
type Config struct {
// MediaType identifies the payload format.
MediaType string `json:"mediaType"`
// Size is the logical image size in bytes.
Size int64 `json:"size"`
// ChunkSize is the fixed chunk window in bytes (a power of two).
ChunkSize int64 `json:"chunkSize"`
// Chunks is the ordered per-chunk digest index, one entry per chunk window
// covering [0, Size). "" means an all-zero (hole) chunk.
Chunks []string `json:"chunks"`
}
Config is the JSON config blob: the image geometry plus the ordered list of per-chunk digests. Reading chunk i means fetching Chunks[i]; an empty string denotes an all-zero chunk that need not be stored at all.
type Image ¶
type Image struct {
// contains filtered or unexported fields
}
Image is a read-only block backing recovered from a frozen OCI artifact. It serves ReadAt by pulling the covering chunk blobs on demand (an LRU byte cache avoids re-pulling hot chunks); hole chunks read as zeros. It satisfies both volume.ReadOnly and pool.Backing, and rejects all writes with ErrReadOnly so pool.OpenWith gets a genuinely immutable store.
func OpenReadOnly ¶
OpenReadOnly pulls and parses the manifest tagged ref, recovers the config (size, chunk size, ordered chunk-digest index) and returns an *Image serving reads from src.
func (*Image) ReadAt ¶
ReadAt assembles len(p) bytes at off from the covering chunks, pulling each by digest (cached) and treating hole chunks as zeros. A read past the end returns the bytes available and io.EOF, matching io.ReaderAt semantics.
func (*Image) Sync ¶
Sync always fails: a frozen image is read-only, so any attempt to commit buffered state is rejected. A read-only consumer that never mutates never calls Sync.
type Options ¶
type Options struct {
// ChunkSize is the fixed chunk window in bytes; it must be a power of two.
// Zero selects DefaultChunkSize.
ChunkSize int64
}
Options configures Freeze.
type Overlay ¶
type Overlay struct {
// contains filtered or unexported fields
}
Overlay is a read-write block backing layered over an immutable OCI base Image. Writes are buffered in memory — the base is never mutated — and reads merge the dirty overlay over the base (a never-written region falls through to the base, or reads zero past it). Overlay.Sync is a no-op: durability is the explicit Overlay.Commit, which snapshots the current state into a new versioned OCI artifact and pushes blobs ONLY for the chunks that changed.
Because the overlay absorbs every write — including a pool's own metadata writes — pool.OpenWith(overlay) yields a fully read-write pool over a frozen, content-addressed base: edit, then Commit to a new tag.
func NewOverlay ¶
NewOverlay wraps an immutable base Image in a writable overlay, starting at the base's size and chunk size.
func (*Overlay) Close ¶
Close releases the overlay; the base Image and its registry client remain the caller's to close.
func (*Overlay) Commit ¶
Commit snapshots the overlay's current state into a NEW immutable OCI artifact tagged ref on dst, pushing blobs ONLY for the chunks that changed since the base: an unchanged chunk reuses the base's digest verbatim — no pull, no re-hash, no re-push — so a commit costs the size of the delta, and unchanged chunks are shared by digest across every tag. It returns the new manifest digest. The overlay and its base are left unchanged; reopen ref with OpenReadOnly (e.g. to branch a new overlay from it).
dst may be the base's registry (versioned tags in one repo) or a different one (push the snapshot elsewhere); when it is the base's registry the unchanged chunk blobs are already present, so only the delta uploads.
func (*Overlay) ReadAt ¶
ReadAt assembles len(p) bytes at off, merging the dirty overlay over the base. A read past the current size returns the available bytes and io.EOF.
func (*Overlay) Size ¶
Size reports the current logical size, which may exceed the base after a grow.
func (*Overlay) Sync ¶
Sync is a no-op: the overlay is in memory and durability is provided by Overlay.Commit.