Explorar o código

Builder - add --platform to FROM statement

Signed-off-by: John Howard <jhoward@microsoft.com>
John Howard %!s(int64=7) %!d(string=hai) anos
pai
achega
7f0c2d23e1

+ 1 - 1
builder/dockerfile/dispatchers.go

@@ -148,7 +148,7 @@ func (d *dispatchRequest) getImageMount(imageRefOrID string) (*imageMount, error
 	return d.builder.imageSources.Get(imageRefOrID, localOnly)
 }
 
-// FROM imagename[:tag | @digest] [AS build-stage-name]
+// FROM [--platform=platform] imagename[:tag | @digest] [AS build-stage-name]
 //
 func initializeStage(d dispatchRequest, cmd *instructions.Stage) error {
 	d.builder.imageProber.Reset()

+ 5 - 4
builder/dockerfile/instructions/commands.go

@@ -357,10 +357,11 @@ type ShellCommand struct {
 
 // Stage represents a single stage in a multi-stage build
 type Stage struct {
-	Name       string
-	Commands   []Command
-	BaseName   string
-	SourceCode string
+	Name            string
+	Commands        []Command
+	BaseName        string
+	SourceCode      string
+	OperatingSystem string
 }
 
 // AddCommand to the stage

+ 22 - 5
builder/dockerfile/instructions/parse.go

@@ -3,6 +3,7 @@ package instructions // import "github.com/docker/docker/builder/dockerfile/inst
 import (
 	"fmt"
 	"regexp"
+	"runtime"
 	"sort"
 	"strconv"
 	"strings"
@@ -12,6 +13,7 @@ import (
 	"github.com/docker/docker/api/types/strslice"
 	"github.com/docker/docker/builder/dockerfile/command"
 	"github.com/docker/docker/builder/dockerfile/parser"
+	"github.com/docker/docker/pkg/system"
 	"github.com/pkg/errors"
 )
 
@@ -271,16 +273,31 @@ func parseFrom(req parseRequest) (*Stage, error) {
 		return nil, err
 	}
 
+	flPlatform := req.flags.AddString("platform", "")
 	if err := req.flags.Parse(); err != nil {
 		return nil, err
 	}
+	specPlatform := system.ParsePlatform(flPlatform.Value)
+	if specPlatform.OS == "" {
+		specPlatform.OS = runtime.GOOS
+	}
+	if err := system.ValidatePlatform(specPlatform); err != nil {
+		return nil, fmt.Errorf("invalid platform %q on FROM", flPlatform.Value)
+	}
+	if !system.IsOSSupported(specPlatform.OS) {
+		return nil, fmt.Errorf("unsupported platform %q on FROM", flPlatform.Value)
+	}
+	if err != nil {
+		return nil, err
+	}
 	code := strings.TrimSpace(req.original)
-
+	fmt.Println("JJH", specPlatform.OS)
 	return &Stage{
-		BaseName:   req.args[0],
-		Name:       stageName,
-		SourceCode: code,
-		Commands:   []Command{},
+		BaseName:        req.args[0],
+		Name:            stageName,
+		SourceCode:      code,
+		Commands:        []Command{},
+		OperatingSystem: specPlatform.OS,
 	}, nil
 
 }

+ 12 - 1
builder/dockerfile/instructions/parse_test.go

@@ -1,6 +1,8 @@
 package instructions // import "github.com/docker/docker/builder/dockerfile/instructions"
 
 import (
+	"fmt"
+	"runtime"
 	"strings"
 	"testing"
 
@@ -184,6 +186,16 @@ func TestErrorCases(t *testing.T) {
 			dockerfile:    `foo bar`,
 			expectedError: "unknown instruction: FOO",
 		},
+		{
+			name:          "Invalid platform",
+			dockerfile:    `FROM --platform=invalid busybox`,
+			expectedError: `invalid platform "invalid"`,
+		},
+		{
+			name:          "Only OS",
+			dockerfile:    fmt.Sprintf(`FROM --platform=%s/%s busybox`, runtime.GOOS, runtime.GOARCH),
+			expectedError: `invalid platform`,
+		},
 	}
 	for _, c := range cases {
 		r := strings.NewReader(c.dockerfile)
@@ -196,5 +208,4 @@ func TestErrorCases(t *testing.T) {
 		_, err = ParseInstruction(n)
 		testutil.ErrorContains(t, err, c.expectedError)
 	}
-
 }