oras

package module
v3.0.0-...-42c1a3a Latest Latest
Warning

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

Go to latest
Published: Jan 26, 2026 License: Apache-2.0 Imports: 27 Imported by: 0

README

ORAS Go library

ORAS logo

oras-go is a Go library for managing OCI artifacts, compliant with the OCI Image Format Specification and the OCI Distribution Specification. It provides unified APIs for pushing, pulling, and managing artifacts across OCI-compliant registries, local file systems, and in-memory stores.

[!Note] The main and v2 branches follow Go's Security Policy and support the two latest versions of Go (currently 1.24 and 1.25).

Getting Started

Concepts

Gain insights into the fundamental concepts:

Quickstart

Follow the step-by-step tutorial to use oras-go v2:

Examples

Check out sample code for common use cases of oras-go v2:

Find more API examples at pkg.go.dev.

Versioning

This project follows Semantic Versioning (MAJOR.MINOR.PATCH), with MAJOR for breaking changes, MINOR for backward-compatible features, and PATCH for backward-compatible fixes.

Branches

main (v3 development)

Build Status codecov

The main branch is under active development for v3 and may contain breaking changes. Not recommended for production use.

v2 (stable)

Build Status codecov Go Report Card Go Reference

The v2 branch contains the latest stable release and is recommended for production use.

New features and bug fixes from main will be backported to v2 if applicable.

v1 (maintenance)

Build Status codecov Go Report Card Go Reference

The v1 branch is in maintenance mode and receives only dependency updates and security fixes. No new features are planned.

To migrate from v1 to v2, see MIGRATION_GUIDE.md.

Community

Documentation

Overview

Example (AttachBlobToRemoteRepository)

ExampleAttachBlobToRemoteRepository gives an example of attaching a blob to an existing artifact in a remote repository. The blob is packed as a manifest whose subject is the existing artifact.

package main

import (
	"context"
	"fmt"

	v1 "github.com/opencontainers/image-spec/specs-go/v1"
	oras "github.com/oras-project/oras-go/v3"
	"github.com/oras-project/oras-go/v3/registry/remote"
	"github.com/oras-project/oras-go/v3/registry/remote/auth"
	"github.com/oras-project/oras-go/v3/registry/remote/retry"
)

func main() {
	// 0. Connect to a remote repository with basic authentication
	registry := "myregistry.example.com"
	repository := "myrepo"
	repo, err := remote.NewRepository(fmt.Sprintf("%s/%s", registry, repository))
	if err != nil {
		panic(err)
	}
	// Note: The below code can be omitted if authentication is not required.
	repo.Client = &auth.Client{
		Client: retry.DefaultClient,
		Cache:  auth.NewCache(),
		Credential: auth.StaticCredential(registry, auth.Credential{
			Username: "username",
			Password: "password",
		}),
	}

	// 1. Resolve the subject descriptor
	ctx := context.Background()
	subjectDescriptor, err := repo.Resolve(ctx, "sha256:f3a0356fe9f82b925c2f15106d3932252f36c1c56fd35be6c369d274f433d177")
	if err != nil {
		panic(err)
	}

	// 2. Prepare the blob to be attached
	blob := []byte("example blob")

	// 3. Push the blob to the repository
	blobDescriptor, err := oras.PushBytes(ctx, repo, v1.MediaTypeImageLayer, blob)
	if err != nil {
		panic(err)
	}
	fmt.Println("pushed the blob to the repository")

	// 4. Pack the blob as a manifest with version v1.1 and push it to the repository
	packOpts := oras.PackManifestOptions{
		Layers:  []v1.Descriptor{blobDescriptor},
		Subject: &subjectDescriptor,
	}
	artifactType := "application/vnd.example+type"
	referrerDescriptor, err := oras.PackManifest(ctx, repo, oras.PackManifestVersion1_1, artifactType, packOpts)
	if err != nil {
		panic(err)
	}
	fmt.Printf("attached %s to %s\n", referrerDescriptor.Digest, subjectDescriptor.Digest)
}
Example (CopyArtifactFromRepository)

ExampleCopyArtifactFromRepository gives an example of copying an artifact from a remote repository into memory.

// 0. Connect to a remote repository
repositoryName := "source"
src, err := remote.NewRepository(fmt.Sprintf("%s/%s", remoteHost, repositoryName))
if err != nil {
	panic(err)
}

// 1. Create a memory store
dst := memory.New()
ctx := context.Background()

// 2. Resolve the descriptor of the artifact from the digest
exampleDigest := "sha256:70c29a81e235dda5c2cebb8ec06eafd3cca346cbd91f15ac74cefd98681c5b3d"
descriptor, err := src.Resolve(ctx, exampleDigest)
if err != nil {
	panic(err)
}

// 3. Copy the artifact from the remote repository
err = oras.CopyGraph(ctx, src, dst, descriptor, oras.DefaultCopyGraphOptions)
if err != nil {
	panic(err)
}

// 4. Verify that the artifact manifest described by the descriptor exists in dst
contentExists, err := dst.Exists(ctx, descriptor)
if err != nil {
	panic(err)
}
fmt.Println(contentExists)
Output:

true
Example (ExtendedCopyArtifactAndReferrersFromRepository)

ExampleExtendedCopyArtifactAndReferrersFromRepository gives an example of copying an artifact along with its referrers from a remote repository into memory.

// 0. Connect to a remote repository
repositoryName := "source"
src, err := remote.NewRepository(fmt.Sprintf("%s/%s", remoteHost, repositoryName))
if err != nil {
	panic(err)
}

// 1. Create a memory store
dst := memory.New()
ctx := context.Background()

