Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: --output for oras manifest index create #1490

Merged
merged 5 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions cmd/oras/root/manifest/index/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"encoding/json"
"fmt"
"os"
"strings"

"github.com/opencontainers/image-spec/specs-go"
Expand All @@ -44,9 +45,11 @@ var maxConfigSize int64 = 4 * 1024 * 1024 // 4 MiB
type createOptions struct {
option.Common
option.Target
option.Pretty

sources []string
extraRefs []string
sources []string
extraRefs []string
outputPath string
}

func createCmd() *cobra.Command {
Expand All @@ -70,6 +73,12 @@ Example - create an index and push it with multiple tags:

Example - create an index and push to an OCI image layout folder 'layout-dir' and tag with 'v1':
oras manifest index create layout-dir:v1 linux-amd64 sha256:99e4703fbf30916f549cd6bfa9cdbab614b5392fbe64fdee971359a77073cdf9

Example - create an index and save it locally to index.json, auto push will be disabled:
oras manifest index create --output index.json localhost:5000/hello linux-amd64 linux-arm64

Example - create an index and output the index to stdout, auto push will be disabled:
oras manifest index create localhost:5000/hello linux-arm64 --output - --pretty
`,
Args: oerrors.CheckArgs(argument.AtLeast(1), "the destination index to create."),
PreRunE: func(cmd *cobra.Command, args []string) error {
Expand All @@ -84,6 +93,7 @@ Example - create an index and push to an OCI image layout folder 'layout-dir' an
return createIndex(cmd, opts)
},
}
cmd.Flags().StringVarP(&opts.outputPath, "output", "o", "", "file `path` to write the created index to, use - for stdout")
option.ApplyFlags(&opts, cmd.Flags())
return oerrors.Command(cmd, &opts.Target)
}
Expand All @@ -108,7 +118,18 @@ func createIndex(cmd *cobra.Command, opts createOptions) error {
indexBytes, _ := json.Marshal(index)
desc := content.NewDescriptorFromBytes(ocispec.MediaTypeImageIndex, indexBytes)
opts.Println(status.IndexPromptPacked, descriptor.ShortDigest(desc), ocispec.MediaTypeImageIndex)
return pushIndex(ctx, target, desc, indexBytes, opts.Reference, opts.extraRefs, opts.AnnotatedReference(), opts.Printer)

switch opts.outputPath {
case "":
err = pushIndex(ctx, target, desc, indexBytes, opts.Reference, opts.extraRefs, opts.AnnotatedReference(), opts.Printer)
case "-":
opts.Println("Digest:", desc.Digest)
err = opts.Output(os.Stdout, indexBytes)
default:
opts.Println("Digest:", desc.Digest)
err = os.WriteFile(opts.outputPath, indexBytes, 0666)
}
return err
}

func fetchSourceManifests(ctx context.Context, target oras.ReadOnlyTarget, opts createOptions) ([]ocispec.Descriptor, error) {
Expand Down
5 changes: 5 additions & 0 deletions test/e2e/internal/testdata/multi_arch/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,8 @@ var (
},
}
)

// exported index
var (
CreatedIndex = `{"schemaVersion":2,"mediaType":"application/vnd.oci.image.index.v1+json","manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:9d84a5716c66a1d1b9c13f8ed157ba7d1edfe7f9b8766728b8a1f25c0d9c14c1","size":458,"platform":{"architecture":"amd64","os":"linux"}}]}`
)
31 changes: 31 additions & 0 deletions test/e2e/suite/command/manifest_index.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package command
import (
"encoding/json"
"fmt"
"path/filepath"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
Expand Down Expand Up @@ -130,6 +131,21 @@ var _ = Describe("1.1 registry users:", func() {
ValidateIndex(content, expectedManifests)
})

It("should output created index to file", func() {
testRepo := indexTestRepo("create", "output-to-file")
CopyZOTRepo(ImageRepo, testRepo)
filePath := filepath.Join(GinkgoT().TempDir(), "createdIndex")
ORAS("manifest", "index", "create", RegistryRef(ZOTHost, testRepo, ""), string(multi_arch.LinuxAMD64.Digest), "--output", filePath).Exec()
MatchFile(filePath, multi_arch.CreatedIndex, DefaultTimeout)
})

It("should output created index to stdout", func() {
testRepo := indexTestRepo("create", "output-to-stdout")
CopyZOTRepo(ImageRepo, testRepo)
ORAS("manifest", "index", "create", RegistryRef(ZOTHost, testRepo, ""), string(multi_arch.LinuxAMD64.Digest),
"--output", "-").MatchKeyWords(multi_arch.CreatedIndex).Exec()
})

It("should fail if given a reference that does not exist in the repo", func() {
testRepo := indexTestRepo("create", "nonexist-ref")
CopyZOTRepo(ImageRepo, testRepo)
Expand Down Expand Up @@ -211,6 +227,21 @@ var _ = Describe("OCI image layout users:", func() {
ValidateIndex(content, expectedManifests)
})

It("should output created index to file", func() {
root := PrepareTempOCI(ImageRepo)
indexRef := LayoutRef(root, "output-to-file")
filePath := filepath.Join(GinkgoT().TempDir(), "createdIndex")
ORAS("manifest", "index", "create", Flags.Layout, indexRef, string(multi_arch.LinuxAMD64.Digest), "--output", filePath).Exec()
MatchFile(filePath, multi_arch.CreatedIndex, DefaultTimeout)
})

It("should output created index to stdout", func() {
root := PrepareTempOCI(ImageRepo)
indexRef := LayoutRef(root, "output-to-stdout")
ORAS("manifest", "index", "create", Flags.Layout, indexRef, string(multi_arch.LinuxAMD64.Digest),
"--output", "-").MatchKeyWords(multi_arch.CreatedIndex).Exec()
})

It("should fail if given a reference that does not exist in the repo", func() {
root := PrepareTempOCI(ImageRepo)
indexRef := LayoutRef(root, "latest")
Expand Down
Loading