github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/engine/integration/container/nat_test.go (about) 1 package container // import "github.com/docker/docker/integration/container" 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "io" 8 "net" 9 "strings" 10 "testing" 11 "time" 12 13 "github.com/docker/docker/api/types" 14 "github.com/docker/docker/integration/internal/container" 15 "github.com/docker/go-connections/nat" 16 "gotest.tools/v3/assert" 17 is "gotest.tools/v3/assert/cmp" 18 "gotest.tools/v3/poll" 19 "gotest.tools/v3/skip" 20 ) 21 22 func TestNetworkNat(t *testing.T) { 23 skip.If(t, testEnv.OSType == "windows", "FIXME") 24 skip.If(t, testEnv.IsRemoteDaemon) 25 26 defer setupTest(t)() 27 28 msg := "it works" 29 startServerContainer(t, msg, 8080) 30 31 endpoint := getExternalAddress(t) 32 conn, err := net.Dial("tcp", net.JoinHostPort(endpoint.String(), "8080")) 33 assert.NilError(t, err) 34 defer conn.Close() 35 36 data, err := io.ReadAll(conn) 37 assert.NilError(t, err) 38 assert.Check(t, is.Equal(msg, strings.TrimSpace(string(data)))) 39 } 40 41 func TestNetworkLocalhostTCPNat(t *testing.T) { 42 skip.If(t, testEnv.IsRemoteDaemon) 43 44 defer setupTest(t)() 45 46 msg := "hi yall" 47 startServerContainer(t, msg, 8081) 48 49 conn, err := net.Dial("tcp", "localhost:8081") 50 assert.NilError(t, err) 51 defer conn.Close() 52 53 data, err := io.ReadAll(conn) 54 assert.NilError(t, err) 55 assert.Check(t, is.Equal(msg, strings.TrimSpace(string(data)))) 56 } 57 58 func TestNetworkLoopbackNat(t *testing.T) { 59 skip.If(t, testEnv.OSType == "windows", "FIXME") 60 skip.If(t, testEnv.IsRemoteDaemon) 61 62 defer setupTest(t)() 63 64 msg := "it works" 65 serverContainerID := startServerContainer(t, msg, 8080) 66 67 endpoint := getExternalAddress(t) 68 69 client := testEnv.APIClient() 70 ctx := context.Background() 71 72 cID := container.Run(ctx, t, client, 73 container.WithCmd("sh", "-c", fmt.Sprintf("stty raw && nc -w 1 %s 8080", endpoint.String())), 74 container.WithTty(true), 75 container.WithNetworkMode("container:"+serverContainerID), 76 ) 77 78 poll.WaitOn(t, container.IsStopped(ctx, client, cID), poll.WithDelay(100*time.Millisecond)) 79 80 body, err := client.ContainerLogs(ctx, cID, types.ContainerLogsOptions{ 81 ShowStdout: true, 82 }) 83 assert.NilError(t, err) 84 defer body.Close() 85 86 var b bytes.Buffer 87 _, err = io.Copy(&b, body) 88 assert.NilError(t, err) 89 90 assert.Check(t, is.Equal(msg, strings.TrimSpace(b.String()))) 91 } 92 93 func startServerContainer(t *testing.T, msg string, port int) string { 94 t.Helper() 95 client := testEnv.APIClient() 96 ctx := context.Background() 97 98 cID := container.Run(ctx, t, client, 99 container.WithName("server-"+t.Name()), 100 container.WithCmd("sh", "-c", fmt.Sprintf("echo %q | nc -lp %d", msg, port)), 101 container.WithExposedPorts(fmt.Sprintf("%d/tcp", port)), 102 func(c *container.TestContainerConfig) { 103 c.HostConfig.PortBindings = nat.PortMap{ 104 nat.Port(fmt.Sprintf("%d/tcp", port)): []nat.PortBinding{ 105 { 106 HostPort: fmt.Sprintf("%d", port), 107 }, 108 }, 109 } 110 }) 111 112 poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond)) 113 114 return cID 115 } 116 117 // getExternalAddress() returns the external IP-address from eth0. If eth0 has 118 // multiple IP-addresses, it returns the first IPv4 IP-address; if no IPv4 119 // address is present, it returns the first IP-address found. 120 func getExternalAddress(t *testing.T) net.IP { 121 t.Helper() 122 iface, err := net.InterfaceByName("eth0") 123 skip.If(t, err != nil, "Test not running with `make test-integration`. Interface eth0 not found: %s", err) 124 125 ifaceAddrs, err := iface.Addrs() 126 assert.NilError(t, err) 127 assert.Check(t, 0 != len(ifaceAddrs)) 128 129 if len(ifaceAddrs) > 1 { 130 // Prefer IPv4 address if multiple addresses found, as rootlesskit 131 // does not handle IPv6 currently https://github.com/moby/moby/pull/41908#issuecomment-774200001 132 for _, a := range ifaceAddrs { 133 ifaceIP, _, err := net.ParseCIDR(a.String()) 134 assert.NilError(t, err) 135 if ifaceIP.To4() != nil { 136 return ifaceIP 137 } 138 } 139 } 140 ifaceIP, _, err := net.ParseCIDR(ifaceAddrs[0].String()) 141 assert.NilError(t, err) 142 143 return ifaceIP 144 }