diff --git a/cli/command/registry/logout.go b/cli/command/registry/logout.go index 16218f67d9a7..8071f4f9dba8 100644 --- a/cli/command/registry/logout.go +++ b/cli/command/registry/logout.go @@ -46,7 +46,9 @@ func runLogout(ctx context.Context, dockerCLI command.Cli, serverAddress string) var isDefaultRegistry bool - if serverAddress == "" { + // login stores Docker Hub creds under the index server for both an empty + // server and an explicit "docker.io". logout has to use the same key. + if serverAddress == "" || serverAddress == registry.DefaultNamespace { serverAddress = registry.IndexServer isDefaultRegistry = true } diff --git a/cli/command/registry/logout_test.go b/cli/command/registry/logout_test.go new file mode 100644 index 000000000000..2e2376ae64f1 --- /dev/null +++ b/cli/command/registry/logout_test.go @@ -0,0 +1,41 @@ +package registry + +import ( + "context" + "path/filepath" + "testing" + + "github.com/docker/cli/cli/config/configfile" + configtypes "github.com/docker/cli/cli/config/types" + "github.com/docker/cli/internal/registry" + "github.com/docker/cli/internal/test" + "gotest.tools/v3/assert" + is "gotest.tools/v3/assert/cmp" +) + +func TestRunLogoutDockerIORemovesHubCredentials(t *testing.T) { + tmpDir := t.TempDir() + cfg := configfile.New(filepath.Join(tmpDir, "config.json")) + cfg.AuthConfigs = map[string]configtypes.AuthConfig{ + registry.IndexServer: { + Username: "user", + Password: "pass", + ServerAddress: registry.IndexServer, + }, + "example.com": { + Username: "other", + Password: "secret", + ServerAddress: "example.com", + }, + } + cli := test.NewFakeCli(nil) + cli.SetConfigFile(cfg) + + assert.NilError(t, runLogout(context.Background(), cli, "docker.io")) + + _, hubOK := cfg.AuthConfigs[registry.IndexServer] + assert.Check(t, !hubOK) + _, otherOK := cfg.AuthConfigs["example.com"] + assert.Check(t, otherOK) + assert.Check(t, is.Contains(cli.OutBuffer().String(), "Removing login credentials for "+registry.IndexServer)) +}