mirror of https://github.com/docker/compose.git
Merge pull request #1502 from docker/init_container
add support for service_completed_successfully
This commit is contained in:
commit
0e8a56bfcb
|
@ -25,6 +25,7 @@ import (
|
||||||
"github.com/compose-spec/compose-go/types"
|
"github.com/compose-spec/compose-go/types"
|
||||||
"github.com/containerd/containerd/platforms"
|
"github.com/containerd/containerd/platforms"
|
||||||
moby "github.com/docker/docker/api/types"
|
moby "github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
@ -162,6 +163,14 @@ func (s *composeService) waitDependencies(ctx context.Context, project *types.Pr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
case "service_completed_successfully":
|
||||||
|
exit, err := s.waitCompleted(ctx, project, dep)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if exit != 0 {
|
||||||
|
return fmt.Errorf("service %q didn't completed successfully: exit %d", dep, exit)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return eg.Wait()
|
return eg.Wait()
|
||||||
|
@ -330,8 +339,8 @@ func (s *composeService) connectContainerToNetwork(ctx context.Context, id strin
|
||||||
func (s *composeService) isServiceHealthy(ctx context.Context, project *types.Project, service string) (bool, error) {
|
func (s *composeService) isServiceHealthy(ctx context.Context, project *types.Project, service string) (bool, error) {
|
||||||
containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
|
containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
|
||||||
Filters: filters.NewArgs(
|
Filters: filters.NewArgs(
|
||||||
filters.Arg("label", fmt.Sprintf("%s=%s", projectLabel, project.Name)),
|
projectFilter(project.Name),
|
||||||
filters.Arg("label", fmt.Sprintf("%s=%s", serviceLabel, service)),
|
serviceFilter(service),
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -356,6 +365,28 @@ func (s *composeService) isServiceHealthy(ctx context.Context, project *types.Pr
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *composeService) waitCompleted(ctx context.Context, project *types.Project, dep string) (int64, error) {
|
||||||
|
containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
|
||||||
|
Filters: filters.NewArgs(
|
||||||
|
projectFilter(project.Name),
|
||||||
|
serviceFilter(dep),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
for _, c := range containers {
|
||||||
|
wait, errors := s.apiClient.ContainerWait(ctx, c.ID, container.WaitConditionNextExit)
|
||||||
|
select {
|
||||||
|
case w := <-wait:
|
||||||
|
return w.StatusCode, nil
|
||||||
|
case err := <-errors:
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *composeService) startService(ctx context.Context, project *types.Project, service types.ServiceConfig) error {
|
func (s *composeService) startService(ctx context.Context, project *types.Project, service types.ServiceConfig) error {
|
||||||
err := s.waitDependencies(ctx, project, service)
|
err := s.waitDependencies(ctx, project, service)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -147,3 +147,13 @@ func TestAttachRestart(t *testing.T) {
|
||||||
execRegex := regexp.MustCompile(`another_1 \| world`)
|
execRegex := regexp.MustCompile(`another_1 \| world`)
|
||||||
assert.Equal(t, len(execRegex.FindAllStringIndex(output, -1)), 3, res.Combined())
|
assert.Equal(t, len(execRegex.FindAllStringIndex(output, -1)), 3, res.Combined())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInitContainer(t *testing.T) {
|
||||||
|
c := NewParallelE2eCLI(t, binDir)
|
||||||
|
|
||||||
|
res := c.RunDockerOrExitError("compose", "--ansi=never", "--project-directory", "./fixtures/init-container", "up")
|
||||||
|
defer c.RunDockerCmd("compose", "-p", "init-container", "down")
|
||||||
|
output := res.Stdout()
|
||||||
|
|
||||||
|
assert.Assert(t, strings.Contains(output, "foo_1 | hello\nbar_1 | world"), res.Combined())
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
services:
|
||||||
|
foo:
|
||||||
|
image: alpine
|
||||||
|
command: "echo hello"
|
||||||
|
|
||||||
|
bar:
|
||||||
|
image: alpine
|
||||||
|
command: "echo world"
|
||||||
|
depends_on:
|
||||||
|
foo:
|
||||||
|
condition: "service_completed_successfully"
|
Loading…
Reference in New Issue