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