2022-02-03 04:37:55 -05:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2022-12-05 12:56:09 -05:00
|
|
|
"context"
|
2022-02-03 04:37:55 -05:00
|
|
|
"os"
|
2022-11-03 18:35:45 -04:00
|
|
|
"path/filepath"
|
2022-02-03 04:37:55 -05:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/docker/cli/cli/command"
|
2022-11-03 18:35:45 -04:00
|
|
|
"github.com/docker/cli/cli/context/store"
|
2022-11-03 17:30:27 -04:00
|
|
|
"github.com/docker/cli/cli/flags"
|
2022-02-03 13:11:05 -05:00
|
|
|
"github.com/docker/cli/internal/test/output"
|
2022-12-05 12:56:09 -05:00
|
|
|
"github.com/docker/docker/api/types"
|
|
|
|
"github.com/docker/docker/client"
|
2022-02-03 04:37:55 -05:00
|
|
|
"gotest.tools/v3/assert"
|
|
|
|
"gotest.tools/v3/fs"
|
|
|
|
)
|
|
|
|
|
2022-02-03 13:11:05 -05:00
|
|
|
var pluginFilename = "docker-buildx"
|
|
|
|
|
2022-11-03 18:35:45 -04:00
|
|
|
func TestBuildWithBuilder(t *testing.T) {
|
|
|
|
testcases := []struct {
|
|
|
|
name string
|
|
|
|
context string
|
|
|
|
builder string
|
|
|
|
alias bool
|
|
|
|
expectedEnvs []string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "default",
|
|
|
|
context: "default",
|
|
|
|
alias: false,
|
|
|
|
expectedEnvs: []string{"BUILDX_BUILDER=default"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "custom context",
|
|
|
|
context: "foo",
|
|
|
|
alias: false,
|
|
|
|
expectedEnvs: []string{"BUILDX_BUILDER=foo"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "custom builder name",
|
|
|
|
builder: "mybuilder",
|
|
|
|
alias: false,
|
|
|
|
expectedEnvs: nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "buildx install",
|
|
|
|
alias: true,
|
|
|
|
expectedEnvs: nil,
|
|
|
|
},
|
2022-02-03 13:11:05 -05:00
|
|
|
}
|
|
|
|
|
2022-02-03 04:37:55 -05:00
|
|
|
dir := fs.NewDir(t, t.Name(),
|
2022-02-03 13:11:05 -05:00
|
|
|
fs.WithFile(pluginFilename, `#!/bin/sh
|
2022-09-30 13:13:22 -04:00
|
|
|
echo '{"SchemaVersion":"0.1.0","Vendor":"Docker Inc.","Version":"v0.6.3","ShortDescription":"Build with BuildKit"}'`, fs.WithMode(0o777)),
|
2022-02-03 04:37:55 -05:00
|
|
|
)
|
|
|
|
defer dir.Remove()
|
|
|
|
|
2022-11-03 18:35:45 -04:00
|
|
|
for _, tt := range testcases {
|
|
|
|
tt := tt
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
if tt.builder != "" {
|
|
|
|
t.Setenv("BUILDX_BUILDER", tt.builder)
|
|
|
|
}
|
|
|
|
|
|
|
|
var b bytes.Buffer
|
2022-12-05 12:56:09 -05:00
|
|
|
dockerCli, err := command.NewDockerCli(
|
|
|
|
command.WithAPIClient(&fakeClient{}),
|
|
|
|
command.WithInputStream(discard),
|
|
|
|
command.WithCombinedStreams(&b),
|
|
|
|
)
|
2022-11-03 18:35:45 -04:00
|
|
|
assert.NilError(t, err)
|
|
|
|
assert.NilError(t, dockerCli.Initialize(flags.NewClientOptions()))
|
|
|
|
|
|
|
|
if tt.context != "" {
|
|
|
|
if tt.context != command.DefaultContextName {
|
|
|
|
assert.NilError(t, dockerCli.ContextStore().CreateOrUpdate(store.Metadata{
|
|
|
|
Name: tt.context,
|
|
|
|
Endpoints: map[string]interface{}{
|
|
|
|
"docker": map[string]interface{}{
|
|
|
|
"host": "unix://" + filepath.Join(t.TempDir(), "docker.sock"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
opts := flags.NewClientOptions()
|
2022-11-04 06:58:11 -04:00
|
|
|
opts.Context = tt.context
|
2022-11-03 18:35:45 -04:00
|
|
|
assert.NilError(t, dockerCli.Initialize(opts))
|
|
|
|
}
|
|
|
|
|
|
|
|
dockerCli.ConfigFile().CLIPluginsExtraDirs = []string{dir.Path()}
|
|
|
|
if tt.alias {
|
|
|
|
dockerCli.ConfigFile().Aliases = map[string]string{"builder": "buildx"}
|
|
|
|
}
|
|
|
|
|
|
|
|
tcmd := newDockerCommand(dockerCli)
|
|
|
|
tcmd.SetArgs([]string{"build", "."})
|
|
|
|
|
|
|
|
cmd, args, err := tcmd.HandleGlobalFlags()
|
|
|
|
assert.NilError(t, err)
|
|
|
|
|
|
|
|
var envs []string
|
|
|
|
args, os.Args, envs, err = processBuilder(dockerCli, cmd, args, os.Args)
|
|
|
|
assert.NilError(t, err)
|
|
|
|
assert.DeepEqual(t, []string{builderDefaultPlugin, "build", "."}, args)
|
|
|
|
if tt.expectedEnvs != nil {
|
|
|
|
assert.DeepEqual(t, tt.expectedEnvs, envs)
|
|
|
|
} else {
|
|
|
|
assert.Check(t, len(envs) == 0)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2022-02-03 04:37:55 -05:00
|
|
|
}
|
|
|
|
|
2022-12-05 12:56:09 -05:00
|
|
|
type fakeClient struct {
|
|
|
|
client.Client
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *fakeClient) Ping(_ context.Context) (types.Ping, error) {
|
|
|
|
return types.Ping{OSType: "linux"}, nil
|
|
|
|
}
|
|
|
|
|
2022-02-03 04:37:55 -05:00
|
|
|
func TestBuildkitDisabled(t *testing.T) {
|
2022-09-22 10:31:28 -04:00
|
|
|
t.Setenv("DOCKER_BUILDKIT", "0")
|
2022-02-03 04:37:55 -05:00
|
|
|
|
2022-02-03 13:11:05 -05:00
|
|
|
dir := fs.NewDir(t, t.Name(),
|
2022-09-30 13:13:22 -04:00
|
|
|
fs.WithFile(pluginFilename, `#!/bin/sh exit 1`, fs.WithMode(0o777)),
|
2022-02-03 13:11:05 -05:00
|
|
|
)
|
|
|
|
defer dir.Remove()
|
|
|
|
|
|
|
|
b := bytes.NewBuffer(nil)
|
|
|
|
|
2022-12-05 12:56:09 -05:00
|
|
|
dockerCli, err := command.NewDockerCli(
|
|
|
|
command.WithAPIClient(&fakeClient{}),
|
|
|
|
command.WithInputStream(discard),
|
|
|
|
command.WithCombinedStreams(b),
|
|
|
|
)
|
2022-02-03 13:11:05 -05:00
|
|
|
assert.NilError(t, err)
|
2022-11-03 17:30:27 -04:00
|
|
|
assert.NilError(t, dockerCli.Initialize(flags.NewClientOptions()))
|
2022-02-03 13:11:05 -05:00
|
|
|
dockerCli.ConfigFile().CLIPluginsExtraDirs = []string{dir.Path()}
|
|
|
|
|
|
|
|
tcmd := newDockerCommand(dockerCli)
|
|
|
|
tcmd.SetArgs([]string{"build", "."})
|
|
|
|
|
|
|
|
cmd, args, err := tcmd.HandleGlobalFlags()
|
|
|
|
assert.NilError(t, err)
|
|
|
|
|
2022-11-03 17:30:27 -04:00
|
|
|
var envs []string
|
|
|
|
args, os.Args, envs, err = processBuilder(dockerCli, cmd, args, os.Args)
|
2022-02-03 13:11:05 -05:00
|
|
|
assert.NilError(t, err)
|
|
|
|
assert.DeepEqual(t, []string{"build", "."}, args)
|
2022-11-03 17:30:27 -04:00
|
|
|
assert.Check(t, len(envs) == 0)
|
2022-02-03 13:11:05 -05:00
|
|
|
|
|
|
|
output.Assert(t, b.String(), map[int]func(string) error{
|
|
|
|
0: output.Suffix("DEPRECATED: The legacy builder is deprecated and will be removed in a future release."),
|
2022-12-06 07:46:51 -05:00
|
|
|
1: output.Suffix("BuildKit is currently disabled; enabled it by removing the DOCKER_BUILDKIT=0"),
|
2022-02-03 13:11:05 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestBuilderBroken(t *testing.T) {
|
|
|
|
dir := fs.NewDir(t, t.Name(),
|
2022-09-30 13:13:22 -04:00
|
|
|
fs.WithFile(pluginFilename, `#!/bin/sh exit 1`, fs.WithMode(0o777)),
|
2022-02-03 13:11:05 -05:00
|
|
|
)
|
|
|
|
defer dir.Remove()
|
|
|
|
|
|
|
|
b := bytes.NewBuffer(nil)
|
|
|
|
|
2022-12-05 12:56:09 -05:00
|
|
|
dockerCli, err := command.NewDockerCli(
|
|
|
|
command.WithAPIClient(&fakeClient{}),
|
|
|
|
command.WithInputStream(discard),
|
|
|
|
command.WithCombinedStreams(b),
|
|
|
|
)
|
2022-02-03 04:37:55 -05:00
|
|
|
assert.NilError(t, err)
|
2022-11-03 17:30:27 -04:00
|
|
|
assert.NilError(t, dockerCli.Initialize(flags.NewClientOptions()))
|
2022-02-03 13:11:05 -05:00
|
|
|
dockerCli.ConfigFile().CLIPluginsExtraDirs = []string{dir.Path()}
|
2022-02-03 04:37:55 -05:00
|
|
|
|
|
|
|
tcmd := newDockerCommand(dockerCli)
|
|
|
|
tcmd.SetArgs([]string{"build", "."})
|
|
|
|
|
|
|
|
cmd, args, err := tcmd.HandleGlobalFlags()
|
|
|
|
assert.NilError(t, err)
|
|
|
|
|
2022-11-03 17:30:27 -04:00
|
|
|
var envs []string
|
|
|
|
args, os.Args, envs, err = processBuilder(dockerCli, cmd, args, os.Args)
|
2022-02-03 04:37:55 -05:00
|
|
|
assert.NilError(t, err)
|
|
|
|
assert.DeepEqual(t, []string{"build", "."}, args)
|
2022-11-03 17:30:27 -04:00
|
|
|
assert.Check(t, len(envs) == 0)
|
2022-02-03 13:11:05 -05:00
|
|
|
|
|
|
|
output.Assert(t, b.String(), map[int]func(string) error{
|
|
|
|
0: output.Prefix("failed to fetch metadata:"),
|
|
|
|
2: output.Suffix("DEPRECATED: The legacy builder is deprecated and will be removed in a future release."),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestBuilderBrokenEnforced(t *testing.T) {
|
2022-09-22 10:31:28 -04:00
|
|
|
t.Setenv("DOCKER_BUILDKIT", "1")
|
2022-02-03 13:11:05 -05:00
|
|
|
|
|
|
|
dir := fs.NewDir(t, t.Name(),
|
2022-09-30 13:13:22 -04:00
|
|
|
fs.WithFile(pluginFilename, `#!/bin/sh exit 1`, fs.WithMode(0o777)),
|
2022-02-03 13:11:05 -05:00
|
|
|
)
|
|
|
|
defer dir.Remove()
|
|
|
|
|
|
|
|
b := bytes.NewBuffer(nil)
|
|
|
|
|
2022-12-05 12:56:09 -05:00
|
|
|
dockerCli, err := command.NewDockerCli(
|
|
|
|
command.WithAPIClient(&fakeClient{}),
|
|
|
|
command.WithInputStream(discard),
|
|
|
|
command.WithCombinedStreams(b),
|
|
|
|
)
|
2022-02-03 13:11:05 -05:00
|
|
|
assert.NilError(t, err)
|
2022-11-03 17:30:27 -04:00
|
|
|
assert.NilError(t, dockerCli.Initialize(flags.NewClientOptions()))
|
2022-02-03 13:11:05 -05:00
|
|
|
dockerCli.ConfigFile().CLIPluginsExtraDirs = []string{dir.Path()}
|
|
|
|
|
|
|
|
tcmd := newDockerCommand(dockerCli)
|
|
|
|
tcmd.SetArgs([]string{"build", "."})
|
|
|
|
|
|
|
|
cmd, args, err := tcmd.HandleGlobalFlags()
|
|
|
|
assert.NilError(t, err)
|
|
|
|
|
2022-11-03 17:30:27 -04:00
|
|
|
var envs []string
|
|
|
|
args, os.Args, envs, err = processBuilder(dockerCli, cmd, args, os.Args)
|
2022-02-03 13:11:05 -05:00
|
|
|
assert.DeepEqual(t, []string{"build", "."}, args)
|
2022-11-03 17:30:27 -04:00
|
|
|
assert.Check(t, len(envs) == 0)
|
2022-02-03 13:11:05 -05:00
|
|
|
|
|
|
|
output.Assert(t, err.Error(), map[int]func(string) error{
|
|
|
|
0: output.Prefix("failed to fetch metadata:"),
|
|
|
|
2: output.Suffix("ERROR: BuildKit is enabled but the buildx component is missing or broken."),
|
|
|
|
})
|
2022-02-03 04:37:55 -05:00
|
|
|
}
|
2022-11-03 17:30:27 -04:00
|
|
|
|
|
|
|
func TestHasBuilderName(t *testing.T) {
|
|
|
|
cases := []struct {
|
|
|
|
name string
|
|
|
|
args []string
|
|
|
|
envs []string
|
|
|
|
expected bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "no args",
|
|
|
|
args: []string{"docker", "build", "."},
|
|
|
|
envs: []string{"FOO=bar"},
|
|
|
|
expected: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "env var",
|
|
|
|
args: []string{"docker", "build", "."},
|
|
|
|
envs: []string{"BUILDX_BUILDER=foo"},
|
|
|
|
expected: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "empty env var",
|
|
|
|
args: []string{"docker", "build", "."},
|
|
|
|
envs: []string{"BUILDX_BUILDER="},
|
|
|
|
expected: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "flag",
|
|
|
|
args: []string{"docker", "build", "--builder", "foo", "."},
|
|
|
|
envs: []string{"FOO=bar"},
|
|
|
|
expected: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "both",
|
|
|
|
args: []string{"docker", "build", "--builder", "foo", "."},
|
|
|
|
envs: []string{"BUILDX_BUILDER=foo"},
|
|
|
|
expected: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range cases {
|
|
|
|
tt := tt
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
assert.Equal(t, tt.expected, hasBuilderName(tt.args, tt.envs))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|