diff --git a/cmd/nerdctl/compose/compose_run_linux_test.go b/cmd/nerdctl/compose/compose_run_linux_test.go index c68d9fa258d..6eaae416bbc 100644 --- a/cmd/nerdctl/compose/compose_run_linux_test.go +++ b/cmd/nerdctl/compose/compose_run_linux_test.go @@ -25,9 +25,9 @@ import ( "gotest.tools/v3/assert" - "github.com/containerd/log" "github.com/containerd/nerdctl/mod/tigron/expect" "github.com/containerd/nerdctl/mod/tigron/test" + "github.com/containerd/nerdctl/mod/tigron/tig" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" @@ -54,6 +54,7 @@ services: Description: "pty run", Setup: func(data test.Data, helpers test.Helpers) { data.Temp().Save(dockerComposeYAML, "compose.yaml") + data.Labels().Set("composeYAML", data.Temp().Path("compose.yaml")) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { cmd := helpers.Command( @@ -71,13 +72,16 @@ services: Expected: test.Expects(0, nil, expect.Contains(expectedOutput)), Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", "-v", data.Identifier()) - helpers.Anyhow("compose", "-f", data.Temp().Path("compose.yaml"), "down", "-v") + if yaml := data.Labels().Get("composeYAML"); yaml != "" { + helpers.Anyhow("compose", "-f", yaml, "down", "-v") + } }, }, { Description: "pty run with --rm", Setup: func(data test.Data, helpers test.Helpers) { data.Temp().Save(dockerComposeYAML, "compose.yaml") + data.Labels().Set("composeYAML", data.Temp().Path("compose.yaml")) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { cmd := helpers.Command( @@ -104,7 +108,9 @@ services: }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", "-v", data.Identifier()) - helpers.Anyhow("compose", "-f", data.Temp().Path("compose.yaml"), "down", "-v") + if yaml := data.Labels().Get("composeYAML"); yaml != "" { + helpers.Anyhow("compose", "-f", yaml, "down", "-v") + } }, }, } @@ -233,12 +239,7 @@ services: } func TestComposeRunWithEnv(t *testing.T) { - base := testutil.NewBase(t) - // specify the name of container in order to remove - // TODO: when `compose rm` is implemented, replace it. - containerName := testutil.Identifier(t) - - dockerComposeYAML := fmt.Sprintf(` + var dockerComposeYAML = fmt.Sprintf(` services: alpine: image: %s @@ -248,28 +249,41 @@ services: - "echo $$FOO" `, testutil.CommonImage) - comp := testutil.NewComposeDir(t, dockerComposeYAML) - defer comp.CleanUp() - projectName := comp.ProjectName() - t.Logf("projectName=%q", projectName) - defer base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").Run() + testCase := nerdtest.Setup() - defer base.Cmd("rm", "-f", "-v", containerName).Run() - const partialOutput = "bar" - // unbuffer(1) emulates tty, which is required by `nerdctl run -t`. - // unbuffer(1) can be installed with `apt-get install expect`. - unbuffer := []string{"unbuffer"} - base.ComposeCmdWithHelper(unbuffer, "-f", comp.YAMLFullPath(), - "run", "-e", "FOO=bar", "--name", containerName, "alpine").AssertOutContains(partialOutput) + testCase.Setup = func(data test.Data, helpers test.Helpers) { + data.Temp().Save(dockerComposeYAML, "compose.yaml") + data.Labels().Set("composeYAML", data.Temp().Path("compose.yaml")) + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + if yaml := data.Labels().Get("composeYAML"); yaml != "" { + helpers.Anyhow("compose", "-f", yaml, "down", "-v") + } + } + + testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { + cmd := helpers.Command( + "compose", + "-f", + data.Temp().Path("compose.yaml"), + "run", + "-e", "FOO=bar", + "--name", + data.Identifier(), + "alpine", + ) + cmd.WithPseudoTTY() + return cmd + } + + testCase.Expected = test.Expects(expect.ExitCodeSuccess, nil, expect.Contains("bar")) + + testCase.Run(t) } func TestComposeRunWithUser(t *testing.T) { - base := testutil.NewBase(t) - // specify the name of container in order to remove - // TODO: when `compose rm` is implemented, replace it. - containerName := testutil.Identifier(t) - - dockerComposeYAML := fmt.Sprintf(` + var dockerComposeYAML = fmt.Sprintf(` services: alpine: image: %s @@ -278,26 +292,41 @@ services: - -u `, testutil.CommonImage) - comp := testutil.NewComposeDir(t, dockerComposeYAML) - defer comp.CleanUp() - projectName := comp.ProjectName() - t.Logf("projectName=%q", projectName) - defer base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").Run() + testCase := nerdtest.Setup() - defer base.Cmd("rm", "-f", "-v", containerName).Run() - const partialOutput = "5000" - // unbuffer(1) emulates tty, which is required by `nerdctl run -t`. - // unbuffer(1) can be installed with `apt-get install expect`. - unbuffer := []string{"unbuffer"} - base.ComposeCmdWithHelper(unbuffer, "-f", comp.YAMLFullPath(), - "run", "--user", "5000", "--name", containerName, "alpine").AssertOutContains(partialOutput) + testCase.Setup = func(data test.Data, helpers test.Helpers) { + data.Temp().Save(dockerComposeYAML, "compose.yaml") + data.Labels().Set("composeYAML", data.Temp().Path("compose.yaml")) + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + if yaml := data.Labels().Get("composeYAML"); yaml != "" { + helpers.Anyhow("compose", "-f", yaml, "down", "-v") + } + } + + testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { + cmd := helpers.Command( + "compose", + "-f", + data.Temp().Path("compose.yaml"), + "run", + "--user", "5000", + "--name", + data.Identifier(), + "alpine", + ) + cmd.WithPseudoTTY() + return cmd + } + + testCase.Expected = test.Expects(expect.ExitCodeSuccess, nil, expect.Contains("5000")) + + testCase.Run(t) } func TestComposeRunWithLabel(t *testing.T) { - base := testutil.NewBase(t) - containerName := testutil.Identifier(t) - - dockerComposeYAML := fmt.Sprintf(` + var dockerComposeYAML = fmt.Sprintf(` services: alpine: image: %s @@ -308,33 +337,52 @@ services: - "foo=bar" `, testutil.CommonImage) - comp := testutil.NewComposeDir(t, dockerComposeYAML) - defer comp.CleanUp() - projectName := comp.ProjectName() - t.Logf("projectName=%q", projectName) - defer base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").Run() + testCase := nerdtest.Setup() - defer base.Cmd("rm", "-f", "-v", containerName).Run() - // unbuffer(1) emulates tty, which is required by `nerdctl run -t`. - // unbuffer(1) can be installed with `apt-get install expect`. - unbuffer := []string{"unbuffer"} - base.ComposeCmdWithHelper(unbuffer, "-f", comp.YAMLFullPath(), - "run", "--label", "foo=rab", "--label", "x=y", "--name", containerName, "alpine").AssertOK() + testCase.Setup = func(data test.Data, helpers test.Helpers) { + data.Temp().Save(dockerComposeYAML, "compose.yaml") + data.Labels().Set("composeYAML", data.Temp().Path("compose.yaml")) + } - container := base.InspectContainer(containerName) - if container.Config == nil { - log.L.Errorf("test failed, cannot fetch container config") - t.Fail() + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + if yaml := data.Labels().Get("composeYAML"); yaml != "" { + helpers.Anyhow("compose", "-f", yaml, "down", "-v") + } } - assert.Equal(t, container.Config.Labels["foo"], "rab") - assert.Equal(t, container.Config.Labels["x"], "y") + + testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { + cmd := helpers.Command( + "compose", + "-f", + data.Temp().Path("compose.yaml"), + "run", + "--label", "foo=rab", + "--label", "x=y", + "--name", + data.Identifier(), + "alpine", + ) + cmd.WithPseudoTTY() + return cmd + } + + testCase.Expected = func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: expect.ExitCodeSuccess, + Output: func(stdout string, t tig.T) { + fooLabel := helpers.Capture("inspect", "--format", "{{index .Config.Labels \"foo\"}}", data.Identifier()) + xLabel := helpers.Capture("inspect", "--format", "{{index .Config.Labels \"x\"}}", data.Identifier()) + assert.Equal(t, strings.TrimSpace(fooLabel), "rab") + assert.Equal(t, strings.TrimSpace(xLabel), "y") + }, + } + } + + testCase.Run(t) } func TestComposeRunWithArgs(t *testing.T) { - base := testutil.NewBase(t) - containerName := testutil.Identifier(t) - - dockerComposeYAML := fmt.Sprintf(` + var dockerComposeYAML = fmt.Sprintf(` services: alpine: image: %s @@ -342,28 +390,41 @@ services: - echo `, testutil.CommonImage) - comp := testutil.NewComposeDir(t, dockerComposeYAML) - defer comp.CleanUp() - projectName := comp.ProjectName() - t.Logf("projectName=%q", projectName) - defer base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").Run() + testCase := nerdtest.Setup() - defer base.Cmd("rm", "-f", "-v", containerName).Run() - const partialOutput = "hello world" - // unbuffer(1) emulates tty, which is required by `nerdctl run -t`. - // unbuffer(1) can be installed with `apt-get install expect`. - unbuffer := []string{"unbuffer"} - base.ComposeCmdWithHelper(unbuffer, "-f", comp.YAMLFullPath(), - "run", "--name", containerName, "alpine", partialOutput).AssertOutContains(partialOutput) + testCase.Setup = func(data test.Data, helpers test.Helpers) { + data.Temp().Save(dockerComposeYAML, "compose.yaml") + data.Labels().Set("composeYAML", data.Temp().Path("compose.yaml")) + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + if yaml := data.Labels().Get("composeYAML"); yaml != "" { + helpers.Anyhow("compose", "-f", yaml, "down", "-v") + } + } + + testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { + cmd := helpers.Command( + "compose", + "-f", + data.Temp().Path("compose.yaml"), + "run", + "--name", + data.Identifier(), + "alpine", + "hello world", + ) + cmd.WithPseudoTTY() + return cmd + } + + testCase.Expected = test.Expects(expect.ExitCodeSuccess, nil, expect.Contains("hello world")) + + testCase.Run(t) } func TestComposeRunWithEntrypoint(t *testing.T) { - base := testutil.NewBase(t) - // specify the name of container in order to remove - // TODO: when `compose rm` is implemented, replace it. - containerName := testutil.Identifier(t) - - dockerComposeYAML := fmt.Sprintf(` + var dockerComposeYAML = fmt.Sprintf(` services: alpine: image: %s @@ -371,26 +432,42 @@ services: - stty # should be changed `, testutil.CommonImage) - comp := testutil.NewComposeDir(t, dockerComposeYAML) - defer comp.CleanUp() - projectName := comp.ProjectName() - t.Logf("projectName=%q", projectName) - defer base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").Run() + testCase := nerdtest.Setup() - defer base.Cmd("rm", "-f", "-v", containerName).Run() - const partialOutput = "hello world" - // unbuffer(1) emulates tty, which is required by `nerdctl run -t`. - // unbuffer(1) can be installed with `apt-get install expect`. - unbuffer := []string{"unbuffer"} - base.ComposeCmdWithHelper(unbuffer, "-f", comp.YAMLFullPath(), - "run", "--entrypoint", "echo", "--name", containerName, "alpine", partialOutput).AssertOutContains(partialOutput) + testCase.Setup = func(data test.Data, helpers test.Helpers) { + data.Temp().Save(dockerComposeYAML, "compose.yaml") + data.Labels().Set("composeYAML", data.Temp().Path("compose.yaml")) + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + if yaml := data.Labels().Get("composeYAML"); yaml != "" { + helpers.Anyhow("compose", "-f", yaml, "down", "-v") + } + } + + testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { + cmd := helpers.Command( + "compose", + "-f", + data.Temp().Path("compose.yaml"), + "run", + "--entrypoint", "echo", + "--name", + data.Identifier(), + "alpine", + "hello world", + ) + cmd.WithPseudoTTY() + return cmd + } + + testCase.Expected = test.Expects(expect.ExitCodeSuccess, nil, expect.Contains("hello world")) + + testCase.Run(t) } func TestComposeRunWithVolume(t *testing.T) { - base := testutil.NewBase(t) - containerName := testutil.Identifier(t) - - dockerComposeYAML := fmt.Sprintf(` + var dockerComposeYAML = fmt.Sprintf(` services: alpine: image: %s @@ -398,30 +475,48 @@ services: - stty # no meaning, just put any command `, testutil.CommonImage) - comp := testutil.NewComposeDir(t, dockerComposeYAML) - defer comp.CleanUp() - projectName := comp.ProjectName() - t.Logf("projectName=%q", projectName) - defer base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").Run() + testCase := nerdtest.Setup() - // The directory is automatically removed by Cleanup - tmpDir := t.TempDir() - destinationDir := "/data" - volumeFlagStr := fmt.Sprintf("%s:%s", tmpDir, destinationDir) + testCase.Setup = func(data test.Data, helpers test.Helpers) { + data.Temp().Save(dockerComposeYAML, "compose.yaml") + data.Labels().Set("composeYAML", data.Temp().Path("compose.yaml")) + } - defer base.Cmd("rm", "-f", "-v", containerName).Run() - // unbuffer(1) emulates tty, which is required by `nerdctl run -t`. - // unbuffer(1) can be installed with `apt-get install expect`. - unbuffer := []string{"unbuffer"} - base.ComposeCmdWithHelper(unbuffer, "-f", comp.YAMLFullPath(), - "run", "--volume", volumeFlagStr, "--name", containerName, "alpine").AssertOK() - - container := base.InspectContainer(containerName) - errMsg := fmt.Sprintf("test failed, cannot find volume: %v", container.Mounts) - assert.Assert(t, container.Mounts != nil, errMsg) - assert.Assert(t, len(container.Mounts) == 1, errMsg) - assert.Assert(t, container.Mounts[0].Source == tmpDir, errMsg) - assert.Assert(t, container.Mounts[0].Destination == destinationDir, errMsg) + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + if yaml := data.Labels().Get("composeYAML"); yaml != "" { + helpers.Anyhow("compose", "-f", yaml, "down", "-v") + } + } + + testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { + volumeFlag := fmt.Sprintf("%s:/data", data.Temp().Dir()) + cmd := helpers.Command( + "compose", + "-f", + data.Temp().Path("compose.yaml"), + "run", + "--volume", volumeFlag, + "--name", + data.Identifier(), + "alpine", + ) + cmd.WithPseudoTTY() + return cmd + } + + testCase.Expected = func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: expect.ExitCodeSuccess, + Output: func(stdout string, t tig.T) { + source := helpers.Capture("inspect", "--format", "{{(index .Mounts 0).Source}}", data.Identifier()) + dest := helpers.Capture("inspect", "--format", "{{(index .Mounts 0).Destination}}", data.Identifier()) + assert.Equal(t, strings.TrimSpace(source), data.Temp().Dir()) + assert.Equal(t, strings.TrimSpace(dest), "/data") + }, + } + } + + testCase.Run(t) } func TestComposePushAndPullWithCosignVerify(t *testing.T) {