snapshot

package
v1.14.0-beta.1 Latest Latest
Warning

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

Go to latest
Published: Aug 3, 2026 License: MPL-2.0 Imports: 21 Imported by: 0

Documentation

Index

Constants

View Source
const (
	VolumesMediaType     = "application/vnd.devsy.snapshot.volumes.v1.tar+gzip"
	ManifestMediaType    = "application/vnd.oci.image.manifest.v1+json"
	ManifestArtifactType = "application/vnd.devsy.snapshot.manifest.v1+json"
)
View Source
const (
	AnnotationWorkspaceUID     = "sh.devsy.snapshot.workspace-uid"
	AnnotationCreatedAt        = "sh.devsy.snapshot.created-at"
	AnnotationParent           = "sh.devsy.snapshot.parent"
	AnnotationDevContainerHash = "sh.devsy.snapshot.devcontainer-hash"
	AnnotationSourceProvider   = "sh.devsy.snapshot.source-provider"
	AnnotationMessage          = "sh.devsy.snapshot.message"
	// AnnotationMountPrefix is the create-time mount target path (leading "/"
	// trimmed) that volumes archive entries are prefixed with. Restore must
	// strip exactly this many path segments regardless of the restore-side
	// mount target's own depth, since the two are not guaranteed to match
	// (different provider defaults, different workspace-folder conventions).
	AnnotationMountPrefix = "sh.devsy.snapshot.mount-prefix"
	// AnnotationRunArgs is the create-time devcontainer.json's runArgs
	// (JSON-encoded []string), replayed onto the restored container so
	// runArgs the original devcontainer.json relied on (e.g.
	// --add-host=host.docker.internal:host-gateway for a registry reachable
	// only via that hostname) still apply — restore pins DevContainerSource
	// to the committed image, which bypasses the project devcontainer.json
	// and would otherwise silently drop them.
	AnnotationRunArgs = "sh.devsy.snapshot.run-args"
	// AnnotationContainerEnv is the create-time devcontainer.json's
	// containerEnv (JSON-encoded map[string]string), replayed onto the
	// restored container for the same reason as AnnotationRunArgs: restore
	// pins DevContainerSource to the committed image, bypassing the project
	// devcontainer.json and silently dropping any containerEnv it set.
	AnnotationContainerEnv = "sh.devsy.snapshot.container-env"
)

Variables

This section is empty.

Functions

func CheckPushPermissions

func CheckPushPermissions(ctx context.Context, imageRef string) error

CheckPushPermissions checks push permission for imageRef, honoring this package's dockerInternalHost insecure-registry override.

func DeleteManifest

func DeleteManifest(ctx context.Context, ref string) error

DeleteManifest deletes the manifest tag at ref. Orphaned blobs are left for the registry's own garbage collection, matching the design's atomicity model (manifest visibility is the only thing that matters).

Real registries (e.g. registry:2) reject DELETE-by-tag with 400 DIGEST_INVALID and only accept DELETE-by-digest, so this resolves ref to its digest via HEAD before deleting, rather than deleting the tag reference directly.

func ParseImageReference

func ParseImageReference(s string) (name.Reference, error)

ParseImageReference parses s as an image reference, honoring this package's dockerInternalHost insecure-registry override.

func PullBlob

func PullBlob(ctx context.Context, repository, digest string) (io.ReadCloser, error)

PullBlob returns the blob's content as an io.ReadCloser; the caller owns it and must Close it.

func PushBlob

func PushBlob(
	ctx context.Context, repository, mediaType string, r io.Reader,
) (string, int64, error)

PushBlob pushes the content of r as a content-addressed blob of mediaType into repository and returns its digest and size. The blob is stored verbatim (no gzip envelope), so the returned digest and size describe the exact bytes read from r, and PullBlob returns them unchanged.

func PushBlobStreaming

func PushBlobStreaming(
	ctx context.Context, repository, mediaType string, r io.Reader,
) (string, int64, error)

PushBlobStreaming pushes the content of r as a content-addressed blob of mediaType into repository, like PushBlob, but spools r to a temp file instead of buffering it in memory. Use this for blobs that may be large (e.g. workspace volume tars); PushBlob remains the simpler choice for small, already in-memory content such as manifests.

func PushManifest

func PushManifest(ctx context.Context, ref string, m *Manifest) error

The manifest's config/layer digests must already exist in the repository (pushed via PushBlob).

func PushVolumesFromTunnel

func PushVolumesFromTunnel(
	ctx context.Context, client tunnel.TunnelClient, repository string,
) (string, int64, error)

