Documentation
¶
Index ¶
- Constants
- func CheckPushPermissions(ctx context.Context, imageRef string) error
- func DeleteManifest(ctx context.Context, ref string) error
- func ParseImageReference(s string) (name.Reference, error)
- func PullBlob(ctx context.Context, repository, digest string) (io.ReadCloser, error)
- func PushBlob(ctx context.Context, repository, mediaType string, r io.Reader) (string, int64, error)
- func PushBlobStreaming(ctx context.Context, repository, mediaType string, r io.Reader) (string, int64, error)
- func PushManifest(ctx context.Context, ref string, m *Manifest) error
- func PushVolumesFromTunnel(ctx context.Context, client tunnel.TunnelClient, repository string) (string, int64, error)
- func RestoreComposition(snapshotRef string) (source string, devContainerSource string, err error)
- type BuildManifestOptions
- type Descriptor
- type Manifest
- type Ref
Constants ¶
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" )
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 ¶
CheckPushPermissions checks push permission for imageRef, honoring this package's dockerInternalHost insecure-registry override.
func DeleteManifest ¶
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 ¶
ParseImageReference parses s as an image reference, honoring this package's dockerInternalHost insecure-registry override.
func PullBlob ¶
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 ¶
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 ¶
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 (*Manifest) ContainerEnv ¶
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 (*Manifest) RunArgs ¶
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 ¶
Ref identifies a snapshot as <repository>:<workspace-id>-<timestamp>-<random>.
func ListRefs ¶
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 (*Ref) FSImageRef ¶
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.