github.com/brahmaroutu/docker@v1.2.1-0.20160809185609-eb28dde01f16/integration-cli/docker_cli_network_unix_test.go (about) 1 // +build !windows 2 3 package main 4 5 import ( 6 "encoding/json" 7 "fmt" 8 "io/ioutil" 9 "net" 10 "net/http" 11 "net/http/httptest" 12 "os" 13 "path/filepath" 14 "strings" 15 "time" 16 17 "github.com/docker/docker/pkg/integration/checker" 18 "github.com/docker/docker/pkg/stringid" 19 "github.com/docker/docker/runconfig" 20 "github.com/docker/engine-api/types" 21 "github.com/docker/engine-api/types/versions/v1p20" 22 "github.com/docker/libnetwork/driverapi" 23 remoteapi "github.com/docker/libnetwork/drivers/remote/api" 24 "github.com/docker/libnetwork/ipamapi" 25 remoteipam "github.com/docker/libnetwork/ipams/remote/api" 26 "github.com/docker/libnetwork/netlabel" 27 "github.com/go-check/check" 28 "github.com/vishvananda/netlink" 29 ) 30 31 const dummyNetworkDriver = "dummy-network-driver" 32 const dummyIpamDriver = "dummy-ipam-driver" 33 34 var remoteDriverNetworkRequest remoteapi.CreateNetworkRequest 35 36 func init() { 37 check.Suite(&DockerNetworkSuite{ 38 ds: &DockerSuite{}, 39 }) 40 } 41 42 type DockerNetworkSuite struct { 43 server *httptest.Server 44 ds *DockerSuite 45 d *Daemon 46 } 47 48 func (s *DockerNetworkSuite) SetUpTest(c *check.C) { 49 s.d = NewDaemon(c) 50 } 51 52 func (s *DockerNetworkSuite) TearDownTest(c *check.C) { 53 s.d.Stop() 54 s.ds.TearDownTest(c) 55 } 56 57 func (s *DockerNetworkSuite) SetUpSuite(c *check.C) { 58 mux := http.NewServeMux() 59 s.server = httptest.NewServer(mux) 60 c.Assert(s.server, check.NotNil, check.Commentf("Failed to start an HTTP Server")) 61 setupRemoteNetworkDrivers(c, mux, s.server.URL, dummyNetworkDriver, dummyIpamDriver) 62 } 63 64 func setupRemoteNetworkDrivers(c *check.C, mux *http.ServeMux, url, netDrv, ipamDrv string) { 65 66 mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) { 67 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 68 fmt.Fprintf(w, `{"Implements": ["%s", "%s"]}`, driverapi.NetworkPluginEndpointType, ipamapi.PluginEndpointType) 69 }) 70 71 // Network driver implementation 72 mux.HandleFunc(fmt.Sprintf("/%s.GetCapabilities", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 73 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 74 fmt.Fprintf(w, `{"Scope":"local"}`) 75 }) 76 77 mux.HandleFunc(fmt.Sprintf("/%s.CreateNetwork", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 78 err := json.NewDecoder(r.Body).Decode(&remoteDriverNetworkRequest) 79 if err != nil { 80 http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest) 81 return 82 } 83 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 84 fmt.Fprintf(w, "null") 85 }) 86 87 mux.HandleFunc(fmt.Sprintf("/%s.DeleteNetwork", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 88 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 89 fmt.Fprintf(w, "null") 90 }) 91 92 mux.HandleFunc(fmt.Sprintf("/%s.CreateEndpoint", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 93 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 94 fmt.Fprintf(w, `{"Interface":{"MacAddress":"a0:b1:c2:d3:e4:f5"}}`) 95 }) 96 97 mux.HandleFunc(fmt.Sprintf("/%s.Join", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 98 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 99 100 veth := &netlink.Veth{ 101 LinkAttrs: netlink.LinkAttrs{Name: "randomIfName", TxQLen: 0}, PeerName: "cnt0"} 102 if err := netlink.LinkAdd(veth); err != nil { 103 fmt.Fprintf(w, `{"Error":"failed to add veth pair: `+err.Error()+`"}`) 104 } else { 105 fmt.Fprintf(w, `{"InterfaceName":{ "SrcName":"cnt0", "DstPrefix":"veth"}}`) 106 } 107 }) 108 109 mux.HandleFunc(fmt.Sprintf("/%s.Leave", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 110 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 111 fmt.Fprintf(w, "null") 112 }) 113 114 mux.HandleFunc(fmt.Sprintf("/%s.DeleteEndpoint", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 115 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 116 if link, err := netlink.LinkByName("cnt0"); err == nil { 117 netlink.LinkDel(link) 118 } 119 fmt.Fprintf(w, "null") 120 }) 121 122 // Ipam Driver implementation 123 var ( 124 poolRequest remoteipam.RequestPoolRequest 125 poolReleaseReq remoteipam.ReleasePoolRequest 126 addressRequest remoteipam.RequestAddressRequest 127 addressReleaseReq remoteipam.ReleaseAddressRequest 128 lAS = "localAS" 129 gAS = "globalAS" 130 pool = "172.28.0.0/16" 131 poolID = lAS + "/" + pool 132 gw = "172.28.255.254/16" 133 ) 134 135 mux.HandleFunc(fmt.Sprintf("/%s.GetDefaultAddressSpaces", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 136 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 137 fmt.Fprintf(w, `{"LocalDefaultAddressSpace":"`+lAS+`", "GlobalDefaultAddressSpace": "`+gAS+`"}`) 138 }) 139 140 mux.HandleFunc(fmt.Sprintf("/%s.RequestPool", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 141 err := json.NewDecoder(r.Body).Decode(&poolRequest) 142 if err != nil { 143 http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest) 144 return 145 } 146 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 147 if poolRequest.AddressSpace != lAS && poolRequest.AddressSpace != gAS { 148 fmt.Fprintf(w, `{"Error":"Unknown address space in pool request: `+poolRequest.AddressSpace+`"}`) 149 } else if poolRequest.Pool != "" && poolRequest.Pool != pool { 150 fmt.Fprintf(w, `{"Error":"Cannot handle explicit pool requests yet"}`) 151 } else { 152 fmt.Fprintf(w, `{"PoolID":"`+poolID+`", "Pool":"`+pool+`"}`) 153 } 154 }) 155 156 mux.HandleFunc(fmt.Sprintf("/%s.RequestAddress", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 157 err := json.NewDecoder(r.Body).Decode(&addressRequest) 158 if err != nil { 159 http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest) 160 return 161 } 162 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 163 // make sure libnetwork is now querying on the expected pool id 164 if addressRequest.PoolID != poolID { 165 fmt.Fprintf(w, `{"Error":"unknown pool id"}`) 166 } else if addressRequest.Address != "" { 167 fmt.Fprintf(w, `{"Error":"Cannot handle explicit address requests yet"}`) 168 } else { 169 fmt.Fprintf(w, `{"Address":"`+gw+`"}`) 170 } 171 }) 172 173 mux.HandleFunc(fmt.Sprintf("/%s.ReleaseAddress", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 174 err := json.NewDecoder(r.Body).Decode(&addressReleaseReq) 175 if err != nil { 176 http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest) 177 return 178 } 179 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 180 // make sure libnetwork is now asking to release the expected address from the expected poolid 181 if addressRequest.PoolID != poolID { 182 fmt.Fprintf(w, `{"Error":"unknown pool id"}`) 183 } else if addressReleaseReq.Address != gw { 184 fmt.Fprintf(w, `{"Error":"unknown address"}`) 185 } else { 186 fmt.Fprintf(w, "null") 187 } 188 }) 189 190 mux.HandleFunc(fmt.Sprintf("/%s.ReleasePool", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 191 err := json.NewDecoder(r.Body).Decode(&poolReleaseReq) 192 if err != nil { 193 http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest) 194 return 195 } 196 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 197 // make sure libnetwork is now asking to release the expected poolid 198 if addressRequest.PoolID != poolID { 199 fmt.Fprintf(w, `{"Error":"unknown pool id"}`) 200 } else { 201 fmt.Fprintf(w, "null") 202 } 203 }) 204 205 err := os.MkdirAll("/etc/docker/plugins", 0755) 206 c.Assert(err, checker.IsNil) 207 208 fileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", netDrv) 209 err = ioutil.WriteFile(fileName, []byte(url), 0644) 210 c.Assert(err, checker.IsNil) 211 212 ipamFileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", ipamDrv) 213 err = ioutil.WriteFile(ipamFileName, []byte(url), 0644) 214 c.Assert(err, checker.IsNil) 215 } 216 217 func (s *DockerNetworkSuite) TearDownSuite(c *check.C) { 218 if s.server == nil { 219 return 220 } 221 222 s.server.Close() 223 224 err := os.RemoveAll("/etc/docker/plugins") 225 c.Assert(err, checker.IsNil) 226 } 227 228 func assertNwIsAvailable(c *check.C, name string) { 229 if !isNwPresent(c, name) { 230 c.Fatalf("Network %s not found in network ls o/p", name) 231 } 232 } 233 234 func assertNwNotAvailable(c *check.C, name string) { 235 if isNwPresent(c, name) { 236 c.Fatalf("Found network %s in network ls o/p", name) 237 } 238 } 239 240 func isNwPresent(c *check.C, name string) bool { 241 out, _ := dockerCmd(c, "network", "ls") 242 lines := strings.Split(out, "\n") 243 for i := 1; i < len(lines)-1; i++ { 244 netFields := strings.Fields(lines[i]) 245 if netFields[1] == name { 246 return true 247 } 248 } 249 return false 250 } 251 252 // assertNwList checks network list retrieved with ls command 253 // equals to expected network list 254 // note: out should be `network ls [option]` result 255 func assertNwList(c *check.C, out string, expectNws []string) { 256 lines := strings.Split(out, "\n") 257 var nwList []string 258 for _, line := range lines[1 : len(lines)-1] { 259 netFields := strings.Fields(line) 260 // wrap all network name in nwList 261 nwList = append(nwList, netFields[1]) 262 } 263 264 // network ls should contains all expected networks 265 c.Assert(nwList, checker.DeepEquals, expectNws) 266 } 267 268 func getNwResource(c *check.C, name string) *types.NetworkResource { 269 out, _ := dockerCmd(c, "network", "inspect", name) 270 nr := []types.NetworkResource{} 271 err := json.Unmarshal([]byte(out), &nr) 272 c.Assert(err, check.IsNil) 273 return &nr[0] 274 } 275 276 func (s *DockerNetworkSuite) TestDockerNetworkLsDefault(c *check.C) { 277 defaults := []string{"bridge", "host", "none"} 278 for _, nn := range defaults { 279 assertNwIsAvailable(c, nn) 280 } 281 } 282 283 func (s *DockerSuite) TestNetworkLsFormat(c *check.C) { 284 testRequires(c, DaemonIsLinux) 285 out, _ := dockerCmd(c, "network", "ls", "--format", "{{.Name}}") 286 lines := strings.Split(strings.TrimSpace(string(out)), "\n") 287 288 expected := []string{"bridge", "host", "none"} 289 var names []string 290 for _, l := range lines { 291 names = append(names, l) 292 } 293 c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names)) 294 } 295 296 func (s *DockerSuite) TestNetworkLsFormatDefaultFormat(c *check.C) { 297 testRequires(c, DaemonIsLinux) 298 299 config := `{ 300 "networksFormat": "{{ .Name }} default" 301 }` 302 d, err := ioutil.TempDir("", "integration-cli-") 303 c.Assert(err, checker.IsNil) 304 defer os.RemoveAll(d) 305 306 err = ioutil.WriteFile(filepath.Join(d, "config.json"), []byte(config), 0644) 307 c.Assert(err, checker.IsNil) 308 309 out, _ := dockerCmd(c, "--config", d, "network", "ls") 310 lines := strings.Split(strings.TrimSpace(string(out)), "\n") 311 312 expected := []string{"bridge default", "host default", "none default"} 313 var names []string 314 for _, l := range lines { 315 names = append(names, l) 316 } 317 c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names)) 318 } 319 320 func (s *DockerNetworkSuite) TestDockerNetworkCreatePredefined(c *check.C) { 321 predefined := []string{"bridge", "host", "none", "default"} 322 for _, net := range predefined { 323 // predefined networks can't be created again 324 out, _, err := dockerCmdWithError("network", "create", net) 325 c.Assert(err, checker.NotNil, check.Commentf("%v", out)) 326 } 327 } 328 329 func (s *DockerNetworkSuite) TestDockerNetworkCreateHostBind(c *check.C) { 330 dockerCmd(c, "network", "create", "--subnet=192.168.10.0/24", "--gateway=192.168.10.1", "-o", "com.docker.network.bridge.host_binding_ipv4=192.168.10.1", "testbind") 331 assertNwIsAvailable(c, "testbind") 332 333 out, _ := runSleepingContainer(c, "--net=testbind", "-p", "5000:5000") 334 id := strings.TrimSpace(out) 335 c.Assert(waitRun(id), checker.IsNil) 336 out, _ = dockerCmd(c, "ps") 337 c.Assert(out, checker.Contains, "192.168.10.1:5000->5000/tcp") 338 } 339 340 func (s *DockerNetworkSuite) TestDockerNetworkRmPredefined(c *check.C) { 341 predefined := []string{"bridge", "host", "none", "default"} 342 for _, net := range predefined { 343 // predefined networks can't be removed 344 out, _, err := dockerCmdWithError("network", "rm", net) 345 c.Assert(err, checker.NotNil, check.Commentf("%v", out)) 346 } 347 } 348 349 func (s *DockerNetworkSuite) TestDockerNetworkLsFilter(c *check.C) { 350 testNet := "testnet1" 351 testLabel := "foo" 352 testValue := "bar" 353 out, _ := dockerCmd(c, "network", "create", "dev") 354 defer func() { 355 dockerCmd(c, "network", "rm", "dev") 356 dockerCmd(c, "network", "rm", testNet) 357 }() 358 networkID := strings.TrimSpace(out) 359 360 // filter with partial ID 361 // only show 'dev' network 362 out, _ = dockerCmd(c, "network", "ls", "-f", "id="+networkID[0:5]) 363 assertNwList(c, out, []string{"dev"}) 364 365 out, _ = dockerCmd(c, "network", "ls", "-f", "name=dge") 366 assertNwList(c, out, []string{"bridge"}) 367 368 // only show built-in network (bridge, none, host) 369 out, _ = dockerCmd(c, "network", "ls", "-f", "type=builtin") 370 assertNwList(c, out, []string{"bridge", "host", "none"}) 371 372 // only show custom networks (dev) 373 out, _ = dockerCmd(c, "network", "ls", "-f", "type=custom") 374 assertNwList(c, out, []string{"dev"}) 375 376 // show all networks with filter 377 // it should be equivalent of ls without option 378 out, _ = dockerCmd(c, "network", "ls", "-f", "type=custom", "-f", "type=builtin") 379 assertNwList(c, out, []string{"bridge", "dev", "host", "none"}) 380 381 out, _ = dockerCmd(c, "network", "create", "--label", testLabel+"="+testValue, testNet) 382 assertNwIsAvailable(c, testNet) 383 384 out, _ = dockerCmd(c, "network", "ls", "-f", "label="+testLabel) 385 assertNwList(c, out, []string{testNet}) 386 387 out, _ = dockerCmd(c, "network", "ls", "-f", "label="+testLabel+"="+testValue) 388 assertNwList(c, out, []string{testNet}) 389 390 out, _ = dockerCmd(c, "network", "ls", "-f", "label=nonexistent") 391 outArr := strings.Split(strings.TrimSpace(out), "\n") 392 c.Assert(len(outArr), check.Equals, 1, check.Commentf("%s\n", out)) 393 394 out, _ = dockerCmd(c, "network", "ls", "-f", "driver=null") 395 assertNwList(c, out, []string{"none"}) 396 397 out, _ = dockerCmd(c, "network", "ls", "-f", "driver=host") 398 assertNwList(c, out, []string{"host"}) 399 400 out, _ = dockerCmd(c, "network", "ls", "-f", "driver=bridge") 401 assertNwList(c, out, []string{"bridge", "dev", testNet}) 402 } 403 404 func (s *DockerNetworkSuite) TestDockerNetworkCreateDelete(c *check.C) { 405 dockerCmd(c, "network", "create", "test") 406 assertNwIsAvailable(c, "test") 407 408 dockerCmd(c, "network", "rm", "test") 409 assertNwNotAvailable(c, "test") 410 } 411 412 func (s *DockerNetworkSuite) TestDockerNetworkCreateLabel(c *check.C) { 413 testNet := "testnetcreatelabel" 414 testLabel := "foo" 415 testValue := "bar" 416 417 dockerCmd(c, "network", "create", "--label", testLabel+"="+testValue, testNet) 418 assertNwIsAvailable(c, testNet) 419 420 out, _, err := dockerCmdWithError("network", "inspect", "--format={{ .Labels."+testLabel+" }}", testNet) 421 c.Assert(err, check.IsNil) 422 c.Assert(strings.TrimSpace(out), check.Equals, testValue) 423 424 dockerCmd(c, "network", "rm", testNet) 425 assertNwNotAvailable(c, testNet) 426 } 427 428 func (s *DockerSuite) TestDockerNetworkDeleteNotExists(c *check.C) { 429 out, _, err := dockerCmdWithError("network", "rm", "test") 430 c.Assert(err, checker.NotNil, check.Commentf("%v", out)) 431 } 432 433 func (s *DockerSuite) TestDockerNetworkDeleteMultiple(c *check.C) { 434 dockerCmd(c, "network", "create", "testDelMulti0") 435 assertNwIsAvailable(c, "testDelMulti0") 436 dockerCmd(c, "network", "create", "testDelMulti1") 437 assertNwIsAvailable(c, "testDelMulti1") 438 dockerCmd(c, "network", "create", "testDelMulti2") 439 assertNwIsAvailable(c, "testDelMulti2") 440 out, _ := dockerCmd(c, "run", "-d", "--net", "testDelMulti2", "busybox", "top") 441 containerID := strings.TrimSpace(out) 442 waitRun(containerID) 443 444 // delete three networks at the same time, since testDelMulti2 445 // contains active container, its deletion should fail. 446 out, _, err := dockerCmdWithError("network", "rm", "testDelMulti0", "testDelMulti1", "testDelMulti2") 447 // err should not be nil due to deleting testDelMulti2 failed. 448 c.Assert(err, checker.NotNil, check.Commentf("out: %s", out)) 449 // testDelMulti2 should fail due to network has active endpoints 450 c.Assert(out, checker.Contains, "has active endpoints") 451 assertNwNotAvailable(c, "testDelMulti0") 452 assertNwNotAvailable(c, "testDelMulti1") 453 // testDelMulti2 can't be deleted, so it should exist 454 assertNwIsAvailable(c, "testDelMulti2") 455 } 456 457 func (s *DockerSuite) TestDockerNetworkInspect(c *check.C) { 458 out, _ := dockerCmd(c, "network", "inspect", "host") 459 networkResources := []types.NetworkResource{} 460 err := json.Unmarshal([]byte(out), &networkResources) 461 c.Assert(err, check.IsNil) 462 c.Assert(networkResources, checker.HasLen, 1) 463 464 out, _ = dockerCmd(c, "network", "inspect", "--format={{ .Name }}", "host") 465 c.Assert(strings.TrimSpace(out), check.Equals, "host") 466 } 467 468 func (s *DockerSuite) TestDockerNetworkInspectWithID(c *check.C) { 469 out, _ := dockerCmd(c, "network", "create", "test2") 470 networkID := strings.TrimSpace(out) 471 assertNwIsAvailable(c, "test2") 472 out, _ = dockerCmd(c, "network", "inspect", "--format={{ .Id }}", "test2") 473 c.Assert(strings.TrimSpace(out), check.Equals, networkID) 474 475 out, _ = dockerCmd(c, "network", "inspect", "--format={{ .ID }}", "test2") 476 c.Assert(strings.TrimSpace(out), check.Equals, networkID) 477 } 478 479 func (s *DockerSuite) TestDockerInspectMultipleNetwork(c *check.C) { 480 out, _ := dockerCmd(c, "network", "inspect", "host", "none") 481 networkResources := []types.NetworkResource{} 482 err := json.Unmarshal([]byte(out), &networkResources) 483 c.Assert(err, check.IsNil) 484 c.Assert(networkResources, checker.HasLen, 2) 485 486 // Should print an error, return an exitCode 1 *but* should print the host network 487 out, exitCode, err := dockerCmdWithError("network", "inspect", "host", "nonexistent") 488 c.Assert(err, checker.NotNil) 489 c.Assert(exitCode, checker.Equals, 1) 490 c.Assert(out, checker.Contains, "Error: No such network: nonexistent") 491 networkResources = []types.NetworkResource{} 492 inspectOut := strings.SplitN(out, "\nError: No such network: nonexistent\n", 2)[0] 493 err = json.Unmarshal([]byte(inspectOut), &networkResources) 494 c.Assert(networkResources, checker.HasLen, 1) 495 496 // Should print an error and return an exitCode, nothing else 497 out, exitCode, err = dockerCmdWithError("network", "inspect", "nonexistent") 498 c.Assert(err, checker.NotNil) 499 c.Assert(exitCode, checker.Equals, 1) 500 c.Assert(out, checker.Contains, "Error: No such network: nonexistent") 501 } 502 503 func (s *DockerSuite) TestDockerInspectNetworkWithContainerName(c *check.C) { 504 dockerCmd(c, "network", "create", "brNetForInspect") 505 assertNwIsAvailable(c, "brNetForInspect") 506 defer func() { 507 dockerCmd(c, "network", "rm", "brNetForInspect") 508 assertNwNotAvailable(c, "brNetForInspect") 509 }() 510 511 out, _ := dockerCmd(c, "run", "-d", "--name", "testNetInspect1", "--net", "brNetForInspect", "busybox", "top") 512 c.Assert(waitRun("testNetInspect1"), check.IsNil) 513 containerID := strings.TrimSpace(out) 514 defer func() { 515 // we don't stop container by name, because we'll rename it later 516 dockerCmd(c, "stop", containerID) 517 }() 518 519 out, _ = dockerCmd(c, "network", "inspect", "brNetForInspect") 520 networkResources := []types.NetworkResource{} 521 err := json.Unmarshal([]byte(out), &networkResources) 522 c.Assert(err, check.IsNil) 523 c.Assert(networkResources, checker.HasLen, 1) 524 container, ok := networkResources[0].Containers[containerID] 525 c.Assert(ok, checker.True) 526 c.Assert(container.Name, checker.Equals, "testNetInspect1") 527 528 // rename container and check docker inspect output update 529 newName := "HappyNewName" 530 dockerCmd(c, "rename", "testNetInspect1", newName) 531 532 // check whether network inspect works properly 533 out, _ = dockerCmd(c, "network", "inspect", "brNetForInspect") 534 newNetRes := []types.NetworkResource{} 535 err = json.Unmarshal([]byte(out), &newNetRes) 536 c.Assert(err, check.IsNil) 537 c.Assert(newNetRes, checker.HasLen, 1) 538 container1, ok := newNetRes[0].Containers[containerID] 539 c.Assert(ok, checker.True) 540 c.Assert(container1.Name, checker.Equals, newName) 541 542 } 543 544 func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnect(c *check.C) { 545 dockerCmd(c, "network", "create", "test") 546 assertNwIsAvailable(c, "test") 547 nr := getNwResource(c, "test") 548 549 c.Assert(nr.Name, checker.Equals, "test") 550 c.Assert(len(nr.Containers), checker.Equals, 0) 551 552 // run a container 553 out, _ := dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top") 554 c.Assert(waitRun("test"), check.IsNil) 555 containerID := strings.TrimSpace(out) 556 557 // connect the container to the test network 558 dockerCmd(c, "network", "connect", "test", containerID) 559 560 // inspect the network to make sure container is connected 561 nr = getNetworkResource(c, nr.ID) 562 c.Assert(len(nr.Containers), checker.Equals, 1) 563 c.Assert(nr.Containers[containerID], check.NotNil) 564 565 // check if container IP matches network inspect 566 ip, _, err := net.ParseCIDR(nr.Containers[containerID].IPv4Address) 567 c.Assert(err, check.IsNil) 568 containerIP := findContainerIP(c, "test", "test") 569 c.Assert(ip.String(), checker.Equals, containerIP) 570 571 // disconnect container from the network 572 dockerCmd(c, "network", "disconnect", "test", containerID) 573 nr = getNwResource(c, "test") 574 c.Assert(nr.Name, checker.Equals, "test") 575 c.Assert(len(nr.Containers), checker.Equals, 0) 576 577 // run another container 578 out, _ = dockerCmd(c, "run", "-d", "--net", "test", "--name", "test2", "busybox", "top") 579 c.Assert(waitRun("test2"), check.IsNil) 580 containerID = strings.TrimSpace(out) 581 582 nr = getNwResource(c, "test") 583 c.Assert(nr.Name, checker.Equals, "test") 584 c.Assert(len(nr.Containers), checker.Equals, 1) 585 586 // force disconnect the container to the test network 587 dockerCmd(c, "network", "disconnect", "-f", "test", containerID) 588 589 nr = getNwResource(c, "test") 590 c.Assert(nr.Name, checker.Equals, "test") 591 c.Assert(len(nr.Containers), checker.Equals, 0) 592 593 dockerCmd(c, "network", "rm", "test") 594 assertNwNotAvailable(c, "test") 595 } 596 597 func (s *DockerNetworkSuite) TestDockerNetworkIpamMultipleNetworks(c *check.C) { 598 // test0 bridge network 599 dockerCmd(c, "network", "create", "--subnet=192.168.0.0/16", "test1") 600 assertNwIsAvailable(c, "test1") 601 602 // test2 bridge network does not overlap 603 dockerCmd(c, "network", "create", "--subnet=192.169.0.0/16", "test2") 604 assertNwIsAvailable(c, "test2") 605 606 // for networks w/o ipam specified, docker will choose proper non-overlapping subnets 607 dockerCmd(c, "network", "create", "test3") 608 assertNwIsAvailable(c, "test3") 609 dockerCmd(c, "network", "create", "test4") 610 assertNwIsAvailable(c, "test4") 611 dockerCmd(c, "network", "create", "test5") 612 assertNwIsAvailable(c, "test5") 613 614 // test network with multiple subnets 615 // bridge network doesn't support multiple subnets. hence, use a dummy driver that supports 616 617 dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, "--subnet=192.168.0.0/16", "--subnet=192.170.0.0/16", "test6") 618 assertNwIsAvailable(c, "test6") 619 620 // test network with multiple subnets with valid ipam combinations 621 // also check same subnet across networks when the driver supports it. 622 dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, 623 "--subnet=192.168.0.0/16", "--subnet=192.170.0.0/16", 624 "--gateway=192.168.0.100", "--gateway=192.170.0.100", 625 "--ip-range=192.168.1.0/24", 626 "--aux-address", "a=192.168.1.5", "--aux-address", "b=192.168.1.6", 627 "--aux-address", "a=192.170.1.5", "--aux-address", "b=192.170.1.6", 628 "test7") 629 assertNwIsAvailable(c, "test7") 630 631 // cleanup 632 for i := 1; i < 8; i++ { 633 dockerCmd(c, "network", "rm", fmt.Sprintf("test%d", i)) 634 } 635 } 636 637 func (s *DockerNetworkSuite) TestDockerNetworkCustomIpam(c *check.C) { 638 // Create a bridge network using custom ipam driver 639 dockerCmd(c, "network", "create", "--ipam-driver", dummyIpamDriver, "br0") 640 assertNwIsAvailable(c, "br0") 641 642 // Verify expected network ipam fields are there 643 nr := getNetworkResource(c, "br0") 644 c.Assert(nr.Driver, checker.Equals, "bridge") 645 c.Assert(nr.IPAM.Driver, checker.Equals, dummyIpamDriver) 646 647 // remove network and exercise remote ipam driver 648 dockerCmd(c, "network", "rm", "br0") 649 assertNwNotAvailable(c, "br0") 650 } 651 652 func (s *DockerNetworkSuite) TestDockerNetworkIpamOptions(c *check.C) { 653 // Create a bridge network using custom ipam driver and options 654 dockerCmd(c, "network", "create", "--ipam-driver", dummyIpamDriver, "--ipam-opt", "opt1=drv1", "--ipam-opt", "opt2=drv2", "br0") 655 assertNwIsAvailable(c, "br0") 656 657 // Verify expected network ipam options 658 nr := getNetworkResource(c, "br0") 659 opts := nr.IPAM.Options 660 c.Assert(opts["opt1"], checker.Equals, "drv1") 661 c.Assert(opts["opt2"], checker.Equals, "drv2") 662 } 663 664 func (s *DockerNetworkSuite) TestDockerNetworkInspectDefault(c *check.C) { 665 nr := getNetworkResource(c, "none") 666 c.Assert(nr.Driver, checker.Equals, "null") 667 c.Assert(nr.Scope, checker.Equals, "local") 668 c.Assert(nr.Internal, checker.Equals, false) 669 c.Assert(nr.EnableIPv6, checker.Equals, false) 670 c.Assert(nr.IPAM.Driver, checker.Equals, "default") 671 c.Assert(len(nr.IPAM.Config), checker.Equals, 0) 672 673 nr = getNetworkResource(c, "host") 674 c.Assert(nr.Driver, checker.Equals, "host") 675 c.Assert(nr.Scope, checker.Equals, "local") 676 c.Assert(nr.Internal, checker.Equals, false) 677 c.Assert(nr.EnableIPv6, checker.Equals, false) 678 c.Assert(nr.IPAM.Driver, checker.Equals, "default") 679 c.Assert(len(nr.IPAM.Config), checker.Equals, 0) 680 681 nr = getNetworkResource(c, "bridge") 682 c.Assert(nr.Driver, checker.Equals, "bridge") 683 c.Assert(nr.Scope, checker.Equals, "local") 684 c.Assert(nr.Internal, checker.Equals, false) 685 c.Assert(nr.EnableIPv6, checker.Equals, false) 686 c.Assert(nr.IPAM.Driver, checker.Equals, "default") 687 c.Assert(len(nr.IPAM.Config), checker.Equals, 1) 688 c.Assert(nr.IPAM.Config[0].Subnet, checker.NotNil) 689 c.Assert(nr.IPAM.Config[0].Gateway, checker.NotNil) 690 } 691 692 func (s *DockerNetworkSuite) TestDockerNetworkInspectCustomUnspecified(c *check.C) { 693 // if unspecified, network subnet will be selected from inside preferred pool 694 dockerCmd(c, "network", "create", "test01") 695 assertNwIsAvailable(c, "test01") 696 697 nr := getNetworkResource(c, "test01") 698 c.Assert(nr.Driver, checker.Equals, "bridge") 699 c.Assert(nr.Scope, checker.Equals, "local") 700 c.Assert(nr.Internal, checker.Equals, false) 701 c.Assert(nr.EnableIPv6, checker.Equals, false) 702 c.Assert(nr.IPAM.Driver, checker.Equals, "default") 703 c.Assert(len(nr.IPAM.Config), checker.Equals, 1) 704 c.Assert(nr.IPAM.Config[0].Subnet, checker.NotNil) 705 c.Assert(nr.IPAM.Config[0].Gateway, checker.NotNil) 706 707 dockerCmd(c, "network", "rm", "test01") 708 assertNwNotAvailable(c, "test01") 709 } 710 711 func (s *DockerNetworkSuite) TestDockerNetworkInspectCustomSpecified(c *check.C) { 712 dockerCmd(c, "network", "create", "--driver=bridge", "--ipv6", "--subnet=172.28.0.0/16", "--ip-range=172.28.5.0/24", "--gateway=172.28.5.254", "br0") 713 assertNwIsAvailable(c, "br0") 714 715 nr := getNetworkResource(c, "br0") 716 c.Assert(nr.Driver, checker.Equals, "bridge") 717 c.Assert(nr.Scope, checker.Equals, "local") 718 c.Assert(nr.Internal, checker.Equals, false) 719 c.Assert(nr.EnableIPv6, checker.Equals, true) 720 c.Assert(nr.IPAM.Driver, checker.Equals, "default") 721 c.Assert(len(nr.IPAM.Config), checker.Equals, 1) 722 c.Assert(nr.IPAM.Config[0].Subnet, checker.Equals, "172.28.0.0/16") 723 c.Assert(nr.IPAM.Config[0].IPRange, checker.Equals, "172.28.5.0/24") 724 c.Assert(nr.IPAM.Config[0].Gateway, checker.Equals, "172.28.5.254") 725 c.Assert(nr.Internal, checker.False) 726 dockerCmd(c, "network", "rm", "br0") 727 assertNwNotAvailable(c, "test01") 728 } 729 730 func (s *DockerNetworkSuite) TestDockerNetworkIpamInvalidCombinations(c *check.C) { 731 // network with ip-range out of subnet range 732 _, _, err := dockerCmdWithError("network", "create", "--subnet=192.168.0.0/16", "--ip-range=192.170.0.0/16", "test") 733 c.Assert(err, check.NotNil) 734 735 // network with multiple gateways for a single subnet 736 _, _, err = dockerCmdWithError("network", "create", "--subnet=192.168.0.0/16", "--gateway=192.168.0.1", "--gateway=192.168.0.2", "test") 737 c.Assert(err, check.NotNil) 738 739 // Multiple overlapping subnets in the same network must fail 740 _, _, err = dockerCmdWithError("network", "create", "--subnet=192.168.0.0/16", "--subnet=192.168.1.0/16", "test") 741 c.Assert(err, check.NotNil) 742 743 // overlapping subnets across networks must fail 744 // create a valid test0 network 745 dockerCmd(c, "network", "create", "--subnet=192.168.0.0/16", "test0") 746 assertNwIsAvailable(c, "test0") 747 // create an overlapping test1 network 748 _, _, err = dockerCmdWithError("network", "create", "--subnet=192.168.128.0/17", "test1") 749 c.Assert(err, check.NotNil) 750 dockerCmd(c, "network", "rm", "test0") 751 assertNwNotAvailable(c, "test0") 752 } 753 754 func (s *DockerNetworkSuite) TestDockerNetworkDriverOptions(c *check.C) { 755 dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, "-o", "opt1=drv1", "-o", "opt2=drv2", "testopt") 756 assertNwIsAvailable(c, "testopt") 757 gopts := remoteDriverNetworkRequest.Options[netlabel.GenericData] 758 c.Assert(gopts, checker.NotNil) 759 opts, ok := gopts.(map[string]interface{}) 760 c.Assert(ok, checker.Equals, true) 761 c.Assert(opts["opt1"], checker.Equals, "drv1") 762 c.Assert(opts["opt2"], checker.Equals, "drv2") 763 dockerCmd(c, "network", "rm", "testopt") 764 assertNwNotAvailable(c, "testopt") 765 766 } 767 768 func (s *DockerDaemonSuite) TestDockerNetworkNoDiscoveryDefaultBridgeNetwork(c *check.C) { 769 testRequires(c, ExecSupport) 770 // On default bridge network built-in service discovery should not happen 771 hostsFile := "/etc/hosts" 772 bridgeName := "external-bridge" 773 bridgeIP := "192.169.255.254/24" 774 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 775 c.Assert(err, check.IsNil, check.Commentf(out)) 776 defer deleteInterface(c, bridgeName) 777 778 err = s.d.StartWithBusybox("--bridge", bridgeName) 779 c.Assert(err, check.IsNil) 780 defer s.d.Restart() 781 782 // run two containers and store first container's etc/hosts content 783 out, err = s.d.Cmd("run", "-d", "busybox", "top") 784 c.Assert(err, check.IsNil) 785 cid1 := strings.TrimSpace(out) 786 defer s.d.Cmd("stop", cid1) 787 788 hosts, err := s.d.Cmd("exec", cid1, "cat", hostsFile) 789 c.Assert(err, checker.IsNil) 790 791 out, err = s.d.Cmd("run", "-d", "--name", "container2", "busybox", "top") 792 c.Assert(err, check.IsNil) 793 cid2 := strings.TrimSpace(out) 794 795 // verify first container's etc/hosts file has not changed after spawning the second named container 796 hostsPost, err := s.d.Cmd("exec", cid1, "cat", hostsFile) 797 c.Assert(err, checker.IsNil) 798 c.Assert(string(hosts), checker.Equals, string(hostsPost), 799 check.Commentf("Unexpected %s change on second container creation", hostsFile)) 800 801 // stop container 2 and verify first container's etc/hosts has not changed 802 _, err = s.d.Cmd("stop", cid2) 803 c.Assert(err, check.IsNil) 804 805 hostsPost, err = s.d.Cmd("exec", cid1, "cat", hostsFile) 806 c.Assert(err, checker.IsNil) 807 c.Assert(string(hosts), checker.Equals, string(hostsPost), 808 check.Commentf("Unexpected %s change on second container creation", hostsFile)) 809 810 // but discovery is on when connecting to non default bridge network 811 network := "anotherbridge" 812 out, err = s.d.Cmd("network", "create", network) 813 c.Assert(err, check.IsNil, check.Commentf(out)) 814 defer s.d.Cmd("network", "rm", network) 815 816 out, err = s.d.Cmd("network", "connect", network, cid1) 817 c.Assert(err, check.IsNil, check.Commentf(out)) 818 819 hosts, err = s.d.Cmd("exec", cid1, "cat", hostsFile) 820 c.Assert(err, checker.IsNil) 821 822 hostsPost, err = s.d.Cmd("exec", cid1, "cat", hostsFile) 823 c.Assert(err, checker.IsNil) 824 c.Assert(string(hosts), checker.Equals, string(hostsPost), 825 check.Commentf("Unexpected %s change on second network connection", hostsFile)) 826 } 827 828 func (s *DockerNetworkSuite) TestDockerNetworkAnonymousEndpoint(c *check.C) { 829 testRequires(c, ExecSupport, NotArm) 830 hostsFile := "/etc/hosts" 831 cstmBridgeNw := "custom-bridge-nw" 832 cstmBridgeNw1 := "custom-bridge-nw1" 833 834 dockerCmd(c, "network", "create", "-d", "bridge", cstmBridgeNw) 835 assertNwIsAvailable(c, cstmBridgeNw) 836 837 // run two anonymous containers and store their etc/hosts content 838 out, _ := dockerCmd(c, "run", "-d", "--net", cstmBridgeNw, "busybox", "top") 839 cid1 := strings.TrimSpace(out) 840 841 hosts1, err := readContainerFileWithExec(cid1, hostsFile) 842 c.Assert(err, checker.IsNil) 843 844 out, _ = dockerCmd(c, "run", "-d", "--net", cstmBridgeNw, "busybox", "top") 845 cid2 := strings.TrimSpace(out) 846 847 hosts2, err := readContainerFileWithExec(cid2, hostsFile) 848 c.Assert(err, checker.IsNil) 849 850 // verify first container etc/hosts file has not changed 851 hosts1post, err := readContainerFileWithExec(cid1, hostsFile) 852 c.Assert(err, checker.IsNil) 853 c.Assert(string(hosts1), checker.Equals, string(hosts1post), 854 check.Commentf("Unexpected %s change on anonymous container creation", hostsFile)) 855 856 // Connect the 2nd container to a new network and verify the 857 // first container /etc/hosts file still hasn't changed. 858 dockerCmd(c, "network", "create", "-d", "bridge", cstmBridgeNw1) 859 assertNwIsAvailable(c, cstmBridgeNw1) 860 861 dockerCmd(c, "network", "connect", cstmBridgeNw1, cid2) 862 863 hosts2, err = readContainerFileWithExec(cid2, hostsFile) 864 c.Assert(err, checker.IsNil) 865 866 hosts1post, err = readContainerFileWithExec(cid1, hostsFile) 867 c.Assert(err, checker.IsNil) 868 c.Assert(string(hosts1), checker.Equals, string(hosts1post), 869 check.Commentf("Unexpected %s change on container connect", hostsFile)) 870 871 // start a named container 872 cName := "AnyName" 873 out, _ = dockerCmd(c, "run", "-d", "--net", cstmBridgeNw, "--name", cName, "busybox", "top") 874 cid3 := strings.TrimSpace(out) 875 876 // verify that container 1 and 2 can ping the named container 877 dockerCmd(c, "exec", cid1, "ping", "-c", "1", cName) 878 dockerCmd(c, "exec", cid2, "ping", "-c", "1", cName) 879 880 // Stop named container and verify first two containers' etc/hosts file hasn't changed 881 dockerCmd(c, "stop", cid3) 882 hosts1post, err = readContainerFileWithExec(cid1, hostsFile) 883 c.Assert(err, checker.IsNil) 884 c.Assert(string(hosts1), checker.Equals, string(hosts1post), 885 check.Commentf("Unexpected %s change on name container creation", hostsFile)) 886 887 hosts2post, err := readContainerFileWithExec(cid2, hostsFile) 888 c.Assert(err, checker.IsNil) 889 c.Assert(string(hosts2), checker.Equals, string(hosts2post), 890 check.Commentf("Unexpected %s change on name container creation", hostsFile)) 891 892 // verify that container 1 and 2 can't ping the named container now 893 _, _, err = dockerCmdWithError("exec", cid1, "ping", "-c", "1", cName) 894 c.Assert(err, check.NotNil) 895 _, _, err = dockerCmdWithError("exec", cid2, "ping", "-c", "1", cName) 896 c.Assert(err, check.NotNil) 897 } 898 899 func (s *DockerNetworkSuite) TestDockerNetworkLinkOnDefaultNetworkOnly(c *check.C) { 900 // Legacy Link feature must work only on default network, and not across networks 901 cnt1 := "container1" 902 cnt2 := "container2" 903 network := "anotherbridge" 904 905 // Run first container on default network 906 dockerCmd(c, "run", "-d", "--name", cnt1, "busybox", "top") 907 908 // Create another network and run the second container on it 909 dockerCmd(c, "network", "create", network) 910 assertNwIsAvailable(c, network) 911 dockerCmd(c, "run", "-d", "--net", network, "--name", cnt2, "busybox", "top") 912 913 // Try launching a container on default network, linking to the first container. Must succeed 914 dockerCmd(c, "run", "-d", "--link", fmt.Sprintf("%s:%s", cnt1, cnt1), "busybox", "top") 915 916 // Try launching a container on default network, linking to the second container. Must fail 917 _, _, err := dockerCmdWithError("run", "-d", "--link", fmt.Sprintf("%s:%s", cnt2, cnt2), "busybox", "top") 918 c.Assert(err, checker.NotNil) 919 920 // Connect second container to default network. Now a container on default network can link to it 921 dockerCmd(c, "network", "connect", "bridge", cnt2) 922 dockerCmd(c, "run", "-d", "--link", fmt.Sprintf("%s:%s", cnt2, cnt2), "busybox", "top") 923 } 924 925 func (s *DockerNetworkSuite) TestDockerNetworkOverlayPortMapping(c *check.C) { 926 // Verify exposed ports are present in ps output when running a container on 927 // a network managed by a driver which does not provide the default gateway 928 // for the container 929 nwn := "ov" 930 ctn := "bb" 931 port1 := 80 932 port2 := 443 933 expose1 := fmt.Sprintf("--expose=%d", port1) 934 expose2 := fmt.Sprintf("--expose=%d", port2) 935 936 dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, nwn) 937 assertNwIsAvailable(c, nwn) 938 939 dockerCmd(c, "run", "-d", "--net", nwn, "--name", ctn, expose1, expose2, "busybox", "top") 940 941 // Check docker ps o/p for last created container reports the unpublished ports 942 unpPort1 := fmt.Sprintf("%d/tcp", port1) 943 unpPort2 := fmt.Sprintf("%d/tcp", port2) 944 out, _ := dockerCmd(c, "ps", "-n=1") 945 // Missing unpublished ports in docker ps output 946 c.Assert(out, checker.Contains, unpPort1) 947 // Missing unpublished ports in docker ps output 948 c.Assert(out, checker.Contains, unpPort2) 949 } 950 951 func (s *DockerNetworkSuite) TestDockerNetworkDriverUngracefulRestart(c *check.C) { 952 testRequires(c, DaemonIsLinux, NotUserNamespace) 953 dnd := "dnd" 954 did := "did" 955 956 mux := http.NewServeMux() 957 server := httptest.NewServer(mux) 958 setupRemoteNetworkDrivers(c, mux, server.URL, dnd, did) 959 960 s.d.StartWithBusybox() 961 _, err := s.d.Cmd("network", "create", "-d", dnd, "--subnet", "1.1.1.0/24", "net1") 962 c.Assert(err, checker.IsNil) 963 964 _, err = s.d.Cmd("run", "-itd", "--net", "net1", "--name", "foo", "--ip", "1.1.1.10", "busybox", "sh") 965 c.Assert(err, checker.IsNil) 966 967 // Kill daemon and restart 968 if err = s.d.cmd.Process.Kill(); err != nil { 969 c.Fatal(err) 970 } 971 972 server.Close() 973 974 startTime := time.Now().Unix() 975 if err = s.d.Restart(); err != nil { 976 c.Fatal(err) 977 } 978 lapse := time.Now().Unix() - startTime 979 if lapse > 60 { 980 // In normal scenarios, daemon restart takes ~1 second. 981 // Plugin retry mechanism can delay the daemon start. systemd may not like it. 982 // Avoid accessing plugins during daemon bootup 983 c.Logf("daemon restart took too long : %d seconds", lapse) 984 } 985 986 // Restart the custom dummy plugin 987 mux = http.NewServeMux() 988 server = httptest.NewServer(mux) 989 setupRemoteNetworkDrivers(c, mux, server.URL, dnd, did) 990 991 // trying to reuse the same ip must succeed 992 _, err = s.d.Cmd("run", "-itd", "--net", "net1", "--name", "bar", "--ip", "1.1.1.10", "busybox", "sh") 993 c.Assert(err, checker.IsNil) 994 } 995 996 func (s *DockerNetworkSuite) TestDockerNetworkMacInspect(c *check.C) { 997 // Verify endpoint MAC address is correctly populated in container's network settings 998 nwn := "ov" 999 ctn := "bb" 1000 1001 dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, nwn) 1002 assertNwIsAvailable(c, nwn) 1003 1004 dockerCmd(c, "run", "-d", "--net", nwn, "--name", ctn, "busybox", "top") 1005 1006 mac := inspectField(c, ctn, "NetworkSettings.Networks."+nwn+".MacAddress") 1007 c.Assert(mac, checker.Equals, "a0:b1:c2:d3:e4:f5") 1008 } 1009 1010 func (s *DockerSuite) TestInspectApiMultipleNetworks(c *check.C) { 1011 dockerCmd(c, "network", "create", "mybridge1") 1012 dockerCmd(c, "network", "create", "mybridge2") 1013 out, _ := dockerCmd(c, "run", "-d", "busybox", "top") 1014 id := strings.TrimSpace(out) 1015 c.Assert(waitRun(id), check.IsNil) 1016 1017 dockerCmd(c, "network", "connect", "mybridge1", id) 1018 dockerCmd(c, "network", "connect", "mybridge2", id) 1019 1020 body := getInspectBody(c, "v1.20", id) 1021 var inspect120 v1p20.ContainerJSON 1022 err := json.Unmarshal(body, &inspect120) 1023 c.Assert(err, checker.IsNil) 1024 1025 versionedIP := inspect120.NetworkSettings.IPAddress 1026 1027 body = getInspectBody(c, "v1.21", id) 1028 var inspect121 types.ContainerJSON 1029 err = json.Unmarshal(body, &inspect121) 1030 c.Assert(err, checker.IsNil) 1031 c.Assert(inspect121.NetworkSettings.Networks, checker.HasLen, 3) 1032 1033 bridge := inspect121.NetworkSettings.Networks["bridge"] 1034 c.Assert(bridge.IPAddress, checker.Equals, versionedIP) 1035 c.Assert(bridge.IPAddress, checker.Equals, inspect121.NetworkSettings.IPAddress) 1036 } 1037 1038 func connectContainerToNetworks(c *check.C, d *Daemon, cName string, nws []string) { 1039 // Run a container on the default network 1040 out, err := d.Cmd("run", "-d", "--name", cName, "busybox", "top") 1041 c.Assert(err, checker.IsNil, check.Commentf(out)) 1042 1043 // Attach the container to other networks 1044 for _, nw := range nws { 1045 out, err = d.Cmd("network", "create", nw) 1046 c.Assert(err, checker.IsNil, check.Commentf(out)) 1047 out, err = d.Cmd("network", "connect", nw, cName) 1048 c.Assert(err, checker.IsNil, check.Commentf(out)) 1049 } 1050 } 1051 1052 func verifyContainerIsConnectedToNetworks(c *check.C, d *Daemon, cName string, nws []string) { 1053 // Verify container is connected to all the networks 1054 for _, nw := range nws { 1055 out, err := d.Cmd("inspect", "-f", fmt.Sprintf("{{.NetworkSettings.Networks.%s}}", nw), cName) 1056 c.Assert(err, checker.IsNil, check.Commentf(out)) 1057 c.Assert(out, checker.Not(checker.Equals), "<no value>\n") 1058 } 1059 } 1060 1061 func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksGracefulDaemonRestart(c *check.C) { 1062 cName := "bb" 1063 nwList := []string{"nw1", "nw2", "nw3"} 1064 1065 s.d.StartWithBusybox() 1066 1067 connectContainerToNetworks(c, s.d, cName, nwList) 1068 verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList) 1069 1070 // Reload daemon 1071 s.d.Restart() 1072 1073 _, err := s.d.Cmd("start", cName) 1074 c.Assert(err, checker.IsNil) 1075 1076 verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList) 1077 } 1078 1079 func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksUngracefulDaemonRestart(c *check.C) { 1080 cName := "cc" 1081 nwList := []string{"nw1", "nw2", "nw3"} 1082 1083 s.d.StartWithBusybox() 1084 1085 connectContainerToNetworks(c, s.d, cName, nwList) 1086 verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList) 1087 1088 // Kill daemon and restart 1089 if err := s.d.cmd.Process.Kill(); err != nil { 1090 c.Fatal(err) 1091 } 1092 s.d.Restart() 1093 1094 // Restart container 1095 _, err := s.d.Cmd("start", cName) 1096 c.Assert(err, checker.IsNil) 1097 1098 verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList) 1099 } 1100 1101 func (s *DockerNetworkSuite) TestDockerNetworkRunNetByID(c *check.C) { 1102 out, _ := dockerCmd(c, "network", "create", "one") 1103 containerOut, _, err := dockerCmdWithError("run", "-d", "--net", strings.TrimSpace(out), "busybox", "top") 1104 c.Assert(err, checker.IsNil, check.Commentf(containerOut)) 1105 } 1106 1107 func (s *DockerNetworkSuite) TestDockerNetworkHostModeUngracefulDaemonRestart(c *check.C) { 1108 testRequires(c, DaemonIsLinux, NotUserNamespace) 1109 s.d.StartWithBusybox() 1110 1111 // Run a few containers on host network 1112 for i := 0; i < 10; i++ { 1113 cName := fmt.Sprintf("hostc-%d", i) 1114 out, err := s.d.Cmd("run", "-d", "--name", cName, "--net=host", "--restart=always", "busybox", "top") 1115 c.Assert(err, checker.IsNil, check.Commentf(out)) 1116 1117 // verfiy container has finished starting before killing daemon 1118 err = s.d.waitRun(cName) 1119 c.Assert(err, checker.IsNil) 1120 } 1121 1122 // Kill daemon ungracefully and restart 1123 if err := s.d.cmd.Process.Kill(); err != nil { 1124 c.Fatal(err) 1125 } 1126 if err := s.d.Restart(); err != nil { 1127 c.Fatal(err) 1128 } 1129 1130 // make sure all the containers are up and running 1131 for i := 0; i < 10; i++ { 1132 err := s.d.waitRun(fmt.Sprintf("hostc-%d", i)) 1133 c.Assert(err, checker.IsNil) 1134 } 1135 } 1136 1137 func (s *DockerNetworkSuite) TestDockerNetworkConnectToHostFromOtherNetwork(c *check.C) { 1138 dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top") 1139 c.Assert(waitRun("container1"), check.IsNil) 1140 dockerCmd(c, "network", "disconnect", "bridge", "container1") 1141 out, _, err := dockerCmdWithError("network", "connect", "host", "container1") 1142 c.Assert(err, checker.NotNil, check.Commentf(out)) 1143 c.Assert(out, checker.Contains, runconfig.ErrConflictHostNetwork.Error()) 1144 } 1145 1146 func (s *DockerNetworkSuite) TestDockerNetworkDisconnectFromHost(c *check.C) { 1147 dockerCmd(c, "run", "-d", "--name", "container1", "--net=host", "busybox", "top") 1148 c.Assert(waitRun("container1"), check.IsNil) 1149 out, _, err := dockerCmdWithError("network", "disconnect", "host", "container1") 1150 c.Assert(err, checker.NotNil, check.Commentf("Should err out disconnect from host")) 1151 c.Assert(out, checker.Contains, runconfig.ErrConflictHostNetwork.Error()) 1152 } 1153 1154 func (s *DockerNetworkSuite) TestDockerNetworkConnectWithPortMapping(c *check.C) { 1155 testRequires(c, NotArm) 1156 dockerCmd(c, "network", "create", "test1") 1157 dockerCmd(c, "run", "-d", "--name", "c1", "-p", "5000:5000", "busybox", "top") 1158 c.Assert(waitRun("c1"), check.IsNil) 1159 dockerCmd(c, "network", "connect", "test1", "c1") 1160 } 1161 1162 func verifyPortMap(c *check.C, container, port, originalMapping string, mustBeEqual bool) { 1163 chk := checker.Equals 1164 if !mustBeEqual { 1165 chk = checker.Not(checker.Equals) 1166 } 1167 currentMapping, _ := dockerCmd(c, "port", container, port) 1168 c.Assert(currentMapping, chk, originalMapping) 1169 } 1170 1171 func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnectWithPortMapping(c *check.C) { 1172 // Connect and disconnect a container with explicit and non-explicit 1173 // host port mapping to/from networks which do cause and do not cause 1174 // the container default gateway to change, and verify docker port cmd 1175 // returns congruent information 1176 testRequires(c, NotArm) 1177 cnt := "c1" 1178 dockerCmd(c, "network", "create", "aaa") 1179 dockerCmd(c, "network", "create", "ccc") 1180 1181 dockerCmd(c, "run", "-d", "--name", cnt, "-p", "9000:90", "-p", "70", "busybox", "top") 1182 c.Assert(waitRun(cnt), check.IsNil) 1183 curPortMap, _ := dockerCmd(c, "port", cnt, "70") 1184 curExplPortMap, _ := dockerCmd(c, "port", cnt, "90") 1185 1186 // Connect to a network which causes the container's default gw switch 1187 dockerCmd(c, "network", "connect", "aaa", cnt) 1188 verifyPortMap(c, cnt, "70", curPortMap, false) 1189 verifyPortMap(c, cnt, "90", curExplPortMap, true) 1190 1191 // Read current mapping 1192 curPortMap, _ = dockerCmd(c, "port", cnt, "70") 1193 1194 // Disconnect from a network which causes the container's default gw switch 1195 dockerCmd(c, "network", "disconnect", "aaa", cnt) 1196 verifyPortMap(c, cnt, "70", curPortMap, false) 1197 verifyPortMap(c, cnt, "90", curExplPortMap, true) 1198 1199 // Read current mapping 1200 curPortMap, _ = dockerCmd(c, "port", cnt, "70") 1201 1202 // Connect to a network which does not cause the container's default gw switch 1203 dockerCmd(c, "network", "connect", "ccc", cnt) 1204 verifyPortMap(c, cnt, "70", curPortMap, true) 1205 verifyPortMap(c, cnt, "90", curExplPortMap, true) 1206 } 1207 1208 func (s *DockerNetworkSuite) TestDockerNetworkConnectWithMac(c *check.C) { 1209 macAddress := "02:42:ac:11:00:02" 1210 dockerCmd(c, "network", "create", "mynetwork") 1211 dockerCmd(c, "run", "--name=test", "-d", "--mac-address", macAddress, "busybox", "top") 1212 c.Assert(waitRun("test"), check.IsNil) 1213 mac1 := inspectField(c, "test", "NetworkSettings.Networks.bridge.MacAddress") 1214 c.Assert(strings.TrimSpace(mac1), checker.Equals, macAddress) 1215 dockerCmd(c, "network", "connect", "mynetwork", "test") 1216 mac2 := inspectField(c, "test", "NetworkSettings.Networks.mynetwork.MacAddress") 1217 c.Assert(strings.TrimSpace(mac2), checker.Not(checker.Equals), strings.TrimSpace(mac1)) 1218 } 1219 1220 func (s *DockerNetworkSuite) TestDockerNetworkInspectCreatedContainer(c *check.C) { 1221 dockerCmd(c, "create", "--name", "test", "busybox") 1222 networks := inspectField(c, "test", "NetworkSettings.Networks") 1223 c.Assert(networks, checker.Contains, "bridge", check.Commentf("Should return 'bridge' network")) 1224 } 1225 1226 func (s *DockerNetworkSuite) TestDockerNetworkRestartWithMultipleNetworks(c *check.C) { 1227 dockerCmd(c, "network", "create", "test") 1228 dockerCmd(c, "run", "--name=foo", "-d", "busybox", "top") 1229 c.Assert(waitRun("foo"), checker.IsNil) 1230 dockerCmd(c, "network", "connect", "test", "foo") 1231 dockerCmd(c, "restart", "foo") 1232 networks := inspectField(c, "foo", "NetworkSettings.Networks") 1233 c.Assert(networks, checker.Contains, "bridge", check.Commentf("Should contain 'bridge' network")) 1234 c.Assert(networks, checker.Contains, "test", check.Commentf("Should contain 'test' network")) 1235 } 1236 1237 func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnectToStoppedContainer(c *check.C) { 1238 dockerCmd(c, "network", "create", "test") 1239 dockerCmd(c, "create", "--name=foo", "busybox", "top") 1240 dockerCmd(c, "network", "connect", "test", "foo") 1241 networks := inspectField(c, "foo", "NetworkSettings.Networks") 1242 c.Assert(networks, checker.Contains, "test", check.Commentf("Should contain 'test' network")) 1243 1244 // Restart docker daemon to test the config has persisted to disk 1245 s.d.Restart() 1246 networks = inspectField(c, "foo", "NetworkSettings.Networks") 1247 c.Assert(networks, checker.Contains, "test", check.Commentf("Should contain 'test' network")) 1248 1249 // start the container and test if we can ping it from another container in the same network 1250 dockerCmd(c, "start", "foo") 1251 c.Assert(waitRun("foo"), checker.IsNil) 1252 ip := inspectField(c, "foo", "NetworkSettings.Networks.test.IPAddress") 1253 ip = strings.TrimSpace(ip) 1254 dockerCmd(c, "run", "--net=test", "busybox", "sh", "-c", fmt.Sprintf("ping -c 1 %s", ip)) 1255 1256 dockerCmd(c, "stop", "foo") 1257 1258 // Test disconnect 1259 dockerCmd(c, "network", "disconnect", "test", "foo") 1260 networks = inspectField(c, "foo", "NetworkSettings.Networks") 1261 c.Assert(networks, checker.Not(checker.Contains), "test", check.Commentf("Should not contain 'test' network")) 1262 1263 // Restart docker daemon to test the config has persisted to disk 1264 s.d.Restart() 1265 networks = inspectField(c, "foo", "NetworkSettings.Networks") 1266 c.Assert(networks, checker.Not(checker.Contains), "test", check.Commentf("Should not contain 'test' network")) 1267 1268 } 1269 1270 func (s *DockerNetworkSuite) TestDockerNetworkConnectPreferredIP(c *check.C) { 1271 // create two networks 1272 dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.28.0.0/16", "--subnet=2001:db8:1234::/64", "n0") 1273 assertNwIsAvailable(c, "n0") 1274 1275 dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.30.0.0/16", "--ip-range=172.30.5.0/24", "--subnet=2001:db8:abcd::/64", "--ip-range=2001:db8:abcd::/80", "n1") 1276 assertNwIsAvailable(c, "n1") 1277 1278 // run a container on first network specifying the ip addresses 1279 dockerCmd(c, "run", "-d", "--name", "c0", "--net=n0", "--ip", "172.28.99.88", "--ip6", "2001:db8:1234::9988", "busybox", "top") 1280 c.Assert(waitRun("c0"), check.IsNil) 1281 verifyIPAddressConfig(c, "c0", "n0", "172.28.99.88", "2001:db8:1234::9988") 1282 verifyIPAddresses(c, "c0", "n0", "172.28.99.88", "2001:db8:1234::9988") 1283 1284 // connect the container to the second network specifying an ip addresses 1285 dockerCmd(c, "network", "connect", "--ip", "172.30.55.44", "--ip6", "2001:db8:abcd::5544", "n1", "c0") 1286 verifyIPAddressConfig(c, "c0", "n1", "172.30.55.44", "2001:db8:abcd::5544") 1287 verifyIPAddresses(c, "c0", "n1", "172.30.55.44", "2001:db8:abcd::5544") 1288 1289 // Stop and restart the container 1290 dockerCmd(c, "stop", "c0") 1291 dockerCmd(c, "start", "c0") 1292 1293 // verify requested addresses are applied and configs are still there 1294 verifyIPAddressConfig(c, "c0", "n0", "172.28.99.88", "2001:db8:1234::9988") 1295 verifyIPAddresses(c, "c0", "n0", "172.28.99.88", "2001:db8:1234::9988") 1296 verifyIPAddressConfig(c, "c0", "n1", "172.30.55.44", "2001:db8:abcd::5544") 1297 verifyIPAddresses(c, "c0", "n1", "172.30.55.44", "2001:db8:abcd::5544") 1298 1299 // Still it should fail to connect to the default network with a specified IP (whatever ip) 1300 out, _, err := dockerCmdWithError("network", "connect", "--ip", "172.21.55.44", "bridge", "c0") 1301 c.Assert(err, checker.NotNil, check.Commentf("out: %s", out)) 1302 c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkAndIP.Error()) 1303 1304 } 1305 1306 func (s *DockerNetworkSuite) TestDockerNetworkConnectPreferredIPStoppedContainer(c *check.C) { 1307 // create a container 1308 dockerCmd(c, "create", "--name", "c0", "busybox", "top") 1309 1310 // create a network 1311 dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.30.0.0/16", "--subnet=2001:db8:abcd::/64", "n0") 1312 assertNwIsAvailable(c, "n0") 1313 1314 // connect the container to the network specifying an ip addresses 1315 dockerCmd(c, "network", "connect", "--ip", "172.30.55.44", "--ip6", "2001:db8:abcd::5544", "n0", "c0") 1316 verifyIPAddressConfig(c, "c0", "n0", "172.30.55.44", "2001:db8:abcd::5544") 1317 1318 // start the container, verify config has not changed and ip addresses are assigned 1319 dockerCmd(c, "start", "c0") 1320 c.Assert(waitRun("c0"), check.IsNil) 1321 verifyIPAddressConfig(c, "c0", "n0", "172.30.55.44", "2001:db8:abcd::5544") 1322 verifyIPAddresses(c, "c0", "n0", "172.30.55.44", "2001:db8:abcd::5544") 1323 1324 // stop the container and check ip config has not changed 1325 dockerCmd(c, "stop", "c0") 1326 verifyIPAddressConfig(c, "c0", "n0", "172.30.55.44", "2001:db8:abcd::5544") 1327 } 1328 1329 func (s *DockerNetworkSuite) TestDockerNetworkUnsupportedRequiredIP(c *check.C) { 1330 // requested IP is not supported on predefined networks 1331 for _, mode := range []string{"none", "host", "bridge", "default"} { 1332 checkUnsupportedNetworkAndIP(c, mode) 1333 } 1334 1335 // requested IP is not supported on networks with no user defined subnets 1336 dockerCmd(c, "network", "create", "n0") 1337 assertNwIsAvailable(c, "n0") 1338 1339 out, _, err := dockerCmdWithError("run", "-d", "--ip", "172.28.99.88", "--net", "n0", "busybox", "top") 1340 c.Assert(err, checker.NotNil, check.Commentf("out: %s", out)) 1341 c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkNoSubnetAndIP.Error()) 1342 1343 out, _, err = dockerCmdWithError("run", "-d", "--ip6", "2001:db8:1234::9988", "--net", "n0", "busybox", "top") 1344 c.Assert(err, checker.NotNil, check.Commentf("out: %s", out)) 1345 c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkNoSubnetAndIP.Error()) 1346 1347 dockerCmd(c, "network", "rm", "n0") 1348 assertNwNotAvailable(c, "n0") 1349 } 1350 1351 func checkUnsupportedNetworkAndIP(c *check.C, nwMode string) { 1352 out, _, err := dockerCmdWithError("run", "-d", "--net", nwMode, "--ip", "172.28.99.88", "--ip6", "2001:db8:1234::9988", "busybox", "top") 1353 c.Assert(err, checker.NotNil, check.Commentf("out: %s", out)) 1354 c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkAndIP.Error()) 1355 } 1356 1357 func verifyIPAddressConfig(c *check.C, cName, nwname, ipv4, ipv6 string) { 1358 if ipv4 != "" { 1359 out := inspectField(c, cName, fmt.Sprintf("NetworkSettings.Networks.%s.IPAMConfig.IPv4Address", nwname)) 1360 c.Assert(strings.TrimSpace(out), check.Equals, ipv4) 1361 } 1362 1363 if ipv6 != "" { 1364 out := inspectField(c, cName, fmt.Sprintf("NetworkSettings.Networks.%s.IPAMConfig.IPv6Address", nwname)) 1365 c.Assert(strings.TrimSpace(out), check.Equals, ipv6) 1366 } 1367 } 1368 1369 func verifyIPAddresses(c *check.C, cName, nwname, ipv4, ipv6 string) { 1370 out := inspectField(c, cName, fmt.Sprintf("NetworkSettings.Networks.%s.IPAddress", nwname)) 1371 c.Assert(strings.TrimSpace(out), check.Equals, ipv4) 1372 1373 out = inspectField(c, cName, fmt.Sprintf("NetworkSettings.Networks.%s.GlobalIPv6Address", nwname)) 1374 c.Assert(strings.TrimSpace(out), check.Equals, ipv6) 1375 } 1376 1377 func (s *DockerNetworkSuite) TestDockerNetworkConnectLinkLocalIP(c *check.C) { 1378 // create one test network 1379 dockerCmd(c, "network", "create", "n0") 1380 assertNwIsAvailable(c, "n0") 1381 1382 // run a container with incorrect link-local address 1383 _, _, err := dockerCmdWithError("run", "--link-local-ip", "169.253.5.5", "busybox", "top") 1384 c.Assert(err, check.NotNil) 1385 _, _, err = dockerCmdWithError("run", "--link-local-ip", "2001:db8::89", "busybox", "top") 1386 c.Assert(err, check.NotNil) 1387 1388 // run two containers with link-local ip on the test network 1389 dockerCmd(c, "run", "-d", "--name", "c0", "--net=n0", "--link-local-ip", "169.254.7.7", "--link-local-ip", "fe80::254:77", "busybox", "top") 1390 c.Assert(waitRun("c0"), check.IsNil) 1391 dockerCmd(c, "run", "-d", "--name", "c1", "--net=n0", "--link-local-ip", "169.254.8.8", "--link-local-ip", "fe80::254:88", "busybox", "top") 1392 c.Assert(waitRun("c1"), check.IsNil) 1393 1394 // run a container on the default network and connect it to the test network specifying a link-local address 1395 dockerCmd(c, "run", "-d", "--name", "c2", "busybox", "top") 1396 c.Assert(waitRun("c2"), check.IsNil) 1397 dockerCmd(c, "network", "connect", "--link-local-ip", "169.254.9.9", "n0", "c2") 1398 1399 // verify the three containers can ping each other via the link-local addresses 1400 _, _, err = dockerCmdWithError("exec", "c0", "ping", "-c", "1", "169.254.8.8") 1401 c.Assert(err, check.IsNil) 1402 _, _, err = dockerCmdWithError("exec", "c1", "ping", "-c", "1", "169.254.9.9") 1403 c.Assert(err, check.IsNil) 1404 _, _, err = dockerCmdWithError("exec", "c2", "ping", "-c", "1", "169.254.7.7") 1405 c.Assert(err, check.IsNil) 1406 1407 // Stop and restart the three containers 1408 dockerCmd(c, "stop", "c0") 1409 dockerCmd(c, "stop", "c1") 1410 dockerCmd(c, "stop", "c2") 1411 dockerCmd(c, "start", "c0") 1412 dockerCmd(c, "start", "c1") 1413 dockerCmd(c, "start", "c2") 1414 1415 // verify the ping again 1416 _, _, err = dockerCmdWithError("exec", "c0", "ping", "-c", "1", "169.254.8.8") 1417 c.Assert(err, check.IsNil) 1418 _, _, err = dockerCmdWithError("exec", "c1", "ping", "-c", "1", "169.254.9.9") 1419 c.Assert(err, check.IsNil) 1420 _, _, err = dockerCmdWithError("exec", "c2", "ping", "-c", "1", "169.254.7.7") 1421 c.Assert(err, check.IsNil) 1422 } 1423 1424 func (s *DockerSuite) TestUserDefinedNetworkConnectDisconnectLink(c *check.C) { 1425 testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm) 1426 dockerCmd(c, "network", "create", "-d", "bridge", "foo1") 1427 dockerCmd(c, "network", "create", "-d", "bridge", "foo2") 1428 1429 dockerCmd(c, "run", "-d", "--net=foo1", "--name=first", "busybox", "top") 1430 c.Assert(waitRun("first"), check.IsNil) 1431 1432 // run a container in a user-defined network with a link for an existing container 1433 // and a link for a container that doesn't exist 1434 dockerCmd(c, "run", "-d", "--net=foo1", "--name=second", "--link=first:FirstInFoo1", 1435 "--link=third:bar", "busybox", "top") 1436 c.Assert(waitRun("second"), check.IsNil) 1437 1438 // ping to first and its alias FirstInFoo1 must succeed 1439 _, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first") 1440 c.Assert(err, check.IsNil) 1441 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo1") 1442 c.Assert(err, check.IsNil) 1443 1444 // connect first container to foo2 network 1445 dockerCmd(c, "network", "connect", "foo2", "first") 1446 // connect second container to foo2 network with a different alias for first container 1447 dockerCmd(c, "network", "connect", "--link=first:FirstInFoo2", "foo2", "second") 1448 1449 // ping the new alias in network foo2 1450 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo2") 1451 c.Assert(err, check.IsNil) 1452 1453 // disconnect first container from foo1 network 1454 dockerCmd(c, "network", "disconnect", "foo1", "first") 1455 1456 // link in foo1 network must fail 1457 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo1") 1458 c.Assert(err, check.NotNil) 1459 1460 // link in foo2 network must succeed 1461 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo2") 1462 c.Assert(err, check.IsNil) 1463 } 1464 1465 func (s *DockerNetworkSuite) TestDockerNetworkDisconnectDefault(c *check.C) { 1466 netWorkName1 := "test1" 1467 netWorkName2 := "test2" 1468 containerName := "foo" 1469 1470 dockerCmd(c, "network", "create", netWorkName1) 1471 dockerCmd(c, "network", "create", netWorkName2) 1472 dockerCmd(c, "create", "--name", containerName, "busybox", "top") 1473 dockerCmd(c, "network", "connect", netWorkName1, containerName) 1474 dockerCmd(c, "network", "connect", netWorkName2, containerName) 1475 dockerCmd(c, "network", "disconnect", "bridge", containerName) 1476 1477 dockerCmd(c, "start", containerName) 1478 c.Assert(waitRun(containerName), checker.IsNil) 1479 networks := inspectField(c, containerName, "NetworkSettings.Networks") 1480 c.Assert(networks, checker.Contains, netWorkName1, check.Commentf(fmt.Sprintf("Should contain '%s' network", netWorkName1))) 1481 c.Assert(networks, checker.Contains, netWorkName2, check.Commentf(fmt.Sprintf("Should contain '%s' network", netWorkName2))) 1482 c.Assert(networks, checker.Not(checker.Contains), "bridge", check.Commentf("Should not contain 'bridge' network")) 1483 } 1484 1485 func (s *DockerNetworkSuite) TestDockerNetworkConnectWithAliasOnDefaultNetworks(c *check.C) { 1486 testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm) 1487 1488 defaults := []string{"bridge", "host", "none"} 1489 out, _ := dockerCmd(c, "run", "-d", "--net=none", "busybox", "top") 1490 containerID := strings.TrimSpace(out) 1491 for _, net := range defaults { 1492 res, _, err := dockerCmdWithError("network", "connect", "--alias", "alias"+net, net, containerID) 1493 c.Assert(err, checker.NotNil) 1494 c.Assert(res, checker.Contains, runconfig.ErrUnsupportedNetworkAndAlias.Error()) 1495 } 1496 } 1497 1498 func (s *DockerSuite) TestUserDefinedNetworkConnectDisconnectAlias(c *check.C) { 1499 testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm) 1500 dockerCmd(c, "network", "create", "-d", "bridge", "net1") 1501 dockerCmd(c, "network", "create", "-d", "bridge", "net2") 1502 1503 cid, _ := dockerCmd(c, "run", "-d", "--net=net1", "--name=first", "--net-alias=foo", "busybox", "top") 1504 c.Assert(waitRun("first"), check.IsNil) 1505 1506 dockerCmd(c, "run", "-d", "--net=net1", "--name=second", "busybox", "top") 1507 c.Assert(waitRun("second"), check.IsNil) 1508 1509 // ping first container and its alias 1510 _, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first") 1511 c.Assert(err, check.IsNil) 1512 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo") 1513 c.Assert(err, check.IsNil) 1514 1515 // ping first container's short-id alias 1516 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", stringid.TruncateID(cid)) 1517 c.Assert(err, check.IsNil) 1518 1519 // connect first container to net2 network 1520 dockerCmd(c, "network", "connect", "--alias=bar", "net2", "first") 1521 // connect second container to foo2 network with a different alias for first container 1522 dockerCmd(c, "network", "connect", "net2", "second") 1523 1524 // ping the new alias in network foo2 1525 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar") 1526 c.Assert(err, check.IsNil) 1527 1528 // disconnect first container from net1 network 1529 dockerCmd(c, "network", "disconnect", "net1", "first") 1530 1531 // ping to net1 scoped alias "foo" must fail 1532 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo") 1533 c.Assert(err, check.NotNil) 1534 1535 // ping to net2 scoped alias "bar" must still succeed 1536 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar") 1537 c.Assert(err, check.IsNil) 1538 // ping to net2 scoped alias short-id must still succeed 1539 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", stringid.TruncateID(cid)) 1540 c.Assert(err, check.IsNil) 1541 1542 // verify the alias option is rejected when running on predefined network 1543 out, _, err := dockerCmdWithError("run", "--rm", "--name=any", "--net-alias=any", "busybox", "top") 1544 c.Assert(err, checker.NotNil, check.Commentf("out: %s", out)) 1545 c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkAndAlias.Error()) 1546 1547 // verify the alias option is rejected when connecting to predefined network 1548 out, _, err = dockerCmdWithError("network", "connect", "--alias=any", "bridge", "first") 1549 c.Assert(err, checker.NotNil, check.Commentf("out: %s", out)) 1550 c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkAndAlias.Error()) 1551 } 1552 1553 func (s *DockerSuite) TestUserDefinedNetworkConnectivity(c *check.C) { 1554 testRequires(c, DaemonIsLinux, NotUserNamespace) 1555 dockerCmd(c, "network", "create", "-d", "bridge", "br.net1") 1556 1557 dockerCmd(c, "run", "-d", "--net=br.net1", "--name=c1.net1", "busybox", "top") 1558 c.Assert(waitRun("c1.net1"), check.IsNil) 1559 1560 dockerCmd(c, "run", "-d", "--net=br.net1", "--name=c2.net1", "busybox", "top") 1561 c.Assert(waitRun("c2.net1"), check.IsNil) 1562 1563 // ping first container by its unqualified name 1564 _, _, err := dockerCmdWithError("exec", "c2.net1", "ping", "-c", "1", "c1.net1") 1565 c.Assert(err, check.IsNil) 1566 1567 // ping first container by its qualified name 1568 _, _, err = dockerCmdWithError("exec", "c2.net1", "ping", "-c", "1", "c1.net1.br.net1") 1569 c.Assert(err, check.IsNil) 1570 1571 // ping with first qualified name masked by an additional domain. should fail 1572 _, _, err = dockerCmdWithError("exec", "c2.net1", "ping", "-c", "1", "c1.net1.br.net1.google.com") 1573 c.Assert(err, check.NotNil) 1574 } 1575 1576 func (s *DockerSuite) TestEmbeddedDNSInvalidInput(c *check.C) { 1577 testRequires(c, DaemonIsLinux, NotUserNamespace) 1578 dockerCmd(c, "network", "create", "-d", "bridge", "nw1") 1579 1580 // Sending garbage to embedded DNS shouldn't crash the daemon 1581 dockerCmd(c, "run", "-i", "--net=nw1", "--name=c1", "debian:jessie", "bash", "-c", "echo InvalidQuery > /dev/udp/127.0.0.11/53") 1582 } 1583 1584 func (s *DockerSuite) TestDockerNetworkConnectFailsNoInspectChange(c *check.C) { 1585 dockerCmd(c, "run", "-d", "--name=bb", "busybox", "top") 1586 c.Assert(waitRun("bb"), check.IsNil) 1587 1588 ns0 := inspectField(c, "bb", "NetworkSettings.Networks.bridge") 1589 1590 // A failing redundant network connect should not alter current container's endpoint settings 1591 _, _, err := dockerCmdWithError("network", "connect", "bridge", "bb") 1592 c.Assert(err, check.NotNil) 1593 1594 ns1 := inspectField(c, "bb", "NetworkSettings.Networks.bridge") 1595 c.Assert(ns1, check.Equals, ns0) 1596 } 1597 1598 func (s *DockerSuite) TestDockerNetworkInternalMode(c *check.C) { 1599 dockerCmd(c, "network", "create", "--driver=bridge", "--internal", "internal") 1600 assertNwIsAvailable(c, "internal") 1601 nr := getNetworkResource(c, "internal") 1602 c.Assert(nr.Internal, checker.True) 1603 1604 dockerCmd(c, "run", "-d", "--net=internal", "--name=first", "busybox", "top") 1605 c.Assert(waitRun("first"), check.IsNil) 1606 dockerCmd(c, "run", "-d", "--net=internal", "--name=second", "busybox", "top") 1607 c.Assert(waitRun("second"), check.IsNil) 1608 out, _, err := dockerCmdWithError("exec", "first", "ping", "-W", "4", "-c", "1", "www.google.com") 1609 c.Assert(err, check.NotNil) 1610 c.Assert(out, checker.Contains, "ping: bad address") 1611 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "first") 1612 c.Assert(err, check.IsNil) 1613 } 1614 1615 // Test for #21401 1616 func (s *DockerNetworkSuite) TestDockerNetworkCreateDeleteSpecialCharacters(c *check.C) { 1617 dockerCmd(c, "network", "create", "test@#$") 1618 assertNwIsAvailable(c, "test@#$") 1619 dockerCmd(c, "network", "rm", "test@#$") 1620 assertNwNotAvailable(c, "test@#$") 1621 1622 dockerCmd(c, "network", "create", "kiwl$%^") 1623 assertNwIsAvailable(c, "kiwl$%^") 1624 dockerCmd(c, "network", "rm", "kiwl$%^") 1625 assertNwNotAvailable(c, "kiwl$%^") 1626 } 1627 1628 func (s *DockerDaemonSuite) TestDaemonRestartRestoreBridgeNetwork(t *check.C) { 1629 testRequires(t, DaemonIsLinux) 1630 if err := s.d.StartWithBusybox("--live-restore"); err != nil { 1631 t.Fatal(err) 1632 } 1633 defer s.d.Stop() 1634 oldCon := "old" 1635 1636 _, err := s.d.Cmd("run", "-d", "--name", oldCon, "-p", "80:80", "busybox", "top") 1637 if err != nil { 1638 t.Fatal(err) 1639 } 1640 oldContainerIP, err := s.d.Cmd("inspect", "-f", "{{ .NetworkSettings.Networks.bridge.IPAddress }}", oldCon) 1641 if err != nil { 1642 t.Fatal(err) 1643 } 1644 // Kill the daemon 1645 if err := s.d.Kill(); err != nil { 1646 t.Fatal(err) 1647 } 1648 1649 // restart the daemon 1650 if err := s.d.Start("--live-restore"); err != nil { 1651 t.Fatal(err) 1652 } 1653 1654 // start a new container, the new container's ip should not be the same with 1655 // old running container. 1656 newCon := "new" 1657 _, err = s.d.Cmd("run", "-d", "--name", newCon, "busybox", "top") 1658 if err != nil { 1659 t.Fatal(err) 1660 } 1661 newContainerIP, err := s.d.Cmd("inspect", "-f", "{{ .NetworkSettings.Networks.bridge.IPAddress }}", newCon) 1662 if err != nil { 1663 t.Fatal(err) 1664 } 1665 if strings.Compare(strings.TrimSpace(oldContainerIP), strings.TrimSpace(newContainerIP)) == 0 { 1666 t.Fatalf("new container ip should not equal to old running container ip") 1667 } 1668 1669 // start a new container, the new container should ping old running container 1670 _, err = s.d.Cmd("run", "-t", "busybox", "ping", "-c", "1", oldContainerIP) 1671 if err != nil { 1672 t.Fatal(err) 1673 } 1674 1675 // start a new container, trying to publish port 80:80 should fail 1676 out, err := s.d.Cmd("run", "-p", "80:80", "-d", "busybox", "top") 1677 if err == nil || !strings.Contains(out, "Bind for 0.0.0.0:80 failed: port is already allocated") { 1678 t.Fatalf("80 port is allocated to old running container, it should failed on allocating to new container") 1679 } 1680 1681 // kill old running container and try to allocate again 1682 _, err = s.d.Cmd("kill", oldCon) 1683 if err != nil { 1684 t.Fatal(err) 1685 } 1686 id, err := s.d.Cmd("run", "-p", "80:80", "-d", "busybox", "top") 1687 if err != nil { 1688 t.Fatal(err) 1689 } 1690 1691 // Cleanup because these containers will not be shut down by daemon 1692 out, err = s.d.Cmd("stop", newCon) 1693 if err != nil { 1694 t.Fatalf("err: %v %v", err, string(out)) 1695 } 1696 _, err = s.d.Cmd("stop", strings.TrimSpace(id)) 1697 if err != nil { 1698 t.Fatal(err) 1699 } 1700 } 1701 1702 func (s *DockerNetworkSuite) TestDockerNetworkFlagAlias(c *check.C) { 1703 dockerCmd(c, "network", "create", "user") 1704 output, status := dockerCmd(c, "run", "--rm", "--network=user", "--network-alias=foo", "busybox", "true") 1705 c.Assert(status, checker.Equals, 0, check.Commentf("unexpected status code %d (%s)", status, output)) 1706 1707 output, status, _ = dockerCmdWithError("run", "--rm", "--net=user", "--network=user", "busybox", "true") 1708 c.Assert(status, checker.Equals, 0, check.Commentf("unexpected status code %d (%s)", status, output)) 1709 1710 output, status, _ = dockerCmdWithError("run", "--rm", "--network=user", "--net-alias=foo", "--network-alias=bar", "busybox", "true") 1711 c.Assert(status, checker.Equals, 0, check.Commentf("unexpected status code %d (%s)", status, output)) 1712 }