mirror of https://github.com/docker/compose.git
				
				
				
			Add tests for filtering containers not created by Compose
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
This commit is contained in:
		
							parent
							
								
									82ef998511
								
							
						
					
					
						commit
						0b1c86726e
					
				|  | @ -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" | ||||||
|  | 
 | ||||||
|  | @ -11,5 +11,7 @@ Background: | ||||||
| 
 | 
 | ||||||
| Scenario: --pull always | Scenario: --pull always | ||||||
|     When I run "compose up --pull=always -d" |     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" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -20,6 +20,7 @@ import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"os" | 	"os" | ||||||
|  | 	"path/filepath" | ||||||
| 	"regexp" | 	"regexp" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"testing" | 	"testing" | ||||||
|  | @ -78,9 +79,12 @@ func setup(s *godog.ScenarioContext) { | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	s.Step(`^a compose file$`, th.setComposeFile) | 	s.Step(`^a compose file$`, th.setComposeFile) | ||||||
|  | 	s.Step(`^a dockerfile$`, th.setDockerfile) | ||||||
| 	s.Step(`^I run "compose (.*)"$`, th.runComposeCommand) | 	s.Step(`^I run "compose (.*)"$`, th.runComposeCommand) | ||||||
|  | 	s.Step(`^I run "docker (.*)"$`, th.runDockerCommand) | ||||||
| 	s.Step(`service "(.*)" is "(.*)"$`, th.serviceIsStatus) | 	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) | 	s.Step(`exit code is (\d+)$`, th.exitCodeIs) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -88,6 +92,7 @@ type testHelper struct { | ||||||
| 	T               *testing.T | 	T               *testing.T | ||||||
| 	ProjectName     string | 	ProjectName     string | ||||||
| 	ComposeFile     string | 	ComposeFile     string | ||||||
|  | 	TestDir         string | ||||||
| 	CommandOutput   string | 	CommandOutput   string | ||||||
| 	CommandExitCode int | 	CommandExitCode int | ||||||
| 	CLI             *e2e.CLI | 	CLI             *e2e.CLI | ||||||
|  | @ -104,16 +109,21 @@ func (th *testHelper) serviceIsStatus(service, status string) error { | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (th *testHelper) outputContains(substring string) error { | func (th *testHelper) outputContains(expected bool) func(string) error { | ||||||
| 	if !strings.Contains(th.CommandOutput, substring) { | 	return func(substring string) error { | ||||||
| 		return fmt.Errorf("Missing output substring: %s\noutput: %s", substring, th.CommandOutput) | 		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 { | func (th *testHelper) exitCodeIs(exitCode int) error { | ||||||
| 	if exitCode != th.CommandExitCode { | 	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 | 	return nil | ||||||
| } | } | ||||||
|  | @ -127,6 +137,21 @@ func (th *testHelper) runComposeCommand(command string) error { | ||||||
| 
 | 
 | ||||||
| 	cmd := th.CLI.NewDockerComposeCmd(th.T, commandArgs...) | 	cmd := th.CLI.NewDockerComposeCmd(th.T, commandArgs...) | ||||||
| 	cmd.Stdin = strings.NewReader(th.ComposeFile) | 	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) | 	res := icmd.RunCmd(cmd) | ||||||
| 	th.CommandOutput = res.Combined() | 	th.CommandOutput = res.Combined() | ||||||
| 	th.CommandExitCode = res.ExitCode | 	th.CommandExitCode = res.ExitCode | ||||||
|  | @ -137,3 +162,14 @@ func (th *testHelper) setComposeFile(composeString string) error { | ||||||
| 	th.ComposeFile = composeString | 	th.ComposeFile = composeString | ||||||
| 	return nil | 	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 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -68,6 +68,7 @@ func TestServiceLinks(t *testing.T) { | ||||||
| 			projectFilter(testProject), | 			projectFilter(testProject), | ||||||
| 			serviceFilter("db"), | 			serviceFilter("db"), | ||||||
| 			oneOffFilter(false), | 			oneOffFilter(false), | ||||||
|  | 			hasConfigHashLabel(), | ||||||
| 		), | 		), | ||||||
| 		All: true, | 		All: true, | ||||||
| 	} | 	} | ||||||
|  | @ -193,6 +194,7 @@ func TestServiceLinks(t *testing.T) { | ||||||
| 				projectFilter(testProject), | 				projectFilter(testProject), | ||||||
| 				serviceFilter("web"), | 				serviceFilter("web"), | ||||||
| 				oneOffFilter(false), | 				oneOffFilter(false), | ||||||
|  | 				hasConfigHashLabel(), | ||||||
| 			), | 			), | ||||||
| 			All: true, | 			All: true, | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -50,7 +50,7 @@ func TestKillAll(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	ctx := context.Background() | 	ctx := context.Background() | ||||||
| 	api.EXPECT().ContainerList(ctx, moby.ContainerListOptions{ | 	api.EXPECT().ContainerList(ctx, moby.ContainerListOptions{ | ||||||
| 		Filters: filters.NewArgs(projectFilter(name)), | 		Filters: filters.NewArgs(projectFilter(name), hasConfigHashLabel()), | ||||||
| 	}).Return( | 	}).Return( | ||||||
| 		[]moby.Container{testContainer("service1", "123", false), testContainer("service1", "456", false), testContainer("service2", "789", false)}, nil) | 		[]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)))). | 	api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))). | ||||||
|  | @ -81,7 +81,7 @@ func TestKillSignal(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	name := strings.ToLower(testProject) | 	name := strings.ToLower(testProject) | ||||||
| 	listOptions := moby.ContainerListOptions{ | 	listOptions := moby.ContainerListOptions{ | ||||||
| 		Filters: filters.NewArgs(projectFilter(name), serviceFilter(serviceName)), | 		Filters: filters.NewArgs(projectFilter(name), serviceFilter(serviceName), hasConfigHashLabel()), | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	ctx := context.Background() | 	ctx := context.Background() | ||||||
|  | @ -133,6 +133,7 @@ func anyCancellableContext() gomock.Matcher { | ||||||
| func projectFilterListOpt(withOneOff bool) moby.ContainerListOptions { | func projectFilterListOpt(withOneOff bool) moby.ContainerListOptions { | ||||||
| 	filter := filters.NewArgs( | 	filter := filters.NewArgs( | ||||||
| 		projectFilter(strings.ToLower(testProject)), | 		projectFilter(strings.ToLower(testProject)), | ||||||
|  | 		hasConfigHashLabel(), | ||||||
| 	) | 	) | ||||||
| 	if !withOneOff { | 	if !withOneOff { | ||||||
| 		filter.Add("label", fmt.Sprintf("%s=False", compose.OneoffLabel)) | 		filter.Add("label", fmt.Sprintf("%s=False", compose.OneoffLabel)) | ||||||
|  |  | ||||||
|  | @ -52,7 +52,7 @@ func TestComposeService_Logs_Demux(t *testing.T) { | ||||||
| 	ctx := context.Background() | 	ctx := context.Background() | ||||||
| 	api.EXPECT().ContainerList(ctx, moby.ContainerListOptions{ | 	api.EXPECT().ContainerList(ctx, moby.ContainerListOptions{ | ||||||
| 		All:     true, | 		All:     true, | ||||||
| 		Filters: filters.NewArgs(oneOffFilter(false), projectFilter(name)), | 		Filters: filters.NewArgs(oneOffFilter(false), projectFilter(name), hasConfigHashLabel()), | ||||||
| 	}).Return( | 	}).Return( | ||||||
| 		[]moby.Container{ | 		[]moby.Container{ | ||||||
| 			testContainer("service", "c", false), | 			testContainer("service", "c", false), | ||||||
|  | @ -125,7 +125,7 @@ func TestComposeService_Logs_ServiceFiltering(t *testing.T) { | ||||||
| 	ctx := context.Background() | 	ctx := context.Background() | ||||||
| 	api.EXPECT().ContainerList(ctx, moby.ContainerListOptions{ | 	api.EXPECT().ContainerList(ctx, moby.ContainerListOptions{ | ||||||
| 		All:     true, | 		All:     true, | ||||||
| 		Filters: filters.NewArgs(oneOffFilter(false), projectFilter(name)), | 		Filters: filters.NewArgs(oneOffFilter(false), projectFilter(name), hasConfigHashLabel()), | ||||||
| 	}).Return( | 	}).Return( | ||||||
| 		[]moby.Container{ | 		[]moby.Container{ | ||||||
| 			testContainer("serviceA", "c1", false), | 			testContainer("serviceA", "c1", false), | ||||||
|  |  | ||||||
|  | @ -42,7 +42,7 @@ func TestPs(t *testing.T) { | ||||||
| 	cli.EXPECT().Client().Return(api).AnyTimes() | 	cli.EXPECT().Client().Return(api).AnyTimes() | ||||||
| 
 | 
 | ||||||
| 	ctx := context.Background() | 	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") | 	args.Add("label", "com.docker.compose.oneoff=False") | ||||||
| 	listOpts := moby.ContainerListOptions{Filters: args, All: false} | 	listOpts := moby.ContainerListOptions{Filters: args, All: false} | ||||||
| 	c1, inspect1 := containerDetails("service1", "123", "running", "healthy", 0) | 	c1, inspect1 := containerDetails("service1", "123", "running", "healthy", 0) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue