Implement docker login with standalone client lib.

Signed-off-by: David Calavera <david.calavera@gmail.com>
This commit is contained in:
David Calavera 2015-12-03 19:12:35 -05:00
parent 9073a52ea8
commit b36531db60
3 changed files with 56 additions and 32 deletions

View file

@ -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
}

28
api/client/lib/login.go Normal file
View file

@ -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
}

View file

@ -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
}