Skip to content

Commit 8cf4eef

Browse files
pstibranypracucci
andauthored
Fix docker port parsing in integration tests (#4103) (#4131)
* Fix docker port parsing in integration tests Signed-off-by: Marco Pracucci <[email protected]> * Fixed linter Signed-off-by: Marco Pracucci <[email protected]> Co-authored-by: Marco Pracucci <[email protected]>
1 parent 4afaa35 commit 8cf4eef

File tree

2 files changed

+47
-11
lines changed

2 files changed

+47
-11
lines changed

integration/e2e/service.go

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ import (
2121
)
2222

2323
var (
24-
dockerPortPattern = regexp.MustCompile(`^.*:(\d+)$`)
25-
errMissingMetric = errors.New("metric not found")
24+
dockerIPv4PortPattern = regexp.MustCompile(`^\d+\.\d+\.\d+\.\d+:(\d+)$`)
25+
errMissingMetric = errors.New("metric not found")
2626
)
2727

2828
// ConcreteService represents microservice with optional ports which will be discoverable from docker
@@ -118,7 +118,6 @@ func (s *ConcreteService) Start(networkName, sharedDir string) (err error) {
118118
// Get the dynamic local ports mapped to the container.
119119
for _, containerPort := range s.networkPorts {
120120
var out []byte
121-
var localPort int
122121

123122
out, err = RunCommandAndGetOutput("docker", "port", s.containerName(), strconv.Itoa(containerPort))
124123
if err != nil {
@@ -129,18 +128,14 @@ func (s *ConcreteService) Start(networkName, sharedDir string) (err error) {
129128
return errors.Wrapf(err, "unable to get mapping for port %d; service: %s; output: %q", containerPort, s.name, out)
130129
}
131130

132-
stdout := strings.TrimSpace(string(out))
133-
matches := dockerPortPattern.FindStringSubmatch(stdout)
134-
if len(matches) != 2 {
135-
return fmt.Errorf("unable to get mapping for port %d (output: %s); service: %s", containerPort, stdout, s.name)
136-
}
137-
138-
localPort, err = strconv.Atoi(matches[1])
131+
localPort, err := parseDockerIPv4Port(string(out))
139132
if err != nil {
140-
return errors.Wrapf(err, "unable to get mapping for port %d; service: %s", containerPort, s.name)
133+
return errors.Wrapf(err, "unable to get mapping for port %d (output: %s); service: %s", containerPort, string(out), s.name)
141134
}
135+
142136
s.networkPortsContainerToLocal[containerPort] = localPort
143137
}
138+
144139
logger.Log("Ports for container:", s.containerName(), "Mapping:", s.networkPortsContainerToLocal)
145140
return nil
146141
}
@@ -668,3 +663,26 @@ func (s *HTTPService) WaitRemovedMetric(metricName string, opts ...MetricsOption
668663

669664
return fmt.Errorf("the metric %s is still exported by %s", metricName, s.name)
670665
}
666+
667+
// parseDockerIPv4Port parses the input string which is expected to be the output of "docker port"
668+
// command and returns the first IPv4 port found.
669+
func parseDockerIPv4Port(out string) (int, error) {
670+
// The "docker port" output may be multiple lines if both IPv4 and IPv6 are supported,
671+
// so we need to parse each line.
672+
for _, line := range strings.Split(out, "\n") {
673+
matches := dockerIPv4PortPattern.FindStringSubmatch(strings.TrimSpace(line))
674+
if len(matches) != 2 {
675+
continue
676+
}
677+
678+
port, err := strconv.Atoi(matches[1])
679+
if err != nil {
680+
continue
681+
}
682+
683+
return port, nil
684+
}
685+
686+
// We've not been able to parse the output format.
687+
return 0, errors.New("unknown output format")
688+
}

integration/e2e/service_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"testing"
1111
"time"
1212

13+
"github.com/stretchr/testify/assert"
1314
"github.com/stretchr/testify/require"
1415

1516
"github.com/cortexproject/cortex/pkg/util"
@@ -170,3 +171,20 @@ metric_b 1000
170171
})
171172
require.NoError(t, s.WaitSumMetrics(Equals(math.NaN()), "metric_a"))
172173
}
174+
175+
func TestParseDockerPort(t *testing.T) {
176+
_, err := parseDockerIPv4Port("")
177+
assert.Error(t, err)
178+
179+
actual, err := parseDockerIPv4Port("0.0.0.0:36999")
180+
assert.NoError(t, err)
181+
assert.Equal(t, 36999, actual)
182+
183+
actual, err = parseDockerIPv4Port("0.0.0.0:49155\n:::49156")
184+
assert.NoError(t, err)
185+
assert.Equal(t, 49155, actual)
186+
187+
actual, err = parseDockerIPv4Port(":::49156\n0.0.0.0:49155")
188+
assert.NoError(t, err)
189+
assert.Equal(t, 49155, actual)
190+
}

0 commit comments

Comments
 (0)