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 c6038b4884)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2021-02-11 21:45:16 +01:00
parent 86d98f5711
commit ef2351b416
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
4 changed files with 77 additions and 72 deletions

View File

@ -297,7 +297,7 @@ func waitForExec(c *testing.T, id string) {
} }
func inspectContainer(c *testing.T, id string, out interface{}) { func inspectContainer(c *testing.T, id string, out interface{}) {
resp, body, err := request.Get(fmt.Sprintf("/containers/%s/json", id)) resp, body, err := request.Get("/containers/" + id + "/json")
assert.NilError(c, err) assert.NilError(c, err)
defer body.Close() defer body.Close()
assert.Equal(c, resp.StatusCode, http.StatusOK) assert.Equal(c, resp.StatusCode, http.StatusOK)

View File

@ -1,8 +1,8 @@
package main package main
import ( import (
"context"
"fmt" "fmt"
"net"
"regexp" "regexp"
"sort" "sort"
"strconv" "strconv"
@ -51,7 +51,8 @@ func (s *DockerSuite) TestPortList(c *testing.T) {
err = assertPortList(c, out, []string{ err = assertPortList(c, out, []string{
"80/tcp -> 0.0.0.0:9876", "80/tcp -> 0.0.0.0:9876",
"81/tcp -> 0.0.0.0:9877", "81/tcp -> 0.0.0.0:9877",
"82/tcp -> 0.0.0.0:9878"}) "82/tcp -> 0.0.0.0:9878",
})
// Port list is not correct // Port list is not correct
assert.NilError(c, err) assert.NilError(c, err)
@ -78,7 +79,8 @@ func (s *DockerSuite) TestPortList(c *testing.T) {
"80/tcp -> 0.0.0.0:9876", "80/tcp -> 0.0.0.0:9876",
"80/tcp -> 0.0.0.0:9999", "80/tcp -> 0.0.0.0:9999",
"81/tcp -> 0.0.0.0:9877", "81/tcp -> 0.0.0.0:9877",
"82/tcp -> 0.0.0.0:9878"}) "82/tcp -> 0.0.0.0:9878",
})
// Port list is not correct // Port list is not correct
assert.NilError(c, err) assert.NilError(c, err)
dockerCmd(c, "rm", "-f", ID) dockerCmd(c, "rm", "-f", ID)
@ -87,9 +89,7 @@ func (s *DockerSuite) TestPortList(c *testing.T) {
// host port ranges used // host port ranges used
IDs := make([]string, 3) IDs := make([]string, 3)
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
out, _ = dockerCmd(c, "run", "-d", out, _ = dockerCmd(c, "run", "-d", "-p", "9090-9092:80", "busybox", "top")
"-p", "9090-9092:80",
"busybox", "top")
IDs[i] = strings.TrimSpace(out) IDs[i] = strings.TrimSpace(out)
out, _ = dockerCmd(c, "port", IDs[i]) out, _ = dockerCmd(c, "port", IDs[i])
@ -100,9 +100,7 @@ func (s *DockerSuite) TestPortList(c *testing.T) {
} }
// test port range exhaustion // test port range exhaustion
out, _, err = dockerCmdWithError("run", "-d", out, _, err = dockerCmdWithError("run", "-d", "-p", "9090-9092:80", "busybox", "top")
"-p", "9090-9092:80",
"busybox", "top")
// Exhausted port range did not return an error // Exhausted port range did not return an error
assert.Assert(c, err != nil, "out: %s", out) assert.Assert(c, err != nil, "out: %s", out)
@ -116,17 +114,13 @@ func (s *DockerSuite) TestPortList(c *testing.T) {
// test invalid port ranges // test invalid port ranges
for _, invalidRange := range []string{"9090-9089:80", "9090-:80", "-9090:80"} { for _, invalidRange := range []string{"9090-9089:80", "9090-:80", "-9090:80"} {
out, _, err = dockerCmdWithError("run", "-d", out, _, err = dockerCmdWithError("run", "-d", "-p", invalidRange, "busybox", "top")
"-p", invalidRange,
"busybox", "top")
// Port range should have returned an error // Port range should have returned an error
assert.Assert(c, err != nil, "out: %s", out) assert.Assert(c, err != nil, "out: %s", out)
} }
// test host range:container range spec. // test host range:container range spec.
out, _ = dockerCmd(c, "run", "-d", out, _ = dockerCmd(c, "run", "-d", "-p", "9800-9803:80-83", "busybox", "top")
"-p", "9800-9803:80-83",
"busybox", "top")
ID = strings.TrimSpace(out) ID = strings.TrimSpace(out)
out, _ = dockerCmd(c, "port", ID) out, _ = dockerCmd(c, "port", ID)
@ -135,28 +129,27 @@ func (s *DockerSuite) TestPortList(c *testing.T) {
"80/tcp -> 0.0.0.0:9800", "80/tcp -> 0.0.0.0:9800",
"81/tcp -> 0.0.0.0:9801", "81/tcp -> 0.0.0.0:9801",
"82/tcp -> 0.0.0.0:9802", "82/tcp -> 0.0.0.0:9802",
"83/tcp -> 0.0.0.0:9803"}) "83/tcp -> 0.0.0.0:9803",
})
// Port list is not correct // Port list is not correct
assert.NilError(c, err) assert.NilError(c, err)
dockerCmd(c, "rm", "-f", ID) dockerCmd(c, "rm", "-f", ID)
// test mixing protocols in same port range // test mixing protocols in same port range
out, _ = dockerCmd(c, "run", "-d", out, _ = dockerCmd(c, "run", "-d", "-p", "8000-8080:80", "-p", "8000-8080:80/udp", "busybox", "top")
"-p", "8000-8080:80",
"-p", "8000-8080:80/udp",
"busybox", "top")
ID = strings.TrimSpace(out) ID = strings.TrimSpace(out)
out, _ = dockerCmd(c, "port", ID) out, _ = dockerCmd(c, "port", ID)
// Running this test multiple times causes the TCP port to increment. // Running this test multiple times causes the TCP port to increment.
err = assertPortRange(c, out, []int{8000, 8080}, []int{8000, 8080}) err = assertPortRange(ID, []int{8000, 8080}, []int{8000, 8080})
// Port list is not correct // Port list is not correct
assert.NilError(c, err) assert.NilError(c, err)
dockerCmd(c, "rm", "-f", ID) dockerCmd(c, "rm", "-f", ID)
} }
func assertPortList(c *testing.T, out string, expected []string) error { func assertPortList(c *testing.T, out string, expected []string) error {
c.Helper()
lines := strings.Split(strings.Trim(out, "\n "), "\n") lines := strings.Split(strings.Trim(out, "\n "), "\n")
if len(lines) != len(expected) { if len(lines) != len(expected) {
return fmt.Errorf("different size lists %s, %d, %d", out, len(lines), len(expected)) 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 {
sort.Strings(lines) sort.Strings(lines)
sort.Strings(expected) sort.Strings(expected)
// "docker port" does not yet have a "--format" flag, and older versions
// of the CLI used an incorrect output format for mappings on IPv6 addresses
// for example, "80/tcp -> :::80" instead of "80/tcp -> [::]:80".
oldFormat := func(mapping string) string {
old := strings.Replace(mapping, "-> [", "-> ", 1)
old = strings.Replace(old, "]:", ":", 1)
return old
}
for i := 0; i < len(expected); i++ { for i := 0; i < len(expected); i++ {
if lines[i] != expected[i] { if lines[i] == expected[i] {
continue
}
if lines[i] != oldFormat(expected[i]) {
return fmt.Errorf("|" + lines[i] + "!=" + expected[i] + "|") return fmt.Errorf("|" + lines[i] + "!=" + expected[i] + "|")
} }
} }
@ -173,27 +178,40 @@ func assertPortList(c *testing.T, out string, expected []string) error {
return nil return nil
} }
func assertPortRange(c *testing.T, out string, expectedTCP, expectedUDP []int) error { func assertPortRange(id string, expectedTCP, expectedUDP []int) error {
lines := strings.Split(strings.Trim(out, "\n "), "\n") client := testEnv.APIClient()
inspect, err := client.ContainerInspect(context.TODO(), id)
if err != nil {
return err
}
var validTCP, validUDP bool var validTCP, validUDP bool
for _, l := range lines { for portAndProto, binding := range inspect.NetworkSettings.Ports {
// 80/tcp -> 0.0.0.0:8015 if portAndProto.Proto() == "tcp" && len(expectedTCP) == 0 {
port, err := strconv.Atoi(strings.Split(l, ":")[1]) continue
if err != nil {
return err
} }
if strings.Contains(l, "tcp") && expectedTCP != nil { if portAndProto.Proto() == "udp" && len(expectedTCP) == 0 {
if port < expectedTCP[0] || port > expectedTCP[1] { continue
return fmt.Errorf("tcp port (%d) not in range expected range %d-%d", port, expectedTCP[0], expectedTCP[1])
}
validTCP = true
} }
if strings.Contains(l, "udp") && expectedUDP != nil {
if port < expectedUDP[0] || port > expectedUDP[1] { for _, b := range binding {
return fmt.Errorf("udp port (%d) not in range expected range %d-%d", port, expectedUDP[0], expectedUDP[1]) port, err := strconv.Atoi(b.HostPort)
if err != nil {
return err
}
if len(expectedTCP) > 0 {
if port < expectedTCP[0] || port > expectedTCP[1] {
return fmt.Errorf("tcp port (%d) not in range expected range %d-%d", port, expectedTCP[0], expectedTCP[1])
}
validTCP = true
}
if len(expectedUDP) > 0 {
if port < expectedUDP[0] || port > expectedUDP[1] {
return fmt.Errorf("udp port (%d) not in range expected range %d-%d", port, expectedUDP[0], expectedUDP[1])
}
validUDP = true
} }
validUDP = true
} }
} }
if !validTCP { if !validTCP {
@ -282,8 +300,7 @@ func (s *DockerSuite) TestUnpublishedPortsInPsOutput(c *testing.T) {
func (s *DockerSuite) TestPortHostBinding(c *testing.T) { func (s *DockerSuite) TestPortHostBinding(c *testing.T) {
testRequires(c, DaemonIsLinux, NotUserNamespace) testRequires(c, DaemonIsLinux, NotUserNamespace)
out, _ := dockerCmd(c, "run", "-d", "-p", "9876:80", "busybox", out, _ := dockerCmd(c, "run", "-d", "-p", "9876:80", "busybox", "nc", "-l", "-p", "80")
"nc", "-l", "-p", "80")
firstID := strings.TrimSpace(out) firstID := strings.TrimSpace(out)
out, _ = dockerCmd(c, "port", firstID, "80") out, _ = dockerCmd(c, "port", firstID, "80")
@ -292,8 +309,7 @@ func (s *DockerSuite) TestPortHostBinding(c *testing.T) {
// Port list is not correct // Port list is not correct
assert.NilError(c, err) assert.NilError(c, err)
dockerCmd(c, "run", "--net=host", "busybox", dockerCmd(c, "run", "--net=host", "busybox", "nc", "localhost", "9876")
"nc", "localhost", "9876")
dockerCmd(c, "rm", "-f", firstID) dockerCmd(c, "rm", "-f", firstID)
@ -304,22 +320,17 @@ func (s *DockerSuite) TestPortHostBinding(c *testing.T) {
func (s *DockerSuite) TestPortExposeHostBinding(c *testing.T) { func (s *DockerSuite) TestPortExposeHostBinding(c *testing.T) {
testRequires(c, DaemonIsLinux, NotUserNamespace) testRequires(c, DaemonIsLinux, NotUserNamespace)
out, _ := dockerCmd(c, "run", "-d", "-P", "--expose", "80", "busybox", out, _ := dockerCmd(c, "run", "-d", "-P", "--expose", "80", "busybox", "nc", "-l", "-p", "80")
"nc", "-l", "-p", "80")
firstID := strings.TrimSpace(out) firstID := strings.TrimSpace(out)
out, _ = dockerCmd(c, "port", firstID, "80") out, _ = dockerCmd(c, "inspect", "--format", `{{index .NetworkSettings.Ports "80/tcp" 0 "HostPort" }}`, firstID)
_, exposedPort, err := net.SplitHostPort(out) exposedPort := strings.TrimSpace(out)
assert.Assert(c, err == nil, "out: %s", out) dockerCmd(c, "run", "--net=host", "busybox", "nc", "127.0.0.1", exposedPort)
dockerCmd(c, "run", "--net=host", "busybox",
"nc", "localhost", strings.TrimSpace(exposedPort))
dockerCmd(c, "rm", "-f", firstID) dockerCmd(c, "rm", "-f", firstID)
out, _, err = dockerCmdWithError("run", "--net=host", "busybox", out, _, err := dockerCmdWithError("run", "--net=host", "busybox", "nc", "127.0.0.1", exposedPort)
"nc", "localhost", strings.TrimSpace(exposedPort))
// Port is still bound after the Container is removed // Port is still bound after the Container is removed
assert.Assert(c, err != nil, "out: %s", out) assert.Assert(c, err != nil, "out: %s", out)
} }

View File

@ -594,20 +594,16 @@ func (s *DockerSuite) TestPsImageIDAfterUpdate(c *testing.T) {
func (s *DockerSuite) TestPsNotShowPortsOfStoppedContainer(c *testing.T) { func (s *DockerSuite) TestPsNotShowPortsOfStoppedContainer(c *testing.T) {
testRequires(c, DaemonIsLinux) testRequires(c, DaemonIsLinux)
dockerCmd(c, "run", "--name=foo", "-d", "-p", "5000:5000", "busybox", "top") dockerCmd(c, "run", "--name=foo", "-d", "-p", "6000:5000", "busybox", "top")
assert.Assert(c, waitRun("foo") == nil) assert.Assert(c, waitRun("foo") == nil)
out, _ := dockerCmd(c, "ps") ports, _ := dockerCmd(c, "ps", "--format", "{{ .Ports }}", "--filter", "name=foo")
lines := strings.Split(strings.TrimSpace(out), "\n") expected := ":6000->5000/tcp"
expected := "0.0.0.0:5000->5000/tcp" assert.Assert(c, is.Contains(ports, expected), "Expected: %v, got: %v", expected, ports)
fields := strings.Fields(lines[1])
assert.Equal(c, fields[len(fields)-2], expected, fmt.Sprintf("Expected: %v, got: %v", expected, fields[len(fields)-2]))
dockerCmd(c, "kill", "foo") dockerCmd(c, "kill", "foo")
dockerCmd(c, "wait", "foo") dockerCmd(c, "wait", "foo")
out, _ = dockerCmd(c, "ps", "-l") ports, _ = dockerCmd(c, "ps", "--format", "{{ .Ports }}", "--filter", "name=foo")
lines = strings.Split(strings.TrimSpace(out), "\n") assert.Equal(c, ports, "", "Should not got %v", expected)
fields = strings.Fields(lines[1])
assert.Assert(c, fields[len(fields)-2] != expected, "Should not got %v", expected)
} }
func (s *DockerSuite) TestPsShowMounts(c *testing.T) { func (s *DockerSuite) TestPsShowMounts(c *testing.T) {

View File

@ -2063,12 +2063,11 @@ func (s *DockerSuite) TestRunAllocatePortInReservedRange(c *testing.T) {
out, _ := dockerCmd(c, "run", "-d", "-P", "-p", "80", "busybox", "top") out, _ := dockerCmd(c, "run", "-d", "-P", "-p", "80", "busybox", "top")
id := strings.TrimSpace(out) id := strings.TrimSpace(out)
out, _ = dockerCmd(c, "port", id, "80") out, _ = dockerCmd(c, "inspect", "--format", `{{index .NetworkSettings.Ports "80/tcp" 0 "HostPort" }}`, id)
out = strings.TrimSpace(out)
strPort := strings.Split(strings.TrimSpace(out), ":")[1] port, err := strconv.ParseInt(out, 10, 64)
port, err := strconv.ParseInt(strPort, 10, 64)
if err != nil { if err != nil {
c.Fatalf("invalid port, got: %s, error: %s", strPort, err) c.Fatalf("invalid port, got: %s, error: %s", out, err)
} }
// allocate a static port and a dynamic port together, with static port // allocate a static port and a dynamic port together, with static port
@ -2278,7 +2277,7 @@ func (s *DockerSuite) TestRunAllowPortRangeThroughExpose(c *testing.T) {
if portnum < 3000 || portnum > 3003 { if portnum < 3000 || portnum > 3003 {
c.Fatalf("Port %d is out of range ", portnum) c.Fatalf("Port %d is out of range ", portnum)
} }
if binding == nil || len(binding) != 1 || len(binding[0].HostPort) == 0 { if len(binding) == 0 || len(binding[0].HostPort) == 0 {
c.Fatalf("Port is not mapped for the port %s", port) c.Fatalf("Port is not mapped for the port %s", port)
} }
} }
@ -2497,13 +2496,12 @@ func (s *DockerSuite) TestRunPortFromDockerRangeInUse(c *testing.T) {
out, _ := dockerCmd(c, "run", "-d", "-p", ":80", "busybox", "top") out, _ := dockerCmd(c, "run", "-d", "-p", ":80", "busybox", "top")
id := strings.TrimSpace(out) id := strings.TrimSpace(out)
out, _ = dockerCmd(c, "port", id)
out, _ = dockerCmd(c, "inspect", "--format", `{{index .NetworkSettings.Ports "80/tcp" 0 "HostPort" }}`, id)
out = strings.TrimSpace(out) out = strings.TrimSpace(out)
if out == "" { if out == "" {
c.Fatal("docker port command output is empty") c.Fatal("docker port command output is empty")
} }
out = strings.Split(out, ":")[1]
lastPort, err := strconv.Atoi(out) lastPort, err := strconv.Atoi(out)
if err != nil { if err != nil {
c.Fatal(err) c.Fatal(err)
@ -2637,7 +2635,7 @@ func (s *DockerSuite) TestRunAllowPortRangeThroughPublish(c *testing.T) {
if portnum < 3000 || portnum > 3003 { if portnum < 3000 || portnum > 3003 {
c.Fatalf("Port %d is out of range ", portnum) c.Fatalf("Port %d is out of range ", portnum)
} }
if binding == nil || len(binding) != 1 || len(binding[0].HostPort) == 0 { if len(binding) == 0 || len(binding[0].HostPort) == 0 {
c.Fatal("Port is not mapped for the port "+port, out) c.Fatal("Port is not mapped for the port "+port, out)
} }
} }