Browse code

Fix support for registry auth with Dockerfile build.

Docker-DCO-1.1-Signed-off-by: Jake Moshenko <jake@devtable.com> (github: jakedt)

Jake Moshenko authored on 2014/01/04 05:13:32
Showing 6 changed files
... ...
@@ -925,10 +925,17 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
925 925
 		rawRm             = r.FormValue("rm")
926 926
 		authEncoded       = r.Header.Get("X-Registry-Auth")
927 927
 		authConfig        = &auth.AuthConfig{}
928
+		configFileEncoded = r.Header.Get("X-Registry-Config")
929
+		configFile        = &auth.ConfigFile{}
928 930
 		tag               string
929 931
 	)
930 932
 	repoName, tag = utils.ParseRepositoryTag(repoName)
931
-	if authEncoded != "" {
933
+
934
+	// This block can be removed when API versions prior to 1.9 are deprecated.
935
+	// Both headers will be parsed and sent along to the daemon, but if a non-empty
936
+	// ConfigFile is present, any value provided as an AuthConfig directly will
937
+	// be overridden. See BuildFile::CmdFrom for details.
938
+	if version < 1.9 && authEncoded != "" {
932 939
 		authJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
933 940
 		if err := json.NewDecoder(authJson).Decode(authConfig); err != nil {
934 941
 			// 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
937 937
 		}
938 938
 	}
939 939
 
940
+	if configFileEncoded != "" {
941
+		configFileJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(configFileEncoded))
942
+		if err := json.NewDecoder(configFileJson).Decode(configFile); err != nil {
943
+			// for a pull it is not an error if no auth was given
944
+			// to increase compatibility with the existing api it is defaulting to be empty
945
+			configFile = &auth.ConfigFile{}
946
+		}
947
+	}
948
+
940 949
 	var context io.Reader
941 950
 
942 951
 	if remoteURL == "" {
... ...
@@ -1003,7 +1019,7 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
1003 1003
 			Writer:          utils.NewWriteFlusher(w),
1004 1004
 			StreamFormatter: sf,
1005 1005
 		},
1006
-		!suppressOutput, !noCache, rm, utils.NewWriteFlusher(w), sf, authConfig)
1006
+		!suppressOutput, !noCache, rm, utils.NewWriteFlusher(w), sf, authConfig, configFile)
1007 1007
 	id, err := b.Build(context)
