Skip to content

Commit ced6565

Browse files
ndeloofglours
authored andcommitted
normalization creates implicit default network only when used by some service
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent 8472f87 commit ced6565

File tree

2 files changed

+101
-13
lines changed

2 files changed

+101
-13
lines changed

loader/normalize.go

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,12 @@ import (
2626

2727
// Normalize compose project by moving deprecated attributes to their canonical position and injecting implicit defaults
2828
func Normalize(dict map[string]any, env types.Mapping) (map[string]any, error) {
29-
dict["networks"] = normalizeNetworks(dict)
29+
normalizeNetworks(dict)
3030

3131
if d, ok := dict["services"]; ok {
3232
services := d.(map[string]any)
3333
for name, s := range services {
3434
service := s.(map[string]any)
35-
_, hasNetworks := service["networks"]
36-
_, hasNetworkMode := service["network_mode"]
37-
if !hasNetworks && !hasNetworkMode {
38-
// Service without explicit network attachment are implicitly exposed on default network
39-
service["networks"] = map[string]any{"default": nil}
40-
}
4135

4236
if service["pull_policy"] == types.PullPolicyIfNotPresent {
4337
service["pull_policy"] = types.PullPolicyMissing
@@ -137,18 +131,51 @@ func Normalize(dict map[string]any, env types.Mapping) (map[string]any, error) {
137131
return dict, nil
138132
}
139133

140-
func normalizeNetworks(dict map[string]any) map[string]any {
134+
func normalizeNetworks(dict map[string]any) {
141135
var networks map[string]any
142136
if n, ok := dict["networks"]; ok {
143137
networks = n.(map[string]any)
144138
} else {
145139
networks = map[string]any{}
146140
}
147-
if _, ok := networks["default"]; !ok {
141+
142+
// implicit `default` network must be introduced only if actually used by some service
143+
usesDefaultNetwork := false
144+
145+
if s, ok := dict["services"]; ok {
146+
services := s.(map[string]any)
147+
for name, se := range services {
148+
service := se.(map[string]any)
149+
if _, ok := service["network_mode"]; ok {
150+
continue
151+
}
152+
if n, ok := service["networks"]; !ok {
153+
// If none explicitly declared, service is connected to default network
154+
service["networks"] = map[string]any{"default": nil}
155+
usesDefaultNetwork = true
156+
} else {
157+
net := n.(map[string]any)
158+
if len(net) == 0 {
159+
// networks section declared but empty (corner case)
160+
service["networks"] = map[string]any{"default": nil}
161+
usesDefaultNetwork = true
162+
} else if _, ok := net["default"]; ok {
163+
usesDefaultNetwork = true
164+
}
165+
}
166+
services[name] = service
167+
}
168+
dict["services"] = services
169+
}
170+
171+
if _, ok := networks["default"]; !ok && usesDefaultNetwork {
148172
// If not declared explicitly, Compose model involves an implicit "default" network
149173
networks["default"] = nil
150174
}
151-
return networks
175+
176+
if len(networks) > 0 {
177+
dict["networks"] = networks
178+
}
152179
}
153180

154181
func resolve(a any, fn func(s string) (string, bool)) (any, bool) {

loader/normalize_test.go

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,6 @@ volumes:
8888

8989
expected := `
9090
name: myProject
91-
networks:
92-
default:
93-
name: myProject_default
9491
volumes:
9592
myExternalVol:
9693
name: myExternalVol
@@ -275,3 +272,67 @@ networks:
275272
assert.NilError(t, err)
276273
assert.DeepEqual(t, expect, model)
277274
}
275+
276+
func TestNormalizeDefaultNetwork(t *testing.T) {
277+
project := `
278+
name: myProject
279+
services:
280+
test:
281+
image: test
282+
`
283+
284+
expected := `
285+
name: myProject
286+
networks:
287+
default:
288+
name: myProject_default
289+
services:
290+
test:
291+
image: test
292+
networks:
293+
default: null
294+
`
295+
var model map[string]any
296+
err := yaml.Unmarshal([]byte(project), &model)
297+
assert.NilError(t, err)
298+
model, err = Normalize(model, nil)
299+
assert.NilError(t, err)
300+
301+
var expect map[string]any
302+
err = yaml.Unmarshal([]byte(expected), &expect)
303+
assert.NilError(t, err)
304+
assert.DeepEqual(t, expect, model)
305+
}
306+
307+
func TestNormalizeCustomNetwork(t *testing.T) {
308+
project := `
309+
name: myProject
310+
services:
311+
test:
312+
networks:
313+
my_network: null
314+
networks:
315+
my_network: null
316+
`
317+
318+
expected := `
319+
name: myProject
320+
networks:
321+
my_network:
322+
name: myProject_my_network
323+
services:
324+
test:
325+
networks:
326+
my_network: null
327+
`
328+
var model map[string]any
329+
err := yaml.Unmarshal([]byte(project), &model)
330+
assert.NilError(t, err)
331+
model, err = Normalize(model, nil)
332+
assert.NilError(t, err)
333+
334+
var expect map[string]any
335+
err = yaml.Unmarshal([]byte(expected), &expect)
336+
assert.NilError(t, err)
337+
assert.DeepEqual(t, expect, model)
338+
}

0 commit comments

Comments
 (0)