فهرست منبع

Use appropriate dependency condition for one-shot containers when running `compose up --wait`

Also add e2e tests to ensure `compose up --wait` does not get stuck forever waiting for one-shot containers

Signed-off-by: Laura Brehm <[email protected]>
Laura Brehm 3 سال پیش
والد
کامیت
fd8538f780
3فایلهای تغییر یافته به همراه73 افزوده شده و 1 حذف شده
  1. 15 1
      pkg/compose/start.go
  2. 47 0
      pkg/e2e/compose_up_test.go
  3. 11 0
      pkg/e2e/fixtures/dependencies/deps-completed-successfully.yaml

+ 15 - 1
pkg/compose/start.go

@@ -80,7 +80,7 @@ func (s *composeService) start(ctx context.Context, projectName string, options
 		depends := types.DependsOnConfig{}
 		for _, s := range project.Services {
 			depends[s.Name] = types.ServiceDependency{
-				Condition: ServiceConditionRunningOrHealthy,
+				Condition: getDependencyCondition(s, project),
 			}
 		}
 		err = s.waitDependencies(ctx, project, depends)
@@ -92,6 +92,20 @@ func (s *composeService) start(ctx context.Context, projectName string, options
 	return eg.Wait()
 }
 
+// getDependencyCondition checks if service is depended on by other services
+// with service_completed_successfully condition, and applies that condition
+// instead, or --wait will never finish waiting for one-shot containers
+func getDependencyCondition(service types.ServiceConfig, project *types.Project) string {
+	for _, services := range project.Services {
+		for dependencyService, dependencyConfig := range services.DependsOn {
+			if dependencyService == service.Name && dependencyConfig.Condition == types.ServiceConditionCompletedSuccessfully {
+				return types.ServiceConditionCompletedSuccessfully
+			}
+		}
+	}
+	return ServiceConditionRunningOrHealthy
+}
+
 type containerWatchFn func(container moby.Container) error
 
 // watchContainers uses engine events to capture container start/die and notify ContainerEventListener

+ 47 - 0
pkg/e2e/compose_up_test.go

@@ -0,0 +1,47 @@
+/*
+   Copyright 2020 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 (
+	"strings"
+	"testing"
+	"time"
+
+	"gotest.tools/v3/assert"
+)
+
+func TestUpWait(t *testing.T) {
+	c := NewParallelCLI(t)
+	const projectName = "e2e-deps-wait"
+
+	timeout := time.After(30 * time.Second)
+	done := make(chan bool)
+	go func() {
+		res := c.RunDockerComposeCmd(t, "-f", "fixtures/dependencies/deps-completed-successfully.yaml", "--project-name", projectName, "up", "--wait", "-d")
+		assert.Assert(t, strings.Contains(res.Combined(), "e2e-deps-wait-oneshot-1"), res.Combined())
+		done <- true
+	}()
+
+	select {
+	case <-timeout:
+		t.Fatal("test did not finish in time")
+	case <-done:
+		break
+	}
+
+	c.RunDockerComposeCmd(t, "--project-name", projectName, "down")
+}

+ 11 - 0
pkg/e2e/fixtures/dependencies/deps-completed-successfully.yaml

@@ -0,0 +1,11 @@
+version: '3'
+services:
+  oneshot:
+    image: ubuntu
+    command: echo 'hello world'
+  longrunning:
+    image: ubuntu
+    depends_on:
+      oneshot:
+        condition: service_completed_successfully
+    command: sleep infinity