Skip to content

Commit 92cdb05

Browse files
committed
Add custom capabilities setting to registry config
Allows a registry mirror to be configured with the "push" capability which can be helpful in some proxy use-cases. Signed-off-by: Will Jordan <[email protected]>
1 parent d5a40ad commit 92cdb05

File tree

3 files changed

+88
-2
lines changed

3 files changed

+88
-2
lines changed

util/resolver/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ type RegistryConfig struct {
77
RootCAs []string `toml:"ca"`
88
KeyPairs []TLSKeyPair `toml:"keypair"`
99
TLSConfigDir []string `toml:"tlsconfigdir"`
10+
Capabilities []string `toml:"capabilities"`
1011
}
1112

1213
type TLSKeyPair struct {

util/resolver/resolver.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package resolver
33
import (
44
"crypto/tls"
55
"crypto/x509"
6+
"fmt"
67
"net"
78
"net/http"
89
"os"
@@ -25,6 +26,25 @@ const (
2526
defaultPath = "/v2"
2627
)
2728

29+
func fillConfigOpts(host string, c config.RegistryConfig, h docker.RegistryHost) (*docker.RegistryHost, error) {
30+
if len(c.Capabilities) > 0 {
31+
h.Capabilities = 0
32+
for _, capability := range c.Capabilities {
33+
switch strings.ToLower(capability) {
34+
case "pull":
35+
h.Capabilities |= docker.HostCapabilityPull
36+
case "resolve":
37+
h.Capabilities |= docker.HostCapabilityResolve
38+
case "push":
39+
h.Capabilities |= docker.HostCapabilityPush
40+
default:
41+
return nil, fmt.Errorf("unknown capability %v", c)
42+
}
43+
}
44+
}
45+
46+
return fillInsecureOpts(host, c, h)
47+
}
2848
func fillInsecureOpts(host string, c config.RegistryConfig, h docker.RegistryHost) (*docker.RegistryHost, error) {
2949
tc, err := loadTLSConfig(c)
3050
if err != nil {
@@ -134,7 +154,7 @@ func NewRegistryConfig(m map[string]config.RegistryConfig) docker.RegistryHosts
134154
for _, rawMirror := range c.Mirrors {
135155
h := newMirrorRegistryHost(rawMirror)
136156
mirrorHost := h.Host
137-
host, err := fillInsecureOpts(mirrorHost, m[mirrorHost], h)
157+
host, err := fillConfigOpts(mirrorHost, m[mirrorHost], h)
138158
if err != nil {
139159
return nil, err
140160
}
@@ -154,7 +174,7 @@ func NewRegistryConfig(m map[string]config.RegistryConfig) docker.RegistryHosts
154174
Capabilities: docker.HostCapabilityPush | docker.HostCapabilityPull | docker.HostCapabilityResolve,
155175
}
156176

157-
hosts, err := fillInsecureOpts(host, c, h)
177+
hosts, err := fillConfigOpts(host, c, h)
158178
if err != nil {
159179
return nil, err
160180
}

util/resolver/resolver_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"path"
66
"testing"
77

8+
"github.com/containerd/containerd/v2/core/remotes/docker"
89
"github.com/moby/buildkit/cmd/buildkitd/config"
910
"github.com/stretchr/testify/require"
1011
)
@@ -66,3 +67,67 @@ mirrors = ["https://url/", "https://url/path/"]
6667
}
6768
}
6869
}
70+
71+
func TestNewRegistryConfig(t *testing.T) {
72+
const testConfig = `
73+
[registry."docker.io"]
74+
mirrors = ["yourmirror.local", "proxy.local:5000/proxy.docker.io"]
75+
76+
[registry."yourmirror.local"]
77+
http = true
78+
79+
[registry."proxy.local:5000"]
80+
capabilities = ["pull", "resolve", "push"]
81+
`
82+
83+
tests := map[string]struct {
84+
description string
85+
http bool
86+
capabilities docker.HostCapabilities
87+
mirrors []string
88+
scheme string
89+
path string
90+
}{
91+
"registry-1.docker.io": {
92+
description: "valid_docker_io_with_mirrors",
93+
mirrors: []string{"yourmirror.local", "proxy.local:5000", "registry-1.docker.io"},
94+
scheme: "https",
95+
path: defaultPath,
96+
capabilities: docker.HostCapabilityPull | docker.HostCapabilityResolve | docker.HostCapabilityPush,
97+
},
98+
"yourmirror.local": {
99+
description: "http_mirror",
100+
scheme: "http",
101+
path: defaultPath,
102+
capabilities: docker.HostCapabilityPull | docker.HostCapabilityResolve,
103+
},
104+
"proxy.local:5000": {
105+
description: "proxy_push_mirror",
106+
scheme: "https",
107+
path: path.Join(defaultPath, "proxy.docker.io"),
108+
capabilities: docker.HostCapabilityPull | docker.HostCapabilityResolve | docker.HostCapabilityPush,
109+
},
110+
}
111+
112+
cfg, err := config.Load(bytes.NewBuffer([]byte(testConfig)))
113+
require.NoError(t, err)
114+
115+
require.NotEqual(t, 0, len(cfg.Registries))
116+
registryHosts := NewRegistryConfig(cfg.Registries)
117+
require.NotNil(t, registryHosts)
118+
hosts, err := registryHosts("docker.io")
119+
require.NoError(t, err)
120+
hostnames := make([]string, 0, len(hosts))
121+
for _, host := range hosts {
122+
test := tests[host.Host]
123+
desc := test.description
124+
t.Run(desc, func(t *testing.T) {
125+
hostnames = append(hostnames, host.Host)
126+
require.NotNil(t, test, "unexpected registry host: %s", host.Host)
127+
require.Equal(t, test.capabilities, host.Capabilities)
128+
require.Equal(t, test.scheme, host.Scheme)
129+
require.Equal(t, test.path, host.Path)
130+
})
131+
}
132+
require.Equal(t, tests["registry-1.docker.io"].mirrors, hostnames)
133+
}

0 commit comments

Comments
 (0)