From 78d2bc8b31740b429f52f00f97899afda32714c8 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:47:02 +0100 Subject: [PATCH] remove regctl and create the right oras client Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> --- .../extensions/repositories/ocireg/blobs.go | 16 +- .../repositories/ocireg/namespace.go | 12 +- .../repositories/ocireg/repository.go | 44 ++- .../extensions/repositories/ocireg/utils.go | 6 +- api/tech/docker/lister.go | 4 +- api/tech/docker/pusher.go | 9 +- api/tech/docker/resolver.go | 11 +- api/tech/oras/client.go | 20 +- api/tech/{regclient => oras}/interface.go | 2 +- api/tech/regclient/client.go | 324 ------------------ api/tech/regclient/client_test.go | 16 - api/tech/regclient/delayed_reader.go | 55 --- go.mod | 2 - go.sum | 4 - 14 files changed, 77 insertions(+), 448 deletions(-) rename api/tech/{regclient => oras}/interface.go (99%) delete mode 100644 api/tech/regclient/client.go delete mode 100644 api/tech/regclient/client_test.go delete mode 100644 api/tech/regclient/delayed_reader.go diff --git a/api/oci/extensions/repositories/ocireg/blobs.go b/api/oci/extensions/repositories/ocireg/blobs.go index f92deba0a..d8491c266 100644 --- a/api/oci/extensions/repositories/ocireg/blobs.go +++ b/api/oci/extensions/repositories/ocireg/blobs.go @@ -10,7 +10,7 @@ import ( "ocm.software/ocm/api/oci/cpi" "ocm.software/ocm/api/oci/extensions/attrs/cacheattr" - "ocm.software/ocm/api/tech/regclient" + "ocm.software/ocm/api/tech/oras" "ocm.software/ocm/api/utils/accessio" "ocm.software/ocm/api/utils/blobaccess/blobaccess" ) @@ -23,20 +23,20 @@ type BlobContainer interface { type blobContainer struct { accessio.StaticAllocatable - fetcher regclient.Fetcher - pusher regclient.Pusher + fetcher oras.Fetcher + pusher oras.Pusher mime string } type BlobContainers struct { lock sync.Mutex cache accessio.BlobCache - fetcher regclient.Fetcher - pusher regclient.Pusher + fetcher oras.Fetcher + pusher oras.Pusher mimes map[string]BlobContainer } -func NewBlobContainers(ctx cpi.Context, fetcher remotes.Fetcher, pusher regclient.Pusher) *BlobContainers { +func NewBlobContainers(ctx cpi.Context, fetcher remotes.Fetcher, pusher oras.Pusher) *BlobContainers { return &BlobContainers{ cache: cacheattr.Get(ctx), fetcher: fetcher, @@ -73,7 +73,7 @@ func (c *BlobContainers) Release() error { return list.Result() } -func newBlobContainer(mime string, fetcher regclient.Fetcher, pusher regclient.Pusher) *blobContainer { +func newBlobContainer(mime string, fetcher oras.Fetcher, pusher oras.Pusher) *blobContainer { return &blobContainer{ mime: mime, fetcher: fetcher, @@ -81,7 +81,7 @@ func newBlobContainer(mime string, fetcher regclient.Fetcher, pusher regclient.P } } -func NewBlobContainer(cache accessio.BlobCache, mime string, fetcher regclient.Fetcher, pusher regclient.Pusher) (BlobContainer, error) { +func NewBlobContainer(cache accessio.BlobCache, mime string, fetcher oras.Fetcher, pusher oras.Pusher) (BlobContainer, error) { c := newBlobContainer(mime, fetcher, pusher) if cache == nil { diff --git a/api/oci/extensions/repositories/ocireg/namespace.go b/api/oci/extensions/repositories/ocireg/namespace.go index cae5c05c3..dd3583d7b 100644 --- a/api/oci/extensions/repositories/ocireg/namespace.go +++ b/api/oci/extensions/repositories/ocireg/namespace.go @@ -12,7 +12,7 @@ import ( "ocm.software/ocm/api/oci/cpi" "ocm.software/ocm/api/oci/cpi/support" "ocm.software/ocm/api/oci/extensions/actions/oci-repository-prepare" - "ocm.software/ocm/api/tech/regclient" + "ocm.software/ocm/api/tech/oras" "ocm.software/ocm/api/utils/accessio" "ocm.software/ocm/api/utils/blobaccess/blobaccess" "ocm.software/ocm/api/utils/logging" @@ -22,10 +22,10 @@ import ( type NamespaceContainer struct { impl support.NamespaceAccessImpl repo *RepositoryImpl - resolver regclient.Resolver - lister regclient.Lister - fetcher regclient.Fetcher - pusher regclient.Pusher + resolver oras.Resolver + lister oras.Lister + fetcher oras.Fetcher + pusher oras.Pusher blobs *BlobContainers checked bool } @@ -69,7 +69,7 @@ func (n *NamespaceContainer) SetImplementation(impl support.NamespaceAccessImpl) n.impl = impl } -func (n *NamespaceContainer) getPusher(vers string) (regclient.Pusher, error) { +func (n *NamespaceContainer) getPusher(vers string) (oras.Pusher, error) { err := n.assureCreated() if err != nil { return nil, err diff --git a/api/oci/extensions/repositories/ocireg/repository.go b/api/oci/extensions/repositories/ocireg/repository.go index 62eab2280..391831533 100644 --- a/api/oci/extensions/repositories/ocireg/repository.go +++ b/api/oci/extensions/repositories/ocireg/repository.go @@ -2,6 +2,9 @@ package ocireg import ( "context" + "crypto/tls" + "crypto/x509" + "net/http" "path" "strings" @@ -12,11 +15,11 @@ import ( "oras.land/oras-go/v2/registry/remote/retry" "ocm.software/ocm/api/credentials" + "ocm.software/ocm/api/datacontext/attrs/rootcertsattr" "ocm.software/ocm/api/oci/artdesc" "ocm.software/ocm/api/oci/cpi" "ocm.software/ocm/api/tech/oci/identity" "ocm.software/ocm/api/tech/oras" - "ocm.software/ocm/api/tech/regclient" "ocm.software/ocm/api/utils" ocmlog "ocm.software/ocm/api/utils/logging" "ocm.software/ocm/api/utils/refmgmt" @@ -111,7 +114,7 @@ func (r *RepositoryImpl) getCreds(comp string) (credentials.Credentials, error) return identity.GetCredentials(r.GetContext(), r.info.Locator, comp) } -func (r *RepositoryImpl) getResolver(comp string) (regclient.Resolver, error) { +func (r *RepositoryImpl) getResolver(comp string) (oras.Resolver, error) { creds, err := r.getCreds(comp) if err != nil { if !errors.IsErrUnknownKind(err, credentials.KIND_CONSUMER) { @@ -133,13 +136,44 @@ func (r *RepositoryImpl) getResolver(comp string) (regclient.Resolver, error) { authCreds.Password = pass } - client := &auth.Client{ - Client: retry.DefaultClient, + client := retry.DefaultClient + if r.info.Scheme == "https" { + // set up TLS + //nolint:gosec // used like the default, there are OCI servers (quay.io) not working with min version. + conf := &tls.Config{ + // MinVersion: tls.VersionTLS13, + RootCAs: func() *x509.CertPool { + var rootCAs *x509.CertPool + if creds != nil { + c := creds.GetProperty(credentials.ATTR_CERTIFICATE_AUTHORITY) + if c != "" { + rootCAs = x509.NewCertPool() + rootCAs.AppendCertsFromPEM([]byte(c)) + } + } + if rootCAs == nil { + rootCAs = rootcertsattr.Get(r.GetContext()).GetRootCertPool(true) + } + return rootCAs + }(), + } + client = &http.Client{ + Transport: retry.NewTransport(&http.Transport{ + TLSClientConfig: conf, + }), + } + } + + authClient := &auth.Client{ + Client: client, Cache: auth.NewCache(), Credential: auth.StaticCredential(r.info.HostPort(), authCreds), } - return oras.New(oras.ClientOptions{Client: client}), nil + return oras.New(oras.ClientOptions{ + Client: authClient, + PlainHTTP: r.info.Scheme == "http", + }), nil } func (r *RepositoryImpl) GetRef(comp, vers string) string { diff --git a/api/oci/extensions/repositories/ocireg/utils.go b/api/oci/extensions/repositories/ocireg/utils.go index 8c58c5237..761cb045c 100644 --- a/api/oci/extensions/repositories/ocireg/utils.go +++ b/api/oci/extensions/repositories/ocireg/utils.go @@ -14,7 +14,7 @@ import ( "ocm.software/ocm/api/oci/artdesc" "ocm.software/ocm/api/oci/cpi" - "ocm.software/ocm/api/tech/regclient" + "ocm.software/ocm/api/tech/oras" "ocm.software/ocm/api/utils/accessio" "ocm.software/ocm/api/utils/blobaccess/blobaccess" "ocm.software/ocm/api/utils/logging" @@ -81,12 +81,12 @@ func readAll(reader io.ReadCloser, err error) ([]byte, error) { return data, nil } -func push(ctx context.Context, p regclient.Pusher, blob blobaccess.BlobAccess) error { +func push(ctx context.Context, p oras.Pusher, blob blobaccess.BlobAccess) error { desc := *artdesc.DefaultBlobDescriptor(blob) return pushData(ctx, p, desc, blob) } -func pushData(ctx context.Context, p regclient.Pusher, desc artdesc.Descriptor, data blobaccess.DataAccess) error { +func pushData(ctx context.Context, p oras.Pusher, desc artdesc.Descriptor, data blobaccess.DataAccess) error { key := remotes.MakeRefKey(ctx, desc) if desc.Size == 0 { desc.Size = -1 diff --git a/api/tech/docker/lister.go b/api/tech/docker/lister.go index 95b7a5117..aa492f3a7 100644 --- a/api/tech/docker/lister.go +++ b/api/tech/docker/lister.go @@ -11,7 +11,7 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/log" "github.com/pkg/errors" - "ocm.software/ocm/api/tech/regclient" + "ocm.software/ocm/api/tech/oras" ) var ErrObjectNotRequired = errors.New("object not required") @@ -25,7 +25,7 @@ type dockerLister struct { dockerBase *dockerBase } -func (r *dockerResolver) Lister(ctx context.Context, ref string) (regclient.Lister, error) { +func (r *dockerResolver) Lister(ctx context.Context, ref string) (oras.Lister, error) { base, err := r.resolveDockerBase(ref) if err != nil { return nil, err diff --git a/api/tech/docker/pusher.go b/api/tech/docker/pusher.go index 53b2a785f..0ab86dd4d 100644 --- a/api/tech/docker/pusher.go +++ b/api/tech/docker/pusher.go @@ -19,9 +19,8 @@ import ( ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "ocm.software/ocm/api/tech/regclient" - remoteserrors "ocm.software/ocm/api/tech/docker/errors" + "ocm.software/ocm/api/tech/oras" "ocm.software/ocm/api/utils/accessio" ) @@ -39,11 +38,11 @@ type dockerPusher struct { tracker StatusTracker } -func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor, src regclient.Source) (regclient.PushRequest, error) { +func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor, src oras.Source) (oras.PushRequest, error) { return p.push(ctx, desc, src, remotes.MakeRefKey(ctx, desc), false) } -func (p dockerPusher) push(ctx context.Context, desc ocispec.Descriptor, src regclient.Source, ref string, unavailableOnFail bool) (regclient.PushRequest, error) { +func (p dockerPusher) push(ctx context.Context, desc ocispec.Descriptor, src oras.Source, ref string, unavailableOnFail bool) (oras.PushRequest, error) { if l, ok := p.tracker.(StatusTrackLocker); ok { l.Lock(ref) defer l.Unlock(ref) @@ -324,7 +323,7 @@ type pushRequest struct { ref string responseC <-chan response - source regclient.Source + source oras.Source isManifest bool expected digest.Digest diff --git a/api/tech/docker/resolver.go b/api/tech/docker/resolver.go index a5b5f3161..231a78976 100644 --- a/api/tech/docker/resolver.go +++ b/api/tech/docker/resolver.go @@ -22,8 +22,7 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/net/context/ctxhttp" - "ocm.software/ocm/api/tech/regclient" - + "ocm.software/ocm/api/tech/oras" "ocm.software/ocm/api/utils/accessio" ) @@ -120,7 +119,7 @@ type dockerResolver struct { } // NewResolver returns a new resolver to a Docker registry. -func NewResolver(options ResolverOptions) regclient.Resolver { +func NewResolver(options ResolverOptions) oras.Resolver { if options.Tracker == nil { options.Tracker = NewInMemoryTracker() } @@ -204,7 +203,7 @@ func (r *countingReader) Read(p []byte) (int, error) { return n, err } -var _ regclient.Resolver = &dockerResolver{} +var _ oras.Resolver = &dockerResolver{} func (r *dockerResolver) Resolve(ctx context.Context, ref string) (string, ocispec.Descriptor, error) { base, err := r.resolveDockerBase(ref) @@ -384,7 +383,7 @@ func (r *dockerResolver) Resolve(ctx context.Context, ref string) (string, ocisp return "", ocispec.Descriptor{}, firstErr } -func (r *dockerResolver) Fetcher(ctx context.Context, ref string) (regclient.Fetcher, error) { +func (r *dockerResolver) Fetcher(ctx context.Context, ref string) (oras.Fetcher, error) { base, err := r.resolveDockerBase(ref) if err != nil { return nil, err @@ -395,7 +394,7 @@ func (r *dockerResolver) Fetcher(ctx context.Context, ref string) (regclient.Fet }, nil } -func (r *dockerResolver) Pusher(ctx context.Context, ref string) (regclient.Pusher, error) { +func (r *dockerResolver) Pusher(ctx context.Context, ref string) (oras.Pusher, error) { base, err := r.resolveDockerBase(ref) if err != nil { return nil, err diff --git a/api/tech/oras/client.go b/api/tech/oras/client.go index 34972532a..bf9c3b89d 100644 --- a/api/tech/oras/client.go +++ b/api/tech/oras/client.go @@ -12,8 +12,6 @@ import ( ociv1 "github.com/opencontainers/image-spec/specs-go/v1" "oras.land/oras-go/v2/registry/remote" "oras.land/oras-go/v2/registry/remote/auth" - - "ocm.software/ocm/api/tech/regclient" ) type ClientOptions struct { @@ -37,13 +35,13 @@ func (p *pushRequest) Status() (content.Status, error) { return content.Status{}, nil } -var _ regclient.PushRequest = &pushRequest{} +var _ PushRequest = &pushRequest{} var ( - _ regclient.Resolver = &Client{} - _ regclient.Fetcher = &Client{} - _ regclient.Pusher = &Client{} - _ regclient.Lister = &Client{} + _ Resolver = &Client{} + _ Fetcher = &Client{} + _ Pusher = &Client{} + _ Lister = &Client{} ) func New(opts ClientOptions) *Client { @@ -73,22 +71,22 @@ func (c *Client) Resolve(ctx context.Context, ref string) (string, ociv1.Descrip return "", desc, nil } -func (c *Client) Fetcher(ctx context.Context, ref string) (regclient.Fetcher, error) { +func (c *Client) Fetcher(ctx context.Context, ref string) (Fetcher, error) { c.Ref = ref return c, nil } -func (c *Client) Pusher(ctx context.Context, ref string) (regclient.Pusher, error) { +func (c *Client) Pusher(ctx context.Context, ref string) (Pusher, error) { c.Ref = ref return c, nil } -func (c *Client) Lister(ctx context.Context, ref string) (regclient.Lister, error) { +func (c *Client) Lister(ctx context.Context, ref string) (Lister, error) { c.Ref = ref return c, nil } -func (c *Client) Push(ctx context.Context, d ociv1.Descriptor, src regclient.Source) (regclient.PushRequest, error) { +func (c *Client) Push(ctx context.Context, d ociv1.Descriptor, src Source) (PushRequest, error) { reader, err := src.Reader() if err != nil { return nil, err diff --git a/api/tech/regclient/interface.go b/api/tech/oras/interface.go similarity index 99% rename from api/tech/regclient/interface.go rename to api/tech/oras/interface.go index d11f0648d..ccd9ab1d4 100644 --- a/api/tech/regclient/interface.go +++ b/api/tech/oras/interface.go @@ -1,4 +1,4 @@ -package regclient +package oras import ( "context" diff --git a/api/tech/regclient/client.go b/api/tech/regclient/client.go deleted file mode 100644 index cd51397b6..000000000 --- a/api/tech/regclient/client.go +++ /dev/null @@ -1,324 +0,0 @@ -package regclient - -import ( - "bytes" - "context" - "errors" - "fmt" - "io" - "strings" - "time" - - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/images" - "github.com/opencontainers/go-digest" - ociv1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/regclient/regclient" - "github.com/regclient/regclient/config" - "github.com/regclient/regclient/scheme/reg" - "github.com/regclient/regclient/types/descriptor" - regerr "github.com/regclient/regclient/types/errs" - "github.com/regclient/regclient/types/manifest" - "github.com/regclient/regclient/types/platform" - regref "github.com/regclient/regclient/types/ref" -) - -type ClientOptions struct { - Host []config.Host - Version string -} - -type Client struct { - rc *regclient.RegClient - ref regref.Ref -} - -type pushRequest struct { - rc *regclient.RegClient - desc descriptor.Descriptor - ref regref.Ref -} - -// Commit and Status are actually not really used in the library. Commit is a second stage operation and Status is never called in -// the library. The Status was a thing mostly in docker being used to track chunk reads. But that's taken care of -// by regclient internally. -func (p *pushRequest) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error { - return p.rc.Close(ctx, p.ref) -} - -func (p *pushRequest) Status() (content.Status, error) { - return content.Status{ - Ref: p.ref.Reference, - Total: p.desc.Size, - }, nil -} - -var _ PushRequest = &pushRequest{} - -var ( - _ Resolver = &Client{} - _ Fetcher = &Client{} - _ Pusher = &Client{} - _ Lister = &Client{} -) - -func New(opts ClientOptions) *Client { - rc := regclient.New( - regclient.WithConfigHost(opts.Host...), - regclient.WithDockerCerts(), - regclient.WithDockerCreds(), - regclient.WithUserAgent("containerd/"+opts.Version), - regclient.WithRegOpts( - // reg.WithCertDirs([]string{"."}), - reg.WithDelay(2*time.Second, 15*time.Second), - reg.WithRetryLimit(5), - reg.WithCache(5*time.Minute, 500), // built in cache!! Nice! - ), - ) - - return &Client{rc: rc} -} - -// Close must be called at the end of the operation. -func (c *Client) Close(ctx context.Context, ref regref.Ref) error { - return c.rc.Close(ctx, ref) -} - -func (c *Client) convertDescriptorToOCI(desc descriptor.Descriptor) ociv1.Descriptor { - var p *ociv1.Platform - if desc.Platform != nil { - p = &ociv1.Platform{ - Architecture: desc.Platform.Architecture, - OS: desc.Platform.OS, - OSVersion: desc.Platform.OSVersion, - OSFeatures: desc.Platform.OSFeatures, - Variant: desc.Platform.Variant, - } - } - - return ociv1.Descriptor{ - MediaType: desc.MediaType, - Size: desc.Size, - Digest: desc.Digest, - Platform: p, - URLs: desc.URLs, - Annotations: desc.Annotations, - Data: desc.Data, - ArtifactType: desc.ArtifactType, - } -} - -func (c *Client) convertDescriptorToRegClient(desc ociv1.Descriptor) descriptor.Descriptor { - var p *platform.Platform - if desc.Platform != nil { - p = &platform.Platform{ - Architecture: desc.Platform.Architecture, - OS: desc.Platform.OS, - OSVersion: desc.Platform.OSVersion, - OSFeatures: desc.Platform.OSFeatures, - Variant: desc.Platform.Variant, - } - } - - return descriptor.Descriptor{ - MediaType: desc.MediaType, - Size: desc.Size, - Digest: desc.Digest, - Platform: p, - URLs: desc.URLs, - Annotations: desc.Annotations, - Data: desc.Data, - ArtifactType: desc.ArtifactType, - } -} - -func (c *Client) Resolve(ctx context.Context, ref string) (string, ociv1.Descriptor, error) { - r, err := regref.New(ref) - if err != nil { - return "", ociv1.Descriptor{}, err - } - - // first, try to find the manifest - m, err := c.rc.ManifestHead(ctx, r) - if err != nil { - if c.isNotFoundError(err) { - // try to find a blob - if r.Digest != "" { - blob, err := c.rc.BlobHead(ctx, r, descriptor.Descriptor{ - Digest: digest.Digest(r.Digest), - }) - defer blob.Close() //nolint:staticcheck // we can safely close it as this is not when we read it. - - if err != nil { - if c.isNotFoundError(err) { - return "", ociv1.Descriptor{}, errdefs.ErrNotFound - } - - return "", ociv1.Descriptor{}, fmt.Errorf("failed to resolve blob head: %w", err) - } - - // update the reference that has been resolved successfully - c.ref = r - - return ref, c.convertDescriptorToOCI(blob.GetDescriptor()), nil - } - - return "", ociv1.Descriptor{}, errdefs.ErrNotFound - } - - return "", ociv1.Descriptor{}, fmt.Errorf("failed to get manifest: %w", err) - } - - // update the Ref of the client to the resolved reference. - c.ref = r - - return ref, c.convertDescriptorToOCI(m.GetDescriptor()), nil -} - -func (c *Client) Fetcher(ctx context.Context, ref string) (Fetcher, error) { - var err error - c.ref, err = regref.New(ref) - if err != nil { - return nil, err - } - - return c, nil -} - -func (c *Client) Pusher(ctx context.Context, ref string) (Pusher, error) { - var err error - c.ref, err = regref.New(ref) - if err != nil { - return nil, err - } - - return c, nil -} - -func (c *Client) Lister(ctx context.Context, ref string) (Lister, error) { - var err error - c.ref, err = regref.New(ref) - if err != nil { - return nil, err - } - - return c, nil -} - -func (c *Client) Push(ctx context.Context, d ociv1.Descriptor, src Source) (PushRequest, error) { - reader, err := src.Reader() - if err != nil { - return nil, err - } - - if c.isManifest(d) { - manifestContent, err := io.ReadAll(reader) - if err != nil { - return nil, fmt.Errorf("failed to read manifest: %w", err) - } - - m, err := manifest.New(manifest.WithDesc(c.convertDescriptorToRegClient(d)), manifest.WithRef(c.ref), manifest.WithRaw(manifestContent)) - if err != nil { - return nil, fmt.Errorf("failed to create a manifest: %w", err) - } - - if err := c.rc.ManifestPut(ctx, c.ref, m); err != nil { - return nil, fmt.Errorf("failed to put manifest: %w", err) - } - - // pushRequest closes the RC on `Commit`. - return &pushRequest{ - desc: c.convertDescriptorToRegClient(d), - rc: c.rc, - ref: c.ref, - }, nil - } - - desc, err := c.rc.BlobPut(ctx, c.ref, c.convertDescriptorToRegClient(d), reader) - if err != nil { - return nil, err - } - - return &pushRequest{ - desc: desc, - rc: c.rc, - ref: c.ref, - }, nil -} - -func (c *Client) Fetch(ctx context.Context, desc ociv1.Descriptor) (_ io.ReadCloser, err error) { - defer func() { - if cerr := c.rc.Close(ctx, c.ref); cerr != nil { - err = errors.Join(err, fmt.Errorf("failed to close the client after fetch: %w", cerr)) - } - }() - - // -1 is not a thing in regclient. - if desc.Size < 0 { - desc.Size = 0 - } - - if c.isManifest(desc) { - manifestContent, err := c.rc.ManifestGet(ctx, c.ref, regclient.WithManifestDesc(c.convertDescriptorToRegClient(desc))) - if err != nil { - if c.isNotFoundError(err) { - return nil, errdefs.ErrNotFound - } - - return nil, err - } - - body, err := manifestContent.RawBody() - if err != nil { - return nil, err - } - - return io.NopCloser(bytes.NewReader(body)), nil - } - - // check if the blob exists so we can bail early - _, err = c.rc.BlobHead(ctx, c.ref, c.convertDescriptorToRegClient(desc)) - if err != nil { - if c.isNotFoundError(err) { - return nil, errdefs.ErrNotFound - } - - return nil, err - } - - delayer := func() (io.ReadCloser, error) { - return c.rc.BlobGet(ctx, c.ref, c.convertDescriptorToRegClient(desc)) - } - - return newDelayedReader(delayer) -} - -func (c *Client) List(ctx context.Context) (_ []string, err error) { - defer func() { - if cerr := c.rc.Close(ctx, c.ref); cerr != nil { - err = errors.Join(err, fmt.Errorf("failed to close the client after list: %w", cerr)) - } - }() - - tags, err := c.rc.TagList(ctx, c.ref) - if err != nil { - return nil, err - } - - return tags.Tags, nil -} - -func (c *Client) isManifest(desc ociv1.Descriptor) bool { - switch desc.MediaType { - case images.MediaTypeDockerSchema2Manifest, images.MediaTypeDockerSchema2ManifestList, - ociv1.MediaTypeImageManifest, ociv1.MediaTypeImageIndex: - return true - } - - return false -} - -func (c *Client) isNotFoundError(err error) bool { - return errors.Is(err, regerr.ErrNotFound) || strings.Contains(err.Error(), regerr.ErrNotFound.Error()) -} diff --git a/api/tech/regclient/client_test.go b/api/tech/regclient/client_test.go deleted file mode 100644 index b5045d702..000000000 --- a/api/tech/regclient/client_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package regclient - -import ( - "testing" - - "github.com/regclient/regclient/config" - "github.com/stretchr/testify/require" -) - -func TestNew(t *testing.T) { - host := config.HostNew() - n := New(ClientOptions{Host: []config.Host{ - *host, - }}) - require.NotNil(t, n) -} diff --git a/api/tech/regclient/delayed_reader.go b/api/tech/regclient/delayed_reader.go deleted file mode 100644 index ac7f3d5fa..000000000 --- a/api/tech/regclient/delayed_reader.go +++ /dev/null @@ -1,55 +0,0 @@ -package regclient - -import "io" - -// delayedReader sets up a reader that only fetches a blob -// upon explicit reading request, otherwise, it stores the -// way of getting the reader. -type delayedReader struct { - open func() (io.ReadCloser, error) - rc io.ReadCloser - closed bool -} - -func newDelayedReader(open func() (io.ReadCloser, error)) (io.ReadCloser, error) { - return &delayedReader{ - open: open, - }, nil -} - -func (d *delayedReader) Read(p []byte) (n int, err error) { - if d.closed { - return 0, io.EOF - } - - reader, err := d.reader() - if err != nil { - return 0, err - } - - return reader.Read(p) -} - -func (d *delayedReader) reader() (io.ReadCloser, error) { - if d.rc != nil { - return d.rc, nil - } - - rc, err := d.open() - if err != nil { - return nil, err - } - - d.rc = rc - return rc, nil -} - -func (d *delayedReader) Close() error { - if d.closed { - return nil - } - - // we close regardless of an error - d.closed = true - return d.rc.Close() -} diff --git a/go.mod b/go.mod index ac7d4f164..e2c53c704 100644 --- a/go.mod +++ b/go.mod @@ -58,7 +58,6 @@ require ( github.com/opencontainers/image-spec v1.1.0 github.com/pkg/errors v0.9.1 github.com/redis/go-redis/v9 v9.7.0 - github.com/regclient/regclient v0.7.2 github.com/rogpeppe/go-internal v1.13.1 github.com/sigstore/cosign/v2 v2.4.1 github.com/sigstore/rekor v1.3.7 @@ -176,7 +175,6 @@ require ( github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/elliotchance/orderedmap v1.7.0 // indirect github.com/emicklei/go-restful/v3 v3.12.1 // indirect diff --git a/go.sum b/go.sum index d0c118cd9..cfe049224 100644 --- a/go.sum +++ b/go.sum @@ -783,8 +783,6 @@ github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olareg/olareg v0.1.1 h1:Ui7q93zjcoF+U9U71sgqgZWByDoZOpqHitUXEu2xV+g= -github.com/olareg/olareg v0.1.1/go.mod h1:w8NP4SWrHHtxsFaUiv1lnCnYPm4sN1seCd2h7FK/dc0= github.com/oleiade/reflections v1.1.0 h1:D+I/UsXQB4esMathlt0kkZRJZdUDmhv5zGi/HOwYTWo= github.com/oleiade/reflections v1.1.0/go.mod h1:mCxx0QseeVCHs5Um5HhJeCKVC7AwS8kO67tky4rdisA= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -874,8 +872,6 @@ github.com/redis/go-redis/extra/redisotel/v9 v9.5.3 h1:kuvuJL/+MZIEdvtb/kTBRiRgY github.com/redis/go-redis/extra/redisotel/v9 v9.5.3/go.mod h1:7f/FMrf5RRRVHXgfk7CzSVzXHiWeuOQUu2bsVqWoa+g= github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= -github.com/regclient/regclient v0.7.2 h1:vcldDAwBMLtighYVMeb6qNt5+0hKg3AN2IkCc0JIJNM= -github.com/regclient/regclient v0.7.2/go.mod h1:QlA7W9/pvmbblOXM4d49JgfuOTwVXcUMKt3bFuOSVIQ= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=