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 }