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: implement local puller and pusher #1871

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from 8 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
1 change: 0 additions & 1 deletion cmd/crane/cmd/append.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,5 @@ container image.`,

appendCmd.MarkFlagsMutuallyExclusive("oci-empty-base", "base")
appendCmd.MarkFlagRequired("new_tag")
appendCmd.MarkFlagRequired("new_layer")
return appendCmd
}
16 changes: 5 additions & 11 deletions cmd/crane/cmd/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,14 @@ func NewCmdExport(options *[]crane.Option) *cobra.Command {
return fmt.Errorf("reading tarball from stdin: %w", err)
}
} else {
desc, err := crane.Get(src, *options...)
desc, err := crane.Artifact(src, *options...)
if err != nil {
return fmt.Errorf("pulling %s: %w", src, err)
}
if desc.MediaType.IsSchema1() {
img, err = desc.Schema1()
if err != nil {
return fmt.Errorf("pulling schema 1 image %s: %w", src, err)
}
} else {
img, err = desc.Image()
if err != nil {
return fmt.Errorf("pulling Image %s: %w", src, err)
}
var ok bool
thesayyn marked this conversation as resolved.
Show resolved Hide resolved
img, ok = desc.(v1.Image)
if !ok {
return fmt.Errorf("pulling schema 1 image %s: %w", src, err)
}
}

Expand Down
21 changes: 9 additions & 12 deletions cmd/crane/cmd/flatten.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,26 +91,23 @@ func NewCmdFlatten(options *[]crane.Option) *cobra.Command {
}

func flatten(ref name.Reference, repo name.Repository, use string, o crane.Options) (partial.Describable, error) {
desc, err := remote.Get(ref, o.Remote...)
desc, err := remote.Artifact(ref, o.Remote...)
if err != nil {
return nil, fmt.Errorf("pulling %s: %w", ref, err)
}

if desc.MediaType.IsIndex() {
idx, err := desc.ImageIndex()
if err != nil {
return nil, err
}
if idx, ok := desc.(v1.ImageIndex); ok {
return flattenIndex(idx, repo, use, o)
} else if desc.MediaType.IsImage() {
img, err := desc.Image()
if err != nil {
return nil, err
}
} else if img, ok := desc.(v1.Image); ok {
return flattenImage(img, repo, use, o)
}

return nil, fmt.Errorf("can't flatten %s", desc.MediaType)
mt, err := desc.MediaType()
if err != nil {
return nil, err
}

return nil, fmt.Errorf("can't flatten %s", mt)
}

func push(flat partial.Describable, ref name.Reference, o crane.Options) error {
Expand Down
39 changes: 15 additions & 24 deletions cmd/crane/cmd/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,19 @@ func NewCmdIndexFilter(options *[]crane.Option) *cobra.Command {
if err != nil {
return err
}
desc, err := remote.Get(ref, o.Remote...)
desc, err := remote.Artifact(ref, o.Remote...)
if err != nil {
return fmt.Errorf("pulling %s: %w", baseRef, err)
}
if !desc.MediaType.IsIndex() {
return fmt.Errorf("expected %s to be an index, got %q", baseRef, desc.MediaType)
}
base, err := desc.ImageIndex()
mt, err := desc.MediaType()
if err != nil {
return nil
return err
}

var base v1.ImageIndex
var ok bool
if base, ok = desc.(v1.ImageIndex); !ok {
return fmt.Errorf("expected %s to be an index, got %q", baseRef, mt)
}

idx := filterIndex(base, platforms.platforms)
Expand Down Expand Up @@ -142,6 +145,7 @@ The platform for appended manifests is inferred from the config file or omitted
var (
base v1.ImageIndex
err error
ok bool
ref name.Reference
)

Expand All @@ -160,17 +164,13 @@ The platform for appended manifests is inferred from the config file or omitted
if err != nil {
return err
}
desc, err := remote.Get(ref, o.Remote...)
desc, err := remote.Artifact(ref, o.Remote...)
if err != nil {
return fmt.Errorf("pulling %s: %w", baseRef, err)
}
if !desc.MediaType.IsIndex() {
if base, ok = desc.(v1.ImageIndex); !ok {
return fmt.Errorf("expected %s to be an index, got %q", baseRef, desc.MediaType)
}
base, err = desc.ImageIndex()
if err != nil {
return err
}
}

adds := make([]mutate.IndexAddendum, 0, len(newManifests))
Expand All @@ -180,16 +180,11 @@ The platform for appended manifests is inferred from the config file or omitted
if err != nil {
return err
}
desc, err := remote.Get(ref, o.Remote...)
desc, err := remote.Artifact(ref, o.Remote...)
if err != nil {
return err
}
if desc.MediaType.IsImage() {
img, err := desc.Image()
if err != nil {
return err
}

if img, ok := desc.(v1.Image); ok {
cf, err := img.ConfigFile()
if err != nil {
return err
Expand All @@ -203,11 +198,7 @@ The platform for appended manifests is inferred from the config file or omitted
Add: img,
Descriptor: *newDesc,
})
} else if desc.MediaType.IsIndex() {
idx, err := desc.ImageIndex()
if err != nil {
return err
}
} else if idx, ok := desc.(v1.ImageIndex); ok {
if flatten {
im, err := idx.IndexManifest()
if err != nil {
Expand Down
10 changes: 9 additions & 1 deletion cmd/crane/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
"github.com/google/go-containerregistry/internal/cmd"
"github.com/google/go-containerregistry/pkg/crane"
"github.com/google/go-containerregistry/pkg/logs"
"github.com/google/go-containerregistry/pkg/v1/layout"
"github.com/google/go-containerregistry/pkg/v1/local"

Check failure on line 33 in cmd/crane/cmd/root.go

View workflow job for this annotation

GitHub Actions / Lint

could not import github.com/google/go-containerregistry/pkg/v1/local (-: # github.com/google/go-containerregistry/pkg/v1/local
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/spf13/cobra"
)
Expand All @@ -47,6 +49,7 @@
insecure := false
ndlayers := false
platform := &platformValue{}
uselocal := ""

wt := &warnTransport{}

Expand All @@ -68,6 +71,10 @@
if ndlayers {
options = append(options, crane.WithNondistributable())
}
if uselocal != "" {
p, _ := layout.FromPath(uselocal)
options = append(options, crane.WithPuller(local.NewPuller(p)), crane.WithPusher(local.NewPusher(p)))
}
if Version != "" {
binary := "crane"
if len(os.Args[0]) != 0 {
Expand Down Expand Up @@ -137,7 +144,8 @@
root.PersistentFlags().BoolVar(&insecure, "insecure", false, "Allow image references to be fetched without TLS")
root.PersistentFlags().BoolVar(&ndlayers, "allow-nondistributable-artifacts", false, "Allow pushing non-distributable (foreign) layers")
root.PersistentFlags().Var(platform, "platform", "Specifies the platform in the form os/arch[/variant][:osversion] (e.g. linux/amd64).")

root.PersistentFlags().StringVar(&uselocal, "local", "", "Use a local oci-layout as remote registry")
root.PersistentFlags().MarkHidden("local")
return root
}

Expand Down
26 changes: 15 additions & 11 deletions cmd/crane/cmd/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"fmt"

"github.com/google/go-containerregistry/pkg/crane"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/tarball"
"github.com/google/go-containerregistry/pkg/v1/validate"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -52,7 +53,7 @@ func NewCmdValidate(options *[]crane.Option) *cobra.Command {
}

if remoteRef != "" {
rmt, err := crane.Get(remoteRef, *options...)
rmt, err := crane.Artifact(remoteRef, *options...)
if err != nil {
return fmt.Errorf("failed to read image %s: %w", remoteRef, err)
}
Expand All @@ -63,24 +64,27 @@ func NewCmdValidate(options *[]crane.Option) *cobra.Command {
if fast {
opt = append(opt, validate.Fast)
}
if rmt.MediaType.IsIndex() && o.Platform == nil {
idx, err := rmt.ImageIndex()
if err != nil {
return fmt.Errorf("reading index: %w", err)
}
var (
idx v1.ImageIndex
img v1.Image
ok bool
)
if idx, ok = rmt.(v1.ImageIndex); ok && o.Platform == nil {
if err := validate.Index(idx, opt...); err != nil {
fmt.Fprintf(cmd.OutOrStdout(), "FAIL: %s: %v\n", remoteRef, err)
return err
}
} else {
img, err := rmt.Image()
if err != nil {
return fmt.Errorf("reading image: %w", err)
}
} else if img, ok = rmt.(v1.Image); ok {
if err := validate.Image(img, opt...); err != nil {
fmt.Fprintf(cmd.OutOrStdout(), "FAIL: %s: %v\n", remoteRef, err)
return err
}
} else {
mt, err := rmt.MediaType()
if err != nil {
return err
}
return fmt.Errorf("failed to validate ref %s: uknown media type %s", remoteRef, mt)
}
fmt.Fprintf(cmd.OutOrStdout(), "PASS: %s\n", remoteRef)
}
Expand Down
15 changes: 12 additions & 3 deletions internal/cmd/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,14 +280,19 @@ func editManifest(in io.Reader, out io.Writer, src string, dst string, mt string
return nil, err
}

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

manifest, err := desc.RawManifest()
if err != nil {
return nil, err
}

var edited []byte
if interactive(in, out) {
edited, err = editor.Edit(bytes.NewReader(desc.Manifest), ".json")
edited, err = editor.Edit(bytes.NewReader(manifest), ".json")
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -317,7 +322,11 @@ func editManifest(in io.Reader, out io.Writer, src string, dst string, mt string

if mt == "" {
// If --media-type is unset, use Content-Type by default.
mt = string(desc.MediaType)
mediatype, err := desc.MediaType()
if err != nil {
return nil, err
}
mt = string(mediatype)

// If document contains mediaType, default to that.
wmt := withMediaType{}
Expand Down
Binary file added main
Binary file not shown.
Empty file added notes.txt
Empty file.
Binary file added pkg/.DS_Store
thesayyn marked this conversation as resolved.
Show resolved Hide resolved
Binary file not shown.
12 changes: 3 additions & 9 deletions pkg/crane/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,15 @@ func Copy(src, dst string, opt ...Option) error {
}

logs.Progress.Printf("Copying from %v to %v", srcRef, dstRef)
desc, err := puller.Get(o.ctx, srcRef)
desc, err := puller.Artifact(o.ctx, srcRef)
if err != nil {
return fmt.Errorf("fetching %q: %w", src, err)
}

if o.Platform == nil {
return pusher.Push(o.ctx, dstRef, desc)
}

// If platform is explicitly set, don't copy the whole index, just the appropriate image.
img, err := desc.Image()
if err != nil {
return err
}
return pusher.Push(o.ctx, dstRef, img)
return pusher.Push(o.ctx, dstRef, desc)
}

// CopyRepository copies every tag from src to dst.
Expand Down Expand Up @@ -166,7 +160,7 @@ func CopyRepository(src, dst string, opt ...Option) error {
}

logs.Progress.Printf("Fetching %s", srcTag)
desc, err := puller.Get(ctx, srcTag)
desc, err := puller.Artifact(ctx, srcTag)
if err != nil {
return err
}
Expand Down
25 changes: 11 additions & 14 deletions pkg/crane/digest.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,19 @@

package crane

import "github.com/google/go-containerregistry/pkg/logs"
import (
"github.com/google/go-containerregistry/pkg/logs"
)

// Digest returns the sha256 hash of the remote image at ref.
func Digest(ref string, opt ...Option) (string, error) {
o := makeOptions(opt...)
if o.Platform != nil {
desc, err := getManifest(ref, opt...)
desc, err := getArtifact(ref, opt...)
if err != nil {
return "", err
}
if !desc.MediaType.IsIndex() {
return desc.Digest.String(), nil
}

// TODO: does not work for indexes which contain schema v1 manifests
img, err := desc.Image()
if err != nil {
return "", err
}
digest, err := img.Digest()
digest, err := desc.Digest()
if err != nil {
return "", err
}
Expand All @@ -42,11 +35,15 @@ func Digest(ref string, opt ...Option) (string, error) {
desc, err := Head(ref, opt...)
if err != nil {
logs.Warn.Printf("HEAD request failed, falling back on GET: %v", err)
rdesc, err := getManifest(ref, opt...)
rdesc, err := getArtifact(ref, opt...)
if err != nil {
return "", err
}
hash, err := rdesc.Digest()
if err != nil {
return "", err
}
return rdesc.Digest.String(), nil
return hash.String(), nil
}
return desc.Digest.String(), nil
}
Loading
Loading