dockerfile: allow automatic platform variables

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
docker-18.09
Tonis Tiigi 2018-07-10 16:57:57 -07:00
parent 33f4382b69
commit 69bb8e8a15
3 changed files with 130 additions and 1 deletions

View File

@ -58,6 +58,11 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
platformOpt := buildPlatformOpt(&opt)
optMetaArgs := getPlatformArgs(platformOpt)
for i, arg := range optMetaArgs {
optMetaArgs[i] = setKVValue(arg, opt.BuildArgs)
}
dockerfile, err := parser.Parse(bytes.NewReader(dt))
if err != nil {
return nil, nil, err
@ -70,7 +75,6 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
return nil, nil, err
}
optMetaArgs := []instructions.KeyValuePairOptional{}
for _, metaArg := range metaArgs {
optMetaArgs = append(optMetaArgs, setKVValue(metaArg.KeyValuePairOptional, opt.BuildArgs))
}

View File

@ -2,6 +2,7 @@ package dockerfile2llb
import (
"github.com/containerd/containerd/platforms"
"github.com/moby/buildkit/frontend/dockerfile/instructions"
specs "github.com/opencontainers/image-spec/specs-go/v1"
)
@ -34,3 +35,24 @@ func buildPlatformOpt(opt *ConvertOpt) *platformOpt {
implicitTarget: implicitTargetPlatform,
}
}
func getPlatformArgs(po *platformOpt) []instructions.KeyValuePairOptional {
bp := po.buildPlatforms[0]
tp := po.targetPlatform
m := map[string]string{
"BUILDPLATFORM": platforms.Format(bp),
"BUILDOS": bp.OS,
"BUILDARCH": bp.Architecture,
"BUILDVARIANT": bp.Variant,
"TARGETPLATFORM": platforms.Format(tp),
"TARGETOS": tp.OS,
"TARGETARCH": tp.Architecture,
"TARGETVARIANT": tp.Variant,
}
opts := make([]instructions.KeyValuePairOptional, 0, len(m))
for k, v := range m {
s := v
opts = append(opts, instructions.KeyValuePairOptional{Key: k, Value: &s})
}
return opts
}

View File

@ -13,6 +13,7 @@ import (
"os"
"os/exec"
"path/filepath"
"runtime"
"sort"
"strings"
"testing"
@ -69,6 +70,8 @@ func TestIntegration(t *testing.T) {
testNoSnapshotLeak,
testCopySymlinks,
testContextChangeDirToFile,
testPlatformArgsImplicit,
testPlatformArgsExplicit,
})
}
@ -2281,6 +2284,106 @@ COPY --from=s1 unique2 /
require.NotEqual(t, string(unique2Dir1), string(unique2Dir3))
}
func testPlatformArgsImplicit(t *testing.T, sb integration.Sandbox) {
t.Parallel()
dockerfile := []byte(fmt.Sprintf(`
FROM scratch AS build-%s
COPY foo bar
FROM build-${TARGETOS}
COPY foo2 bar2
`, runtime.GOOS))
dir, err := tmpdir(
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("d0"), 0600),
fstest.CreateFile("foo2", []byte("d1"), 0600),
)
require.NoError(t, err)
defer os.RemoveAll(dir)
c, err := client.New(context.TODO(), sb.Address())
require.NoError(t, err)
defer c.Close()
destDir, err := ioutil.TempDir("", "buildkit")
require.NoError(t, err)
defer os.RemoveAll(destDir)
opt := client.SolveOpt{
Frontend: "dockerfile.v0",
Exporter: client.ExporterLocal,
ExporterOutputDir: destDir,
LocalDirs: map[string]string{
builder.LocalNameDockerfile: dir,
builder.LocalNameContext: dir,
},
}
_, err = c.Solve(context.TODO(), nil, opt, nil)
require.NoError(t, err)
dt, err := ioutil.ReadFile(filepath.Join(destDir, "bar"))
require.NoError(t, err)
require.Equal(t, "d0", string(dt))
dt, err = ioutil.ReadFile(filepath.Join(destDir, "bar2"))
require.NoError(t, err)
require.Equal(t, "d1", string(dt))
}
func testPlatformArgsExplicit(t *testing.T, sb integration.Sandbox) {
t.Parallel()
dockerfile := []byte(`
FROM --platform=$BUILDPLATFORM busybox AS build
ARG TARGETPLATFORM
ARG TARGETOS
RUN mkdir /out && echo -n $TARGETPLATFORM > /out/platform && echo -n $TARGETOS > /out/os
FROM scratch
COPY --from=build out .
`)
dir, err := tmpdir(
fstest.CreateFile("Dockerfile", dockerfile, 0600),
)
require.NoError(t, err)
defer os.RemoveAll(dir)
c, err := client.New(context.TODO(), sb.Address())
require.NoError(t, err)
defer c.Close()
destDir, err := ioutil.TempDir("", "buildkit")
require.NoError(t, err)
defer os.RemoveAll(destDir)
opt := client.SolveOpt{
Frontend: "dockerfile.v0",
Exporter: client.ExporterLocal,
FrontendAttrs: map[string]string{
"platform": "darwin/ppc64le",
"build-arg:TARGETOS": "freebsd",
},
ExporterOutputDir: destDir,
LocalDirs: map[string]string{
builder.LocalNameDockerfile: dir,
builder.LocalNameContext: dir,
},
}
_, err = c.Solve(context.TODO(), nil, opt, nil)
require.NoError(t, err)
dt, err := ioutil.ReadFile(filepath.Join(destDir, "platform"))
require.NoError(t, err)
require.Equal(t, "darwin/ppc64le", string(dt))
dt, err = ioutil.ReadFile(filepath.Join(destDir, "os"))
require.NoError(t, err)
require.Equal(t, "freebsd", string(dt))
}
func testBuiltinArgs(t *testing.T, sb integration.Sandbox) {
t.Parallel()