// 2. Copy the artifact and its referrers from the remote repository
tagName := "latest"
// ExtendedCopy will copy the artifact tagged by "latest" along with all of its
// referrers from src to dst.
desc, err := oras.ExtendedCopy(ctx, src, tagName, dst, tagName, oras.DefaultExtendedCopyOptions)
if err != nil {
	panic(err)
}

fmt.Println(desc.Digest)
Output:

sha256:f396bc4d300934a39ca28ab0d5ac8a3573336d7d63c654d783a68cd1e2057662
Example (ExtendedCopyArtifactAndReferrersToRepository)

ExampleExtendedCopyArtifactAndReferrersToRepository is an example of pushing an artifact and its referrer to a remote repository.

// 0. Assemble the referenced manifest in memory with tag "v1"
ctx := context.Background()
src := memory.New()
manifestDescriptor, err := oras.PackManifest(ctx, src, oras.PackManifestVersion1_1, "application/vnd.example+type", oras.PackManifestOptions{})
if err != nil {
	panic(err)
}
fmt.Println("created manifest: ", manifestDescriptor)

tag := "v1"
err = src.Tag(ctx, manifestDescriptor, tag)
if err != nil {
	panic(err)
}
fmt.Println("tagged manifest: ", manifestDescriptor.Digest)

// 1. Assemble the referrer manifest in memory
referrerPackOpts := oras.PackManifestOptions{
	Subject: &manifestDescriptor,
}
referrerDescriptor, err := oras.PackManifest(ctx, src, oras.PackManifestVersion1_1, "sbom/example", referrerPackOpts)
if err != nil {
	panic(err)
}
fmt.Println("created referrer: ", referrerDescriptor)

// 2. Connect to a remote repository with basic authentication
registry := "myregistry.example.com"
repository := "myrepo"
repo, err := remote.NewRepository(fmt.Sprintf("%s/%s", registry, repository))
if err != nil {
	panic(err)
}
// Note: The below code can be omitted if authentication is not required.
repo.Client = &auth.Client{
	Client: retry.DefaultClient,
	Cache:  auth.NewCache(),
	Credential: auth.StaticCredential(registry, auth.Credential{
		Username: "username",
		Password: "password",
	}),
}

// 3. Push the manifest and its referrer to the remote repository
desc, err := oras.ExtendedCopy(ctx, src, tag, repo, "", oras.DefaultExtendedCopyOptions)
if err != nil {
	panic(err)
}
fmt.Println("pushed: ", desc.Digest)
Example (PullFilesFromRemoteRepository)

ExamplePullFilesFromRemoteRepository gives an example of pulling files from a remote repository to the local file system.

package main

import (
	"context"
	"fmt"

	oras "github.com/oras-project/oras-go/v3"
	"github.com/oras-project/oras-go/v3/content/file"
	"github.com/oras-project/oras-go/v3/registry/remote"
	"github.com/oras-project/oras-go/v3/registry/remote/auth"
	"github.com/oras-project/oras-go/v3/registry/remote/retry"
)

func main() {
	// 0. Create a file store
	fs, err := file.New("/tmp/")
	if err != nil {
		panic(err)
	}
	defer fs.Close()

	// 1. Connect to a remote repository
	ctx := context.Background()
	reg := "myregistry.example.com"
	repo, err := remote.NewRepository(reg + "/myrepo")
	if err != nil {
		panic(err)
	}
	// Note: The below code can be omitted if authentication is not required
	repo.Client = &auth.Client{
		Client: retry.DefaultClient,
		Cache:  auth.NewCache(),
		Credential: auth.StaticCredential(reg, auth.Credential{
			Username: "username",
			Password: "password",
		}),
	}

	// 2. Copy from the remote repository to the file store
	tag := "latest"
	manifestDescriptor, err := oras.Copy(ctx, repo, tag, fs, tag, oras.DefaultCopyOptions)
	if err != nil {
		panic(err)
	}
	fmt.Println("manifest descriptor:", manifestDescriptor)
}
Example (PullImageFromRemoteRepository)

ExamplePullImageFromRemoteRepository gives an example of pulling an image from a remote repository to an OCI Image layout folder.

package main

import (
	"context"
	"fmt"

	oras "github.com/oras-project/oras-go/v3"
	"github.com/oras-project/oras-go/v3/content/oci"
	"github.com/oras-project/oras-go/v3/registry/remote"
	"github.com/oras-project/oras-go/v3/registry/remote/auth"
	"github.com/oras-project/oras-go/v3/registry/remote/retry"
)

func main() {
	// 0. Create an OCI layout store
	store, err := oci.New("/tmp/oci-layout-root")
	if err != nil {
		panic(err)
	}

	// 1. Connect to a remote repository
	ctx := context.Background()
	reg := "myregistry.example.com"
	repo, err := remote.NewRepository(reg + "/myrepo")
	if err != nil {
		panic(err)
	}
	// Note: The below code can be omitted if authentication is not required
	repo.Client = &auth.Client{
		Client: retry.DefaultClient,
		Cache:  auth.NewCache(),
		Credential: auth.StaticCredential(reg, auth.Credential{
			Username: "username",
			Password: "password",
		}),
	}

	// 2. Copy from the remote repository to the OCI layout store
	tag := "latest"
	manifestDescriptor, err := oras.Copy(ctx, repo, tag, store, tag, oras.DefaultCopyOptions)
	if err != nil {
		panic(err)
	}
	fmt.Println("manifest descriptor:", manifestDescriptor)
}
Example (PullImageUsingDockerCredentials)

ExamplePullImageUsingDockerCredentials gives an example of pulling an image from a remote repository to an OCI Image layout folder using Docker credentials.

package main

