Merge pull request #3442 from DevTable/master

Fix support for registry auth with Dockerfile build.
This commit is contained in:
Victor Vieux 2014-01-20 15:50:14 -08:00
Родитель 37c1c7cf7a 6e6ff85362
Коммит ffe78e82c3
6 изменённых файлов: 47 добавлений и 9 удалений

20
api.go
Просмотреть файл

@ -925,10 +925,17 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
rawRm = r.FormValue("rm")
authEncoded = r.Header.Get("X-Registry-Auth")
authConfig = &auth.AuthConfig{}
configFileEncoded = r.Header.Get("X-Registry-Config")
configFile = &auth.ConfigFile{}
tag string
)
repoName, tag = utils.ParseRepositoryTag(repoName)
if authEncoded != "" {
// This block can be removed when API versions prior to 1.9 are deprecated.
// Both headers will be parsed and sent along to the daemon, but if a non-empty
// ConfigFile is present, any value provided as an AuthConfig directly will
// be overridden. See BuildFile::CmdFrom for details.
if version < 1.9 && authEncoded != "" {
authJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
if err := json.NewDecoder(authJson).Decode(authConfig); err != nil {
// for a pull it is not an error if no auth was given
@ -937,6 +944,15 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
}
}
if configFileEncoded != "" {
configFileJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(configFileEncoded))
if err := json.NewDecoder(configFileJson).Decode(configFile); err != nil {
// for a pull it is not an error if no auth was given
// to increase compatibility with the existing api it is defaulting to be empty
configFile = &auth.ConfigFile{}
}
}
var context io.Reader
if remoteURL == "" {
@ -1003,7 +1019,7 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
Writer: utils.NewWriteFlusher(w),
StreamFormatter: sf,
},
!suppressOutput, !noCache, rm, utils.NewWriteFlusher(w), sf, authConfig)
!suppressOutput, !noCache, rm, utils.NewWriteFlusher(w), sf, authConfig, configFile)
id, err := b.Build(context)
if err != nil {
if sf.Used() {

Просмотреть файл

@ -8,6 +8,7 @@ import (
"fmt"
"github.com/dotcloud/docker/archive"
"github.com/dotcloud/docker/auth"
"github.com/dotcloud/docker/registry"
"github.com/dotcloud/docker/utils"
"io"
"io/ioutil"
@ -47,6 +48,7 @@ type buildFile struct {
rm bool
authConfig *auth.AuthConfig
configFile *auth.ConfigFile
tmpContainers map[string]struct{}
tmpImages map[string]struct{}
@ -72,7 +74,17 @@ func (b *buildFile) CmdFrom(name string) error {
if err != nil {
if b.runtime.graph.IsNotExist(err) {
remote, tag := utils.ParseRepositoryTag(name)
if err := b.srv.ImagePull(remote, tag, b.outOld, b.sf, b.authConfig, nil, true); err != nil {
pullRegistryAuth := b.authConfig
if len(b.configFile.Configs) > 0 {
// The request came with a full auth config file, we prefer to use that
endpoint, _, err := registry.ResolveRepositoryName(remote)
if err != nil {
return err
}
resolvedAuth := b.configFile.ResolveAuthConfig(endpoint)
pullRegistryAuth = &resolvedAuth
}
if err := b.srv.ImagePull(remote, tag, b.outOld, b.sf, pullRegistryAuth, nil, true); err != nil {
return err
}
image, err = b.runtime.repositories.LookupImage(name)
@ -696,7 +708,7 @@ func (b *buildFile) Build(context io.Reader) (string, error) {
return "", fmt.Errorf("No image was generated. This may be because the Dockerfile does not, like, do anything.\n")
}
func NewBuildFile(srv *Server, outStream, errStream io.Writer, verbose, utilizeCache, rm bool, outOld io.Writer, sf *utils.StreamFormatter, auth *auth.AuthConfig) BuildFile {
func NewBuildFile(srv *Server, outStream, errStream io.Writer, verbose, utilizeCache, rm bool, outOld io.Writer, sf *utils.StreamFormatter, auth *auth.AuthConfig, authConfigFile *auth.ConfigFile) BuildFile {
return &buildFile{
runtime: srv.runtime,
srv: srv,
@ -710,6 +722,7 @@ func NewBuildFile(srv *Server, outStream, errStream io.Writer, verbose, utilizeC
rm: rm,
sf: sf,
authConfig: auth,
configFile: authConfigFile,
outOld: outOld,
}
}

Просмотреть файл

@ -227,12 +227,14 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
v.Set("rm", "1")
}
cli.LoadConfigFile()
headers := http.Header(make(map[string][]string))
buf, err := json.Marshal(cli.configFile)
if err != nil {
return err
}
headers.Add("X-Registry-Auth", base64.URLEncoding.EncodeToString(buf))
headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
if context != nil {
headers.Set("Content-Type", "application/tar")

Просмотреть файл

@ -54,6 +54,13 @@ What's new
**New!** This endpoint now returns a list of json message, like the events endpoint
.. http:post:: /build
**New!** This endpoint now takes a serialized ConfigFile which it uses to
resolve the proper registry auth credentials for pulling the base image.
Clients which previously implemented the version accepting an AuthConfig
object must be updated.
v1.8
****

Просмотреть файл

@ -1025,7 +1025,7 @@ Build an image from Dockerfile via stdin
:query q: suppress verbose build output
:query nocache: do not use the cache when building the image
:reqheader Content-type: should be set to ``"application/tar"``.
:reqheader X-Registry-Auth: base64-encoded AuthConfig object
:reqheader X-Registry-Config: base64-encoded ConfigFile object
:statuscode 200: no error
:statuscode 500: server error

Просмотреть файл

@ -296,7 +296,7 @@ func buildImage(context testContextTemplate, t *testing.T, eng *engine.Engine, u
}
dockerfile := constructDockerfile(context.dockerfile, ip, port)
buildfile := docker.NewBuildFile(srv, ioutil.Discard, ioutil.Discard, false, useCache, false, ioutil.Discard, utils.NewStreamFormatter(false), nil)
buildfile := docker.NewBuildFile(srv, ioutil.Discard, ioutil.Discard, false, useCache, false, ioutil.Discard, utils.NewStreamFormatter(false), nil, nil)
id, err := buildfile.Build(mkTestContext(dockerfile, context.files, t))
if err != nil {
return nil, err
@ -700,7 +700,7 @@ func TestForbiddenContextPath(t *testing.T) {
}
dockerfile := constructDockerfile(context.dockerfile, ip, port)
buildfile := docker.NewBuildFile(srv, ioutil.Discard, ioutil.Discard, false, true, false, ioutil.Discard, utils.NewStreamFormatter(false), nil)
buildfile := docker.NewBuildFile(srv, ioutil.Discard, ioutil.Discard, false, true, false, ioutil.Discard, utils.NewStreamFormatter(false), nil, nil)
_, err = buildfile.Build(mkTestContext(dockerfile, context.files, t))
if err == nil {
@ -746,7 +746,7 @@ func TestBuildADDFileNotFound(t *testing.T) {
}
dockerfile := constructDockerfile(context.dockerfile, ip, port)
buildfile := docker.NewBuildFile(mkServerFromEngine(eng, t), ioutil.Discard, ioutil.Discard, false, true, false, ioutil.Discard, utils.NewStreamFormatter(false), nil)
buildfile := docker.NewBuildFile(mkServerFromEngine(eng, t), ioutil.Discard, ioutil.Discard, false, true, false, ioutil.Discard, utils.NewStreamFormatter(false), nil, nil)
_, err = buildfile.Build(mkTestContext(dockerfile, context.files, t))
if err == nil {