mirror of https://github.com/containers/image.git
634 lines
22 KiB
Go
634 lines
22 KiB
Go
package sysregistriesv2
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/containers/image/v5/docker/reference"
|
|
"github.com/containers/image/v5/types"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestParseLocation(t *testing.T) {
|
|
var err error
|
|
var location string
|
|
|
|
// invalid locations
|
|
_, err = parseLocation("https://example.com")
|
|
assert.NotNil(t, err)
|
|
assert.Contains(t, err.Error(), "invalid location 'https://example.com': URI schemes are not supported")
|
|
|
|
_, err = parseLocation("john.doe@example.com")
|
|
assert.Nil(t, err)
|
|
|
|
// valid locations
|
|
location, err = parseLocation("example.com")
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, "example.com", location)
|
|
|
|
location, err = parseLocation("example.com/") // trailing slashes are stripped
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, "example.com", location)
|
|
|
|
location, err = parseLocation("example.com//////") // trailing slahes are stripped
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, "example.com", location)
|
|
|
|
location, err = parseLocation("example.com:5000/with/path")
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, "example.com:5000/with/path", location)
|
|
}
|
|
|
|
func TestEmptyConfig(t *testing.T) {
|
|
registries, err := GetRegistries(&types.SystemContext{
|
|
SystemRegistriesConfPath: "testdata/empty.conf",
|
|
SystemRegistriesConfDirPath: "testdata/this-does-not-exist",
|
|
})
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 0, len(registries))
|
|
|
|
// When SystemRegistriesConfPath is not explicitly specified (but RootForImplicitAbsolutePaths might be), missing file is treated
|
|
// the same as an empty one, without reporting an error.
|
|
nonexistentRoot, err := filepath.Abs("testdata/this-does-not-exist")
|
|
require.NoError(t, err)
|
|
registries, err = GetRegistries(&types.SystemContext{
|
|
RootForImplicitAbsolutePaths: nonexistentRoot,
|
|
SystemRegistriesConfDirPath: "testdata/this-does-not-exist",
|
|
})
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 0, len(registries))
|
|
}
|
|
|
|
func TestMirrors(t *testing.T) {
|
|
sys := &types.SystemContext{
|
|
SystemRegistriesConfPath: "testdata/mirrors.conf",
|
|
SystemRegistriesConfDirPath: "testdata/this-does-not-exist",
|
|
}
|
|
|
|
registries, err := GetRegistries(sys)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 2, len(registries))
|
|
|
|
reg, err := FindRegistry(sys, "registry.com/image:tag")
|
|
assert.Nil(t, err)
|
|
assert.NotNil(t, reg)
|
|
assert.Equal(t, 2, len(reg.Mirrors))
|
|
assert.Equal(t, "mirror-1.registry.com", reg.Mirrors[0].Location)
|
|
assert.False(t, reg.Mirrors[0].Insecure)
|
|
assert.Equal(t, "mirror-2.registry.com", reg.Mirrors[1].Location)
|
|
assert.True(t, reg.Mirrors[1].Insecure)
|
|
}
|
|
|
|
func TestRefMatchesPrefix(t *testing.T) {
|
|
for _, c := range []struct {
|
|
ref, prefix string
|
|
expected bool
|
|
}{
|
|
// Prefix is a reference.Domain() value
|
|
{"docker.io", "docker.io", true},
|
|
{"docker.io", "example.com", false},
|
|
{"example.com:5000", "example.com:5000", true},
|
|
{"example.com:50000", "example.com:5000", false},
|
|
{"example.com:5000", "example.com", true}, // FIXME FIXME This is unintended and undocumented, don't rely on this behavior
|
|
{"example.com/foo", "example.com", true},
|
|
{"example.com/foo/bar", "example.com", true},
|
|
{"example.com/foo/bar:baz", "example.com", true},
|
|
{"example.com/foo/bar@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "example.com", true},
|
|
// Prefix is a reference.Named.Name() value or a repo namespace
|
|
{"docker.io", "docker.io/library", false},
|
|
{"docker.io/library", "docker.io/library", true},
|
|
{"example.com/library", "docker.io/library", false},
|
|
{"docker.io/libraryy", "docker.io/library", false},
|
|
{"docker.io/library/busybox", "docker.io/library", true},
|
|
{"docker.io", "docker.io/library/busybox", false},
|
|
{"docker.io/library/busybox", "docker.io/library/busybox", true},
|
|
{"example.com/library/busybox", "docker.io/library/busybox", false},
|
|
{"docker.io/library/busybox2", "docker.io/library/busybox", false},
|
|
// Prefix is a single image
|
|
{"example.com", "example.com/foo:bar", false},
|
|
{"example.com/foo", "example.com/foo:bar", false},
|
|
{"example.com/foo:bar", "example.com/foo:bar", true},
|
|
{"example.com/foo:bar2", "example.com/foo:bar", false},
|
|
{"example.com", "example.com/foo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", false},
|
|
{"example.com/foo", "example.com/foo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", false},
|
|
{"example.com/foo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "example.com/foo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", true},
|
|
{"example.com/foo@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "example.com/foo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", false},
|
|
} {
|
|
res := refMatchesPrefix(c.ref, c.prefix)
|
|
assert.Equal(t, c.expected, res, fmt.Sprintf("%s vs. %s", c.ref, c.prefix))
|
|
}
|
|
}
|
|
|
|
func TestConfigPath(t *testing.T) {
|
|
const nondefaultPath = "/this/is/not/the/default/registries.conf"
|
|
const variableReference = "$HOME"
|
|
const rootPrefix = "/root/prefix"
|
|
oldHomeEnv, hasHomeEnv := os.LookupEnv("HOME")
|
|
tempHome, err := ioutil.TempDir("", "tempHome")
|
|
require.NoError(t, err)
|
|
err = os.Setenv("HOME", tempHome)
|
|
require.NoError(t, err)
|
|
defer func() {
|
|
os.RemoveAll(tempHome)
|
|
if hasHomeEnv {
|
|
os.Setenv("HOME", oldHomeEnv)
|
|
} else {
|
|
os.Unsetenv("HOME")
|
|
}
|
|
}()
|
|
var userRegistriesFile = filepath.FromSlash(".config/containers/registries.conf")
|
|
userRegistriesFilePath := filepath.Join(tempHome, userRegistriesFile)
|
|
|
|
for _, c := range []struct {
|
|
sys *types.SystemContext
|
|
userfilePresent bool
|
|
expected string
|
|
}{
|
|
// The common case
|
|
{nil, false, systemRegistriesConfPath},
|
|
// There is a context, but it does not override the path.
|
|
{&types.SystemContext{}, false, systemRegistriesConfPath},
|
|
// Path overridden
|
|
{&types.SystemContext{SystemRegistriesConfPath: nondefaultPath}, false, nondefaultPath},
|
|
// Root overridden
|
|
{
|
|
&types.SystemContext{RootForImplicitAbsolutePaths: rootPrefix},
|
|
false,
|
|
filepath.Join(rootPrefix, systemRegistriesConfPath),
|
|
},
|
|
// Root and path overrides present simultaneously,
|
|
{
|
|
&types.SystemContext{
|
|
RootForImplicitAbsolutePaths: rootPrefix,
|
|
SystemRegistriesConfPath: nondefaultPath,
|
|
},
|
|
false,
|
|
nondefaultPath,
|
|
},
|
|
// User registries file overridden
|
|
{&types.SystemContext{}, true, userRegistriesFilePath},
|
|
// Context and user User registries file preset simultaneously
|
|
{&types.SystemContext{SystemRegistriesConfPath: nondefaultPath}, true, nondefaultPath},
|
|
// Root and user registries file overrides present simultaneously,
|
|
{
|
|
&types.SystemContext{
|
|
RootForImplicitAbsolutePaths: rootPrefix,
|
|
SystemRegistriesConfPath: nondefaultPath,
|
|
},
|
|
true,
|
|
nondefaultPath,
|
|
},
|
|
// No environment expansion happens in the overridden paths
|
|
{&types.SystemContext{SystemRegistriesConfPath: variableReference}, false, variableReference},
|
|
} {
|
|
if c.userfilePresent {
|
|
err := os.MkdirAll(filepath.Dir(userRegistriesFilePath), os.ModePerm)
|
|
require.NoError(t, err)
|
|
f, err := os.Create(userRegistriesFilePath)
|
|
require.NoError(t, err)
|
|
f.Close()
|
|
} else {
|
|
os.Remove(userRegistriesFilePath)
|
|
}
|
|
path := ConfigPath(c.sys)
|
|
assert.Equal(t, c.expected, path)
|
|
}
|
|
}
|
|
|
|
func TestFindRegistry(t *testing.T) {
|
|
sys := &types.SystemContext{
|
|
SystemRegistriesConfPath: "testdata/find-registry.conf",
|
|
SystemRegistriesConfDirPath: "testdata/this-does-not-exist",
|
|
}
|
|
|
|
registries, err := GetRegistries(sys)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 5, len(registries))
|
|
|
|
reg, err := FindRegistry(sys, "simple-prefix.com/foo/bar:latest")
|
|
assert.Nil(t, err)
|
|
assert.NotNil(t, reg)
|
|
assert.Equal(t, "simple-prefix.com", reg.Prefix)
|
|
assert.Equal(t, reg.Location, "registry.com:5000")
|
|
|
|
// path match
|
|
reg, err = FindRegistry(sys, "simple-prefix.com/")
|
|
assert.Nil(t, err)
|
|
assert.NotNil(t, reg)
|
|
|
|
// hostname match
|
|
reg, err = FindRegistry(sys, "simple-prefix.com")
|
|
assert.Nil(t, err)
|
|
assert.NotNil(t, reg)
|
|
|
|
// invalid match
|
|
reg, err = FindRegistry(sys, "simple-prefix.comx")
|
|
assert.Nil(t, err)
|
|
assert.Nil(t, reg)
|
|
|
|
reg, err = FindRegistry(sys, "complex-prefix.com:4000/with/path/and/beyond:tag")
|
|
assert.Nil(t, err)
|
|
assert.NotNil(t, reg)
|
|
assert.Equal(t, "complex-prefix.com:4000/with/path", reg.Prefix)
|
|
assert.Equal(t, "another-registry.com:5000", reg.Location)
|
|
|
|
reg, err = FindRegistry(sys, "no-prefix.com/foo:tag")
|
|
assert.Nil(t, err)
|
|
assert.NotNil(t, reg)
|
|
assert.Equal(t, "no-prefix.com", reg.Prefix)
|
|
assert.Equal(t, "no-prefix.com", reg.Location)
|
|
|
|
reg, err = FindRegistry(sys, "empty-prefix.com/foo:tag")
|
|
assert.Nil(t, err)
|
|
assert.NotNil(t, reg)
|
|
assert.Equal(t, "empty-prefix.com", reg.Prefix)
|
|
assert.Equal(t, "empty-prefix.com", reg.Location)
|
|
|
|
_, err = FindRegistry(&types.SystemContext{SystemRegistriesConfPath: "testdata/this-does-not-exist.conf"}, "example.com")
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func assertRegistryLocationsEqual(t *testing.T, expected []string, regs []Registry) {
|
|
// verify the expected registries and their order
|
|
names := []string{}
|
|
for _, r := range regs {
|
|
names = append(names, r.Location)
|
|
}
|
|
assert.Equal(t, expected, names)
|
|
}
|
|
|
|
func TestFindUnqualifiedSearchRegistries(t *testing.T) {
|
|
sys := &types.SystemContext{
|
|
SystemRegistriesConfPath: "testdata/unqualified-search.conf",
|
|
SystemRegistriesConfDirPath: "testdata/this-does-not-exist",
|
|
}
|
|
|
|
registries, err := GetRegistries(sys)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 4, len(registries))
|
|
|
|
unqRegs, origin, err := UnqualifiedSearchRegistriesWithOrigin(sys)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, []string{"registry-a.com", "registry-c.com", "registry-d.com"}, unqRegs)
|
|
assert.Equal(t, "testdata/unqualified-search.conf", origin)
|
|
|
|
_, err = UnqualifiedSearchRegistries(&types.SystemContext{
|
|
SystemRegistriesConfPath: "testdata/invalid-search.conf",
|
|
SystemRegistriesConfDirPath: "testdata/this-does-not-exist",
|
|
})
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestInvalidV2Configs(t *testing.T) {
|
|
for _, c := range []struct{ path, errorSubstring string }{
|
|
{"testdata/insecure-conflicts.conf", "registry 'registry.com' is defined multiple times with conflicting 'insecure' setting"},
|
|
{"testdata/blocked-conflicts.conf", "registry 'registry.com' is defined multiple times with conflicting 'blocked' setting"},
|
|
{"testdata/missing-registry-location.conf", "invalid location"},
|
|
{"testdata/missing-mirror-location.conf", "invalid location"},
|
|
{"testdata/invalid-prefix.conf", "invalid location"},
|
|
{"testdata/this-does-not-exist.conf", "no such file or directory"},
|
|
} {
|
|
_, err := GetRegistries(&types.SystemContext{SystemRegistriesConfPath: c.path})
|
|
assert.Error(t, err, c.path)
|
|
if c.errorSubstring != "" {
|
|
assert.Contains(t, err.Error(), c.errorSubstring, c.path)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestUnmarshalConfig(t *testing.T) {
|
|
registries, err := GetRegistries(&types.SystemContext{
|
|
SystemRegistriesConfPath: "testdata/unmarshal.conf",
|
|
SystemRegistriesConfDirPath: "testdata/this-does-not-exist",
|
|
})
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 4, len(registries))
|
|
}
|
|
|
|
func TestV1BackwardsCompatibility(t *testing.T) {
|
|
sys := &types.SystemContext{
|
|
SystemRegistriesConfPath: "testdata/v1-compatibility.conf",
|
|
SystemRegistriesConfDirPath: "testdata/this-does-not-exist",
|
|
}
|
|
|
|
registries, err := GetRegistries(sys)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 4, len(registries))
|
|
|
|
unqRegs, err := UnqualifiedSearchRegistries(sys)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, []string{"registry-a.com", "registry-c.com", "registry-d.com"}, unqRegs)
|
|
|
|
// check if merging works
|
|
reg, err := FindRegistry(sys, "registry-b.com/bar/foo/barfoo:latest")
|
|
assert.Nil(t, err)
|
|
assert.NotNil(t, reg)
|
|
assert.True(t, reg.Insecure)
|
|
assert.True(t, reg.Blocked)
|
|
|
|
for _, c := range []string{"testdata/v1-invalid-block.conf", "testdata/v1-invalid-insecure.conf", "testdata/v1-invalid-search.conf"} {
|
|
_, err := GetRegistries(&types.SystemContext{
|
|
SystemRegistriesConfPath: c,
|
|
SystemRegistriesConfDirPath: "testdata/this-does-not-exist",
|
|
})
|
|
assert.Error(t, err, c)
|
|
}
|
|
}
|
|
|
|
func TestMixingV1andV2(t *testing.T) {
|
|
_, err := GetRegistries(&types.SystemContext{
|
|
SystemRegistriesConfPath: "testdata/mixing-v1-v2.conf",
|
|
SystemRegistriesConfDirPath: "testdata/this-does-not-exist",
|
|
})
|
|
assert.NotNil(t, err)
|
|
assert.Contains(t, err.Error(), "mixing sysregistry v1/v2 is not supported")
|
|
}
|
|
|
|
func TestConfigCache(t *testing.T) {
|
|
configFile, err := ioutil.TempFile("", "sysregistriesv2-test")
|
|
require.NoError(t, err)
|
|
defer os.Remove(configFile.Name())
|
|
defer configFile.Close()
|
|
|
|
err = ioutil.WriteFile(configFile.Name(), []byte(`
|
|
[[registry]]
|
|
location = "registry.com"
|
|
|
|
[[registry.mirror]]
|
|
location = "mirror-1.registry.com"
|
|
|
|
[[registry.mirror]]
|
|
location = "mirror-2.registry.com"
|
|
|
|
|
|
[[registry]]
|
|
location = "blocked.registry.com"
|
|
blocked = true
|
|
|
|
|
|
[[registry]]
|
|
location = "insecure.registry.com"
|
|
insecure = true
|
|
|
|
|
|
[[registry]]
|
|
location = "untrusted.registry.com"
|
|
insecure = true`), 0600)
|
|
require.NoError(t, err)
|
|
|
|
ctx := &types.SystemContext{SystemRegistriesConfPath: configFile.Name()}
|
|
|
|
configCache = make(map[configWrapper]*V2RegistriesConf)
|
|
registries, err := GetRegistries(ctx)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 4, len(registries))
|
|
|
|
// empty the config, but use the same SystemContext to show that the
|
|
// previously specified registries are in the cache
|
|
err = ioutil.WriteFile(configFile.Name(), []byte{}, 0600)
|
|
require.NoError(t, err)
|
|
registries, err = GetRegistries(ctx)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 4, len(registries))
|
|
}
|
|
|
|
func TestInvalidateCache(t *testing.T) {
|
|
ctx := &types.SystemContext{SystemRegistriesConfPath: "testdata/invalidate-cache.conf"}
|
|
|
|
configCache = make(map[configWrapper]*V2RegistriesConf)
|
|
registries, err := GetRegistries(ctx)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 4, len(registries))
|
|
assertRegistryLocationsEqual(t, []string{"blocked.registry.com", "insecure.registry.com", "registry.com", "untrusted.registry.com"}, registries)
|
|
|
|
// invalidate the cache, make sure it's empty and reload
|
|
InvalidateCache()
|
|
assert.Equal(t, 0, len(configCache))
|
|
|
|
registries, err = GetRegistries(ctx)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 4, len(registries))
|
|
assertRegistryLocationsEqual(t, []string{"blocked.registry.com", "insecure.registry.com", "registry.com", "untrusted.registry.com"}, registries)
|
|
}
|
|
|
|
func toNamedRef(t *testing.T, ref string) reference.Named {
|
|
parsedRef, err := reference.ParseNamed(ref)
|
|
require.NoError(t, err)
|
|
return parsedRef
|
|
}
|
|
|
|
func TestRewriteReferenceSuccess(t *testing.T) {
|
|
for _, c := range []struct{ inputRef, prefix, location, expected string }{
|
|
// Standard use cases
|
|
{"example.com/image", "example.com", "example.com", "example.com/image"},
|
|
{"example.com/image:latest", "example.com", "example.com", "example.com/image:latest"},
|
|
{"example.com:5000/image", "example.com:5000", "example.com:5000", "example.com:5000/image"},
|
|
{"example.com:5000/image:latest", "example.com:5000", "example.com:5000", "example.com:5000/image:latest"},
|
|
// Separator test ('/', '@', ':')
|
|
{"example.com/foo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
"example.com", "example.com",
|
|
"example.com/foo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
|
|
{"example.com/foo/image:latest", "example.com/foo", "example.com", "example.com/image:latest"},
|
|
{"example.com/foo/image:latest", "example.com/foo", "example.com/path", "example.com/path/image:latest"},
|
|
// Docker examples
|
|
{"docker.io/library/image:latest", "docker.io", "docker.io", "docker.io/library/image:latest"},
|
|
{"docker.io/library/image", "docker.io/library", "example.com", "example.com/image"},
|
|
{"docker.io/library/image", "docker.io", "example.com", "example.com/library/image"},
|
|
{"docker.io/library/prefix/image", "docker.io/library/prefix", "example.com", "example.com/image"},
|
|
} {
|
|
ref := toNamedRef(t, c.inputRef)
|
|
testEndpoint := Endpoint{Location: c.location}
|
|
out, err := testEndpoint.rewriteReference(ref, c.prefix)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, c.expected, out.String())
|
|
}
|
|
}
|
|
|
|
func TestRewriteReferenceFailedDuringParseNamed(t *testing.T) {
|
|
for _, c := range []struct{ inputRef, prefix, location string }{
|
|
// Invalid reference format
|
|
{"example.com/foo/image:latest", "example.com/foo", "example.com/path/"},
|
|
{"example.com/foo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
"example.com/foo", "example.com"},
|
|
{"example.com:5000/image:latest", "example.com", ""},
|
|
{"example.com:5000/image:latest", "example.com", "example.com:5000"},
|
|
// Malformed prefix
|
|
{"example.com/foo/image:latest", "example.com//foo", "example.com/path"},
|
|
{"example.com/image:latest", "image", "anotherimage"},
|
|
{"example.com/foo/image:latest", "example.com/foo/", "example.com"},
|
|
{"example.com/foo/image", "example.com/fo", "example.com/foo"},
|
|
{"example.com/foo:latest", "example.com/fo", "example.com/foo"},
|
|
{"example.com/foo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
"example.com/fo", "example.com/foo"},
|
|
{"docker.io/library/image", "example.com", "example.com"},
|
|
} {
|
|
ref := toNamedRef(t, c.inputRef)
|
|
testEndpoint := Endpoint{Location: c.location}
|
|
out, err := testEndpoint.rewriteReference(ref, c.prefix)
|
|
assert.NotNil(t, err)
|
|
assert.Nil(t, out)
|
|
}
|
|
}
|
|
|
|
func TestPullSourcesFromReference(t *testing.T) {
|
|
sys := &types.SystemContext{
|
|
SystemRegistriesConfPath: "testdata/pull-sources-from-reference.conf",
|
|
SystemRegistriesConfDirPath: "testdata/this-does-not-exist",
|
|
}
|
|
registries, err := GetRegistries(sys)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 2, len(registries))
|
|
|
|
// Registry A allowing any kind of pull from mirrors
|
|
registryA, err := FindRegistry(sys, "registry-a.com/foo/image:latest")
|
|
assert.Nil(t, err)
|
|
assert.NotNil(t, registryA)
|
|
// Digest
|
|
referenceADigest := toNamedRef(t, "registry-a.com/foo/image@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
|
|
pullSources, err := registryA.PullSourcesFromReference(referenceADigest)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 3, len(pullSources))
|
|
assert.Equal(t, "mirror-1.registry-a.com/image@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", pullSources[0].Reference.String())
|
|
assert.True(t, pullSources[1].Endpoint.Insecure)
|
|
// Tag
|
|
referenceATag := toNamedRef(t, "registry-a.com/foo/image:aaa")
|
|
pullSources, err = registryA.PullSourcesFromReference(referenceATag)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 3, len(pullSources))
|
|
assert.Equal(t, "registry-a.com/bar/image:aaa", pullSources[2].Reference.String())
|
|
|
|
// Registry B allowing digests pull only from mirrors
|
|
registryB, err := FindRegistry(sys, "registry-b.com/foo/image:latest")
|
|
assert.Nil(t, err)
|
|
assert.NotNil(t, registryB)
|
|
// Digest
|
|
referenceBDigest := toNamedRef(t, "registry-b.com/foo/image@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
|
|
pullSources, err = registryB.PullSourcesFromReference(referenceBDigest)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 3, len(pullSources))
|
|
assert.Equal(t, "registry-b.com/bar", pullSources[2].Endpoint.Location)
|
|
assert.Equal(t, "registry-b.com/bar/image@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", pullSources[2].Reference.String())
|
|
// Tag
|
|
referenceBTag := toNamedRef(t, "registry-b.com/foo/image:aaa")
|
|
pullSources, err = registryB.PullSourcesFromReference(referenceBTag)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 1, len(pullSources))
|
|
}
|
|
|
|
func TestTryUpdatingCache(t *testing.T) {
|
|
ctx := &types.SystemContext{
|
|
SystemRegistriesConfPath: "testdata/try-update-cache-valid.conf",
|
|
SystemRegistriesConfDirPath: "testdata/this-does-not-exist",
|
|
}
|
|
configCache = make(map[configWrapper]*V2RegistriesConf)
|
|
registries, err := TryUpdatingCache(ctx)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, 1, len(registries.Registries))
|
|
assert.Equal(t, 1, len(configCache))
|
|
|
|
ctxInvalid := &types.SystemContext{
|
|
SystemRegistriesConfPath: "testdata/try-update-cache-invalid.conf",
|
|
SystemRegistriesConfDirPath: "testdata/this-does-not-exist",
|
|
}
|
|
registries, err = TryUpdatingCache(ctxInvalid)
|
|
assert.NotNil(t, err)
|
|
assert.Nil(t, registries)
|
|
assert.Equal(t, 1, len(configCache))
|
|
}
|
|
|
|
func TestRegistriesConfDirectory(t *testing.T) {
|
|
ctx := &types.SystemContext{
|
|
SystemRegistriesConfPath: "testdata/base-for-registries.d.conf",
|
|
SystemRegistriesConfDirPath: "testdata/registries.conf.d",
|
|
}
|
|
|
|
configCache = make(map[configWrapper]*V2RegistriesConf)
|
|
registries, err := TryUpdatingCache(ctx)
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, registries)
|
|
|
|
assert.Equal(t, []string{"example-overwrite.com"}, registries.UnqualifiedSearchRegistries)
|
|
assert.Equal(t, 3, len(registries.Registries))
|
|
assertRegistryLocationsEqual(t, []string{"1.com", "2.com", "base.com"}, registries.Registries)
|
|
|
|
reg, err := FindRegistry(ctx, "base.com/test:latest")
|
|
require.NoError(t, err)
|
|
assert.True(t, reg.Blocked)
|
|
|
|
usrs, origin, err := UnqualifiedSearchRegistriesWithOrigin(ctx)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []string{"example-overwrite.com"}, usrs)
|
|
assert.Equal(t, "testdata/registries.conf.d/config-1.conf", origin)
|
|
}
|
|
|
|
func TestParseShortNameMode(t *testing.T) {
|
|
tests := []struct {
|
|
input string
|
|
result types.ShortNameMode
|
|
mustFail bool
|
|
}{
|
|
{"disabled", types.ShortNameModeDisabled, false},
|
|
{"enforcing", types.ShortNameModeEnforcing, false},
|
|
{"permissive", types.ShortNameModePermissive, false},
|
|
{"", types.ShortNameModePermissive, true},
|
|
{"xxx", -1, true},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
shortName, err := parseShortNameMode(test.input)
|
|
if test.mustFail {
|
|
assert.Error(t, err)
|
|
continue
|
|
}
|
|
require.NoError(t, err)
|
|
assert.Equal(t, test.result, shortName)
|
|
}
|
|
}
|
|
|
|
func TestGetShortNameMode(t *testing.T) {
|
|
tests := []struct {
|
|
path string
|
|
mode types.ShortNameMode
|
|
mustFail bool
|
|
}{
|
|
{
|
|
"testdata/aliases.conf",
|
|
types.ShortNameModeEnforcing,
|
|
false,
|
|
},
|
|
{
|
|
"testdata/registries.conf.d/config-2.conf",
|
|
types.ShortNameModePermissive,
|
|
false,
|
|
},
|
|
{
|
|
"testdata/registries.conf.d/config-3.conf",
|
|
types.ShortNameModePermissive, // empty -> default to permissive
|
|
false,
|
|
},
|
|
{
|
|
"testdata/invalid-short-name-mode.conf",
|
|
-1,
|
|
true,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
sys := &types.SystemContext{
|
|
SystemRegistriesConfPath: test.path,
|
|
SystemRegistriesConfDirPath: "testdata/this-does-not-exist",
|
|
}
|
|
mode, err := GetShortNameMode(sys)
|
|
if test.mustFail {
|
|
assert.Error(t, err)
|
|
continue
|
|
}
|
|
require.NoError(t, err)
|
|
assert.Equal(t, test.mode, mode, "%s", test.path)
|
|
}
|
|
}
|