github.com/tonistiigi/docker@v0.10.1-0.20240229224939-974013b0dc6a/integration-cli/docker_cli_start_test.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/docker/docker/integration-cli/cli"
    11  	"gotest.tools/v3/assert"
    12  	"gotest.tools/v3/icmd"
    13  )
    14  
    15  type DockerCLIStartSuite struct {
    16  	ds *DockerSuite
    17  }
    18  
    19  func (s *DockerCLIStartSuite) TearDownTest(ctx context.Context, c *testing.T) {
    20  	s.ds.TearDownTest(ctx, c)
    21  }
    22  
    23  func (s *DockerCLIStartSuite) OnTimeout(c *testing.T) {
    24  	s.ds.OnTimeout(c)
    25  }
    26  
    27  // Regression test for https://github.com/docker/docker/issues/7843
    28  func (s *DockerCLIStartSuite) TestStartAttachReturnsOnError(c *testing.T) {
    29  	// Windows does not support link
    30  	testRequires(c, DaemonIsLinux)
    31  	cli.DockerCmd(c, "run", "--name", "test", "busybox")
    32  
    33  	// Expect this to fail because the above container is stopped, this is what we want
    34  	out, _, err := dockerCmdWithError("run", "--name", "test2", "--link", "test:test", "busybox")
    35  	// err shouldn't be nil because container test2 try to link to stopped container
    36  	assert.Assert(c, err != nil, "out: %s", out)
    37  
    38  	ch := make(chan error, 1)
    39  	go func() {
    40  		// Attempt to start attached to the container that won't start
    41  		// This should return an error immediately since the container can't be started
    42  		if out, _, err := dockerCmdWithError("start", "-a", "test2"); err == nil {
    43  			ch <- fmt.Errorf("Expected error but got none:\n%s", out)
    44  		}
    45  		close(ch)
    46  	}()
    47  
    48  	select {
    49  	case err := <-ch:
    50  		assert.NilError(c, err)
    51  	case <-time.After(5 * time.Second):
    52  		c.Fatalf("Attach did not exit properly")
    53  	}
    54  }
    55  
    56  // gh#8555: Exit code should be passed through when using start -a
    57  func (s *DockerCLIStartSuite) TestStartAttachCorrectExitCode(c *testing.T) {
    58  	testRequires(c, DaemonIsLinux)
    59  	out := cli.DockerCmd(c, "run", "-d", "busybox", "sh", "-c", "sleep 2; exit 1").Stdout()
    60  	out = strings.TrimSpace(out)
    61  
    62  	// make sure the container has exited before trying the "start -a"
    63  	cli.DockerCmd(c, "wait", out)
    64  
    65  	cli.Docker(cli.Args("start", "-a", out)).Assert(c, icmd.Expected{
    66  		ExitCode: 1,
    67  	})
    68  }
    69  
    70  func (s *DockerCLIStartSuite) TestStartAttachSilent(c *testing.T) {
    71  	name := "teststartattachcorrectexitcode"
    72  	cli.DockerCmd(c, "run", "--name", name, "busybox", "echo", "test")
    73  
    74  	// make sure the container has exited before trying the "start -a"
    75  	cli.DockerCmd(c, "wait", name)
    76  
    77  	startOut := cli.DockerCmd(c, "start", "-a", name).Combined()
    78  	// start -a produced unexpected output
    79  	assert.Equal(c, startOut, "test\n")
    80  }
    81  
    82  func (s *DockerCLIStartSuite) TestStartRecordError(c *testing.T) {
    83  	// TODO Windows CI: Requires further porting work. Should be possible.
    84  	testRequires(c, DaemonIsLinux)
    85  	// when container runs successfully, we should not have state.Error
    86  	cli.DockerCmd(c, "run", "-d", "-p", "9999:9999", "--name", "test", "busybox", "top")
    87  	stateErr := inspectField(c, "test", "State.Error")
    88  	// Expected to not have state error
    89  	assert.Equal(c, stateErr, "")
    90  
    91  	// Expect this to fail and records error because of ports conflict
    92  	out, _, err := dockerCmdWithError("run", "-d", "--name", "test2", "-p", "9999:9999", "busybox", "top")
    93  	// err shouldn't be nil because docker run will fail
    94  	assert.Assert(c, err != nil, "out: %s", out)
    95  
    96  	stateErr = inspectField(c, "test2", "State.Error")
    97  	assert.Assert(c, strings.Contains(stateErr, "port is already allocated"))
    98  	// Expect the conflict to be resolved when we stop the initial container
    99  	cli.DockerCmd(c, "stop", "test")
   100  	cli.DockerCmd(c, "start", "test2")
   101  	stateErr = inspectField(c, "test2", "State.Error")
   102  	// Expected to not have state error but got one
   103  	assert.Equal(c, stateErr, "")
   104  }
   105  
   106  func (s *DockerCLIStartSuite) TestStartPausedContainer(c *testing.T) {
   107  	// Windows does not support pausing containers
   108  	testRequires(c, IsPausable)
   109  
   110  	runSleepingContainer(c, "-d", "--name", "testing")
   111  
   112  	cli.DockerCmd(c, "pause", "testing")
   113  
   114  	out, _, err := dockerCmdWithError("start", "testing")
   115  	// an error should have been shown that you cannot start paused container
   116  	assert.Assert(c, err != nil, "out: %s", out)
   117  	// an error should have been shown that you cannot start paused container
   118  	assert.Assert(c, strings.Contains(strings.ToLower(out), "cannot start a paused container, try unpause instead"))
   119  }
   120  
   121  func (s *DockerCLIStartSuite) TestStartMultipleContainers(c *testing.T) {
   122  	// Windows does not support --link
   123  	testRequires(c, DaemonIsLinux)
   124  	// run a container named 'parent' and create two container link to `parent`
   125  	cli.DockerCmd(c, "run", "-d", "--name", "parent", "busybox", "top")
   126  
   127  	for _, container := range []string{"child_first", "child_second"} {
   128  		cli.DockerCmd(c, "create", "--name", container, "--link", "parent:parent", "busybox", "top")
   129  	}
   130  
   131  	// stop 'parent' container
   132  	cli.DockerCmd(c, "stop", "parent")
   133  
   134  	out := inspectField(c, "parent", "State.Running")
   135  	// Container should be stopped
   136  	assert.Equal(c, out, "false")
   137  
   138  	// start all the three containers, container `child_first` start first which should be failed
   139  	// container 'parent' start second and then start container 'child_second'
   140  	const expOut = "Cannot link to a non running container"
   141  	const expErr = "failed to start containers: [child_first]"
   142  	out, _, err := dockerCmdWithError("start", "child_first", "parent", "child_second")
   143  	// err shouldn't be nil because start will fail
   144  	assert.Assert(c, err != nil, "out: %s", out)
   145  	// output does not correspond to what was expected
   146  	if !(strings.Contains(out, expOut) || strings.Contains(err.Error(), expErr)) {
   147  		c.Fatalf("Expected out: %v with err: %v  but got out: %v with err: %v", expOut, expErr, out, err)
   148  	}
   149  
   150  	for container, expected := range map[string]string{"parent": "true", "child_first": "false", "child_second": "true"} {
   151  		out := inspectField(c, container, "State.Running")
   152  		// Container running state wrong
   153  		assert.Equal(c, out, expected)
   154  	}
   155  }
   156  
   157  func (s *DockerCLIStartSuite) TestStartAttachMultipleContainers(c *testing.T) {
   158  	// run  multiple containers to test
   159  	for _, container := range []string{"test1", "test2", "test3"} {
   160  		runSleepingContainer(c, "--name", container)
   161  	}
   162  
   163  	// stop all the containers
   164  	for _, container := range []string{"test1", "test2", "test3"} {
   165  		cli.DockerCmd(c, "stop", container)
   166  	}
   167  
   168  	// test start and attach multiple containers at once, expected error
   169  	for _, option := range []string{"-a", "-i", "-ai"} {
   170  		out, _, err := dockerCmdWithError("start", option, "test1", "test2", "test3")
   171  		// err shouldn't be nil because start will fail
   172  		assert.Assert(c, err != nil, "out: %s", out)
   173  		// output does not correspond to what was expected
   174  		assert.Assert(c, strings.Contains(out, "you cannot start and attach multiple containers at once"))
   175  	}
   176  
   177  	// confirm the state of all the containers be stopped
   178  	for container, expected := range map[string]string{"test1": "false", "test2": "false", "test3": "false"} {
   179  		out := inspectField(c, container, "State.Running")
   180  		// Container running state wrong
   181  		assert.Equal(c, out, expected)
   182  	}
   183  }
   184  
   185  // Test case for #23716
   186  func (s *DockerCLIStartSuite) TestStartAttachWithRename(c *testing.T) {
   187  	testRequires(c, DaemonIsLinux)
   188  	cli.DockerCmd(c, "create", "-t", "--name", "before", "busybox")
   189  	go func() {
   190  		cli.WaitRun(c, "before")
   191  		cli.DockerCmd(c, "rename", "before", "after")
   192  		cli.DockerCmd(c, "stop", "--time=2", "after")
   193  	}()
   194  	// FIXME(vdemeester) the intent is not clear and potentially racey
   195  	result := cli.Docker(cli.Args("start", "-a", "before")).Assert(c, icmd.Expected{
   196  		ExitCode: 137,
   197  	})
   198  	assert.Assert(c, !strings.Contains(result.Stderr(), "No such container"))
   199  }
   200  
   201  func (s *DockerCLIStartSuite) TestStartReturnCorrectExitCode(c *testing.T) {
   202  	cli.DockerCmd(c, "create", "--restart=on-failure:2", "--name", "withRestart", "busybox", "sh", "-c", "exit 11")
   203  	cli.DockerCmd(c, "create", "--rm", "--name", "withRm", "busybox", "sh", "-c", "exit 12")
   204  	cli.Docker(cli.Args("start", "-a", "withRestart")).Assert(c, icmd.Expected{ExitCode: 11})
   205  	cli.Docker(cli.Args("start", "-a", "withRm")).Assert(c, icmd.Expected{ExitCode: 12})
   206  }