diff --git a/internal/ocipush/push.go b/internal/oci/push.go similarity index 99% rename from internal/ocipush/push.go rename to internal/oci/push.go index 194a3c1edd7..5aa4f80b353 100644 --- a/internal/ocipush/push.go +++ b/internal/oci/push.go @@ -14,7 +14,7 @@ limitations under the License. */ -package ocipush +package oci import ( "context" diff --git a/internal/oci/resolver.go b/internal/oci/resolver.go new file mode 100644 index 00000000000..744e0b05e9e --- /dev/null +++ b/internal/oci/resolver.go @@ -0,0 +1,72 @@ +/* + Copyright 2023 Docker Compose CLI authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package oci + +import ( + "context" + "io" + + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/remotes/docker" + "github.com/distribution/reference" + "github.com/docker/cli/cli/config/configfile" + "github.com/docker/compose/v2/internal/registry" + spec "github.com/opencontainers/image-spec/specs-go/v1" +) + +// NewResolver setup an OCI Resolver based on docker/cli config to provide registry credentials +func NewResolver(config *configfile.ConfigFile) remotes.Resolver { + return docker.NewResolver(docker.ResolverOptions{ + Hosts: docker.ConfigureDefaultRegistries( + docker.WithAuthorizer(docker.NewDockerAuthorizer( + docker.WithAuthCreds(func(host string) (string, string, error) { + host = registry.GetAuthConfigKey(host) + auth, err := config.GetAuthConfig(host) + if err != nil { + return "", "", err + } + if auth.IdentityToken != "" { + return "", auth.IdentityToken, nil + } + return auth.Username, auth.Password, nil + }), + )), + ), + }) +} + +// Get retrieves a Named OCI resource and returns OCI Descriptor and Manifest +func Get(ctx context.Context, resolver remotes.Resolver, ref reference.Named) (spec.Descriptor, []byte, error) { + _, descriptor, err := resolver.Resolve(ctx, ref.String()) + if err != nil { + return spec.Descriptor{}, nil, err + } + + fetcher, err := resolver.Fetcher(ctx, ref.String()) + if err != nil { + return spec.Descriptor{}, nil, err + } + fetch, err := fetcher.Fetch(ctx, descriptor) + if err != nil { + return spec.Descriptor{}, nil, err + } + content, err := io.ReadAll(fetch) + if err != nil { + return spec.Descriptor{}, nil, err + } + return descriptor, content, nil +} diff --git a/pkg/compose/publish.go b/pkg/compose/publish.go index 623559a92dc..1580858dd0f 100644 --- a/pkg/compose/publish.go +++ b/pkg/compose/publish.go @@ -29,11 +29,9 @@ import ( "github.com/DefangLabs/secret-detector/pkg/secrets" "github.com/compose-spec/compose-go/v2/loader" "github.com/compose-spec/compose-go/v2/types" - "github.com/containerd/containerd/v2/core/remotes/docker" "github.com/distribution/reference" "github.com/docker/cli/cli/command" - "github.com/docker/compose/v2/internal/ocipush" - "github.com/docker/compose/v2/internal/registry" + "github.com/docker/compose/v2/internal/oci" "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/compose/transform" "github.com/docker/compose/v2/pkg/progress" @@ -67,23 +65,7 @@ func (s *composeService) publish(ctx context.Context, project *types.Project, re config := s.dockerCli.ConfigFile() - resolver := docker.NewResolver(docker.ResolverOptions{ - Hosts: docker.ConfigureDefaultRegistries( - docker.WithAuthorizer(docker.NewDockerAuthorizer( - docker.WithAuthCreds(func(host string) (string, string, error) { - host = registry.GetAuthConfigKey(host) - auth, err := config.GetAuthConfig(host) - if err != nil { - return "", "", err - } - if auth.IdentityToken != "" { - return "", auth.IdentityToken, nil - } - return auth.Username, auth.Password, nil - }), - )), - ), - }) + resolver := oci.NewResolver(config) var layers []v1.Descriptor extFiles := map[string]string{} @@ -93,7 +75,7 @@ func (s *composeService) publish(ctx context.Context, project *types.Project, re return err } - layerDescriptor := ocipush.DescriptorForComposeFile(file, data) + layerDescriptor := oci.DescriptorForComposeFile(file, data) layers = append(layers, layerDescriptor) } @@ -113,7 +95,7 @@ func (s *composeService) publish(ctx context.Context, project *types.Project, re return err } - layerDescriptor := ocipush.DescriptorForComposeFile("image-digests.yaml", yaml) + layerDescriptor := oci.DescriptorForComposeFile("image-digests.yaml", yaml) layers = append(layers, layerDescriptor) } @@ -124,7 +106,7 @@ func (s *composeService) publish(ctx context.Context, project *types.Project, re Status: progress.Working, }) if !s.dryRun { - err = ocipush.PushManifest(ctx, resolver, named, layers, options.OCIVersion) + err = oci.PushManifest(ctx, resolver, named, layers, options.OCIVersion) if err != nil { w.Event(progress.Event{ ID: repository, @@ -151,7 +133,7 @@ func processExtends(ctx context.Context, project *types.Project, extFiles map[st return nil, err } - layerDescriptor := ocipush.DescriptorForComposeFile(hash, data) + layerDescriptor := oci.DescriptorForComposeFile(hash, data) layerDescriptor.Annotations["com.docker.compose.extends"] = "true" layers = append(layers, layerDescriptor) } @@ -360,7 +342,7 @@ func envFileLayers(project *types.Project) []v1.Descriptor { // if we can't read the file, skip to the next one continue } - layerDescriptor := ocipush.DescriptorForEnvFile(envFile.Path, f) + layerDescriptor := oci.DescriptorForEnvFile(envFile.Path, f) layers = append(layers, layerDescriptor) } } diff --git a/pkg/remote/oci.go b/pkg/remote/oci.go index 5dff332ef96..2833b3ad177 100644 --- a/pkg/remote/oci.go +++ b/pkg/remote/oci.go @@ -26,11 +26,10 @@ import ( "strings" "github.com/compose-spec/compose-go/v2/loader" + "github.com/containerd/containerd/v2/core/remotes" "github.com/distribution/reference" - "github.com/docker/buildx/store/storeutil" - "github.com/docker/buildx/util/imagetools" "github.com/docker/cli/cli/command" - "github.com/docker/compose/v2/internal/ocipush" + "github.com/docker/compose/v2/internal/oci" v1 "github.com/opencontainers/image-spec/specs-go/v1" ) @@ -88,13 +87,9 @@ func (g ociRemoteLoader) Load(ctx context.Context, path string) (string, error) return "", err } - opt, err := storeutil.GetImageConfig(g.dockerCli, nil) - if err != nil { - return "", err - } - resolver := imagetools.New(opt) + resolver := oci.NewResolver(g.dockerCli.ConfigFile()) - content, descriptor, err := resolver.Get(ctx, ref.String()) + descriptor, content, err := oci.Get(ctx, resolver, ref) if err != nil { return "", err } @@ -128,7 +123,7 @@ func (g ociRemoteLoader) Dir(path string) string { return g.known[path] } -func (g ociRemoteLoader) pullComposeFiles(ctx context.Context, local string, manifest v1.Manifest, ref reference.Named, resolver *imagetools.Resolver) error { //nolint:gocyclo +func (g ociRemoteLoader) pullComposeFiles(ctx context.Context, local string, manifest v1.Manifest, ref reference.Named, resolver remotes.Resolver) error { //nolint:gocyclo err := os.MkdirAll(local, 0o700) if err != nil { return err @@ -139,8 +134,8 @@ func (g ociRemoteLoader) pullComposeFiles(ctx context.Context, local string, man return err } defer f.Close() //nolint:errcheck - if (manifest.ArtifactType != "" && manifest.ArtifactType != ocipush.ComposeProjectArtifactType) || - (manifest.ArtifactType == "" && manifest.Config.MediaType != ocipush.ComposeEmptyConfigMediaType) { + if (manifest.ArtifactType != "" && manifest.ArtifactType != oci.ComposeProjectArtifactType) || + (manifest.ArtifactType == "" && manifest.Config.MediaType != oci.ComposeEmptyConfigMediaType) { return fmt.Errorf("%s is not a compose project OCI artifact, but %s", ref.String(), manifest.ArtifactType) } @@ -149,13 +144,14 @@ func (g ociRemoteLoader) pullComposeFiles(ctx context.Context, local string, man if err != nil { return err } - content, _, err := resolver.Get(ctx, digested.String()) + + _, content, err := oci.Get(ctx, resolver, digested) if err != nil { return err } switch layer.MediaType { - case ocipush.ComposeYAMLMediaType: + case oci.ComposeYAMLMediaType: target := f _, extends := layer.Annotations["com.docker.compose.extends"] if extends { @@ -167,11 +163,11 @@ func (g ociRemoteLoader) pullComposeFiles(ctx context.Context, local string, man if err := writeComposeFile(layer, i, target, content); err != nil { return err } - case ocipush.ComposeEnvFileMediaType: + case oci.ComposeEnvFileMediaType: if err := writeEnvFile(layer, local, content); err != nil { return err } - case ocipush.ComposeEmptyConfigMediaType: + case oci.ComposeEmptyConfigMediaType: } } return nil