Skip to content

Commit ebff485

Browse files
committed
don't fail down cmd if services with pre_stop hook already stopped/removed
Signed-off-by: Guillaume Lours <[email protected]>
1 parent c9ebfad commit ebff485

File tree

7 files changed

+160
-0
lines changed

7 files changed

+160
-0
lines changed

pkg/compose/down.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,10 @@ func (s *composeService) stopContainer(ctx context.Context, w progress.Writer, s
306306
for _, hook := range service.PreStop {
307307
err := s.runHook(ctx, ctr, *service, hook, nil)
308308
if err != nil {
309+
// Ignore errors indicating that some containers were already stopped or removed.
310+
if cerrdefs.IsNotFound(err) || cerrdefs.IsConflict(err) {
311+
return nil
312+
}
309313
return err
310314
}
311315
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
services:
2+
sample:
3+
image: nginx
4+
volumes:
5+
- data:/data
6+
pre_stop:
7+
- command: sh -c 'echo "In the pre-stop" >> /data/log.txt'
8+
test:
9+
image: nginx
10+
post_start:
11+
- command: sh -c 'echo env'
12+
volumes:
13+
data:
14+
name: sample-data
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
services:
2+
3+
test:
4+
image: alpine
5+
command: sh -c 'echo "start container" >> /data/log.txt'
6+
post_start:
7+
- command: sh -c 'echo env'
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
services:
2+
test:
3+
image: nginx
4+
post_start:
5+
- command: sh -c 'echo env'
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
services:
2+
sample:
3+
image: nginx
4+
volumes:
5+
- data:/data
6+
pre_stop:
7+
- command: sh -c 'command in error'
8+
volumes:
9+
data:
10+
name: sample-data
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
services:
2+
sample:
3+
image: nginx
4+
volumes:
5+
- data:/data
6+
pre_stop:
7+
- command: sh -c 'echo "In the pre-stop" >> /data/log.txt'
8+
volumes:
9+
data:
10+
name: sample-data

pkg/e2e/hooks_test.go

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
Copyright 2023 Docker Compose CLI authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package e2e
17+
18+
import (
19+
"gotest.tools/v3/assert"
20+
"gotest.tools/v3/icmd"
21+
"strings"
22+
"testing"
23+
)
24+
25+
func TestPostStartHookInError(t *testing.T) {
26+
c := NewParallelCLI(t)
27+
const projectName = "hooks-post-start-failure"
28+
29+
t.Cleanup(func() {
30+
c.RunDockerComposeCmd(t, "--project-name", projectName, "down", "-v", "--remove-orphans", "-t", "0")
31+
})
32+
33+
res := c.RunDockerComposeCmdNoCheck(t, "-f", "fixtures/hooks/poststart/compose-error.yaml", "--project-name", projectName, "up", "-d")
34+
res.Assert(t, icmd.Expected{ExitCode: 1})
35+
assert.Assert(t, strings.Contains(res.Combined(), "Error response from daemon: container"), res.Combined())
36+
assert.Assert(t, strings.Contains(res.Combined(), "is not running"), res.Combined())
37+
}
38+
39+
func TestPostStartHookSuccess(t *testing.T) {
40+
c := NewParallelCLI(t)
41+
const projectName = "hooks-post-start-success"
42+
43+
t.Cleanup(func() {
44+
c.RunDockerComposeCmd(t, "--project-name", projectName, "down", "-v", "--remove-orphans", "-t", "0")
45+
})
46+
47+
res := c.RunDockerComposeCmd(t, "-f", "fixtures/hooks/poststart/compose-success.yaml", "--project-name", projectName, "up", "-d")
48+
res.Assert(t, icmd.Expected{ExitCode: 0})
49+
}
50+
51+
func TestPreStopHookSuccess(t *testing.T) {
52+
c := NewParallelCLI(t)
53+
const projectName = "hooks-pre-stop-success"
54+
55+
t.Cleanup(func() {
56+
c.RunDockerComposeCmd(t, "-f", "fixtures/hooks/prestop/compose-success.yaml", "--project-name", projectName, "down", "-v", "--remove-orphans", "-t", "0")
57+
})
58+
59+
res := c.RunDockerComposeCmd(t, "-f", "fixtures/hooks/prestop/compose-success.yaml", "--project-name", projectName, "up", "-d")
60+
res.Assert(t, icmd.Expected{ExitCode: 0})
61+
62+
res = c.RunDockerComposeCmd(t, "-f", "fixtures/hooks/prestop/compose-success.yaml", "--project-name", projectName, "down", "-v", "--remove-orphans", "-t", "0")
63+
res.Assert(t, icmd.Expected{ExitCode: 0})
64+
}
65+
66+
func TestPreStopHookInError(t *testing.T) {
67+
c := NewParallelCLI(t)
68+
const projectName = "hooks-pre-stop-failure"
69+
70+
t.Cleanup(func() {
71+
c.RunDockerComposeCmd(t, "-f", "fixtures/hooks/prestop/compose-success.yaml", "--project-name", projectName, "down", "-v", "--remove-orphans", "-t", "0")
72+
})
73+
74+
res := c.RunDockerComposeCmdNoCheck(t, "-f", "fixtures/hooks/prestop/compose-error.yaml", "--project-name", projectName, "up", "-d")
75+
res.Assert(t, icmd.Expected{ExitCode: 0})
76+
77+
res = c.RunDockerComposeCmdNoCheck(t, "-f", "fixtures/hooks/prestop/compose-error.yaml", "--project-name", projectName, "down", "-v", "--remove-orphans", "-t", "0")
78+
res.Assert(t, icmd.Expected{ExitCode: 1})
79+
assert.Assert(t, strings.Contains(res.Combined(), "sample hook exited with status 127"))
80+
81+
}
82+
83+
func TestPreStopHookSuccessWithPreviousStop(t *testing.T) {
84+
c := NewParallelCLI(t)
85+
const projectName = "hooks-pre-stop-success-with-previous-stop"
86+
87+
t.Cleanup(func() {
88+
res := c.RunDockerComposeCmd(t, "-f", "fixtures/hooks/compose.yaml", "--project-name", projectName, "down", "-v", "--remove-orphans", "-t", "0")
89+
res.Assert(t, icmd.Expected{ExitCode: 0})
90+
})
91+
92+
res := c.RunDockerComposeCmd(t, "-f", "fixtures/hooks/compose.yaml", "--project-name", projectName, "up", "-d")
93+
res.Assert(t, icmd.Expected{ExitCode: 0})
94+
95+
res = c.RunDockerComposeCmd(t, "-f", "fixtures/hooks/compose.yaml", "--project-name", projectName, "stop", "sample")
96+
res.Assert(t, icmd.Expected{ExitCode: 0})
97+
}
98+
99+
func TestPostStartAndPreStopHook(t *testing.T) {
100+
c := NewParallelCLI(t)
101+
const projectName = "hooks-post-start-and-pre-stop"
102+
103+
t.Cleanup(func() {
104+
res := c.RunDockerComposeCmd(t, "-f", "fixtures/hooks/compose.yaml", "--project-name", projectName, "down", "-v", "--remove-orphans", "-t", "0")
105+
res.Assert(t, icmd.Expected{ExitCode: 0})
106+
})
107+
108+
res := c.RunDockerComposeCmd(t, "-f", "fixtures/hooks/compose.yaml", "--project-name", projectName, "up", "-d")
109+
res.Assert(t, icmd.Expected{ExitCode: 0})
110+
}

0 commit comments

Comments
 (0)