Skip to content

Commit

Permalink
Cleanup legacy mirror string to registry host
Browse files Browse the repository at this point in the history
Move the conversion to its own function and add unit tests.

Signed-off-by: Derek McGowan <derek@mcg.dev>
  • Loading branch information
dmcgowan committed May 13, 2024
1 parent e3b7590 commit 336126a
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 33 deletions.
74 changes: 41 additions & 33 deletions daemon/hosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,29 +50,7 @@ func (daemon *Daemon) mergeLegacyConfig(host string, hosts []docker.RegistryHost
}
sc := daemon.registryService.ServiceConfig()
if host == "docker.io" && len(sc.Mirrors) > 0 {
var mirrorHosts []docker.RegistryHost
for _, mirror := range sc.Mirrors {
h := hosts[0]
h.Capabilities = docker.HostCapabilityPull | docker.HostCapabilityResolve

u, err := url.Parse(mirror)
if err != nil || u.Host == "" {
u, err = url.Parse(fmt.Sprintf("//%s", mirror))
}
if err == nil && u.Host != "" {
h.Host = u.Host
h.Path = strings.TrimRight(u.Path, "/")
if !strings.HasSuffix(h.Path, defaultPath) {
h.Path = path.Join(defaultPath, h.Path)
}
} else {
h.Host = mirror
h.Path = defaultPath
}

mirrorHosts = append(mirrorHosts, h)
}
hosts = append(mirrorHosts, hosts[0])
hosts = mirrorsToRegistryHosts(sc.Mirrors, hosts[0])
}
hostDir := hostconfig.HostDirFromRoot(registry.CertsDir())
for i := range hosts {
Expand All @@ -93,20 +71,50 @@ func (daemon *Daemon) mergeLegacyConfig(host string, hosts []docker.RegistryHost
}
}
if daemon.registryService.IsInsecureRegistry(hosts[i].Host) {
if t.TLSClientConfig != nil {
t.TLSClientConfig.InsecureSkipVerify = true
} else {
t.TLSClientConfig = &tls.Config{
InsecureSkipVerify: true,
}
if t.TLSClientConfig == nil {
t.TLSClientConfig = &tls.Config{} //nolint: gosec // G402: TLS MinVersion too low.
}
t.TLSClientConfig.InsecureSkipVerify = true

hosts[i].Client.Transport = docker.NewHTTPFallback(hosts[i].Client.Transport)
}
}
return hosts, nil
}

func mirrorsToRegistryHosts(mirrors []string, dHost docker.RegistryHost) []docker.RegistryHost {
var mirrorHosts []docker.RegistryHost
for _, mirror := range mirrors {
h := dHost
h.Capabilities = docker.HostCapabilityPull | docker.HostCapabilityResolve

u, err := url.Parse(mirror)
if err != nil || u.Host == "" {
u, err = url.Parse(fmt.Sprintf("dummy://%s", mirror))
}
if err == nil && u.Host != "" {
h.Host = u.Host
h.Path = strings.TrimSuffix(u.Path, "/")

// For compatibility with legacy mirrors, ensure ends with /v2
// NOTE: Use newer configuration to completely override the path
if !strings.HasSuffix(h.Path, defaultPath) {
h.Path = path.Join(h.Path, defaultPath)
}
if u.Scheme != "dummy" {
h.Scheme = u.Scheme
}
} else {
h.Host = mirror
h.Path = defaultPath
}

mirrorHosts = append(mirrorHosts, h)
}
return append(mirrorHosts, dHost)

}

