Merge pull request #5611 from thaJeztah/27.x_backport_login_minor_refactor

[27.x backport] cli/command: PromptUserForCredentials: assorted minor improvements and (linting) fixes
This commit is contained in:
Sebastiaan van Stijn 2024-11-14 14:51:17 +01:00 committed by GitHub
commit 8be6bec27d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 46 additions and 28 deletions

View File

@ -19,20 +19,24 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
const patSuggest = "You can log in with your password or a Personal Access " + const (
registerSuggest = "Log in with your Docker ID or email address to push and pull images from Docker Hub. " +
"If you don't have a Docker ID, head over to https://hub.docker.com/ to create one."
patSuggest = "You can log in with your password or a Personal Access " +
"Token (PAT). Using a limited-scope PAT grants better security and is required " + "Token (PAT). Using a limited-scope PAT grants better security and is required " +
"for organizations using SSO. Learn more at https://docs.docker.com/go/access-tokens/" "for organizations using SSO. Learn more at https://docs.docker.com/go/access-tokens/"
)
// RegistryAuthenticationPrivilegedFunc returns a RequestPrivilegeFunc from the specified registry index info // RegistryAuthenticationPrivilegedFunc returns a RequestPrivilegeFunc from the specified registry index info
// for the given command. // for the given command.
func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInfo, cmdName string) types.RequestPrivilegeFunc { func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInfo, cmdName string) types.RequestPrivilegeFunc {
return func(ctx context.Context) (string, error) { return func(ctx context.Context) (string, error) {
fmt.Fprintf(cli.Out(), "\nLogin prior to %s:\n", cmdName) _, _ = fmt.Fprintf(cli.Out(), "\nLogin 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.ConfigFile(), 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)
} }
select { select {
@ -112,7 +116,7 @@ func ConfigureAuth(ctx context.Context, cli Cli, flUser, flPassword string, auth
// If defaultUsername is not empty, the username prompt includes that username // If defaultUsername is not empty, the username prompt includes that username
// and the user can hit enter without inputting a username to use that default // and the user can hit enter without inputting a username to use that default
// username. // username.
func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword, defaultUsername, serverAddress string) (authConfig registrytypes.AuthConfig, err error) { func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword, defaultUsername, serverAddress string) (registrytypes.AuthConfig, error) {
// On Windows, force the use of the regular OS stdin stream. // On Windows, force the use of the regular OS stdin stream.
// //
// See: // See:
@ -125,57 +129,71 @@ func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword
cli.SetIn(streams.NewIn(os.Stdin)) cli.SetIn(streams.NewIn(os.Stdin))
} }
isDefaultRegistry := serverAddress == registry.IndexServer argUser = strings.TrimSpace(argUser)
defaultUsername = strings.TrimSpace(defaultUsername) if argUser == "" {
if serverAddress == registry.IndexServer {
if argUser = strings.TrimSpace(argUser); argUser == "" { // When signing in to the default (Docker Hub) registry, we display
if isDefaultRegistry { // hints for creating an account, and (if hints are enabled), using
// if this is a default registry (docker hub), then display the following message. // a token instead of a password.
fmt.Fprintln(cli.Out(), "Log in with your Docker ID or email address to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com/ to create one.") _, _ = fmt.Fprintln(cli.Out(), registerSuggest)
if hints.Enabled() { if hints.Enabled() {
fmt.Fprintln(cli.Out(), patSuggest) _, _ = fmt.Fprintln(cli.Out(), patSuggest)
fmt.Fprintln(cli.Out()) _, _ = fmt.Fprintln(cli.Out())
} }
} }
var prompt string var prompt string
defaultUsername = strings.TrimSpace(defaultUsername)
if defaultUsername == "" { if defaultUsername == "" {
prompt = "Username: " prompt = "Username: "
} else { } else {
prompt = fmt.Sprintf("Username (%s): ", defaultUsername) prompt = fmt.Sprintf("Username (%s): ", defaultUsername)
} }
var err error
argUser, err = PromptForInput(ctx, cli.In(), cli.Out(), prompt) argUser, err = PromptForInput(ctx, cli.In(), cli.Out(), prompt)
if err != nil { if err != nil {
return authConfig, err return registrytypes.AuthConfig{}, err
} }
if argUser == "" { if argUser == "" {
argUser = defaultUsername argUser = defaultUsername
} }
}
if argUser == "" { if argUser == "" {
return authConfig, errors.Errorf("Error: Non-null Username Required") return registrytypes.AuthConfig{}, errors.Errorf("Error: Non-null Username Required")
} }
}
argPassword = strings.TrimSpace(argPassword)
if argPassword == "" { if argPassword == "" {
restoreInput, err := DisableInputEcho(cli.In()) restoreInput, err := DisableInputEcho(cli.In())
if err != nil { if err != nil {
return authConfig, err return registrytypes.AuthConfig{}, err
} }
defer restoreInput() defer func() {
if err := restoreInput(); err != nil {
// TODO(thaJeztah): we should consider printing instructions how
// to restore this manually (other than restarting the shell).
// e.g., 'run stty echo' when in a Linux or macOS shell, but
// PowerShell and CMD.exe may need different instructions.
_, _ = fmt.Fprintln(cli.Err(), "Error: failed to restore terminal state to echo input:", err)
}
}()
argPassword, err = PromptForInput(ctx, cli.In(), cli.Out(), "Password: ") argPassword, err = PromptForInput(ctx, cli.In(), cli.Out(), "Password: ")
if err != nil { if err != nil {
return authConfig, err return registrytypes.AuthConfig{}, err
} }
fmt.Fprint(cli.Out(), "\n") _, _ = fmt.Fprintln(cli.Out())
if argPassword == "" { if argPassword == "" {
return authConfig, errors.Errorf("Error: Password Required") return registrytypes.AuthConfig{}, errors.Errorf("Error: Password Required")
} }
} }
authConfig.Username = argUser return registrytypes.AuthConfig{
authConfig.Password = argPassword Username: argUser,
authConfig.ServerAddress = serverAddress Password: argPassword,
return authConfig, nil ServerAddress: serverAddress,
}, nil
} }
// RetrieveAuthTokenFromImage retrieves an encoded auth token given a complete // RetrieveAuthTokenFromImage retrieves an encoded auth token given a complete