image/pkg/docker/config/config_test.go

889 lines
24 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package config
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strings"
"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 TestGetPathToAuth(t *testing.T) {
const linux = "linux"
const darwin = "darwin"
uid := fmt.Sprintf("%d", os.Getuid())
// We dont have to override the home directory for this because use of this path does not depend
// on any state of the filesystem.
darwinDefault := filepath.Join(os.Getenv("HOME"), ".config", "containers", "auth.json")
tmpDir, err := ioutil.TempDir("", "TestGetPathToAuth")
require.NoError(t, err)
defer os.RemoveAll(tmpDir)
// Environment is per-process, so this looks very unsafe; actually it seems fine because tests are not
// run in parallel unless they opt in by calling t.Parallel(). So dont do that.
oldXRD, hasXRD := os.LookupEnv("XDG_RUNTIME_DIR")
defer func() {
if hasXRD {
os.Setenv("XDG_RUNTIME_DIR", oldXRD)
} else {
os.Unsetenv("XDG_RUNTIME_DIR")
}
}()
for _, c := range []struct {
sys *types.SystemContext
os string
xrd string
expected string
legacyFormat bool
}{
// Default paths
{&types.SystemContext{}, linux, "", "/run/containers/" + uid + "/auth.json", false},
{&types.SystemContext{}, darwin, "", darwinDefault, false},
{nil, linux, "", "/run/containers/" + uid + "/auth.json", false},
{nil, darwin, "", darwinDefault, false},
// SystemContext overrides
{&types.SystemContext{AuthFilePath: "/absolute/path"}, linux, "", "/absolute/path", false},
{&types.SystemContext{AuthFilePath: "/absolute/path"}, darwin, "", "/absolute/path", false},
{&types.SystemContext{LegacyFormatAuthFilePath: "/absolute/path"}, linux, "", "/absolute/path", true},
{&types.SystemContext{LegacyFormatAuthFilePath: "/absolute/path"}, darwin, "", "/absolute/path", true},
{&types.SystemContext{RootForImplicitAbsolutePaths: "/prefix"}, linux, "", "/prefix/run/containers/" + uid + "/auth.json", false},
{&types.SystemContext{RootForImplicitAbsolutePaths: "/prefix"}, darwin, "", "/prefix/run/containers/" + uid + "/auth.json", false},
// XDG_RUNTIME_DIR defined
{nil, linux, tmpDir, tmpDir + "/containers/auth.json", false},
{nil, darwin, tmpDir, darwinDefault, false},
{nil, linux, tmpDir + "/thisdoesnotexist", "", false},
{nil, darwin, tmpDir + "/thisdoesnotexist", darwinDefault, false},
} {
if c.xrd != "" {
os.Setenv("XDG_RUNTIME_DIR", c.xrd)
} else {
os.Unsetenv("XDG_RUNTIME_DIR")
}
res, lf, err := getPathToAuthWithOS(c.sys, c.os)
if c.expected == "" {
assert.Error(t, err)
} else {
require.NoError(t, err)
assert.Equal(t, c.expected, res)
assert.Equal(t, c.legacyFormat, lf)
}
}
}
func TestGetAuth(t *testing.T) {
origXDG := os.Getenv("XDG_RUNTIME_DIR")
tmpXDGRuntimeDir, err := ioutil.TempDir("", "test_docker_client_get_auth")
if err != nil {
t.Fatal(err)
}
t.Logf("using temporary XDG_RUNTIME_DIR directory: %q", tmpXDGRuntimeDir)
// override XDG_RUNTIME_DIR
os.Setenv("XDG_RUNTIME_DIR", tmpXDGRuntimeDir)
defer func() {
err := os.RemoveAll(tmpXDGRuntimeDir)
if err != nil {
t.Logf("failed to cleanup temporary home directory %q: %v", tmpXDGRuntimeDir, err)
}
os.Setenv("XDG_RUNTIME_DIR", origXDG)
}()
// override PATH for executing credHelper
curtDir, err := os.Getwd()
require.NoError(t, err)
origPath := os.Getenv("PATH")
newPath := fmt.Sprintf("%s:%s", filepath.Join(curtDir, "testdata"), origPath)
os.Setenv("PATH", newPath)
t.Logf("using PATH: %q", newPath)
defer func() {
os.Setenv("PATH", origPath)
}()
tmpHomeDir, err := ioutil.TempDir("", "test_docker_client_get_auth")
if err != nil {
t.Fatal(err)
}
t.Logf("using temporary home directory: %q", tmpHomeDir)
defer func() {
err := os.RemoveAll(tmpHomeDir)
if err != nil {
t.Logf("failed to cleanup temporary home directory %q: %v", tmpHomeDir, err)
}
}()
configDir1 := filepath.Join(tmpXDGRuntimeDir, "containers")
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
configDir1 = filepath.Join(tmpHomeDir, ".config", "containers")
}
if err := os.MkdirAll(configDir1, 0700); err != nil {
t.Fatal(err)
}
configDir2 := filepath.Join(tmpHomeDir, ".docker")
if err := os.MkdirAll(configDir2, 0700); err != nil {
t.Fatal(err)
}
configPaths := [2]string{filepath.Join(configDir1, "auth.json"), filepath.Join(configDir2, "config.json")}
for _, configPath := range configPaths {
for _, tc := range []struct {
name string
ref string
hostname string
path string
expected types.DockerAuthConfig
expectedError error
sys *types.SystemContext
testPreviousAPI bool
}{
{
name: "no auth config",
hostname: "index.docker.io",
testPreviousAPI: true,
},
{
name: "empty hostname",
path: filepath.Join("testdata", "example.json"),
},
{
name: "match one",
hostname: "example.org",
path: filepath.Join("testdata", "example.json"),
expected: types.DockerAuthConfig{
Username: "example",
Password: "org",
},
testPreviousAPI: true,
},
{
name: "match none",
hostname: "registry.example.org",
path: filepath.Join("testdata", "example.json"),
testPreviousAPI: true,
},
{
name: "match docker.io",
hostname: "docker.io",
path: filepath.Join("testdata", "full.json"),
expected: types.DockerAuthConfig{
Username: "docker",
Password: "io",
},
testPreviousAPI: true,
},
{
name: "match docker.io normalized",
hostname: "docker.io",
path: filepath.Join("testdata", "abnormal.json"),
expected: types.DockerAuthConfig{
Username: "index",
Password: "docker.io",
},
testPreviousAPI: true,
},
{
name: "normalize registry",
hostname: "https://example.org/v1",
path: filepath.Join("testdata", "full.json"),
expected: types.DockerAuthConfig{
Username: "example",
Password: "org",
},
testPreviousAPI: true,
},
{
name: "match localhost",
hostname: "http://localhost",
path: filepath.Join("testdata", "full.json"),
expected: types.DockerAuthConfig{
Username: "local",
Password: "host",
},
testPreviousAPI: true,
},
{
name: "match ip",
hostname: "10.10.30.45:5000",
path: filepath.Join("testdata", "full.json"),
expected: types.DockerAuthConfig{
Username: "10.10",
Password: "30.45-5000",
},
testPreviousAPI: true,
},
{
name: "match port",
hostname: "https://localhost:5000",
path: filepath.Join("testdata", "abnormal.json"),
expected: types.DockerAuthConfig{
Username: "local",
Password: "host-5000",
},
testPreviousAPI: true,
},
{
name: "use system context",
hostname: "example.org",
path: filepath.Join("testdata", "example.json"),
expected: types.DockerAuthConfig{
Username: "foo",
Password: "bar",
},
sys: &types.SystemContext{
DockerAuthConfig: &types.DockerAuthConfig{
Username: "foo",
Password: "bar",
},
},
testPreviousAPI: true,
},
{
name: "identity token",
hostname: "example.org",
path: filepath.Join("testdata", "example_identitytoken.json"),
expected: types.DockerAuthConfig{
Username: "00000000-0000-0000-0000-000000000000",
Password: "",
IdentityToken: "some very long identity token",
},
testPreviousAPI: true,
},
{
name: "match none (empty.json)",
hostname: "https://localhost:5000",
path: filepath.Join("testdata", "empty.json"),
testPreviousAPI: true,
},
{
name: "credhelper from registries.conf",
hostname: "registry-a.com",
sys: &types.SystemContext{
SystemRegistriesConfPath: filepath.Join("testdata", "cred-helper.conf"),
SystemRegistriesConfDirPath: filepath.Join("testdata", "IdoNotExist"),
},
expected: types.DockerAuthConfig{
Username: "foo",
Password: "bar",
},
testPreviousAPI: true,
},
{
name: "match ref image",
hostname: "example.org",
ref: "example.org/repo/image:latest",
path: filepath.Join("testdata", "refpath.json"),
expected: types.DockerAuthConfig{
Username: "example",
Password: "org",
},
testPreviousAPI: false,
},
{
name: "match ref repo",
hostname: "example.org",
ref: "example.org/repo",
path: filepath.Join("testdata", "refpath.json"),
expected: types.DockerAuthConfig{
Username: "example",
Password: "org",
},
testPreviousAPI: false,
},
{
name: "match ref host",
hostname: "example.org",
ref: "example.org/image:latest",
path: filepath.Join("testdata", "refpath.json"),
expected: types.DockerAuthConfig{
Username: "local",
Password: "host",
},
testPreviousAPI: false,
},
} {
t.Run(tc.name, func(t *testing.T) {
if err := os.RemoveAll(configPath); err != nil {
t.Fatal(err)
}
if tc.path != "" {
contents, err := ioutil.ReadFile(tc.path)
if err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(configPath, contents, 0640); err != nil {
t.Fatal(err)
}
}
var sys *types.SystemContext
if tc.sys != nil {
sys = tc.sys
}
var ref reference.Named
if tc.ref != "" {
ref, err = reference.ParseNamed(tc.ref)
assert.NoError(t, err)
}
auth, err := getCredentialsWithHomeDir(sys, ref, tc.hostname, tmpHomeDir)
assert.Equal(t, tc.expectedError, err)
assert.Equal(t, tc.expected, auth)
// Test for the previous APIs.
if tc.testPreviousAPI {
username, password, err := getAuthenticationWithHomeDir(sys, tc.hostname, tmpHomeDir)
if tc.expected.IdentityToken != "" {
assert.Equal(t, "", username)
assert.Equal(t, "", password)
assert.Error(t, err)
} else {
assert.Equal(t, tc.expected.Username, username)
assert.Equal(t, tc.expected.Password, password)
assert.Equal(t, tc.expectedError, err)
}
}
require.NoError(t, os.RemoveAll(configPath))
})
}
}
}
func TestGetAuthFromLegacyFile(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "test_docker_client_get_auth")
if err != nil {
t.Fatal(err)
}
t.Logf("using temporary home directory: %q", tmpDir)
defer func() {
err := os.RemoveAll(tmpDir)
if err != nil {
t.Logf("failed to cleanup temporary home directory %q: %v", tmpDir, err)
}
}()
configPath := filepath.Join(tmpDir, ".dockercfg")
contents, err := ioutil.ReadFile(filepath.Join("testdata", "legacy.json"))
if err != nil {
t.Fatal(err)
}
for _, tc := range []struct {
name string
hostname string
expected types.DockerAuthConfig
expectedError error
}{
{
name: "normalize registry",
hostname: "https://docker.io/v1",
expected: types.DockerAuthConfig{
Username: "docker",
Password: "io-legacy",
},
},
{
name: "ignore schema and path",
hostname: "http://index.docker.io/v1",
expected: types.DockerAuthConfig{
Username: "docker",
Password: "io-legacy",
},
},
} {
t.Run(tc.name, func(t *testing.T) {
if err := ioutil.WriteFile(configPath, contents, 0640); err != nil {
t.Fatal(err)
}
auth, err := getCredentialsWithHomeDir(nil, nil, tc.hostname, tmpDir)
assert.Equal(t, tc.expectedError, err)
assert.Equal(t, tc.expected, auth)
// Testing for previous APIs
username, password, err := getAuthenticationWithHomeDir(nil, tc.hostname, tmpDir)
assert.Equal(t, tc.expectedError, err)
assert.Equal(t, tc.expected.Username, username)
assert.Equal(t, tc.expected.Password, password)
})
}
}
func TestGetAuthPreferNewConfig(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "test_docker_client_get_auth")
if err != nil {
t.Fatal(err)
}
t.Logf("using temporary home directory: %q", tmpDir)
defer func() {
err := os.RemoveAll(tmpDir)
if err != nil {
t.Logf("failed to cleanup temporary home directory %q: %v", tmpDir, err)
}
}()
configDir := filepath.Join(tmpDir, ".docker")
if err := os.Mkdir(configDir, 0750); err != nil {
t.Fatal(err)
}
for _, data := range []struct {
source string
target string
}{
{
source: filepath.Join("testdata", "full.json"),
target: filepath.Join(configDir, "config.json"),
},
{
source: filepath.Join("testdata", "legacy.json"),
target: filepath.Join(tmpDir, ".dockercfg"),
},
} {
contents, err := ioutil.ReadFile(data.source)
if err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(data.target, contents, 0640); err != nil {
t.Fatal(err)
}
}
auth, err := getCredentialsWithHomeDir(nil, nil, "docker.io", tmpDir)
assert.NoError(t, err)
assert.Equal(t, "docker", auth.Username)
assert.Equal(t, "io", auth.Password)
}
func TestGetAuthFailsOnBadInput(t *testing.T) {
origXDG := os.Getenv("XDG_RUNTIME_DIR")
tmpXDGRuntimeDir, err := ioutil.TempDir("", "test_docker_client_get_auth")
if err != nil {
t.Fatal(err)
}
t.Logf("using temporary XDG_RUNTIME_DIR directory: %q", tmpXDGRuntimeDir)
// override XDG_RUNTIME_DIR
os.Setenv("XDG_RUNTIME_DIR", tmpXDGRuntimeDir)
defer func() {
err := os.RemoveAll(tmpXDGRuntimeDir)
if err != nil {
t.Logf("failed to cleanup temporary home directory %q: %v", tmpXDGRuntimeDir, err)
}
os.Setenv("XDG_RUNTIME_DIR", origXDG)
}()
tmpHomeDir, err := ioutil.TempDir("", "test_docker_client_get_auth")
if err != nil {
t.Fatal(err)
}
t.Logf("using temporary home directory: %q", tmpHomeDir)
defer func() {
err := os.RemoveAll(tmpHomeDir)
if err != nil {
t.Logf("failed to cleanup temporary home directory %q: %v", tmpHomeDir, err)
}
}()
configDir := filepath.Join(tmpXDGRuntimeDir, "containers")
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
configDir = filepath.Join(tmpHomeDir, ".config", "containers")
}
if err := os.MkdirAll(configDir, 0750); err != nil {
t.Fatal(err)
}
configPath := filepath.Join(configDir, "auth.json")
// no config file present
auth, err := getCredentialsWithHomeDir(nil, nil, "index.docker.io", tmpHomeDir)
if err != nil {
t.Fatalf("got unexpected error: %#+v", err)
}
assert.Equal(t, types.DockerAuthConfig{}, auth)
if err := ioutil.WriteFile(configPath, []byte("Json rocks! Unless it doesn't."), 0640); err != nil {
t.Fatalf("failed to write file %q: %v", configPath, err)
}
auth, err = getCredentialsWithHomeDir(nil, nil, "index.docker.io", tmpHomeDir)
if err == nil {
t.Fatalf("got unexpected non-error: username=%q, password=%q", auth.Username, auth.Password)
}
if !strings.Contains(err.Error(), "unmarshaling JSON") {
t.Fatalf("expected JSON syntax error, not: %#+v", err)
}
// remove the invalid config file
os.RemoveAll(configPath)
// no config file present
auth, err = getCredentialsWithHomeDir(nil, nil, "index.docker.io", tmpHomeDir)
if err != nil {
t.Fatalf("got unexpected error: %#+v", err)
}
assert.Equal(t, types.DockerAuthConfig{}, auth)
configPath = filepath.Join(tmpHomeDir, ".dockercfg")
if err := ioutil.WriteFile(configPath, []byte("I'm certainly not a json string."), 0640); err != nil {
t.Fatalf("failed to write file %q: %v", configPath, err)
}
auth, err = getCredentialsWithHomeDir(nil, nil, "index.docker.io", tmpHomeDir)
if err == nil {
t.Fatalf("got unexpected non-error: username=%q, password=%q", auth.Username, auth.Password)
}
if !strings.Contains(err.Error(), "unmarshaling JSON") {
t.Fatalf("expected JSON syntax error, not: %#+v", err)
}
}
func TestGetAllCredentials(t *testing.T) {
// Create a temporary authentication file.
tmpFile, err := ioutil.TempFile("", "auth.json.")
require.NoError(t, err)
_, err = tmpFile.Write([]byte{'{', '}'})
require.NoError(t, err)
err = tmpFile.Close()
require.NoError(t, err)
authFilePath := tmpFile.Name()
// override PATH for executing credHelper
path, err := os.Getwd()
require.NoError(t, err)
origPath := os.Getenv("PATH")
newPath := fmt.Sprintf("%s:%s", filepath.Join(path, "testdata"), origPath)
os.Setenv("PATH", newPath)
t.Logf("using PATH: %q", newPath)
defer func() {
os.Setenv("PATH", origPath)
}()
err = os.Chmod(filepath.Join(path, "testdata", "docker-credential-helper-registry"), os.ModePerm)
require.NoError(t, err)
sys := types.SystemContext{
AuthFilePath: authFilePath,
SystemRegistriesConfPath: filepath.Join("testdata", "cred-helper-with-auth-files.conf"),
SystemRegistriesConfDirPath: filepath.Join("testdata", "IdoNotExist"),
}
data := []struct {
server string
username string
password string
noStore bool
}{
{
server: "example.org",
username: "example-user",
password: "example-password",
},
{
server: "quay.io",
username: "quay-user",
password: "quay-password",
},
{
server: "localhost:5000",
username: "local-user",
password: "local-password",
},
{
server: "registry-a.com",
username: "foo",
password: "bar",
noStore: true,
},
}
// Write the credentials to the authfile.
for _, d := range data {
if d.noStore {
continue
}
err := SetAuthentication(&sys, d.server, d.username, d.password)
require.NoError(t, err)
}
// Now ask for all credentials and make sure that map includes all
// servers and the correct credentials.
authConfigs, err := GetAllCredentials(&sys)
require.NoError(t, err)
require.Equal(t, len(data), len(authConfigs))
for _, d := range data {
conf, exists := authConfigs[d.server]
require.True(t, exists, "%v", d)
require.Equal(t, d.username, conf.Username, "%v", d)
require.Equal(t, d.password, conf.Password, "%v", d)
}
}
func TestAuthKeysForRef(t *testing.T) {
for _, tc := range []struct {
name, ref string
expected []string
}{
{
name: "image without tag",
ref: "quay.io/image",
expected: []string{
"quay.io/image",
"quay.io",
},
},
{
name: "image with tag",
ref: "quay.io/image:latest",
expected: []string{
"quay.io/image",
"quay.io",
},
},
{
name: "image single path tag",
ref: "quay.io/user/image:latest",
expected: []string{
"quay.io/user/image",
"quay.io/user",
"quay.io",
},
},
{
name: "image with nested path",
ref: "quay.io/a/b/c/d/image:latest",
expected: []string{
"quay.io/a/b/c/d/image",
"quay.io/a/b/c/d",
"quay.io/a/b/c",
"quay.io/a/b",
"quay.io/a",
"quay.io",
},
},
} {
ref, err := reference.ParseNamed(tc.ref)
require.NoError(t, err, tc.name)
result := authKeysForRef(ref)
require.Equal(t, tc.expected, result, tc.name)
}
}
func TestSetCredentials(t *testing.T) {
const (
usernamePrefix = "username-"
passwordPrefix = "password-"
)
getAuth := func(sys *types.SystemContext, input string) types.DockerAuthConfig {
ref, err := reference.ParseNamed(input)
require.NoError(t, err)
auth, err := GetCredentialsForRef(sys, ref)
require.NoError(t, err)
return auth
}
for _, tc := range []struct {
input []string
assert func(*types.SystemContext, dockerConfigFile)
}{
{
input: []string{"quay.io"},
assert: func(sys *types.SystemContext, auth dockerConfigFile) {
assert.Len(t, auth.AuthConfigs, 1)
assert.NotEmpty(t, auth.AuthConfigs["quay.io"].Auth)
},
},
{
input: []string{"quay.io/a/b/c/d/image"},
assert: func(sys *types.SystemContext, auth dockerConfigFile) {
assert.Len(t, auth.AuthConfigs, 1)
assert.NotEmpty(t, auth.AuthConfigs["quay.io/a/b/c/d/image"].Auth)
ta := getAuth(sys, "quay.io/a/b/c/d/image")
assert.Equal(t, usernamePrefix+"0", ta.Username)
assert.Equal(t, passwordPrefix+"0", ta.Password)
},
},
{
input: []string{
"quay.io/a/b/c",
"quay.io/a/b",
"quay.io/a",
"quay.io",
"my-registry.local",
"my-registry.local",
},
assert: func(sys *types.SystemContext, auth dockerConfigFile) {
assert.Len(t, auth.AuthConfigs, 5)
assert.NotEmpty(t, auth.AuthConfigs["quay.io/a/b/c"].Auth)
assert.NotEmpty(t, auth.AuthConfigs["quay.io/a/b"].Auth)
assert.NotEmpty(t, auth.AuthConfigs["quay.io/a"].Auth)
assert.NotEmpty(t, auth.AuthConfigs["quay.io"].Auth)
assert.NotEmpty(t, auth.AuthConfigs["my-registry.local"].Auth)
ta0 := getAuth(sys, "quay.io/a/b/c")
assert.Equal(t, usernamePrefix+"0", ta0.Username)
assert.Equal(t, passwordPrefix+"0", ta0.Password)
ta1 := getAuth(sys, "quay.io/a/b")
assert.Equal(t, usernamePrefix+"1", ta1.Username)
assert.Equal(t, passwordPrefix+"1", ta1.Password)
ta2 := getAuth(sys, "quay.io/a")
assert.Equal(t, usernamePrefix+"2", ta2.Username)
assert.Equal(t, passwordPrefix+"2", ta2.Password)
},
},
} {
tmpFile, err := ioutil.TempFile("", "auth.json.set")
require.NoError(t, err)
defer os.RemoveAll(tmpFile.Name())
_, err = tmpFile.WriteString("{}")
require.NoError(t, err)
sys := &types.SystemContext{AuthFilePath: tmpFile.Name()}
for i, input := range tc.input {
_, err := SetCredentials(
sys,
input,
usernamePrefix+fmt.Sprint(i),
passwordPrefix+fmt.Sprint(i),
)
assert.NoError(t, err)
}
auth, err := readJSONFile(tmpFile.Name(), false)
require.NoError(t, err)
tc.assert(sys, auth)
}
}
func TestRemoveAuthentication(t *testing.T) {
testAuth := dockerAuthConfig{Auth: "ZXhhbXBsZTpvcmc="}
for _, tc := range []struct {
config dockerConfigFile
inputs []string
shouldError bool
assert func(dockerConfigFile)
}{
{
config: dockerConfigFile{
AuthConfigs: map[string]dockerAuthConfig{
"quay.io": testAuth,
},
},
inputs: []string{"quay.io"},
assert: func(auth dockerConfigFile) {
assert.Len(t, auth.AuthConfigs, 0)
},
},
{
config: dockerConfigFile{
AuthConfigs: map[string]dockerAuthConfig{
"quay.io": testAuth,
},
},
inputs: []string{"quay.io/user/image"},
shouldError: true, // not logged in
assert: func(auth dockerConfigFile) {
assert.Len(t, auth.AuthConfigs, 1)
assert.NotEmpty(t, auth.AuthConfigs["quay.io"].Auth)
},
},
{
config: dockerConfigFile{
AuthConfigs: map[string]dockerAuthConfig{
"quay.io": testAuth,
"my-registry.local": testAuth,
},
},
inputs: []string{"my-registry.local"},
assert: func(auth dockerConfigFile) {
assert.Len(t, auth.AuthConfigs, 1)
assert.NotEmpty(t, auth.AuthConfigs["quay.io"].Auth)
},
},
{
config: dockerConfigFile{
AuthConfigs: map[string]dockerAuthConfig{
"quay.io/a/b/c": testAuth,
"quay.io/a/b": testAuth,
"quay.io/a": testAuth,
"quay.io": testAuth,
"my-registry.local": testAuth,
},
},
inputs: []string{
"quay.io/a/b",
"quay.io",
"my-registry.local",
},
assert: func(auth dockerConfigFile) {
assert.Len(t, auth.AuthConfigs, 2)
assert.NotEmpty(t, auth.AuthConfigs["quay.io/a/b/c"].Auth)
assert.NotEmpty(t, auth.AuthConfigs["quay.io/a"].Auth)
},
},
} {
content, err := json.Marshal(&tc.config)
require.NoError(t, err)
tmpFile, err := ioutil.TempFile("", "auth.json")
require.NoError(t, err)
defer os.RemoveAll(tmpFile.Name())
_, err = tmpFile.Write(content)
require.NoError(t, err)
sys := &types.SystemContext{AuthFilePath: tmpFile.Name()}
for _, input := range tc.inputs {
err := RemoveAuthentication(sys, input)
if tc.shouldError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
}
auth, err := readJSONFile(tmpFile.Name(), false)
require.NoError(t, err)
tc.assert(auth)
}
}
func TestValidateKey(t *testing.T) {
for _, tc := range []struct {
key string
shouldError bool
isNamespaced bool
}{
{"my-registry.local", false, false},
{"https://my-registry.local", true, false},
{"my-registry.local/path", false, true},
{"quay.io/a/b/c/d", false, true},
} {
isNamespaced, err := validateKey(tc.key)
if tc.shouldError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
assert.Equal(t, tc.isNamespaced, isNamespaced)
}
}