PushVolumesFromTunnel asks the in-container agent to tar its workspace mounts over the existing gRPC tunnel and streams the result into the registry as a volumes blob. The stream is spooled to a temp file rather than buffered in memory (via PushBlobStreaming), since workspace volume tars can be multiple GB.

func RestoreComposition

func RestoreComposition(snapshotRef string) (source string, devContainerSource string, err error)

RestoreComposition parses snapshotRef and returns the WorkspaceSource string and DevContainerSource override needed to restore a workspace from it: "snapshot:<ref>" and "image:<repository>:<tag>-fs". `devsy snapshot restore` and `devsy up --from-snapshot` both call this so a snapshot restores identically regardless of entry point.

Types

type BuildManifestOptions

type BuildManifestOptions struct {
	WorkspaceUID     string
	CreatedAt        time.Time
	Parent           string
	DevContainerHash string
	SourceProvider   string
	Message          string
	MountPrefix      string
	RunArgs          []string
	ContainerEnv     map[string]string

	ContainerImageMediaType string
	ContainerImageDigest    string
	ContainerImageSize      int64

	VolumesDigest string
	VolumesSize   int64
}

type Descriptor

type Descriptor struct {
	MediaType string `json:"mediaType"`
	Digest    string `json:"digest"`
	Size      int64  `json:"size"`
}

Descriptor mirrors the OCI content descriptor fields we need; kept minimal rather than depending on go-containerregistry's v1.Descriptor so this package stays free of registry I/O concerns.

type Manifest

type Manifest struct {
	SchemaVersion int               `json:"schemaVersion"`
	MediaType     string            `json:"mediaType"`
	ArtifactType  string            `json:"artifactType,omitempty"`
	Config        Descriptor        `json:"config"`
	Layers        []Descriptor      `json:"layers"`
	Annotations   map[string]string `json:"annotations,omitempty"`
}

func BuildManifest

func BuildManifest(opts BuildManifestOptions) (*Manifest, error)

BuildManifest builds a snapshot manifest referencing the committed container image and the volumes blob by digest, annotated per the sh.devsy.snapshot.* convention.

func ParseManifest

func ParseManifest(raw []byte) (*Manifest, error)

func PullManifest

func PullManifest(ctx context.Context, ref string) (*Manifest, error)

func (*Manifest) ContainerEnv

func (m *Manifest) ContainerEnv() (map[string]string, error)

ContainerEnv decodes the create-time devcontainer.json's containerEnv from the manifest, or returns nil when the snapshot carries none.

func (*Manifest) ContainerImage

func (m *Manifest) ContainerImage() (Descriptor, error)

ContainerImage returns the manifest's committed container filesystem layer, or an error if the manifest's layer contract isn't satisfied (see validateLayers).

func (*Manifest) MarshalOCI

func (m *Manifest) MarshalOCI() ([]byte, error)

func (*Manifest) RunArgs

func (m *Manifest) RunArgs() ([]string, error)

RunArgs decodes the create-time devcontainer.json's runArgs from the manifest, or returns nil when the snapshot carries none.

func (*Manifest) Volumes

func (m *Manifest) Volumes() (Descriptor, error)

Volumes returns the manifest's volumes archive layer, or an error if the manifest's layer contract isn't satisfied (see validateLayers).

type Ref

type Ref struct {
	Repository  string
	WorkspaceID string
	Timestamp   time.Time
	Tag         string
}

Ref identifies a snapshot as <repository>:<workspace-id>-<timestamp>-<random>.

func ListRefs

func ListRefs(ctx context.Context, repository, workspaceID string) ([]*Ref, error)

ListRefs lists snapshot tags in repository belonging to workspaceID, newest first. Tags are filtered by the "<workspace-id>-<timestamp>" naming convention rather than by pulling every manifest, since registries expose tag lists cheaply but annotations only after a manifest GET. remote.List fetches every tag in the repository in one call, so cost grows with total snapshot count across all workspaces sharing repository, not just workspaceID's.

func NewRef

func NewRef(repository, workspaceID string, at time.Time) (*Ref, error)

func ParseRef

func ParseRef(s string) (*Ref, error)

func (*Ref) FSImageRef

func (r *Ref) FSImageRef() string

FSImageRef is the single place that owns the "-fs" suffix convention: `snapshot create` pushes the committed container image under this ref, and `snapshot restore` / `up --from-snapshot` point DevContainerSource at it.

func (*Ref) String

func (r *Ref) String() string

Jump to

Keyboard shortcuts

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