Skip to content

Commit c5cb8b2

Browse files
authored
Merge pull request #350 from ndeloof/depends_on_restart
introduce `restart` for depends_on
2 parents b16c6a1 + 6bce3b9 commit c5cb8b2

File tree

6 files changed

+117
-38
lines changed

6 files changed

+117
-38
lines changed

loader/loader.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
233233
}
234234

235235
if !opts.SkipNormalization {
236-
err = normalize(project, opts.ResolvePaths)
236+
err = Normalize(project, opts.ResolvePaths)
237237
if err != nil {
238238
return nil, err
239239
}

loader/loader_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ services:
783783
build:
784784
context: ./web
785785
links:
786-
- bar
786+
- db
787787
pid: host
788788
db:
789789
image: db
@@ -837,7 +837,7 @@ services:
837837
image: web
838838
build: .
839839
links:
840-
- bar
840+
- db
841841
db:
842842
image: db
843843
build:

loader/normalize.go

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,16 @@ import (
2020
"fmt"
2121
"os"
2222
"path/filepath"
23+
"strings"
2324

2425
"github.com/compose-spec/compose-go/errdefs"
2526
"github.com/compose-spec/compose-go/types"
2627
"github.com/pkg/errors"
2728
"github.com/sirupsen/logrus"
2829
)
2930

30-
// normalize compose project by moving deprecated attributes to their canonical position and injecting implicit defaults
31-
func normalize(project *types.Project, resolvePaths bool) error {
31+
// Normalize compose project by moving deprecated attributes to their canonical position and injecting implicit defaults
32+
func Normalize(project *types.Project, resolvePaths bool) error {
3233
absWorkingDir, err := filepath.Abs(project.WorkingDir)
3334
if err != nil {
3435
return err
@@ -95,6 +96,37 @@ func normalize(project *types.Project, resolvePaths bool) error {
9596
s.Extends["file"] = &p
9697
}
9798

99+
for _, link := range s.Links {
100+
parts := strings.Split(link, ":")
101+
if len(parts) == 2 {
102+
link = parts[0]
103+
}
104+
s.DependsOn = setIfMissing(s.DependsOn, link, types.ServiceDependency{
105+
Condition: types.ServiceConditionStarted,
106+
Restart: true,
107+
})
108+
}
109+
110+
for _, namespace := range []string{s.NetworkMode, s.Ipc, s.Pid, s.Uts, s.Cgroup} {
111+
if strings.HasPrefix(namespace, types.ServicePrefix) {
112+
name := namespace[len(types.ServicePrefix):]
113+
s.DependsOn = setIfMissing(s.DependsOn, name, types.ServiceDependency{
114+
Condition: types.ServiceConditionStarted,
115+
Restart: true,
116+
})
117+
}
118+
}
119+
120+
for _, vol := range s.VolumesFrom {
121+
if !strings.HasPrefix(s.Pid, types.ContainerPrefix) {
122+
spec := strings.Split(vol, ":")
123+
s.DependsOn = setIfMissing(s.DependsOn, spec[0], types.ServiceDependency{
124+
Condition: types.ServiceConditionStarted,
125+
Restart: false,
126+
})
127+
}
128+
}
129+
98130
err := relocateLogDriver(&s)
99131
if err != nil {
100132
return err
@@ -131,9 +163,20 @@ func normalize(project *types.Project, resolvePaths bool) error {
131163
return nil
132164
}
133165

166+
// setIfMissing adds a ServiceDependency for service if not already defined
167+
func setIfMissing(d types.DependsOnConfig, service string, dep types.ServiceDependency) types.DependsOnConfig {
168+
if d == nil {
169+
d = types.DependsOnConfig{}
170+
}
171+
if _, ok := d[service]; !ok {
172+
d[service] = dep
173+
}
174+
return d
175+
}
176+
134177
func relocateScale(s *types.ServiceConfig) error {
135178
scale := uint64(s.Scale)
136-
if scale != 1 {
179+
if scale > 1 {
137180
logrus.Warn("`scale` is deprecated. Use the `deploy.replicas` element")
138181
if s.Deploy == nil {
139182
s.Deploy = &types.DeployConfig{}

loader/normalize_test.go

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ networks:
8282
mynet:
8383
name: myProject_mynet
8484
`
85-
err := normalize(&project, false)
85+
err := Normalize(&project, false)
8686
assert.NilError(t, err)
8787
marshal, err := yaml.Marshal(project)
8888
assert.NilError(t, err)
@@ -118,7 +118,7 @@ networks:
118118
default:
119119
name: myProject_default
120120
`, filepath.Join(wd, "testdata"))
121-
err := normalize(&project, true)
121+
err := Normalize(&project, true)
122122
assert.NilError(t, err)
123123
marshal, err := yaml.Marshal(project)
124124
assert.NilError(t, err)
@@ -142,7 +142,7 @@ func TestNormalizeAbsolutePaths(t *testing.T) {
142142
WorkingDir: absWorkingDir,
143143
ComposeFiles: []string{absComposeFile, absOverrideFile},
144144
}
145-
err := normalize(&project, false)
145+
err := Normalize(&project, false)
146146
assert.NilError(t, err)
147147
assert.DeepEqual(t, expected, project)
148148
}
@@ -180,7 +180,65 @@ func TestNormalizeVolumes(t *testing.T) {
180180
WorkingDir: absCwd,
181181
ComposeFiles: []string{},
182182
}
183-
err := normalize(&project, false)
183+
err := Normalize(&project, false)
184184
assert.NilError(t, err)
185185
assert.DeepEqual(t, expected, project)
186186
}
187+
188+
func TestNormalizeDependsOn(t *testing.T) {
189+
project := types.Project{
190+
Name: "myProject",
191+
Networks: types.Networks{},
192+
Volumes: types.Volumes{},
193+
Services: []types.ServiceConfig{
194+
{
195+
Name: "foo",
196+
DependsOn: map[string]types.ServiceDependency{
197+
"bar": { // explicit depends_on never should be overridden
198+
Condition: types.ServiceConditionHealthy,
199+
Restart: false,
200+
},
201+
},
202+
NetworkMode: "service:zot",
203+
},
204+
{
205+
Name: "bar",
206+
VolumesFrom: []string{"zot"},
207+
},
208+
{
209+
Name: "zot",
210+
},
211+
},
212+
}
213+
214+
expected := `name: myProject
215+
services:
216+
bar:
217+
depends_on:
218+
zot:
219+
condition: service_started
220+
networks:
221+
default: null
222+
volumes_from:
223+
- zot
224+
foo:
225+
depends_on:
226+
bar:
227+
condition: service_healthy
228+
zot:
229+
condition: service_started
230+
restart: true
231+
network_mode: service:zot
232+
zot:
233+
networks:
234+
default: null
235+
networks:
236+
default:
237+
name: myProject_default
238+
`
239+
err := Normalize(&project, true)
240+
assert.NilError(t, err)
241+
marshal, err := yaml.Marshal(project)
242+
assert.NilError(t, err)
243+
assert.DeepEqual(t, expected, string(marshal))
244+
}

schema/compose-spec.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@
181181
"type": "object",
182182
"additionalProperties": false,
183183
"properties": {
184+
"restart": {"type": "boolean"},
184185
"condition": {
185186
"type": "string",
186187
"enum": ["service_started", "service_healthy", "service_completed_successfully"]

types/types.go

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -256,35 +256,11 @@ const (
256256

257257
// GetDependencies retrieve all services this service depends on
258258
func (s ServiceConfig) GetDependencies() []string {
259-
dependencies := make(set)
260-
for dependency := range s.DependsOn {
261-
dependencies.append(dependency)
262-
}
263-
for _, link := range s.Links {
264-
parts := strings.Split(link, ":")
265-
if len(parts) == 2 {
266-
dependencies.append(parts[0])
267-
} else {
268-
dependencies.append(link)
269-
}
270-
}
271-
if strings.HasPrefix(s.NetworkMode, ServicePrefix) {
272-
dependencies.append(s.NetworkMode[len(ServicePrefix):])
273-
}
274-
if strings.HasPrefix(s.Ipc, ServicePrefix) {
275-
dependencies.append(s.Ipc[len(ServicePrefix):])
259+
var dependencies []string
260+
for service := range s.DependsOn {
261+
dependencies = append(dependencies, service)
276262
}
277-
if strings.HasPrefix(s.Pid, ServicePrefix) {
278-
dependencies.append(s.Pid[len(ServicePrefix):])
279-
}
280-
for _, vol := range s.VolumesFrom {
281-
if !strings.HasPrefix(s.Pid, ContainerPrefix) {
282-
spec := strings.Split(vol, ":")
283-
dependencies.append(spec[0])
284-
}
285-
}
286-
287-
return dependencies.toSlice()
263+
return dependencies
288264
}
289265

290266
type set map[string]struct{}
@@ -1007,6 +983,7 @@ type DependsOnConfig map[string]ServiceDependency
1007983

1008984
type ServiceDependency struct {
1009985
Condition string `yaml:",omitempty" json:"condition,omitempty"`
986+
Restart bool `yaml:",omitempty" json:"restart,omitempty"`
1010987
Extensions map[string]interface{} `yaml:",inline" json:"-"`
1011988
}
1012989

0 commit comments

Comments
 (0)