Selaa lähdekoodia

Add tests for filtering containers not created by Compose

Signed-off-by: Laura Brehm <[email protected]>
Laura Brehm 2 vuotta sitten
vanhempi
sitoutus
0b1c86726e

+ 27 - 0
e2e/cucumber-features/ps.feature

@@ -0,0 +1,27 @@
+Feature: PS
+
+Background:
+    Given a compose file
+        """
+        services:
+          build:
+            image: test:latest
+            build:
+                context: ./
+          pull:
+            image: alpine
+            command: top
+        """
+    And a dockerfile
+        """
+        FROM golang:1.19-alpine
+        """
+
+Scenario: external container from compose image exists
+    When I run "compose build"
+    Then the exit code is 0
+    And I run "docker run --name external-test test:latest ls"
+    Then the exit code is 0
+    And I run "compose ps -a"
+    Then the output does not contain "external-test"
+

+ 3 - 1
e2e/cucumber-features/up.feature

@@ -11,5 +11,7 @@ Background:
 
 Scenario: --pull always
     When I run "compose up --pull=always -d"
-    Then the output contains "simple Pulled"
+    And the output contains "simple Pulled"
+    Then I run "compose up --pull=always -d"
+    And the output contains "simple Pulled"
 

+ 42 - 6
e2e/cucumber_test.go

@@ -20,6 +20,7 @@ import (
 	"context"
 	"fmt"
 	"os"
+	"path/filepath"
 	"regexp"
 	"strings"
 	"testing"
@@ -78,9 +79,12 @@ func setup(s *godog.ScenarioContext) {
 	})
 
 	s.Step(`^a compose file$`, th.setComposeFile)
+	s.Step(`^a dockerfile$`, th.setDockerfile)
 	s.Step(`^I run "compose (.*)"$`, th.runComposeCommand)
+	s.Step(`^I run "docker (.*)"$`, th.runDockerCommand)
 	s.Step(`service "(.*)" is "(.*)"$`, th.serviceIsStatus)
-	s.Step(`output contains "(.*)"$`, th.outputContains)
+	s.Step(`output contains "(.*)"$`, th.outputContains(true))
+	s.Step(`output does not contain "(.*)"$`, th.outputContains(false))
 	s.Step(`exit code is (\d+)$`, th.exitCodeIs)
 }
 
@@ -88,6 +92,7 @@ type testHelper struct {
 	T               *testing.T
 	ProjectName     string
 	ComposeFile     string
+	TestDir         string
 	CommandOutput   string
 	CommandExitCode int
 	CLI             *e2e.CLI
@@ -104,16 +109,21 @@ func (th *testHelper) serviceIsStatus(service, status string) error {
 	return nil
 }
 
-func (th *testHelper) outputContains(substring string) error {
-	if !strings.Contains(th.CommandOutput, substring) {
-		return fmt.Errorf("Missing output substring: %s\noutput: %s", substring, th.CommandOutput)
+func (th *testHelper) outputContains(expected bool) func(string) error {
+	return func(substring string) error {
+		contains := strings.Contains(th.CommandOutput, substring)
+		if contains && !expected {
+			return fmt.Errorf("Unexpected substring in output: %s\noutput: %s", substring, th.CommandOutput)
+		} else if !contains && expected {
+			return fmt.Errorf("Missing substring in output: %s\noutput: %s", substring, th.CommandOutput)
+		}
+		return nil
 	}
-	return nil
 }
 
 func (th *testHelper) exitCodeIs(exitCode int) error {
 	if exitCode != th.CommandExitCode {
-		return fmt.Errorf("Wrong exit code: %d expected: %d", th.CommandExitCode, exitCode)
+		return fmt.Errorf("Wrong exit code: %d expected: %d || command output: %s", th.CommandExitCode, exitCode, th.CommandOutput)
 	}
 	return nil
 }
@@ -127,6 +137,21 @@ func (th *testHelper) runComposeCommand(command string) error {
 
 	cmd := th.CLI.NewDockerComposeCmd(th.T, commandArgs...)
 	cmd.Stdin = strings.NewReader(th.ComposeFile)
+	cmd.Dir = th.TestDir
+	res := icmd.RunCmd(cmd)
+	th.CommandOutput = res.Combined()
+	th.CommandExitCode = res.ExitCode
+	return nil
+}
+
+func (th *testHelper) runDockerCommand(command string) error {
+	commandArgs, err := shellwords.Parse(command)
+	if err != nil {
+		return err
+	}
+
+	cmd := th.CLI.NewDockerCmd(th.T, commandArgs...)
+	cmd.Dir = th.TestDir
 	res := icmd.RunCmd(cmd)
 	th.CommandOutput = res.Combined()
 	th.CommandExitCode = res.ExitCode
@@ -137,3 +162,14 @@ func (th *testHelper) setComposeFile(composeString string) error {
 	th.ComposeFile = composeString
 	return nil
 }
+
+func (th *testHelper) setDockerfile(dockerfileString string) error {
+	tempDir := th.T.TempDir()
+	th.TestDir = tempDir
+
+	err := os.WriteFile(filepath.Join(tempDir, "Dockerfile"), []byte(dockerfileString), 0o644)
+	if err != nil {
+		return err
+	}
+	return nil
+}

+ 2 - 0
pkg/compose/convergence_test.go

@@ -68,6 +68,7 @@ func TestServiceLinks(t *testing.T) {
 			projectFilter(testProject),
 			serviceFilter("db"),
 			oneOffFilter(false),
+			hasConfigHashLabel(),
 		),
 		All: true,
 	}
@@ -193,6 +194,7 @@ func TestServiceLinks(t *testing.T) {
 				projectFilter(testProject),
 				serviceFilter("web"),
 				oneOffFilter(false),
+				hasConfigHashLabel(),
 			),
 			All: true,
 		}

+ 3 - 2
pkg/compose/kill_test.go

@@ -50,7 +50,7 @@ func TestKillAll(t *testing.T) {
 
 	ctx := context.Background()
 	api.EXPECT().ContainerList(ctx, moby.ContainerListOptions{
-		Filters: filters.NewArgs(projectFilter(name)),
+		Filters: filters.NewArgs(projectFilter(name), hasConfigHashLabel()),
 	}).Return(
 		[]moby.Container{testContainer("service1", "123", false), testContainer("service1", "456", false), testContainer("service2", "789", false)}, nil)
 	api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))).