1008 1008
 	if err != nil {
1009 1009
 		if sf.Used() {
... ...
@@ -8,6 +8,7 @@ import (
8 8
 	"fmt"
9 9
 	"github.com/dotcloud/docker/archive"
10 10
 	"github.com/dotcloud/docker/auth"
11
+	"github.com/dotcloud/docker/registry"
11 12
 	"github.com/dotcloud/docker/utils"
12 13
 	"io"
13 14
 	"io/ioutil"
... ...
@@ -47,6 +48,7 @@ type buildFile struct {
47 47
 	rm           bool
48 48
 
49 49
 	authConfig *auth.AuthConfig
50
+	configFile *auth.ConfigFile
50 51
 
51 52
 	tmpContainers map[string]struct{}
52 53
 	tmpImages     map[string]struct{}
... ...
@@ -72,7 +74,17 @@ func (b *buildFile) CmdFrom(name string) error {
72 72
 	if err != nil {
73 73
 		if b.runtime.graph.IsNotExist(err) {
74 74
 			remote, tag := utils.ParseRepositoryTag(name)
75
-			if err := b.srv.ImagePull(remote, tag, b.outOld, b.sf, b.authConfig, nil, true); err != nil {
75
+			pullRegistryAuth := b.authConfig
76
+			if len(b.configFile.Configs) > 0 {
77
+				// The request came with a full auth config file, we prefer to use that
78
+				endpoint, _, err := registry.ResolveRepositoryName(remote)
79
+				if err != nil {
80
+					return err
81
+				}
82
+				resolvedAuth := b.configFile.ResolveAuthConfig(endpoint)
83
+				pullRegistryAuth = &resolvedAuth
84
+			}
85
+			if err := b.srv.ImagePull(remote, tag, b.outOld, b.sf, pullRegistryAuth, nil, true); err != nil {
76 86
 				return err
77 87
 			}
78 88
 			image, err = b.runtime.repositories.LookupImage(name)
... ...
@@ -696,7 +708,7 @@ func (b *buildFile) Build(context io.Reader) (string, error) {
696 696
 	return "", fmt.Errorf("No image was generated. This may be because the Dockerfile does not, like, do anything.\n")
697 697
 }
698 698
 
699
-func NewBuildFile(srv *Server, outStream, errStream io.Writer, verbose, utilizeCache, rm bool, outOld io.Writer, sf *utils.StreamFormatter, auth *auth.AuthConfig) BuildFile {
699
+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 {
700 700
 	return &buildFile{
701 701
 		runtime:       srv.runtime,
702 702
 		srv:           srv,
... ...
@@ -710,6 +722,7 @@ func NewBuildFile(srv *Server, outStream, errStream io.Writer, verbose, utilizeC
710 710
 		rm:            rm,
711 711
 		sf:            sf,
712 712
 		authConfig:    auth,
713
+		configFile:    authConfigFile,
713 714
 		outOld:        outOld,
714 715
 	}
715 716
 }
... ...
@@ -227,12 +227,14 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
227 227
 		v.Set("rm", "1")
228 228
 	}
229 229
 
230
+	cli.LoadConfigFile()
231
+
230 232
 	headers := http.Header(make(map[string][]string))
231 233
 	buf, err := json.Marshal(cli.configFile)
232 234
 	if err != nil {
233 235
 		return err
234 236
 	}
235
-	headers.Add("X-Registry-Auth", base64.URLEncoding.EncodeToString(buf))
237
+	headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
236 238
 
237 239
 	if context != nil {
238 240
 		headers.Set("Content-Type", "application/tar")
... ...
@@ -54,6 +54,13 @@ What's new
54 54
 
55 55
    **New!** This endpoint now returns a list of json message, like the events endpoint
56 56
 
57
+.. http:post:: /build
58
+
59
+   **New!** This endpoint now takes a serialized ConfigFile which it uses to
60
+   resolve the proper registry auth credentials for pulling the base image.
61
+   Clients which previously implemented the version accepting an AuthConfig
62
+   object must be updated.
63
+
57 64
 v1.8
58 65
 ****
59 66
 
... ...
@@ -1025,7 +1025,7 @@ Build an image from Dockerfile via stdin
1025 1025
    :query q: suppress verbose build output
1026 1026
    :query nocache: do not use the cache when building the image
1027 1027
    :reqheader Content-type: should be set to ``"application/tar"``.
1028
-   :reqheader X-Registry-Auth: base64-encoded AuthConfig object
1028
+   :reqheader X-Registry-Config: base64-encoded ConfigFile object
1029 1029
    :statuscode 200: no error
1030 1030
    :statuscode 500: server error
1031 1031
 
... ...
@@ -296,7 +296,7 @@ func buildImage(context testContextTemplate, t *testing.T, eng *engine.Engine, u
296 296
 	}
297 297
 	dockerfile := constructDockerfile(context.dockerfile, ip, port)
298 298
 
299
-	buildfile := docker.NewBuildFile(srv, ioutil.Discard, ioutil.Discard, false, useCache, false, ioutil.Discard, utils.NewStreamFormatter(false), nil)
299
+	buildfile := docker.NewBuildFile(srv, ioutil.Discard, ioutil.Discard, false, useCache, false, ioutil.Discard, utils.NewStreamFormatter(false), nil, nil)
300 300
 	id, err := buildfile.Build(mkTestContext(dockerfile, context.files, t))
301 301
 	if err != nil {
302 302
 		return nil, err
... ...
@@ -700,7 +700,7 @@ func TestForbiddenContextPath(t *testing.T) {
700 700
 	}
701 701
 	dockerfile := constructDockerfile(context.dockerfile, ip, port)
702 702
 
703
-	buildfile := docker.NewBuildFile(srv, ioutil.Discard, ioutil.Discard, false, true, false, ioutil.Discard, utils.NewStreamFormatter(false), nil)
703
+	buildfile := docker.NewBuildFile(srv, ioutil.Discard, ioutil.Discard, false, true, false, ioutil.Discard, utils.NewStreamFormatter(false), nil, nil)
704 704
 	_, err = buildfile.Build(mkTestContext(dockerfile, context.files, t))
705 705
 
706 706
 	if err == nil {
... ...
@@ -746,7 +746,7 @@ func TestBuildADDFileNotFound(t *testing.T) {
746 746
 	}
747 747
 	dockerfile := constructDockerfile(context.dockerfile, ip, port)
748 748
 
749
-	buildfile := docker.NewBuildFile(mkServerFromEngine(eng, t), ioutil.Discard, ioutil.Discard, false, true, false, ioutil.Discard, utils.NewStreamFormatter(false), nil)
749
+	buildfile := docker.NewBuildFile(mkServerFromEngine(eng, t), ioutil.Discard, ioutil.Discard, false, true, false, ioutil.Discard, utils.NewStreamFormatter(false), nil, nil)
750 750
 	_, err = buildfile.Build(mkTestContext(dockerfile, context.files, t))
751 751
 
752 752
 	if err == nil {