Files
docker-cli/cmd/docker/builder_test.go
Sebastiaan van Stijn 3499669e18 cli/flags: merge CommonOptions into ClientOptions
CommonOptions was inherited from when the cli and daemon were in the same
repository, and some options would be shared between them. That's no longer
the case, and some options are even "incorrect" (for example, while the
daemon can be configured to run on multiple hosts, the CLI can only connect
with a single host / connection). This patch does not (yet) address that,
but merges the CommonOptions into the ClientOptions.

An alias is created for the old type, although it doesn't appear there's
any external consumers using the CommonOptions type (or its constructor).

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-11-22 12:32:18 +01:00

250 lines
6.7 KiB
Go

package main
import (
"bytes"
"os"
"path/filepath"
"testing"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/context/store"
"github.com/docker/cli/cli/flags"
"github.com/docker/cli/internal/test/output"
"gotest.tools/v3/assert"
"gotest.tools/v3/fs"
)
var pluginFilename = "docker-buildx"
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,
},
}
dir := fs.NewDir(t, t.Name(),
fs.WithFile(pluginFilename, `#!/bin/sh
echo '{"SchemaVersion":"0.1.0","Vendor":"Docker Inc.","Version":"v0.6.3","ShortDescription":"Build with BuildKit"}'`, fs.WithMode(0o777)),
)
defer dir.Remove()
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
dockerCli, err := command.NewDockerCli(command.WithInputStream(discard), command.WithCombinedStreams(&b))
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()
opts.Context = tt.context
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)
}
})
}
}
func TestBuildkitDisabled(t *testing.T) {
t.Setenv("DOCKER_BUILDKIT", "0")
dir := fs.NewDir(t, t.Name(),
fs.WithFile(pluginFilename, `#!/bin/sh exit 1`, fs.WithMode(0o777)),
)
defer dir.Remove()
b := bytes.NewBuffer(nil)
dockerCli, err := command.NewDockerCli(command.WithInputStream(discard), command.WithCombinedStreams(b))
assert.NilError(t, err)
assert.NilError(t, dockerCli.Initialize(flags.NewClientOptions()))
dockerCli.ConfigFile().CLIPluginsExtraDirs = []string{dir.Path()}
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{"build", "."}, args)
assert.Check(t, len(envs) == 0)
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."),
})
}
func TestBuilderBroken(t *testing.T) {
dir := fs.NewDir(t, t.Name(),
fs.WithFile(pluginFilename, `#!/bin/sh exit 1`, fs.WithMode(0o777)),
)
defer dir.Remove()
b := bytes.NewBuffer(nil)
dockerCli, err := command.NewDockerCli(command.WithInputStream(discard), command.WithCombinedStreams(b))
assert.NilError(t, err)
assert.NilError(t, dockerCli.Initialize(flags.NewClientOptions()))
dockerCli.ConfigFile().CLIPluginsExtraDirs = []string{dir.Path()}
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{"build", "."}, args)
assert.Check(t, len(envs) == 0)
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) {
t.Setenv("DOCKER_BUILDKIT", "1")
dir := fs.NewDir(t, t.Name(),
fs.WithFile(pluginFilename, `#!/bin/sh exit 1`, fs.WithMode(0o777)),
)
defer dir.Remove()
b := bytes.NewBuffer(nil)
dockerCli, err := command.NewDockerCli(command.WithInputStream(discard), command.WithCombinedStreams(b))
assert.NilError(t, err)
assert.NilError(t, dockerCli.Initialize(flags.NewClientOptions()))
dockerCli.ConfigFile().CLIPluginsExtraDirs = []string{dir.Path()}
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.DeepEqual(t, []string{"build", "."}, args)
assert.Check(t, len(envs) == 0)
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."),
})
}
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))
})
}
}