Skip to content

Commit

Permalink
Remove email address field from login
Browse files Browse the repository at this point in the history
This removes the email prompt when you use docker login, and also removes the ability to register via the docker cli. Docker login, will strictly be used for logging into a registry server.

Signed-off-by: Ken Cochrane <[email protected]>
  • Loading branch information
kencochrane authored and dmcgowan committed Mar 1, 2016
1 parent 6a96006 commit aee260d
Show file tree
Hide file tree
Showing 18 changed files with 180 additions and 182 deletions.
37 changes: 12 additions & 25 deletions api/client/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
"github.com/docker/engine-api/types"
)

// CmdLogin logs in or registers a user to a Docker registry service.
// CmdLogin logs in a user to a Docker registry service.
//
// If no server is specified, the user will be logged into or registered to the registry's index server.
//
Expand All @@ -28,7 +28,9 @@ func (cli *DockerCli) CmdLogin(args ...string) error {

flUser := cmd.String([]string{"u", "-username"}, "", "Username")
flPassword := cmd.String([]string{"p", "-password"}, "", "Password")
flEmail := cmd.String([]string{"e", "-email"}, "", "Email")

// Deprecated in 1.11: Should be removed in docker 1.13
cmd.String([]string{"#e", "#-email"}, "", "Email")

cmd.ParseFlags(args, true)

Expand All @@ -38,13 +40,15 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
}

var serverAddress string
var isDefaultRegistry bool
if len(cmd.Args()) > 0 {
serverAddress = cmd.Arg(0)
} else {
serverAddress = cli.electAuthServer()
isDefaultRegistry = true
}

authConfig, err := cli.configureAuth(*flUser, *flPassword, *flEmail, serverAddress)
authConfig, err := cli.configureAuth(*flUser, *flPassword, serverAddress, isDefaultRegistry)
if err != nil {
return err
}
Expand Down Expand Up @@ -77,7 +81,7 @@ func (cli *DockerCli) promptWithDefault(prompt string, configDefault string) {
}
}

