Move CLI config processing out from under registry dir
No logic changes should be in here, just moving things around. Signed-off-by: Doug Davis <dug@us.ibm.com>master
							parent
							
								
									34d1494c7f
								
							
						
					
					
						commit
						a8b9bec104
					
				
							
								
								
									
										210
									
								
								docs/auth.go
								
								
								
								
							
							
						
						
									
										210
									
								
								docs/auth.go
								
								
								
								
							| 
						 | 
				
			
			@ -1,51 +1,21 @@
 | 
			
		|||
package registry
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"github.com/docker/docker/pkg/homedir"
 | 
			
		||||
	"github.com/docker/docker/cliconfig"
 | 
			
		||||
	"github.com/docker/docker/pkg/requestdecorator"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// Where we store the config file
 | 
			
		||||
	CONFIGFILE     = "config.json"
 | 
			
		||||
	OLD_CONFIGFILE = ".dockercfg"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	ErrConfigFileMissing = errors.New("The Auth config file is missing")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Registry Auth Info
 | 
			
		||||
type AuthConfig struct {
 | 
			
		||||
	Username      string `json:"username,omitempty"`
 | 
			
		||||
	Password      string `json:"password,omitempty"`
 | 
			
		||||
	Auth          string `json:"auth"`
 | 
			
		||||
	Email         string `json:"email"`
 | 
			
		||||
	ServerAddress string `json:"serveraddress,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ~/.docker/config.json file info
 | 
			
		||||
type ConfigFile struct {
 | 
			
		||||
	AuthConfigs map[string]AuthConfig `json:"auths"`
 | 
			
		||||
	HttpHeaders map[string]string     `json:"HttpHeaders,omitempty"`
 | 
			
		||||
	filename    string                // Note: not serialized - for internal use only
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type RequestAuthorization struct {
 | 
			
		||||
	authConfig       *AuthConfig
 | 
			
		||||
	authConfig       *cliconfig.AuthConfig
 | 
			
		||||
	registryEndpoint *Endpoint
 | 
			
		||||
	resource         string
 | 
			
		||||
	scope            string
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +26,7 @@ type RequestAuthorization struct {
 | 
			
		|||
	tokenExpiration time.Time
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewRequestAuthorization(authConfig *AuthConfig, registryEndpoint *Endpoint, resource, scope string, actions []string) *RequestAuthorization {
 | 
			
		||||
func NewRequestAuthorization(authConfig *cliconfig.AuthConfig, registryEndpoint *Endpoint, resource, scope string, actions []string) *RequestAuthorization {
 | 
			
		||||
	return &RequestAuthorization{
 | 
			
		||||
		authConfig:       authConfig,
 | 
			
		||||
		registryEndpoint: registryEndpoint,
 | 
			
		||||
| 
						 | 
				
			
			@ -121,160 +91,8 @@ func (auth *RequestAuthorization) Authorize(req *http.Request) error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// create a base64 encoded auth string to store in config
 | 
			
		||||
func encodeAuth(authConfig *AuthConfig) string {
 | 
			
		||||
	authStr := authConfig.Username + ":" + authConfig.Password
 | 
			
		||||
	msg := []byte(authStr)
 | 
			
		||||
	encoded := make([]byte, base64.StdEncoding.EncodedLen(len(msg)))
 | 
			
		||||
	base64.StdEncoding.Encode(encoded, msg)
 | 
			
		||||
	return string(encoded)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// decode the auth string
 | 
			
		||||
func decodeAuth(authStr string) (string, string, error) {
 | 
			
		||||
	decLen := base64.StdEncoding.DecodedLen(len(authStr))
 | 
			
		||||
	decoded := make([]byte, decLen)
 | 
			
		||||
	authByte := []byte(authStr)
 | 
			
		||||
	n, err := base64.StdEncoding.Decode(decoded, authByte)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", "", err
 | 
			
		||||
	}
 | 
			
		||||
	if n > decLen {
 | 
			
		||||
		return "", "", fmt.Errorf("Something went wrong decoding auth config")
 | 
			
		||||
	}
 | 
			
		||||
	arr := strings.SplitN(string(decoded), ":", 2)
 | 
			
		||||
	if len(arr) != 2 {
 | 
			
		||||
		return "", "", fmt.Errorf("Invalid auth configuration file")
 | 
			
		||||
	}
 | 
			
		||||
	password := strings.Trim(arr[1], "\x00")
 | 
			
		||||
	return arr[0], password, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// load up the auth config information and return values
 | 
			
		||||
// FIXME: use the internal golang config parser
 | 
			
		||||
func LoadConfig(configDir string) (*ConfigFile, error) {
 | 
			
		||||
	if configDir == "" {
 | 
			
		||||
		configDir = filepath.Join(homedir.Get(), ".docker")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	configFile := ConfigFile{
 | 
			
		||||
		AuthConfigs: make(map[string]AuthConfig),
 | 
			
		||||
		filename:    filepath.Join(configDir, CONFIGFILE),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Try happy path first - latest config file
 | 
			
		||||
	if _, err := os.Stat(configFile.filename); err == nil {
 | 
			
		||||
		file, err := os.Open(configFile.filename)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return &configFile, err
 | 
			
		||||
		}
 | 
			
		||||
		defer file.Close()
 | 
			
		||||
 | 
			
		||||
		if err := json.NewDecoder(file).Decode(&configFile); err != nil {
 | 
			
		||||
			return &configFile, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for addr, ac := range configFile.AuthConfigs {
 | 
			
		||||
			ac.Username, ac.Password, err = decodeAuth(ac.Auth)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return &configFile, err
 | 
			
		||||
			}
 | 
			
		||||
			ac.Auth = ""
 | 
			
		||||
			ac.ServerAddress = addr
 | 
			
		||||
			configFile.AuthConfigs[addr] = ac
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return &configFile, nil
 | 
			
		||||
	} else if !os.IsNotExist(err) {
 | 
			
		||||
		// if file is there but we can't stat it for any reason other
 | 
			
		||||
		// than it doesn't exist then stop
 | 
			
		||||
		return &configFile, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Can't find latest config file so check for the old one
 | 
			
		||||
	confFile := filepath.Join(homedir.Get(), OLD_CONFIGFILE)
 | 
			
		||||
 | 
			
		||||
	if _, err := os.Stat(confFile); err != nil {
 | 
			
		||||
		return &configFile, nil //missing file is not an error
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b, err := ioutil.ReadFile(confFile)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return &configFile, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := json.Unmarshal(b, &configFile.AuthConfigs); err != nil {
 | 
			
		||||
		arr := strings.Split(string(b), "\n")
 | 
			
		||||
		if len(arr) < 2 {
 | 
			
		||||
			return &configFile, fmt.Errorf("The Auth config file is empty")
 | 
			
		||||
		}
 | 
			
		||||
		authConfig := AuthConfig{}
 | 
			
		||||
		origAuth := strings.Split(arr[0], " = ")
 | 
			
		||||
		if len(origAuth) != 2 {
 | 
			
		||||
			return &configFile, fmt.Errorf("Invalid Auth config file")
 | 
			
		||||
		}
 | 
			
		||||
		authConfig.Username, authConfig.Password, err = decodeAuth(origAuth[1])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return &configFile, err
 | 
			
		||||
		}
 | 
			
		||||
		origEmail := strings.Split(arr[1], " = ")
 | 
			
		||||
		if len(origEmail) != 2 {
 | 
			
		||||
			return &configFile, fmt.Errorf("Invalid Auth config file")
 | 
			
		||||
		}
 | 
			
		||||
		authConfig.Email = origEmail[1]
 | 
			
		||||
		authConfig.ServerAddress = IndexServerAddress()
 | 
			
		||||
		// *TODO: Switch to using IndexServerName() instead?
 | 
			
		||||
		configFile.AuthConfigs[IndexServerAddress()] = authConfig
 | 
			
		||||
	} else {
 | 
			
		||||
		for k, authConfig := range configFile.AuthConfigs {
 | 
			
		||||
			authConfig.Username, authConfig.Password, err = decodeAuth(authConfig.Auth)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return &configFile, err
 | 
			
		||||
			}
 | 
			
		||||
			authConfig.Auth = ""
 | 
			
		||||
			authConfig.ServerAddress = k
 | 
			
		||||
			configFile.AuthConfigs[k] = authConfig
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return &configFile, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (configFile *ConfigFile) Save() error {
 | 
			
		||||
	// Encode sensitive data into a new/temp struct
 | 
			
		||||
	tmpAuthConfigs := make(map[string]AuthConfig, len(configFile.AuthConfigs))
 | 
			
		||||
	for k, authConfig := range configFile.AuthConfigs {
 | 
			
		||||
		authCopy := authConfig
 | 
			
		||||
 | 
			
		||||
		authCopy.Auth = encodeAuth(&authCopy)
 | 
			
		||||
		authCopy.Username = ""
 | 
			
		||||
		authCopy.Password = ""
 | 
			
		||||
		authCopy.ServerAddress = ""
 | 
			
		||||
		tmpAuthConfigs[k] = authCopy
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	saveAuthConfigs := configFile.AuthConfigs
 | 
			
		||||
	configFile.AuthConfigs = tmpAuthConfigs
 | 
			
		||||
	defer func() { configFile.AuthConfigs = saveAuthConfigs }()
 | 
			
		||||
 | 
			
		||||
	data, err := json.MarshalIndent(configFile, "", "\t")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := os.MkdirAll(filepath.Dir(configFile.filename), 0700); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = ioutil.WriteFile(configFile.filename, data, 0600)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Login tries to register/login to the registry server.
 | 
			
		||||
func Login(authConfig *AuthConfig, registryEndpoint *Endpoint, factory *requestdecorator.RequestFactory) (string, error) {
 | 
			
		||||
func Login(authConfig *cliconfig.AuthConfig, registryEndpoint *Endpoint, factory *requestdecorator.RequestFactory) (string, error) {
 | 
			
		||||
	// Separates the v2 registry login logic from the v1 logic.
 | 
			
		||||
	if registryEndpoint.Version == APIVersion2 {
 | 
			
		||||
		return loginV2(authConfig, registryEndpoint, factory)
 | 
			
		||||
| 
						 | 
				
			
			@ -283,7 +101,7 @@ func Login(authConfig *AuthConfig, registryEndpoint *Endpoint, factory *requestd
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// loginV1 tries to register/login to the v1 registry server.
 | 
			
		||||
func loginV1(authConfig *AuthConfig, registryEndpoint *Endpoint, factory *requestdecorator.RequestFactory) (string, error) {
 | 
			
		||||
func loginV1(authConfig *cliconfig.AuthConfig, registryEndpoint *Endpoint, factory *requestdecorator.RequestFactory) (string, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		status        string
 | 
			
		||||
		reqBody       []byte
 | 
			
		||||
| 
						 | 
				
			
			@ -396,7 +214,7 @@ func loginV1(authConfig *AuthConfig, registryEndpoint *Endpoint, factory *reques
 | 
			
		|||
// now, users should create their account through other means like directly from a web page
 | 
			
		||||
// served by the v2 registry service provider. Whether this will be supported in the future
 | 
			
		||||
// is to be determined.
 | 
			
		||||
func loginV2(authConfig *AuthConfig, registryEndpoint *Endpoint, factory *requestdecorator.RequestFactory) (string, error) {
 | 
			
		||||
func loginV2(authConfig *cliconfig.AuthConfig, registryEndpoint *Endpoint, factory *requestdecorator.RequestFactory) (string, error) {
 | 
			
		||||
	logrus.Debugf("attempting v2 login to registry endpoint %s", registryEndpoint)
 | 
			
		||||
	var (
 | 
			
		||||
		err       error
 | 
			
		||||
| 
						 | 
				
			
			@ -429,7 +247,7 @@ func loginV2(authConfig *AuthConfig, registryEndpoint *Endpoint, factory *reques
 | 
			
		|||
	return "", fmt.Errorf("no successful auth challenge for %s - errors: %s", registryEndpoint, allErrors)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func tryV2BasicAuthLogin(authConfig *AuthConfig, params map[string]string, registryEndpoint *Endpoint, client *http.Client, factory *requestdecorator.RequestFactory) error {
 | 
			
		||||
func tryV2BasicAuthLogin(authConfig *cliconfig.AuthConfig, params map[string]string, registryEndpoint *Endpoint, client *http.Client, factory *requestdecorator.RequestFactory) error {
 | 
			
		||||
	req, err := factory.NewRequest("GET", registryEndpoint.Path(""), nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
| 
						 | 
				
			
			@ -450,7 +268,7 @@ func tryV2BasicAuthLogin(authConfig *AuthConfig, params map[string]string, regis
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func tryV2TokenAuthLogin(authConfig *AuthConfig, params map[string]string, registryEndpoint *Endpoint, client *http.Client, factory *requestdecorator.RequestFactory) error {
 | 
			
		||||
func tryV2TokenAuthLogin(authConfig *cliconfig.AuthConfig, params map[string]string, registryEndpoint *Endpoint, client *http.Client, factory *requestdecorator.RequestFactory) error {
 | 
			
		||||
	token, err := getToken(authConfig.Username, authConfig.Password, params, registryEndpoint, client, factory)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
| 
						 | 
				
			
			@ -477,7 +295,7 @@ func tryV2TokenAuthLogin(authConfig *AuthConfig, params map[string]string, regis
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// this method matches a auth configuration to a server address or a url
 | 
			
		||||
func (config *ConfigFile) ResolveAuthConfig(index *IndexInfo) AuthConfig {
 | 
			
		||||
func ResolveAuthConfig(config *cliconfig.ConfigFile, index *IndexInfo) cliconfig.AuthConfig {
 | 
			
		||||
	configKey := index.GetAuthConfigKey()
 | 
			
		||||
	// First try the happy case
 | 
			
		||||
	if c, found := config.AuthConfigs[configKey]; found || index.Official {
 | 
			
		||||
| 
						 | 
				
			
			@ -499,16 +317,12 @@ func (config *ConfigFile) ResolveAuthConfig(index *IndexInfo) AuthConfig {
 | 
			
		|||
 | 
			
		||||
	// Maybe they have a legacy config file, we will iterate the keys converting
 | 
			
		||||
	// them to the new format and testing
 | 
			
		||||
	for registry, config := range config.AuthConfigs {
 | 
			
		||||
	for registry, ac := range config.AuthConfigs {
 | 
			
		||||
		if configKey == convertToHostname(registry) {
 | 
			
		||||
			return config
 | 
			
		||||
			return ac
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// When all else fails, return an empty auth config
 | 
			
		||||
	return AuthConfig{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (config *ConfigFile) Filename() string {
 | 
			
		||||
	return config.filename
 | 
			
		||||
	return cliconfig.AuthConfig{}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,14 +5,16 @@ import (
 | 
			
		|||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/cliconfig"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestEncodeAuth(t *testing.T) {
 | 
			
		||||
	newAuthConfig := &AuthConfig{Username: "ken", Password: "test", Email: "test@example.com"}
 | 
			
		||||
	authStr := encodeAuth(newAuthConfig)
 | 
			
		||||
	decAuthConfig := &AuthConfig{}
 | 
			
		||||
	newAuthConfig := &cliconfig.AuthConfig{Username: "ken", Password: "test", Email: "test@example.com"}
 | 
			
		||||
	authStr := cliconfig.EncodeAuth(newAuthConfig)
 | 
			
		||||
	decAuthConfig := &cliconfig.AuthConfig{}
 | 
			
		||||
	var err error
 | 
			
		||||
	decAuthConfig.Username, decAuthConfig.Password, err = decodeAuth(authStr)
 | 
			
		||||
	decAuthConfig.Username, decAuthConfig.Password, err = cliconfig.DecodeAuth(authStr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -27,19 +29,16 @@ func TestEncodeAuth(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func setupTempConfigFile() (*ConfigFile, error) {
 | 
			
		||||
func setupTempConfigFile() (*cliconfig.ConfigFile, error) {
 | 
			
		||||
	root, err := ioutil.TempDir("", "docker-test-auth")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	root = filepath.Join(root, CONFIGFILE)
 | 
			
		||||
	configFile := &ConfigFile{
 | 
			
		||||
		AuthConfigs: make(map[string]AuthConfig),
 | 
			
		||||
		filename:    root,
 | 
			
		||||
	}
 | 
			
		||||
	root = filepath.Join(root, cliconfig.CONFIGFILE)
 | 
			
		||||
	configFile := cliconfig.NewConfigFile(root)
 | 
			
		||||
 | 
			
		||||
	for _, registry := range []string{"testIndex", IndexServerAddress()} {
 | 
			
		||||
		configFile.AuthConfigs[registry] = AuthConfig{
 | 
			
		||||
		configFile.AuthConfigs[registry] = cliconfig.AuthConfig{
 | 
			
		||||
			Username: "docker-user",
 | 
			
		||||
			Password: "docker-pass",
 | 
			
		||||
			Email:    "docker@docker.io",
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +53,7 @@ func TestSameAuthDataPostSave(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	defer os.RemoveAll(configFile.filename)
 | 
			
		||||
	defer os.RemoveAll(configFile.Filename())
 | 
			
		||||
 | 
			
		||||
	err = configFile.Save()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -81,7 +80,7 @@ func TestResolveAuthConfigIndexServer(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	defer os.RemoveAll(configFile.filename)
 | 
			
		||||
	defer os.RemoveAll(configFile.Filename())
 | 
			
		||||
 | 
			
		||||
	indexConfig := configFile.AuthConfigs[IndexServerAddress()]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -92,10 +91,10 @@ func TestResolveAuthConfigIndexServer(t *testing.T) {
 | 
			
		|||
		Official: false,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resolved := configFile.ResolveAuthConfig(officialIndex)
 | 
			
		||||
	resolved := ResolveAuthConfig(configFile, officialIndex)
 | 
			
		||||
	assertEqual(t, resolved, indexConfig, "Expected ResolveAuthConfig to return IndexServerAddress()")
 | 
			
		||||
 | 
			
		||||
	resolved = configFile.ResolveAuthConfig(privateIndex)
 | 
			
		||||
	resolved = ResolveAuthConfig(configFile, privateIndex)
 | 
			
		||||
	assertNotEqual(t, resolved, indexConfig, "Expected ResolveAuthConfig to not return IndexServerAddress()")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -104,26 +103,26 @@ func TestResolveAuthConfigFullURL(t *testing.T) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	defer os.RemoveAll(configFile.filename)
 | 
			
		||||
	defer os.RemoveAll(configFile.Filename())
 | 
			
		||||
 | 
			
		||||
	registryAuth := AuthConfig{
 | 
			
		||||
	registryAuth := cliconfig.AuthConfig{
 | 
			
		||||
		Username: "foo-user",
 | 
			
		||||
		Password: "foo-pass",
 | 
			
		||||
		Email:    "foo@example.com",
 | 
			
		||||
	}
 | 
			
		||||
	localAuth := AuthConfig{
 | 
			
		||||
	localAuth := cliconfig.AuthConfig{
 | 
			
		||||
		Username: "bar-user",
 | 
			
		||||
		Password: "bar-pass",
 | 
			
		||||
		Email:    "bar@example.com",
 | 
			
		||||
	}
 | 
			
		||||
	officialAuth := AuthConfig{
 | 
			
		||||
	officialAuth := cliconfig.AuthConfig{
 | 
			
		||||
		Username: "baz-user",
 | 
			
		||||
		Password: "baz-pass",
 | 
			
		||||
		Email:    "baz@example.com",
 | 
			
		||||
	}
 | 
			
		||||
	configFile.AuthConfigs[IndexServerAddress()] = officialAuth
 | 
			
		||||
 | 
			
		||||
	expectedAuths := map[string]AuthConfig{
 | 
			
		||||
	expectedAuths := map[string]cliconfig.AuthConfig{
 | 
			
		||||
		"registry.example.com": registryAuth,
 | 
			
		||||
		"localhost:8000":       localAuth,
 | 
			
		||||
		"registry.com":         localAuth,
 | 
			
		||||
| 
						 | 
				
			
			@ -160,12 +159,12 @@ func TestResolveAuthConfigFullURL(t *testing.T) {
 | 
			
		|||
		}
 | 
			
		||||
		for _, registry := range registries {
 | 
			
		||||
			configFile.AuthConfigs[registry] = configured
 | 
			
		||||
			resolved := configFile.ResolveAuthConfig(index)
 | 
			
		||||
			resolved := ResolveAuthConfig(configFile, index)
 | 
			
		||||
			if resolved.Email != configured.Email {
 | 
			
		||||
				t.Errorf("%s -> %q != %q\n", registry, resolved.Email, configured.Email)
 | 
			
		||||
			}
 | 
			
		||||
			delete(configFile.AuthConfigs, registry)
 | 
			
		||||
			resolved = configFile.ResolveAuthConfig(index)
 | 
			
		||||
			resolved = ResolveAuthConfig(configFile, index)
 | 
			
		||||
			if resolved.Email == configured.Email {
 | 
			
		||||
				t.Errorf("%s -> %q == %q\n", registry, resolved.Email, configured.Email)
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,157 +0,0 @@
 | 
			
		|||
package registry
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/pkg/homedir"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestMissingFile(t *testing.T) {
 | 
			
		||||
	tmpHome, _ := ioutil.TempDir("", "config-test")
 | 
			
		||||
 | 
			
		||||
	config, err := LoadConfig(tmpHome)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed loading on missing file: %q", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Now save it and make sure it shows up in new form
 | 
			
		||||
	err = config.Save()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed to save: %q", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buf, err := ioutil.ReadFile(filepath.Join(tmpHome, CONFIGFILE))
 | 
			
		||||
	if !strings.Contains(string(buf), `"auths":`) {
 | 
			
		||||
		t.Fatalf("Should have save in new form: %s", string(buf))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestSaveFileToDirs(t *testing.T) {
 | 
			
		||||
	tmpHome, _ := ioutil.TempDir("", "config-test")
 | 
			
		||||
 | 
			
		||||
	tmpHome += "/.docker"
 | 
			
		||||
 | 
			
		||||
	config, err := LoadConfig(tmpHome)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed loading on missing file: %q", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Now save it and make sure it shows up in new form
 | 
			
		||||
	err = config.Save()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed to save: %q", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buf, err := ioutil.ReadFile(filepath.Join(tmpHome, CONFIGFILE))
 | 
			
		||||
	if !strings.Contains(string(buf), `"auths":`) {
 | 
			
		||||
		t.Fatalf("Should have save in new form: %s", string(buf))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestEmptyFile(t *testing.T) {
 | 
			
		||||
	tmpHome, _ := ioutil.TempDir("", "config-test")
 | 
			
		||||
	fn := filepath.Join(tmpHome, CONFIGFILE)
 | 
			
		||||
	ioutil.WriteFile(fn, []byte(""), 0600)
 | 
			
		||||
 | 
			
		||||
	_, err := LoadConfig(tmpHome)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		t.Fatalf("Was supposed to fail")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestEmptyJson(t *testing.T) {
 | 
			
		||||
	tmpHome, _ := ioutil.TempDir("", "config-test")
 | 
			
		||||
	fn := filepath.Join(tmpHome, CONFIGFILE)
 | 
			
		||||
	ioutil.WriteFile(fn, []byte("{}"), 0600)
 | 
			
		||||
 | 
			
		||||
	config, err := LoadConfig(tmpHome)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed loading on empty json file: %q", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Now save it and make sure it shows up in new form
 | 
			
		||||
	err = config.Save()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed to save: %q", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buf, err := ioutil.ReadFile(filepath.Join(tmpHome, CONFIGFILE))
 | 
			
		||||
	if !strings.Contains(string(buf), `"auths":`) {
 | 
			
		||||
		t.Fatalf("Should have save in new form: %s", string(buf))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestOldJson(t *testing.T) {
 | 
			
		||||
	if runtime.GOOS == "windows" {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tmpHome, _ := ioutil.TempDir("", "config-test")
 | 
			
		||||
	defer os.RemoveAll(tmpHome)
 | 
			
		||||
 | 
			
		||||
	homeKey := homedir.Key()
 | 
			
		||||
	homeVal := homedir.Get()
 | 
			
		||||
 | 
			
		||||
	defer func() { os.Setenv(homeKey, homeVal) }()
 | 
			
		||||
	os.Setenv(homeKey, tmpHome)
 | 
			
		||||
 | 
			
		||||
	fn := filepath.Join(tmpHome, OLD_CONFIGFILE)
 | 
			
		||||
	js := `{"https://index.docker.io/v1/":{"auth":"am9lam9lOmhlbGxv","email":"user@example.com"}}`
 | 
			
		||||
	ioutil.WriteFile(fn, []byte(js), 0600)
 | 
			
		||||
 | 
			
		||||
	config, err := LoadConfig(tmpHome)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed loading on empty json file: %q", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ac := config.AuthConfigs["https://index.docker.io/v1/"]
 | 
			
		||||
	if ac.Email != "user@example.com" || 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
 | 
			
		||||
	err = config.Save()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed to save: %q", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buf, err := ioutil.ReadFile(filepath.Join(tmpHome, CONFIGFILE))
 | 
			
		||||
	if !strings.Contains(string(buf), `"auths":`) ||
 | 
			
		||||
		!strings.Contains(string(buf), "user@example.com") {
 | 
			
		||||
		t.Fatalf("Should have save in new form: %s", string(buf))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestNewJson(t *testing.T) {
 | 
			
		||||
	tmpHome, _ := ioutil.TempDir("", "config-test")
 | 
			
		||||
	fn := filepath.Join(tmpHome, CONFIGFILE)
 | 
			
		||||
	js := ` { "auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } } }`
 | 
			
		||||
	ioutil.WriteFile(fn, []byte(js), 0600)
 | 
			
		||||
 | 
			
		||||
	config, err := LoadConfig(tmpHome)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed loading on empty json file: %q", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ac := config.AuthConfigs["https://index.docker.io/v1/"]
 | 
			
		||||
	if ac.Email != "user@example.com" || 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
 | 
			
		||||
	err = config.Save()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed to save: %q", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buf, err := ioutil.ReadFile(filepath.Join(tmpHome, CONFIGFILE))
 | 
			
		||||
	if !strings.Contains(string(buf), `"auths":`) ||
 | 
			
		||||
		!strings.Contains(string(buf), "user@example.com") {
 | 
			
		||||
		t.Fatalf("Should have save in new form: %s", string(buf))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ import (
 | 
			
		|||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/cliconfig"
 | 
			
		||||
	"github.com/docker/docker/pkg/requestdecorator"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +21,7 @@ const (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
func spawnTestRegistrySession(t *testing.T) *Session {
 | 
			
		||||
	authConfig := &AuthConfig{}
 | 
			
		||||
	authConfig := &cliconfig.AuthConfig{}
 | 
			
		||||
	endpoint, err := NewEndpoint(makeIndex("/v1/"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
| 
						 | 
				
			
			@ -33,7 +34,7 @@ func spawnTestRegistrySession(t *testing.T) *Session {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func TestPublicSession(t *testing.T) {
 | 
			
		||||
	authConfig := &AuthConfig{}
 | 
			
		||||
	authConfig := &cliconfig.AuthConfig{}
 | 
			
		||||
 | 
			
		||||
	getSessionDecorators := func(index *IndexInfo) int {
 | 
			
		||||
		endpoint, err := NewEndpoint(index)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
package registry
 | 
			
		||||
 | 
			
		||||
import "github.com/docker/docker/cliconfig"
 | 
			
		||||
 | 
			
		||||
type Service struct {
 | 
			
		||||
	Config *ServiceConfig
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +17,7 @@ func NewService(options *Options) *Service {
 | 
			
		|||
// Auth contacts the public registry with the provided credentials,
 | 
			
		||||
// and returns OK if authentication was sucessful.
 | 
			
		||||
// It can be used to verify the validity of a client's credentials.
 | 
			
		||||
func (s *Service) Auth(authConfig *AuthConfig) (string, error) {
 | 
			
		||||
func (s *Service) Auth(authConfig *cliconfig.AuthConfig) (string, error) {
 | 
			
		||||
	addr := authConfig.ServerAddress
 | 
			
		||||
	if addr == "" {
 | 
			
		||||
		// Use the official registry address if not specified.
 | 
			
		||||
| 
						 | 
				
			
			@ -35,7 +37,7 @@ func (s *Service) Auth(authConfig *AuthConfig) (string, error) {
 | 
			
		|||
 | 
			
		||||
// Search queries the public registry for images matching the specified
 | 
			
		||||
// search terms, and returns the results.
 | 
			
		||||
func (s *Service) Search(term string, authConfig *AuthConfig, headers map[string][]string) (*SearchResults, error) {
 | 
			
		||||
func (s *Service) Search(term string, authConfig *cliconfig.AuthConfig, headers map[string][]string) (*SearchResults, error) {
 | 
			
		||||
	repoInfo, err := s.ResolveRepository(term)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,20 +18,21 @@ import (
 | 
			
		|||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"github.com/docker/docker/cliconfig"
 | 
			
		||||
	"github.com/docker/docker/pkg/httputils"
 | 
			
		||||
	"github.com/docker/docker/pkg/requestdecorator"
 | 
			
		||||
	"github.com/docker/docker/pkg/tarsum"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Session struct {
 | 
			
		||||
	authConfig    *AuthConfig
 | 
			
		||||
	authConfig    *cliconfig.AuthConfig
 | 
			
		||||
	reqFactory    *requestdecorator.RequestFactory
 | 
			
		||||
	indexEndpoint *Endpoint
 | 
			
		||||
	jar           *cookiejar.Jar
 | 
			
		||||
	timeout       TimeoutType
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewSession(authConfig *AuthConfig, factory *requestdecorator.RequestFactory, endpoint *Endpoint, timeout bool) (r *Session, err error) {
 | 
			
		||||
func NewSession(authConfig *cliconfig.AuthConfig, factory *requestdecorator.RequestFactory, endpoint *Endpoint, timeout bool) (r *Session, err error) {
 | 
			
		||||
	r = &Session{
 | 
			
		||||
		authConfig:    authConfig,
 | 
			
		||||
		indexEndpoint: endpoint,
 | 
			
		||||
| 
						 | 
				
			
			@ -600,12 +601,12 @@ func (r *Session) SearchRepositories(term string) (*SearchResults, error) {
 | 
			
		|||
	return result, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Session) GetAuthConfig(withPasswd bool) *AuthConfig {
 | 
			
		||||
func (r *Session) GetAuthConfig(withPasswd bool) *cliconfig.AuthConfig {
 | 
			
		||||
	password := ""
 | 
			
		||||
	if withPasswd {
 | 
			
		||||
		password = r.authConfig.Password
 | 
			
		||||
	}
 | 
			
		||||
	return &AuthConfig{
 | 
			
		||||
	return &cliconfig.AuthConfig{
 | 
			
		||||
		Username: r.authConfig.Username,
 | 
			
		||||
		Password: password,
 | 
			
		||||
		Email:    r.authConfig.Email,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue