github.com/crquan/docker@v1.8.1/api/client/login.go (about)

     1  package client
     2  
     3  import (
     4  	"bufio"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"os"
     9  	"strings"
    10  
    11  	"github.com/docker/docker/api/types"
    12  	Cli "github.com/docker/docker/cli"
    13  	"github.com/docker/docker/cliconfig"
    14  	flag "github.com/docker/docker/pkg/mflag"
    15  	"github.com/docker/docker/pkg/term"
    16  	"github.com/docker/docker/registry"
    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]"}, "Register or log in to a Docker registry server, if no server is\nspecified \""+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  	serverAddress := registry.IndexServer
    37  	if len(cmd.Args()) > 0 {
    38  		serverAddress = cmd.Arg(0)
    39  	}
    40  
    41  	promptDefault := func(prompt string, configDefault string) {
    42  		if configDefault == "" {
    43  			fmt.Fprintf(cli.out, "%s: ", prompt)
    44  		} else {
    45  			fmt.Fprintf(cli.out, "%s (%s): ", prompt, configDefault)
    46  		}
    47  	}
    48  
    49  	readInput := func(in io.Reader, out io.Writer) string {
    50  		reader := bufio.NewReader(in)
    51  		line, _, err := reader.ReadLine()
    52  		if err != nil {
    53  			fmt.Fprintln(out, err.Error())
    54  			os.Exit(1)
    55  		}
    56  		return string(line)
    57  	}
    58  
    59  	authconfig, ok := cli.configFile.AuthConfigs[serverAddress]
    60  	if !ok {
    61  		authconfig = cliconfig.AuthConfig{}
    62  	}
    63  
    64  	if username == "" {
    65  		promptDefault("Username", authconfig.Username)
    66  		username = readInput(cli.in, cli.out)
    67  		username = strings.Trim(username, " ")
    68  		if username == "" {
    69  			username = authconfig.Username
    70  		}
    71  	}
    72  	// Assume that a different username means they may not want to use
    73  	// the password or email from the config file, so prompt them
    74  	if username != authconfig.Username {
    75  		if password == "" {
    76  			oldState, err := term.SaveState(cli.inFd)
    77  			if err != nil {
    78  				return err
    79  			}
    80  			fmt.Fprintf(cli.out, "Password: ")
    81  			term.DisableEcho(cli.inFd, oldState)
    82  
    83  			password = readInput(cli.in, cli.out)
    84  			fmt.Fprint(cli.out, "\n")
    85  
    86  			term.RestoreTerminal(cli.inFd, oldState)
    87  			if password == "" {
    88  				return fmt.Errorf("Error : Password Required")
    89  			}
    90  		}
    91  
    92  		if email == "" {
    93  			promptDefault("Email", authconfig.Email)
    94  			email = readInput(cli.in, cli.out)
    95  			if email == "" {
    96  				email = authconfig.Email
    97  			}
    98  		}
    99  	} else {
   100  		// However, if they don't override the username use the
   101  		// password or email from the cmd line if specified. IOW, allow
   102  		// then to change/override them.  And if not specified, just
   103  		// use what's in the config file
   104  		if password == "" {
   105  			password = authconfig.Password
   106  		}
   107  		if email == "" {
   108  			email = authconfig.Email
   109  		}
   110  	}
   111  	authconfig.Username = username
   112  	authconfig.Password = password
   113  	authconfig.Email = email
   114  	authconfig.ServerAddress = serverAddress
   115  	cli.configFile.AuthConfigs[serverAddress] = authconfig
   116  
   117  	serverResp, err := cli.call("POST", "/auth", cli.configFile.AuthConfigs[serverAddress], nil)
   118  	if serverResp.statusCode == 401 {
   119  		delete(cli.configFile.AuthConfigs, serverAddress)
   120  		if err2 := cli.configFile.Save(); err2 != nil {
   121  			fmt.Fprintf(cli.out, "WARNING: could not save config file: %v\n", err2)
   122  		}
   123  		return err
   124  	}
   125  	if err != nil {
   126  		return err
   127  	}
   128  
   129  	defer serverResp.body.Close()
   130  
   131  	var response types.AuthResponse
   132  	if err := json.NewDecoder(serverResp.body).Decode(&response); err != nil {
   133  		// Upon error, remove entry
   134  		delete(cli.configFile.AuthConfigs, serverAddress)
   135  		return err
   136  	}
   137  
   138  	if err := cli.configFile.Save(); err != nil {
   139  		return fmt.Errorf("Error saving config file: %v", err)
   140  	}
   141  	fmt.Fprintf(cli.out, "WARNING: login credentials saved in %s\n", cli.configFile.Filename())
   142  
   143  	if response.Status != "" {
   144  		fmt.Fprintf(cli.out, "%s\n", response.Status)
   145  	}
   146  	return nil
   147  }