76d8bfdff4
This field was added in f0e5b3d7d8
to
account for older versions of the engine (Docker EE LTS versions), which
did not yet provide the OSType field in Docker info, and had to be manually
set using the TEST_OSTYPE env-var.
This patch removes the field in favor of the equivalent in DaemonInfo. It's
more verbose, but also less ambiguous what information we're using (i.e.,
the platform the daemon is running on, not the local platform).
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
359 lines
12 KiB
Go
359 lines
12 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/docker/docker/integration-cli/cli"
|
|
"github.com/docker/docker/integration-cli/cli/build"
|
|
"github.com/docker/docker/pkg/stringid"
|
|
"github.com/docker/docker/testutil/fakecontext"
|
|
"github.com/docker/go-connections/nat"
|
|
"gotest.tools/v3/assert"
|
|
is "gotest.tools/v3/assert/cmp"
|
|
)
|
|
|
|
type DockerCLICreateSuite struct {
|
|
ds *DockerSuite
|
|
}
|
|
|
|
func (s *DockerCLICreateSuite) TearDownTest(c *testing.T) {
|
|
s.ds.TearDownTest(c)
|
|
}
|
|
|
|
func (s *DockerCLICreateSuite) OnTimeout(c *testing.T) {
|
|
s.ds.OnTimeout(c)
|
|
}
|
|
|
|
// Make sure we can create a simple container with some args
|
|
func (s *DockerCLICreateSuite) TestCreateArgs(c *testing.T) {
|
|
// Intentionally clear entrypoint, as the Windows busybox image needs an entrypoint, which breaks this test
|
|
out, _ := dockerCmd(c, "create", "--entrypoint=", "busybox", "command", "arg1", "arg2", "arg with space", "-c", "flags")
|
|
|
|
cleanedContainerID := strings.TrimSpace(out)
|
|
|
|
out, _ = dockerCmd(c, "inspect", cleanedContainerID)
|
|
|
|
var containers []struct {
|
|
Path string
|
|
Args []string
|
|
}
|
|
|
|
err := json.Unmarshal([]byte(out), &containers)
|
|
assert.Assert(c, err == nil, "Error inspecting the container: %s", err)
|
|
assert.Equal(c, len(containers), 1)
|
|
|
|
cont := containers[0]
|
|
assert.Equal(c, cont.Path, "command", fmt.Sprintf("Unexpected container path. Expected command, received: %s", cont.Path))
|
|
|
|
b := false
|
|
expected := []string{"arg1", "arg2", "arg with space", "-c", "flags"}
|
|
for i, arg := range expected {
|
|
if arg != cont.Args[i] {
|
|
b = true
|
|
break
|
|
}
|
|
}
|
|
if len(cont.Args) != len(expected) || b {
|
|
c.Fatalf("Unexpected args. Expected %v, received: %v", expected, cont.Args)
|
|
}
|
|
}
|
|
|
|
// Make sure we can set hostconfig options too
|
|
func (s *DockerCLICreateSuite) TestCreateHostConfig(c *testing.T) {
|
|
out, _ := dockerCmd(c, "create", "-P", "busybox", "echo")
|
|
|
|
cleanedContainerID := strings.TrimSpace(out)
|
|
|
|
out, _ = dockerCmd(c, "inspect", cleanedContainerID)
|
|
|
|
var containers []struct {
|
|
HostConfig *struct {
|
|
PublishAllPorts bool
|
|
}
|
|
}
|
|
|
|
err := json.Unmarshal([]byte(out), &containers)
|
|
assert.Assert(c, err == nil, "Error inspecting the container: %s", err)
|
|
assert.Equal(c, len(containers), 1)
|
|
|
|
cont := containers[0]
|
|
assert.Assert(c, cont.HostConfig != nil, "Expected HostConfig, got none")
|
|
assert.Assert(c, cont.HostConfig.PublishAllPorts, "Expected PublishAllPorts, got false")
|
|
}
|
|
|
|
func (s *DockerCLICreateSuite) TestCreateWithPortRange(c *testing.T) {
|
|
out, _ := dockerCmd(c, "create", "-p", "3300-3303:3300-3303/tcp", "busybox", "echo")
|
|
|
|
cleanedContainerID := strings.TrimSpace(out)
|
|
|
|
out, _ = dockerCmd(c, "inspect", cleanedContainerID)
|
|
|
|
var containers []struct {
|
|
HostConfig *struct {
|
|
PortBindings map[nat.Port][]nat.PortBinding
|
|
}
|
|
}
|
|
err := json.Unmarshal([]byte(out), &containers)
|
|
assert.Assert(c, err == nil, "Error inspecting the container: %s", err)
|
|
assert.Equal(c, len(containers), 1)
|
|
|
|
cont := containers[0]
|
|
|
|
assert.Assert(c, cont.HostConfig != nil, "Expected HostConfig, got none")
|
|
assert.Equal(c, len(cont.HostConfig.PortBindings), 4, fmt.Sprintf("Expected 4 ports bindings, got %d", len(cont.HostConfig.PortBindings)))
|
|
|
|
for k, v := range cont.HostConfig.PortBindings {
|
|
assert.Equal(c, len(v), 1, fmt.Sprintf("Expected 1 ports binding, for the port %s but found %s", k, v))
|
|
assert.Equal(c, k.Port(), v[0].HostPort, fmt.Sprintf("Expected host port %s to match published port %s", k.Port(), v[0].HostPort))
|
|
}
|
|
}
|
|
|
|
func (s *DockerCLICreateSuite) TestCreateWithLargePortRange(c *testing.T) {
|
|
out, _ := dockerCmd(c, "create", "-p", "1-65535:1-65535/tcp", "busybox", "echo")
|
|
|
|
cleanedContainerID := strings.TrimSpace(out)
|
|
|
|
out, _ = dockerCmd(c, "inspect", cleanedContainerID)
|
|
|
|
var containers []struct {
|
|
HostConfig *struct {
|
|
PortBindings map[nat.Port][]nat.PortBinding
|
|
}
|
|
}
|
|
|
|
err := json.Unmarshal([]byte(out), &containers)
|
|
assert.Assert(c, err == nil, "Error inspecting the container: %s", err)
|
|
assert.Equal(c, len(containers), 1)
|
|
|
|
cont := containers[0]
|
|
assert.Assert(c, cont.HostConfig != nil, "Expected HostConfig, got none")
|
|
assert.Equal(c, len(cont.HostConfig.PortBindings), 65535)
|
|
|
|
for k, v := range cont.HostConfig.PortBindings {
|
|
assert.Equal(c, len(v), 1)
|
|
assert.Equal(c, k.Port(), v[0].HostPort, fmt.Sprintf("Expected host port %s to match published port %s", k.Port(), v[0].HostPort))
|
|
}
|
|
}
|
|
|
|
// "test123" should be printed by docker create + start
|
|
func (s *DockerCLICreateSuite) TestCreateEchoStdout(c *testing.T) {
|
|
out, _ := dockerCmd(c, "create", "busybox", "echo", "test123")
|
|
|
|
cleanedContainerID := strings.TrimSpace(out)
|
|
|
|
out, _ = dockerCmd(c, "start", "-ai", cleanedContainerID)
|
|
assert.Equal(c, out, "test123\n", "container should've printed 'test123', got %q", out)
|
|
}
|
|
|
|
func (s *DockerCLICreateSuite) TestCreateVolumesCreated(c *testing.T) {
|
|
testRequires(c, testEnv.IsLocalDaemon)
|
|
prefix, slash := getPrefixAndSlashFromDaemonPlatform()
|
|
|
|
name := "test_create_volume"
|
|
dockerCmd(c, "create", "--name", name, "-v", prefix+slash+"foo", "busybox")
|
|
|
|
dir, err := inspectMountSourceField(name, prefix+slash+"foo")
|
|
assert.Assert(c, err == nil, "Error getting volume host path: %q", err)
|
|
|
|
if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) {
|
|
c.Fatalf("Volume was not created")
|
|
}
|
|
if err != nil {
|
|
c.Fatalf("Error statting volume host path: %q", err)
|
|
}
|
|
}
|
|
|
|
func (s *DockerCLICreateSuite) TestCreateLabels(c *testing.T) {
|
|
name := "test_create_labels"
|
|
expected := map[string]string{"k1": "v1", "k2": "v2"}
|
|
dockerCmd(c, "create", "--name", name, "-l", "k1=v1", "--label", "k2=v2", "busybox")
|
|
|
|
actual := make(map[string]string)
|
|
inspectFieldAndUnmarshall(c, name, "Config.Labels", &actual)
|
|
|
|
if !reflect.DeepEqual(expected, actual) {
|
|
c.Fatalf("Expected %s got %s", expected, actual)
|
|
}
|
|
}
|
|
|
|
func (s *DockerCLICreateSuite) TestCreateLabelFromImage(c *testing.T) {
|
|
imageName := "testcreatebuildlabel"
|
|
buildImageSuccessfully(c, imageName, build.WithDockerfile(`FROM busybox
|
|
LABEL k1=v1 k2=v2`))
|
|
|
|
name := "test_create_labels_from_image"
|
|
expected := map[string]string{"k2": "x", "k3": "v3", "k1": "v1"}
|
|
dockerCmd(c, "create", "--name", name, "-l", "k2=x", "--label", "k3=v3", imageName)
|
|
|
|
actual := make(map[string]string)
|
|
inspectFieldAndUnmarshall(c, name, "Config.Labels", &actual)
|
|
|
|
if !reflect.DeepEqual(expected, actual) {
|
|
c.Fatalf("Expected %s got %s", expected, actual)
|
|
}
|
|
}
|
|
|
|
func (s *DockerCLICreateSuite) TestCreateHostnameWithNumber(c *testing.T) {
|
|
image := "busybox"
|
|
// Busybox on Windows does not implement hostname command
|
|
if testEnv.DaemonInfo.OSType == "windows" {
|
|
image = testEnv.PlatformDefaults.BaseImage
|
|
}
|
|
out, _ := dockerCmd(c, "run", "-h", "web.0", image, "hostname")
|
|
assert.Equal(c, strings.TrimSpace(out), "web.0", "hostname not set, expected `web.0`, got: %s", out)
|
|
}
|
|
|
|
func (s *DockerCLICreateSuite) TestCreateRM(c *testing.T) {
|
|
// Test to make sure we can 'rm' a new container that is in
|
|
// "Created" state, and has ever been run. Test "rm -f" too.
|
|
|
|
// create a container
|
|
out, _ := dockerCmd(c, "create", "busybox")
|
|
cID := strings.TrimSpace(out)
|
|
|
|
dockerCmd(c, "rm", cID)
|
|
|
|
// Now do it again so we can "rm -f" this time
|
|
out, _ = dockerCmd(c, "create", "busybox")
|
|
|
|
cID = strings.TrimSpace(out)
|
|
dockerCmd(c, "rm", "-f", cID)
|
|
}
|
|
|
|
func (s *DockerCLICreateSuite) TestCreateModeIpcContainer(c *testing.T) {
|
|
// Uses Linux specific functionality (--ipc)
|
|
testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon)
|
|
|
|
out, _ := dockerCmd(c, "create", "busybox")
|
|
id := strings.TrimSpace(out)
|
|
|
|
dockerCmd(c, "create", fmt.Sprintf("--ipc=container:%s", id), "busybox")
|
|
}
|
|
|
|
func (s *DockerCLICreateSuite) TestCreateByImageID(c *testing.T) {
|
|
imageName := "testcreatebyimageid"
|
|
buildImageSuccessfully(c, imageName, build.WithDockerfile(`FROM busybox
|
|
MAINTAINER dockerio`))
|
|
imageID := getIDByName(c, imageName)
|
|
truncatedImageID := stringid.TruncateID(imageID)
|
|
|
|
dockerCmd(c, "create", imageID)
|
|
dockerCmd(c, "create", truncatedImageID)
|
|
|
|
// Ensure this fails
|
|
out, exit, _ := dockerCmdWithError("create", fmt.Sprintf("%s:%s", imageName, imageID))
|
|
if exit == 0 {
|
|
c.Fatalf("expected non-zero exit code; received %d", exit)
|
|
}
|
|
|
|
if expected := "invalid reference format"; !strings.Contains(out, expected) {
|
|
c.Fatalf(`Expected %q in output; got: %s`, expected, out)
|
|
}
|
|
|
|
if i := strings.IndexRune(imageID, ':'); i >= 0 {
|
|
imageID = imageID[i+1:]
|
|
}
|
|
out, exit, _ = dockerCmdWithError("create", fmt.Sprintf("%s:%s", "wrongimage", imageID))
|
|
if exit == 0 {
|
|
c.Fatalf("expected non-zero exit code; received %d", exit)
|
|
}
|
|
|
|
if expected := "Unable to find image"; !strings.Contains(out, expected) {
|
|
c.Fatalf(`Expected %q in output; got: %s`, expected, out)
|
|
}
|
|
}
|
|
|
|
func (s *DockerCLICreateSuite) TestCreateStopSignal(c *testing.T) {
|
|
name := "test_create_stop_signal"
|
|
dockerCmd(c, "create", "--name", name, "--stop-signal", "9", "busybox")
|
|
|
|
res := inspectFieldJSON(c, name, "Config.StopSignal")
|
|
assert.Assert(c, strings.Contains(res, "9"))
|
|
}
|
|
|
|
func (s *DockerCLICreateSuite) TestCreateWithWorkdir(c *testing.T) {
|
|
name := "foo"
|
|
|
|
prefix, slash := getPrefixAndSlashFromDaemonPlatform()
|
|
dir := prefix + slash + "home" + slash + "foo" + slash + "bar"
|
|
|
|
dockerCmd(c, "create", "--name", name, "-w", dir, "busybox")
|
|
// Windows does not create the workdir until the container is started
|
|
if testEnv.DaemonInfo.OSType == "windows" {
|
|
dockerCmd(c, "start", name)
|
|
if testEnv.DaemonInfo.Isolation.IsHyperV() {
|
|
// Hyper-V isolated containers do not allow file-operations on a
|
|
// running container. This test currently uses `docker cp` to verify
|
|
// that the WORKDIR was automatically created, which cannot be done
|
|
// while the container is running.
|
|
dockerCmd(c, "stop", name)
|
|
}
|
|
}
|
|
// TODO: rewrite this test to not use `docker cp` for verifying that the WORKDIR was created
|
|
dockerCmd(c, "cp", fmt.Sprintf("%s:%s", name, dir), prefix+slash+"tmp")
|
|
}
|
|
|
|
func (s *DockerCLICreateSuite) TestCreateWithInvalidLogOpts(c *testing.T) {
|
|
name := "test-invalidate-log-opts"
|
|
out, _, err := dockerCmdWithError("create", "--name", name, "--log-opt", "invalid=true", "busybox")
|
|
assert.ErrorContains(c, err, "")
|
|
assert.Assert(c, strings.Contains(out, "unknown log opt"))
|
|
assert.Assert(c, is.Contains(out, "unknown log opt"))
|
|
|
|
out, _ = dockerCmd(c, "ps", "-a")
|
|
assert.Assert(c, !strings.Contains(out, name))
|
|
}
|
|
|
|
// #20972
|
|
func (s *DockerCLICreateSuite) TestCreate64ByteHexID(c *testing.T) {
|
|
out := inspectField(c, "busybox", "Id")
|
|
imageID := strings.TrimPrefix(strings.TrimSpace(out), "sha256:")
|
|
|
|
dockerCmd(c, "create", imageID)
|
|
}
|
|
|
|
// Test case for #23498
|
|
func (s *DockerCLICreateSuite) TestCreateUnsetEntrypoint(c *testing.T) {
|
|
name := "test-entrypoint"
|
|
dockerfile := `FROM busybox
|
|
ADD entrypoint.sh /entrypoint.sh
|
|
RUN chmod 755 /entrypoint.sh
|
|
ENTRYPOINT ["/entrypoint.sh"]
|
|
CMD echo foobar`
|
|
|
|
ctx := fakecontext.New(c, "",
|
|
fakecontext.WithDockerfile(dockerfile),
|
|
fakecontext.WithFiles(map[string]string{
|
|
"entrypoint.sh": `#!/bin/sh
|
|
echo "I am an entrypoint"
|
|
exec "$@"`,
|
|
}))
|
|
defer ctx.Close()
|
|
|
|
cli.BuildCmd(c, name, build.WithExternalBuildContext(ctx))
|
|
|
|
out := cli.DockerCmd(c, "create", "--entrypoint=", name, "echo", "foo").Combined()
|
|
id := strings.TrimSpace(out)
|
|
assert.Assert(c, id != "")
|
|
out = cli.DockerCmd(c, "start", "-a", id).Combined()
|
|
assert.Equal(c, strings.TrimSpace(out), "foo")
|
|
}
|
|
|
|
// #22471
|
|
func (s *DockerCLICreateSuite) TestCreateStopTimeout(c *testing.T) {
|
|
name1 := "test_create_stop_timeout_1"
|
|
dockerCmd(c, "create", "--name", name1, "--stop-timeout", "15", "busybox")
|
|
|
|
res := inspectFieldJSON(c, name1, "Config.StopTimeout")
|
|
assert.Assert(c, strings.Contains(res, "15"))
|
|
name2 := "test_create_stop_timeout_2"
|
|
dockerCmd(c, "create", "--name", name2, "busybox")
|
|
|
|
res = inspectFieldJSON(c, name2, "Config.StopTimeout")
|
|
assert.Assert(c, strings.Contains(res, "null"))
|
|
}
|