Skip to content
This repository was archived by the owner on Nov 27, 2023. It is now read-only.

Commit 0e8a56b

Browse files
authored
Merge pull request #1502 from docker/init_container
add support for service_completed_successfully
2 parents cf7f0db + 15a21a4 commit 0e8a56b

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

local/compose/convergence.go

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/compose-spec/compose-go/types"
2626
"github.com/containerd/containerd/platforms"
2727
moby "github.com/docker/docker/api/types"
28+
"github.com/docker/docker/api/types/container"
2829
"github.com/docker/docker/api/types/filters"
2930
"github.com/docker/docker/api/types/network"
3031
specs "github.com/opencontainers/image-spec/specs-go/v1"
@@ -162,6 +163,14 @@ func (s *composeService) waitDependencies(ctx context.Context, project *types.Pr
162163
}
163164
}
164165
})
166+
case "service_completed_successfully":
167+
exit, err := s.waitCompleted(ctx, project, dep)
168+
if err != nil {
169+
return err
170+
}
171+
if exit != 0 {
172+
return fmt.Errorf("service %q didn't completed successfully: exit %d", dep, exit)
173+
}
165174
}
166175
}
167176
return eg.Wait()
@@ -330,8 +339,8 @@ func (s *composeService) connectContainerToNetwork(ctx context.Context, id strin
330339
func (s *composeService) isServiceHealthy(ctx context.Context, project *types.Project, service string) (bool, error) {
331340
containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
332341
Filters: filters.NewArgs(
333-
filters.Arg("label", fmt.Sprintf("%s=%s", projectLabel, project.Name)),
334-
filters.Arg("label", fmt.Sprintf("%s=%s", serviceLabel, service)),
342+
projectFilter(project.Name),
343+
serviceFilter(service),
335344
),
336345
})
337346
if err != nil {
@@ -356,6 +365,28 @@ func (s *composeService) isServiceHealthy(ctx context.Context, project *types.Pr
356365
return true, nil
357366
}
358367

368+
func (s *composeService) waitCompleted(ctx context.Context, project *types.Project, dep string) (int64, error) {
369+
containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
370+
Filters: filters.NewArgs(
371+
projectFilter(project.Name),
372+
serviceFilter(dep),
373+
),
374+
})
375+
if err != nil {
376+
return 0, err
377+
}
378+
for _, c := range containers {
379+
wait, errors := s.apiClient.ContainerWait(ctx, c.ID, container.WaitConditionNextExit)
380+
select {
381+
case w := <-wait:
382+
return w.StatusCode, nil
383+
case err := <-errors:
384+
return 0, err
385+
}
386+
}
387+
return 0, nil
388+
}
389+
359390
func (s *composeService) startService(ctx context.Context, project *types.Project, service types.ServiceConfig) error {
360391
err := s.waitDependencies(ctx, project, service)
361392
if err != nil {

local/e2e/compose/compose_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,13 @@ func TestAttachRestart(t *testing.T) {
147147
execRegex := regexp.MustCompile(`another_1 \| world`)
148148
assert.Equal(t, len(execRegex.FindAllStringIndex(output, -1)), 3, res.Combined())
149149
}
150+
151+
func TestInitContainer(t *testing.T) {
152+
c := NewParallelE2eCLI(t, binDir)
153+
154+
res := c.RunDockerOrExitError("compose", "--ansi=never", "--project-directory", "./fixtures/init-container", "up")
155+
defer c.RunDockerCmd("compose", "-p", "init-container", "down")
156+
output := res.Stdout()
157+
158+
assert.Assert(t, strings.Contains(output, "foo_1 | hello\nbar_1 | world"), res.Combined())
159+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
services:
2+
foo:
3+
image: alpine
4+
command: "echo hello"
5+
6+
bar:
7+
image: alpine
8+
command: "echo world"
9+
depends_on:
10+
foo:
11+
condition: "service_completed_successfully"

0 commit comments

Comments
 (0)