github.com/endocode/docker@v1.4.2-0.20160113120958-46eb4700391e/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  	flag "github.com/docker/docker/pkg/mflag"
    13  	"github.com/docker/docker/pkg/term"
    14  	"github.com/docker/docker/registry"
    15  	"github.com/docker/engine-api/client"
    16  	"github.com/docker/engine-api/types"
    17  )
    18  
    19  // CmdLogin logs in or registers 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 \""+registry.IndexServer+"\" is the default.", true)
    26  	cmd.Require(flag.Max, 1)
    27  
    28  	var username, password, email string
    29  
    30  	cmd.StringVar(&username, []string{"u", "-username"}, "", "Username")
    31  	cmd.StringVar(&password, []string{"p", "-password"}, "", "Password")
    32  	cmd.StringVar(&email, []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  	serverAddress := registry.IndexServer
    42  	if len(cmd.Args()) > 0 {
    43  		serverAddress = cmd.Arg(0)
    44  	}
    45  
    46  	promptDefault := func(prompt string, configDefault string) {
    47  		if configDefault == "" {
    48  			fmt.Fprintf(cli.out, "%s: ", prompt)
    49  		} else {
    50  			fmt.Fprintf(cli.out, "%s (%s): ", prompt, configDefault)
    51  		}
    52  	}
    53  
    54  	readInput := func(in io.Reader, out io.Writer) string {
    55  		reader := bufio.NewReader(in)
    56  		line, _, err := reader.ReadLine()
    57  		if err != nil {
    58  			fmt.Fprintln(out, err.Error())
    59  			os.Exit(1)
    60  		}
    61  		return string(line)
    62  	}
    63  
    64  	authconfig, ok := cli.configFile.AuthConfigs[serverAddress]
    65  	if !ok {
    66  		authconfig = types.AuthConfig{}
    67  	}
    68  
    69  	if username == "" {
    70  		promptDefault("Username", authconfig.Username)
    71  		username = readInput(cli.in, cli.out)
    72  		username = strings.TrimSpace(username)
    73  		if username == "" {
    74  			username = authconfig.Username
    75  		}
    76  	}
    77  	// Assume that a different username means they may not want to use
    78  	// the password or email from the config file, so prompt them
    79  	if username != authconfig.Username {
    80  		if password == "" {
    81  			oldState, err := term.SaveState(cli.inFd)
    82  			if err != nil {
    83  				return err
    84  			}
    85  			fmt.Fprintf(cli.out, "Password: ")
    86  			term.DisableEcho(cli.inFd, oldState)
    87  
    88  			password = readInput(cli.in, cli.out)
    89  			fmt.Fprint(cli.out, "\n")
    90  
    91  			term.RestoreTerminal(cli.inFd, oldState)
    92  			if password == "" {
    93  				return fmt.Errorf("Error : Password Required")
    94  			}
    95  		}
    96  
    97  		if email == "" {
    98  			promptDefault("Email", authconfig.Email)
    99  			email = readInput(cli.in, cli.out)
   100  			if email == "" {
   101  				email = authconfig.Email
   102  			}
   103  		}
   104  	} else {
   105  		// However, if they don't override the username use the
   106  		// password or email from the cmd line if specified. IOW, allow
   107  		// then to change/override them.  And if not specified, just
   108  		// use what's in the config file
   109  		if password == "" {
   110  			password = authconfig.Password
   111  		}
   112  		if email == "" {
   113  			email = authconfig.Email
   114  		}
   115  	}
   116  	authconfig.Username = username
   117  	authconfig.Password = password
   118  	authconfig.Email = email
   119  	authconfig.ServerAddress = serverAddress
   120  	cli.configFile.AuthConfigs[serverAddress] = authconfig
   121  
   122  	auth := cli.configFile.AuthConfigs[serverAddress]
   123  	response, err := cli.client.RegistryLogin(auth)
   124  	if err != nil {
   125  		if client.IsErrUnauthorized(err) {
   126  			delete(cli.configFile.AuthConfigs, serverAddress)
   127  			if err2 := cli.configFile.Save(); err2 != nil {
   128  				fmt.Fprintf(cli.out, "WARNING: could not save config file: %v\n", err2)
   129  			}
   130  		}
   131  		return err
   132  	}
   133  
   134  	if err := cli.configFile.Save(); err != nil {
   135  		return fmt.Errorf("Error saving config file: %v", err)
   136  	}
   137  	fmt.Fprintf(cli.out, "WARNING: login credentials saved in %s\n", cli.configFile.Filename())
   138  
   139  	if response.Status != "" {
   140  		fmt.Fprintf(cli.out, "%s\n", response.Status)
   141  	}
   142  	return nil
   143  }