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>
This commit is contained in:
Doug Davis 2015-04-22 05:06:58 -07:00
parent 34d1494c7f
commit a8b9bec104
6 changed files with 45 additions and 385 deletions

View file

@ -1,51 +1,21 @@
package registry package registry
import ( import (
"encoding/base64"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os"
"path/filepath"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/homedir" "github.com/docker/docker/cliconfig"
"github.com/docker/docker/pkg/requestdecorator" "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 { type RequestAuthorization struct {
authConfig *AuthConfig authConfig *cliconfig.AuthConfig
registryEndpoint *Endpoint registryEndpoint *Endpoint
resource string resource string
scope string scope string
@ -56,7 +26,7 @@ type RequestAuthorization struct {
tokenExpiration time.Time 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{ return &RequestAuthorization{
authConfig: authConfig, authConfig: authConfig,
registryEndpoint: registryEndpoint, registryEndpoint: registryEndpoint,
@ -121,160 +91,8 @@ func (auth *RequestAuthorization) Authorize(req *http.Request) error {
return nil 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. // 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. // Separates the v2 registry login logic from the v1 logic.
if registryEndpoint.Version == APIVersion2 { if registryEndpoint.Version == APIVersion2 {
return loginV2(authConfig, registryEndpoint, factory) 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. // 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 ( var (
status string status string
reqBody []byte 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 // 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 // served by the v2 registry service provider. Whether this will be supported in the future
// is to be determined. // 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) logrus.Debugf("attempting v2 login to registry endpoint %s", registryEndpoint)
var ( var (
err error 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) 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) req, err := factory.NewRequest("GET", registryEndpoint.Path(""), nil)
if err != nil { if err != nil {
return err return err
@ -450,7 +268,7 @@ func tryV2BasicAuthLogin(authConfig *AuthConfig, params map[string]string, regis
return nil 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) token, err := getToken(authConfig.Username, authConfig.Password, params, registryEndpoint, client, factory)
if err != nil { if err != nil {
return err 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 // 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() configKey := index.GetAuthConfigKey()
// First try the happy case // First try the happy case
if c, found := config.AuthConfigs[configKey]; found || index.Official { 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 // Maybe they have a legacy config file, we will iterate the keys converting
// them to the new format and testing // them to the new format and testing
for registry, config := range config.AuthConfigs { for registry, ac := range config.AuthConfigs {
if configKey == convertToHostname(registry) { if configKey == convertToHostname(registry) {
return config return ac
} }
} }
// When all else fails, return an empty auth config // When all else fails, return an empty auth config
return AuthConfig{} return cliconfig.AuthConfig{}
}
func (config *ConfigFile) Filename() string {
return config.filename
} }

View file

@ -5,14 +5,16 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/docker/docker/cliconfig"
) )
func TestEncodeAuth(t *testing.T) { func TestEncodeAuth(t *testing.T) {
newAuthConfig := &AuthConfig{Username: "ken", Password: "test", Email: "test@example.com"} newAuthConfig := &cliconfig.AuthConfig{Username: "ken", Password: "test", Email: "test@example.com"}
authStr := encodeAuth(newAuthConfig) authStr := cliconfig.EncodeAuth(newAuthConfig)
decAuthConfig := &AuthConfig{} decAuthConfig := &cliconfig.AuthConfig{}
var err error var err error
decAuthConfig.Username, decAuthConfig.Password, err = decodeAuth(authStr) decAuthConfig.Username, decAuthConfig.Password, err = cliconfig.DecodeAuth(authStr)
if err != nil { if err != nil {
t.Fatal(err) 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") root, err := ioutil.TempDir("", "docker-test-auth")
if err != nil { if err != nil {
return nil, err return nil, err
} }
root = filepath.Join(root, CONFIGFILE) root = filepath.Join(root, cliconfig.CONFIGFILE)
configFile := &ConfigFile{ configFile := cliconfig.NewConfigFile(root)
AuthConfigs: make(map[string]AuthConfig),
filename: root,
}
for _, registry := range []string{"testIndex", IndexServerAddress()} { for _, registry := range []string{"testIndex", IndexServerAddress()} {
configFile.AuthConfigs[registry] = AuthConfig{ configFile.AuthConfigs[registry] = cliconfig.AuthConfig{
Username: "docker-user", Username: "docker-user",
Password: "docker-pass", Password: "docker-pass",
Email: "docker@docker.io", Email: "docker@docker.io",
@ -54,7 +53,7 @@ func TestSameAuthDataPostSave(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer os.RemoveAll(configFile.filename) defer os.RemoveAll(configFile.Filename())
err = configFile.Save() err = configFile.Save()
if err != nil { if err != nil {
@ -81,7 +80,7 @@ func TestResolveAuthConfigIndexServer(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer os.RemoveAll(configFile.filename) defer os.RemoveAll(configFile.Filename())
indexConfig := configFile.AuthConfigs[IndexServerAddress()] indexConfig := configFile.AuthConfigs[IndexServerAddress()]
@ -92,10 +91,10 @@ func TestResolveAuthConfigIndexServer(t *testing.T) {
Official: false, Official: false,
} }
resolved := configFile.ResolveAuthConfig(officialIndex) resolved := ResolveAuthConfig(configFile, officialIndex)
assertEqual(t, resolved, indexConfig, "Expected ResolveAuthConfig to return IndexServerAddress()") 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()") assertNotEqual(t, resolved, indexConfig, "Expected ResolveAuthConfig to not return IndexServerAddress()")
} }
@ -104,26 +103,26 @@ func TestResolveAuthConfigFullURL(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer os.RemoveAll(configFile.filename) defer os.RemoveAll(configFile.Filename())
registryAuth := AuthConfig{ registryAuth := cliconfig.AuthConfig{
Username: "foo-user", Username: "foo-user",
Password: "foo-pass", Password: "foo-pass",
Email: "foo@example.com", Email: "foo@example.com",
} }
localAuth := AuthConfig{ localAuth := cliconfig.AuthConfig{
Username: "bar-user", Username: "bar-user",
Password: "bar-pass", Password: "bar-pass",
Email: "bar@example.com", Email: "bar@example.com",
} }
officialAuth := AuthConfig{ officialAuth := cliconfig.AuthConfig{
Username: "baz-user", Username: "baz-user",
Password: "baz-pass", Password: "baz-pass",
Email: "baz@example.com", Email: "baz@example.com",
} }
configFile.AuthConfigs[IndexServerAddress()] = officialAuth configFile.AuthConfigs[IndexServerAddress()] = officialAuth
expectedAuths := map[string]AuthConfig{ expectedAuths := map[string]cliconfig.AuthConfig{
"registry.example.com": registryAuth, "registry.example.com": registryAuth,
"localhost:8000": localAuth, "localhost:8000": localAuth,
"registry.com": localAuth, "registry.com": localAuth,
@ -160,12 +159,12 @@ func TestResolveAuthConfigFullURL(t *testing.T) {
} }
for _, registry := range registries { for _, registry := range registries {
configFile.AuthConfigs[registry] = configured configFile.AuthConfigs[registry] = configured
resolved := configFile.ResolveAuthConfig(index) resolved := ResolveAuthConfig(configFile, index)
if resolved.Email != configured.Email { if resolved.Email != configured.Email {
t.Errorf("%s -> %q != %q\n", registry, resolved.Email, configured.Email) t.Errorf("%s -> %q != %q\n", registry, resolved.Email, configured.Email)
} }
delete(configFile.AuthConfigs, registry) delete(configFile.AuthConfigs, registry)
resolved = configFile.ResolveAuthConfig(index) resolved = ResolveAuthConfig(configFile, index)
if resolved.Email == configured.Email { if resolved.Email == configured.Email {
t.Errorf("%s -> %q == %q\n", registry, resolved.Email, configured.Email) t.Errorf("%s -> %q == %q\n", registry, resolved.Email, configured.Email)
} }

View file

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

View file

@ -7,6 +7,7 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/docker/docker/cliconfig"
"github.com/docker/docker/pkg/requestdecorator" "github.com/docker/docker/pkg/requestdecorator"
) )
@ -20,7 +21,7 @@ const (
) )
func spawnTestRegistrySession(t *testing.T) *Session { func spawnTestRegistrySession(t *testing.T) *Session {
authConfig := &AuthConfig{} authConfig := &cliconfig.AuthConfig{}
endpoint, err := NewEndpoint(makeIndex("/v1/")) endpoint, err := NewEndpoint(makeIndex("/v1/"))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -33,7 +34,7 @@ func spawnTestRegistrySession(t *testing.T) *Session {
} }
func TestPublicSession(t *testing.T) { func TestPublicSession(t *testing.T) {
authConfig := &AuthConfig{} authConfig := &cliconfig.AuthConfig{}
getSessionDecorators := func(index *IndexInfo) int { getSessionDecorators := func(index *IndexInfo) int {
endpoint, err := NewEndpoint(index) endpoint, err := NewEndpoint(index)

View file

@ -1,5 +1,7 @@
package registry package registry
import "github.com/docker/docker/cliconfig"
type Service struct { type Service struct {
Config *ServiceConfig Config *ServiceConfig
} }
@ -15,7 +17,7 @@ func NewService(options *Options) *Service {
// Auth contacts the public registry with the provided credentials, // Auth contacts the public registry with the provided credentials,
// and returns OK if authentication was sucessful. // and returns OK if authentication was sucessful.
// It can be used to verify the validity of a client's credentials. // 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 addr := authConfig.ServerAddress
if addr == "" { if addr == "" {
// Use the official registry address if not specified. // 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 queries the public registry for images matching the specified
// search terms, and returns the results. // 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) repoInfo, err := s.ResolveRepository(term)
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -18,20 +18,21 @@ import (
"time" "time"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/docker/docker/cliconfig"
"github.com/docker/docker/pkg/httputils" "github.com/docker/docker/pkg/httputils"
"github.com/docker/docker/pkg/requestdecorator" "github.com/docker/docker/pkg/requestdecorator"
"github.com/docker/docker/pkg/tarsum" "github.com/docker/docker/pkg/tarsum"
) )
type Session struct { type Session struct {
authConfig *AuthConfig authConfig *cliconfig.AuthConfig
reqFactory *requestdecorator.RequestFactory reqFactory *requestdecorator.RequestFactory
indexEndpoint *Endpoint indexEndpoint *Endpoint
jar *cookiejar.Jar jar *cookiejar.Jar
timeout TimeoutType 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{ r = &Session{
authConfig: authConfig, authConfig: authConfig,
indexEndpoint: endpoint, indexEndpoint: endpoint,
@ -600,12 +601,12 @@ func (r *Session) SearchRepositories(term string) (*SearchResults, error) {
return result, err return result, err
} }
func (r *Session) GetAuthConfig(withPasswd bool) *AuthConfig { func (r *Session) GetAuthConfig(withPasswd bool) *cliconfig.AuthConfig {
password := "" password := ""
if withPasswd { if withPasswd {
password = r.authConfig.Password password = r.authConfig.Password
} }
return &AuthConfig{ return &cliconfig.AuthConfig{
Username: r.authConfig.Username, Username: r.authConfig.Username,
Password: password, Password: password,
Email: r.authConfig.Email, Email: r.authConfig.Email,