Remove the block comment which is stale, and redundant now that the
function is just as readable as the comment.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
... | ... |
@@ -185,17 +185,6 @@ func sanitizeRepoAndTags(names []string) ([]reference.Named, error) { |
185 | 185 |
|
186 | 186 |
// build runs the Dockerfile builder from a context and a docker object that allows to make calls |
187 | 187 |
// to Docker. |
188 |
-// |
|
189 |
-// This will (barring errors): |
|
190 |
-// |
|
191 |
-// * read the dockerfile from context |
|
192 |
-// * parse the dockerfile if not already parsed |
|
193 |
-// * walk the AST and execute it by dispatching to handlers. If Remove |
|
194 |
-// or ForceRemove is set, additional cleanup around containers happens after |
|
195 |
-// processing. |
|
196 |
-// * Tag image, if applicable. |
|
197 |
-// * Print a happy message and return the image ID. |
|
198 |
-// |
|
199 | 188 |
func (b *Builder) build(stdout io.Writer, stderr io.Writer, out io.Writer) (string, error) { |
200 | 189 |
defer b.imageContexts.unmount() |
201 | 190 |
|
... | ... |
@@ -203,7 +192,7 @@ func (b *Builder) build(stdout io.Writer, stderr io.Writer, out io.Writer) (stri |
203 | 203 |
b.Stderr = stderr |
204 | 204 |
b.Output = out |
205 | 205 |
|
206 |
- dockerfile, err := b.readDockerfile() |
|
206 |
+ dockerfile, err := b.readAndParseDockerfile() |
|
207 | 207 |
if err != nil { |
208 | 208 |
return "", err |
209 | 209 |
} |
... | ... |
@@ -215,14 +204,37 @@ func (b *Builder) build(stdout io.Writer, stderr io.Writer, out io.Writer) (stri |
215 | 215 |
|
216 | 216 |
addNodesForLabelOption(dockerfile, b.options.Labels) |
217 | 217 |
|
218 |
- var shortImgID string |
|
219 |
- total := len(dockerfile.Children) |
|
220 |
- for _, n := range dockerfile.Children { |
|
221 |
- if err := b.checkDispatch(n, false); err != nil { |
|
222 |
- return "", errors.Wrapf(err, "Dockerfile parse error line %d", n.StartLine) |
|
218 |
+ if err := checkDispatchDockerfile(dockerfile); err != nil { |
|
219 |
+ return "", err |
|
220 |
+ } |
|
221 |
+ |
|
222 |
+ shortImageID, err := b.dispatchDockerfileWithCancellation(dockerfile) |
|
223 |
+ if err != nil { |
|
224 |
+ return "", err |
|
225 |
+ } |
|
226 |
+ |
|
227 |
+ b.warnOnUnusedBuildArgs() |
|
228 |
+ |
|
229 |
+ if b.image == "" { |
|
230 |
+ return "", errors.New("No image was generated. Is your Dockerfile empty?") |
|
231 |
+ } |
|
232 |
+ |
|
233 |
+ if b.options.Squash { |
|
234 |
+ if err := b.squashBuild(); err != nil { |
|
235 |
+ return "", err |
|
223 | 236 |
} |
224 | 237 |
} |
225 | 238 |
|
239 |
+ fmt.Fprintf(b.Stdout, "Successfully built %s\n", shortImageID) |
|
240 |
+ if err := b.tagImages(repoAndTags); err != nil { |
|
241 |
+ return "", err |
|
242 |
+ } |
|
243 |
+ return b.image, nil |
|
244 |
+} |
|
245 |
+ |
|
246 |
+func (b *Builder) dispatchDockerfileWithCancellation(dockerfile *parser.Node) (string, error) { |
|
247 |
+ total := len(dockerfile.Children) |
|
248 |
+ var shortImgID string |
|
226 | 249 |
for i, n := range dockerfile.Children { |
227 | 250 |
select { |
228 | 251 |
case <-b.clientCtx.Done(): |
... | ... |
@@ -255,34 +267,20 @@ func (b *Builder) build(stdout io.Writer, stderr io.Writer, out io.Writer) (stri |
255 | 255 |
return "", errors.Errorf("failed to reach build target %s in Dockerfile", b.options.Target) |
256 | 256 |
} |
257 | 257 |
|
258 |
- b.warnOnUnusedBuildArgs() |
|
259 |
- |
|
260 |
- if b.image == "" { |
|
261 |
- return "", errors.New("No image was generated. Is your Dockerfile empty?") |
|
262 |
- } |
|
258 |
+ return shortImgID, nil |
|
259 |
+} |
|
263 | 260 |
|
264 |
- if b.options.Squash { |
|
265 |
- var fromID string |
|
266 |
- if b.from != nil { |
|
267 |
- fromID = b.from.ImageID() |
|
268 |
- } |
|
269 |
- b.image, err = b.docker.SquashImage(b.image, fromID) |
|
270 |
- if err != nil { |
|
271 |
- return "", errors.Wrap(err, "error squashing image") |
|
272 |
- } |
|
261 |
+func (b *Builder) squashBuild() error { |
|
262 |
+ var fromID string |
|
263 |
+ var err error |
|
264 |
+ if b.from != nil { |
|
265 |
+ fromID = b.from.ImageID() |
|
273 | 266 |
} |
274 |
- |
|
275 |
- fmt.Fprintf(b.Stdout, "Successfully built %s\n", shortImgID) |
|
276 |
- |
|
277 |
- imageID := image.ID(b.image) |
|
278 |
- for _, rt := range repoAndTags { |
|
279 |
- if err := b.docker.TagImageWithReference(imageID, rt); err != nil { |
|
280 |
- return "", err |
|
281 |
- } |
|
282 |
- fmt.Fprintf(b.Stdout, "Successfully tagged %s\n", reference.FamiliarString(rt)) |
|
267 |
+ b.image, err = b.docker.SquashImage(b.image, fromID) |
|
268 |
+ if err != nil { |
|
269 |
+ return errors.Wrap(err, "error squashing image") |
|
283 | 270 |
} |
284 |
- |
|
285 |
- return b.image, nil |
|
271 |
+ return nil |
|
286 | 272 |
} |
287 | 273 |
|
288 | 274 |
func addNodesForLabelOption(dockerfile *parser.Node, labels map[string]string) { |
... | ... |
@@ -303,6 +301,17 @@ func (b *Builder) warnOnUnusedBuildArgs() { |
303 | 303 |
} |
304 | 304 |
} |
305 | 305 |
|
306 |
+func (b *Builder) tagImages(repoAndTags []reference.Named) error { |
|
307 |
+ imageID := image.ID(b.image) |
|
308 |
+ for _, rt := range repoAndTags { |
|
309 |
+ if err := b.docker.TagImageWithReference(imageID, rt); err != nil { |
|
310 |
+ return err |
|
311 |
+ } |
|
312 |
+ fmt.Fprintf(b.Stdout, "Successfully tagged %s\n", reference.FamiliarString(rt)) |
|
313 |
+ } |
|
314 |
+ return nil |
|
315 |
+} |
|
316 |
+ |
|
306 | 317 |
// hasFromImage returns true if the builder has processed a `FROM <image>` line |
307 | 318 |
func (b *Builder) hasFromImage() bool { |
308 | 319 |
return b.image != "" || b.noBaseImage |
... | ... |
@@ -345,18 +354,31 @@ func BuildFromConfig(config *container.Config, changes []string) (*container.Con |
345 | 345 |
b.Stderr = ioutil.Discard |
346 | 346 |
b.disableCommit = true |
347 | 347 |
|
348 |
- total := len(ast.Children) |
|
349 |
- for _, n := range ast.Children { |
|
350 |
- if err := b.checkDispatch(n, false); err != nil { |
|
351 |
- return nil, err |
|
348 |
+ if err := checkDispatchDockerfile(ast); err != nil { |
|
349 |
+ return nil, err |
|
350 |
+ } |
|
351 |
+ |
|
352 |
+ if err := dispatchFromDockerfile(b, ast); err != nil { |
|
353 |
+ return nil, err |
|
354 |
+ } |
|
355 |
+ return b.runConfig, nil |
|
356 |
+} |
|
357 |
+ |
|
358 |
+func checkDispatchDockerfile(dockerfile *parser.Node) error { |
|
359 |
+ for _, n := range dockerfile.Children { |
|
360 |
+ if err := checkDispatch(n); err != nil { |
|
361 |
+ return errors.Wrapf(err, "Dockerfile parse error line %d", n.StartLine) |
|
352 | 362 |
} |
353 | 363 |
} |
364 |
+ return nil |
|
365 |
+} |
|
354 | 366 |
|
367 |
+func dispatchFromDockerfile(b *Builder, ast *parser.Node) error { |
|
368 |
+ total := len(ast.Children) |
|
355 | 369 |
for i, n := range ast.Children { |
356 | 370 |
if err := b.dispatch(i, total, n); err != nil { |
357 |
- return nil, err |
|
371 |
+ return err |
|
358 | 372 |
} |
359 | 373 |
} |
360 |
- |
|
361 |
- return b.runConfig, nil |
|
374 |
+ return nil |
|
362 | 375 |
} |
... | ... |
@@ -206,8 +206,7 @@ func (b *Builder) runConfigEnvMapping() map[string]string { |
206 | 206 |
// arg, env, etc., this syntax check will not be complete and could not replace |
207 | 207 |
// the runtime check. Instead, this function is only a helper that allows |
208 | 208 |
// user to find out the obvious error in Dockerfile earlier on. |
209 |
-// onbuild bool: indicate if instruction XXX is part of `ONBUILD XXX` trigger |
|
210 |
-func (b *Builder) checkDispatch(ast *parser.Node, onbuild bool) error { |
|
209 |
+func checkDispatch(ast *parser.Node) error { |
|
211 | 210 |
cmd := ast.Value |
212 | 211 |
upperCasedCmd := strings.ToUpper(cmd) |
213 | 212 |
|
... | ... |
@@ -225,16 +224,6 @@ func (b *Builder) checkDispatch(ast *parser.Node, onbuild bool) error { |
225 | 225 |
} |
226 | 226 |
} |
227 | 227 |
|
228 |
- // The instruction is part of ONBUILD trigger (not the instruction itself) |
|
229 |
- if onbuild { |
|
230 |
- switch upperCasedCmd { |
|
231 |
- case "ONBUILD": |
|
232 |
- return errors.New("Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed") |
|
233 |
- case "MAINTAINER", "FROM": |
|
234 |
- return fmt.Errorf("%s isn't allowed as an ONBUILD trigger", upperCasedCmd) |
|
235 |
- } |
|
236 |
- } |
|
237 |
- |
|
238 | 228 |
if _, ok := evaluateTable[cmd]; ok { |
239 | 229 |
return nil |
240 | 230 |
} |
... | ... |
@@ -467,19 +467,24 @@ func (b *Builder) processImageFrom(img builder.Image) error { |
467 | 467 |
return err |
468 | 468 |
} |
469 | 469 |
|
470 |
- total := len(ast.Children) |
|
471 | 470 |
for _, n := range ast.Children { |
472 |
- if err := b.checkDispatch(n, true); err != nil { |
|
471 |
+ if err := checkDispatch(n); err != nil { |
|
473 | 472 |
return err |
474 | 473 |
} |
475 |
- } |
|
476 |
- for i, n := range ast.Children { |
|
477 |
- if err := b.dispatch(i, total, n); err != nil { |
|
478 |
- return err |
|
474 |
+ |
|
475 |
+ upperCasedCmd := strings.ToUpper(n.Value) |
|
476 |
+ switch upperCasedCmd { |
|
477 |
+ case "ONBUILD": |
|
478 |
+ return errors.New("Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed") |
|
479 |
+ case "MAINTAINER", "FROM": |
|
480 |
+ return errors.Errorf("%s isn't allowed as an ONBUILD trigger", upperCasedCmd) |
|
479 | 481 |
} |
480 | 482 |
} |
481 |
- } |
|
482 | 483 |
|
484 |
+ if err := dispatchFromDockerfile(b, ast); err != nil { |
|
485 |
+ return err |
|
486 |
+ } |
|
487 |
+ } |
|
483 | 488 |
return nil |
484 | 489 |
} |
485 | 490 |
|
... | ... |
@@ -644,8 +649,8 @@ func (b *Builder) clearTmp() { |
644 | 644 |
} |
645 | 645 |
} |
646 | 646 |
|
647 |
-// readDockerfile reads a Dockerfile from the current context. |
|
648 |
-func (b *Builder) readDockerfile() (*parser.Node, error) { |
|
647 |
+// readAndParseDockerfile reads a Dockerfile from the current context. |
|
648 |
+func (b *Builder) readAndParseDockerfile() (*parser.Node, error) { |
|
649 | 649 |
// If no -f was specified then look for 'Dockerfile'. If we can't find |
650 | 650 |
// that then look for 'dockerfile'. If neither are found then default |
651 | 651 |
// back to 'Dockerfile' and use that in the error message. |