import (
	"context"
	"fmt"

	oras "github.com/oras-project/oras-go/v3"
	"github.com/oras-project/oras-go/v3/content/oci"
	"github.com/oras-project/oras-go/v3/registry/remote"
	"github.com/oras-project/oras-go/v3/registry/remote/auth"
	"github.com/oras-project/oras-go/v3/registry/remote/credentials"
	"github.com/oras-project/oras-go/v3/registry/remote/retry"
)

func main() {
	// 0. Create an OCI layout store
	store, err := oci.New("/tmp/oci-layout-root")
	if err != nil {
		panic(err)
	}

	// 1. Connect to a remote repository
	ctx := context.Background()
	reg := "docker.io"
	repo, err := remote.NewRepository(reg + "/user/my-repo")
	if err != nil {
		panic(err)
	}

	// prepare authentication using Docker credentials
	storeOpts := credentials.StoreOptions{}
	credStore, err := credentials.NewStoreFromDocker(storeOpts)
	if err != nil {
		panic(err)
	}
	repo.Client = &auth.Client{
		Client:     retry.DefaultClient,
		Cache:      auth.NewCache(),
		Credential: credentials.Credential(credStore), // Use the credentials store
	}

	// 2. Copy from the remote repository to the OCI layout store
	tag := "latest"
	manifestDescriptor, err := oras.Copy(ctx, repo, tag, store, tag, oras.DefaultCopyOptions)
	if err != nil {
		panic(err)
	}

	fmt.Println("manifest pulled:", manifestDescriptor.Digest, manifestDescriptor.MediaType)
}
Example (PushFilesToRemoteRepository)

ExamplePushFilesToRemoteRepository gives an example of pushing local files to a remote repository.

package main

import (
	"context"
	"fmt"

	v1 "github.com/opencontainers/image-spec/specs-go/v1"
	oras "github.com/oras-project/oras-go/v3"
	"github.com/oras-project/oras-go/v3/content/file"
	"github.com/oras-project/oras-go/v3/registry/remote"
	"github.com/oras-project/oras-go/v3/registry/remote/auth"
	"github.com/oras-project/oras-go/v3/registry/remote/retry"
)

func main() {
	// 0. Create a file store
	fs, err := file.New("/tmp/")
	if err != nil {
		panic(err)
	}
	defer fs.Close()
	ctx := context.Background()

	// 1. Add files to the file store
	mediaType := "application/vnd.test.file"
	fileNames := []string{"/tmp/myfile"}
	fileDescriptors := make([]v1.Descriptor, 0, len(fileNames))
	for _, name := range fileNames {
		fileDescriptor, err := fs.Add(ctx, name, mediaType, "")
		if err != nil {
			panic(err)
		}
		fileDescriptors = append(fileDescriptors, fileDescriptor)
		fmt.Printf("file descriptor for %s: %v\n", name, fileDescriptor)
	}

	// 2. Pack the files and tag the packed manifest
	artifactType := "application/vnd.test.artifact"
	opts := oras.PackManifestOptions{
		Layers: fileDescriptors,
	}
	manifestDescriptor, err := oras.PackManifest(ctx, fs, oras.PackManifestVersion1_1, artifactType, opts)
	if err != nil {
		panic(err)
	}
	fmt.Println("manifest descriptor:", manifestDescriptor)

	tag := "latest"
	if err = fs.Tag(ctx, manifestDescriptor, tag); err != nil {
		panic(err)
	}

	// 3. Connect to a remote repository
	reg := "myregistry.example.com"
	repo, err := remote.NewRepository(reg + "/myrepo")
	if err != nil {
		panic(err)
	}
	// Note: The below code can be omitted if authentication is not required
	repo.Client = &auth.Client{
		Client: retry.DefaultClient,
		Cache:  auth.NewCache(),
		Credential: auth.StaticCredential(reg, auth.Credential{
			Username: "username",
			Password: "password",
		}),
	}

	// 4. Copy from the file store to the remote repository
	_, err = oras.Copy(ctx, fs, tag, repo, tag, oras.DefaultCopyOptions)
	if err != nil {
		panic(err)
	}
}

Index

Examples

Constants

View Source
const (
	// MediaTypeUnknownConfig is the default config mediaType used
	//   - for [Pack] when PackOptions.PackImageManifest is true and
	//     PackOptions.ConfigDescriptor is not specified.
	//   - for [PackManifest] when packManifestVersion is PackManifestVersion1_0
	//     and PackManifestOptions.ConfigDescriptor is not specified.
	MediaTypeUnknownConfig = "application/vnd.unknown.config.v1+json"

	// MediaTypeUnknownArtifact is the default artifactType used for [Pack]
	// when PackOptions.PackImageManifest is false and artifactType is
	// not specified.
	MediaTypeUnknownArtifact = "application/vnd.unknown.artifact.v1"
)

Variables

View Source
var (
	// ErrInvalidDateTimeFormat is returned by [Pack] and [PackManifest] when
	// "org.opencontainers.artifact.created" or "org.opencontainers.image.created"
	// is provided, but its value is not in RFC 3339 format.
	// Reference: https://www.rfc-editor.org/rfc/rfc3339#section-5.6
	ErrInvalidDateTimeFormat = errors.New("invalid date and time format")

	// ErrMissingArtifactType is returned by [PackManifest] when
	// packManifestVersion is PackManifestVersion1_1 and artifactType is
	// empty and the config media type is set to
	// "application/vnd.oci.empty.v1+json".
	ErrMissingArtifactType = errors.New("missing artifact type")
)
View Source
var SkipNode = errors.New("skip node")

SkipNode signals to stop copying a node. When returned from PreCopy the blob must exist in the target. This can be used to signal that a blob has been made available in the target repository by "Mount()" or some other technique.

Functions

func Copy

func Copy(ctx context.Context, src ReadOnlyTarget, srcRef string, dst Target, dstRef string, opts CopyOptions) (ocispec.Descriptor, error)