@@ -81,7 +81,7 @@ func TestKillSignal(t *testing.T) {
 
 	name := strings.ToLower(testProject)
 	listOptions := moby.ContainerListOptions{
-		Filters: filters.NewArgs(projectFilter(name), serviceFilter(serviceName)),
+		Filters: filters.NewArgs(projectFilter(name), serviceFilter(serviceName), hasConfigHashLabel()),
 	}
 
 	ctx := context.Background()
@@ -133,6 +133,7 @@ func anyCancellableContext() gomock.Matcher {
 func projectFilterListOpt(withOneOff bool) moby.ContainerListOptions {
 	filter := filters.NewArgs(
 		projectFilter(strings.ToLower(testProject)),
+		hasConfigHashLabel(),
 	)
 	if !withOneOff {
 		filter.Add("label", fmt.Sprintf("%s=False", compose.OneoffLabel))

+ 2 - 2
pkg/compose/logs_test.go

@@ -52,7 +52,7 @@ func TestComposeService_Logs_Demux(t *testing.T) {
 	ctx := context.Background()
 	api.EXPECT().ContainerList(ctx, moby.ContainerListOptions{
 		All:     true,
-		Filters: filters.NewArgs(oneOffFilter(false), projectFilter(name)),
+		Filters: filters.NewArgs(oneOffFilter(false), projectFilter(name), hasConfigHashLabel()),
 	}).Return(
 		[]moby.Container{
 			testContainer("service", "c", false),
@@ -125,7 +125,7 @@ func TestComposeService_Logs_ServiceFiltering(t *testing.T) {
 	ctx := context.Background()
 	api.EXPECT().ContainerList(ctx, moby.ContainerListOptions{
 		All:     true,
-		Filters: filters.NewArgs(oneOffFilter(false), projectFilter(name)),
+		Filters: filters.NewArgs(oneOffFilter(false), projectFilter(name), hasConfigHashLabel()),
 	}).Return(
 		[]moby.Container{
 			testContainer("serviceA", "c1", false),

+ 1 - 1
pkg/compose/ps_test.go

@@ -42,7 +42,7 @@ func TestPs(t *testing.T) {
 	cli.EXPECT().Client().Return(api).AnyTimes()
 
 	ctx := context.Background()
-	args := filters.NewArgs(projectFilter(strings.ToLower(testProject)))
+	args := filters.NewArgs(projectFilter(strings.ToLower(testProject)), hasConfigHashLabel())
 	args.Add("label", "com.docker.compose.oneoff=False")
 	listOpts := moby.ContainerListOptions{Filters: args, All: false}
 	c1, inspect1 := containerDetails("service1", "123", "running", "healthy", 0)