Docker-DCO-1.1-Signed-off-by: Jake Moshenko <jake@devtable.com> (github: jakedt)
| ... | ... |
@@ -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 {
|