func (cli *DockerCli) configureAuth(flUser, flPassword, flEmail, serverAddress string) (types.AuthConfig, error) {
func (cli *DockerCli) configureAuth(flUser, flPassword, serverAddress string, isDefaultRegistry bool) (types.AuthConfig, error) {
authconfig, err := getCredentials(cli.configFile, serverAddress)
if err != nil {
return authconfig, err
Expand All @@ -86,6 +90,10 @@ func (cli *DockerCli) configureAuth(flUser, flPassword, flEmail, serverAddress s
authconfig.Username = strings.TrimSpace(authconfig.Username)

if flUser = strings.TrimSpace(flUser); flUser == "" {
if isDefaultRegistry {
// if this is a defauly registry (docker hub), then display the following message.
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.")
}
cli.promptWithDefault("Username", authconfig.Username)
flUser = readInput(cli.in, cli.out)
flUser = strings.TrimSpace(flUser)
Expand Down Expand Up @@ -115,29 +123,8 @@ func (cli *DockerCli) configureAuth(flUser, flPassword, flEmail, serverAddress s
}
}

// Assume that a different username means they may not want to use
// the email from the config file, so prompt it
if flUser != authconfig.Username {
if flEmail == "" {
cli.promptWithDefault("Email", authconfig.Email)
flEmail = readInput(cli.in, cli.out)
if flEmail == "" {
flEmail = authconfig.Email
}
}
} else {
// However, if they don't override the username use the
// email from the cmd line if specified. IOW, allow
// then to change/override them. And if not specified, just
// use what's in the config file
if flEmail == "" {
flEmail = authconfig.Email
}
}

authconfig.Username = flUser
authconfig.Password = flPassword
authconfig.Email = flEmail
authconfig.ServerAddress = serverAddress

return authconfig, nil
Expand Down
2 changes: 1 addition & 1 deletion api/client/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (cli *DockerCli) registryAuthenticationPrivilegedFunc(index *registrytypes.
return func() (string, error) {
fmt.Fprintf(cli.out, "\nPlease login prior to %s:\n", cmdName)
indexServer := registry.GetAuthConfigKey(index)
authConfig, err := cli.configureAuth("", "", "", indexServer)
authConfig, err := cli.configureAuth("", "", indexServer, false)
if err != nil {
return "", err
}
Expand Down
5 changes: 0 additions & 5 deletions cliconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,6 @@ func (configFile *ConfigFile) LegacyLoadFromReader(configData io.Reader) error {
if err != nil {
return err
}
origEmail := strings.Split(arr[1], " = ")
if len(origEmail) != 2 {
return fmt.Errorf("Invalid Auth config file")
}
authConfig.Email = origEmail[1]
authConfig.ServerAddress = defaultIndexserver
configFile.AuthConfigs[defaultIndexserver] = authConfig
} else {
Expand Down
127 changes: 102 additions & 25 deletions cliconfig/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,9 @@ func TestOldInvalidsAuth(t *testing.T) {
invalids := map[string]string{
`username = test`: "The Auth config file is empty",
`username
password
email`: "Invalid Auth config file",
password`: "Invalid Auth config file",
`username = test
email`: "Invalid auth configuration file",
`username = am9lam9lOmhlbGxv
email`: "Invalid Auth config file",
}

tmpHome, err := ioutil.TempDir("", "config-test")
Expand Down Expand Up @@ -164,7 +161,7 @@ func TestOldValidAuth(t *testing.T) {

fn := filepath.Join(tmpHome, oldConfigfile)
js := `username = am9lam9lOmhlbGxv
email = [email protected]`
email = [email protected]`
if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil {
t.Fatal(err)
}
Expand All @@ -176,15 +173,23 @@ email = [email protected]`

// defaultIndexserver is https://index.docker.io/v1/
ac := config.AuthConfigs["https://index.docker.io/v1/"]
if ac.Email != "[email protected]" || ac.Username != "joejoe" || ac.Password != "hello" {
if ac.Username != "joejoe" || ac.Password != "hello" {
t.Fatalf("Missing data from parsing:\n%q", config)
}

// Now save it and make sure it shows up in new form
configStr := saveConfigAndValidateNewFormat(t, config, tmpHome)

if !strings.Contains(configStr, "[email protected]") {
t.Fatalf("Should have save in new form: %s", configStr)
expConfStr := `{
"auths": {
"https://index.docker.io/v1/": {
"auth": "am9lam9lOmhlbGxv"
}
}
}`

if configStr != expConfStr {
t.Fatalf("Should have save in new form: \n%s\n not \n%s", configStr, expConfStr)
}
}

Expand Down Expand Up @@ -239,15 +244,24 @@ func TestOldJson(t *testing.T) {
}

ac := config.AuthConfigs["https://index.docker.io/v1/"]
if ac.Email != "[email protected]" || ac.Username != "joejoe" || ac.Password != "hello" {
if ac.Username != "joejoe" || ac.Password != "hello" {
t.Fatalf("Missing data from parsing:\n%q", config)
}

// Now save it and make sure it shows up in new form
configStr := saveConfigAndValidateNewFormat(t, config, tmpHome)

if !strings.Contains(configStr, "[email protected]") {
t.Fatalf("Should have save in new form: %s", configStr)
expConfStr := `{
"auths": {
"https://index.docker.io/v1/": {
"auth": "am9lam9lOmhlbGxv",
"email": "[email protected]"
}
}
}`

if configStr != expConfStr {
t.Fatalf("Should have save in new form: \n'%s'\n not \n'%s'\n", configStr, expConfStr)
}
}

Expand All @@ -259,7 +273,7 @@ func TestNewJson(t *testing.T) {
defer os.RemoveAll(tmpHome)

fn := filepath.Join(tmpHome, ConfigFileName)
js := ` { "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "[email protected]" } } }`
js := ` { "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv" } } }`
if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil {
t.Fatal(err)
}
Expand All @@ -270,15 +284,62 @@ func TestNewJson(t *testing.T) {
}

ac := config.AuthConfigs["https://index.docker.io/v1/"]
if ac.Email != "[email protected]" || ac.Username != "joejoe" || ac.Password != "hello" {
if ac.Username != "joejoe" || ac.Password != "hello" {
t.Fatalf("Missing data from parsing:\n%q", config)
}

// Now save it and make sure it shows up in new form
configStr := saveConfigAndValidateNewFormat(t, config, tmpHome)

if !strings.Contains(configStr, "[email protected]") {
t.Fatalf("Should have save in new form: %s", configStr)
expConfStr := `{
"auths": {
"https://index.docker.io/v1/": {
"auth": "am9lam9lOmhlbGxv"
}
}
}`

if configStr != expConfStr {
t.Fatalf("Should have save in new form: \n%s\n not \n%s", configStr, expConfStr)
}
}

func TestNewJsonNoEmail(t *testing.T) {
tmpHome, err := ioutil.TempDir("", "config-test")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpHome)

fn := filepath.Join(tmpHome, ConfigFileName)
js := ` { "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv" } } }`
if err := ioutil.WriteFile(fn, []byte(js), 0600); err != nil {
t.Fatal(err)
}

config, err := Load(tmpHome)
if err != nil {
t.Fatalf("Failed loading on empty json file: %q", err)
}

ac := config.AuthConfigs["https://index.docker.io/v1/"]
if ac.Username != "joejoe" || ac.Password != "hello" {
t.Fatalf("Missing data from parsing:\n%q", config)
}

// Now save it and make sure it shows up in new form
configStr := saveConfigAndValidateNewFormat(t, config, tmpHome)

expConfStr := `{
"auths": {
"https://index.docker.io/v1/": {
"auth": "am9lam9lOmhlbGxv"
}
}
}`

if configStr != expConfStr {
t.Fatalf("Should have save in new form: \n%s\n not \n%s", configStr, expConfStr)
}
}

Expand Down Expand Up @@ -366,7 +427,7 @@ func TestJsonReaderNoFile(t *testing.T) {
}

ac := config.AuthConfigs["https://index.docker.io/v1/"]
if ac.Email != "[email protected]" || ac.Username != "joejoe" || ac.Password != "hello" {
if ac.Username != "joejoe" || ac.Password != "hello" {
t.Fatalf("Missing data from parsing:\n%q", config)
}

Expand All @@ -381,7 +442,7 @@ func TestOldJsonReaderNoFile(t *testing.T) {
}

ac := config.AuthConfigs["https://index.docker.io/v1/"]
if ac.Email != "[email protected]" || ac.Username != "joejoe" || ac.Password != "hello" {
if ac.Username != "joejoe" || ac.Password != "hello" {
t.Fatalf("Missing data from parsing:\n%q", config)
}
}
Expand All @@ -404,7 +465,7 @@ func TestJsonWithPsFormatNoFile(t *testing.T) {

func TestJsonSaveWithNoFile(t *testing.T) {
js := `{
"auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "[email protected]" } },
"auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv" } },
"psFormat": "table {{.ID}}\\t{{.Label \"com.docker.label.cpu\"}}"
}`
config, err := LoadFromReader(strings.NewReader(js))
Expand All @@ -426,9 +487,16 @@ func TestJsonSaveWithNoFile(t *testing.T) {
t.Fatalf("Failed saving to file: %q", err)
}
buf, err := ioutil.ReadFile(filepath.Join(tmpHome, ConfigFileName))
if !strings.Contains(string(buf), `"auths":`) ||
!strings.Contains(string(buf), "[email protected]") {
t.Fatalf("Should have save in new form: %s", string(buf))
expConfStr := `{
"auths": {
"https://index.docker.io/v1/": {
"auth": "am9lam9lOmhlbGxv"
}
},
"psFormat": "table {{.ID}}\\t{{.Label \"com.docker.label.cpu\"}}"
}`
if string(buf) != expConfStr {
t.Fatalf("Should have save in new form: \n%s\nnot \n%s", string(buf), expConfStr)
}
}

Expand All @@ -454,14 +522,23 @@ func TestLegacyJsonSaveWithNoFile(t *testing.T) {
t.Fatalf("Failed saving to file: %q", err)
}
buf, err := ioutil.ReadFile(filepath.Join(tmpHome, ConfigFileName))
if !strings.Contains(string(buf), `"auths":`) ||
!strings.Contains(string(buf), "[email protected]") {
t.Fatalf("Should have save in new form: %s", string(buf))

expConfStr := `{
"auths": {
"https://index.docker.io/v1/": {
"auth": "am9lam9lOmhlbGxv",
"email": "[email protected]"
}
}
}`

if string(buf) != expConfStr {
t.Fatalf("Should have save in new form: \n%s\n not \n%s", string(buf), expConfStr)
}
}

func TestEncodeAuth(t *testing.T) {
newAuthConfig := &types.AuthConfig{Username: "ken", Password: "test", Email: "[email protected]"}
newAuthConfig := &types.AuthConfig{Username: "ken", Password: "test"}
authStr := encodeAuth(newAuthConfig)
decAuthConfig := &types.AuthConfig{}
var err error
Expand Down
6 changes: 3 additions & 3 deletions contrib/completion/bash/docker
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,7 @@ _docker_daemon() {
return
;;
esac

local key=$(__docker_map_key_of_current_option '--storage-opt')
case "$key" in
dm.@(blkdiscard|override_udev_sync_check|use_deferred_@(removal|deletion)))
Expand Down Expand Up @@ -1205,14 +1205,14 @@ _docker_load() {

_docker_login() {
case "$prev" in
--email|-e|--password|-p|--username|-u)
--password|-p|--username|-u)
return
;;
esac

case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--email -e --help --password -p --username -u" -- "$cur" ) )
COMPREPLY=( $( compgen -W "--help --password -p --username -u" -- "$cur" ) )
;;
esac
}
Expand Down
5 changes: 1 addition & 4 deletions contrib/completion/fish/docker.fish
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,7 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from load' -l help -d 'Print
complete -c docker -A -f -n '__fish_seen_subcommand_from load' -s i -l input -d 'Read from a tar archive file, instead of STDIN'

# login
complete -c docker -f -n '__fish_docker_no_subcommand' -a login -d 'Register or log in to a Docker registry server'
complete -c docker -A -f -n '__fish_seen_subcommand_from login' -s e -l email -d 'Email'
complete -c docker -f -n '__fish_docker_no_subcommand' -a login -d 'Log in to a Docker registry server'
complete -c docker -A -f -n '__fish_seen_subcommand_from login' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from login' -s p -l password -d 'Password'
complete -c docker -A -f -n '__fish_seen_subcommand_from login' -s u -l username -d 'Username'
Expand Down Expand Up @@ -399,5 +398,3 @@ complete -c docker -f -n '__fish_docker_no_subcommand' -a version -d 'Show the D
complete -c docker -f -n '__fish_docker_no_subcommand' -a wait -d 'Block until a container stops, then print its exit code'
complete -c docker -A -f -n '__fish_seen_subcommand_from wait' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from wait' -a '(__fish_print_docker_containers running)' -d "Container"


1 change: 0 additions & 1 deletion contrib/completion/zsh/_docker
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,6 @@ __docker_subcommand() {
(login)
_arguments $(__docker_arguments) \
$opts_help \
"($help -e --email)"{-e=,--email=}"[Email]:email: " \
"($help -p --password)"{-p=,--password=}"[Password]:password: " \
"($help -u --user)"{-u=,--user=}"[Username]:username: " \
"($help -)1:server: " && ret=0
Expand Down
7 changes: 7 additions & 0 deletions docs/deprecated.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ weight=80

The following list of features are deprecated in Engine.

### `-e` and `--email` flags on `docker login`
**Deprecated In Release: v1.11**

**Target For Removal In Release: v1.13**

The docker login command is removing the ability to automatically register for an account with the target registry if the given username doesn't exist. Due to this change, the email flag is no longer required, and will be deprecated.

### Ambiguous event fields in API
**Deprecated In Release: v1.10**

Expand Down
Loading

0 comments on commit aee260d

Please sign in to comment.