Copy copies a rooted directed acyclic graph (DAG), such as an artifact, from the source Target to the destination Target.

The root node (e.g. a tagged manifest of the artifact) is identified by the source reference. The destination reference will be the same as the source reference if the destination reference is left blank.

Returns the descriptor of the root node on successful copy.

Example (MemoryToMemory)
src := exampleMemoryStore
dst := memory.New()

tagName := "latest"
ctx := context.Background()
desc, err := oras.Copy(ctx, src, tagName, dst, tagName, oras.DefaultCopyOptions)
if err != nil {
	panic(err) // Handle error
}
fmt.Println(desc.Digest)
Output:

sha256:7cbb44b44e8ede5a89cf193db3f5f2fd019d89697e6b87e8ed2589e60649b0d1
Example (MemoryToOCIStore)
src := exampleMemoryStore
tempDir, err := os.MkdirTemp("", "oras_oci_example_*")
if err != nil {
	panic(err) // Handle error
}
defer os.RemoveAll(tempDir)
dst, err := oci.New(tempDir)
if err != nil {
	panic(err) // Handle error
}

tagName := "latest"
ctx := context.Background()
desc, err := oras.Copy(ctx, src, tagName, dst, tagName, oras.DefaultCopyOptions)
if err != nil {
	panic(err) // Handle error
}
fmt.Println(desc.Digest)
Output:

sha256:7cbb44b44e8ede5a89cf193db3f5f2fd019d89697e6b87e8ed2589e60649b0d1
Example (MemoryToRepository)
src := exampleMemoryStore
reg, err := remote.NewRegistry(remoteHost)
if err != nil {
	panic(err) // Handle error
}
ctx := context.Background()
dst, err := reg.Repository(ctx, "destination")
if err != nil {
	panic(err) // Handle error
}

tagName := "latest"
desc, err := oras.Copy(ctx, src, tagName, dst, tagName, oras.DefaultCopyOptions)
if err != nil {
	panic(err) // Handle error
}
fmt.Println(desc.Digest)
Output:

sha256:7cbb44b44e8ede5a89cf193db3f5f2fd019d89697e6b87e8ed2589e60649b0d1
Example (RepositoryToMemory)
reg, err := remote.NewRegistry(remoteHost)
if err != nil {
	panic(err) // Handle error
}

ctx := context.Background()
src, err := reg.Repository(ctx, "source")
if err != nil {
	panic(err) // Handle error
}
dst := memory.New()

tagName := "latest"
desc, err := oras.Copy(ctx, src, tagName, dst, tagName, oras.DefaultCopyOptions)
if err != nil {
	panic(err) // Handle error
}
fmt.Println(desc.Digest)
Output:

sha256:7cbb44b44e8ede5a89cf193db3f5f2fd019d89697e6b87e8ed2589e60649b0d1
Example (RepositoryToRepository)
reg, err := remote.NewRegistry(remoteHost)
if err != nil {
	panic(err) // Handle error
}
ctx := context.Background()
src, err := reg.Repository(ctx, "source")
if err != nil {
	panic(err) // Handle error
}
dst, err := reg.Repository(ctx, "destination")
if err != nil {
	panic(err) // Handle error
}

tagName := "latest"
desc, err := oras.Copy(ctx, src, tagName, dst, tagName, oras.DefaultCopyOptions)
if err != nil {
	panic(err) // Handle error
}
fmt.Println(desc.Digest)
Output:

sha256:7cbb44b44e8ede5a89cf193db3f5f2fd019d89697e6b87e8ed2589e60649b0d1
Example (RepositoryToRepositoryWithMount)
reg, err := remote.NewRegistry(remoteHost)
if err != nil {
	panic(err) // Handle error
}
ctx := context.Background()
src, err := reg.Repository(ctx, "source")
if err != nil {
	panic(err) // Handle error
}
dst, err := reg.Repository(ctx, "destination")
if err != nil {
	panic(err) // Handle error
}

tagName := "latest"

opts := oras.CopyOptions{}
// optionally be notified that a mount occurred.
opts.OnMounted = func(ctx context.Context, desc ocispec.Descriptor) error {
	// log.Println("Mounted", desc.Digest)
	return nil
}

// Enable cross-repository blob mounting
opts.MountFrom = func(ctx context.Context, desc ocispec.Descriptor) ([]string, error) {
	// the slice of source repositories may also come from a database of known locations of blobs
	return []string{"source/repository/name"}, nil
}

desc, err := oras.Copy(ctx, src, tagName, dst, tagName, opts)
if err != nil {
	panic(err) // Handle error
}
fmt.Println("Final", desc.Digest)
Output:

Final sha256:7cbb44b44e8ede5a89cf193db3f5f2fd019d89697e6b87e8ed2589e60649b0d1

func CopyGraph

CopyGraph copies a rooted directed acyclic graph (DAG), such as an artifact, from the source CAS to the destination CAS. The root node (e.g. a manifest of the artifact) is identified by a descriptor.

func ExtendedCopy

func ExtendedCopy(ctx context.Context, src ReadOnlyGraphTarget, srcRef string, dst Target, dstRef string, opts ExtendedCopyOptions) (ocispec.Descriptor, error)

ExtendedCopy copies the directed acyclic graph (DAG) that are reachable from the given tagged node from the source GraphTarget to the destination Target. In other words, it copies a tagged artifact along with its referrers or other predecessor manifests referencing it.

The tagged node (e.g. a tagged manifest of the artifact) is identified by the source reference. The destination reference will be the same as the source reference if the destination reference is left blank.

Returns the descriptor of the tagged node on successful copy.

func ExtendedCopyGraph

