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