Browse code

integration-cli: rely less on "docker port" output format

Also re-formatting some lines for readability.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit c6038b488406ca3b7cc62ddcc0438cf678694bf7)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2021/02/12 05:45:16
Showing 4 changed files
... ...
@@ -297,7 +297,7 @@ func waitForExec(c *testing.T, id string) {
297 297
 }
298 298
 
299 299
 func inspectContainer(c *testing.T, id string, out interface{}) {
300
-	resp, body, err := request.Get(fmt.Sprintf("/containers/%s/json", id))
300
+	resp, body, err := request.Get("/containers/" + id + "/json")
301 301
 	assert.NilError(c, err)
302 302
 	defer body.Close()
303 303
 	assert.Equal(c, resp.StatusCode, http.StatusOK)
... ...
@@ -1,8 +1,8 @@
1 1
 package main
2 2
 
3 3
 import (
4
+	"context"
4 5
 	"fmt"
5
-	"net"
6 6
 	"regexp"
7 7
 	"sort"
8 8
 	"strconv"
... ...
@@ -51,7 +51,8 @@ func (s *DockerSuite) TestPortList(c *testing.T) {
51 51
 	err = assertPortList(c, out, []string{
52 52
 		"80/tcp -> 0.0.0.0:9876",
53 53
 		"81/tcp -> 0.0.0.0:9877",
54
-		"82/tcp -> 0.0.0.0:9878"})
54
+		"82/tcp -> 0.0.0.0:9878",
55
+	})
55 56
 	// Port list is not correct
56 57
 	assert.NilError(c, err)
57 58
 
... ...
@@ -78,7 +79,8 @@ func (s *DockerSuite) TestPortList(c *testing.T) {
78 78
 		"80/tcp -> 0.0.0.0:9876",
79 79
 		"80/tcp -> 0.0.0.0:9999",
80 80
 		"81/tcp -> 0.0.0.0:9877",
81
-		"82/tcp -> 0.0.0.0:9878"})
81
+		"82/tcp -> 0.0.0.0:9878",
82
+	})
82 83
 	// Port list is not correct
83 84
 	assert.NilError(c, err)
84 85
 	dockerCmd(c, "rm", "-f", ID)
... ...
@@ -87,9 +89,7 @@ func (s *DockerSuite) TestPortList(c *testing.T) {
87 87
 		// host port ranges used
88 88
 		IDs := make([]string, 3)
89 89
 		for i := 0; i < 3; i++ {
90
-			out, _ = dockerCmd(c, "run", "-d",
91
-				"-p", "9090-9092:80",
92
-				"busybox", "top")
90
+			out, _ = dockerCmd(c, "run", "-d", "-p", "9090-9092:80", "busybox", "top")
93 91
 			IDs[i] = strings.TrimSpace(out)
94 92
 
95 93
 			out, _ = dockerCmd(c, "port", IDs[i])
... ...
@@ -100,9 +100,7 @@ func (s *DockerSuite) TestPortList(c *testing.T) {
100 100
 		}
101 101
 
102 102
 		// test port range exhaustion
103
-		out, _, err = dockerCmdWithError("run", "-d",
104
-			"-p", "9090-9092:80",
105
-			"busybox", "top")
103
+		out, _, err = dockerCmdWithError("run", "-d", "-p", "9090-9092:80", "busybox", "top")
106 104
 		// Exhausted port range did not return an error
107 105
 		assert.Assert(c, err != nil, "out: %s", out)
108 106
 
... ...
@@ -116,17 +114,13 @@ func (s *DockerSuite) TestPortList(c *testing.T) {
116 116
 
117 117
 	// test invalid port ranges
118 118
 	for _, invalidRange := range []string{"9090-9089:80", "9090-:80", "-9090:80"} {
119
-		out, _, err = dockerCmdWithError("run", "-d",
120
-			"-p", invalidRange,
121
-			"busybox", "top")
119
+		out, _, err = dockerCmdWithError("run", "-d", "-p", invalidRange, "busybox", "top")
122 120
 		// Port range should have returned an error
123 121
 		assert.Assert(c, err != nil, "out: %s", out)
124 122
 	}
125 123
 
126 124
 	// test host range:container range spec.
127
-	out, _ = dockerCmd(c, "run", "-d",
128
-		"-p", "9800-9803:80-83",
129
-		"busybox", "top")
125
+	out, _ = dockerCmd(c, "run", "-d", "-p", "9800-9803:80-83", "busybox", "top")
130 126
 	ID = strings.TrimSpace(out)
131 127
 
132 128
 	out, _ = dockerCmd(c, "port", ID)
... ...
@@ -135,28 +129,27 @@ func (s *DockerSuite) TestPortList(c *testing.T) {
135 135
 		"80/tcp -> 0.0.0.0:9800",
136 136
 		"81/tcp -> 0.0.0.0:9801",
137 137
 		"82/tcp -> 0.0.0.0:9802",
138
-		"83/tcp -> 0.0.0.0:9803"})
138
+		"83/tcp -> 0.0.0.0:9803",
139
+	})
139 140
 	// Port list is not correct
