diff --git a/util/resolver/config/config.go b/util/resolver/config/config.go index 125255037b6d..dc660aa95872 100644 --- a/util/resolver/config/config.go +++ b/util/resolver/config/config.go @@ -7,6 +7,7 @@ type RegistryConfig struct { RootCAs []string `toml:"ca"` KeyPairs []TLSKeyPair `toml:"keypair"` TLSConfigDir []string `toml:"tlsconfigdir"` + Capabilities []string `toml:"capabilities"` } type TLSKeyPair struct { diff --git a/util/resolver/resolver.go b/util/resolver/resolver.go index 8308299c109f..adcc28f790ef 100644 --- a/util/resolver/resolver.go +++ b/util/resolver/resolver.go @@ -25,6 +25,25 @@ const ( defaultPath = "/v2" ) +func fillConfigOpts(host string, c config.RegistryConfig, h docker.RegistryHost) (*docker.RegistryHost, error) { + if len(c.Capabilities) > 0 { + h.Capabilities = 0 + for _, capability := range c.Capabilities { + switch strings.ToLower(capability) { + case "pull": + h.Capabilities |= docker.HostCapabilityPull + case "resolve": + h.Capabilities |= docker.HostCapabilityResolve + case "push": + h.Capabilities |= docker.HostCapabilityPush + default: + return nil, errors.Errorf("unknown capability %v", c) + } + } + } + + return fillInsecureOpts(host, c, h) +} func fillInsecureOpts(host string, c config.RegistryConfig, h docker.RegistryHost) (*docker.RegistryHost, error) { tc, err := loadTLSConfig(c) if err != nil { @@ -134,7 +153,7 @@ func NewRegistryConfig(m map[string]config.RegistryConfig) docker.RegistryHosts for _, rawMirror := range c.Mirrors { h := newMirrorRegistryHost(rawMirror) mirrorHost := h.Host - host, err := fillInsecureOpts(mirrorHost, m[mirrorHost], h) + host, err := fillConfigOpts(mirrorHost, m[mirrorHost], h) if err != nil { return nil, err } @@ -154,7 +173,7 @@ func NewRegistryConfig(m map[string]config.RegistryConfig) docker.RegistryHosts Capabilities: docker.HostCapabilityPush | docker.HostCapabilityPull | docker.HostCapabilityResolve, } - hosts, err := fillInsecureOpts(host, c, h) + hosts, err := fillConfigOpts(host, c, h) if err != nil { return nil, err } diff --git a/util/resolver/resolver_test.go b/util/resolver/resolver_test.go index ed84508c2d40..b1d7aeb312a3 100644 --- a/util/resolver/resolver_test.go +++ b/util/resolver/resolver_test.go @@ -5,6 +5,7 @@ import ( "path" "testing" + "github.com/containerd/containerd/v2/core/remotes/docker" "github.com/moby/buildkit/cmd/buildkitd/config" "github.com/stretchr/testify/require" ) @@ -66,3 +67,73 @@ mirrors = ["https://url/", "https://url/path/"] } } } + +func TestNewRegistryConfig(t *testing.T) { + const testConfig = ` +[registry."docker.io"] +mirrors = ["yourmirror.local", "proxy.local:5000/proxy.docker.io"] + +[registry."yourmirror.local"] +http = true + +[registry."proxy.local:5000"] +capabilities = ["pull", "resolve", "push"] +` + + pull, resolve, push := docker.HostCapabilityPull, docker.HostCapabilityResolve, docker.HostCapabilityPush + tests := map[string][]struct { + host string + scheme string + path string + capabilities docker.HostCapabilities + }{ + "docker.io": { + { + host: "yourmirror.local", + scheme: "http", + path: defaultPath, + capabilities: pull | resolve, + }, + { + host: "proxy.local:5000", + scheme: "https", + path: path.Join(defaultPath, "proxy.docker.io"), + capabilities: pull | resolve | push, + }, + { + host: "registry-1.docker.io", + scheme: "https", + path: defaultPath, + capabilities: pull | resolve | push, + }, + }, + "yourmirror.local": { + { + host: "yourmirror.local", + scheme: "http", + path: defaultPath, + capabilities: pull | resolve | push, + }, + }, + } + + cfg, err := config.Load(bytes.NewBuffer([]byte(testConfig))) + require.NoError(t, err) + + require.NotEqual(t, 0, len(cfg.Registries)) + registryHosts := NewRegistryConfig(cfg.Registries) + require.NotNil(t, registryHosts) + + for hostname, testHost := range tests { + hosts, err := registryHosts(hostname) + require.NoError(t, err) + require.Equal(t, len(testHost), len(hosts)) + for i, host := range hosts { + test := testHost[i] + require.Equal(t, test.host, host.Host) + require.Equal(t, test.capabilities, host.Capabilities) + require.Equal(t, test.scheme, host.Scheme) + require.Equal(t, test.path, host.Path) + } + } +}