Browse code

Factor out functions from builder/dockerfile/builder.go:Builder.build()

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>

Daniel Nephin authored on 2017/04/05 05:34:19
Showing 4 changed files
... ...
@@ -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.
... ...
@@ -77,6 +77,6 @@ func readAndCheckDockerfile(t *testing.T, testName, contextDir, dockerfilePath,
77 77
 
78 78
 	b := &Builder{options: options, context: context}
79 79
 
80
-	_, err = b.readDockerfile()
80
+	_, err = b.readAndParseDockerfile()
81 81
 	assert.Error(t, err, expectedError)
82 82
 }