Skip to content

Commit 867e842

Browse files
authored
Handle string ports in docker compose v2 config yaml (#748)
docker-compose v2.3.x changed some ports in `docker-compose config` from int to string. Handle both cases.
1 parent 2a298f8 commit 867e842

File tree

2 files changed

+52
-5
lines changed

2 files changed

+52
-5
lines changed

internal/compose/compose.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,20 @@ type portMapping struct {
5454
Protocol string
5555
}
5656

57+
type intOrStringYaml int
58+
59+
func (p *intOrStringYaml) UnmarshalYAML(node *yaml.Node) error {
60+
var s string
61+
err := node.Decode(&s)
62+
if err == nil {
63+
i, err := strconv.Atoi(s)
64+
*p = intOrStringYaml(i)
65+
return err
66+
}
67+
68+
return node.Decode(p)
69+
}
70+
5771
// UnmarshalYAML unmarshals a Docker Compose port mapping in YAML to
5872
// a portMapping.
5973
func (p *portMapping) UnmarshalYAML(node *yaml.Node) error {
@@ -67,18 +81,18 @@ func (p *portMapping) UnmarshalYAML(node *yaml.Node) error {
6781
}
6882

6983
var s struct {
70-
HostIP string `yaml:"host_ip"`
71-
Target int
72-
Published int
84+
HostIP string `yaml:"host_ip"`
85+
Target intOrStringYaml // Docker compose v2 can define ports as strings.
86+
Published intOrStringYaml // Docker compose v2 can define ports as strings.
7387
Protocol string
7488
}
7589

7690
if err := yaml.Unmarshal(b, &s); err != nil {
7791
return errors.Wrap(err, "could not unmarshal YAML map node")
7892
}
7993

80-
p.InternalPort = s.Target
81-
p.ExternalPort = s.Published
94+
p.InternalPort = int(s.Target)
95+
p.ExternalPort = int(s.Published)
8296
p.Protocol = s.Protocol
8397
p.ExternalIP = s.HostIP
8498
return nil

internal/compose/compose_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
// or more contributor license agreements. Licensed under the Elastic License;
3+
// you may not use this file except in compliance with the Elastic License.
4+
5+
package compose
6+
7+
import (
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
12+
"gopkg.in/yaml.v3"
13+
)
14+
15+
func TestIntOrStringYaml(t *testing.T) {
16+
cases := []struct {
17+
yaml string
18+
expected int
19+
}{
20+
{`"9200"`, 9200},
21+
{`'9200'`, 9200},
22+
{`9200`, 9200},
23+
}
24+
25+
for _, c := range cases {
26+
t.Run(c.yaml, func(t *testing.T) {
27+
var n intOrStringYaml
28+
err := yaml.Unmarshal([]byte(c.yaml), &n)
29+
require.NoError(t, err)
30+
assert.Equal(t, c.expected, int(n))
31+
})
32+
}
33+
}

0 commit comments

Comments
 (0)