Skip to content

Commit de4589d

Browse files
committed
Support compose depends_on with condition: service_completed_successfully
1 parent 623f0a8 commit de4589d

File tree

6 files changed

+55
-8
lines changed

6 files changed

+55
-8
lines changed

internal/app/up/up.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,9 +1127,13 @@ func (u *upRunner) setAppMaxObservedPodStatus(app *app, s podStatus) {
11271127
switch {
11281128
case s == podStatusStarted:
11291129
app.reporterRow.AddStatus(reporter.StatusRunning)
1130-
case s >= podStatusReady:
1130+
case s == podStatusReady:
11311131
app.reporterRow.RemoveStatus(reporter.StatusRunning)
11321132
app.reporterRow.AddStatus(reporter.StatusReady)
1133+
case s >= podStatusCompleted:
1134+
app.reporterRow.RemoveStatus(reporter.StatusRunning)
1135+
app.reporterRow.RemoveStatus(reporter.StatusReady)
1136+
app.reporterRow.AddStatus(reporter.StatusCompleted)
11331137
}
11341138
}
11351139
app.newLogEntry().Debugf("pod status %s", &app.maxObservedPodStatus)
@@ -1159,14 +1163,20 @@ func (u *upRunner) createPodsIfNeeded() error {
11591163
for name, healthiness := range app1.composeService.DockerComposeService.DependsOn {
11601164
composeService := u.cfg.Services[name]
11611165
app2 := u.apps[composeService.Name()]
1162-
if healthiness == dockerComposeConfig.ServiceHealthy {
1166+
switch healthiness {
1167+
case dockerComposeConfig.ServiceHealthy:
11631168
if app2.maxObservedPodStatus != podStatusReady {
11641169
createPod = false
11651170
}
1166-
} else {
1171+
case dockerComposeConfig.ServiceStarted:
11671172
if app2.maxObservedPodStatus != podStatusStarted && app2.maxObservedPodStatus != podStatusReady {
11681173
createPod = false
11691174
}
1175+
case dockerComposeConfig.ServiceCompletedSuccessfully:
1176+
// Note the assumption here is made that podStatusCompleted implies successfully. PRs welcome.
1177+
if app2.maxObservedPodStatus != podStatusCompleted {
1178+
createPod = false
1179+
}
11701180
}
11711181
}
11721182
if createPod {
@@ -1190,10 +1200,13 @@ func (u *upRunner) formatCreatePodReason(app1 *app) string {
11901200
reason.WriteString(", ")
11911201
}
11921202
reason.WriteString(name)
1193-
if healthiness == dockerComposeConfig.ServiceHealthy {
1194-
reason.WriteString(": ready")
1195-
} else {
1203+
switch healthiness {
1204+
case dockerComposeConfig.ServiceStarted:
11961205
reason.WriteString(": running")
1206+
case dockerComposeConfig.ServiceHealthy:
1207+
reason.WriteString(": ready")
1208+
case dockerComposeConfig.ServiceCompletedSuccessfully:
1209+
reason.WriteString(": completed")
11971210
}
11981211
comma = true
11991212
}

internal/app/up/up_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,25 @@ func TestFormatCreatePodReason(t *testing.T) {
130130
t.Error(s)
131131
}
132132
}
133+
134+
func TestFormatCreatePodReasonCompleted(t *testing.T) {
135+
cfg := &config.Config{}
136+
serviceA := cfg.AddService(&dockerComposeConfig.Service{
137+
Name: "a",
138+
})
139+
cfg.AddService(&dockerComposeConfig.Service{
140+
Name: "b",
141+
})
142+
serviceA.DockerComposeService.DependsOn = map[string]dockerComposeConfig.ServiceHealthiness{}
143+
serviceA.DockerComposeService.DependsOn["b"] = dockerComposeConfig.ServiceCompletedSuccessfully
144+
145+
u := &upRunner{
146+
cfg: cfg,
147+
}
148+
u.initApps()
149+
appA := u.apps["a"]
150+
s := u.formatCreatePodReason(appA)
151+
if s != "all depends_on conditions satisfied (b: completed)" {
152+
t.Error(s)
153+
}
154+
}

internal/pkg/progress/reporter/reporter.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ var (
5757
TextWidth: 8,
5858
Priority: 3,
5959
}
60+
StatusCompleted = &Status{
61+
Text: "completed ✅", // checkmark
62+
TextWidth: 12,
63+
Priority: 4,
64+
}
6065
)
6166

6267
type Status struct {

pkg/docker/compose/config/parse.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ func (t *dependsOn) Decode(into mapdecode.Into) error {
9898
t.Values[service] = ServiceHealthy
9999
case "service_started":
100100
t.Values[service] = ServiceStarted
101+
case "service_completed_successfully":
102+
t.Values[service] = ServiceCompletedSuccessfully
101103
default:
102104
return fmt.Errorf("depends_on map contains an entry with an invalid condition: %s", obj.Condition)
103105
}

pkg/docker/compose/config/parse_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,9 @@ func TestDependsOnDecode_MapSuccess(t *testing.T) {
270270
"service-bla-2": {
271271
"condition": "service_started",
272272
},
273+
"service-bla-3": {
274+
"condition": "service_completed_successfully",
275+
},
273276
}
274277
var dst dependsOn
275278
err := mapdecode.Decode(&dst, src)
@@ -279,6 +282,7 @@ func TestDependsOnDecode_MapSuccess(t *testing.T) {
279282
if !reflect.DeepEqual(dst.Values, map[string]ServiceHealthiness{
280283
"service-bla-1": ServiceHealthy,
281284
"service-bla-2": ServiceStarted,
285+
"service-bla-3": ServiceCompletedSuccessfully,
282286
}) {
283287
t.Error(dst)
284288
}

pkg/docker/compose/config/service_healthiness.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package config
44
type ServiceHealthiness int
55

66
const (
7-
ServiceStarted ServiceHealthiness = 0
8-
ServiceHealthy ServiceHealthiness = 1
7+
ServiceStarted ServiceHealthiness = 0
8+
ServiceHealthy ServiceHealthiness = 1
9+
ServiceCompletedSuccessfully ServiceHealthiness = 2
910
)

0 commit comments

Comments
 (0)