Przeglądaj źródła

introduce --insecure-registry, reserved for testing purpose

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 1 miesiąc temu
rodzic
commit
7eb5adeef6

+ 17 - 11
cmd/compose/compose.go

@@ -131,16 +131,17 @@ func Adapt(fn Command) func(cmd *cobra.Command, args []string) error {
 }
 
 type ProjectOptions struct {
-	ProjectName   string
-	Profiles      []string
-	ConfigPaths   []string
-	WorkDir       string
-	ProjectDir    string
-	EnvFiles      []string
-	Compatibility bool
-	Progress      string
-	Offline       bool
-	All           bool
+	ProjectName        string
+	Profiles           []string
+	ConfigPaths        []string
+	WorkDir            string
+	ProjectDir         string
+	EnvFiles           []string
+	Compatibility      bool
+	Progress           string
+	Offline            bool
+	All                bool
+	insecureRegistries []string
 }
 
 // ProjectFunc does stuff within a types.Project
@@ -216,6 +217,8 @@ func (o *ProjectOptions) addProjectFlags(f *pflag.FlagSet) {
 	f.StringArrayVar(&o.Profiles, "profile", []string{}, "Specify a profile to enable")
 	f.StringVarP(&o.ProjectName, "project-name", "p", "", "Project name")
 	f.StringArrayVarP(&o.ConfigPaths, "file", "f", []string{}, "Compose configuration files")
+	f.StringArrayVar(&o.insecureRegistries, "insecure-registry", []string{}, "Use insecure registry to pull Compose OCI artifacts. Doesn't apply to images")
+	_ = f.MarkHidden("insecure-registry")
 	f.StringArrayVar(&o.EnvFiles, "env-file", defaultStringArrayVar(ComposeEnvFiles), "Specify an alternate environment file")
 	f.StringVar(&o.ProjectDir, "project-directory", "", "Specify an alternate working directory\n(default: the path of the, first specified, Compose file)")
 	f.StringVar(&o.WorkDir, "workdir", "", "DEPRECATED! USE --project-directory INSTEAD.\nSpecify an alternate working directory\n(default: the path of the, first specified, Compose file)")
@@ -337,6 +340,9 @@ func (o *ProjectOptions) ToProject(ctx context.Context, dockerCli command.Cli, b
 		Compatibility:     o.Compatibility,
 		ProjectOptionsFns: po,
 		LoadListeners:     []api.LoadListener{metricsListener},
+		OCI: api.OCIOptions{
+			InsecureRegistries: o.insecureRegistries,
+		},
 	}
 
 	project, err := backend.LoadProject(ctx, loadOpts)
@@ -352,7 +358,7 @@ func (o *ProjectOptions) remoteLoaders(dockerCli command.Cli) []loader.ResourceL
 		return nil
 	}
 	git := remote.NewGitRemoteLoader(dockerCli, o.Offline)
-	oci := remote.NewOCIRemoteLoader(dockerCli, o.Offline)
+	oci := remote.NewOCIRemoteLoader(dockerCli, o.Offline, api.OCIOptions{})
 	return []loader.ResourceLoader{git, oci}
 }
 

+ 5 - 0
cmd/compose/publish.go

@@ -36,6 +36,7 @@ type publishOptions struct {
 	withEnvironment     bool
 	assumeYes           bool
 	app                 bool
+	insecureRegistry    bool
 }
 
 func publishCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *BackendOptions) *cobra.Command {
@@ -56,6 +57,7 @@ func publishCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *Ba
 	flags.BoolVar(&opts.withEnvironment, "with-env", false, "Include environment variables in the published OCI artifact")
 	flags.BoolVarP(&opts.assumeYes, "yes", "y", false, `Assume "yes" as answer to all prompts`)
 	flags.BoolVar(&opts.app, "app", false, "Published compose application (includes referenced images)")
+	flags.BoolVar(&opts.insecureRegistry, "insecure-registry", false, "Use insecure registry")
 	flags.SetNormalizeFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName {
 		// assumeYes was introduced by mistake as `--y`
 		if name == "y" {
@@ -64,6 +66,8 @@ func publishCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *Ba
 		}
 		return pflag.NormalizedName(name)
 	})
+	// Should **only** be used for testing purpose, we don't want to promote use of insecure registries
+	_ = flags.MarkHidden("insecure-registry")
 
 	return cmd
 }
@@ -92,5 +96,6 @@ func runPublish(ctx context.Context, dockerCli command.Cli, backendOptions *Back
 		Application:         opts.app,
 		OCIVersion:          api.OCIVersion(opts.ociVersion),
 		WithEnvironment:     opts.withEnvironment,
+		InsecureRegistry:    opts.insecureRegistry,
 	})
 }

