Przeglądaj źródła

Extract two functions from the FROM dispatcher

This helps clarify the difference cases for parsing ctxName, and for
getting an image.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Daniel Nephin 8 lat temu
rodzic
commit
4d62f67117
1 zmienionych plików z 53 dodań i 42 usunięć
  1. 53 42
      builder/dockerfile/dispatchers.go

+ 53 - 42
builder/dockerfile/dispatchers.go

@@ -176,69 +176,80 @@ func dispatchCopy(b *Builder, args []string, attributes map[string]bool, origina
 	return b.runContextCommand(args, false, false, "COPY", im)
 }
 
-// FROM imagename
-//
-// This sets the image the dockerfile will build on top of.
+// FROM imagename[:tag | @digest] [AS build-stage-name]
 //
+// from sets the base image
 func from(b *Builder, args []string, attributes map[string]bool, original string) error {
-	ctxName := ""
-	if len(args) == 3 && strings.EqualFold(args[1], "as") {
-		ctxName = strings.ToLower(args[2])
-		if ok, _ := regexp.MatchString("^[a-z][a-z0-9-_\\.]*$", ctxName); !ok {
-			return errors.Errorf("invalid name for build stage: %q, name can't start with a number or contain symbols", ctxName)
-		}
-	} else if len(args) != 1 {
-		return errors.New("FROM requires either one or three arguments")
+	ctxName, err := parseBuildStageName(args)
+	if err != nil {
+		return err
 	}
 
 	if err := b.flags.Parse(); err != nil {
 		return err
 	}
-
-	substituionArgs := []string{}
-	for key, value := range b.buildArgs.GetAllMeta() {
-		substituionArgs = append(substituionArgs, key+"="+value)
+	b.resetImageCache()
+	if _, err := b.imageContexts.new(ctxName, true); err != nil {
+		return err
 	}
 
-	name, err := ProcessWord(args[0], substituionArgs, b.escapeToken)
+	image, err := b.getFromImage(args[0])
 	if err != nil {
 		return err
 	}
+	if image != nil {
+		b.imageContexts.update(image.ImageID(), image.RunConfig())
+	}
+	b.from = image
 
-	var image builder.Image
+	b.buildArgs.ResetAllowed()
+	return b.processImageFrom(image)
+}
 
-	b.resetImageCache()
-	if _, err := b.imageContexts.new(ctxName, true); err != nil {
-		return err
+func parseBuildStageName(args []string) (string, error) {
+	stageName := ""
+	switch {
+	case len(args) == 3 && strings.EqualFold(args[1], "as"):
+		stageName = strings.ToLower(args[2])
+		if ok, _ := regexp.MatchString("^[a-z][a-z0-9-_\\.]*$", stageName); !ok {
+			return "", errors.Errorf("invalid name for build stage: %q, name can't start with a number or contain symbols", stageName)
+		}
+	case len(args) != 1:
+		return "", errors.New("FROM requires either one or three arguments")
+	}
+
+	return stageName, nil
+}
+
+func (b *Builder) getFromImage(name string) (builder.Image, error) {
+	substitutionArgs := []string{}
+	for key, value := range b.buildArgs.GetAllMeta() {
+		substitutionArgs = append(substitutionArgs, key+"="+value)
+	}
+
+	name, err := ProcessWord(name, substitutionArgs, b.escapeToken)
+	if err != nil {
+		return nil, err
 	}
 
 	if im, ok := b.imageContexts.byName[name]; ok {
 		if len(im.ImageID()) > 0 {
-			image = im
+			return im, nil
 		}
-	} else {
-		// Windows cannot support a container with no base image.
-		if name == api.NoBaseImageSpecifier {
-			if runtime.GOOS == "windows" {
-				return errors.New("Windows does not support FROM scratch")
-			}
-			b.image = ""
-			b.noBaseImage = true
-		} else {
-			var err error
-			image, err = pullOrGetImage(b, name)
-			if err != nil {
-				return err
-			}
-		}
-	}
-	if image != nil {
-		b.imageContexts.update(image.ImageID(), image.RunConfig())
+		// FROM scratch does not have an ImageID
+		return nil, nil
 	}
-	b.from = image
 
-	b.buildArgs.ResetAllowed()
-	return b.processImageFrom(image)
+	// Windows cannot support a container with no base image.
+	if name == api.NoBaseImageSpecifier {
+		if runtime.GOOS == "windows" {
+			return nil, errors.New("Windows does not support FROM scratch")
+		}
+		b.image = ""
+		b.noBaseImage = true
+		return nil, nil
+	}
+	return pullOrGetImage(b, name)
 }
 
 // ONBUILD RUN echo yo