ソースを参照

use containerd client for OCI operations

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 3 ヶ月 前
コミット
fa08127456
4 ファイル変更92 行追加42 行削除
  1. 1 1
      internal/oci/push.go
  2. 72 0
      internal/oci/resolver.go
  3. 7 25
      pkg/compose/publish.go
  4. 12 16
      pkg/remote/oci.go

+ 1 - 1
internal/ocipush/push.go → internal/oci/push.go

@@ -14,7 +14,7 @@
    limitations under the License.
 */
 
-package ocipush
+package oci
 
 import (
 	"context"

+ 72 - 0
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
+}

+ 7 - 25
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)
 		}
 	}

+ 12 - 16
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