140 141
 	assert.NilError(c, err)
141 142
 	dockerCmd(c, "rm", "-f", ID)
142 143
 
143 144
 	// test mixing protocols in same port range
144
-	out, _ = dockerCmd(c, "run", "-d",
145
-		"-p", "8000-8080:80",
146
-		"-p", "8000-8080:80/udp",
147
-		"busybox", "top")
145
+	out, _ = dockerCmd(c, "run", "-d", "-p", "8000-8080:80", "-p", "8000-8080:80/udp", "busybox", "top")
148 146
 	ID = strings.TrimSpace(out)
149 147
 
150 148
 	out, _ = dockerCmd(c, "port", ID)
151 149
 
152 150
 	// Running this test multiple times causes the TCP port to increment.
153
-	err = assertPortRange(c, out, []int{8000, 8080}, []int{8000, 8080})
151
+	err = assertPortRange(ID, []int{8000, 8080}, []int{8000, 8080})
154 152
 	// Port list is not correct
155 153
 	assert.NilError(c, err)
156 154
 	dockerCmd(c, "rm", "-f", ID)
157 155
 }
158 156
 
159 157
 func assertPortList(c *testing.T, out string, expected []string) error {
158
+	c.Helper()
160 159
 	lines := strings.Split(strings.Trim(out, "\n "), "\n")
161 160
 	if len(lines) != len(expected) {
162 161
 		return fmt.Errorf("different size lists %s, %d, %d", out, len(lines), len(expected))
... ...
@@ -164,8 +157,20 @@ func assertPortList(c *testing.T, out string, expected []string) error {
164 164
 	sort.Strings(lines)
165 165
 	sort.Strings(expected)
166 166
 
167
+	// "docker port" does not yet have a "--format" flag, and older versions
168
+	// of the CLI used an incorrect output format for mappings on IPv6 addresses
169
+	// for example, "80/tcp -> :::80" instead of "80/tcp -> [::]:80".
170
+	oldFormat := func(mapping string) string {
171
+		old := strings.Replace(mapping, "-> [", "-> ", 1)
172
+		old = strings.Replace(old, "]:", ":", 1)
173
+		return old
174
+	}
175
+
167 176
 	for i := 0; i < len(expected); i++ {
168
-		if lines[i] != expected[i] {
177
+		if lines[i] == expected[i] {
178
+			continue
179
+		}
180
+		if lines[i] != oldFormat(expected[i]) {
169 181
 			return fmt.Errorf("|" + lines[i] + "!=" + expected[i] + "|")
170 182
 		}
171 183
 	}
... ...
@@ -173,27 +178,40 @@ func assertPortList(c *testing.T, out string, expected []string) error {
173 173
 	return nil
174 174
 }
175 175
 
176
-func assertPortRange(c *testing.T, out string, expectedTCP, expectedUDP []int) error {
177
-	lines := strings.Split(strings.Trim(out, "\n "), "\n")
176
+func assertPortRange(id string, expectedTCP, expectedUDP []int) error {
177
+	client := testEnv.APIClient()
178
+	inspect, err := client.ContainerInspect(context.TODO(), id)
179
+	if err != nil {
180
+		return err
181
+	}
178 182
 
179 183
 	var validTCP, validUDP bool
180
-	for _, l := range lines {
181
-		// 80/tcp -> 0.0.0.0:8015
182
-		port, err := strconv.Atoi(strings.Split(l, ":")[1])
183
-		if err != nil {
184
-			return err
184
+	for portAndProto, binding := range inspect.NetworkSettings.Ports {
185
+		if portAndProto.Proto() == "tcp" && len(expectedTCP) == 0 {
186
+			continue
185 187
 		}
186
-		if strings.Contains(l, "tcp") && expectedTCP != nil {
187
-			if port < expectedTCP[0] || port > expectedTCP[1] {
188
-				return fmt.Errorf("tcp port (%d) not in range expected range %d-%d", port, expectedTCP[0], expectedTCP[1])
189
-			}
190
-			validTCP = true
188
+		if portAndProto.Proto() == "udp" && len(expectedTCP) == 0 {
189
+			continue
191 190
 		}
192
-		if strings.Contains(l, "udp") && expectedUDP != nil {
193
-			if port < expectedUDP[0] || port > expectedUDP[1] {
194
-				return fmt.Errorf("udp port (%d) not in range expected range %d-%d", port, expectedUDP[0], expectedUDP[1])
191
+
192
+		for _, b := range binding {
193
+			port, err := strconv.Atoi(b.HostPort)
194
+			if err != nil {
195
+				return err
196
+			}
197
+
198
+			if len(expectedTCP) > 0 {
199
+				if port < expectedTCP[0] || port > expectedTCP[1] {
200
+					return fmt.Errorf("tcp port (%d) not in range expected range %d-%d", port, expectedTCP[0], expectedTCP[1])
201
+				}
202
+				validTCP = true
203
+			}
204
+			if len(expectedUDP) > 0 {
205
+				if port < expectedUDP[0] || port > expectedUDP[1] {
206
+					return fmt.Errorf("udp port (%d) not in range expected range %d-%d", port, expectedUDP[0], expectedUDP[1])
207
+				}
208
+				validUDP = true
195 209
 			}
196
-			validUDP = true
197 210
 		}
198 211
 	}
199 212
 	if !validTCP {
... ...
@@ -282,8 +300,7 @@ func (s *DockerSuite) TestUnpublishedPortsInPsOutput(c *testing.T) {
282 282
 
283 283
 func (s *DockerSuite) TestPortHostBinding(c *testing.T) {
284 284
 	testRequires(c, DaemonIsLinux, NotUserNamespace)
285
-	out, _ := dockerCmd(c, "run", "-d", "-p", "9876:80", "busybox",
286
-		"nc", "-l", "-p", "80")
285
+	out, _ := dockerCmd(c, "run", "-d", "-p", "9876:80", "busybox", "nc", "-l", "-p", "80")
287 286
 	firstID := strings.TrimSpace(out)
288 287
 
289 288
 	out, _ = dockerCmd(c, "port", firstID, "80")
... ...
@@ -292,8 +309,7 @@ func (s *DockerSuite) TestPortHostBinding(c *testing.T) {
292 292
 	// Port list is not correct
293 293
 	assert.NilError(c, err)
294 294
 
295
-	dockerCmd(c, "run", "--net=host", "busybox",
296
-		"nc", "localhost", "9876")
295
+	dockerCmd(c, "run", "--net=host", "busybox", "nc", "localhost", "9876")
297 296
 
298 297
 	dockerCmd(c, "rm", "-f", firstID)
299 298
 
... ...
@@ -304,22 +320,17 @@ func (s *DockerSuite) TestPortHostBinding(c *testing.T) {
304 304
 
305 305
 func (s *DockerSuite) TestPortExposeHostBinding(c *testing.T) {
306 306
 	testRequires(c, DaemonIsLinux, NotUserNamespace)
307
-	out, _ := dockerCmd(c, "run", "-d", "-P", "--expose", "80", "busybox",
308
-		"nc", "-l", "-p", "80")
307
+	out, _ := dockerCmd(c, "run", "-d", "-P", "--expose", "80", "busybox", "nc", "-l", "-p", "80")
309 308
 	firstID := strings.TrimSpace(out)
310 309
 
311
-	out, _ = dockerCmd(c, "port", firstID, "80")
312
-
313
-	_, exposedPort, err := net.SplitHostPort(out)
314
-	assert.Assert(c, err == nil, "out: %s", out)
310
+	out, _ = dockerCmd(c, "inspect", "--format", `{{index .NetworkSettings.Ports "80/tcp" 0 "HostPort" }}`, firstID)
315 311
 
316
-	dockerCmd(c, "run", "--net=host", "busybox",
317
-		"nc", "localhost", strings.TrimSpace(exposedPort))
312
+	exposedPort := strings.TrimSpace(out)
313
+	dockerCmd(c, "run", "--net=host", "busybox", "nc", "127.0.0.1", exposedPort)
318 314
 
319 315
 	dockerCmd(c, "rm", "-f", firstID)
320 316
 
321
-	out, _, err = dockerCmdWithError("run", "--net=host", "busybox",
322
-		"nc", "localhost", strings.TrimSpace(exposedPort))
317
+	out, _, err := dockerCmdWithError("run", "--net=host", "busybox", "nc", "127.0.0.1", exposedPort)
323 318
 	// Port is still bound after the Container is removed
324 319
 	assert.Assert(c, err != nil, "out: %s", out)
325 320
 }
... ...
@@ -594,20 +594,16 @@ func (s *DockerSuite) TestPsImageIDAfterUpdate(c *testing.T) {
594 594
 
595 595
 func (s *DockerSuite) TestPsNotShowPortsOfStoppedContainer(c *testing.T) {
596 596
 	testRequires(c, DaemonIsLinux)
597
-	dockerCmd(c, "run", "--name=foo", "-d", "-p", "5000:5000", "busybox", "top")
597
+	dockerCmd(c, "run", "--name=foo", "-d", "-p", "6000:5000", "busybox", "top")
598 598
 	assert.Assert(c, waitRun("foo") == nil)
599
-	out, _ := dockerCmd(c, "ps")
600
-	lines := strings.Split(strings.TrimSpace(out), "\n")
601
-	expected := "0.0.0.0:5000->5000/tcp"
602
-	fields := strings.Fields(lines[1])
603
-	assert.Equal(c, fields[len(fields)-2], expected, fmt.Sprintf("Expected: %v, got: %v", expected, fields[len(fields)-2]))
599
+	ports, _ := dockerCmd(c, "ps", "--format", "{{ .Ports }}", "--filter", "name=foo")
600
+	expected := ":6000->5000/tcp"
601
+	assert.Assert(c, is.Contains(ports, expected), "Expected: %v, got: %v", expected, ports)
604 602
 
605 603
 	dockerCmd(c, "kill", "foo")
606 604
 	dockerCmd(c, "wait", "foo")
607
-	out, _ = dockerCmd(c, "ps", "-l")
608
-	lines = strings.Split(strings.TrimSpace(out), "\n")
609
-	fields = strings.Fields(lines[1])
610
-	assert.Assert(c, fields[len(fields)-2] != expected, "Should not got %v", expected)
605
+	ports, _ = dockerCmd(c, "ps", "--format", "{{ .Ports }}", "--filter", "name=foo")
606
+	assert.Equal(c, ports, "", "Should not got %v", expected)
611 607
 }
612 608
 
613 609
 func (s *DockerSuite) TestPsShowMounts(c *testing.T) {
... ...
@@ -2063,12 +2063,11 @@ func (s *DockerSuite) TestRunAllocatePortInReservedRange(c *testing.T) {
2063 2063
 	out, _ := dockerCmd(c, "run", "-d", "-P", "-p", "80", "busybox", "top")
2064 2064
 
2065 2065
 	id := strings.TrimSpace(out)
2066
-	out, _ = dockerCmd(c, "port", id, "80")
2067
-
2068
-	strPort := strings.Split(strings.TrimSpace(out), ":")[1]
2069
-	port, err := strconv.ParseInt(strPort, 10, 64)
2066
+	out, _ = dockerCmd(c, "inspect", "--format", `{{index .NetworkSettings.Ports "80/tcp" 0 "HostPort" }}`, id)
2067
+	out = strings.TrimSpace(out)
2068
+	port, err := strconv.ParseInt(out, 10, 64)
2070 2069
 	if err != nil {
2071
-		c.Fatalf("invalid port, got: %s, error: %s", strPort, err)
2070
+		c.Fatalf("invalid port, got: %s, error: %s", out, err)
2072 2071
 	}
2073 2072
 
2074 2073
 	// allocate a static port and a dynamic port together, with static port
... ...
@@ -2278,7 +2277,7 @@ func (s *DockerSuite) TestRunAllowPortRangeThroughExpose(c *testing.T) {
2278 2278
 		if portnum < 3000 || portnum > 3003 {
2279 2279
 			c.Fatalf("Port %d is out of range ", portnum)
2280 2280
 		}
2281
-		if binding == nil || len(binding) != 1 || len(binding[0].HostPort) == 0 {
2281
+		if len(binding) == 0 || len(binding[0].HostPort) == 0 {
2282 2282
 			c.Fatalf("Port is not mapped for the port %s", port)
2283 2283
 		}
2284 2284
 	}
... ...
@@ -2497,13 +2496,12 @@ func (s *DockerSuite) TestRunPortFromDockerRangeInUse(c *testing.T) {
2497 2497
 	out, _ := dockerCmd(c, "run", "-d", "-p", ":80", "busybox", "top")
2498 2498
 
2499 2499
 	id := strings.TrimSpace(out)
2500
-	out, _ = dockerCmd(c, "port", id)
2501 2500
 
2501
+	out, _ = dockerCmd(c, "inspect", "--format", `{{index .NetworkSettings.Ports "80/tcp" 0 "HostPort" }}`, id)
2502 2502
 	out = strings.TrimSpace(out)
2503 2503
 	if out == "" {
2504 2504
 		c.Fatal("docker port command output is empty")
2505 2505
 	}
2506
-	out = strings.Split(out, ":")[1]
2507 2506
 	lastPort, err := strconv.Atoi(out)
2508 2507
 	if err != nil {
2509 2508
 		c.Fatal(err)
... ...
@@ -2637,7 +2635,7 @@ func (s *DockerSuite) TestRunAllowPortRangeThroughPublish(c *testing.T) {
2637 2637
 		if portnum < 3000 || portnum > 3003 {
2638 2638
 			c.Fatalf("Port %d is out of range ", portnum)
2639 2639
 		}
2640
-		if binding == nil || len(binding) != 1 || len(binding[0].HostPort) == 0 {
2640
+		if len(binding) == 0 || len(binding[0].HostPort) == 0 {
2641 2641
 			c.Fatal("Port is not mapped for the port "+port, out)
2642 2642
 		}
2643 2643
 	}