@@ -13,6 +13,7 @@ import (
1313 "sync"
1414
1515 "github.com/Sirupsen/logrus"
16+ apierrors "github.com/docker/docker/api/errors"
1617 "github.com/docker/docker/api/server/httputils"
1718 "github.com/docker/docker/api/types"
1819 "github.com/docker/docker/api/types/backend"
@@ -22,6 +23,7 @@ import (
2223 "github.com/docker/docker/pkg/progress"
2324 "github.com/docker/docker/pkg/streamformatter"
2425 units "github.com/docker/go-units"
26+ "github.com/pkg/errors"
2527 "golang.org/x/net/context"
2628)
2729
@@ -87,9 +89,6 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
8789 options .Ulimits = buildUlimits
8890 }
8991
90- var buildArgs = map [string ]* string {}
91- buildArgsJSON := r .FormValue ("buildargs" )
92-
9392 // Note that there are two ways a --build-arg might appear in the
9493 // json of the query param:
9594 // "foo":"bar"
@@ -102,25 +101,27 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
102101 // the fact they mentioned it, we need to pass that along to the builder
103102 // so that it can print a warning about "foo" being unused if there is
104103 // no "ARG foo" in the Dockerfile.
104+ buildArgsJSON := r .FormValue ("buildargs" )
105105 if buildArgsJSON != "" {
106+ var buildArgs = map [string ]* string {}
106107 if err := json .Unmarshal ([]byte (buildArgsJSON ), & buildArgs ); err != nil {
107108 return nil , err
108109 }
109110 options .BuildArgs = buildArgs
110111 }
111112
112- var labels = map [string ]string {}
113113 labelsJSON := r .FormValue ("labels" )
114114 if labelsJSON != "" {
115+ var labels = map [string ]string {}
115116 if err := json .Unmarshal ([]byte (labelsJSON ), & labels ); err != nil {
116117 return nil , err
117118 }
118119 options .Labels = labels
119120 }
120121
121- var cacheFrom = []string {}
122122 cacheFromJSON := r .FormValue ("cachefrom" )
123123 if cacheFromJSON != "" {
124+ var cacheFrom = []string {}
124125 if err := json .Unmarshal ([]byte (cacheFromJSON ), & cacheFrom ); err != nil {
125126 return nil , err
126127 }
@@ -130,33 +131,8 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
130131 return options , nil
131132}
132133
133- type syncWriter struct {
134- w io.Writer
135- mu sync.Mutex
136- }
137-
138- func (s * syncWriter ) Write (b []byte ) (count int , err error ) {
139- s .mu .Lock ()
140- count , err = s .w .Write (b )
141- s .mu .Unlock ()
142- return
143- }
144-
145134func (br * buildRouter ) postBuild (ctx context.Context , w http.ResponseWriter , r * http.Request , vars map [string ]string ) error {
146- var (
147- authConfigs = map [string ]types.AuthConfig {}
148- authConfigsEncoded = r .Header .Get ("X-Registry-Config" )
149- notVerboseBuffer = bytes .NewBuffer (nil )
150- )
151-
152- if authConfigsEncoded != "" {
153- authConfigsJSON := base64 .NewDecoder (base64 .URLEncoding , strings .NewReader (authConfigsEncoded ))
154- if err := json .NewDecoder (authConfigsJSON ).Decode (& authConfigs ); err != nil {
155- // for a pull it is not an error if no auth was given
156- // to increase compatibility with the existing api it is defaulting
157- // to be empty.
158- }
159- }
135+ var notVerboseBuffer = bytes .NewBuffer (nil )
160136
161137 w .Header ().Set ("Content-Type" , "application/json" )
162138
@@ -183,7 +159,12 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
183159 if err != nil {
184160 return errf (err )
185161 }
186- buildOptions .AuthConfigs = authConfigs
162+ buildOptions .AuthConfigs = getAuthConfigs (r .Header )
163+
164+ if buildOptions .Squash && ! br .daemon .HasExperimental () {
165+ return apierrors .NewBadRequestError (
166+ errors .New ("squash is only supported with experimental mode" ))
167+ }
187168
188169 // Currently, only used if context is from a remote url.
189170 // Look at code in DetectContextFromRemoteURL for more information.
@@ -199,18 +180,12 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
199180 if buildOptions .SuppressOutput {
200181 out = notVerboseBuffer
201182 }
202- out = & syncWriter {w : out }
203- stdout := & streamformatter.StdoutFormatter {Writer : out , StreamFormatter : sf }
204- stderr := & streamformatter.StderrFormatter {Writer : out , StreamFormatter : sf }
205-
206- pg := backend.ProgressWriter {
207- Output : out ,
208- StdoutFormatter : stdout ,
209- StderrFormatter : stderr ,
210- ProgressReaderFunc : createProgressReader ,
211- }
212183
213- imgID , err := br .backend .BuildFromContext (ctx , r .Body , buildOptions , pg )
184+ imgID , err := br .backend .Build (ctx , backend.BuildConfig {
185+ Source : r .Body ,
186+ Options : buildOptions ,
187+ ProgressWriter : buildProgressWriter (out , sf , createProgressReader ),
188+ })
214189 if err != nil {
215190 return errf (err )
216191 }
@@ -219,8 +194,47 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
219194 // should be just the image ID and we'll print that to stdout.
220195 if buildOptions .SuppressOutput {
221196 stdout := & streamformatter.StdoutFormatter {Writer : output , StreamFormatter : sf }
222- fmt .Fprintf (stdout , "%s \n " , string ( imgID ) )
197+ fmt .Fprintln (stdout , imgID )
223198 }
224-
225199 return nil
226200}
201+
202+ func getAuthConfigs (header http.Header ) map [string ]types.AuthConfig {
203+ authConfigs := map [string ]types.AuthConfig {}
204+ authConfigsEncoded := header .Get ("X-Registry-Config" )
205+
206+ if authConfigsEncoded == "" {
207+ return authConfigs
208+ }
209+
210+ authConfigsJSON := base64 .NewDecoder (base64 .URLEncoding , strings .NewReader (authConfigsEncoded ))
211+ // Pulling an image does not error when no auth is provided so to remain
212+ // consistent with the existing api decode errors are ignored
213+ json .NewDecoder (authConfigsJSON ).Decode (& authConfigs )
214+ return authConfigs
215+ }
216+
217+ type syncWriter struct {
218+ w io.Writer
219+ mu sync.Mutex
220+ }
221+
222+ func (s * syncWriter ) Write (b []byte ) (count int , err error ) {
223+ s .mu .Lock ()
224+ count , err = s .w .Write (b )
225+ s .mu .Unlock ()
226+ return
227+ }
228+
229+ func buildProgressWriter (out io.Writer , sf * streamformatter.StreamFormatter , createProgressReader func (io.ReadCloser ) io.ReadCloser ) backend.ProgressWriter {
230+ out = & syncWriter {w : out }
231+ stdout := & streamformatter.StdoutFormatter {Writer : out , StreamFormatter : sf }
232+ stderr := & streamformatter.StderrFormatter {Writer : out , StreamFormatter : sf }
233+
234+ return backend.ProgressWriter {
235+ Output : out ,
236+ StdoutFormatter : stdout ,
237+ StderrFormatter : stderr ,
238+ ProgressReaderFunc : createProgressReader ,
239+ }
240+ }
0 commit comments