From da693b64239133b048a71ab9148fc7230536d729 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Thu, 3 Dec 2015 19:12:35 -0500 Subject: [PATCH] Implement docker login with standalone client lib. Signed-off-by: David Calavera Upstream-commit: b36531db6020134c8b561db71a67c4346051ed4a Component: engine --- components/engine/api/client/lib/errors.go | 32 +++++++++++++--------- components/engine/api/client/lib/login.go | 28 +++++++++++++++++++ components/engine/api/client/login.go | 28 ++++++------------- 3 files changed, 56 insertions(+), 32 deletions(-) create mode 100644 components/engine/api/client/lib/login.go diff --git a/components/engine/api/client/lib/errors.go b/components/engine/api/client/lib/errors.go index 21a41f03f4..3ee56e6333 100644 --- a/components/engine/api/client/lib/errors.go +++ b/components/engine/api/client/lib/errors.go @@ -12,20 +12,26 @@ func (i imageNotFoundError) Error() string { return fmt.Sprintf("Image not found: %s", i.imageID) } -// ImageNotFound returns the ID of the image not found on the docker host. -func (i imageNotFoundError) ImageIDNotFound() string { - return i.imageID -} - -// ImageNotFound is an interface that describes errors caused -// when an image is not found in the docker host. -type ImageNotFound interface { - ImageIDNotFound() string -} - -// IsImageNotFound returns true when the error is caused +// IsImageNotFound returns true if the error is caused // when an image is not found in the docker host. func IsErrImageNotFound(err error) bool { - _, ok := err.(ImageNotFound) + _, ok := err.(imageNotFoundError) + return ok +} + +// unauthorizedError represents an authorization error in a remote registry. +type unauthorizedError struct { + cause error +} + +// Error returns a string representation of an unauthorizedError +func (u unauthorizedError) Error() string { + return u.cause.Error() +} + +// IsUnauthorized returns true if the error is caused +// when an the remote registry authentication fails +func IsErrUnauthorized(err error) bool { + _, ok := err.(unauthorizedError) return ok } diff --git a/components/engine/api/client/lib/login.go b/components/engine/api/client/lib/login.go new file mode 100644 index 0000000000..ca194150ed --- /dev/null +++ b/components/engine/api/client/lib/login.go @@ -0,0 +1,28 @@ +package lib + +import ( + "encoding/json" + "net/http" + "net/url" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/cliconfig" +) + +// RegistryLogin authenticates the docker server with a given docker registry. +// It returns UnauthorizerError when the authentication fails. +func (cli *Client) RegistryLogin(auth cliconfig.AuthConfig) (types.AuthResponse, error) { + resp, err := cli.POST("/auth", url.Values{}, auth, nil) + + if resp != nil && resp.statusCode == http.StatusUnauthorized { + return types.AuthResponse{}, unauthorizedError{err} + } + if err != nil { + return types.AuthResponse{}, err + } + defer resp.body.Close() + + var response types.AuthResponse + err = json.NewDecoder(resp.body).Decode(&response) + return response, err +} diff --git a/components/engine/api/client/login.go b/components/engine/api/client/login.go index e941a14efe..31022919c9 100644 --- a/components/engine/api/client/login.go +++ b/components/engine/api/client/login.go @@ -2,14 +2,13 @@ package client import ( "bufio" - "encoding/json" "fmt" "io" "os" "runtime" "strings" - "github.com/docker/docker/api/types" + "github.com/docker/docker/api/client/lib" Cli "github.com/docker/docker/cli" "github.com/docker/docker/cliconfig" flag "github.com/docker/docker/pkg/mflag" @@ -120,24 +119,15 @@ func (cli *DockerCli) CmdLogin(args ...string) error { authconfig.ServerAddress = serverAddress cli.configFile.AuthConfigs[serverAddress] = authconfig - serverResp, err := cli.call("POST", "/auth", cli.configFile.AuthConfigs[serverAddress], nil) - if serverResp.statusCode == 401 { - delete(cli.configFile.AuthConfigs, serverAddress) - if err2 := cli.configFile.Save(); err2 != nil { - fmt.Fprintf(cli.out, "WARNING: could not save config file: %v\n", err2) - } - return err - } + auth := cli.configFile.AuthConfigs[serverAddress] + response, err := cli.client.RegistryLogin(auth) if err != nil { - return err - } - - defer serverResp.body.Close() - - var response types.AuthResponse - if err := json.NewDecoder(serverResp.body).Decode(&response); err != nil { - // Upon error, remove entry - delete(cli.configFile.AuthConfigs, serverAddress) + if lib.IsErrUnauthorized(err) { + delete(cli.configFile.AuthConfigs, serverAddress) + if err2 := cli.configFile.Save(); err2 != nil { + fmt.Fprintf(cli.out, "WARNING: could not save config file: %v\n", err2) + } + } return err }