From 211220cbb0806f5ac65d586aecd7837b97b7e90a Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 10 Jul 2023 17:24:07 +0200 Subject: [PATCH] cli/command: ResolveAuthConfig, GetDefaultAuthConfig: take ConfigFile as arg Both these functions took the whole DockerCLI as argument, but only needed the ConfigFile. ResolveAuthConfig also had an unused context.Context as argument. This patch updates both functions to accept a ConfigFile, and removes the unused context.Context. Signed-off-by: Sebastiaan van Stijn --- cli/command/cli.go | 2 +- cli/command/container/create.go | 2 +- cli/command/image/push.go | 2 +- cli/command/image/trust.go | 2 +- cli/command/plugin/install.go | 7 ++-- cli/command/plugin/push.go | 2 +- cli/command/registry.go | 23 ++++++------ cli/command/registry/login.go | 2 +- cli/command/registry/search.go | 4 +- cli/command/registry_test.go | 37 +++++-------------- cli/command/service/create.go | 2 +- cli/command/service/trust.go | 7 ++-- cli/command/service/update.go | 2 +- cli/command/stack/swarm/deploy_composefile.go | 2 +- cli/command/trust/sign.go | 2 +- 15 files changed, 38 insertions(+), 60 deletions(-) diff --git a/cli/command/cli.go b/cli/command/cli.go index a000bcc246..dfc22b701f 100644 --- a/cli/command/cli.go +++ b/cli/command/cli.go @@ -189,7 +189,7 @@ func (cli *DockerCli) ManifestStore() manifeststore.Store { // registry func (cli *DockerCli) RegistryClient(allowInsecure bool) registryclient.RegistryClient { resolver := func(ctx context.Context, index *registry.IndexInfo) registry.AuthConfig { - return ResolveAuthConfig(ctx, cli, index) + return ResolveAuthConfig(cli.ConfigFile(), index) } return registryclient.NewRegistryClient(resolver, UserAgent(), allowInsecure) } diff --git a/cli/command/container/create.go b/cli/command/container/create.go index bd594124d0..89273b8d99 100644 --- a/cli/command/container/create.go +++ b/cli/command/container/create.go @@ -114,7 +114,7 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, options *createOptio // FIXME(thaJeztah): this is the only code-path that uses APIClient.ImageCreate. Rewrite this to use the regular "pull" code (or vice-versa). func pullImage(ctx context.Context, dockerCli command.Cli, image string, opts *createOptions) error { - encodedAuth, err := command.RetrieveAuthTokenFromImage(ctx, dockerCli, image) + encodedAuth, err := command.RetrieveAuthTokenFromImage(dockerCli.ConfigFile(), image) if err != nil { return err } diff --git a/cli/command/image/push.go b/cli/command/image/push.go index f60a92c33c..de8a79530b 100644 --- a/cli/command/image/push.go +++ b/cli/command/image/push.go @@ -76,7 +76,7 @@ func RunPush(dockerCli command.Cli, opts pushOptions) error { ctx := context.Background() // Resolve the Auth config relevant for this server - authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index) + authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), repoInfo.Index) encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig) if err != nil { return err diff --git a/cli/command/image/trust.go b/cli/command/image/trust.go index 3da1e8032e..a02c50dfc3 100644 --- a/cli/command/image/trust.go +++ b/cli/command/image/trust.go @@ -339,6 +339,6 @@ func TagTrusted(ctx context.Context, cli command.Cli, trustedRef reference.Canon // AuthResolver returns an auth resolver function from a command.Cli func AuthResolver(cli command.Cli) func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig { return func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig { - return command.ResolveAuthConfig(ctx, cli, index) + return command.ResolveAuthConfig(cli.ConfigFile(), index) } } diff --git a/cli/command/plugin/install.go b/cli/command/plugin/install.go index 2b6d3040cf..fbd0c5dbdd 100644 --- a/cli/command/plugin/install.go +++ b/cli/command/plugin/install.go @@ -79,19 +79,18 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti return types.PluginInstallOptions{}, errors.Errorf("invalid name: %s", ref.String()) } - trusted, err := image.TrustedReference(context.Background(), dockerCli, nt) + trusted, err := image.TrustedReference(ctx, dockerCli, nt) if err != nil { return types.PluginInstallOptions{}, err } remote = reference.FamiliarString(trusted) } - authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index) + authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), repoInfo.Index) encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig) if err != nil { return types.PluginInstallOptions{}, err } - registryAuthFunc := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, cmdName) options := types.PluginInstallOptions{ RegistryAuth: encodedAuth, @@ -99,7 +98,7 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti Disabled: opts.disable, AcceptAllPermissions: opts.grantPerms, AcceptPermissionsFunc: acceptPrivileges(dockerCli, opts.remote), - PrivilegeFunc: registryAuthFunc, + PrivilegeFunc: command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, cmdName), Args: opts.args, } return options, nil diff --git a/cli/command/plugin/push.go b/cli/command/plugin/push.go index bb03bcfc11..f6973d4323 100644 --- a/cli/command/plugin/push.go +++ b/cli/command/plugin/push.go @@ -55,7 +55,7 @@ func runPush(dockerCli command.Cli, opts pushOptions) error { if err != nil { return err } - authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index) + authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), repoInfo.Index) encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig) if err != nil { return err diff --git a/cli/command/registry.go b/cli/command/registry.go index 94f58fe541..c3ee03f998 100644 --- a/cli/command/registry.go +++ b/cli/command/registry.go @@ -2,13 +2,13 @@ package command import ( "bufio" - "context" "fmt" "io" "os" "runtime" "strings" + "github.com/docker/cli/cli/config/configfile" configtypes "github.com/docker/cli/cli/config/types" "github.com/docker/cli/cli/streams" "github.com/docker/distribution/reference" @@ -26,7 +26,7 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf fmt.Fprintf(cli.Out(), "\nPlease login prior to %s:\n", cmdName) indexServer := registry.GetAuthConfigKey(index) isDefaultRegistry := indexServer == registry.IndexServer - authConfig, err := GetDefaultAuthConfig(cli, true, indexServer, isDefaultRegistry) + authConfig, err := GetDefaultAuthConfig(cli.ConfigFile(), true, indexServer, isDefaultRegistry) if err != nil { fmt.Fprintf(cli.Err(), "Unable to retrieve stored credentials for %s, error: %s.\n", indexServer, err) } @@ -44,26 +44,26 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf // // It is similar to [registry.ResolveAuthConfig], but uses the credentials- // store, instead of looking up credentials from a map. -func ResolveAuthConfig(_ context.Context, cli Cli, index *registrytypes.IndexInfo) registrytypes.AuthConfig { +func ResolveAuthConfig(cfg *configfile.ConfigFile, index *registrytypes.IndexInfo) registrytypes.AuthConfig { configKey := index.Name if index.Official { configKey = registry.IndexServer } - a, _ := cli.ConfigFile().GetAuthConfig(configKey) + a, _ := cfg.GetAuthConfig(configKey) return registrytypes.AuthConfig(a) } // GetDefaultAuthConfig gets the default auth config given a serverAddress // If credentials for given serverAddress exists in the credential store, the configuration will be populated with values in it -func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (registrytypes.AuthConfig, error) { +func GetDefaultAuthConfig(cfg *configfile.ConfigFile, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (registrytypes.AuthConfig, error) { if !isDefaultRegistry { serverAddress = registry.ConvertToHostname(serverAddress) } authconfig := configtypes.AuthConfig{} var err error if checkCredStore { - authconfig, err = cli.ConfigFile().GetAuthConfig(serverAddress) + authconfig, err = cfg.GetAuthConfig(serverAddress) if err != nil { return registrytypes.AuthConfig{ ServerAddress: serverAddress, @@ -72,8 +72,7 @@ func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, is } authconfig.ServerAddress = serverAddress authconfig.IdentityToken = "" - res := registrytypes.AuthConfig(authconfig) - return res, nil + return registrytypes.AuthConfig(authconfig), nil } // ConfigureAuth handles prompting of user's username and password if needed @@ -172,9 +171,9 @@ func promptWithDefault(out io.Writer, prompt string, configDefault string) { // // For details on base64url encoding, see: // - RFC4648, section 5: https://tools.ietf.org/html/rfc4648#section-5 -func RetrieveAuthTokenFromImage(ctx context.Context, cli Cli, image string) (string, error) { +func RetrieveAuthTokenFromImage(cfg *configfile.ConfigFile, image string) (string, error) { // Retrieve encoded auth token from the image reference - authConfig, err := resolveAuthConfigFromImage(ctx, cli, image) + authConfig, err := resolveAuthConfigFromImage(cfg, image) if err != nil { return "", err } @@ -186,7 +185,7 @@ func RetrieveAuthTokenFromImage(ctx context.Context, cli Cli, image string) (str } // resolveAuthConfigFromImage retrieves that AuthConfig using the image string -func resolveAuthConfigFromImage(ctx context.Context, cli Cli, image string) (registrytypes.AuthConfig, error) { +func resolveAuthConfigFromImage(cfg *configfile.ConfigFile, image string) (registrytypes.AuthConfig, error) { registryRef, err := reference.ParseNormalizedNamed(image) if err != nil { return registrytypes.AuthConfig{}, err @@ -195,5 +194,5 @@ func resolveAuthConfigFromImage(ctx context.Context, cli Cli, image string) (reg if err != nil { return registrytypes.AuthConfig{}, err } - return ResolveAuthConfig(ctx, cli, repoInfo.Index), nil + return ResolveAuthConfig(cfg, repoInfo.Index), nil } diff --git a/cli/command/registry/login.go b/cli/command/registry/login.go index 7ddfccca20..6098c1863e 100644 --- a/cli/command/registry/login.go +++ b/cli/command/registry/login.go @@ -117,7 +117,7 @@ func runLogin(dockerCli command.Cli, opts loginOptions) error { //nolint:gocyclo } isDefaultRegistry := serverAddress == registry.IndexServer - authConfig, err := command.GetDefaultAuthConfig(dockerCli, opts.user == "" && opts.password == "", serverAddress, isDefaultRegistry) + authConfig, err := command.GetDefaultAuthConfig(dockerCli.ConfigFile(), opts.user == "" && opts.password == "", serverAddress, isDefaultRegistry) if err == nil && authConfig.Username != "" && authConfig.Password != "" { response, err = loginWithCredStoreCreds(ctx, dockerCli, &authConfig) } diff --git a/cli/command/registry/search.go b/cli/command/registry/search.go index 6ba00b5236..86e3ae91e5 100644 --- a/cli/command/registry/search.go +++ b/cli/command/registry/search.go @@ -54,13 +54,13 @@ func runSearch(dockerCli command.Cli, options searchOptions) error { return err } - ctx := context.Background() - authConfig := command.ResolveAuthConfig(ctx, dockerCli, indexInfo) + authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), indexInfo) encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig) if err != nil { return err } + ctx := context.Background() requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, indexInfo, "search") results, err := dockerCli.Client().ImageSearch(ctx, options.term, types.ImageSearchOptions{ RegistryAuth: encodedAuth, diff --git a/cli/command/registry_test.go b/cli/command/registry_test.go index 4fa8658ebc..1099dfd05b 100644 --- a/cli/command/registry_test.go +++ b/cli/command/registry_test.go @@ -1,26 +1,17 @@ package command_test import ( - "bytes" - "context" "fmt" "testing" . "github.com/docker/cli/cli/command" // Prevents a circular import with "github.com/docker/cli/internal/test" + "github.com/docker/cli/cli/config/configfile" configtypes "github.com/docker/cli/cli/config/types" - "github.com/docker/cli/internal/test" "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/api/types/system" - "github.com/docker/docker/client" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) -type fakeClient struct { - client.Client - infoFunc func() (system.Info, error) -} - var testAuthConfigs = []registry.AuthConfig{ { ServerAddress: "https://index.docker.io/v1/", @@ -34,13 +25,6 @@ var testAuthConfigs = []registry.AuthConfig{ }, } -func (cli *fakeClient) Info(_ context.Context) (system.Info, error) { - if cli.infoFunc != nil { - return cli.infoFunc() - } - return system.Info{}, nil -} - func TestGetDefaultAuthConfig(t *testing.T) { testCases := []struct { checkCredStore bool @@ -77,15 +61,13 @@ func TestGetDefaultAuthConfig(t *testing.T) { expectedAuthConfig: testAuthConfigs[1], }, } - cli := test.NewFakeCli(&fakeClient{}) - errBuf := new(bytes.Buffer) - cli.SetErr(errBuf) + cfg := configfile.New("filename") for _, authconfig := range testAuthConfigs { - cli.ConfigFile().GetCredentialsStore(authconfig.ServerAddress).Store(configtypes.AuthConfig(authconfig)) + cfg.GetCredentialsStore(authconfig.ServerAddress).Store(configtypes.AuthConfig(authconfig)) } for _, tc := range testCases { serverAddress := tc.inputServerAddress - authconfig, err := GetDefaultAuthConfig(cli, tc.checkCredStore, serverAddress, serverAddress == "https://index.docker.io/v1/") + authconfig, err := GetDefaultAuthConfig(cfg, tc.checkCredStore, serverAddress, serverAddress == "https://index.docker.io/v1/") if tc.expectedErr != "" { assert.Check(t, err != nil) assert.Check(t, is.Equal(tc.expectedErr, err.Error())) @@ -97,15 +79,14 @@ func TestGetDefaultAuthConfig(t *testing.T) { } func TestGetDefaultAuthConfig_HelperError(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{}) - errBuf := new(bytes.Buffer) - cli.SetErr(errBuf) - cli.ConfigFile().CredentialsStore = "fake-does-not-exist" - serverAddress := "test-server-address" + cfg := configfile.New("filename") + cfg.CredentialsStore = "fake-does-not-exist" + + const serverAddress = "test-server-address" expectedAuthConfig := registry.AuthConfig{ ServerAddress: serverAddress, } - authconfig, err := GetDefaultAuthConfig(cli, true, serverAddress, serverAddress == "https://index.docker.io/v1/") + authconfig, err := GetDefaultAuthConfig(cfg, true, serverAddress, serverAddress == "https://index.docker.io/v1/") assert.Check(t, is.DeepEqual(expectedAuthConfig, authconfig)) assert.Check(t, is.ErrorContains(err, "docker-credential-fake-does-not-exist")) } diff --git a/cli/command/service/create.go b/cli/command/service/create.go index 8d4bc76cdd..d5b8fec087 100644 --- a/cli/command/service/create.go +++ b/cli/command/service/create.go @@ -112,7 +112,7 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, opts *serviceOptions // only send auth if flag was set if opts.registryAuth { // Retrieve encoded auth token from the image reference - encodedAuth, err := command.RetrieveAuthTokenFromImage(ctx, dockerCli, opts.image) + encodedAuth, err := command.RetrieveAuthTokenFromImage(dockerCli.ConfigFile(), opts.image) if err != nil { return err } diff --git a/cli/command/service/trust.go b/cli/command/service/trust.go index b7453ccbb9..75b8fad124 100644 --- a/cli/command/service/trust.go +++ b/cli/command/service/trust.go @@ -1,7 +1,6 @@ package service import ( - "context" "encoding/hex" "github.com/docker/cli/cli/command" @@ -39,7 +38,7 @@ func resolveServiceImageDigestContentTrust(dockerCli command.Cli, service *swarm return errors.New("failed to resolve image digest using content trust: reference is not tagged") } - resolvedImage, err := trustedResolveDigest(context.Background(), dockerCli, taggedRef) + resolvedImage, err := trustedResolveDigest(dockerCli, taggedRef) if err != nil { return errors.Wrap(err, "failed to resolve image digest using content trust") } @@ -51,13 +50,13 @@ func resolveServiceImageDigestContentTrust(dockerCli command.Cli, service *swarm return nil } -func trustedResolveDigest(ctx context.Context, cli command.Cli, ref reference.NamedTagged) (reference.Canonical, error) { +func trustedResolveDigest(cli command.Cli, ref reference.NamedTagged) (reference.Canonical, error) { repoInfo, err := registry.ParseRepositoryInfo(ref) if err != nil { return nil, err } - authConfig := command.ResolveAuthConfig(ctx, cli, repoInfo.Index) + authConfig := command.ResolveAuthConfig(cli.ConfigFile(), repoInfo.Index) notaryRepo, err := trust.GetNotaryRepository(cli.In(), cli.Out(), command.UserAgent(), repoInfo, &authConfig, "pull") if err != nil { diff --git a/cli/command/service/update.go b/cli/command/service/update.go index 2ef9014cab..c087224ba4 100644 --- a/cli/command/service/update.go +++ b/cli/command/service/update.go @@ -223,7 +223,7 @@ func runUpdate(dockerCli command.Cli, flags *pflag.FlagSet, options *serviceOpti // Retrieve encoded auth token from the image reference // This would be the old image if it didn't change in this update image := spec.TaskTemplate.ContainerSpec.Image - encodedAuth, err := command.RetrieveAuthTokenFromImage(ctx, dockerCli, image) + encodedAuth, err := command.RetrieveAuthTokenFromImage(dockerCli.ConfigFile(), image) if err != nil { return err } diff --git a/cli/command/stack/swarm/deploy_composefile.go b/cli/command/stack/swarm/deploy_composefile.go index 778cdd9757..2d8a46639c 100644 --- a/cli/command/stack/swarm/deploy_composefile.go +++ b/cli/command/stack/swarm/deploy_composefile.go @@ -198,7 +198,7 @@ func deployServices(ctx context.Context, dockerCli command.Cli, services map[str if sendAuth { // Retrieve encoded auth token from the image reference - encodedAuth, err = command.RetrieveAuthTokenFromImage(ctx, dockerCli, image) + encodedAuth, err = command.RetrieveAuthTokenFromImage(dockerCli.ConfigFile(), image) if err != nil { return err } diff --git a/cli/command/trust/sign.go b/cli/command/trust/sign.go index 5f8f3c1014..7679b38f7c 100644 --- a/cli/command/trust/sign.go +++ b/cli/command/trust/sign.go @@ -93,7 +93,7 @@ func runSignImage(cli command.Cli, options signOptions) error { } fmt.Fprintf(cli.Err(), "Signing and pushing trust data for local image %s, may overwrite remote trust data\n", imageName) - authConfig := command.ResolveAuthConfig(ctx, cli, imgRefAndAuth.RepoInfo().Index) + authConfig := command.ResolveAuthConfig(cli.ConfigFile(), imgRefAndAuth.RepoInfo().Index) encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig) if err != nil { return err