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

crane pull: support pulling index to OCI Layout #1215

Merged
merged 3 commits into from
Jan 5, 2022
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
18 changes: 18 additions & 0 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,21 @@ jobs:
./app/crane pull --format=oci $img $layout
./app/crane push --image-refs=foo.images $layout $dst
diff <(./app/crane manifest $img) <(./app/crane manifest $(cat foo.images))

# Make sure we can roundtrip an index (distroless).
distroless=$(mktemp -d)
remote="gcr.io/distroless/static"
local="localhost:1338/distroless:static"

./app/crane pull --format=oci $remote $distroless
./app/crane push $distroless $local
diff <(./app/crane manifest $remote) <(./app/crane manifest $local)

# And that it works for a single platform (pulling from what we just pushed).
distroless=$(mktemp -d)
remote="$local"
local="localhost:1338/distroless/platform:static"

./app/crane pull --platform=linux/arm64 --format=oci $remote $distroless
./app/crane push $distroless $local
diff <(./app/crane manifest --platform linux/arm64 $remote) <(./app/crane manifest $local)
45 changes: 42 additions & 3 deletions cmd/crane/cmd/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ import (
"fmt"

"github.com/google/go-containerregistry/pkg/crane"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/cache"
"github.com/google/go-containerregistry/pkg/v1/layout"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/spf13/cobra"
)

Expand All @@ -33,16 +36,38 @@ func NewCmdPull(options *[]crane.Option) *cobra.Command {
Args: cobra.MinimumNArgs(2),
RunE: func(_ *cobra.Command, args []string) error {
imageMap := map[string]v1.Image{}
indexMap := map[string]v1.ImageIndex{}
srcList, path := args[:len(args)-1], args[len(args)-1]
for _, src := range srcList {
img, err := crane.Pull(src, *options...)
o := crane.GetOptions(*options...)
ref, err := name.ParseReference(src, o.Name...)
mattmoor marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return fmt.Errorf("pulling %s: %w", src, err)
return fmt.Errorf("parsing reference %q: %w", src, err)
}

rmt, err := remote.Get(ref, o.Remote...)
if err != nil {
return err
}

// If we're writing an index to a layout and --platform hasn't been set,
// pull the entire index, not just a child image.
if format == "oci" && rmt.MediaType.IsIndex() && o.Platform == nil {
idx, err := rmt.ImageIndex()
mattmoor marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return err
}
indexMap[src] = idx
continue
}

img, err := rmt.Image()
if err != nil {
return err
}
if cachePath != "" {
img = cache.Image(img, cache.NewFilesystemCache(cachePath))
}

imageMap[src] = img
}

Expand All @@ -59,6 +84,20 @@ func NewCmdPull(options *[]crane.Option) *cobra.Command {
if err := crane.MultiSaveOCI(imageMap, path); err != nil {
return fmt.Errorf("saving oci image layout %s: %w", path, err)
}

// crane.MultiSaveOCI doesn't support index, so just append these at the end.
p, err := layout.FromPath(path)
if err != nil {
return err
}
for ref, idx := range indexMap {
anns := map[string]string{
"dev.ggcr.image.name": ref,
}
if err := p.AppendIndex(idx, layout.WithAnnotations(anns)); err != nil {
return err
}
}
default:
return fmt.Errorf("unexpected --format: %q (valid values are: tarball, legacy, and oci)", format)
}
Expand Down
7 changes: 5 additions & 2 deletions pkg/crane/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,11 @@ func MultiSaveOCI(imgMap map[string]v1.Image, path string) error {
return err
}
}
for _, img := range imgMap {
if err = p.AppendImage(img); err != nil {
for ref, img := range imgMap {
anns := map[string]string{
"dev.ggcr.image.name": ref,
}
if err = p.AppendImage(img, layout.WithAnnotations(anns)); err != nil {
return err
}
}
Expand Down