ExtendedCopyGraph copies the directed acyclic graph (DAG) that are reachable from the given node from the source GraphStorage to the destination Storage. In other words, it copies an artifact along with its referrers or other predecessor manifests referencing it. The node (e.g. a manifest of the artifact) is identified by a descriptor.

func Fetch

func Fetch(ctx context.Context, target ReadOnlyTarget, reference string, opts FetchOptions) (ocispec.Descriptor, io.ReadCloser, error)

Fetch fetches the content identified by the reference.

func FetchBytes

func FetchBytes(ctx context.Context, target ReadOnlyTarget, reference string, opts FetchBytesOptions) (ocispec.Descriptor, []byte, error)

FetchBytes fetches the content bytes identified by the reference.

func Pack deprecated

func Pack(ctx context.Context, pusher content.Pusher, artifactType string, blobs []ocispec.Descriptor, opts PackOptions) (ocispec.Descriptor, error)

Pack packs the given blobs, generates a manifest for the pack, and pushes it to a content storage.

When opts.PackImageManifest is true, artifactType will be used as the the config descriptor mediaType of the image manifest.

If succeeded, returns a descriptor of the manifest.

Deprecated: This method is deprecated and not recommended for future use. Use PackManifest instead.

func PackManifest

func PackManifest(ctx context.Context, pusher content.Pusher, packManifestVersion PackManifestVersion, artifactType string, opts PackManifestOptions) (ocispec.Descriptor, error)

PackManifest generates an OCI Image Manifest based on the given parameters and pushes the packed manifest to a content storage using pusher. The version of the manifest to be packed is determined by packManifestVersion (Recommended value: PackManifestVersion1_1).

  • If packManifestVersion is PackManifestVersion1_1: artifactType MUST NOT be empty unless opts.ConfigDescriptor is specified.
  • If packManifestVersion is PackManifestVersion1_0: if opts.ConfigDescriptor is nil, artifactType will be used as the config media type; if artifactType is empty, "application/vnd.unknown.config.v1+json" will be used. if opts.ConfigDescriptor is NOT nil, artifactType will be ignored.

artifactType and opts.ConfigDescriptor.MediaType MUST comply with RFC 6838.

Each time when PackManifest is called, if a time stamp is not specified, a new time stamp is generated in the manifest annotations with the key ocispec.AnnotationCreated (i.e. "org.opencontainers.image.created"). To make PackManifest reproducible, set the key ocispec.AnnotationCreated to a fixed value in opts.ManifestAnnotations. The value MUST conform to RFC 3339.

If succeeded, returns a descriptor of the packed manifest.

Example (ImageV10)

ExampleImageV10 demonstrates packing an OCI Image Manifest as defined in image-spec v1.0.2.

// 0. Create a storage
store := memory.New()

// 1. Set optional parameters
opts := oras.PackManifestOptions{
	ManifestAnnotations: map[string]string{
		// this time stamp will be automatically generated if not specified
		// use a fixed value here to make the pack result reproducible
		ocispec.AnnotationCreated: "2000-01-01T00:00:00Z",
	},
}
ctx := context.Background()

// 2. Pack a manifest
artifactType := "application/vnd.example+type"
manifestDesc, err := oras.PackManifest(ctx, store, oras.PackManifestVersion1_0, artifactType, opts)
if err != nil {
	panic(err)
}
fmt.Println("Manifest descriptor:", manifestDesc)

// 3. Verify the packed manifest
manifestData, err := content.FetchAll(ctx, store, manifestDesc)
if err != nil {
	panic(err)
}
fmt.Println("Manifest content:", string(manifestData))
Output:

Manifest descriptor: {application/vnd.oci.image.manifest.v1+json sha256:da221a11559704e4971c3dcf6564303707a333c8de8cb5475fc48b0072b36c19 308 [] map[org.opencontainers.image.created:2000-01-01T00:00:00Z] [] <nil> application/vnd.example+type}
Manifest content: {"schemaVersion":2,"mediaType":"application/vnd.oci.image.manifest.v1+json","config":{"mediaType":"application/vnd.example+type","digest":"sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a","size":2},"layers":[],"annotations":{"org.opencontainers.image.created":"2000-01-01T00:00:00Z"}}
Example (ImageV11)

ExampleImageV11 demonstrates packing an OCI Image Manifest as defined in image-spec v1.1.1.

// 0. Create a storage
store := memory.New()

// 1. Set optional parameters
opts := oras.PackManifestOptions{
	ManifestAnnotations: map[string]string{
		// this time stamp will be automatically generated if not specified
		// use a fixed value here to make the pack result reproducible
		ocispec.AnnotationCreated: "2000-01-01T00:00:00Z",
	},
}
ctx := context.Background()

// 2. Pack a manifest
artifactType := "application/vnd.example+type"
manifestDesc, err := oras.PackManifest(ctx, store, oras.PackManifestVersion1_1, artifactType, opts)
if err != nil {
	panic(err)
}
fmt.Println("Manifest descriptor:", manifestDesc)

// 3. Verify the packed manifest
manifestData, err := content.FetchAll(ctx, store, manifestDesc)
if err != nil {
	panic(err)
}
fmt.Println("Manifest content:", string(manifestData))
Output:

Manifest descriptor: {application/vnd.oci.image.manifest.v1+json sha256:c259a195a48d8029d75449579c81269ca6225cd5b57d36073a7de6458afdfdbd 528 [] map[org.opencontainers.image.created:2000-01-01T00:00:00Z] [] <nil> application/vnd.example+type}
Manifest content: {"schemaVersion":2,"mediaType":"application/vnd.oci.image.manifest.v1+json","artifactType":"application/vnd.example+type","config":{"mediaType":"application/vnd.oci.empty.v1+json","digest":"sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a","size":2,"data":"e30="},"layers":[{"mediaType":"application/vnd.oci.empty.v1+json","digest":"sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a","size":2,"data":"e30="}],"annotations":{"org.opencontainers.image.created":"2000-01-01T00:00:00Z"}}

