mirror of
https://github.com/docker/compose.git
synced 2026-02-15 13:09:24 +08:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0938c7e96f | ||
|
|
f429ee958a | ||
|
|
e9ded2c518 | ||
|
|
54e6e0bd8f | ||
|
|
3bc871e64b | ||
|
|
6ff15d9472 | ||
|
|
49bc0603e3 | ||
|
|
ce8a09b53f | ||
|
|
3dc8734897 | ||
|
|
852e192820 | ||
|
|
d9e7859664 |
@@ -15,7 +15,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
ARG GO_VERSION=1.20.5
|
||||
ARG GO_VERSION=1.20.6
|
||||
ARG XX_VERSION=1.2.1
|
||||
ARG GOLANGCI_LINT_VERSION=v1.53.2
|
||||
ARG ADDLICENSE_VERSION=v1.0.0
|
||||
|
||||
11
go.mod
11
go.mod
@@ -11,10 +11,10 @@ require (
|
||||
github.com/containerd/containerd v1.7.2
|
||||
github.com/cucumber/godog v0.0.0-00010101000000-000000000000 // replaced; see replace for the actual version used
|
||||
github.com/distribution/distribution/v3 v3.0.0-20230601133803-97b1d649c493
|
||||
github.com/docker/buildx v0.11.1
|
||||
github.com/docker/cli v24.0.2+incompatible
|
||||
github.com/docker/buildx v0.11.2
|
||||
github.com/docker/cli v24.0.4+incompatible
|
||||
github.com/docker/cli-docs-tool v0.6.0
|
||||
github.com/docker/docker v24.0.4+incompatible
|
||||
github.com/docker/docker v24.0.5-0.20230714235725-36e9e796c6fc+incompatible // v24.0.5-dev
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/docker/go-units v0.5.0
|
||||
github.com/fsnotify/fsevents v0.1.1
|
||||
@@ -24,7 +24,7 @@ require (
|
||||
github.com/jonboulle/clockwork v0.4.0
|
||||
github.com/mattn/go-shellwords v1.0.12
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/moby/buildkit v0.11.0-rc3.0.20230609092854-67a08623b95a
|
||||
github.com/moby/buildkit v0.12.1-0.20230717122532-faa0cc7da353 // v0.12 release branch
|
||||
github.com/moby/patternmatcher v0.5.0
|
||||
github.com/moby/term v0.5.0
|
||||
github.com/morikuni/aec v1.0.0
|
||||
@@ -71,7 +71,6 @@ require (
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cloudflare/cfssl v1.6.4 // indirect
|
||||
github.com/containerd/continuity v0.4.1 // indirect
|
||||
github.com/containerd/ttrpc v1.2.2 // indirect
|
||||
github.com/containerd/typeurl/v2 v2.1.1 // indirect
|
||||
github.com/cucumber/gherkin-go/v19 v19.0.3 // indirect
|
||||
github.com/cucumber/messages-go/v16 v16.0.1 // indirect
|
||||
@@ -148,7 +147,7 @@ require (
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/subosito/gotenv v1.4.1 // indirect
|
||||
github.com/tonistiigi/fsutil v0.0.0-20230407161946-9e7a6df48576 // indirect
|
||||
github.com/tonistiigi/fsutil v0.0.0-20230629203738-36ef4d8c0dbb // indirect
|
||||
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
|
||||
github.com/tonistiigi/vt100 v0.0.0-20230623042737-f9a4f7ef6531 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
|
||||
24
go.sum
24
go.sum
@@ -145,7 +145,6 @@ github.com/containerd/nydus-snapshotter v0.8.2 h1:7SOrMU2YmLzfbsr5J7liMZJlNi5WT6
|
||||
github.com/containerd/stargz-snapshotter v0.14.3 h1:OTUVZoPSPs8mGgmQUE1dqw3WX/3nrsmsurW7UPLWl1U=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
|
||||
github.com/containerd/ttrpc v1.2.2 h1:9vqZr0pxwOF5koz6N0N3kJ0zDHokrcPxIR/ZR2YFtOs=
|
||||
github.com/containerd/ttrpc v1.2.2/go.mod h1:sIT6l32Ph/H9cvnJsfXM5drIVzTr5A2flTf1G5tYZak=
|
||||
github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4=
|
||||
github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
@@ -167,17 +166,17 @@ github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zA
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/distribution/distribution/v3 v3.0.0-20230601133803-97b1d649c493 h1:fm5DpBD+A7o0+x9Nf+o9/4/qPGbfxLpr9qIPVuV8vQc=
|
||||
github.com/distribution/distribution/v3 v3.0.0-20230601133803-97b1d649c493/go.mod h1:+fqBJ4vPYo4Uu1ZE4d+bUtTLRXfdSL3NvCZIZ9GHv58=
|
||||
github.com/docker/buildx v0.11.1 h1:xfmrAkOJrN+NLRcwhZn1iBgJVAK1dEBEv8lWu1Wxg14=
|
||||
github.com/docker/buildx v0.11.1/go.mod h1:qAxs3bsJEfVo7DOc9riES/f9Z187CeGM5nLPmadk8AA=
|
||||
github.com/docker/cli v24.0.2+incompatible h1:QdqR7znue1mtkXIJ+ruQMGQhpw2JzMJLRXp6zpzF6tM=
|
||||
github.com/docker/cli v24.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/buildx v0.11.2 h1:R3p9F0gnI4FwvQ0p40UwdX1T4ugap4UWxY3TFHoP4Ws=
|
||||
github.com/docker/buildx v0.11.2/go.mod h1:CWAABt10iIuGpleypA3103mplDfcGu0A2AvT03xfpTc=
|
||||
github.com/docker/cli v24.0.4+incompatible h1:Y3bYF9ekNTm2VFz5U/0BlMdJy73D+Y1iAAZ8l63Ydzw=
|
||||
github.com/docker/cli v24.0.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli-docs-tool v0.6.0 h1:Z9x10SaZgFaB6jHgz3OWooynhSa40CsWkpe5hEnG/qA=
|
||||
github.com/docker/cli-docs-tool v0.6.0/go.mod h1:zMjqTFCU361PRh8apiXzeAZ1Q/xupbIwTusYpzCXS/o=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
|
||||
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v24.0.4+incompatible h1:s/LVDftw9hjblvqIeTiGYXBCD95nOEEl7qRsRrIOuQI=
|
||||
github.com/docker/docker v24.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v24.0.5-0.20230714235725-36e9e796c6fc+incompatible h1:sdGvA1bxu/1J51gAs1XU0bZC+2WxncYnI210as3c6g8=
|
||||
github.com/docker/docker v24.0.5-0.20230714235725-36e9e796c6fc+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
|
||||
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
|
||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
|
||||
@@ -465,8 +464,8 @@ github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WT
|
||||
github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/moby/buildkit v0.11.0-rc3.0.20230609092854-67a08623b95a h1:1k3bAXwxC2N1FncWijq/43sLj2OVIZ11FT0APIXWhMg=
|
||||
github.com/moby/buildkit v0.11.0-rc3.0.20230609092854-67a08623b95a/go.mod h1:4sM7BBBqXOQ+vV6LrVAOAMhZI9cVNYV5RhZCl906a64=
|
||||
github.com/moby/buildkit v0.12.1-0.20230717122532-faa0cc7da353 h1:/ZIwqvOF3QKObJbjX96xVvAKtnWdw/AuEqysbbujaZA=
|
||||
github.com/moby/buildkit v0.12.1-0.20230717122532-faa0cc7da353/go.mod h1:+n9GmkxwBCjVz4u7wmiyh+oqvjIjQM+1zk3iJrWfdos=
|
||||
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||
github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo=
|
||||
@@ -557,7 +556,6 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
|
||||
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
@@ -579,7 +577,6 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
|
||||
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
@@ -626,8 +623,8 @@ github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4D
|
||||
github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw=
|
||||
github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 h1:QB54BJwA6x8QU9nHY3xJSZR2kX9bgpZekRKGkLTmEXA=
|
||||
github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375/go.mod h1:xRroudyp5iVtxKqZCrA6n2TLFRBf8bmnjr1UD4x+z7g=
|
||||
github.com/tonistiigi/fsutil v0.0.0-20230407161946-9e7a6df48576 h1:fZXPQDVh5fm2x7pA0CH1TtH80tiZ0L7i834kZqZN8Pw=
|
||||
github.com/tonistiigi/fsutil v0.0.0-20230407161946-9e7a6df48576/go.mod h1:q1CxMSzcAbjUkVGHoZeQUcCaALnaE4XdWk+zJcgMYFw=
|
||||
github.com/tonistiigi/fsutil v0.0.0-20230629203738-36ef4d8c0dbb h1:uUe8rNyVXM8moActoBol6Xf6xX2GMr7SosR2EywMvGg=
|
||||
github.com/tonistiigi/fsutil v0.0.0-20230629203738-36ef4d8c0dbb/go.mod h1:SxX/oNQ/ag6Vaoli547ipFK9J7BZn5JqJG0JE8lf8bA=
|
||||
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0=
|
||||
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk=
|
||||
github.com/tonistiigi/vt100 v0.0.0-20230623042737-f9a4f7ef6531 h1:Y/M5lygoNPKwVNLMPXgVfsRT40CSFKXCxuU8LoHySjs=
|
||||
@@ -863,7 +860,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
|
||||
@@ -35,6 +35,12 @@ func TestLocalComposeExec(t *testing.T) {
|
||||
return ret
|
||||
}
|
||||
|
||||
cleanup := func() {
|
||||
c.RunDockerComposeCmd(t, cmdArgs("down", "--timeout=0")...)
|
||||
}
|
||||
cleanup()
|
||||
t.Cleanup(cleanup)
|
||||
|
||||
c.RunDockerComposeCmd(t, cmdArgs("up", "-d")...)
|
||||
|
||||
t.Run("exec true", func(t *testing.T) {
|
||||
|
||||
@@ -281,8 +281,12 @@ func TestStopWithDependenciesAttached(t *testing.T) {
|
||||
const projectName = "compose-e2e-stop-with-deps"
|
||||
c := NewParallelCLI(t, WithEnv("COMMAND=echo hello"))
|
||||
|
||||
t.Run("up", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/dependencies/compose.yaml", "-p", projectName, "up", "--attach-dependencies", "foo")
|
||||
res.Assert(t, icmd.Expected{Out: "exited with code 0"})
|
||||
})
|
||||
cleanup := func() {
|
||||
c.RunDockerComposeCmd(t, "-p", projectName, "down", "--remove-orphans", "--timeout=0")
|
||||
}
|
||||
cleanup()
|
||||
t.Cleanup(cleanup)
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/dependencies/compose.yaml", "-p", projectName, "up", "--attach-dependencies", "foo")
|
||||
res.Assert(t, icmd.Expected{Out: "exited with code 0"})
|
||||
}
|
||||
|
||||
@@ -51,8 +51,18 @@ func TestUpExitCodeFrom(t *testing.T) {
|
||||
c := NewParallelCLI(t)
|
||||
const projectName = "e2e-exit-code-from"
|
||||
|
||||
res := c.RunDockerComposeCmdNoCheck(t, "-f", "fixtures/start-fail/start-depends_on-long-lived.yaml", "--project-name", projectName, "up", "--exit-code-from=failure", "failure")
|
||||
res.Assert(t, icmd.Expected{ExitCode: 42})
|
||||
|
||||
c.RunDockerComposeCmd(t, "--project-name", projectName, "down", "--remove-orphans")
|
||||
}
|
||||
|
||||
func TestUpExitCodeFromContainerKilled(t *testing.T) {
|
||||
c := NewParallelCLI(t)
|
||||
const projectName = "e2e-exit-code-from-kill"
|
||||
|
||||
res := c.RunDockerComposeCmdNoCheck(t, "-f", "fixtures/start-fail/start-depends_on-long-lived.yaml", "--project-name", projectName, "up", "--exit-code-from=test")
|
||||
res.Assert(t, icmd.Expected{ExitCode: 137})
|
||||
res.Assert(t, icmd.Expected{ExitCode: 143})
|
||||
|
||||
c.RunDockerComposeCmd(t, "--project-name", projectName, "down", "--remove-orphans")
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
services:
|
||||
base:
|
||||
image: base
|
||||
init: true
|
||||
build:
|
||||
context: .
|
||||
dockerfile: base.dockerfile
|
||||
service:
|
||||
init: true
|
||||
depends_on:
|
||||
- base
|
||||
build:
|
||||
|
||||
@@ -4,6 +4,7 @@ services:
|
||||
command: echo 'hello world'
|
||||
longrunning:
|
||||
image: alpine
|
||||
init: true
|
||||
depends_on:
|
||||
oneshot:
|
||||
condition: service_completed_successfully
|
||||
|
||||
@@ -3,6 +3,7 @@ services:
|
||||
my-service:
|
||||
image: alpine
|
||||
command: tail -f /dev/null
|
||||
init: true
|
||||
depends_on:
|
||||
nginx: {condition: service_healthy}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
services:
|
||||
foo:
|
||||
image: alpine
|
||||
init: true
|
||||
entrypoint: ["sleep", "600"]
|
||||
networks:
|
||||
default:
|
||||
@@ -9,4 +10,4 @@ networks:
|
||||
default:
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 10.1.0.0/16
|
||||
- subnet: 10.1.0.0/16
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
services:
|
||||
ping:
|
||||
image: alpine
|
||||
init: true
|
||||
command: ping localhost -c ${REPEAT:-1}
|
||||
hello:
|
||||
image: alpine
|
||||
|
||||
@@ -6,12 +6,14 @@ services:
|
||||
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
|
||||
db:
|
||||
image: gtardif/sentences-db
|
||||
init: true
|
||||
networks:
|
||||
- dbnet
|
||||
- closesnetworkname1
|
||||
- closesnetworkname2
|
||||
words:
|
||||
image: gtardif/sentences-api
|
||||
init: true
|
||||
ports:
|
||||
- "8080:8080"
|
||||
networks:
|
||||
@@ -19,6 +21,7 @@ services:
|
||||
- servicenet
|
||||
web:
|
||||
image: gtardif/sentences-web
|
||||
init: true
|
||||
ports:
|
||||
- "80:80"
|
||||
labels:
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
services:
|
||||
with-restart:
|
||||
image: alpine
|
||||
init: true
|
||||
command: tail -f /dev/null
|
||||
depends_on:
|
||||
nginx: {condition: service_healthy, restart: true}
|
||||
|
||||
no-restart:
|
||||
image: alpine
|
||||
init: true
|
||||
command: tail -f /dev/null
|
||||
depends_on:
|
||||
nginx: { condition: service_healthy }
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
services:
|
||||
restart:
|
||||
image: alpine
|
||||
init: true
|
||||
command: ash -c "if [[ -f /tmp/restart.lock ]] ; then sleep infinity; else touch /tmp/restart.lock; fi"
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
services:
|
||||
db:
|
||||
image: gtardif/sentences-db
|
||||
init: true
|
||||
words:
|
||||
image: gtardif/sentences-api
|
||||
init: true
|
||||
ports:
|
||||
- "95:8080"
|
||||
web:
|
||||
image: gtardif/sentences-web
|
||||
init: true
|
||||
ports:
|
||||
- "90:80"
|
||||
labels:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
services:
|
||||
fail:
|
||||
image: alpine
|
||||
init: true
|
||||
command: sleep infinity
|
||||
healthcheck:
|
||||
test: "false"
|
||||
@@ -8,6 +9,7 @@ services:
|
||||
retries: 3
|
||||
depends:
|
||||
image: alpine
|
||||
init: true
|
||||
command: sleep infinity
|
||||
depends_on:
|
||||
fail:
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
services:
|
||||
safe:
|
||||
image: 'alpine'
|
||||
init: true
|
||||
command: ['/bin/sh', '-c', 'sleep infinity'] # never exiting
|
||||
failure:
|
||||
image: 'alpine'
|
||||
command: ['/bin/sh', '-c', 'sleep 2 ; echo "exiting" ; exit 42']
|
||||
init: true
|
||||
command: ['/bin/sh', '-c', 'sleep 1 ; echo "exiting with error" ; exit 42']
|
||||
test:
|
||||
image: 'alpine'
|
||||
init: true
|
||||
command: ['/bin/sh', '-c', 'sleep 99999 ; echo "tests are OK"'] # very long job
|
||||
depends_on: [safe]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
services:
|
||||
stderr:
|
||||
image: alpine
|
||||
init: true
|
||||
command: /bin/ash /log_to_stderr.sh
|
||||
volumes:
|
||||
- ./log_to_stderr.sh:/log_to_stderr.sh
|
||||
|
||||
34
pkg/e2e/fixtures/watch/compose.yaml
Normal file
34
pkg/e2e/fixtures/watch/compose.yaml
Normal file
@@ -0,0 +1,34 @@
|
||||
x-dev: &x-dev
|
||||
watch:
|
||||
- action: sync
|
||||
path: ./data
|
||||
target: /app/data
|
||||
ignore:
|
||||
- '*.foo'
|
||||
- ./ignored
|
||||
|
||||
services:
|
||||
alpine:
|
||||
build:
|
||||
dockerfile_inline: |-
|
||||
FROM alpine
|
||||
RUN mkdir -p /app/data
|
||||
init: true
|
||||
command: sleep infinity
|
||||
x-develop: *x-dev
|
||||
busybox:
|
||||
build:
|
||||
dockerfile_inline: |-
|
||||
FROM busybox
|
||||
RUN mkdir -p /app/data
|
||||
init: true
|
||||
command: sleep infinity
|
||||
x-develop: *x-dev
|
||||
debian:
|
||||
build:
|
||||
dockerfile_inline: |-
|
||||
FROM debian
|
||||
RUN mkdir -p /app/data
|
||||
init: true
|
||||
command: sleep infinity
|
||||
x-develop: *x-dev
|
||||
1
pkg/e2e/fixtures/watch/data/hello.txt
Normal file
1
pkg/e2e/fixtures/watch/data/hello.txt
Normal file
@@ -0,0 +1 @@
|
||||
hello world
|
||||
184
pkg/e2e/watch_test.go
Normal file
184
pkg/e2e/watch_test.go
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
Copyright 2023 Docker Compose CLI authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
|
||||
"github.com/distribution/distribution/v3/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gotest.tools/v3/assert"
|
||||
"gotest.tools/v3/assert/cmp"
|
||||
"gotest.tools/v3/icmd"
|
||||
"gotest.tools/v3/poll"
|
||||
)
|
||||
|
||||
func TestWatch(t *testing.T) {
|
||||
services := []string{"alpine", "busybox", "debian"}
|
||||
for _, svcName := range services {
|
||||
t.Run(svcName, func(t *testing.T) {
|
||||
t.Helper()
|
||||
doTest(t, svcName)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: these tests all share a single Compose file but are safe to run concurrently
|
||||
func doTest(t *testing.T, svcName string) {
|
||||
tmpdir := t.TempDir()
|
||||
dataDir := filepath.Join(tmpdir, "data")
|
||||
writeDataFile := func(name string, contents string) {
|
||||
t.Helper()
|
||||
dest := filepath.Join(dataDir, name)
|
||||
require.NoError(t, os.MkdirAll(filepath.Dir(dest), 0o700))
|
||||
t.Logf("writing %q to %q", contents, dest)
|
||||
require.NoError(t, os.WriteFile(dest, []byte(contents+"\n"), 0o600))
|
||||
}
|
||||
|
||||
composeFilePath := filepath.Join(tmpdir, "compose.yaml")
|
||||
CopyFile(t, filepath.Join("fixtures", "watch", "compose.yaml"), composeFilePath)
|
||||
|
||||
projName := "e2e-watch-" + svcName
|
||||
env := []string{
|
||||
"COMPOSE_FILE=" + composeFilePath,
|
||||
"COMPOSE_PROJECT_NAME=" + projName,
|
||||
}
|
||||
|
||||
cli := NewParallelCLI(t, WithEnv(env...))
|
||||
|
||||
cleanup := func() {
|
||||
cli.RunDockerComposeCmd(t, "down", svcName, "--timeout=0", "--remove-orphans", "--volumes")
|
||||
}
|
||||
cleanup()
|
||||
t.Cleanup(cleanup)
|
||||
|
||||
cli.RunDockerComposeCmd(t, "up", svcName, "--wait", "--build")
|
||||
|
||||
cmd := cli.NewDockerComposeCmd(t, "--verbose", "alpha", "watch", svcName)
|
||||
// stream output since watch runs in the background
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
r := icmd.StartCmd(cmd)
|
||||
require.NoError(t, r.Error)
|
||||
t.Cleanup(func() {
|
||||
// IMPORTANT: watch doesn't exit on its own, don't leak processes!
|
||||
if r.Cmd.Process != nil {
|
||||
_ = r.Cmd.Process.Kill()
|
||||
}
|
||||
})
|
||||
var testComplete atomic.Bool
|
||||
go func() {
|
||||
// if the process exits abnormally before the test is done, fail the test
|
||||
if err := r.Cmd.Wait(); err != nil && !testComplete.Load() {
|
||||
assert.Check(t, cmp.Nil(err))
|
||||
}
|
||||
}()
|
||||
|
||||
require.NoError(t, os.Mkdir(dataDir, 0o700))
|
||||
|
||||
checkFileContents := func(path string, contents string) poll.Check {
|
||||
return func(pollLog poll.LogT) poll.Result {
|
||||
if r.Cmd.ProcessState != nil {
|
||||
return poll.Error(fmt.Errorf("watch process exited early: %s", r.Cmd.ProcessState))
|
||||
}
|
||||
res := icmd.RunCmd(cli.NewDockerComposeCmd(t, "exec", svcName, "cat", path))
|
||||
if strings.Contains(res.Stdout(), contents) {
|
||||
return poll.Success()
|
||||
}
|
||||
return poll.Continue(res.Combined())
|
||||
}
|
||||
}
|
||||
|
||||
waitForFlush := func() {
|
||||
sentinelVal := uuid.Generate().String()
|
||||
writeDataFile("wait.txt", sentinelVal)
|
||||
poll.WaitOn(t, checkFileContents("/app/data/wait.txt", sentinelVal))
|
||||
}
|
||||
|
||||
t.Logf("Writing to a file until Compose watch is up and running")
|
||||
poll.WaitOn(t, func(t poll.LogT) poll.Result {
|
||||
writeDataFile("hello.txt", "hello world")
|
||||
return checkFileContents("/app/data/hello.txt", "hello world")(t)
|
||||
})
|
||||
|
||||
t.Logf("Modifying file contents")
|
||||
writeDataFile("hello.txt", "hello watch")
|
||||
poll.WaitOn(t, checkFileContents("/app/data/hello.txt", "hello watch"))
|
||||
|
||||
t.Logf("Deleting file")
|
||||
require.NoError(t, os.Remove(filepath.Join(dataDir, "hello.txt")))
|
||||
waitForFlush()
|
||||
cli.RunDockerComposeCmdNoCheck(t, "exec", svcName, "stat", "/app/data/hello.txt").
|
||||
Assert(t, icmd.Expected{
|
||||
ExitCode: 1,
|
||||
Err: "No such file or directory",
|
||||
},
|
||||
)
|
||||
|
||||
t.Logf("Writing to ignored paths")
|
||||
writeDataFile("data.foo", "ignored")
|
||||
writeDataFile(filepath.Join("ignored", "hello.txt"), "ignored")
|
||||
waitForFlush()
|
||||
cli.RunDockerComposeCmdNoCheck(t, "exec", svcName, "stat", "/app/data/data.foo").
|
||||
Assert(t, icmd.Expected{
|
||||
ExitCode: 1,
|
||||
Err: "No such file or directory",
|
||||
},
|
||||
)
|
||||
cli.RunDockerComposeCmdNoCheck(t, "exec", svcName, "stat", "/app/data/ignored").
|
||||
Assert(t, icmd.Expected{
|
||||
ExitCode: 1,
|
||||
Err: "No such file or directory",
|
||||
},
|
||||
)
|
||||
|
||||
t.Logf("Creating subdirectory")
|
||||
require.NoError(t, os.Mkdir(filepath.Join(dataDir, "subdir"), 0o700))
|
||||
waitForFlush()
|
||||
cli.RunDockerComposeCmd(t, "exec", svcName, "stat", "/app/data/subdir")
|
||||
|
||||
t.Logf("Writing to file in subdirectory")
|
||||
writeDataFile(filepath.Join("subdir", "file.txt"), "a")
|
||||
poll.WaitOn(t, checkFileContents("/app/data/subdir/file.txt", "a"))
|
||||
|
||||
t.Logf("Writing to file multiple times")
|
||||
writeDataFile(filepath.Join("subdir", "file.txt"), "x")
|
||||
writeDataFile(filepath.Join("subdir", "file.txt"), "y")
|
||||
writeDataFile(filepath.Join("subdir", "file.txt"), "z")
|
||||
poll.WaitOn(t, checkFileContents("/app/data/subdir/file.txt", "z"))
|
||||
writeDataFile(filepath.Join("subdir", "file.txt"), "z")
|
||||
writeDataFile(filepath.Join("subdir", "file.txt"), "y")
|
||||
writeDataFile(filepath.Join("subdir", "file.txt"), "x")
|
||||
poll.WaitOn(t, checkFileContents("/app/data/subdir/file.txt", "x"))
|
||||
|
||||
t.Logf("Deleting directory")
|
||||
require.NoError(t, os.RemoveAll(filepath.Join(dataDir, "subdir")))
|
||||
waitForFlush()
|
||||
cli.RunDockerComposeCmdNoCheck(t, "exec", svcName, "stat", "/app/data/subdir").
|
||||
Assert(t, icmd.Expected{
|
||||
ExitCode: 1,
|
||||
Err: "No such file or directory",
|
||||
},
|
||||
)
|
||||
|
||||
testComplete.Store(true)
|
||||
}
|
||||
Reference in New Issue
Block a user