From e10b179b42f1b5245757bb7f02e2c1b0b3dba4b1 Mon Sep 17 00:00:00 2001 From: Xiaoxuan Wang Date: Thu, 3 Aug 2023 07:10:34 +0000 Subject: [PATCH] resolved the comments Signed-off-by: Xiaoxuan Wang --- example_copy_test.go | 356 ++++++++++++++++++++++++++++++++++++++++ example_test.go | 364 +++++++++-------------------------------- larger_example_test.go | 162 ------------------ 3 files changed, 437 insertions(+), 445 deletions(-) create mode 100644 example_copy_test.go delete mode 100644 larger_example_test.go diff --git a/example_copy_test.go b/example_copy_test.go new file mode 100644 index 00000000..91fb9da0 --- /dev/null +++ b/example_copy_test.go @@ -0,0 +1,356 @@ +/* +Copyright The ORAS Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package oras_test + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "net/url" + "os" + "strconv" + "strings" + "testing" + + "github.com/opencontainers/go-digest" + specs "github.com/opencontainers/image-spec/specs-go" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "oras.land/oras-go/v2" + "oras.land/oras-go/v2/content/memory" + "oras.land/oras-go/v2/content/oci" + "oras.land/oras-go/v2/internal/spec" + "oras.land/oras-go/v2/registry/remote" +) + +var exampleMemoryStore oras.Target +var remoteHost string +var ( + exampleManifest, _ = json.Marshal(spec.Artifact{ + MediaType: spec.MediaTypeArtifactManifest, + ArtifactType: "example/content"}) + exampleManifestDescriptor = ocispec.Descriptor{ + MediaType: spec.MediaTypeArtifactManifest, + Digest: digest.Digest(digest.FromBytes(exampleManifest)), + Size: int64(len(exampleManifest))} + exampleSignatureManifest, _ = json.Marshal(spec.Artifact{ + MediaType: spec.MediaTypeArtifactManifest, + ArtifactType: "example/signature", + Subject: &exampleManifestDescriptor}) + exampleSignatureManifestDescriptor = ocispec.Descriptor{ + MediaType: spec.MediaTypeArtifactManifest, + Digest: digest.FromBytes(exampleSignatureManifest), + Size: int64(len(exampleSignatureManifest))} +) + +func pushBlob(ctx context.Context, mediaType string, blob []byte, target oras.Target) (desc ocispec.Descriptor, err error) { + desc = ocispec.Descriptor{ // Generate descriptor based on the media type and blob content + MediaType: mediaType, + Digest: digest.FromBytes(blob), // Calculate digest + Size: int64(len(blob)), // Include blob size + } + return desc, target.Push(ctx, desc, bytes.NewReader(blob)) // Push the blob to the registry target +} + +func generateManifestContent(config ocispec.Descriptor, layers ...ocispec.Descriptor) ([]byte, error) { + content := ocispec.Manifest{ + Config: config, // Set config blob + Layers: layers, // Set layer blobs + Versioned: specs.Versioned{SchemaVersion: 2}, + } + return json.Marshal(content) // Get json content +} + +func TestMain(m *testing.M) { + const exampleTag = "latest" + const exampleUploadUUid = "0bc84d80-837c-41d9-824e-1907463c53b3" + + // Setup example local target + exampleMemoryStore = memory.New() + layerBlob := []byte("Hello layer") + ctx := context.Background() + layerDesc, err := pushBlob(ctx, ocispec.MediaTypeImageLayer, layerBlob, exampleMemoryStore) // push layer blob + if err != nil { + panic(err) + } + configBlob := []byte("Hello config") + configDesc, err := pushBlob(ctx, ocispec.MediaTypeImageConfig, configBlob, exampleMemoryStore) // push config blob + if err != nil { + panic(err) + } + manifestBlob, err := generateManifestContent(configDesc, layerDesc) // generate a image manifest + if err != nil { + panic(err) + } + manifestDesc, err := pushBlob(ctx, ocispec.MediaTypeImageManifest, manifestBlob, exampleMemoryStore) // push manifest blob + if err != nil { + panic(err) + } + err = exampleMemoryStore.Tag(ctx, manifestDesc, exampleTag) + if err != nil { + panic(err) + } + + // Setup example remote target + httpsServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + p := r.URL.Path + m := r.Method + switch { + case strings.Contains(p, "/blobs/uploads/") && m == "POST": + w.Header().Set("Content-Type", ocispec.MediaTypeImageManifest) + w.Header().Set("Location", p+exampleUploadUUid) + w.WriteHeader(http.StatusAccepted) + case strings.Contains(p, "/blobs/uploads/"+exampleUploadUUid) && m == "GET": + w.WriteHeader(http.StatusCreated) + case strings.Contains(p, "/manifests/"+string(exampleSignatureManifestDescriptor.Digest)): + w.Header().Set("Content-Type", spec.MediaTypeArtifactManifest) + w.Header().Set("Docker-Content-Digest", string(exampleSignatureManifestDescriptor.Digest)) + w.Header().Set("Content-Length", strconv.Itoa(len(exampleSignatureManifest))) + w.Write(exampleSignatureManifest) + case strings.Contains(p, "/manifests/latest") && m == "PUT": + w.WriteHeader(http.StatusCreated) + case strings.Contains(p, "/manifests/"+string(exampleManifestDescriptor.Digest)), + strings.Contains(p, "/manifests/latest") && m == "HEAD": + w.Header().Set("Content-Type", spec.MediaTypeArtifactManifest) + w.Header().Set("Docker-Content-Digest", string(exampleManifestDescriptor.Digest)) + w.Header().Set("Content-Length", strconv.Itoa(len(exampleManifest))) + if m == "GET" { + w.Write(exampleManifest) + } + case strings.Contains(p, "/v2/source/referrers/"): + var referrers []ocispec.Descriptor + if p == "/v2/source/referrers/"+exampleManifestDescriptor.Digest.String() { + referrers = []ocispec.Descriptor{exampleSignatureManifestDescriptor} + } + result := ocispec.Index{ + Versioned: specs.Versioned{ + SchemaVersion: 2, // historical value. does not pertain to OCI or docker version + }, + MediaType: ocispec.MediaTypeImageIndex, + Manifests: referrers, + } + if err := json.NewEncoder(w).Encode(result); err != nil { + panic(err) + } + case strings.Contains(p, "/manifests/") && (m == "HEAD" || m == "GET"): + w.Header().Set("Content-Type", ocispec.MediaTypeImageManifest) + w.Header().Set("Docker-Content-Digest", string(manifestDesc.Digest)) + w.Header().Set("Content-Length", strconv.Itoa(len([]byte(manifestBlob)))) + w.Write([]byte(manifestBlob)) + case strings.Contains(p, "/blobs/") && (m == "GET" || m == "HEAD"): + arr := strings.Split(p, "/") + digest := arr[len(arr)-1] + var desc ocispec.Descriptor + var content []byte + switch digest { + case layerDesc.Digest.String(): + desc = layerDesc + content = layerBlob + case configDesc.Digest.String(): + desc = configDesc + content = configBlob + case manifestDesc.Digest.String(): + desc = manifestDesc + content = manifestBlob + } + w.Header().Set("Content-Type", desc.MediaType) + w.Header().Set("Docker-Content-Digest", digest) + w.Header().Set("Content-Length", strconv.Itoa(len([]byte(content)))) + w.Write([]byte(content)) + case strings.Contains(p, "/manifests/") && m == "PUT": + w.WriteHeader(http.StatusCreated) + } + + })) + defer httpsServer.Close() + u, err := url.Parse(httpsServer.URL) + if err != nil { + panic(err) + } + remoteHost = u.Host + http.DefaultTransport = httpsServer.Client().Transport + + os.Exit(m.Run()) +} + +func ExampleCopy_remoteToRemote() { + 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, "target") + 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 +} + +func ExampleCopy_remoteToLocal() { + 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 +} + +func ExampleCopy_localToLocal() { + 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 +} + +func ExampleCopy_localToOciFile() { + 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 +} + +func ExampleCopy_localToRemote() { + src := exampleMemoryStore + reg, err := remote.NewRegistry(remoteHost) + if err != nil { + panic(err) // Handle error + } + ctx := context.Background() + dst, err := reg.Repository(ctx, "target") + 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_copyArtifactManifestRemoteToLocal gives an example of copying +// an artifact manifest from a remote repository to local. +func Example_copyArtifactManifestRemoteToLocal() { + src, err := remote.NewRepository(fmt.Sprintf("%s/source", remoteHost)) + if err != nil { + panic(err) + } + dst := memory.New() + ctx := context.Background() + + exampleDigest := "sha256:70c29a81e235dda5c2cebb8ec06eafd3cca346cbd91f15ac74cefd98681c5b3d" + descriptor, err := src.Resolve(ctx, exampleDigest) + if err != nil { + panic(err) + } + err = oras.CopyGraph(ctx, src, dst, descriptor, oras.DefaultCopyGraphOptions) + if err != nil { + panic(err) + } + + // 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_extendedCopyArtifactAndReferrersRemoteToLocal gives an example of +// copying an artifact along with its referrers from a remote repository to local. +func Example_extendedCopyArtifactAndReferrersRemoteToLocal() { + src, err := remote.NewRepository(fmt.Sprintf("%s/source", remoteHost)) + if err != nil { + panic(err) + } + dst := memory.New() + ctx := context.Background() + + 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 +} diff --git a/example_test.go b/example_test.go index 91fb9da0..427451f0 100644 --- a/example_test.go +++ b/example_test.go @@ -16,341 +16,139 @@ limitations under the License. package oras_test import ( - "bytes" "context" - "encoding/json" "fmt" - "net/http" - "net/http/httptest" - "net/url" - "os" - "strconv" - "strings" - "testing" - "github.com/opencontainers/go-digest" - specs "github.com/opencontainers/image-spec/specs-go" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" + v1 "github.com/opencontainers/image-spec/specs-go/v1" "oras.land/oras-go/v2" - "oras.land/oras-go/v2/content/memory" + "oras.land/oras-go/v2/content/file" "oras.land/oras-go/v2/content/oci" - "oras.land/oras-go/v2/internal/spec" "oras.land/oras-go/v2/registry/remote" + "oras.land/oras-go/v2/registry/remote/auth" + "oras.land/oras-go/v2/registry/remote/retry" ) -var exampleMemoryStore oras.Target -var remoteHost string -var ( - exampleManifest, _ = json.Marshal(spec.Artifact{ - MediaType: spec.MediaTypeArtifactManifest, - ArtifactType: "example/content"}) - exampleManifestDescriptor = ocispec.Descriptor{ - MediaType: spec.MediaTypeArtifactManifest, - Digest: digest.Digest(digest.FromBytes(exampleManifest)), - Size: int64(len(exampleManifest))} - exampleSignatureManifest, _ = json.Marshal(spec.Artifact{ - MediaType: spec.MediaTypeArtifactManifest, - ArtifactType: "example/signature", - Subject: &exampleManifestDescriptor}) - exampleSignatureManifestDescriptor = ocispec.Descriptor{ - MediaType: spec.MediaTypeArtifactManifest, - Digest: digest.FromBytes(exampleSignatureManifest), - Size: int64(len(exampleSignatureManifest))} -) - -func pushBlob(ctx context.Context, mediaType string, blob []byte, target oras.Target) (desc ocispec.Descriptor, err error) { - desc = ocispec.Descriptor{ // Generate descriptor based on the media type and blob content - MediaType: mediaType, - Digest: digest.FromBytes(blob), // Calculate digest - Size: int64(len(blob)), // Include blob size - } - return desc, target.Push(ctx, desc, bytes.NewReader(blob)) // Push the blob to the registry target -} - -func generateManifestContent(config ocispec.Descriptor, layers ...ocispec.Descriptor) ([]byte, error) { - content := ocispec.Manifest{ - Config: config, // Set config blob - Layers: layers, // Set layer blobs - Versioned: specs.Versioned{SchemaVersion: 2}, - } - return json.Marshal(content) // Get json content -} - -func TestMain(m *testing.M) { - const exampleTag = "latest" - const exampleUploadUUid = "0bc84d80-837c-41d9-824e-1907463c53b3" - - // Setup example local target - exampleMemoryStore = memory.New() - layerBlob := []byte("Hello layer") - ctx := context.Background() - layerDesc, err := pushBlob(ctx, ocispec.MediaTypeImageLayer, layerBlob, exampleMemoryStore) // push layer blob - if err != nil { - panic(err) - } - configBlob := []byte("Hello config") - configDesc, err := pushBlob(ctx, ocispec.MediaTypeImageConfig, configBlob, exampleMemoryStore) // push config blob - if err != nil { - panic(err) - } - manifestBlob, err := generateManifestContent(configDesc, layerDesc) // generate a image manifest - if err != nil { - panic(err) - } - manifestDesc, err := pushBlob(ctx, ocispec.MediaTypeImageManifest, manifestBlob, exampleMemoryStore) // push manifest blob +func Example_pullFilesFromRemoteRepository() { + // 0. Create a file store + fs, err := file.New("/tmp/") if err != nil { panic(err) } - err = exampleMemoryStore.Tag(ctx, manifestDesc, exampleTag) - if err != nil { - panic(err) - } - - // Setup example remote target - httpsServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - p := r.URL.Path - m := r.Method - switch { - case strings.Contains(p, "/blobs/uploads/") && m == "POST": - w.Header().Set("Content-Type", ocispec.MediaTypeImageManifest) - w.Header().Set("Location", p+exampleUploadUUid) - w.WriteHeader(http.StatusAccepted) - case strings.Contains(p, "/blobs/uploads/"+exampleUploadUUid) && m == "GET": - w.WriteHeader(http.StatusCreated) - case strings.Contains(p, "/manifests/"+string(exampleSignatureManifestDescriptor.Digest)): - w.Header().Set("Content-Type", spec.MediaTypeArtifactManifest) - w.Header().Set("Docker-Content-Digest", string(exampleSignatureManifestDescriptor.Digest)) - w.Header().Set("Content-Length", strconv.Itoa(len(exampleSignatureManifest))) - w.Write(exampleSignatureManifest) - case strings.Contains(p, "/manifests/latest") && m == "PUT": - w.WriteHeader(http.StatusCreated) - case strings.Contains(p, "/manifests/"+string(exampleManifestDescriptor.Digest)), - strings.Contains(p, "/manifests/latest") && m == "HEAD": - w.Header().Set("Content-Type", spec.MediaTypeArtifactManifest) - w.Header().Set("Docker-Content-Digest", string(exampleManifestDescriptor.Digest)) - w.Header().Set("Content-Length", strconv.Itoa(len(exampleManifest))) - if m == "GET" { - w.Write(exampleManifest) - } - case strings.Contains(p, "/v2/source/referrers/"): - var referrers []ocispec.Descriptor - if p == "/v2/source/referrers/"+exampleManifestDescriptor.Digest.String() { - referrers = []ocispec.Descriptor{exampleSignatureManifestDescriptor} - } - result := ocispec.Index{ - Versioned: specs.Versioned{ - SchemaVersion: 2, // historical value. does not pertain to OCI or docker version - }, - MediaType: ocispec.MediaTypeImageIndex, - Manifests: referrers, - } - if err := json.NewEncoder(w).Encode(result); err != nil { - panic(err) - } - case strings.Contains(p, "/manifests/") && (m == "HEAD" || m == "GET"): - w.Header().Set("Content-Type", ocispec.MediaTypeImageManifest) - w.Header().Set("Docker-Content-Digest", string(manifestDesc.Digest)) - w.Header().Set("Content-Length", strconv.Itoa(len([]byte(manifestBlob)))) - w.Write([]byte(manifestBlob)) - case strings.Contains(p, "/blobs/") && (m == "GET" || m == "HEAD"): - arr := strings.Split(p, "/") - digest := arr[len(arr)-1] - var desc ocispec.Descriptor - var content []byte - switch digest { - case layerDesc.Digest.String(): - desc = layerDesc - content = layerBlob - case configDesc.Digest.String(): - desc = configDesc - content = configBlob - case manifestDesc.Digest.String(): - desc = manifestDesc - content = manifestBlob - } - w.Header().Set("Content-Type", desc.MediaType) - w.Header().Set("Docker-Content-Digest", digest) - w.Header().Set("Content-Length", strconv.Itoa(len([]byte(content)))) - w.Write([]byte(content)) - case strings.Contains(p, "/manifests/") && m == "PUT": - w.WriteHeader(http.StatusCreated) - } + defer fs.Close() - })) - defer httpsServer.Close() - u, err := url.Parse(httpsServer.URL) - if err != nil { - panic(err) - } - remoteHost = u.Host - http.DefaultTransport = httpsServer.Client().Transport - - os.Exit(m.Run()) -} - -func ExampleCopy_remoteToRemote() { - reg, err := remote.NewRegistry(remoteHost) - if err != nil { - panic(err) // Handle error - } + // 1. Connect to a remote repository ctx := context.Background() - src, err := reg.Repository(ctx, "source") + reg := "myregistry.example.com" + repo, err := remote.NewRepository(reg + "/myrepo") if err != nil { - panic(err) // Handle error + panic(err) } - dst, err := reg.Repository(ctx, "target") - if err != nil { - panic(err) // Handle error + // Note: The below code can be omitted if authentication is not required + repo.Client = &auth.Client{ + Client: retry.DefaultClient, + Cache: auth.DefaultCache, + Credential: auth.StaticCredential(reg, auth.Credential{ + Username: "username", + Password: "password", + }), } - tagName := "latest" - desc, err := oras.Copy(ctx, src, tagName, dst, tagName, oras.DefaultCopyOptions) + // 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) // Handle error + panic(err) } - fmt.Println(desc.Digest) - - // Output: - // sha256:7cbb44b44e8ede5a89cf193db3f5f2fd019d89697e6b87e8ed2589e60649b0d1 + fmt.Println("manifest descriptor:", manifestDescriptor) } -func ExampleCopy_remoteToLocal() { - 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) +func Example_pullImageFromRemoteRepository() { + // 0. Create an OCI layout store + store, err := oci.New("/tmp/oci-layout-root") if err != nil { - panic(err) // Handle error + panic(err) } - fmt.Println(desc.Digest) - - // Output: - // sha256:7cbb44b44e8ede5a89cf193db3f5f2fd019d89697e6b87e8ed2589e60649b0d1 -} -func ExampleCopy_localToLocal() { - src := exampleMemoryStore - dst := memory.New() - - tagName := "latest" + // 1. Connect to a remote repository ctx := context.Background() - desc, err := oras.Copy(ctx, src, tagName, dst, tagName, oras.DefaultCopyOptions) + reg := "myregistry.example.com" + repo, err := remote.NewRepository(reg + "/myrepo") if err != nil { - panic(err) // Handle error - } - fmt.Println(desc.Digest) - - // Output: - // sha256:7cbb44b44e8ede5a89cf193db3f5f2fd019d89697e6b87e8ed2589e60649b0d1 -} - -func ExampleCopy_localToOciFile() { - src := exampleMemoryStore - tempDir, err := os.MkdirTemp("", "oras_oci_example_*") - if err != nil { - panic(err) // Handle error + panic(err) } - defer os.RemoveAll(tempDir) - dst, err := oci.New(tempDir) - if err != nil { - panic(err) // Handle error + // Note: The below code can be omitted if authentication is not required + repo.Client = &auth.Client{ + Client: retry.DefaultClient, + Cache: auth.DefaultCache, + Credential: auth.StaticCredential(reg, auth.Credential{ + Username: "username", + Password: "password", + }), } - tagName := "latest" - ctx := context.Background() - desc, err := oras.Copy(ctx, src, tagName, dst, tagName, oras.DefaultCopyOptions) + // 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) // Handle error + panic(err) } - fmt.Println(desc.Digest) - - // Output: - // sha256:7cbb44b44e8ede5a89cf193db3f5f2fd019d89697e6b87e8ed2589e60649b0d1 + fmt.Println("manifest descriptor:", manifestDescriptor) } -func ExampleCopy_localToRemote() { - src := exampleMemoryStore - reg, err := remote.NewRegistry(remoteHost) +func Example_pushFilesToRemoteRepository() { + // 0. Create a file store + fs, err := file.New("/tmp/") if err != nil { - panic(err) // Handle error + panic(err) } + defer fs.Close() ctx := context.Background() - dst, err := reg.Repository(ctx, "target") - 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 + // 1. Add files to a file store + mediaType := "example/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) } - fmt.Println(desc.Digest) - // Output: - // sha256:7cbb44b44e8ede5a89cf193db3f5f2fd019d89697e6b87e8ed2589e60649b0d1 -} - -// Example_copyArtifactManifestRemoteToLocal gives an example of copying -// an artifact manifest from a remote repository to local. -func Example_copyArtifactManifestRemoteToLocal() { - src, err := remote.NewRepository(fmt.Sprintf("%s/source", remoteHost)) + // 2. Pack the files and tag the packed manifest + artifactType := "example/files" + manifestDescriptor, err := oras.Pack(ctx, fs, artifactType, fileDescriptors, oras.DefaultPackOptions) if err != nil { panic(err) } - dst := memory.New() - ctx := context.Background() + fmt.Println("manifest descriptor:", manifestDescriptor) - exampleDigest := "sha256:70c29a81e235dda5c2cebb8ec06eafd3cca346cbd91f15ac74cefd98681c5b3d" - descriptor, err := src.Resolve(ctx, exampleDigest) - if err != nil { - panic(err) - } - err = oras.CopyGraph(ctx, src, dst, descriptor, oras.DefaultCopyGraphOptions) - if err != nil { + tag := "latest" + if err = fs.Tag(ctx, manifestDescriptor, tag); err != nil { panic(err) } - // verify that the artifact manifest described by the descriptor exists in dst - contentExists, err := dst.Exists(ctx, descriptor) + // 3. Connect to a remote repository + reg := "myregistry.example.com" + repo, err := remote.NewRepository(reg + "/myrepo") if err != nil { panic(err) } - fmt.Println(contentExists) - - // Output: - // true -} - -// Example_extendedCopyArtifactAndReferrersRemoteToLocal gives an example of -// copying an artifact along with its referrers from a remote repository to local. -func Example_extendedCopyArtifactAndReferrersRemoteToLocal() { - src, err := remote.NewRepository(fmt.Sprintf("%s/source", remoteHost)) - 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.DefaultCache, + Credential: auth.StaticCredential(reg, auth.Credential{ + Username: "username", + Password: "password", + }), } - dst := memory.New() - ctx := context.Background() - 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) + // 3. Copy from the file store to the remote repository + _, err = oras.Copy(ctx, fs, tag, repo, tag, oras.DefaultCopyOptions) if err != nil { panic(err) } - - fmt.Println(desc.Digest) - // Output: - // sha256:f396bc4d300934a39ca28ab0d5ac8a3573336d7d63c654d783a68cd1e2057662 } diff --git a/larger_example_test.go b/larger_example_test.go deleted file mode 100644 index d855a6c6..00000000 --- a/larger_example_test.go +++ /dev/null @@ -1,162 +0,0 @@ -/* -Copyright The ORAS Authors. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package oras_test - -import ( - "context" - "fmt" - - v1 "github.com/opencontainers/image-spec/specs-go/v1" - "oras.land/oras-go/v2" - "oras.land/oras-go/v2/content" - "oras.land/oras-go/v2/content/file" - "oras.land/oras-go/v2/content/oci" - "oras.land/oras-go/v2/registry/remote" - "oras.land/oras-go/v2/registry/remote/auth" - "oras.land/oras-go/v2/registry/remote/retry" -) - -func Example_pullFilesFromRemoteRepository() { - // 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.DefaultCache, - 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) -} - -func Example_pullImageFromRemoteRepository() { - // 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.DefaultCache, - 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 pulled:", manifestDescriptor.Digest, manifestDescriptor.MediaType) - - // 3. Fetch from OCI layout store to verify - fetched, err := content.FetchAll(ctx, store, manifestDescriptor) - if err != nil { - panic(err) - } - fmt.Printf("manifest content:\n%s", fetched) -} - -func Example_pushFilesToRemoteRepository() { - // 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 a file store - mediaType := "example/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 := "example/files" - manifestDescriptor, err := oras.Pack(ctx, fs, artifactType, fileDescriptors, oras.DefaultPackOptions) - 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.DefaultCache, - Credential: auth.StaticCredential(reg, auth.Credential{ - Username: "username", - Password: "password", - }), - } - - // 3. Copy from the file store to the remote repository - _, err = oras.Copy(ctx, fs, tag, repo, tag, oras.DefaultCopyOptions) - if err != nil { - panic(err) - } -}