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 <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2023-07-10 17:24:07 +02:00
parent dc1359230f
commit 211220cbb0
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
15 changed files with 38 additions and 60 deletions

View File

@ -189,7 +189,7 @@ func (cli *DockerCli) ManifestStore() manifeststore.Store {
// registry // registry
func (cli *DockerCli) RegistryClient(allowInsecure bool) registryclient.RegistryClient { func (cli *DockerCli) RegistryClient(allowInsecure bool) registryclient.RegistryClient {
resolver := func(ctx context.Context, index *registry.IndexInfo) registry.AuthConfig { 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) return registryclient.NewRegistryClient(resolver, UserAgent(), allowInsecure)
} }

View File

@ -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). // 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 { 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 { if err != nil {
return err return err
} }

View File

@ -76,7 +76,7 @@ func RunPush(dockerCli command.Cli, opts pushOptions) error {
ctx := context.Background() ctx := context.Background()
// Resolve the Auth config relevant for this server // 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) encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
if err != nil { if err != nil {
return err return err

View File

@ -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 // AuthResolver returns an auth resolver function from a command.Cli
func AuthResolver(cli command.Cli) func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig { 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 func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
return command.ResolveAuthConfig(ctx, cli, index) return command.ResolveAuthConfig(cli.ConfigFile(), index)
} }
} }

View File

@ -79,19 +79,18 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
return types.PluginInstallOptions{}, errors.Errorf("invalid name: %s", ref.String()) 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 { if err != nil {
return types.PluginInstallOptions{}, err return types.PluginInstallOptions{}, err
} }
remote = reference.FamiliarString(trusted) remote = reference.FamiliarString(trusted)
} }
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index) authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), repoInfo.Index)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig) encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
if err != nil { if err != nil {
return types.PluginInstallOptions{}, err return types.PluginInstallOptions{}, err
} }
registryAuthFunc := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, cmdName)
options := types.PluginInstallOptions{ options := types.PluginInstallOptions{
RegistryAuth: encodedAuth, RegistryAuth: encodedAuth,
@ -99,7 +98,7 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
Disabled: opts.disable, Disabled: opts.disable,
AcceptAllPermissions: opts.grantPerms, AcceptAllPermissions: opts.grantPerms,
AcceptPermissionsFunc: acceptPrivileges(dockerCli, opts.remote), AcceptPermissionsFunc: acceptPrivileges(dockerCli, opts.remote),
PrivilegeFunc: registryAuthFunc, PrivilegeFunc: command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, cmdName),
Args: opts.args, Args: opts.args,
} }
return options, nil return options, nil

View File

