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