github.com/boynux/docker@v1.11.0-rc4/api/client/login.go (about)

     1  package client
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"runtime"
     9  	"strings"
    10  
    11  	"golang.org/x/net/context"
    12  
    13  	Cli "github.com/docker/docker/cli"
    14  	"github.com/docker/docker/cliconfig"
    15  	"github.com/docker/docker/cliconfig/credentials"
    16  	flag "github.com/docker/docker/pkg/mflag"
    17  	"github.com/docker/docker/pkg/term"
    18  	"github.com/docker/engine-api/types"
    19  )
    20  
    21  // CmdLogin logs in a user to a Docker registry service.
    22  //
    23  // If no server is specified, the user will be logged into or registered to the registry's index server.
    24  //
    25  // Usage: docker login SERVER
    26  func (cli *DockerCli) CmdLogin(args ...string) error {
    27  	cmd := Cli.Subcmd("login", []string{"[SERVER]"}, Cli.DockerCommands["login"].Description+".\nIf no server is specified, the default is defined by the daemon.", true)
    28  	cmd.Require(flag.Max, 1)
    29  
    30  	flUser := cmd.String([]string{"u", "-username"}, "", "Username")
    31  	flPassword := cmd.String([]string{"p", "-password"}, "", "Password")
    32  
    33  	// Deprecated in 1.11: Should be removed in docker 1.13
    34  	cmd.String([]string{"#e", "#-email"}, "", "Email")
    35  
    36  	cmd.ParseFlags(args, true)
    37  
    38  	// On Windows, force the use of the regular OS stdin stream. Fixes #14336/#14210
    39  	if runtime.GOOS == "windows" {
    40  		cli.in = os.Stdin
    41  	}
    42  
    43  	var serverAddress string
    44  	var isDefaultRegistry bool
    45  	if len(cmd.Args()) > 0 {
    46  		serverAddress = cmd.Arg(0)
    47  	} else {
    48  		serverAddress = cli.electAuthServer()
    49  		isDefaultRegistry = true
    50  	}
    51  
    52  	authConfig, err := cli.configureAuth(*flUser, *flPassword, serverAddress, isDefaultRegistry)
    53  	if err != nil {
    54  		return err
    55  	}
    56  
    57  	response, err := cli.client.RegistryLogin(context.Background(), authConfig)
    58  	if err != nil {
    59  		return err
    60  	}
    61  
    62  	if response.IdentityToken != "" {
    63  		authConfig.Password = ""
    64  		authConfig.IdentityToken = response.IdentityToken
    65  	}
    66  	if err := storeCredentials(cli.configFile, authConfig); err != nil {
    67  		return fmt.Errorf("Error saving credentials: %v", err)
    68  	}
    69  
    70  	if response.Status != "" {
    71  		fmt.Fprintln(cli.out, response.Status)
    72  	}
    73  	return nil
    74  }
    75  
    76  func (cli *DockerCli) promptWithDefault(prompt string, configDefault string) {
    77  	if configDefault == "" {
    78  		fmt.Fprintf(cli.out, "%s: ", prompt)
    79  	} else {
    80  		fmt.Fprintf(cli.out, "%s (%s): ", prompt, configDefault)
    81  	}
    82  }
    83  
    84  func (cli *DockerCli) configureAuth(flUser, flPassword, serverAddress string, isDefaultRegistry bool) (types.AuthConfig, error) {
    85  	authconfig, err := getCredentials(cli.configFile, serverAddress)
    86  	if err != nil {
    87  		return authconfig, err
    88  	}
    89  
    90  	authconfig.Username = strings.TrimSpace(authconfig.Username)
    91  
    92  	if flUser = strings.TrimSpace(flUser); flUser == "" {
    93  		if isDefaultRegistry {
    94  			// if this is a defauly registry (docker hub), then display the following message.
    95  			fmt.Fprintln(cli.out, "Login with your Docker ID 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.")
    96  		}
    97  		cli.promptWithDefault("Username", authconfig.Username)
    98  		flUser = readInput(cli.in, cli.out)
    99  		flUser = strings.TrimSpace(flUser)
   100  		if flUser == "" {
   101  			flUser = authconfig.Username
   102  		}
   103  	}
   104  
   105  	if flUser == "" {
   106  		return authconfig, fmt.Errorf("Error: Non-null Username Required")
   107  	}
   108  
   109  	if flPassword == "" {
   110  		oldState, err := term.SaveState(cli.inFd)
   111  		if err != nil {
   112  			return authconfig, err
   113  		}
   114  		fmt.Fprintf(cli.out, "Password: ")
   115  		term.DisableEcho(cli.inFd, oldState)
   116  
   117  		flPassword = readInput(cli.in, cli.out)
   118  		fmt.Fprint(cli.out, "\n")
   119  
   120  		term.RestoreTerminal(cli.inFd, oldState)
   121  		if flPassword == "" {
   122  			return authconfig, fmt.Errorf("Error: Password Required")
   123  		}
   124  	}
   125  
   126  	authconfig.Username = flUser
   127  	authconfig.Password = flPassword
   128  	authconfig.ServerAddress = serverAddress
   129  	authconfig.IdentityToken = ""
   130  
   131  	return authconfig, nil
   132  }
   133  
   134  func readInput(in io.Reader, out io.Writer) string {
   135  	reader := bufio.NewReader(in)
   136  	line, _, err := reader.ReadLine()
   137  	if err != nil {
   138  		fmt.Fprintln(out, err.Error())
   139  		os.Exit(1)
   140  	}
   141  	return string(line)
   142  }
   143  
   144  // getCredentials loads the user credentials from a credentials store.
   145  // The store is determined by the config file settings.
   146  func getCredentials(c *cliconfig.ConfigFile, serverAddress string) (types.AuthConfig, error) {
   147  	s := loadCredentialsStore(c)
   148  	return s.Get(serverAddress)
   149  }
   150  
   151  func getAllCredentials(c *cliconfig.ConfigFile) (map[string]types.AuthConfig, error) {
   152  	s := loadCredentialsStore(c)
   153  	return s.GetAll()
   154  }
   155  
   156  // storeCredentials saves the user credentials in a credentials store.
   157  // The store is determined by the config file settings.
   158  func storeCredentials(c *cliconfig.ConfigFile, auth types.AuthConfig) error {
   159  	s := loadCredentialsStore(c)
   160  	return s.Store(auth)
   161  }
   162  
   163  // eraseCredentials removes the user credentials from a credentials store.
   164  // The store is determined by the config file settings.
   165  func eraseCredentials(c *cliconfig.ConfigFile, serverAddress string) error {
   166  	s := loadCredentialsStore(c)
   167  	return s.Erase(serverAddress)
   168  }
   169  
   170  // loadCredentialsStore initializes a new credentials store based
   171  // in the settings provided in the configuration file.
   172  func loadCredentialsStore(c *cliconfig.ConfigFile) credentials.Store {
   173  	if c.CredentialsStore != "" {
   174  		return credentials.NewNativeStore(c)
   175  	}
   176  	return credentials.NewFileStore(c)
   177  }