func PushBytes

func PushBytes(ctx context.Context, pusher content.Pusher, mediaType string, contentBytes []byte) (ocispec.Descriptor, error)

PushBytes describes the contentBytes using the given mediaType and pushes it. If mediaType is not specified, "application/octet-stream" is used.

func Resolve

func Resolve(ctx context.Context, target ReadOnlyTarget, reference string, opts ResolveOptions) (ocispec.Descriptor, error)

Resolve resolves a descriptor with provided reference from the target.

func Tag

func Tag(ctx context.Context, target Target, src, dst string) (ocispec.Descriptor, error)

Tag tags the descriptor identified by src with dst.

func TagBytes

func TagBytes(ctx context.Context, target Target, mediaType string, contentBytes []byte, reference string) (ocispec.Descriptor, error)

TagBytes describes the contentBytes using the given mediaType, pushes it, and tag it with the given reference. If mediaType is not specified, "application/octet-stream" is used.

func TagBytesN

func TagBytesN(ctx context.Context, target Target, mediaType string, contentBytes []byte, references []string, opts TagBytesNOptions) (ocispec.Descriptor, error)

TagBytesN describes the contentBytes using the given mediaType, pushes it, and tag it with the given references. If mediaType is not specified, "application/octet-stream" is used.

func TagN

func TagN(ctx context.Context, target Target, srcReference string, dstReferences []string, opts TagNOptions) (ocispec.Descriptor, error)

TagN tags the descriptor identified by srcReference with dstReferences.

Types

type CopyError

type CopyError struct {
	// Op is the operation that caused the error.
	Op string
	// Origin indicates the source of the error.
	Origin CopyErrorOrigin
	// Err is the underlying error.
	Err error
}

CopyError represents an error encountered during a copy operation.

Example

ExampleCopyError demonstrates how to check CopyError returned from copy operations.

src := memory.New()
dst := memory.New()
ctx := context.Background()

// Try to copy a non-existent reference, which is expected to fail
nonExistentRef := "non-existent-reference"
_, err := oras.Copy(ctx, src, nonExistentRef, dst, "", oras.DefaultCopyOptions)
if err != nil {
	// Check if the error is a CopyError and print its details
	var copyErr *oras.CopyError
	if errors.As(err, &copyErr) {
		fmt.Println("copyErr.Origin:", copyErr.Origin)
		fmt.Println("copyErr.Op:", copyErr.Op)
		fmt.Println("copyErr.Err:", copyErr.Err)
		fmt.Println("copyErr.Error():", copyErr.Error())
		return
	}

	fmt.Println("err is not a CopyError:", err)
	return
}

fmt.Println("Copy succeeded unexpectedly")
Output:

copyErr.Origin: source
copyErr.Op: Resolve
copyErr.Err: non-existent-reference: not found
copyErr.Error(): failed to perform "Resolve" on source: non-existent-reference: not found

func (*CopyError) Error

func (e *CopyError) Error() string

Error implements the error interface for CopyError.

func (*CopyError) Unwrap

func (e *CopyError) Unwrap() error

Unwrap implements the errors.Unwrap interface for CopyError.

type CopyErrorOrigin

type CopyErrorOrigin int

CopyErrorOrigin defines the source of a copy error.

const (
	// CopyErrorOriginSource indicates the error occurred at the source side.
	CopyErrorOriginSource CopyErrorOrigin = 1

	// CopyErrorOriginDestination indicates the error occurred at the destination side.
	CopyErrorOriginDestination CopyErrorOrigin = 2
)

func (CopyErrorOrigin) String

func (o CopyErrorOrigin) String() string

String returns the string representation of the CopyErrorOrigin.

type CopyGraphOptions

type CopyGraphOptions struct {
	// Concurrency limits the maximum number of concurrent copy tasks.
	// If less than or equal to 0, a default (currently 3) is used.
	Concurrency int
	// MaxMetadataBytes limits the maximum size of the metadata that can be
	// cached in the memory.
	// If less than or equal to 0, a default (currently 4 MiB) is used.
	MaxMetadataBytes int64
	// PreCopy handles the current descriptor before it is copied. PreCopy can
	// return a SkipNode to signal that desc should be skipped when it already
	// exists in the target.
	PreCopy func(ctx context.Context, desc ocispec.Descriptor) error
	// PostCopy handles the current descriptor after it is copied.
	PostCopy func(ctx context.Context, desc ocispec.Descriptor) error
	// OnCopySkipped will be called when the sub-DAG rooted by the current node
	// is skipped.
	OnCopySkipped func(ctx context.Context, desc ocispec.Descriptor) error
	// MountFrom returns the candidate repositories that desc may be mounted from.
	// The OCI references will be tried in turn.  If mounting fails on all of them,
	// then it falls back to a copy.
	MountFrom func(ctx context.Context, desc ocispec.Descriptor) ([]string, error)
	// OnMounted will be invoked when desc is mounted.
	OnMounted func(ctx context.Context, desc ocispec.Descriptor) error
	// FindSuccessors finds the successors of the current node.
	// fetcher provides cached access to the source storage, and is suitable
	// for fetching non-leaf nodes like manifests. Since anything fetched from
	// fetcher will be cached in the memory, it is recommended to use original
	// source storage to fetch large blobs.
	// If FindSuccessors is nil, content.Successors will be used.
	FindSuccessors func(ctx context.Context, fetcher content.Fetcher, desc ocispec.Descriptor) ([]ocispec.Descriptor, error)
}

CopyGraphOptions contains parameters for oras.CopyGraph.

var DefaultCopyGraphOptions CopyGraphOptions

