Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: handle push/load shorthands for multi exporters #2302

Merged
merged 2 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions commands/bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,9 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba

overrides := in.overrides
if in.exportPush {
if in.exportLoad {
return errors.Errorf("push and load may not be set together at the moment")
}
overrides = append(overrides, "*.push=true")
} else if in.exportLoad {
overrides = append(overrides, "*.output=type=registry")
}
if in.exportLoad {
overrides = append(overrides, "*.output=type=docker")
}
if cFlags.noCache != nil {
Expand Down
46 changes: 23 additions & 23 deletions controller/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,38 +99,38 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
return nil, nil, err
}
if in.ExportPush {
if in.ExportLoad {
return nil, nil, errors.Errorf("push and load may not be set together at the moment")
var pushUsed bool
for i := range outputs {
if outputs[i].Type == client.ExporterImage {
outputs[i].Attrs["push"] = "true"
pushUsed = true
}
}
if len(outputs) == 0 {
outputs = []client.ExportEntry{{
Type: "image",
if !pushUsed {
outputs = append(outputs, client.ExportEntry{
Type: client.ExporterImage,
Attrs: map[string]string{
"push": "true",
},
}}
} else {
switch outputs[0].Type {
case "image":
outputs[0].Attrs["push"] = "true"
default:
return nil, nil, errors.Errorf("push and %q output can't be used together", outputs[0].Type)
}
})
}
}
if in.ExportLoad {
if len(outputs) == 0 {
outputs = []client.ExportEntry{{
Type: "docker",
Attrs: map[string]string{},
}}
} else {
switch outputs[0].Type {
case "docker":
default:
return nil, nil, errors.Errorf("load and %q output can't be used together", outputs[0].Type)
var loadUsed bool
for i := range outputs {
if outputs[i].Type == client.ExporterDocker {
if _, ok := outputs[i].Attrs["dest"]; !ok {
loadUsed = true
break
}
}
}
if !loadUsed {
outputs = append(outputs, client.ExportEntry{
Type: client.ExporterDocker,
Attrs: map[string]string{},
})
}
}

annotations, err := buildflags.ParseAnnotations(in.Annotations)
Expand Down
160 changes: 160 additions & 0 deletions tests/bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ package tests

import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"testing"

"github.com/containerd/continuity/fs/fstest"
"github.com/docker/buildx/util/gitutil"
"github.com/moby/buildkit/identity"
"github.com/moby/buildkit/util/contentutil"
"github.com/moby/buildkit/util/testutil"
"github.com/moby/buildkit/util/testutil/integration"
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -36,6 +42,8 @@ var bakeTests = []func(t *testing.T, sb integration.Sandbox){
testBakeShmSize,
testBakeUlimits,
testBakeRefs,
testBakeMultiExporters,
testBakeLoadPush,
}

func testBakeLocal(t *testing.T, sb integration.Sandbox) {
Expand Down Expand Up @@ -631,3 +639,155 @@ target "default" {

require.NotEmpty(t, md.Default.BuildRef)
}

func testBakeMultiExporters(t *testing.T, sb integration.Sandbox) {
if sb.Name() != "docker" {
t.Skip("skipping test for non-docker workers")
}

registry, err := sb.NewRegistry()
if errors.Is(err, integration.ErrRequirements) {
t.Skip(err.Error())
}
require.NoError(t, err)

targetReg := registry + "/buildx/registry:latest"
targetStore := "buildx:local-" + identity.NewID()

var builderName string
t.Cleanup(func() {
if builderName == "" {
return
}

cmd := dockerCmd(sb, withArgs("image", "rm", targetStore))
cmd.Stderr = os.Stderr
require.NoError(t, cmd.Run())

out, err := rmCmd(sb, withArgs(builderName))
require.NoError(t, err, out)
})

// TODO: use stable buildkit image when v0.13.0 released
out, err := createCmd(sb, withArgs(
"--driver", "docker-container",
"--buildkitd-flags=--allow-insecure-entitlement=network.host",
"--driver-opt", "network=host",
"--driver-opt", "image=moby/buildkit:v0.13.0-rc3",
))
require.NoError(t, err, out)
builderName = strings.TrimSpace(out)

dockerfile := []byte(`
FROM scratch
COPY foo /foo
`)
bakefile := []byte(`
target "default" {
}
`)
dir := tmpdir(
t,
fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
)

outputs := []string{
"--set", fmt.Sprintf("*.output=type=image,name=%s,push=true", targetReg),
"--set", fmt.Sprintf("*.output=type=docker,name=%s", targetStore),
"--set", fmt.Sprintf("*.output=type=oci,dest=%s/result", dir),
}
cmd := buildxCmd(sb, withDir(dir), withArgs("bake"), withArgs(outputs...))
cmd.Env = append(cmd.Env, "BUILDX_BUILDER="+builderName)
outb, err := cmd.CombinedOutput()
require.NoError(t, err, string(outb))

// test registry
desc, provider, err := contentutil.ProviderFromRef(targetReg)
require.NoError(t, err)
_, err = testutil.ReadImages(sb.Context(), provider, desc)
require.NoError(t, err)

// test docker store
cmd = dockerCmd(sb, withArgs("image", "inspect", targetStore))
cmd.Stderr = os.Stderr
require.NoError(t, cmd.Run())

// test oci
_, err = os.ReadFile(fmt.Sprintf("%s/result", dir))
require.NoError(t, err)

// TODO: test metadata file when supported by multi exporters https://github.com/docker/buildx/issues/2181
}

func testBakeLoadPush(t *testing.T, sb integration.Sandbox) {
if sb.Name() != "docker" {
t.Skip("skipping test for non-docker workers")
}

registry, err := sb.NewRegistry()
if errors.Is(err, integration.ErrRequirements) {
t.Skip(err.Error())
}
require.NoError(t, err)

target := registry + "/buildx/registry:" + identity.NewID()

var builderName string
t.Cleanup(func() {
if builderName == "" {
return
}

cmd := dockerCmd(sb, withArgs("image", "rm", target))
cmd.Stderr = os.Stderr
require.NoError(t, cmd.Run())

out, err := rmCmd(sb, withArgs(builderName))
require.NoError(t, err, out)
})

// TODO: use stable buildkit image when v0.13.0 released
out, err := createCmd(sb, withArgs(
"--driver", "docker-container",
"--buildkitd-flags=--allow-insecure-entitlement=network.host",
"--driver-opt", "network=host",
"--driver-opt", "image=moby/buildkit:v0.13.0-rc3",
))
require.NoError(t, err, out)
builderName = strings.TrimSpace(out)

dockerfile := []byte(`
FROM scratch
COPY foo /foo
`)
bakefile := []byte(`
target "default" {
}
`)
dir := tmpdir(
t,
fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
)

cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--push", "--load", fmt.Sprintf("--set=*.tags=%s", target)))
cmd.Env = append(cmd.Env, "BUILDX_BUILDER="+builderName)
outb, err := cmd.CombinedOutput()
require.NoError(t, err, string(outb))

// test registry
desc, provider, err := contentutil.ProviderFromRef(target)
require.NoError(t, err)
_, err = testutil.ReadImages(sb.Context(), provider, desc)
require.NoError(t, err)

// test docker store
cmd = dockerCmd(sb, withArgs("image", "inspect", target))
cmd.Stderr = os.Stderr
require.NoError(t, cmd.Run())

// TODO: test metadata file when supported by multi exporters https://github.com/docker/buildx/issues/2181
}
Loading
Loading