Skip to content

Commit 3b9fc71

Browse files
committed
add port indexer to be sure a service port declaration is unique
Signed-off-by: Guillaume Lours <[email protected]>
1 parent d8ca21a commit 3b9fc71

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

override/uncity.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ func init() {
3636
unique["services.*.expose"] = exposeIndexer
3737
unique["services.*.secrets"] = mountIndexer("/run/secrets")
3838
unique["services.*.configs"] = mountIndexer("")
39+
unique["services.*.ports"] = portIndexer
3940
}
4041

4142
// EnforceUnicity removes redefinition of elements declared in a sequence
@@ -136,3 +137,34 @@ func mountIndexer(defaultPath string) indexer {
136137
}
137138
}
138139
}
140+
141+
func portIndexer(y any, p tree.Path) (string, error) {
142+
switch value := y.(type) {
143+
case int:
144+
return strconv.Itoa(value), nil
145+
case map[string]any:
146+
target, ok := value["target"].(int)
147+
if !ok {
148+
return "", fmt.Errorf("service ports %s is missing a target port", p)
149+
}
150+
published, ok := value["published"].(string)
151+
if !ok {
152+
// try to parse it as an int
153+
if pub, ok := value["published"].(int); ok {
154+
published = fmt.Sprintf("%d", pub)
155+
}
156+
}
157+
host, ok := value["host_ip"].(string)
158+
if !ok {
159+
host = "0.0.0.0"
160+
}
161+
protocol, ok := value["protocol"].(string)
162+
if !ok {
163+
protocol = "tcp"
164+
}
165+
return fmt.Sprintf("%s:%s:%d/%s", host, published, target, protocol), nil
166+
case string:
167+
return value, nil
168+
}
169+
return "", nil
170+
}

override/uncity_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,72 @@ services:
6666
`)
6767
}
6868

69+
func Test_PortsShortUnicity(t *testing.T) {
70+
assertUnicity(t, `
71+
services:
72+
test:
73+
image: foo
74+
ports:
75+
- "9080:80"
76+
- "9081:81"
77+
- "9080:80"
78+
- "5000"
79+
- "6060:6060/udp"
80+
- "9080:6060/udp"
81+
`, `
82+
services:
83+
test:
84+
image: foo
85+
ports:
86+
- "9080:80"
87+
- "9081:81"
88+
- "5000"
89+
- "6060:6060/udp"
90+
- "9080:6060/udp"
91+
`)
92+
}
93+
94+
func Test_PortsLongtUnicity(t *testing.T) {
95+
assertUnicity(t, `
96+
services:
97+
test:
98+
image: foo
99+
ports:
100+
- target: 80
101+
host_ip: 127.0.0.1
102+
published: "8080"
103+
protocol: tcp
104+
mode: host
105+
- target: 81
106+
published: "8080"
107+
protocol: tcp
108+
- target: 80
109+
host_ip: 127.0.0.2
110+
published: "8080"
111+
protocol: tcp
112+
- target: 81
113+
published: "8080"
114+
protocol: tcp
115+
`, `
116+
services:
117+
test:
118+
image: foo
119+
ports:
120+
- target: 80
121+
host_ip: 127.0.0.1
122+
published: "8080"
123+
protocol: tcp
124+
mode: host
125+
- target: 81
126+
published: "8080"
127+
protocol: tcp
128+
- target: 80
129+
host_ip: 127.0.0.2
130+
published: "8080"
131+
protocol: tcp
132+
`)
133+
}
134+
69135
func assertUnicity(t *testing.T, before string, expected string) {
70136
got, err := EnforceUnicity(unmarshall(t, before))
71137
assert.NilError(t, err)

0 commit comments

Comments
 (0)