DefaultCopyGraphOptions provides the default CopyGraphOptions.

type CopyOptions

type CopyOptions struct {
	CopyGraphOptions
	// MapRoot maps the resolved root node to a desired root node for copy.
	// When MapRoot is provided, the descriptor resolved from the source
	// reference will be passed to MapRoot, and the mapped descriptor will be
	// used as the root node for copy.
	MapRoot func(ctx context.Context, src content.ReadOnlyStorage, root ocispec.Descriptor) (ocispec.Descriptor, error)
}

CopyOptions contains parameters for oras.Copy.

var DefaultCopyOptions CopyOptions = CopyOptions{
	CopyGraphOptions: DefaultCopyGraphOptions,
}

DefaultCopyOptions provides the default CopyOptions.

func (*CopyOptions) WithTargetPlatform

func (opts *CopyOptions) WithTargetPlatform(p *ocispec.Platform)

WithTargetPlatform configures opts.MapRoot to select the manifest whose platform matches the given platform. When MapRoot is provided, the platform selection will be applied on the mapped root node.

  • If the given platform is nil, no platform selection will be applied.
  • If the root node is a manifest, it will remain the same if platform matches, otherwise ErrNotFound will be returned.
  • If the root node is a manifest list, it will be mapped to the first matching manifest if exists, otherwise ErrNotFound will be returned.
  • Otherwise ErrUnsupported will be returned.

type ExtendedCopyGraphOptions

type ExtendedCopyGraphOptions struct {
	CopyGraphOptions
	// Depth limits the maximum depth of the directed acyclic graph (DAG) that
	// will be extended-copied.
	// If Depth is no specified, or the specified value is less than or
	// equal to 0, the depth limit will be considered as infinity.
	Depth int
	// FindPredecessors finds the predecessors of the current node.
	// If FindPredecessors is nil, src.Predecessors will be adapted and used.
	FindPredecessors func(ctx context.Context, src content.ReadOnlyGraphStorage, desc ocispec.Descriptor) ([]ocispec.Descriptor, error)
}

ExtendedCopyGraphOptions contains parameters for oras.ExtendedCopyGraph.

var DefaultExtendedCopyGraphOptions ExtendedCopyGraphOptions = ExtendedCopyGraphOptions{
	CopyGraphOptions: DefaultCopyGraphOptions,
}

DefaultExtendedCopyGraphOptions provides the default ExtendedCopyGraphOptions.

func (*ExtendedCopyGraphOptions) FilterAnnotation

func (opts *ExtendedCopyGraphOptions) FilterAnnotation(key string, regex *regexp.Regexp)

FilterAnnotation configures opts.FindPredecessors to filter the predecessors whose annotation matches a given regex pattern.

A predecessor is kept if key is in its annotations and the annotation value matches regex. If regex is nil, predecessors whose annotations contain key will be kept, no matter of the annotation value.

For performance consideration, when using both FilterArtifactType and FilterAnnotation, it's recommended to call FilterArtifactType first.

func (*ExtendedCopyGraphOptions) FilterArtifactType

func (opts *ExtendedCopyGraphOptions) FilterArtifactType(regex *regexp.Regexp)

FilterArtifactType configures opts.FindPredecessors to filter the predecessors whose artifact type matches a given regex pattern.

A predecessor is kept if its artifact type matches regex. If regex is nil, all predecessors will be kept.

For performance consideration, when using both FilterArtifactType and FilterAnnotation, it's recommended to call FilterArtifactType first.

type ExtendedCopyOptions

type ExtendedCopyOptions struct {
	ExtendedCopyGraphOptions
}

ExtendedCopyOptions contains parameters for oras.ExtendedCopy.

var DefaultExtendedCopyOptions ExtendedCopyOptions = ExtendedCopyOptions{
	ExtendedCopyGraphOptions: DefaultExtendedCopyGraphOptions,
}

DefaultExtendedCopyOptions provides the default ExtendedCopyOptions.

type FetchBytesOptions

type FetchBytesOptions struct {
	// FetchOptions contains parameters for fetching content.
	FetchOptions
	// MaxBytes limits the maximum size of the fetched content bytes.
	// If less than or equal to 0, a default (currently 4 MiB) is used.
	MaxBytes int64
}

FetchBytesOptions contains parameters for oras.FetchBytes.

var DefaultFetchBytesOptions FetchBytesOptions

DefaultFetchBytesOptions provides the default FetchBytesOptions.

type FetchOptions

type FetchOptions struct {
	// ResolveOptions contains parameters for resolving reference.
	ResolveOptions
}

FetchOptions contains parameters for oras.Fetch.

var DefaultFetchOptions FetchOptions

DefaultFetchOptions provides the default FetchOptions.

type GraphTarget

type GraphTarget interface {
	content.GraphStorage
	content.TagResolver
}

GraphTarget is a CAS with generic tags that supports direct predecessor node finding.

type PackManifestOptions

type PackManifestOptions struct {
	// Subject is the subject of the manifest.
	// This option is only valid when PackManifestVersion is
	// NOT PackManifestVersion1_0.
	Subject *ocispec.Descriptor

	// Layers is the layers of the manifest.
	Layers []ocispec.Descriptor

	// ManifestAnnotations is the annotation map of the manifest. In order to
	// make [PackManifest] reproducible, set the key ocispec.AnnotationCreated
	// (i.e. "org.opencontainers.image.created") to a fixed value. The value
	// must conform to RFC 3339.
	ManifestAnnotations map[string]string

	// ConfigDescriptor is a pointer to the descriptor of the config blob.
	// If not nil, ConfigAnnotations will be ignored.
	ConfigDescriptor *ocispec.Descriptor

	// ConfigAnnotations is the annotation map of the config descriptor.
	// This option is valid only when ConfigDescriptor is nil.
	ConfigAnnotations map[string]string
}

PackManifestOptions contains optional parameters for PackManifest.

type PackManifestVersion

type PackManifestVersion int

PackManifestVersion represents the manifest version used for PackManifest.

const (
	// PackManifestVersion1_0 represents the OCI Image Manifest defined in
	// image-spec v1.0.2.
	// Reference: https://github.com/opencontainers/image-spec/blob/v1.0.2/manifest.md
	PackManifestVersion1_0 PackManifestVersion = 1

	// PackManifestVersion1_1_RC4 represents the OCI Image Manifest defined
	// in image-spec v1.1.0-rc4.
	// Reference: https://github.com/opencontainers/image-spec/blob/v1.1.0-rc4/manifest.md
	//
	// Deprecated: This constant is deprecated and not recommended for future use.
	// Use [PackManifestVersion1_1] instead.
	PackManifestVersion1_1_RC4 PackManifestVersion = PackManifestVersion1_1

	// PackManifestVersion1_1 represents the OCI Image Manifest defined in
	// image-spec v1.1.1.
	// Reference: https://github.com/opencontainers/image-spec/blob/v1.1.1/manifest.md
	PackManifestVersion1_1 PackManifestVersion = 2
)

type PackOptions deprecated

type PackOptions struct {
	// Subject is the subject of the manifest.
	Subject *ocispec.Descriptor

	// ManifestAnnotations is the annotation map of the manifest.
	ManifestAnnotations map[string]string

	// PackImageManifest controls whether to pack an OCI Image Manifest or not.
	//   - If true, pack an OCI Image Manifest.
	//   - If false, pack an OCI Artifact Manifest (deprecated).
	//
	// Default value: false.
	PackImageManifest bool

	// ConfigDescriptor is a pointer to the descriptor of the config blob.
	// If not nil, artifactType will be implied by the mediaType of the
	// specified ConfigDescriptor, and ConfigAnnotations will be ignored.
	// This option is valid only when PackImageManifest is true.
	ConfigDescriptor *ocispec.Descriptor

	// ConfigAnnotations is the annotation map of the config descriptor.
	// This option is valid only when PackImageManifest is true
	// and ConfigDescriptor is nil.
	ConfigAnnotations map[string]string
}

PackOptions contains optional parameters for Pack.

Deprecated: This type is deprecated and not recommended for future use. Use PackManifestOptions instead.

type ReadOnlyGraphTarget

type ReadOnlyGraphTarget interface {
	content.ReadOnlyGraphStorage
	content.Resolver
}

ReadOnlyGraphTarget represents a read-only GraphTarget.

type ReadOnlyTarget

type ReadOnlyTarget interface {
	content.ReadOnlyStorage
	content.Resolver
}

ReadOnlyTarget represents a read-only Target.

type ResolveOptions

type ResolveOptions struct {
	// TargetPlatform ensures the resolved content matches the target platform
	// if the node is a manifest, or selects the first resolved content that
	// matches the target platform if the node is a manifest list.
	TargetPlatform *ocispec.Platform

	// MaxMetadataBytes limits the maximum size of metadata that can be cached
	// in the memory.
	// If less than or equal to 0, a default (currently 4 MiB) is used.
	MaxMetadataBytes int64
}

ResolveOptions contains parameters for oras.Resolve.

var DefaultResolveOptions ResolveOptions

DefaultResolveOptions provides the default ResolveOptions.

type TagBytesNOptions

type TagBytesNOptions struct {
	// Concurrency limits the maximum number of concurrent tag tasks.
	// If less than or equal to 0, a default (currently 5) is used.
	Concurrency int
}

TagBytesNOptions contains parameters for oras.TagBytesN.

var DefaultTagBytesNOptions TagBytesNOptions

DefaultTagBytesNOptions provides the default TagBytesNOptions.

type TagNOptions

type TagNOptions struct {
	// Concurrency limits the maximum number of concurrent tag tasks.
	// If less than or equal to 0, a default (currently 5) is used.
	Concurrency int

	// MaxMetadataBytes limits the maximum size of metadata that can be cached
	// in the memory.
	// If less than or equal to 0, a default (currently 4 MiB) is used.
	MaxMetadataBytes int64
}

TagNOptions contains parameters for oras.TagN.

var DefaultTagNOptions TagNOptions

DefaultTagNOptions provides the default TagNOptions.

type Target

type Target interface {
	content.Storage
	content.TagResolver
}

Target is a CAS with generic tags.

Directories

Path Synopsis
Package content provides implementations to access content stores.
Package content provides implementations to access content stores.
file
Package file provides implementation of a content store based on file system.
Package file provides implementation of a content store based on file system.
memory
Package memory provides implementation of a memory backed content store.
Package memory provides implementation of a memory backed content store.
oci
Package oci provides access to an OCI content store.
Package oci provides access to an OCI content store.
internal
cas
Package registry provides high-level operations to manage registries.
Package registry provides high-level operations to manage registries.
internal/doc
Package doc provides the constant can be used in example test files.
Package doc provides the constant can be used in example test files.
remote
Package remote provides a client to the remote registry.
Package remote provides a client to the remote registry.
remote/auth
Package auth provides authentication for a client to a remote registry.
Package auth provides authentication for a client to a remote registry.
remote/credentials
Package credentials supports reading, saving, and removing credentials from Docker configuration files and external credential stores that follow the Docker credential helper protocol.
Package credentials supports reading, saving, and removing credentials from Docker configuration files and external credential stores that follow the Docker credential helper protocol.
remote/credentials/internal/executer
Package executer is an abstraction for the docker credential helper protocol binaries.
Package executer is an abstraction for the docker credential helper protocol binaries.

Jump to

Keyboard shortcuts

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