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

Add remote.Reuse for Pusher/Puller #1672

Merged
merged 5 commits into from
Apr 25, 2023
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
57 changes: 0 additions & 57 deletions internal/legacy/copy.go

This file was deleted.

97 changes: 0 additions & 97 deletions internal/legacy/copy_test.go

This file was deleted.

54 changes: 15 additions & 39 deletions pkg/crane/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@ package crane
import (
"fmt"

"github.com/google/go-containerregistry/internal/legacy"
"github.com/google/go-containerregistry/pkg/logs"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/google/go-containerregistry/pkg/v1/types"
)

// Copy copies a remote image or index from src to dst.
Expand All @@ -37,52 +35,30 @@ func Copy(src, dst string, opt ...Option) error {
return fmt.Errorf("parsing reference for %q: %w", dst, err)
}

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

switch desc.MediaType {
case types.OCIImageIndex, types.DockerManifestList:
// Handle indexes separately.
if o.Platform != nil {
// If platform is explicitly set, don't copy the whole index, just the appropriate image.
if err := copyImage(desc, dstRef, o); err != nil {
return fmt.Errorf("failed to copy image: %w", err)
}
} else {
if err := copyIndex(desc, dstRef, o); err != nil {
return fmt.Errorf("failed to copy index: %w", err)
}
}
case types.DockerManifestSchema1, types.DockerManifestSchema1Signed:
// Handle schema 1 images separately.
if err := legacy.CopySchema1(desc, srcRef, dstRef, o.Remote...); err != nil {
return fmt.Errorf("failed to copy schema 1 image: %w", err)
}
default:
// Assume anything else is an image, since some registries don't set mediaTypes properly.
if err := copyImage(desc, dstRef, o); err != nil {
return fmt.Errorf("failed to copy image: %w", err)
}
puller, err := remote.NewPuller(o.Remote...)
if err != nil {
return err
}

return nil
}

func copyImage(desc *remote.Descriptor, dstRef name.Reference, o Options) error {
img, err := desc.Image()
logs.Progress.Printf("Copying from %v to %v", srcRef, dstRef)
desc, err := puller.Get(o.ctx, srcRef)
if err != nil {
return err
return fmt.Errorf("fetching %q: %w", src, err)
}
return remote.Write(dstRef, img, o.Remote...)
}

func copyIndex(desc *remote.Descriptor, dstRef name.Reference, o Options) error {
idx, err := desc.ImageIndex()
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 remote.WriteIndex(dstRef, idx, o.Remote...)
return pusher.Push(o.ctx, dstRef, img)
}
3 changes: 3 additions & 0 deletions pkg/crane/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type Options struct {

transport http.RoundTripper
insecure bool
ctx context.Context
}

// GetOptions exposes the underlying []remote.Option, []name.Option, and
Expand All @@ -50,6 +51,7 @@ func makeOptions(opts ...Option) Options {
remote.WithAuthFromKeychain(authn.DefaultKeychain),
},
Keychain: authn.DefaultKeychain,
ctx: context.Background(),
}

for _, o := range opts {
Expand Down Expand Up @@ -144,6 +146,7 @@ func WithNondistributable() Option {
// WithContext is a functional option for setting the context.
func WithContext(ctx context.Context) Option {
return func(o *Options) {
o.ctx = ctx
o.Remote = append(o.Remote, remote.WithContext(ctx))
}
}
18 changes: 10 additions & 8 deletions pkg/v1/remote/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ func CatalogPage(target name.Registry, last string, n int, options ...Option) ([
if err != nil {
return nil, err
}
f, err := makeFetcher(o.context, target, o)

f, err := newPuller(o).fetcher(o.context, target)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -82,18 +83,18 @@ func Catalog(ctx context.Context, target name.Registry, options ...Option) ([]st
ctx = o.context
}

return newPuller(o).Catalog(ctx, target)
return newPuller(o).catalog(ctx, target, o.pageSize)
}

func (f *fetcher) catalogPage(ctx context.Context, reg name.Registry, next string) (*Catalogs, error) {
func (f *fetcher) catalogPage(ctx context.Context, reg name.Registry, next string, pageSize int) (*Catalogs, error) {
if next == "" {
uri := &url.URL{
Scheme: reg.Scheme(),
Host: reg.RegistryStr(),
Path: "/v2/_catalog",
}
if f.pageSize > 0 {
uri.RawQuery = fmt.Sprintf("n=%d", f.pageSize)
if pageSize > 0 {
uri.RawQuery = fmt.Sprintf("n=%d", pageSize)
}
next = uri.String()
}
Expand Down Expand Up @@ -134,8 +135,9 @@ func (f *fetcher) catalogPage(ctx context.Context, reg name.Registry, next strin
}

type Catalogger struct {
f *fetcher
reg name.Registry
f *fetcher
reg name.Registry
pageSize int

page *Catalogs
err error
Expand All @@ -145,7 +147,7 @@ type Catalogger struct {

func (l *Catalogger) Next(ctx context.Context) (*Catalogs, error) {
if l.needMore {
l.page, l.err = l.f.catalogPage(ctx, l.reg, l.page.Next)
l.page, l.err = l.f.catalogPage(ctx, l.reg, l.page.Next, l.pageSize)
} else {
l.needMore = true
}
Expand Down
34 changes: 1 addition & 33 deletions pkg/v1/remote/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,7 @@
package remote

import (
"fmt"
"net/http"
"net/url"

"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote/transport"
)

// Delete removes the specified image reference from the remote registry.
Expand All @@ -29,32 +24,5 @@ func Delete(ref name.Reference, options ...Option) error {
if err != nil {
return err
}
w, err := makeWriter(o.context, ref.Context(), nil, o)
if err != nil {
return err
}
c := w.client

u := url.URL{
Scheme: ref.Context().Registry.Scheme(),
Host: ref.Context().RegistryStr(),
Path: fmt.Sprintf("/v2/%s/manifests/%s", ref.Context().RepositoryStr(), ref.Identifier()),
}

req, err := http.NewRequest(http.MethodDelete, u.String(), nil)
if err != nil {
return err
}

resp, err := c.Do(req.WithContext(o.context))
if err != nil {
return err
}
defer resp.Body.Close()

return transport.CheckError(resp, http.StatusOK, http.StatusAccepted)

// TODO(jason): If the manifest had a `subject`, and if the registry
// doesn't support Referrers, update the index pointed to by the
// subject's fallback tag to remove the descriptor for this manifest.
return newPusher(o).Delete(o.context, ref)
}
Loading