Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pkg/compose/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,9 @@ func (s *composeService) startDependencies(ctx context.Context, project *types.P
// passes "never" so an existing dependency is reused as-is
Recreate: options.Recreate,
RecreateDependencies: options.RecreateDependencies,
// a recreated dependency keeps its anonymous volumes, as with `up`:
// run has no --renew-anon-volumes to opt out
Inherit: true,
})
if err != nil {
return err
Expand Down
18 changes: 18 additions & 0 deletions pkg/e2e/compose_run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,24 @@ func TestComposeRunNoRecreate(t *testing.T) {
ServiceState("dep", "running"))
}

func TestComposeRunInheritsAnonymousVolumes(t *testing.T) {
// A dependency whose config-hash diverged is recreated by run like by up,
// but run used to drop its anonymous volumes on the way: the new container
// got a fresh, empty volume, so a database dependency looked wiped. The
// marker is written from the test, not by the container itself, so a fresh
// volume cannot pass the check by writing it again.
NewScenario(t, "run must keep the anonymous volumes of a dependency it recreates, as up does").
Step("run creates and starts the dependency",
ComposeCmd("run", "task").WithEnv("TAG=one"),
ServiceState("dep", "running")).
Step("data lands in the dependency's anonymous volume",
ComposeCmd("exec", "dep", "sh", "-c", "echo kept > /data/marker")).
Step("a diverged dependency recreated by run still sees that data",
ComposeCmd("run", "task").WithEnv("TAG=two", "COMPOSE_IGNORE_ORPHANS=True"),
Recreated("dep"),
ExecOutputContains("dep", "cat /data/marker", "kept"))
}

func TestComposeRunNotRequiredDeps(t *testing.T) {
NewScenario(t, "run must skip a dependency marked required: false when its profile is inactive").
Step("run executes the service without materializing the optional dependency",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
services:
task:
image: alpine
command: echo "task done"
depends_on:
- dep
dep:
image: alpine
init: true
command: sleep infinity
volumes:
# anonymous volume: no source, so it lives and dies with the container
# unless carried over on recreate
- /data
environment:
# divergence vector: changing TAG between invocations changes the
# config-hash of dep, which the default policy answers by recreating
TAG: ${TAG:-initial}
Loading