From 13a585240ab863f0d4e2bbb31b4eb7d2065326e3 Mon Sep 17 00:00:00 2001 From: Rafael Matias Date: Wed, 2 Oct 2024 15:18:20 +0200 Subject: [PATCH 01/22] feat: support auth from docker config --- .../docker/docker_manager/docker_auth.go | 98 +++++++++++++++++++ .../docker/docker_manager/docker_manager.go | 15 +++ 2 files changed, 113 insertions(+) create mode 100644 container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go new file mode 100644 index 0000000000..bffda4d18c --- /dev/null +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go @@ -0,0 +1,98 @@ +package docker_manager + +import ( + "bytes" + "encoding/json" + "fmt" + "os" + "os/exec" + "strings" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/registry" + dockerregistry "github.com/docker/docker/registry" +) + +// RegistryAuthConfig holds authentication configuration for a container registry +type RegistryAuthConfig struct { + Auths map[string]registry.AuthConfig `json:"auths"` + CredHelpers map[string]string `json:"credHelpers"` + CredsStore string `json:"credsStore"` +} + +// loadDockerAuth loads the authentication configuration from the config.json file located in $DOCKER_CONFIG or ~/.docker +func loadDockerAuth() (RegistryAuthConfig, error) { + configFilePath := os.Getenv("DOCKER_CONFIG") + if configFilePath == "" { + configFilePath = os.Getenv("HOME") + "/.docker/config.json" + } else { + configFilePath = configFilePath + "/config.json" + } + + file, err := os.ReadFile(configFilePath) + if err != nil { + return RegistryAuthConfig{}, fmt.Errorf("error reading Docker config file: %v", err) + } + + var authConfig RegistryAuthConfig + if err := json.Unmarshal(file, &authConfig); err != nil { + return RegistryAuthConfig{}, fmt.Errorf("error unmarshalling Docker config file: %v", err) + } + + return authConfig, nil +} + +// getCredentialsFromStore fetches credentials from a Docker credential helper (credStore) +func getCredentialsFromStore(credHelper string, registryURL string) (types.AuthConfig, error) { + // Prepare the helper command (docker-credential-) + credHelperCmd := "docker-credential-" + credHelper + + // Execute the credential helper to get credentials for the registry + cmd := exec.Command(credHelperCmd, "get") + cmd.Stdin = strings.NewReader(registryURL) + + var out bytes.Buffer + cmd.Stdout = &out + var stderr bytes.Buffer + cmd.Stderr = &stderr + + if err := cmd.Run(); err != nil { + return registry.AuthConfig{}, fmt.Errorf("error executing credential helper %s: %v, %s", credHelperCmd, err, stderr.String()) + } + + // Parse the output (it should return JSON containing "Username" and "Secret") + var creds registry.AuthConfig + if err := json.Unmarshal(out.Bytes(), &creds); err != nil { + return registry.AuthConfig{}, fmt.Errorf("error parsing credentials from store: %v", err) + } + + return creds, nil +} + +// getAuthFromDockerConfig retrieves the auth configuration for a given repository +func getAuthFromDockerConfig(repo string) (registry.AuthConfig, error) { + authConfig, err := loadDockerAuth() + if err != nil { + return registry.AuthConfig{}, err + } + + registryHost := dockerregistry.ConvertToHostname(repo) + + // 1. Check if there is a credHelper for this specific registry + if credHelper, exists := authConfig.CredHelpers[registryHost]; exists { + return getCredentialsFromStore(credHelper, registryHost) + } + + // 2. Check if there is a default credStore for all registries + if authConfig.CredsStore != "" { + return getCredentialsFromStore(authConfig.CredsStore, registryHost) + } + + // 3. Fallback to credentials in "auths" if no credStore is available + if auth, exists := authConfig.Auths[registryHost]; exists { + return auth, nil + } + + // Return an empty AuthConfig if no credentials were found + return registry.AuthConfig{}, nil +} diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go index bd4e771c04..a38cfa0984 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go @@ -2279,6 +2279,21 @@ func pullImage(dockerClient *client.Client, imageName string, registrySpec *imag PrivilegeFunc: nil, Platform: platform, } + + // Try to obtain the auth configuration from the docker config file + authConfig, err := getAuthFromDockerConfig(imageName) + if err != nil { + logrus.Errorf("An error occurred while getting auth config for image: %s: %s", imageName, err.Error()) + } + + authFromConfig, err := registry.EncodeAuthConfig(authConfig) + if err != nil { + logrus.Errorf("An error occurred while encoding auth config for image: %s: %s", imageName, err.Error()) + } else { + imagePullOptions.RegistryAuth = authFromConfig + } + + // If the registry spec is defined, use that for authentication if registrySpec != nil { authConfig := registry.AuthConfig{ Username: registrySpec.GetUsername(), From a6905b7ea68c55cd1aec56e2deb65a6d46bede16 Mon Sep 17 00:00:00 2001 From: Rafael Matias Date: Wed, 2 Oct 2024 15:29:18 +0200 Subject: [PATCH 02/22] try pass linter checks --- .../docker/docker_manager/docker_auth.go | 19 +++++++++---------- .../docker/docker_manager/docker_manager.go | 12 +++++++----- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go index bffda4d18c..2c96910ed1 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go @@ -8,7 +8,6 @@ import ( "os/exec" "strings" - "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/registry" dockerregistry "github.com/docker/docker/registry" ) @@ -43,7 +42,7 @@ func loadDockerAuth() (RegistryAuthConfig, error) { } // getCredentialsFromStore fetches credentials from a Docker credential helper (credStore) -func getCredentialsFromStore(credHelper string, registryURL string) (types.AuthConfig, error) { +func getCredentialsFromStore(credHelper string, registryURL string) (*registry.AuthConfig, error) { // Prepare the helper command (docker-credential-) credHelperCmd := "docker-credential-" + credHelper @@ -57,23 +56,23 @@ func getCredentialsFromStore(credHelper string, registryURL string) (types.AuthC cmd.Stderr = &stderr if err := cmd.Run(); err != nil { - return registry.AuthConfig{}, fmt.Errorf("error executing credential helper %s: %v, %s", credHelperCmd, err, stderr.String()) + return nil, fmt.Errorf("error executing credential helper %s: %v, %s", credHelperCmd, err, stderr.String()) } // Parse the output (it should return JSON containing "Username" and "Secret") var creds registry.AuthConfig if err := json.Unmarshal(out.Bytes(), &creds); err != nil { - return registry.AuthConfig{}, fmt.Errorf("error parsing credentials from store: %v", err) + return nil, fmt.Errorf("error parsing credentials from store: %v", err) } - return creds, nil + return &creds, nil } // getAuthFromDockerConfig retrieves the auth configuration for a given repository -func getAuthFromDockerConfig(repo string) (registry.AuthConfig, error) { +func getAuthFromDockerConfig(repo string) (*registry.AuthConfig, error) { authConfig, err := loadDockerAuth() if err != nil { - return registry.AuthConfig{}, err + return nil, err } registryHost := dockerregistry.ConvertToHostname(repo) @@ -90,9 +89,9 @@ func getAuthFromDockerConfig(repo string) (registry.AuthConfig, error) { // 3. Fallback to credentials in "auths" if no credStore is available if auth, exists := authConfig.Auths[registryHost]; exists { - return auth, nil + return &auth, nil } - // Return an empty AuthConfig if no credentials were found - return registry.AuthConfig{}, nil + // Return no AuthConfig if no credentials were found + return nil, nil } diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go index a38cfa0984..dd8dac1ef5 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go @@ -2286,11 +2286,13 @@ func pullImage(dockerClient *client.Client, imageName string, registrySpec *imag logrus.Errorf("An error occurred while getting auth config for image: %s: %s", imageName, err.Error()) } - authFromConfig, err := registry.EncodeAuthConfig(authConfig) - if err != nil { - logrus.Errorf("An error occurred while encoding auth config for image: %s: %s", imageName, err.Error()) - } else { - imagePullOptions.RegistryAuth = authFromConfig + if authConfig != nil { + authFromConfig, err := registry.EncodeAuthConfig(*authConfig) + if err != nil { + logrus.Errorf("An error occurred while encoding auth config for image: %s: %s", imageName, err.Error()) + } else { + imagePullOptions.RegistryAuth = authFromConfig + } } // If the registry spec is defined, use that for authentication From 961d487c399448c2fd98fcffbb846b38ad59c303 Mon Sep 17 00:00:00 2001 From: Rafael Matias Date: Wed, 2 Oct 2024 16:41:12 +0200 Subject: [PATCH 03/22] add tests --- .../docker/docker_manager/docker_auth.go | 32 +++++-- .../docker/docker_manager/docker_auth_test.go | 83 +++++++++++++++++++ .../docker/docker_manager/docker_manager.go | 2 +- 3 files changed, 111 insertions(+), 6 deletions(-) create mode 100644 container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go index 2c96910ed1..571949a264 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go @@ -8,6 +8,7 @@ import ( "os/exec" "strings" + "github.com/davecgh/go-spew/spew" "github.com/docker/docker/api/types/registry" dockerregistry "github.com/docker/docker/registry" ) @@ -59,17 +60,28 @@ func getCredentialsFromStore(credHelper string, registryURL string) (*registry.A return nil, fmt.Errorf("error executing credential helper %s: %v, %s", credHelperCmd, err, stderr.String()) } - // Parse the output (it should return JSON containing "Username" and "Secret") - var creds registry.AuthConfig + // Parse the output (it should return JSON containing "Username", "Secret" and "ServerURL") + creds := struct { + Username string `json:"Username"` + Secret string `json:"Secret"` + ServerURL string `json:"ServerURL"` + }{} + if err := json.Unmarshal(out.Bytes(), &creds); err != nil { return nil, fmt.Errorf("error parsing credentials from store: %v", err) } - return &creds, nil + return ®istry.AuthConfig{ + Username: creds.Username, + Password: creds.Secret, + ServerAddress: creds.ServerURL, + }, nil } -// getAuthFromDockerConfig retrieves the auth configuration for a given repository -func getAuthFromDockerConfig(repo string) (*registry.AuthConfig, error) { +// GetAuthFromDockerConfig retrieves the auth configuration for a given repository +// by checking the Docker config.json file and Docker credential helpers. +// Returns nil if no credentials were found. +func GetAuthFromDockerConfig(repo string) (*registry.AuthConfig, error) { authConfig, err := loadDockerAuth() if err != nil { return nil, err @@ -77,6 +89,16 @@ func getAuthFromDockerConfig(repo string) (*registry.AuthConfig, error) { registryHost := dockerregistry.ConvertToHostname(repo) + spew.Dump(registryHost) + if !strings.Contains(registryHost, ".") || registryHost == "docker.io" || registryHost == "registry-1.docker.io" { + registryHost = "https://index.docker.io/v1/" + } + + // Check if the URL contains "://", meaning it already has a protocol + if !strings.Contains(registryHost, "://") { + registryHost = "https://" + registryHost + } + // 1. Check if there is a credHelper for this specific registry if credHelper, exists := authConfig.CredHelpers[registryHost]; exists { return getCredentialsFromStore(credHelper, registryHost) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go new file mode 100644 index 0000000000..3f6904453e --- /dev/null +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go @@ -0,0 +1,83 @@ +package docker_manager + +import ( + "encoding/base64" + "fmt" + "io/ioutil" + "os" + "testing" + + "github.com/docker/docker/api/types/registry" + "github.com/stretchr/testify/assert" +) + +// WriteStaticConfig writes a static Docker config.json file to a temporary directory +func WriteStaticConfig(t *testing.T, configContent string) string { + tmpDir, err := os.MkdirTemp("", "docker-config") + if err != nil { + t.Fatalf("Failed to create temp directory: %v", err) + } + + configPath := tmpDir + "/config.json" + err = ioutil.WriteFile(configPath, []byte(configContent), 0600) + if err != nil { + t.Fatalf("Failed to write config.json: %v", err) + } + + // Set the DOCKER_CONFIG environment variable to the temp directory + os.Setenv("DOCKER_CONFIG", tmpDir) + return tmpDir +} + +func TestGetAuthConfigForRepoPlain(t *testing.T) { + cfg := ` + { + "auths": { + "https://index.docker.io/v1/": { + "auth": "dXNlcjpwYXNzd29yZA==" + } + } + } + ` + tmpDir := WriteStaticConfig(t, cfg) + defer os.RemoveAll(tmpDir) + + expectedAuth := registry.AuthConfig{ + Username: "user", + Password: "password", + } + encodedAuth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", expectedAuth.Username, expectedAuth.Password))) + + // Test 1: Retrieve auth config for Docker Hub using docker.io domain + authConfig, err := GetAuthFromDockerConfig("docker.io/my-repo/my-image:latest") + assert.NoError(t, err) + assert.Equal(t, encodedAuth, authConfig.Auth, "Auth for Docker Hub should match") + + // Test 2: Retrieve auth config for Docker Hub using no domain + authConfig, err = GetAuthFromDockerConfig("my-repo/my-image:latest") + assert.NoError(t, err) + assert.Equal(t, encodedAuth, authConfig.Auth, "Auth for Docker Hub should match when using no host prefix") + + // Test 3: Retrieve auth config for Docker Hub using full domain and https:// prefix + authConfig, err = GetAuthFromDockerConfig("https://registry-1.docker.io/my-repo/my-image:latest") + assert.NoError(t, err) + assert.Equal(t, encodedAuth, authConfig.Auth, "Auth for Docker Hub should match when using no host prefix") + +} + +func TestGetAuthConfigForRepoOSX(t *testing.T) { + t.Skip("Skipping test that requires macOS keychain") + + cfg := `{ + "auths": { + "https://index.docker.io/v1/": {} + }, + "credsStore": "osxkeychain" + }` + tmpDir := WriteStaticConfig(t, cfg) + defer os.RemoveAll(tmpDir) + + authConfig, err := GetAuthFromDockerConfig("my-repo/my-image:latest") + assert.NoError(t, err) + assert.NotNil(t, authConfig, "Auth config should not be nil") +} diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go index dd8dac1ef5..cad0cbc6d9 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go @@ -2281,7 +2281,7 @@ func pullImage(dockerClient *client.Client, imageName string, registrySpec *imag } // Try to obtain the auth configuration from the docker config file - authConfig, err := getAuthFromDockerConfig(imageName) + authConfig, err := GetAuthFromDockerConfig(imageName) if err != nil { logrus.Errorf("An error occurred while getting auth config for image: %s: %s", imageName, err.Error()) } From 41706c0f3883cf2f7b35b03f946282672d0ca213 Mon Sep 17 00:00:00 2001 From: Rafael Matias Date: Wed, 2 Oct 2024 16:45:01 +0200 Subject: [PATCH 04/22] cleanup spew --- .../lib/backend_impls/docker/docker_manager/docker_auth.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go index 571949a264..8685cddad8 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go @@ -8,7 +8,6 @@ import ( "os/exec" "strings" - "github.com/davecgh/go-spew/spew" "github.com/docker/docker/api/types/registry" dockerregistry "github.com/docker/docker/registry" ) @@ -89,7 +88,6 @@ func GetAuthFromDockerConfig(repo string) (*registry.AuthConfig, error) { registryHost := dockerregistry.ConvertToHostname(repo) - spew.Dump(registryHost) if !strings.Contains(registryHost, ".") || registryHost == "docker.io" || registryHost == "registry-1.docker.io" { registryHost = "https://index.docker.io/v1/" } From 7b029624e88764b7311e8e10d1faa4bfd5b5322d Mon Sep 17 00:00:00 2001 From: Rafael Matias Date: Wed, 2 Oct 2024 16:51:39 +0200 Subject: [PATCH 05/22] linter warnings --- .../lib/backend_impls/docker/docker_manager/docker_auth.go | 3 +++ .../backend_impls/docker/docker_manager/docker_auth_test.go | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go index 8685cddad8..8d3d98dc62 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go @@ -74,6 +74,9 @@ func getCredentialsFromStore(credHelper string, registryURL string) (*registry.A Username: creds.Username, Password: creds.Secret, ServerAddress: creds.ServerURL, + Email: "", + IdentityToken: "", + RegistryToken: "", }, nil } diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go index 3f6904453e..bd38048a59 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go @@ -3,7 +3,6 @@ package docker_manager import ( "encoding/base64" "fmt" - "io/ioutil" "os" "testing" @@ -19,7 +18,7 @@ func WriteStaticConfig(t *testing.T, configContent string) string { } configPath := tmpDir + "/config.json" - err = ioutil.WriteFile(configPath, []byte(configContent), 0600) + err = os.WriteFile(configPath, []byte(configContent), 0600) if err != nil { t.Fatalf("Failed to write config.json: %v", err) } From 2e53e923ce8ff2e20391d05e34fa8248afcbce10 Mon Sep 17 00:00:00 2001 From: Rafael Matias Date: Wed, 2 Oct 2024 16:55:23 +0200 Subject: [PATCH 06/22] linter fixup --- .../lib/backend_impls/docker/docker_manager/docker_auth.go | 1 + 1 file changed, 1 insertion(+) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go index 8d3d98dc62..315adb4100 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go @@ -74,6 +74,7 @@ func getCredentialsFromStore(credHelper string, registryURL string) (*registry.A Username: creds.Username, Password: creds.Secret, ServerAddress: creds.ServerURL, + Auth: "", Email: "", IdentityToken: "", RegistryToken: "", From 41451af098b97a0d28c4746752f200fba2b0a5f9 Mon Sep 17 00:00:00 2001 From: Rafael Matias Date: Wed, 2 Oct 2024 17:03:07 +0200 Subject: [PATCH 07/22] try fix gitguardian complain --- .../docker/docker_manager/docker_auth_test.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go index bd38048a59..73d81d8c49 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go @@ -29,22 +29,25 @@ func WriteStaticConfig(t *testing.T, configContent string) string { } func TestGetAuthConfigForRepoPlain(t *testing.T) { - cfg := ` + expectedAuth := registry.AuthConfig{ + Username: "user", + Password: "password", + } + + base64Auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", expectedAuth.Username, expectedAuth.Password))) + + cfg := fmt.Sprintf(` { "auths": { "https://index.docker.io/v1/": { - "auth": "dXNlcjpwYXNzd29yZA==" + "auth": "%s" } } - } - ` + }`, base64Auth) + tmpDir := WriteStaticConfig(t, cfg) defer os.RemoveAll(tmpDir) - expectedAuth := registry.AuthConfig{ - Username: "user", - Password: "password", - } encodedAuth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", expectedAuth.Username, expectedAuth.Password))) // Test 1: Retrieve auth config for Docker Hub using docker.io domain From 181e6c98e56eb4d496d7dcc236bed87987c96a52 Mon Sep 17 00:00:00 2001 From: Rafael Matias Date: Wed, 2 Oct 2024 17:05:27 +0200 Subject: [PATCH 08/22] add missing auth --- .../lib/backend_impls/docker/docker_manager/docker_auth.go | 3 ++- .../backend_impls/docker/docker_manager/docker_auth_test.go | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go index 315adb4100..13098d3bda 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go @@ -2,6 +2,7 @@ package docker_manager import ( "bytes" + "encoding/base64" "encoding/json" "fmt" "os" @@ -74,7 +75,7 @@ func getCredentialsFromStore(credHelper string, registryURL string) (*registry.A Username: creds.Username, Password: creds.Secret, ServerAddress: creds.ServerURL, - Auth: "", + Auth: base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", creds.Username, creds.Secret))), Email: "", IdentityToken: "", RegistryToken: "", diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go index 73d81d8c49..d5f3591304 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go @@ -34,7 +34,7 @@ func TestGetAuthConfigForRepoPlain(t *testing.T) { Password: "password", } - base64Auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", expectedAuth.Username, expectedAuth.Password))) + encodedAuth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", expectedAuth.Username, expectedAuth.Password))) cfg := fmt.Sprintf(` { @@ -43,13 +43,11 @@ func TestGetAuthConfigForRepoPlain(t *testing.T) { "auth": "%s" } } - }`, base64Auth) + }`, encodedAuth) tmpDir := WriteStaticConfig(t, cfg) defer os.RemoveAll(tmpDir) - encodedAuth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", expectedAuth.Username, expectedAuth.Password))) - // Test 1: Retrieve auth config for Docker Hub using docker.io domain authConfig, err := GetAuthFromDockerConfig("docker.io/my-repo/my-image:latest") assert.NoError(t, err) From 7e2b88ca5996c57c7f08481bf3644ec0364a6f4c Mon Sep 17 00:00:00 2001 From: Rafael Matias Date: Wed, 2 Oct 2024 17:09:48 +0200 Subject: [PATCH 09/22] add example test for pass --- .../docker/docker_manager/docker_auth_test.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go index d5f3591304..a537273faf 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go @@ -81,3 +81,20 @@ func TestGetAuthConfigForRepoOSX(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, authConfig, "Auth config should not be nil") } + +func TestGetAuthConfigForRepoUnix(t *testing.T) { + t.Skip("Skipping test that requires unix `pass` password manager") + + cfg := `{ + "auths": { + "https://index.docker.io/v1/": {} + }, + "credsStore": "pass" + }` + tmpDir := WriteStaticConfig(t, cfg) + defer os.RemoveAll(tmpDir) + + authConfig, err := GetAuthFromDockerConfig("my-repo/my-image:latest") + assert.NoError(t, err) + assert.NotNil(t, authConfig, "Auth config should not be nil") +} From c8254bbdddabdc5dfa1872bfc9740ea64fe7fe16 Mon Sep 17 00:00:00 2001 From: Rafael Matias Date: Wed, 2 Oct 2024 17:18:47 +0200 Subject: [PATCH 10/22] linter happiness --- .../docker/docker_manager/docker_auth_test.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go index a537273faf..ae800a7bb0 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go @@ -6,7 +6,6 @@ import ( "os" "testing" - "github.com/docker/docker/api/types/registry" "github.com/stretchr/testify/assert" ) @@ -29,12 +28,10 @@ func WriteStaticConfig(t *testing.T, configContent string) string { } func TestGetAuthConfigForRepoPlain(t *testing.T) { - expectedAuth := registry.AuthConfig{ - Username: "user", - Password: "password", - } + expectedUser := "user" + expectedPassword := "password" - encodedAuth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", expectedAuth.Username, expectedAuth.Password))) + encodedAuth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", expectedUser, expectedPassword))) cfg := fmt.Sprintf(` { From c63cf5224a18dd093e721b5c5d60194dfe258667 Mon Sep 17 00:00:00 2001 From: Rafael Matias Date: Thu, 24 Oct 2024 20:26:15 +0200 Subject: [PATCH 11/22] generate docker config file for engine container --- .../docker_kurtosis_backend/consts/consts.go | 1 + .../engine_functions/create_engine.go | 28 ++- .../docker_config_storage_creator.go | 184 ++++++++++++++++++ .../docker/docker_manager/docker_auth.go | 56 ++++++ .../docker/docker_manager/docker_auth_test.go | 10 +- .../label_value_consts/label_value_consts.go | 2 + .../object_attributes_provider.go | 31 ++- 7 files changed, 298 insertions(+), 14 deletions(-) create mode 100644 container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/docker_config_storage_creator/docker_config_storage_creator.go diff --git a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/consts/consts.go b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/consts/consts.go index a13632c54e..eef3c9fecf 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/consts/consts.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/consts/consts.go @@ -33,6 +33,7 @@ const ( HttpApplicationProtocol = "http" GitHubAuthStorageDirPath = "/kurtosis-data/github-auth/" + DockerConfigStorageDir = "/root/.docker/" EmptyApplicationURL = "" ) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/create_engine.go b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/create_engine.go index 4b46974fbc..d968856398 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/create_engine.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/create_engine.go @@ -3,9 +3,11 @@ package engine_functions import ( "context" "fmt" - "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/github_auth_storage_creator" "time" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/docker_config_storage_creator" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/github_auth_storage_creator" + "github.com/docker/go-connections/nat" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/consts" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/logs_aggregator_functions" @@ -249,14 +251,34 @@ func CreateEngine( return nil, stacktrace.Propagate(err, "An error occurred creating GitHub auth storage.") } + // Configure Docker Config by writing the provided config files to a volume that's accessible by the engine + dockerConfigStorageVolObjAttrs, err := objAttrsProvider.ForDockerConfigStorageVolume() + if err != nil { + return nil, stacktrace.Propagate(err, "An error occurred retrieving object attributes for GitHub auth storage.") + } + dockerConfigStorageVolNameStr := dockerConfigStorageVolObjAttrs.GetName().GetString() + dockerConfigStorageVolLabelStrs := map[string]string{} + for labelKey, labelValue := range dockerConfigStorageVolObjAttrs.GetLabels() { + dockerConfigStorageVolLabelStrs[labelKey.GetString()] = labelValue.GetString() + } + // This volume is created idempotently (like logs storage volume) and just write the token to the file everytime the engine starts + if err = dockerManager.CreateVolume(ctx, dockerConfigStorageVolNameStr, dockerConfigStorageVolLabelStrs); err != nil { + return nil, stacktrace.Propagate(err, "An error occurred creating Docker config storage volume.") + } + err = docker_config_storage_creator.CreateDockerConfigStorage(ctx, targetNetworkId, dockerConfigStorageVolNameStr, consts.DockerConfigStorageDir, dockerManager) + if err != nil { + return nil, stacktrace.Propagate(err, "An error occurred creating Docker config storage.") + } + bindMounts := map[string]string{ // Necessary so that the engine server can interact with the Docker engine consts.DockerSocketFilepath: consts.DockerSocketFilepath, } volumeMounts := map[string]string{ - logsStorageVolNameStr: logsStorageDirPath, - githubAuthStorageVolNameStr: consts.GitHubAuthStorageDirPath, + logsStorageVolNameStr: logsStorageDirPath, + githubAuthStorageVolNameStr: consts.GitHubAuthStorageDirPath, + dockerConfigStorageVolNameStr: consts.DockerConfigStorageDir, } if serverArgs.OnBastionHost { diff --git a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/docker_config_storage_creator/docker_config_storage_creator.go b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/docker_config_storage_creator/docker_config_storage_creator.go new file mode 100644 index 0000000000..c58e24d703 --- /dev/null +++ b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/docker_config_storage_creator/docker_config_storage_creator.go @@ -0,0 +1,184 @@ +package docker_config_storage_creator + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "time" + + "github.com/docker/docker/api/types/registry" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/docker/docker_manager" + "github.com/kurtosis-tech/stacktrace" + "github.com/sirupsen/logrus" +) + +const ( + // We use this image and version because we already are using this in other projects so there is a high probability + // that the image is in the local machine's cache + creatorContainerImage = "alpine:3.17" + creatorContainerName = "kurtosis-docker-config-storage-creator" + + shBinaryFilepath = "/bin/sh" + shCmdFlag = "-c" + printfCmdName = "printf" + + creationSuccessExitCode = 0 + + creationCmdMaxRetries = 2 + creationCmdDelayInRetries = 200 * time.Millisecond + + configFilePath = "config.json" + + sleepSeconds = 1800 +) + +func CreateDockerConfigStorage( + ctx context.Context, + targetNetworkId string, + volumeName string, + storageDirPath string, + dockerManager *docker_manager.DockerManager, +) error { + entrypointArgs := []string{ + shBinaryFilepath, + shCmdFlag, + fmt.Sprintf("sleep %v", sleepSeconds), + } + + volumeMounts := map[string]string{ + volumeName: storageDirPath, + } + + createAndStartArgs := docker_manager.NewCreateAndStartContainerArgsBuilder( + creatorContainerImage, + creatorContainerName, + targetNetworkId, + ).WithEntrypointArgs( + entrypointArgs, + ).WithVolumeMounts( + volumeMounts, + ).Build() + + containerId, _, err := dockerManager.CreateAndStartContainer(ctx, createAndStartArgs) + if err != nil { + return stacktrace.Propagate(err, "An error occurred starting the Docker Config Storage Creator container with these args '%+v'", createAndStartArgs) + } + //The killing step has to be executed always in the success and also in the failed case + defer func() { + if err = dockerManager.RemoveContainer(context.Background(), containerId); err != nil { + logrus.Errorf( + "Launching the Docker Config Creator container with container ID '%v' didn't complete successfully so we "+ + "tried to remove the container we started, but doing so exited with an error:\n%v", + containerId, + err) + logrus.Errorf("ACTION REQUIRED: You'll need to manually remove the container with ID '%v'!!!!!!", containerId) + } + }() + + if err := storeConfigInVolume( + ctx, + dockerManager, + containerId, + creationCmdMaxRetries, + creationCmdDelayInRetries, + storageDirPath, + ); err != nil { + return stacktrace.Propagate(err, "An error occurred creating Docker config storage in volume.") + } + + return nil +} + +// GetGitHubAuthToken Returns empty string if no token found in [githubAuthTokenFile] or [githubAuthTokenFile] doesn't exist +//func GetGitHubAuthToken() string { +// tokenBytes, err := os.ReadFile(path.Join(consts.GitHubAuthStorageDirPath, configFilePath)) +// if err != nil { +// return "" +// } +// return string(tokenBytes) +//} + +func storeConfigInVolume( + ctx context.Context, + dockerManager *docker_manager.DockerManager, + containerId string, + maxRetries uint, + timeBetweenRetries time.Duration, + storageDirPath string, +) error { + // Get all the registries from the Docker config + registries, err := docker_manager.GetAllRegistriesFromDockerConfig() + if err != nil { + return stacktrace.NewError("An error occurred getting all registries from Docker config: %v", err) + } + + cfg := struct { + Auths map[string]registry.AuthConfig `json:"auths"` + }{ + Auths: make(map[string]registry.AuthConfig), + } + + // Add the auths for each registry + for _, registry := range registries { + creds, err := docker_manager.GetAuthFromDockerConfig(registry) + if err != nil { + return stacktrace.NewError("An error occurred getting auth for registry '%v' from Docker config: %v", registry, err) + } + cfg.Auths[registry] = *creds + } + + b, err := json.Marshal(cfg) + if err != nil { + return stacktrace.NewError("An error occurred marshalling the Docker config into JSON: %v", err) + } + + // Write the config.json to the volume + commandStr := fmt.Sprintf( + "%v '%v' > %v", + printfCmdName, + string(b), + fmt.Sprintf("%s/%s", storageDirPath, configFilePath), + ) + + execCmd := []string{ + shBinaryFilepath, + shCmdFlag, + commandStr, + } + for i := uint(0); i < maxRetries; i++ { + outputBuffer := &bytes.Buffer{} + exitCode, err := dockerManager.RunExecCommand(ctx, containerId, execCmd, outputBuffer) + if err == nil { + if exitCode == creationSuccessExitCode { + logrus.Debugf("The Docker config file was successfully added into the volume.") + return nil + } + logrus.Debugf( + "Docker config storage creation command '%v' returned without a Docker error, but exited with non-%v exit code '%v' and logs:\n%v", + commandStr, + creationSuccessExitCode, + exitCode, + outputBuffer.String(), + ) + } else { + logrus.Debugf( + "Docker config storage creation command '%v' experienced a Docker error:\n%v", + commandStr, + err, + ) + } + + // Tiny optimization to not sleep if we're not going to run the loop again + if i < maxRetries { + time.Sleep(timeBetweenRetries) + } + } + + return stacktrace.NewError( + "The Docker config storage creation didn't return success (as measured by the command '%v') even after retrying %v times with %v between retries", + commandStr, + maxRetries, + timeBetweenRetries, + ) +} diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go index 13098d3bda..c49d1acd5a 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go @@ -42,6 +42,35 @@ func loadDockerAuth() (RegistryAuthConfig, error) { return authConfig, nil } +// getRegistriesFromCredsStore fetches all registries from a Docker credential helper (credStore) +func getRegistriesFromCredsStore(credHelper string) ([]string, error) { + credHelperCmd := "docker-credential-" + credHelper + + cmd := exec.Command(credHelperCmd, "list") + + var out bytes.Buffer + cmd.Stdout = &out + var stderr bytes.Buffer + cmd.Stderr = &stderr + + if err := cmd.Run(); err != nil { + return nil, fmt.Errorf("error executing credential helper %s: %v, %s", credHelperCmd, err, stderr.String()) + } + // Output will look like this: {"https://index.docker.io/v1/":"username"} + var result map[string]string + outStr := out.String() + err := json.Unmarshal([]byte(outStr), &result) + if err != nil { + return nil, fmt.Errorf("error unmarshaling credential helper list output %s: %s, %v", credHelperCmd, outStr, err) + } + + registries := []string{} + for k := range result { + registries = append(registries, k) + } + return registries, nil +} + // getCredentialsFromStore fetches credentials from a Docker credential helper (credStore) func getCredentialsFromStore(credHelper string, registryURL string) (*registry.AuthConfig, error) { // Prepare the helper command (docker-credential-) @@ -120,3 +149,30 @@ func GetAuthFromDockerConfig(repo string) (*registry.AuthConfig, error) { // Return no AuthConfig if no credentials were found return nil, nil } + +// GetAllRegistriesFromDockerConfig retrieves all registries from the Docker config.json file +func GetAllRegistriesFromDockerConfig() ([]string, error) { + authConfig, err := loadDockerAuth() + if err != nil { + return nil, err + } + + var registries []string + for registry := range authConfig.Auths { + registries = append(registries, registry) + } + + for registry := range authConfig.CredHelpers { + registries = append(registries, registry) + } + + if authConfig.CredsStore != "" { + r, err := getRegistriesFromCredsStore(authConfig.CredsStore) + if err != nil { + return nil, err + } + registries = append(registries, r...) + } + + return registries, nil +} diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go index ae800a7bb0..61478a3899 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go @@ -9,8 +9,8 @@ import ( "github.com/stretchr/testify/assert" ) -// WriteStaticConfig writes a static Docker config.json file to a temporary directory -func WriteStaticConfig(t *testing.T, configContent string) string { +// writeStaticConfig writes a static Docker config.json file to a temporary directory +func writeStaticConfig(t *testing.T, configContent string) string { tmpDir, err := os.MkdirTemp("", "docker-config") if err != nil { t.Fatalf("Failed to create temp directory: %v", err) @@ -42,7 +42,7 @@ func TestGetAuthConfigForRepoPlain(t *testing.T) { } }`, encodedAuth) - tmpDir := WriteStaticConfig(t, cfg) + tmpDir := writeStaticConfig(t, cfg) defer os.RemoveAll(tmpDir) // Test 1: Retrieve auth config for Docker Hub using docker.io domain @@ -71,7 +71,7 @@ func TestGetAuthConfigForRepoOSX(t *testing.T) { }, "credsStore": "osxkeychain" }` - tmpDir := WriteStaticConfig(t, cfg) + tmpDir := writeStaticConfig(t, cfg) defer os.RemoveAll(tmpDir) authConfig, err := GetAuthFromDockerConfig("my-repo/my-image:latest") @@ -88,7 +88,7 @@ func TestGetAuthConfigForRepoUnix(t *testing.T) { }, "credsStore": "pass" }` - tmpDir := WriteStaticConfig(t, cfg) + tmpDir := writeStaticConfig(t, cfg) defer os.RemoveAll(tmpDir) authConfig, err := GetAuthFromDockerConfig("my-repo/my-image:latest") diff --git a/container-engine-lib/lib/backend_impls/docker/object_attributes_provider/label_value_consts/label_value_consts.go b/container-engine-lib/lib/backend_impls/docker/object_attributes_provider/label_value_consts/label_value_consts.go index c30e9d1a46..9e48d3ccdb 100644 --- a/container-engine-lib/lib/backend_impls/docker/object_attributes_provider/label_value_consts/label_value_consts.go +++ b/container-engine-lib/lib/backend_impls/docker/object_attributes_provider/label_value_consts/label_value_consts.go @@ -28,6 +28,7 @@ const ( logsStorageVolumeTypeLabelValueStr = "kurtosis-logs-storage" logsCollectorVolumeTypeLabelValueStr = "logs-collector-data" githubAuthStorageVolumeTypeLabelValueStr = "github-auth-storage" + dockerConfigStorageVolumeTypeLabelValueStr = "docker-config-storage" ) // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DO NOT CHANGE THESE VALUES !!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -54,3 +55,4 @@ var PersistentDirectoryVolumeTypeDockerLabelValue = docker_label_value.MustCreat var LogsStorageVolumeTypeDockerLabelValue = docker_label_value.MustCreateNewDockerLabelValue(logsStorageVolumeTypeLabelValueStr) var LogsCollectorVolumeTypeDockerLabelValue = docker_label_value.MustCreateNewDockerLabelValue(logsCollectorVolumeTypeLabelValueStr) var GitHubAuthStorageVolumeTypeDockerLabelValue = docker_label_value.MustCreateNewDockerLabelValue(githubAuthStorageVolumeTypeLabelValueStr) +var DockerConfigStorageVolumeTypeDockerLabelValue = docker_label_value.MustCreateNewDockerLabelValue(dockerConfigStorageVolumeTypeLabelValueStr) diff --git a/container-engine-lib/lib/backend_impls/docker/object_attributes_provider/object_attributes_provider.go b/container-engine-lib/lib/backend_impls/docker/object_attributes_provider/object_attributes_provider.go index 5c9af7fada..20da73b2be 100644 --- a/container-engine-lib/lib/backend_impls/docker/object_attributes_provider/object_attributes_provider.go +++ b/container-engine-lib/lib/backend_impls/docker/object_attributes_provider/object_attributes_provider.go @@ -17,12 +17,13 @@ import ( ) const ( - engineServerNamePrefix = "kurtosis-engine" - logsAggregatorName = "kurtosis-logs-aggregator" - logsStorageVolumeName = "kurtosis-logs-storage" - githubAuthStorageVolumeName = "kurtosis-github-auth-storage" - engineRESTAPIPortStr = "engine-rest-api" - reverseProxyNamePrefix = "kurtosis-reverse-proxy" + engineServerNamePrefix = "kurtosis-engine" + logsAggregatorName = "kurtosis-logs-aggregator" + logsStorageVolumeName = "kurtosis-logs-storage" + githubAuthStorageVolumeName = "kurtosis-github-auth-storage" + dockerConfigStorageVolumeName = "kurtosis-docker-config-storage" + engineRESTAPIPortStr = "engine-rest-api" + reverseProxyNamePrefix = "kurtosis-reverse-proxy" ) type DockerObjectAttributesProvider interface { @@ -38,6 +39,7 @@ type DockerObjectAttributesProvider interface { ForLogsStorageVolume() (DockerObjectAttributes, error) ForReverseProxy(engineGuid engine.EngineGUID) (DockerObjectAttributes, error) ForGitHubAuthStorageVolume() (DockerObjectAttributes, error) + ForDockerConfigStorageVolume() (DockerObjectAttributes, error) } func GetDockerObjectAttributesProvider() DockerObjectAttributesProvider { @@ -172,6 +174,23 @@ func (provider *dockerObjectAttributesProviderImpl) ForGitHubAuthStorageVolume() return objectAttributes, nil } +func (provider *dockerObjectAttributesProviderImpl) ForDockerConfigStorageVolume() (DockerObjectAttributes, error) { + name, err := docker_object_name.CreateNewDockerObjectName(dockerConfigStorageVolumeName) + if err != nil { + return nil, stacktrace.Propagate(err, "An error occurred creating a Docker object name object from string '%v'", dockerConfigStorageVolumeName) + } + + labels := map[*docker_label_key.DockerLabelKey]*docker_label_value.DockerLabelValue{ + docker_label_key.VolumeTypeDockerLabelKey: label_value_consts.DockerConfigStorageVolumeTypeDockerLabelValue, + } + + objectAttributes, err := newDockerObjectAttributesImpl(name, labels) + if err != nil { + return nil, stacktrace.Propagate(err, "An error occurred while creating the ObjectAttributesImpl with the name '%s' and labels '%+v'", name, labels) + } + return objectAttributes, nil +} + func (provider *dockerObjectAttributesProviderImpl) ForReverseProxy(engineGuid engine.EngineGUID) (DockerObjectAttributes, error) { nameStr := strings.Join( From 2b582d49ba90edb49160cda507eddda2b8c38da0 Mon Sep 17 00:00:00 2001 From: Rafael Matias Date: Fri, 25 Oct 2024 10:50:56 +0200 Subject: [PATCH 12/22] add docker config volume to API container --- .../backend_creator/backend_creator.go | 3 ++- .../docker_kurtosis_backend/consts/consts.go | 4 ++-- .../docker_kurtosis_backend.go | 19 +++++++++++++++++++ ...urtosis_backend_api_container_functions.go | 13 ++++++++++--- .../engine_functions/create_engine.go | 4 ++-- .../docker/docker_manager/docker_manager.go | 1 + 6 files changed, 36 insertions(+), 8 deletions(-) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/backend_creator/backend_creator.go b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/backend_creator/backend_creator.go index 86d787d599..3a473b1c0d 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/backend_creator/backend_creator.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/backend_creator/backend_creator.go @@ -3,11 +3,12 @@ package backend_creator import ( "context" "fmt" - "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db" "net" "os" "path" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db" + "github.com/docker/docker/client" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/logs_collector_functions" diff --git a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/consts/consts.go b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/consts/consts.go index eef3c9fecf..8bf4bbefae 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/consts/consts.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/consts/consts.go @@ -32,8 +32,8 @@ const ( NameOfNetworkToStartEngineAndLogServiceContainersIn = "bridge" HttpApplicationProtocol = "http" - GitHubAuthStorageDirPath = "/kurtosis-data/github-auth/" - DockerConfigStorageDir = "/root/.docker/" + GitHubAuthStorageDirPath = "/kurtosis-data/github-auth/" + DockerConfigStorageDirPath = "/root/.docker/" EmptyApplicationURL = "" ) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/docker_kurtosis_backend.go b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/docker_kurtosis_backend.go index d663de40a9..d2af3c2e81 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/docker_kurtosis_backend.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/docker_kurtosis_backend.go @@ -618,3 +618,22 @@ func (backend *DockerKurtosisBackend) getGitHubAuthStorageVolume(ctx context.Con volume := foundVolumes[0] return volume.Name, nil } + +// Guaranteed to either return a Docker config storage volume name or throw an error +func (backend *DockerKurtosisBackend) getDockerConfigStorageVolume(ctx context.Context) (string, error) { + volumeSearchLabels := map[string]string{ + docker_label_key.VolumeTypeDockerLabelKey.GetString(): label_value_consts.DockerConfigStorageVolumeTypeDockerLabelValue.GetString(), + } + foundVolumes, err := backend.dockerManager.GetVolumesByLabels(ctx, volumeSearchLabels) + if err != nil { + return "", stacktrace.Propagate(err, "An error occurred getting Docker config storage volumes matching labels '%+v'", volumeSearchLabels) + } + if len(foundVolumes) > 1 { + return "", stacktrace.NewError("Found multiple Docker config storage volumes. This should never happen") + } + if len(foundVolumes) == 0 { + return "", stacktrace.NewError("No Docker config storage volume found.") + } + volume := foundVolumes[0] + return volume.Name, nil +} diff --git a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/docker_kurtosis_backend_api_container_functions.go b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/docker_kurtosis_backend_api_container_functions.go index a99b180b01..757b79f4ca 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/docker_kurtosis_backend_api_container_functions.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/docker_kurtosis_backend_api_container_functions.go @@ -3,10 +3,11 @@ package docker_kurtosis_backend import ( "context" "encoding/json" - "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_registry_spec" "net" "time" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_registry_spec" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/docker/object_attributes_provider/docker_label_key" "github.com/docker/go-connections/nat" @@ -81,6 +82,11 @@ func (backend *DockerKurtosisBackend) CreateAPIContainer( return nil, stacktrace.Propagate(err, "An error occurred getting the GitHub auth storage volume name.") } + dockerConfigStorageVolumeName, err := backend.getDockerConfigStorageVolume(ctx) + if err != nil { + return nil, stacktrace.Propagate(err, "An error occurred getting the Docker config storage volume name.") + } + // Get the Docker network ID where we'll start the new API container enclaveNetwork, err := backend.getEnclaveNetworkByEnclaveUuid(ctx, enclaveUuid) if err != nil { @@ -191,8 +197,9 @@ func (backend *DockerKurtosisBackend) CreateAPIContainer( } volumeMounts := map[string]string{ - enclaveDataVolumeName: enclaveDataVolumeDirpath, - githubAuthStorageVolumeName: consts.GitHubAuthStorageDirPath, + enclaveDataVolumeName: enclaveDataVolumeDirpath, + githubAuthStorageVolumeName: consts.GitHubAuthStorageDirPath, + dockerConfigStorageVolumeName: consts.DockerConfigStorageDirPath, } labelStrs := map[string]string{} diff --git a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/create_engine.go b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/create_engine.go index d968856398..3096451b91 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/create_engine.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/create_engine.go @@ -265,7 +265,7 @@ func CreateEngine( if err = dockerManager.CreateVolume(ctx, dockerConfigStorageVolNameStr, dockerConfigStorageVolLabelStrs); err != nil { return nil, stacktrace.Propagate(err, "An error occurred creating Docker config storage volume.") } - err = docker_config_storage_creator.CreateDockerConfigStorage(ctx, targetNetworkId, dockerConfigStorageVolNameStr, consts.DockerConfigStorageDir, dockerManager) + err = docker_config_storage_creator.CreateDockerConfigStorage(ctx, targetNetworkId, dockerConfigStorageVolNameStr, consts.DockerConfigStorageDirPath, dockerManager) if err != nil { return nil, stacktrace.Propagate(err, "An error occurred creating Docker config storage.") } @@ -278,7 +278,7 @@ func CreateEngine( volumeMounts := map[string]string{ logsStorageVolNameStr: logsStorageDirPath, githubAuthStorageVolNameStr: consts.GitHubAuthStorageDirPath, - dockerConfigStorageVolNameStr: consts.DockerConfigStorageDir, + dockerConfigStorageVolNameStr: consts.DockerConfigStorageDirPath, } if serverArgs.OnBastionHost { diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go index c59299c67f..cff367eb32 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go @@ -2313,6 +2313,7 @@ func pullImage(dockerClient *client.Client, imageName string, registrySpec *imag imagePullOptions.RegistryAuth = encodedAuthConfig } + out, err := dockerClient.ImagePull(pullImageCtx, imageName, imagePullOptions) if err != nil { return stacktrace.Propagate(err, "Tried pulling image '%v' with platform '%v' but failed", imageName, platform), false From 46498807e328343ce8c522398aacc2c55413c1cd Mon Sep 17 00:00:00 2001 From: Rafael Matias Date: Fri, 25 Oct 2024 11:08:06 +0200 Subject: [PATCH 13/22] cleanup comments --- .../docker_config_storage_creator.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/docker_config_storage_creator/docker_config_storage_creator.go b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/docker_config_storage_creator/docker_config_storage_creator.go index c58e24d703..6d392cbd89 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/docker_config_storage_creator/docker_config_storage_creator.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/docker_config_storage_creator/docker_config_storage_creator.go @@ -90,15 +90,6 @@ func CreateDockerConfigStorage( return nil } -// GetGitHubAuthToken Returns empty string if no token found in [githubAuthTokenFile] or [githubAuthTokenFile] doesn't exist -//func GetGitHubAuthToken() string { -// tokenBytes, err := os.ReadFile(path.Join(consts.GitHubAuthStorageDirPath, configFilePath)) -// if err != nil { -// return "" -// } -// return string(tokenBytes) -//} - func storeConfigInVolume( ctx context.Context, dockerManager *docker_manager.DockerManager, From 3ab25bbdd811a5c5a6be9210ea5351eec2ee8d63 Mon Sep 17 00:00:00 2001 From: Rafael Matias Date: Mon, 28 Oct 2024 09:05:56 +0100 Subject: [PATCH 14/22] more explicit var name --- .../docker_config_storage_creator.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/docker_config_storage_creator/docker_config_storage_creator.go b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/docker_config_storage_creator/docker_config_storage_creator.go index 6d392cbd89..47a4ffd962 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/docker_config_storage_creator/docker_config_storage_creator.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions/docker_config_storage_creator/docker_config_storage_creator.go @@ -119,7 +119,7 @@ func storeConfigInVolume( cfg.Auths[registry] = *creds } - b, err := json.Marshal(cfg) + cfgJsonStr, err := json.Marshal(cfg) if err != nil { return stacktrace.NewError("An error occurred marshalling the Docker config into JSON: %v", err) } @@ -128,7 +128,7 @@ func storeConfigInVolume( commandStr := fmt.Sprintf( "%v '%v' > %v", printfCmdName, - string(b), + string(cfgJsonStr), fmt.Sprintf("%s/%s", storageDirPath, configFilePath), ) From 922f5aa70b2b659d5fbca48d91c06f7645c623e2 Mon Sep 17 00:00:00 2001 From: Rafael Matias Date: Mon, 28 Oct 2024 09:12:27 +0100 Subject: [PATCH 15/22] use const for DOCKER_CONFIG env var --- .../lib/backend_impls/docker/docker_manager/docker_auth.go | 6 +++++- .../backend_impls/docker/docker_manager/docker_auth_test.go | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go index c49d1acd5a..9b2df2a2df 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go @@ -13,6 +13,10 @@ import ( dockerregistry "github.com/docker/docker/registry" ) +const ( + ENV_DOCKER_CONFIG string = "DOCKER_CONFIG" +) + // RegistryAuthConfig holds authentication configuration for a container registry type RegistryAuthConfig struct { Auths map[string]registry.AuthConfig `json:"auths"` @@ -22,7 +26,7 @@ type RegistryAuthConfig struct { // loadDockerAuth loads the authentication configuration from the config.json file located in $DOCKER_CONFIG or ~/.docker func loadDockerAuth() (RegistryAuthConfig, error) { - configFilePath := os.Getenv("DOCKER_CONFIG") + configFilePath := os.Getenv(ENV_DOCKER_CONFIG) if configFilePath == "" { configFilePath = os.Getenv("HOME") + "/.docker/config.json" } else { diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go index 61478a3899..1f328911e2 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth_test.go @@ -23,7 +23,7 @@ func writeStaticConfig(t *testing.T, configContent string) string { } // Set the DOCKER_CONFIG environment variable to the temp directory - os.Setenv("DOCKER_CONFIG", tmpDir) + os.Setenv(ENV_DOCKER_CONFIG, tmpDir) return tmpDir } From 26b26e9b851284c799635f6104b3a0de88c85c8e Mon Sep 17 00:00:00 2001 From: Rafael Matias Date: Mon, 28 Oct 2024 09:16:31 +0100 Subject: [PATCH 16/22] use stacktrace.Propagate instead of fmt.Errorf --- .../docker/docker_manager/docker_auth.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go index 9b2df2a2df..2ca583dc74 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go @@ -11,6 +11,7 @@ import ( "github.com/docker/docker/api/types/registry" dockerregistry "github.com/docker/docker/registry" + "github.com/kurtosis-tech/stacktrace" ) const ( @@ -35,12 +36,12 @@ func loadDockerAuth() (RegistryAuthConfig, error) { file, err := os.ReadFile(configFilePath) if err != nil { - return RegistryAuthConfig{}, fmt.Errorf("error reading Docker config file: %v", err) + return RegistryAuthConfig{}, stacktrace.Propagate(err, "error reading Docker config file") } var authConfig RegistryAuthConfig if err := json.Unmarshal(file, &authConfig); err != nil { - return RegistryAuthConfig{}, fmt.Errorf("error unmarshalling Docker config file: %v", err) + return RegistryAuthConfig{}, stacktrace.Propagate(err, "error unmarshalling Docker config file") } return authConfig, nil @@ -58,14 +59,14 @@ func getRegistriesFromCredsStore(credHelper string) ([]string, error) { cmd.Stderr = &stderr if err := cmd.Run(); err != nil { - return nil, fmt.Errorf("error executing credential helper %s: %v, %s", credHelperCmd, err, stderr.String()) + return nil, stacktrace.Propagate(err, "error executing credential helper %s: %s", credHelperCmd, stderr.String()) } // Output will look like this: {"https://index.docker.io/v1/":"username"} var result map[string]string outStr := out.String() err := json.Unmarshal([]byte(outStr), &result) if err != nil { - return nil, fmt.Errorf("error unmarshaling credential helper list output %s: %s, %v", credHelperCmd, outStr, err) + return nil, stacktrace.Propagate(err, "error unmarshaling credential helper list output %s: %s", credHelperCmd, outStr) } registries := []string{} @@ -90,7 +91,7 @@ func getCredentialsFromStore(credHelper string, registryURL string) (*registry.A cmd.Stderr = &stderr if err := cmd.Run(); err != nil { - return nil, fmt.Errorf("error executing credential helper %s: %v, %s", credHelperCmd, err, stderr.String()) + return nil, stacktrace.Propagate(err, "error executing credential helper %s: %s", credHelperCmd, stderr.String()) } // Parse the output (it should return JSON containing "Username", "Secret" and "ServerURL") @@ -101,7 +102,7 @@ func getCredentialsFromStore(credHelper string, registryURL string) (*registry.A }{} if err := json.Unmarshal(out.Bytes(), &creds); err != nil { - return nil, fmt.Errorf("error parsing credentials from store: %v", err) + return nil, stacktrace.Propagate(err, "error parsing credentials from store") } return ®istry.AuthConfig{ From 1b83250a42cb1a08fc7460533d51d9c05b2f1d66 Mon Sep 17 00:00:00 2001 From: Tedi Mitiku Date: Tue, 29 Oct 2024 13:56:12 +0900 Subject: [PATCH 17/22] use cmd string for err --- .../lib/backend_impls/docker/docker_manager/docker_auth.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go index 2ca583dc74..9fdae1317a 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go @@ -59,14 +59,14 @@ func getRegistriesFromCredsStore(credHelper string) ([]string, error) { cmd.Stderr = &stderr if err := cmd.Run(); err != nil { - return nil, stacktrace.Propagate(err, "error executing credential helper %s: %s", credHelperCmd, stderr.String()) + return nil, stacktrace.Propagate(err, "error executing credential helper '%s': %s", cmd.String(), stderr.String()) } // Output will look like this: {"https://index.docker.io/v1/":"username"} var result map[string]string outStr := out.String() err := json.Unmarshal([]byte(outStr), &result) if err != nil { - return nil, stacktrace.Propagate(err, "error unmarshaling credential helper list output %s: %s", credHelperCmd, outStr) + return nil, stacktrace.Propagate(err, "error unmarshaling credential helper list output '%s': %s", cmd.String(), outStr) } registries := []string{} @@ -91,7 +91,7 @@ func getCredentialsFromStore(credHelper string, registryURL string) (*registry.A cmd.Stderr = &stderr if err := cmd.Run(); err != nil { - return nil, stacktrace.Propagate(err, "error executing credential helper %s: %s", credHelperCmd, stderr.String()) + return nil, stacktrace.Propagate(err, "error executing credential helper '%s' for '%s': %s", cmd.String(), registryURL, stderr.String()) } // Parse the output (it should return JSON containing "Username", "Secret" and "ServerURL") From 31ecf0f3c3cd4756213a473c1a649dd83272656f Mon Sep 17 00:00:00 2001 From: Tedi Mitiku Date: Tue, 29 Oct 2024 14:09:23 +0900 Subject: [PATCH 18/22] return empty auth config if no config.json found --- .../backend_impls/docker/docker_manager/docker_auth.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go index 9fdae1317a..2d7caf244b 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/base64" "encoding/json" + "errors" "fmt" "os" "os/exec" @@ -35,13 +36,16 @@ func loadDockerAuth() (RegistryAuthConfig, error) { } file, err := os.ReadFile(configFilePath) - if err != nil { - return RegistryAuthConfig{}, stacktrace.Propagate(err, "error reading Docker config file") + if errors.Is(err, os.ErrNotExist) { + // If the auth config doesn't exist, return an empty auth config + return RegistryAuthConfig{}, nil + } else if err != nil { + return RegistryAuthConfig{}, stacktrace.Propagate(err, "error reading Docker config file at '%s'", configFilePath) } var authConfig RegistryAuthConfig if err := json.Unmarshal(file, &authConfig); err != nil { - return RegistryAuthConfig{}, stacktrace.Propagate(err, "error unmarshalling Docker config file") + return RegistryAuthConfig{}, stacktrace.Propagate(err, "error unmarshalling Docker config file at '%s'", configFilePath) } return authConfig, nil From 4f923a5112de08752d8a1029a822dd51a370f977 Mon Sep 17 00:00:00 2001 From: Tedi Mitiku Date: Tue, 29 Oct 2024 14:27:20 +0900 Subject: [PATCH 19/22] add debug log --- .../lib/backend_impls/docker/docker_manager/docker_auth.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go index 2d7caf244b..1f3879d7ff 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go @@ -6,6 +6,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/sirupsen/logrus" "os" "os/exec" "strings" @@ -38,6 +39,7 @@ func loadDockerAuth() (RegistryAuthConfig, error) { file, err := os.ReadFile(configFilePath) if errors.Is(err, os.ErrNotExist) { // If the auth config doesn't exist, return an empty auth config + logrus.Debugf("No docker config found at '%s'. Returning empty registry auth config.", configFilePath) return RegistryAuthConfig{}, nil } else if err != nil { return RegistryAuthConfig{}, stacktrace.Propagate(err, "error reading Docker config file at '%s'", configFilePath) From f63af84af7d56a973f0069461703a8b325914d3a Mon Sep 17 00:00:00 2001 From: Tedi Mitiku Date: Tue, 29 Oct 2024 14:38:04 +0900 Subject: [PATCH 20/22] adjust enclave continuity ci test --- .circleci/config.yml | 4 ++-- .../docker/docker_manager/docker_auth.go | 20 +++++++++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 792840db5b..14e78ff810 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -765,9 +765,9 @@ jobs: false fi - run: - name: "Verify Kurtosis cleaned up all its volumes (except for the log storage and github auth storage volumes)" + name: "Verify Kurtosis cleaned up all its volumes (except for the log storage, github auth storage, docker auth config storage volumes)" command: | - if ! [ $(docker volume ls | grep -v kurtosis-logs-collector-vol | grep -v kurtosis-logs-db-vol | tail -n+2 | wc -l ) -eq 2 ]; then + if ! [ $(docker volume ls | grep -v kurtosis-logs-collector-vol | grep -v kurtosis-logs-db-vol | tail -n+2 | wc -l ) -eq 3 ]; then docker volume ls false fi diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go index 1f3879d7ff..e956126d92 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_auth.go @@ -40,19 +40,27 @@ func loadDockerAuth() (RegistryAuthConfig, error) { if errors.Is(err, os.ErrNotExist) { // If the auth config doesn't exist, return an empty auth config logrus.Debugf("No docker config found at '%s'. Returning empty registry auth config.", configFilePath) - return RegistryAuthConfig{}, nil + return emptyRegistryAuthConfig(), nil } else if err != nil { - return RegistryAuthConfig{}, stacktrace.Propagate(err, "error reading Docker config file at '%s'", configFilePath) + return emptyRegistryAuthConfig(), stacktrace.Propagate(err, "error reading Docker config file at '%s'", configFilePath) } var authConfig RegistryAuthConfig if err := json.Unmarshal(file, &authConfig); err != nil { - return RegistryAuthConfig{}, stacktrace.Propagate(err, "error unmarshalling Docker config file at '%s'", configFilePath) + return emptyRegistryAuthConfig(), stacktrace.Propagate(err, "error unmarshalling Docker config file at '%s'", configFilePath) } return authConfig, nil } +func emptyRegistryAuthConfig() RegistryAuthConfig { + return RegistryAuthConfig{ + Auths: map[string]registry.AuthConfig{}, + CredHelpers: map[string]string{}, + CredsStore: "", + } +} + // getRegistriesFromCredsStore fetches all registries from a Docker credential helper (credStore) func getRegistriesFromCredsStore(credHelper string) ([]string, error) { credHelperCmd := "docker-credential-" + credHelper @@ -105,7 +113,11 @@ func getCredentialsFromStore(credHelper string, registryURL string) (*registry.A Username string `json:"Username"` Secret string `json:"Secret"` ServerURL string `json:"ServerURL"` - }{} + }{ + Username: "", + Secret: "", + ServerURL: "", + } if err := json.Unmarshal(out.Bytes(), &creds); err != nil { return nil, stacktrace.Propagate(err, "error parsing credentials from store") From fad66b878215389114f4730e882d949c261530c4 Mon Sep 17 00:00:00 2001 From: Tedi Mitiku Date: Tue, 29 Oct 2024 14:50:12 +0900 Subject: [PATCH 21/22] adjust basic cli ci test --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 14e78ff810..c5f4050679 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1004,9 +1004,9 @@ jobs: false fi - run: - name: "Verify Kurtosis cleaned up all its volumes (except for the log storage and github auth storage volumes)" + name: "Verify Kurtosis cleaned up all its volumes (except for the log storage, github auth storage, docker auth config volumes)" command: | - if ! [ $(docker volume ls | grep -v kurtosis-logs-collector-vol | grep -v kurtosis-logs-db-vol | tail -n+2 | wc -l) -eq 2 ]; then + if ! [ $(docker volume ls | grep -v kurtosis-logs-collector-vol | grep -v kurtosis-logs-db-vol | tail -n+2 | wc -l) -eq 3 ]; then docker volume ls false fi From 7912ab8691cc67143bba988866cff4d94c14fe0b Mon Sep 17 00:00:00 2001 From: Tedi Mitiku Date: Tue, 29 Oct 2024 22:14:03 +0900 Subject: [PATCH 22/22] trigger ci --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c5f4050679..9ff8fbf35c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -765,7 +765,7 @@ jobs: false fi - run: - name: "Verify Kurtosis cleaned up all its volumes (except for the log storage, github auth storage, docker auth config storage volumes)" + name: "Verify Kurtosis cleaned up all its volumes (except for the log storage, github auth storage, docker auth config volumes)" command: | if ! [ $(docker volume ls | grep -v kurtosis-logs-collector-vol | grep -v kurtosis-logs-db-vol | tail -n+2 | wc -l ) -eq 3 ]; then docker volume ls