func loadTLSConfig(d string) (*tls.Config, error) {
fs, err := os.ReadDir(d)
if err != nil && !errors.Is(err, os.ErrNotExist) && !errors.Is(err, os.ErrPermission) {
Expand All @@ -121,10 +129,10 @@ func loadTLSConfig(d string) (*tls.Config, error) {
keyPairs []keyPair
)
for _, f := range fs {
if strings.HasSuffix(f.Name(), ".crt") {
switch filepath.Ext(f.Name()) {
case ".crt":
rootCAs = append(rootCAs, filepath.Join(d, f.Name()))
}
if strings.HasSuffix(f.Name(), ".cert") {
case ".cert":
keyPairs = append(keyPairs, keyPair{
Certificate: filepath.Join(d, f.Name()),
Key: filepath.Join(d, strings.TrimSuffix(f.Name(), ".cert")+".key"),
Expand All @@ -150,7 +158,7 @@ func loadTLSConfig(d string) (*tls.Config, error) {
for _, p := range rootCAs {
dt, err := os.ReadFile(p)
if err != nil {
return nil, errors.Wrapf(err, "failed to read %s", p)
return nil, err
}
tc.RootCAs.AppendCertsFromPEM(dt)
}
Expand Down
107 changes: 107 additions & 0 deletions daemon/hosts_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package daemon // import "github.com/docker/docker/daemon"

import (
"testing"

"github.com/containerd/containerd/remotes/docker"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
)

func TestMirrorsToHosts(t *testing.T) {
pullCaps := docker.HostCapabilityPull | docker.HostCapabilityResolve
allCaps := docker.HostCapabilityPull | docker.HostCapabilityResolve | docker.HostCapabilityPush
defaultRegistry := testRegistryHost("https", "registry-1.docker.com", "/v2", allCaps)
for _, tc := range []struct {
mirrors []string
dhost docker.RegistryHost
expected []docker.RegistryHost
}{
{
mirrors: []string{"https://localhost:5000"},
dhost: defaultRegistry,
expected: []docker.RegistryHost{
testRegistryHost("https", "localhost:5000", "/v2", pullCaps),
defaultRegistry,
},
},
{
mirrors: []string{"http://localhost:5000"},
dhost: defaultRegistry,
expected: []docker.RegistryHost{
testRegistryHost("http", "localhost:5000", "/v2", pullCaps),
defaultRegistry,
},
},
{
mirrors: []string{"http://localhost:5000/v2"},
dhost: defaultRegistry,
expected: []docker.RegistryHost{
testRegistryHost("http", "localhost:5000", "/v2", pullCaps),
defaultRegistry,
},
},
{
mirrors: []string{"localhost:5000"},
dhost: defaultRegistry,
expected: []docker.RegistryHost{
testRegistryHost("https", "localhost:5000", "/v2", pullCaps),
defaultRegistry,
},
},
{
mirrors: []string{"localhost:5000/trailingslash/"},
dhost: defaultRegistry,
expected: []docker.RegistryHost{
testRegistryHost("https", "localhost:5000", "/trailingslash/v2", pullCaps),
defaultRegistry,
},
},
{
mirrors: []string{"localhost:5000/2trailingslash//"},
dhost: defaultRegistry,
expected: []docker.RegistryHost{
testRegistryHost("https", "localhost:5000", "/2trailingslash/v2", pullCaps),
defaultRegistry,
},
},
{
mirrors: []string{"localhost:5000/v2/"},
dhost: defaultRegistry,
expected: []docker.RegistryHost{
testRegistryHost("https", "localhost:5000", "/v2", pullCaps),
defaultRegistry,
},
},
{
mirrors: []string{"localhost:5000/base"},
dhost: defaultRegistry,
expected: []docker.RegistryHost{
testRegistryHost("https", "localhost:5000", "/base/v2", pullCaps),
defaultRegistry,
},
},
{
// Legacy mirror configuration always appended /v2, keep functionality the same
mirrors: []string{"localhost:5000/v2/base"},
dhost: defaultRegistry,
expected: []docker.RegistryHost{
testRegistryHost("https", "localhost:5000", "/v2/base/v2", pullCaps),
defaultRegistry,
},
},
} {
actual := mirrorsToRegistryHosts(tc.mirrors, tc.dhost)

assert.Check(t, is.DeepEqual(actual, tc.expected))
}
}

func testRegistryHost(scheme, host, path string, caps docker.HostCapabilities) docker.RegistryHost {
return docker.RegistryHost{
Host: host,
Scheme: scheme,
Path: path,
Capabilities: caps,
}
}

0 comments on commit 336126a

Please sign in to comment.