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