@ -55,7 +55,7 @@ func runPush(dockerCli command.Cli, opts pushOptions) error {
if err != nil { if err != nil {
return err return err
} }
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index) authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), repoInfo.Index)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig) encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
if err != nil { if err != nil {
return err return err

View File

@ -2,13 +2,13 @@ package command
import ( import (
"bufio" "bufio"
"context"
"fmt" "fmt"
"io" "io"
"os" "os"
"runtime" "runtime"
"strings" "strings"
"github.com/docker/cli/cli/config/configfile"
configtypes "github.com/docker/cli/cli/config/types" configtypes "github.com/docker/cli/cli/config/types"
"github.com/docker/cli/cli/streams" "github.com/docker/cli/cli/streams"
"github.com/docker/distribution/reference" "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) fmt.Fprintf(cli.Out(), "\nPlease login prior to %s:\n", cmdName)
indexServer := registry.GetAuthConfigKey(index) indexServer := registry.GetAuthConfigKey(index)
isDefaultRegistry := indexServer == registry.IndexServer isDefaultRegistry := indexServer == registry.IndexServer
authConfig, err := GetDefaultAuthConfig(cli, true, indexServer, isDefaultRegistry) authConfig, err := GetDefaultAuthConfig(cli.ConfigFile(), true, indexServer, isDefaultRegistry)
if err != nil { if err != nil {
fmt.Fprintf(cli.Err(), "Unable to retrieve stored credentials for %s, error: %s.\n", indexServer, err) 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- // It is similar to [registry.ResolveAuthConfig], but uses the credentials-
// store, instead of looking up credentials from a map. // 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 configKey := index.Name
if index.Official { if index.Official {
configKey = registry.IndexServer configKey = registry.IndexServer
} }
a, _ := cli.ConfigFile().GetAuthConfig(configKey) a, _ := cfg.GetAuthConfig(configKey)
return registrytypes.AuthConfig(a) return registrytypes.AuthConfig(a)
} }
// GetDefaultAuthConfig gets the default auth config given a serverAddress // 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 // 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 { if !isDefaultRegistry {
serverAddress = registry.ConvertToHostname(serverAddress) serverAddress = registry.ConvertToHostname(serverAddress)
} }
authconfig := configtypes.AuthConfig{} authconfig := configtypes.AuthConfig{}
var err error var err error
if checkCredStore { if checkCredStore {
authconfig, err = cli.ConfigFile().GetAuthConfig(serverAddress) authconfig, err = cfg.GetAuthConfig(serverAddress)
if err != nil { if err != nil {
return registrytypes.AuthConfig{ return registrytypes.AuthConfig{
ServerAddress: serverAddress, ServerAddress: serverAddress,
@ -72,8 +72,7 @@ func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, is
} }
authconfig.ServerAddress = serverAddress authconfig.ServerAddress = serverAddress
authconfig.IdentityToken = "" authconfig.IdentityToken = ""
res := registrytypes.AuthConfig(authconfig) return registrytypes.AuthConfig(authconfig), nil
return res, nil
} }
// ConfigureAuth handles prompting of user's username and password if needed // 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: // For details on base64url encoding, see:
// - RFC4648, section 5: https://tools.ietf.org/html/rfc4648#section-5 // - 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 // Retrieve encoded auth token from the image reference
authConfig, err := resolveAuthConfigFromImage(ctx, cli, image) authConfig, err := resolveAuthConfigFromImage(cfg, image)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -186,7 +185,7 @@ func RetrieveAuthTokenFromImage(ctx context.Context, cli Cli, image string) (str
} }
// resolveAuthConfigFromImage retrieves that AuthConfig using the image string // 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) registryRef, err := reference.ParseNormalizedNamed(image)
if err != nil { if err != nil {
return registrytypes.AuthConfig{}, err return registrytypes.AuthConfig{}, err
@ -195,5 +194,5 @@ func resolveAuthConfigFromImage(ctx context.Context, cli Cli, image string) (reg
if err != nil { if err != nil {
return registrytypes.AuthConfig{}, err return registrytypes.AuthConfig{}, err
} }
return ResolveAuthConfig(ctx, cli, repoInfo.Index), nil return ResolveAuthConfig(cfg, repoInfo.Index), nil
} }

View File

@ -117,7 +117,7 @@ func runLogin(dockerCli command.Cli, opts loginOptions) error { //nolint:gocyclo
} }
isDefaultRegistry := serverAddress == registry.IndexServer 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 != "" { if err == nil && authConfig.Username != "" && authConfig.Password != "" {
response, err = loginWithCredStoreCreds(ctx, dockerCli, &authConfig) response, err = loginWithCredStoreCreds(ctx, dockerCli, &authConfig)
} }

View File

@ -54,13 +54,13 @@ func runSearch(dockerCli command.Cli, options searchOptions) error {
return err return err
} }
ctx := context.Background() authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), indexInfo)
authConfig := command.ResolveAuthConfig(ctx, dockerCli, indexInfo)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig) encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
if err != nil { if err != nil {
return err return err
} }
ctx := context.Background()
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, indexInfo, "search") requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, indexInfo, "search")
results, err := dockerCli.Client().ImageSearch(ctx, options.term, types.ImageSearchOptions{ results, err := dockerCli.Client().ImageSearch(ctx, options.term, types.ImageSearchOptions{
RegistryAuth: encodedAuth, RegistryAuth: encodedAuth,

View File

@ -1,26 +1,17 @@
package command_test package command_test
import ( import (
"bytes"
"context"
"fmt" "fmt"
"testing" "testing"
. "github.com/docker/cli/cli/command" // Prevents a circular import with "github.com/docker/cli/internal/test" . "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" 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/registry"
"github.com/docker/docker/api/types/system"
"github.com/docker/docker/client"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp" is "gotest.tools/v3/assert/cmp"
) )
type fakeClient struct {
client.Client
infoFunc func() (system.Info, error)
}
var testAuthConfigs = []registry.AuthConfig{ var testAuthConfigs = []registry.AuthConfig{
{ {
ServerAddress: "https://index.docker.io/v1/", 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) { func TestGetDefaultAuthConfig(t *testing.T) {
testCases := []struct { testCases := []struct {
checkCredStore bool checkCredStore bool
@ -77,15 +61,13 @@ func TestGetDefaultAuthConfig(t *testing.T) {
expectedAuthConfig: testAuthConfigs[1], expectedAuthConfig: testAuthConfigs[1],
}, },
} }
cli := test.NewFakeCli(&fakeClient{}) cfg := configfile.New("filename")
errBuf := new(bytes.Buffer)
cli.SetErr(errBuf)
for _, authconfig := range testAuthConfigs { 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 { for _, tc := range testCases {
serverAddress := tc.inputServerAddress 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 != "" { if tc.expectedErr != "" {
assert.Check(t, err != nil) assert.Check(t, err != nil)
assert.Check(t, is.Equal(tc.expectedErr, err.Error())) assert.Check(t, is.Equal(tc.expectedErr, err.Error()))
@ -97,15 +79,14 @@ func TestGetDefaultAuthConfig(t *testing.T) {
} }
func TestGetDefaultAuthConfig_HelperError(t *testing.T) { func TestGetDefaultAuthConfig_HelperError(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{}) cfg := configfile.New("filename")
errBuf := new(bytes.Buffer) cfg.CredentialsStore = "fake-does-not-exist"
cli.SetErr(errBuf)
cli.ConfigFile().CredentialsStore = "fake-does-not-exist" const serverAddress = "test-server-address"
serverAddress := "test-server-address"
expectedAuthConfig := registry.AuthConfig{ expectedAuthConfig := registry.AuthConfig{
ServerAddress: serverAddress, 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.DeepEqual(expectedAuthConfig, authconfig))
assert.Check(t, is.ErrorContains(err, "docker-credential-fake-does-not-exist")) assert.Check(t, is.ErrorContains(err, "docker-credential-fake-does-not-exist"))
} }

View File

@ -112,7 +112,7 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, opts *serviceOptions
// only send auth if flag was set // only send auth if flag was set
if opts.registryAuth { if opts.registryAuth {
// Retrieve encoded auth token from the image reference // 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 { if err != nil {
return err return err
} }

View File

@ -1,7 +1,6 @@
package service package service
import ( import (
"context"
"encoding/hex" "encoding/hex"
"github.com/docker/cli/cli/command" "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") 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 { if err != nil {
return errors.Wrap(err, "failed to resolve image digest using content trust") 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 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) repoInfo, err := registry.ParseRepositoryInfo(ref)
if err != nil { if err != nil {
return nil, err 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") notaryRepo, err := trust.GetNotaryRepository(cli.In(), cli.Out(), command.UserAgent(), repoInfo, &authConfig, "pull")
if err != nil { if err != nil {

View File

@ -223,7 +223,7 @@ func runUpdate(dockerCli command.Cli, flags *pflag.FlagSet, options *serviceOpti
// Retrieve encoded auth token from the image reference // Retrieve encoded auth token from the image reference
// This would be the old image if it didn't change in this update // This would be the old image if it didn't change in this update
image := spec.TaskTemplate.ContainerSpec.Image image := spec.TaskTemplate.ContainerSpec.Image
encodedAuth, err := command.RetrieveAuthTokenFromImage(ctx, dockerCli, image) encodedAuth, err := command.RetrieveAuthTokenFromImage(dockerCli.ConfigFile(), image)
if err != nil { if err != nil {
return err return err
} }

View File

@ -198,7 +198,7 @@ func deployServices(ctx context.Context, dockerCli command.Cli, services map[str
if sendAuth { if sendAuth {
// Retrieve encoded auth token from the image reference // 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 { if err != nil {
return err return err
} }

View File

@ -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) 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) encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
if err != nil { if err != nil {
return err return err