dockerfile: allow automatic platform variables
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>docker-18.09
parent
33f4382b69
commit
69bb8e8a15
|
@ -58,6 +58,11 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
|
||||||
|
|
||||||
platformOpt := buildPlatformOpt(&opt)
|
platformOpt := buildPlatformOpt(&opt)
|
||||||
|
|
||||||
|
optMetaArgs := getPlatformArgs(platformOpt)
|
||||||
|
for i, arg := range optMetaArgs {
|
||||||
|
optMetaArgs[i] = setKVValue(arg, opt.BuildArgs)
|
||||||
|
}
|
||||||
|
|
||||||
dockerfile, err := parser.Parse(bytes.NewReader(dt))
|
dockerfile, err := parser.Parse(bytes.NewReader(dt))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -70,7 +75,6 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
optMetaArgs := []instructions.KeyValuePairOptional{}
|
|
||||||
for _, metaArg := range metaArgs {
|
for _, metaArg := range metaArgs {
|
||||||
optMetaArgs = append(optMetaArgs, setKVValue(metaArg.KeyValuePairOptional, opt.BuildArgs))
|
optMetaArgs = append(optMetaArgs, setKVValue(metaArg.KeyValuePairOptional, opt.BuildArgs))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package dockerfile2llb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/containerd/containerd/platforms"
|
"github.com/containerd/containerd/platforms"
|
||||||
|
"github.com/moby/buildkit/frontend/dockerfile/instructions"
|
||||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -34,3 +35,24 @@ func buildPlatformOpt(opt *ConvertOpt) *platformOpt {
|
||||||
implicitTarget: implicitTargetPlatform,
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -69,6 +70,8 @@ func TestIntegration(t *testing.T) {
|
||||||
testNoSnapshotLeak,
|
testNoSnapshotLeak,
|
||||||
testCopySymlinks,
|
testCopySymlinks,
|
||||||
testContextChangeDirToFile,
|
testContextChangeDirToFile,
|
||||||
|
testPlatformArgsImplicit,
|
||||||
|
testPlatformArgsExplicit,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2281,6 +2284,106 @@ COPY --from=s1 unique2 /
|
||||||
require.NotEqual(t, string(unique2Dir1), string(unique2Dir3))
|
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) {
|
func testBuiltinArgs(t *testing.T, sb integration.Sandbox) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue