github.com/rumpl/bof@v23.0.0-rc.2+incompatible/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.GitHubActions, "FIXME: https://github.com/moby/moby/issues/41561") 60 skip.If(t, testEnv.OSType == "windows", "FIXME") 61 skip.If(t, testEnv.IsRemoteDaemon) 62 63 defer setupTest(t)() 64 65 msg := "it works" 66 serverContainerID := startServerContainer(t, msg, 8080) 67 68 endpoint := getExternalAddress(t) 69 70 client := testEnv.APIClient() 71 ctx := context.Background() 72 73 cID := container.Run(ctx, t, client, 74 container.WithCmd("sh", "-c", fmt.Sprintf("stty raw && nc -w 1 %s 8080", endpoint.String())), 75 container.WithTty(true), 76 container.WithNetworkMode("container:"+serverContainerID), 77 ) 78 79 poll.WaitOn(t, container.IsStopped(ctx, client, cID), poll.WithDelay(100*time.Millisecond)) 80 81 body, err := client.ContainerLogs(ctx, cID, types.ContainerLogsOptions{ 82 ShowStdout: true, 83 }) 84 assert.NilError(t, err) 85 defer body.Close() 86 87 var b bytes.Buffer 88 _, err = io.Copy(&b, body) 89 assert.NilError(t, err) 90 91 assert.Check(t, is.Equal(msg, strings.TrimSpace(b.String()))) 92 } 93 94 func startServerContainer(t *testing.T, msg string, port int) string { 95 t.Helper() 96 client := testEnv.APIClient() 97 ctx := context.Background() 98 99 cID := container.Run(ctx, t, client, 100 container.WithName("server-"+t.Name()), 101 container.WithCmd("sh", "-c", fmt.Sprintf("echo %q | nc -lp %d", msg, port)), 102 container.WithExposedPorts(fmt.Sprintf("%d/tcp", port)), 103 func(c *container.TestContainerConfig) { 104 c.HostConfig.PortBindings = nat.PortMap{ 105 nat.Port(fmt.Sprintf("%d/tcp", port)): []nat.PortBinding{ 106 { 107 HostPort: fmt.Sprintf("%d", port), 108 }, 109 }, 110 } 111 }) 112 113 poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond)) 114 115 return cID 116 } 117 118 // getExternalAddress() returns the external IP-address from eth0. If eth0 has 119 // multiple IP-addresses, it returns the first IPv4 IP-address; if no IPv4 120 // address is present, it returns the first IP-address found. 121 func getExternalAddress(t *testing.T) net.IP { 122 t.Helper() 123 iface, err := net.InterfaceByName("eth0") 124 skip.If(t, err != nil, "Test not running with `make test-integration`. Interface eth0 not found: %s", err) 125 126 ifaceAddrs, err := iface.Addrs() 127 assert.NilError(t, err) 128 assert.Check(t, 0 != len(ifaceAddrs)) 129 130 if len(ifaceAddrs) > 1 { 131 // Prefer IPv4 address if multiple addresses found, as rootlesskit 132 // does not handle IPv6 currently https://github.com/moby/moby/pull/41908#issuecomment-774200001 133 for _, a := range ifaceAddrs { 134 ifaceIP, _, err := net.ParseCIDR(a.String()) 135 assert.NilError(t, err) 136 if ifaceIP.To4() != nil { 137 return ifaceIP 138 } 139 } 140 } 141 ifaceIP, _, err := net.ParseCIDR(ifaceAddrs[0].String()) 142 assert.NilError(t, err) 143 144 return ifaceIP 145 }