github.com/rawahars/moby@v24.0.4+incompatible/integration/network/network_test.go (about) 1 package network // import "github.com/docker/docker/integration/network" 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "fmt" 8 "net/http" 9 "os/exec" 10 "strings" 11 "testing" 12 13 "github.com/docker/docker/api/types" 14 ntypes "github.com/docker/docker/api/types/network" 15 "github.com/docker/docker/integration/internal/container" 16 "github.com/docker/docker/integration/internal/network" 17 "github.com/docker/docker/testutil/daemon" 18 "github.com/docker/docker/testutil/request" 19 "gotest.tools/v3/assert" 20 is "gotest.tools/v3/assert/cmp" 21 "gotest.tools/v3/icmd" 22 "gotest.tools/v3/skip" 23 ) 24 25 func TestRunContainerWithBridgeNone(t *testing.T) { 26 skip.If(t, testEnv.IsRemoteDaemon, "cannot start daemon on remote test run") 27 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 28 skip.If(t, testEnv.IsUserNamespace) 29 skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") 30 31 d := daemon.New(t) 32 d.StartWithBusybox(t, "-b", "none") 33 defer d.Stop(t) 34 35 c := d.NewClientT(t) 36 ctx := context.Background() 37 38 id1 := container.Run(ctx, t, c) 39 defer c.ContainerRemove(ctx, id1, types.ContainerRemoveOptions{Force: true}) 40 41 result, err := container.Exec(ctx, c, id1, []string{"ip", "l"}) 42 assert.NilError(t, err) 43 assert.Check(t, is.Equal(false, strings.Contains(result.Combined(), "eth0")), "There shouldn't be eth0 in container in default(bridge) mode when bridge network is disabled") 44 45 id2 := container.Run(ctx, t, c, container.WithNetworkMode("bridge")) 46 defer c.ContainerRemove(ctx, id2, types.ContainerRemoveOptions{Force: true}) 47 48 result, err = container.Exec(ctx, c, id2, []string{"ip", "l"}) 49 assert.NilError(t, err) 50 assert.Check(t, is.Equal(false, strings.Contains(result.Combined(), "eth0")), "There shouldn't be eth0 in container in bridge mode when bridge network is disabled") 51 52 nsCommand := "ls -l /proc/self/ns/net | awk -F '->' '{print $2}'" 53 cmd := exec.Command("sh", "-c", nsCommand) 54 stdout := bytes.NewBuffer(nil) 55 cmd.Stdout = stdout 56 err = cmd.Run() 57 assert.NilError(t, err, "Failed to get current process network namespace: %+v", err) 58 59 id3 := container.Run(ctx, t, c, container.WithNetworkMode("host")) 60 defer c.ContainerRemove(ctx, id3, types.ContainerRemoveOptions{Force: true}) 61 62 result, err = container.Exec(ctx, c, id3, []string{"sh", "-c", nsCommand}) 63 assert.NilError(t, err) 64 assert.Check(t, is.Equal(stdout.String(), result.Combined()), "The network namespace of container should be the same with host when --net=host and bridge network is disabled") 65 } 66 67 // TestNetworkInvalidJSON tests that POST endpoints that expect a body return 68 // the correct error when sending invalid JSON requests. 69 func TestNetworkInvalidJSON(t *testing.T) { 70 defer setupTest(t)() 71 72 // POST endpoints that accept / expect a JSON body; 73 endpoints := []string{ 74 "/networks/create", 75 "/networks/bridge/connect", 76 "/networks/bridge/disconnect", 77 } 78 79 for _, ep := range endpoints { 80 ep := ep 81 t.Run(ep[1:], func(t *testing.T) { 82 t.Parallel() 83 84 t.Run("invalid content type", func(t *testing.T) { 85 res, body, err := request.Post(ep, request.RawString("{}"), request.ContentType("text/plain")) 86 assert.NilError(t, err) 87 assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest)) 88 89 buf, err := request.ReadBody(body) 90 assert.NilError(t, err) 91 assert.Check(t, is.Contains(string(buf), "unsupported Content-Type header (text/plain): must be 'application/json'")) 92 }) 93 94 t.Run("invalid JSON", func(t *testing.T) { 95 res, body, err := request.Post(ep, request.RawString("{invalid json"), request.JSON) 96 assert.NilError(t, err) 97 assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest)) 98 99 buf, err := request.ReadBody(body) 100 assert.NilError(t, err) 101 assert.Check(t, is.Contains(string(buf), "invalid JSON: invalid character 'i' looking for beginning of object key string")) 102 }) 103 104 t.Run("extra content after JSON", func(t *testing.T) { 105 res, body, err := request.Post(ep, request.RawString(`{} trailing content`), request.JSON) 106 assert.NilError(t, err) 107 assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest)) 108 109 buf, err := request.ReadBody(body) 110 assert.NilError(t, err) 111 assert.Check(t, is.Contains(string(buf), "unexpected content after JSON")) 112 }) 113 114 t.Run("empty body", func(t *testing.T) { 115 // empty body should not produce an 500 internal server error, or 116 // any 5XX error (this is assuming the request does not produce 117 // an internal server error for another reason, but it shouldn't) 118 res, _, err := request.Post(ep, request.RawString(``), request.JSON) 119 assert.NilError(t, err) 120 assert.Check(t, res.StatusCode < http.StatusInternalServerError) 121 }) 122 }) 123 } 124 } 125 126 // TestNetworkList verifies that /networks returns a list of networks either 127 // with, or without a trailing slash (/networks/). Regression test for https://github.com/moby/moby/issues/24595 128 func TestNetworkList(t *testing.T) { 129 defer setupTest(t)() 130 131 endpoints := []string{ 132 "/networks", 133 "/networks/", 134 } 135 136 for _, ep := range endpoints { 137 ep := ep 138 t.Run(ep, func(t *testing.T) { 139 t.Parallel() 140 141 res, body, err := request.Get(ep, request.JSON) 142 assert.NilError(t, err) 143 assert.Equal(t, res.StatusCode, http.StatusOK) 144 145 buf, err := request.ReadBody(body) 146 assert.NilError(t, err) 147 var nws []types.NetworkResource 148 err = json.Unmarshal(buf, &nws) 149 assert.NilError(t, err) 150 assert.Assert(t, len(nws) > 0) 151 }) 152 } 153 } 154 155 func TestHostIPv4BridgeLabel(t *testing.T) { 156 skip.If(t, testEnv.OSType == "windows") 157 skip.If(t, testEnv.IsRemoteDaemon) 158 skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") 159 d := daemon.New(t) 160 d.Start(t) 161 defer d.Stop(t) 162 c := d.NewClientT(t) 163 defer c.Close() 164 ctx := context.Background() 165 166 ipv4SNATAddr := "172.0.0.172" 167 // Create a bridge network with --opt com.docker.network.host_ipv4=172.0.0.172 168 bridgeName := "hostIPv4Bridge" 169 network.CreateNoError(ctx, t, c, bridgeName, 170 network.WithDriver("bridge"), 171 network.WithOption("com.docker.network.host_ipv4", ipv4SNATAddr), 172 network.WithOption("com.docker.network.bridge.name", bridgeName), 173 ) 174 out, err := c.NetworkInspect(ctx, bridgeName, types.NetworkInspectOptions{Verbose: true}) 175 assert.NilError(t, err) 176 assert.Assert(t, len(out.IPAM.Config) > 0) 177 // Make sure the SNAT rule exists 178 icmd.RunCommand("iptables", "-t", "nat", "-C", "POSTROUTING", "-s", out.IPAM.Config[0].Subnet, "!", "-o", bridgeName, "-j", "SNAT", "--to-source", ipv4SNATAddr).Assert(t, icmd.Success) 179 } 180 181 func TestDefaultNetworkOpts(t *testing.T) { 182 skip.If(t, testEnv.OSType == "windows") 183 skip.If(t, testEnv.IsRemoteDaemon) 184 skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") 185 186 tests := []struct { 187 name string 188 mtu int 189 configFrom bool 190 args []string 191 }{ 192 { 193 name: "default value", 194 mtu: 1500, 195 args: []string{}, 196 }, 197 { 198 name: "cmdline value", 199 mtu: 1234, 200 args: []string{"--default-network-opt", "bridge=com.docker.network.driver.mtu=1234"}, 201 }, 202 { 203 name: "config-from value", 204 configFrom: true, 205 mtu: 1233, 206 args: []string{"--default-network-opt", "bridge=com.docker.network.driver.mtu=1234"}, 207 }, 208 } 209 210 for _, tc := range tests { 211 tc := tc 212 t.Run(tc.name, func(t *testing.T) { 213 d := daemon.New(t) 214 d.StartWithBusybox(t, tc.args...) 215 defer d.Stop(t) 216 c := d.NewClientT(t) 217 defer c.Close() 218 ctx := context.Background() 219 220 if tc.configFrom { 221 // Create a new network config 222 network.CreateNoError(ctx, t, c, "from-net", func(create *types.NetworkCreate) { 223 create.ConfigOnly = true 224 create.Options = map[string]string{ 225 "com.docker.network.driver.mtu": fmt.Sprint(tc.mtu), 226 } 227 }) 228 defer c.NetworkRemove(ctx, "from-net") 229 } 230 231 // Create a new network 232 networkName := "testnet" 233 network.CreateNoError(ctx, t, c, networkName, func(create *types.NetworkCreate) { 234 if tc.configFrom { 235 create.ConfigFrom = &ntypes.ConfigReference{ 236 Network: "from-net", 237 } 238 } 239 }) 240 defer c.NetworkRemove(ctx, networkName) 241 242 // Start a container to inspect the MTU of its network interface 243 id1 := container.Run(ctx, t, c, container.WithNetworkMode(networkName)) 244 defer c.ContainerRemove(ctx, id1, types.ContainerRemoveOptions{Force: true}) 245 246 result, err := container.Exec(ctx, c, id1, []string{"ip", "l", "show", "eth0"}) 247 assert.NilError(t, err) 248 assert.Check(t, is.Contains(result.Combined(), fmt.Sprintf(" mtu %d ", tc.mtu)), "Network MTU should have been set to %d", tc.mtu) 249 }) 250 } 251 }