github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/integration/container/nat_test.go (about) 1 package container // import "github.com/Prakhar-Agarwal-byte/moby/integration/container" 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "io" 8 "net" 9 "strings" 10 "testing" 11 "time" 12 13 containertypes "github.com/Prakhar-Agarwal-byte/moby/api/types/container" 14 "github.com/Prakhar-Agarwal-byte/moby/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.DaemonInfo.OSType == "windows", "FIXME") 24 skip.If(t, testEnv.IsRemoteDaemon) 25 26 ctx := setupTest(t) 27 28 msg := "it works" 29 startServerContainer(ctx, 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 ctx := setupTest(t) 45 46 msg := "hi yall" 47 startServerContainer(ctx, 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.DaemonInfo.OSType == "windows", "FIXME") 61 skip.If(t, testEnv.IsRemoteDaemon) 62 63 ctx := setupTest(t) 64 65 msg := "it works" 66 serverContainerID := startServerContainer(ctx, t, msg, 8080) 67 68 endpoint := getExternalAddress(t) 69 70 apiClient := testEnv.APIClient() 71 72 cID := container.Run(ctx, t, apiClient, 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, apiClient, cID), poll.WithDelay(100*time.Millisecond)) 79 80 body, err := apiClient.ContainerLogs(ctx, cID, containertypes.LogsOptions{ 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(ctx context.Context, t *testing.T, msg string, port int) string { 94 t.Helper() 95 apiClient := testEnv.APIClient() 96 97 return container.Run(ctx, t, apiClient, 98 container.WithName("server-"+t.Name()), 99 container.WithCmd("sh", "-c", fmt.Sprintf("echo %q | nc -lp %d", msg, port)), 100 container.WithExposedPorts(fmt.Sprintf("%d/tcp", port)), 101 func(c *container.TestContainerConfig) { 102 c.HostConfig.PortBindings = nat.PortMap{ 103 nat.Port(fmt.Sprintf("%d/tcp", port)): []nat.PortBinding{ 104 { 105 HostPort: fmt.Sprintf("%d", port), 106 }, 107 }, 108 } 109 }, 110 ) 111 } 112 113 // getExternalAddress() returns the external IP-address from eth0. If eth0 has 114 // multiple IP-addresses, it returns the first IPv4 IP-address; if no IPv4 115 // address is present, it returns the first IP-address found. 116 func getExternalAddress(t *testing.T) net.IP { 117 t.Helper() 118 iface, err := net.InterfaceByName("eth0") 119 skip.If(t, err != nil, "Test not running with `make test-integration`. Interface eth0 not found: %s", err) 120 121 ifaceAddrs, err := iface.Addrs() 122 assert.NilError(t, err) 123 assert.Check(t, 0 != len(ifaceAddrs)) 124 125 if len(ifaceAddrs) > 1 { 126 // Prefer IPv4 address if multiple addresses found, as rootlesskit 127 // does not handle IPv6 currently https://github.com/moby/moby/pull/41908#issuecomment-774200001 128 for _, a := range ifaceAddrs { 129 ifaceIP, _, err := net.ParseCIDR(a.String()) 130 assert.NilError(t, err) 131 if ifaceIP.To4() != nil { 132 return ifaceIP 133 } 134 } 135 } 136 ifaceIP, _, err := net.ParseCIDR(ifaceAddrs[0].String()) 137 assert.NilError(t, err) 138 139 return ifaceIP 140 }