+ 11 - 0
docs/reference/docker_compose.yaml

@@ -139,6 +139,17 @@ options:
       experimentalcli: false
       kubernetes: false
       swarm: false
+    - option: insecure-registry
+      value_type: stringArray
+      default_value: '[]'
+      description: |
+        Use insecure registry to pull Compose OCI artifacts. Doesn't apply to images
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
     - option: no-ansi
       value_type: bool
       default_value: "false"

+ 10 - 0
docs/reference/docker_compose_alpha_publish.yaml

@@ -15,6 +15,16 @@ options:
       experimentalcli: false
       kubernetes: false
       swarm: false
+    - option: insecure-registry
+      value_type: bool
+      default_value: "false"
+      description: Use insecure registry
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
     - option: oci-version
       value_type: string
       description: |

+ 10 - 0
docs/reference/docker_compose_publish.yaml

@@ -15,6 +15,16 @@ options:
       experimentalcli: false
       kubernetes: false
       swarm: false
+    - option: insecure-registry
+      value_type: bool
+      default_value: "false"
+      description: Use insecure registry
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
     - option: oci-version
       value_type: string
       description: |

+ 5 - 6
internal/oci/resolver.go

@@ -20,7 +20,7 @@ import (
 	"context"
 	"io"
 	"net/url"
-	"os"
+	"slices"
 	"strings"
 
 	"github.com/containerd/containerd/v2/core/remotes"
@@ -35,7 +35,7 @@ import (
 )
 
 // NewResolver setup an OCI Resolver based on docker/cli config to provide registry credentials
-func NewResolver(config *configfile.ConfigFile) remotes.Resolver {
+func NewResolver(config *configfile.ConfigFile, insecureRegistries ...string) remotes.Resolver {
 	return docker.NewResolver(docker.ResolverOptions{
 		Hosts: docker.ConfigureDefaultRegistries(
 			docker.WithAuthorizer(docker.NewDockerAuthorizer(
@@ -51,10 +51,9 @@ func NewResolver(config *configfile.ConfigFile) remotes.Resolver {
 					return auth.Username, auth.Password, nil
 				}),
 			)),
-			docker.WithPlainHTTP(func(s string) (bool, error) {
-				// Used for testing **only**
-				_, b := os.LookupEnv("__TEST__INSECURE__REGISTRY__")
-				return b, nil
+			docker.WithPlainHTTP(func(domain string) (bool, error) {
+				// Should be used for testing **only**
+				return slices.Contains(insecureRegistries, domain), nil
 			}),
 		),
 	})

+ 9 - 2
pkg/api/api.go

@@ -69,6 +69,12 @@ type ProjectLoadOptions struct {
 	// All registered listeners will be notified of events.
 	// This is optional - pass nil or empty slice if not needed.
 	LoadListeners []LoadListener
+
+	OCI OCIOptions
+}
+
+type OCIOptions struct {
+	InsecureRegistries []string
 }
 
 // Compose is the API interface one can use to programmatically use docker/compose in a third-party software
@@ -484,8 +490,9 @@ type PublishOptions struct {
 	ResolveImageDigests bool
 	Application         bool
 	WithEnvironment     bool
-
-	OCIVersion OCIVersion
+	OCIVersion          OCIVersion
+	// Use plain HTTP to access registry. Should only be used for testing purpose
+	InsecureRegistry bool
 }
 
 func (e Event) String() string {

+ 5 - 5
pkg/compose/loader.go

@@ -33,7 +33,7 @@ import (
 // It loads and validates a Compose project from configuration files.
 func (s *composeService) LoadProject(ctx context.Context, options api.ProjectLoadOptions) (*types.Project, error) {
 	// Setup remote loaders (Git, OCI)
-	remoteLoaders := s.createRemoteLoaders(options.Offline)
+	remoteLoaders := s.createRemoteLoaders(options)
 
 	projectOptions, err := s.buildProjectOptions(options, remoteLoaders)
 	if err != nil {
@@ -66,12 +66,12 @@ func (s *composeService) LoadProject(ctx context.Context, options api.ProjectLoa
 }
 
 // createRemoteLoaders creates Git and OCI remote loaders if not in offline mode
-func (s *composeService) createRemoteLoaders(offline bool) []loader.ResourceLoader {
-	if offline {
+func (s *composeService) createRemoteLoaders(options api.ProjectLoadOptions) []loader.ResourceLoader {
+	if options.Offline {
 		return nil
 	}
-	git := remote.NewGitRemoteLoader(s.dockerCli, offline)
-	oci := remote.NewOCIRemoteLoader(s.dockerCli, offline)
+	git := remote.NewGitRemoteLoader(s.dockerCli, options.Offline)
+	oci := remote.NewOCIRemoteLoader(s.dockerCli, options.Offline, options.OCI)
 	return []loader.ResourceLoader{git, oci}
 }
 

+ 6 - 1
pkg/compose/publish.go

@@ -89,7 +89,12 @@ func (s *composeService) publish(ctx context.Context, project *types.Project, re
 			return err
 		}
 
-		resolver := oci.NewResolver(s.configFile())
+		var insecureRegistries []string
+		if options.InsecureRegistry {
+			insecureRegistries = append(insecureRegistries, reference.Domain(named))
+		}
+
+		resolver := oci.NewResolver(s.configFile(), insecureRegistries...)
 
 		descriptor, err := oci.PushManifest(ctx, resolver, named, layers, options.OCIVersion)
 		if err != nil {

+ 8 - 10
pkg/e2e/publish_test.go

@@ -186,19 +186,17 @@ func TestPublish(t *testing.T) {
 		c.RunDockerCmd(t, "rm", "--force", registryName)
 	})
 
-	cmd := c.NewDockerComposeCmd(t, "-f", "./fixtures/publish/oci/compose.yaml", "-f", "./fixtures/publish/oci/compose-override.yaml",
-		"-p", projectName, "publish", "--with-env", "--yes", registry+"/test:test")
-	icmd.RunCmd(cmd, func(cmd *icmd.Cmd) {
-		cmd.Env = append(cmd.Env, "__TEST__INSECURE__REGISTRY__=true")
-	}).Assert(t, icmd.Expected{ExitCode: 0})
+	res := c.RunDockerComposeCmd(t, "-f", "./fixtures/publish/oci/compose.yaml", "-f", "./fixtures/publish/oci/compose-override.yaml",
+		"-p", projectName, "publish", "--with-env", "--yes", "--insecure-registry", registry+"/test:test")
+	res.Assert(t, icmd.Expected{ExitCode: 0})
 
 	// docker exec -it compose-e2e-publish-registry tree /var/lib/registry/docker/registry/v2/
 
-	cmd = c.NewDockerComposeCmd(t, "--verbose", "--project-name=oci", "-f", fmt.Sprintf("oci://%s/test:test", registry), "config")
-	res := icmd.RunCmd(cmd, func(cmd *icmd.Cmd) {
-		cmd.Env = append(cmd.Env,
-			"XDG_CACHE_HOME="+t.TempDir(),
-			"__TEST__INSECURE__REGISTRY__=true")
+	cmd := c.NewDockerComposeCmd(t, "--verbose", "--project-name=oci",
+		"--insecure-registry", registry,
+		"-f", fmt.Sprintf("oci://%s/test:test", registry), "config")
+	res = icmd.RunCmd(cmd, func(cmd *icmd.Cmd) {
+		cmd.Env = append(cmd.Env, "XDG_CACHE_HOME="+t.TempDir())
 	})
 	res.Assert(t, icmd.Expected{ExitCode: 0})
 	assert.Equal(t, res.Stdout(), `name: oci

+ 11 - 8
pkg/remote/oci.go

@@ -31,6 +31,7 @@ import (
 	"github.com/distribution/reference"
 	"github.com/docker/cli/cli/command"
 	"github.com/docker/compose/v2/internal/oci"
+	"github.com/docker/compose/v2/pkg/api"
 	spec "github.com/opencontainers/image-spec/specs-go/v1"
 )
 
@@ -76,18 +77,20 @@ func ociRemoteLoaderEnabled() (bool, error) {
 	return true, nil
 }
 
-func NewOCIRemoteLoader(dockerCli command.Cli, offline bool) loader.ResourceLoader {
+func NewOCIRemoteLoader(dockerCli command.Cli, offline bool, options api.OCIOptions) loader.ResourceLoader {
 	return ociRemoteLoader{
-		dockerCli: dockerCli,
-		offline:   offline,
-		known:     map[string]string{},
+		dockerCli:          dockerCli,
+		offline:            offline,
+		known:              map[string]string{},
+		insecureRegistries: options.InsecureRegistries,
 	}
 }
 
 type ociRemoteLoader struct {
-	dockerCli command.Cli
-	offline   bool
-	known     map[string]string
+	dockerCli          command.Cli
+	offline            bool
+	known              map[string]string
+	insecureRegistries []string
 }
 
 func (g ociRemoteLoader) Accept(path string) bool {
@@ -115,7 +118,7 @@ func (g ociRemoteLoader) Load(ctx context.Context, path string) (string, error)
 			return "", err
 		}
 
-		resolver := oci.NewResolver(g.dockerCli.ConfigFile())
+		resolver := oci.NewResolver(g.dockerCli.ConfigFile(), g.insecureRegistries...)
 
 		descriptor, content, err := oci.Get(ctx, resolver, ref)
 		if err != nil {