github.com/jwhonce/docker@v0.6.7-0.20190327063223-da823cf3a5a3/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/vishvananda/netlink"
    31  	"golang.org/x/sys/unix"
    32  	"gotest.tools/icmd"
    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  	var 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  	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  	var 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  	var 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  	var 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  	var 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  	var 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, testEnv.IsLocalDaemon)
   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.170.0.0/16", "--subnet=192.171.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.172.0.0/16", "--subnet=192.173.0.0/16",
   620  		"--gateway=192.172.0.100", "--gateway=192.173.0.100",
   621  		"--ip-range=192.172.1.0/24",
   622  		"--aux-address", "a=192.172.1.5", "--aux-address", "b=192.172.1.6",
   623  		"--aux-address", "c=192.173.1.5", "--aux-address", "d=192.173.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, testEnv.IsLocalDaemon)
   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, testEnv.IsLocalDaemon)
   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, testEnv.IsLocalDaemon)
   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, testEnv.IsLocalDaemon)
   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("%s", 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("%s", 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  	// verify first container etc/hosts file has not changed
   884  	hosts1post := readContainerFileWithExec(c, cid1, hostsFile)
   885  	c.Assert(string(hosts1), checker.Equals, string(hosts1post),
   886  		check.Commentf("Unexpected %s change on anonymous container creation", hostsFile))
   887  
   888  	// Connect the 2nd container to a new network and verify the
   889  	// first container /etc/hosts file still hasn't changed.
   890  	dockerCmd(c, "network", "create", "-d", "bridge", cstmBridgeNw1)
   891  	assertNwIsAvailable(c, cstmBridgeNw1)
   892  
   893  	dockerCmd(c, "network", "connect", cstmBridgeNw1, cid2)
   894  
   895  	hosts2 := readContainerFileWithExec(c, cid2, hostsFile)
   896  	hosts1post = readContainerFileWithExec(c, cid1, hostsFile)
   897  	c.Assert(string(hosts1), checker.Equals, string(hosts1post),
   898  		check.Commentf("Unexpected %s change on container connect", hostsFile))
   899  
   900  	// start a named container
   901  	cName := "AnyName"
   902  	out, _ = dockerCmd(c, "run", "-d", "--net", cstmBridgeNw, "--name", cName, "busybox", "top")
   903  	cid3 := strings.TrimSpace(out)
   904  
   905  	// verify that container 1 and 2 can ping the named container
   906  	dockerCmd(c, "exec", cid1, "ping", "-c", "1", cName)
   907  	dockerCmd(c, "exec", cid2, "ping", "-c", "1", cName)
   908  
   909  	// Stop named container and verify first two containers' etc/hosts file hasn't changed
   910  	dockerCmd(c, "stop", cid3)
   911  	hosts1post = readContainerFileWithExec(c, cid1, hostsFile)
   912  	c.Assert(string(hosts1), checker.Equals, string(hosts1post),
   913  		check.Commentf("Unexpected %s change on name container creation", hostsFile))
   914  
   915  	hosts2post := readContainerFileWithExec(c, cid2, hostsFile)
   916  	c.Assert(string(hosts2), checker.Equals, string(hosts2post),
   917  		check.Commentf("Unexpected %s change on name container creation", hostsFile))
   918  
   919  	// verify that container 1 and 2 can't ping the named container now
   920  	_, _, err := dockerCmdWithError("exec", cid1, "ping", "-c", "1", cName)
   921  	c.Assert(err, check.NotNil)
   922  	_, _, err = dockerCmdWithError("exec", cid2, "ping", "-c", "1", cName)
   923  	c.Assert(err, check.NotNil)
   924  }
   925  
   926  func (s *DockerNetworkSuite) TestDockerNetworkLinkOnDefaultNetworkOnly(c *check.C) {
   927  	// Legacy Link feature must work only on default network, and not across networks
   928  	cnt1 := "container1"
   929  	cnt2 := "container2"
   930  	network := "anotherbridge"
   931  
   932  	// Run first container on default network
   933  	dockerCmd(c, "run", "-d", "--name", cnt1, "busybox", "top")
   934  
   935  	// Create another network and run the second container on it
   936  	dockerCmd(c, "network", "create", network)
   937  	assertNwIsAvailable(c, network)
   938  	dockerCmd(c, "run", "-d", "--net", network, "--name", cnt2, "busybox", "top")
   939  
   940  	// Try launching a container on default network, linking to the first container. Must succeed
   941  	dockerCmd(c, "run", "-d", "--link", fmt.Sprintf("%s:%s", cnt1, cnt1), "busybox", "top")
   942  
   943  	// Try launching a container on default network, linking to the second container. Must fail
   944  	_, _, err := dockerCmdWithError("run", "-d", "--link", fmt.Sprintf("%s:%s", cnt2, cnt2), "busybox", "top")
   945  	c.Assert(err, checker.NotNil)
   946  
   947  	// Connect second container to default network. Now a container on default network can link to it
   948  	dockerCmd(c, "network", "connect", "bridge", cnt2)
   949  	dockerCmd(c, "run", "-d", "--link", fmt.Sprintf("%s:%s", cnt2, cnt2), "busybox", "top")
   950  }
   951  
   952  func (s *DockerNetworkSuite) TestDockerNetworkOverlayPortMapping(c *check.C) {
   953  	testRequires(c, testEnv.IsLocalDaemon)
   954  	// Verify exposed ports are present in ps output when running a container on
   955  	// a network managed by a driver which does not provide the default gateway
   956  	// for the container
   957  	nwn := "ov"
   958  	ctn := "bb"
   959  	port1 := 80
   960  	port2 := 443
   961  	expose1 := fmt.Sprintf("--expose=%d", port1)
   962  	expose2 := fmt.Sprintf("--expose=%d", port2)
   963  
   964  	dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, nwn)
   965  	assertNwIsAvailable(c, nwn)
   966  
   967  	dockerCmd(c, "run", "-d", "--net", nwn, "--name", ctn, expose1, expose2, "busybox", "top")
   968  
   969  	// Check docker ps o/p for last created container reports the unpublished ports
   970  	unpPort1 := fmt.Sprintf("%d/tcp", port1)
   971  	unpPort2 := fmt.Sprintf("%d/tcp", port2)
   972  	out, _ := dockerCmd(c, "ps", "-n=1")
   973  	// Missing unpublished ports in docker ps output
   974  	c.Assert(out, checker.Contains, unpPort1)
   975  	// Missing unpublished ports in docker ps output
   976  	c.Assert(out, checker.Contains, unpPort2)
   977  }
   978  
   979  func (s *DockerNetworkSuite) TestDockerNetworkDriverUngracefulRestart(c *check.C) {
   980  	testRequires(c, DaemonIsLinux, NotUserNamespace, testEnv.IsLocalDaemon)
   981  	dnd := "dnd"
   982  	did := "did"
   983  
   984  	mux := http.NewServeMux()
   985  	server := httptest.NewServer(mux)
   986  	setupRemoteNetworkDrivers(c, mux, server.URL, dnd, did)
   987  
   988  	s.d.StartWithBusybox(c)
   989  	_, err := s.d.Cmd("network", "create", "-d", dnd, "--subnet", "1.1.1.0/24", "net1")
   990  	c.Assert(err, checker.IsNil)
   991  
   992  	_, err = s.d.Cmd("run", "-itd", "--net", "net1", "--name", "foo", "--ip", "1.1.1.10", "busybox", "sh")
   993  	c.Assert(err, checker.IsNil)
   994  
   995  	// Kill daemon and restart
   996  	c.Assert(s.d.Kill(), checker.IsNil)
   997  
   998  	server.Close()
   999  
  1000  	startTime := time.Now().Unix()
  1001  	s.d.Restart(c)
  1002  	lapse := time.Now().Unix() - startTime
  1003  	if lapse > 60 {
  1004  		// In normal scenarios, daemon restart takes ~1 second.
  1005  		// Plugin retry mechanism can delay the daemon start. systemd may not like it.
  1006  		// Avoid accessing plugins during daemon bootup
  1007  		c.Logf("daemon restart took too long : %d seconds", lapse)
  1008  	}
  1009  
  1010  	// Restart the custom dummy plugin
  1011  	mux = http.NewServeMux()
  1012  	server = httptest.NewServer(mux)
  1013  	setupRemoteNetworkDrivers(c, mux, server.URL, dnd, did)
  1014  
  1015  	// trying to reuse the same ip must succeed
  1016  	_, err = s.d.Cmd("run", "-itd", "--net", "net1", "--name", "bar", "--ip", "1.1.1.10", "busybox", "sh")
  1017  	c.Assert(err, checker.IsNil)
  1018  }
  1019  
  1020  func (s *DockerNetworkSuite) TestDockerNetworkMacInspect(c *check.C) {
  1021  	testRequires(c, testEnv.IsLocalDaemon)
  1022  	// Verify endpoint MAC address is correctly populated in container's network settings
  1023  	nwn := "ov"
  1024  	ctn := "bb"
  1025  
  1026  	dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, nwn)
  1027  	assertNwIsAvailable(c, nwn)
  1028  
  1029  	dockerCmd(c, "run", "-d", "--net", nwn, "--name", ctn, "busybox", "top")
  1030  
  1031  	mac := inspectField(c, ctn, "NetworkSettings.Networks."+nwn+".MacAddress")
  1032  	c.Assert(mac, checker.Equals, "a0:b1:c2:d3:e4:f5")
  1033  }
  1034  
  1035  func (s *DockerSuite) TestInspectAPIMultipleNetworks(c *check.C) {
  1036  	dockerCmd(c, "network", "create", "mybridge1")
  1037  	dockerCmd(c, "network", "create", "mybridge2")
  1038  	out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
  1039  	id := strings.TrimSpace(out)
  1040  	c.Assert(waitRun(id), check.IsNil)
  1041  
  1042  	dockerCmd(c, "network", "connect", "mybridge1", id)
  1043  	dockerCmd(c, "network", "connect", "mybridge2", id)
  1044  
  1045  	body := getInspectBody(c, "v1.20", id)
  1046  	var inspect120 v1p20.ContainerJSON
  1047  	err := json.Unmarshal(body, &inspect120)
  1048  	c.Assert(err, checker.IsNil)
  1049  
  1050  	versionedIP := inspect120.NetworkSettings.IPAddress
  1051  
  1052  	body = getInspectBody(c, "v1.21", id)
  1053  	var inspect121 types.ContainerJSON
  1054  	err = json.Unmarshal(body, &inspect121)
  1055  	c.Assert(err, checker.IsNil)
  1056  	c.Assert(inspect121.NetworkSettings.Networks, checker.HasLen, 3)
  1057  
  1058  	bridge := inspect121.NetworkSettings.Networks["bridge"]
  1059  	c.Assert(bridge.IPAddress, checker.Equals, versionedIP)
  1060  	c.Assert(bridge.IPAddress, checker.Equals, inspect121.NetworkSettings.IPAddress)
  1061  }
  1062  
  1063  func connectContainerToNetworks(c *check.C, d *daemon.Daemon, cName string, nws []string) {
  1064  	// Run a container on the default network
  1065  	out, err := d.Cmd("run", "-d", "--name", cName, "busybox", "top")
  1066  	c.Assert(err, checker.IsNil, check.Commentf("%s", out))
  1067  
  1068  	// Attach the container to other networks
  1069  	for _, nw := range nws {
  1070  		out, err = d.Cmd("network", "create", nw)
  1071  		c.Assert(err, checker.IsNil, check.Commentf("%s", out))
  1072  		out, err = d.Cmd("network", "connect", nw, cName)
  1073  		c.Assert(err, checker.IsNil, check.Commentf("%s", out))
  1074  	}
  1075  }
  1076  
  1077  func verifyContainerIsConnectedToNetworks(c *check.C, d *daemon.Daemon, cName string, nws []string) {
  1078  	// Verify container is connected to all the networks
  1079  	for _, nw := range nws {
  1080  		out, err := d.Cmd("inspect", "-f", fmt.Sprintf("{{.NetworkSettings.Networks.%s}}", nw), cName)
  1081  		c.Assert(err, checker.IsNil, check.Commentf("%s", out))
  1082  		c.Assert(out, checker.Not(checker.Equals), "<no value>\n")
  1083  	}
  1084  }
  1085  
  1086  func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksGracefulDaemonRestart(c *check.C) {
  1087  	testRequires(c, testEnv.IsLocalDaemon)
  1088  	cName := "bb"
  1089  	nwList := []string{"nw1", "nw2", "nw3"}
  1090  
  1091  	s.d.StartWithBusybox(c)
  1092  
  1093  	connectContainerToNetworks(c, s.d, cName, nwList)
  1094  	verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList)
  1095  
  1096  	// Reload daemon
  1097  	s.d.Restart(c)
  1098  
  1099  	_, err := s.d.Cmd("start", cName)
  1100  	c.Assert(err, checker.IsNil)
  1101  
  1102  	verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList)
  1103  }
  1104  
  1105  func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksUngracefulDaemonRestart(c *check.C) {
  1106  	testRequires(c, testEnv.IsLocalDaemon)
  1107  	cName := "cc"
  1108  	nwList := []string{"nw1", "nw2", "nw3"}
  1109  
  1110  	s.d.StartWithBusybox(c)
  1111  
  1112  	connectContainerToNetworks(c, s.d, cName, nwList)
  1113  	verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList)
  1114  
  1115  	// Kill daemon and restart
  1116  	c.Assert(s.d.Kill(), checker.IsNil)
  1117  	s.d.Restart(c)
  1118  
  1119  	// Restart container
  1120  	_, err := s.d.Cmd("start", cName)
  1121  	c.Assert(err, checker.IsNil)
  1122  
  1123  	verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList)
  1124  }
  1125  
  1126  func (s *DockerNetworkSuite) TestDockerNetworkRunNetByID(c *check.C) {
  1127  	out, _ := dockerCmd(c, "network", "create", "one")
  1128  	containerOut, _, err := dockerCmdWithError("run", "-d", "--net", strings.TrimSpace(out), "busybox", "top")
  1129  	c.Assert(err, checker.IsNil, check.Commentf(containerOut))
  1130  }
  1131  
  1132  func (s *DockerNetworkSuite) TestDockerNetworkHostModeUngracefulDaemonRestart(c *check.C) {
  1133  	testRequires(c, DaemonIsLinux, NotUserNamespace, testEnv.IsLocalDaemon)
  1134  	s.d.StartWithBusybox(c)
  1135  
  1136  	// Run a few containers on host network
  1137  	for i := 0; i < 10; i++ {
  1138  		cName := fmt.Sprintf("hostc-%d", i)
  1139  		out, err := s.d.Cmd("run", "-d", "--name", cName, "--net=host", "--restart=always", "busybox", "top")
  1140  		c.Assert(err, checker.IsNil, check.Commentf("%s", out))
  1141  
  1142  		// verify container has finished starting before killing daemon
  1143  		err = s.d.WaitRun(cName)
  1144  		c.Assert(err, checker.IsNil)
  1145  	}
  1146  
  1147  	// Kill daemon ungracefully and restart
  1148  	c.Assert(s.d.Kill(), checker.IsNil)
  1149  	s.d.Restart(c)
  1150  
  1151  	// make sure all the containers are up and running
  1152  	for i := 0; i < 10; i++ {
  1153  		err := s.d.WaitRun(fmt.Sprintf("hostc-%d", i))
  1154  		c.Assert(err, checker.IsNil)
  1155  	}
  1156  }
  1157  
  1158  func (s *DockerNetworkSuite) TestDockerNetworkConnectToHostFromOtherNetwork(c *check.C) {
  1159  	dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
  1160  	c.Assert(waitRun("container1"), check.IsNil)
  1161  	dockerCmd(c, "network", "disconnect", "bridge", "container1")
  1162  	out, _, err := dockerCmdWithError("network", "connect", "host", "container1")
  1163  	c.Assert(err, checker.NotNil, check.Commentf("%s", out))
  1164  	c.Assert(out, checker.Contains, runconfig.ErrConflictHostNetwork.Error())
  1165  }
  1166  
  1167  func (s *DockerNetworkSuite) TestDockerNetworkDisconnectFromHost(c *check.C) {
  1168  	dockerCmd(c, "run", "-d", "--name", "container1", "--net=host", "busybox", "top")
  1169  	c.Assert(waitRun("container1"), check.IsNil)
  1170  	out, _, err := dockerCmdWithError("network", "disconnect", "host", "container1")
  1171  	c.Assert(err, checker.NotNil, check.Commentf("Should err out disconnect from host"))
  1172  	c.Assert(out, checker.Contains, runconfig.ErrConflictHostNetwork.Error())
  1173  }
  1174  
  1175  func (s *DockerNetworkSuite) TestDockerNetworkConnectWithPortMapping(c *check.C) {
  1176  	testRequires(c, NotArm)
  1177  	dockerCmd(c, "network", "create", "test1")
  1178  	dockerCmd(c, "run", "-d", "--name", "c1", "-p", "5000:5000", "busybox", "top")
  1179  	c.Assert(waitRun("c1"), check.IsNil)
  1180  	dockerCmd(c, "network", "connect", "test1", "c1")
  1181  }
  1182  
  1183  func verifyPortMap(c *check.C, container, port, originalMapping string, mustBeEqual bool) {
  1184  	chk := checker.Equals
  1185  	if !mustBeEqual {
  1186  		chk = checker.Not(checker.Equals)
  1187  	}
  1188  	currentMapping, _ := dockerCmd(c, "port", container, port)
  1189  	c.Assert(currentMapping, chk, originalMapping)
  1190  }
  1191  
  1192  func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnectWithPortMapping(c *check.C) {
  1193  	// Connect and disconnect a container with explicit and non-explicit
  1194  	// host port mapping to/from networks which do cause and do not cause
  1195  	// the container default gateway to change, and verify docker port cmd
  1196  	// returns congruent information
  1197  	testRequires(c, NotArm)
  1198  	cnt := "c1"
  1199  	dockerCmd(c, "network", "create", "aaa")
  1200  	dockerCmd(c, "network", "create", "ccc")
  1201  
  1202  	dockerCmd(c, "run", "-d", "--name", cnt, "-p", "9000:90", "-p", "70", "busybox", "top")
  1203  	c.Assert(waitRun(cnt), check.IsNil)
  1204  	curPortMap, _ := dockerCmd(c, "port", cnt, "70")
  1205  	curExplPortMap, _ := dockerCmd(c, "port", cnt, "90")
  1206  
  1207  	// Connect to a network which causes the container's default gw switch
  1208  	dockerCmd(c, "network", "connect", "aaa", cnt)
  1209  	verifyPortMap(c, cnt, "70", curPortMap, false)
  1210  	verifyPortMap(c, cnt, "90", curExplPortMap, true)
  1211  
  1212  	// Read current mapping
  1213  	curPortMap, _ = dockerCmd(c, "port", cnt, "70")
  1214  
  1215  	// Disconnect from a network which causes the container's default gw switch
  1216  	dockerCmd(c, "network", "disconnect", "aaa", cnt)
  1217  	verifyPortMap(c, cnt, "70", curPortMap, false)
  1218  	verifyPortMap(c, cnt, "90", curExplPortMap, true)
  1219  
  1220  	// Read current mapping
  1221  	curPortMap, _ = dockerCmd(c, "port", cnt, "70")
  1222  
  1223  	// Connect to a network which does not cause the container's default gw switch
  1224  	dockerCmd(c, "network", "connect", "ccc", cnt)
  1225  	verifyPortMap(c, cnt, "70", curPortMap, true)
  1226  	verifyPortMap(c, cnt, "90", curExplPortMap, true)
  1227  }
  1228  
  1229  func (s *DockerNetworkSuite) TestDockerNetworkConnectWithMac(c *check.C) {
  1230  	macAddress := "02:42:ac:11:00:02"
  1231  	dockerCmd(c, "network", "create", "mynetwork")
  1232  	dockerCmd(c, "run", "--name=test", "-d", "--mac-address", macAddress, "busybox", "top")
  1233  	c.Assert(waitRun("test"), check.IsNil)
  1234  	mac1 := inspectField(c, "test", "NetworkSettings.Networks.bridge.MacAddress")
  1235  	c.Assert(strings.TrimSpace(mac1), checker.Equals, macAddress)
  1236  	dockerCmd(c, "network", "connect", "mynetwork", "test")
  1237  	mac2 := inspectField(c, "test", "NetworkSettings.Networks.mynetwork.MacAddress")
  1238  	c.Assert(strings.TrimSpace(mac2), checker.Not(checker.Equals), strings.TrimSpace(mac1))
  1239  }
  1240  
  1241  func (s *DockerNetworkSuite) TestDockerNetworkInspectCreatedContainer(c *check.C) {
  1242  	dockerCmd(c, "create", "--name", "test", "busybox")
  1243  	networks := inspectField(c, "test", "NetworkSettings.Networks")
  1244  	c.Assert(networks, checker.Contains, "bridge", check.Commentf("Should return 'bridge' network"))
  1245  }
  1246  
  1247  func (s *DockerNetworkSuite) TestDockerNetworkRestartWithMultipleNetworks(c *check.C) {
  1248  	dockerCmd(c, "network", "create", "test")
  1249  	dockerCmd(c, "run", "--name=foo", "-d", "busybox", "top")
  1250  	c.Assert(waitRun("foo"), checker.IsNil)
  1251  	dockerCmd(c, "network", "connect", "test", "foo")
  1252  	dockerCmd(c, "restart", "foo")
  1253  	networks := inspectField(c, "foo", "NetworkSettings.Networks")
  1254  	c.Assert(networks, checker.Contains, "bridge", check.Commentf("Should contain 'bridge' network"))
  1255  	c.Assert(networks, checker.Contains, "test", check.Commentf("Should contain 'test' network"))
  1256  }
  1257  
  1258  func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnectToStoppedContainer(c *check.C) {
  1259  	testRequires(c, testEnv.IsLocalDaemon)
  1260  	dockerCmd(c, "network", "create", "test")
  1261  	dockerCmd(c, "create", "--name=foo", "busybox", "top")
  1262  	dockerCmd(c, "network", "connect", "test", "foo")
  1263  	networks := inspectField(c, "foo", "NetworkSettings.Networks")
  1264  	c.Assert(networks, checker.Contains, "test", check.Commentf("Should contain 'test' network"))
  1265  
  1266  	// Restart docker daemon to test the config has persisted to disk
  1267  	s.d.Restart(c)
  1268  	networks = inspectField(c, "foo", "NetworkSettings.Networks")
  1269  	c.Assert(networks, checker.Contains, "test", check.Commentf("Should contain 'test' network"))
  1270  
  1271  	// start the container and test if we can ping it from another container in the same network
  1272  	dockerCmd(c, "start", "foo")
  1273  	c.Assert(waitRun("foo"), checker.IsNil)
  1274  	ip := inspectField(c, "foo", "NetworkSettings.Networks.test.IPAddress")
  1275  	ip = strings.TrimSpace(ip)
  1276  	dockerCmd(c, "run", "--net=test", "busybox", "sh", "-c", fmt.Sprintf("ping -c 1 %s", ip))
  1277  
  1278  	dockerCmd(c, "stop", "foo")
  1279  
  1280  	// Test disconnect
  1281  	dockerCmd(c, "network", "disconnect", "test", "foo")
  1282  	networks = inspectField(c, "foo", "NetworkSettings.Networks")
  1283  	c.Assert(networks, checker.Not(checker.Contains), "test", check.Commentf("Should not contain 'test' network"))
  1284  
  1285  	// Restart docker daemon to test the config has persisted to disk
  1286  	s.d.Restart(c)
  1287  	networks = inspectField(c, "foo", "NetworkSettings.Networks")
  1288  	c.Assert(networks, checker.Not(checker.Contains), "test", check.Commentf("Should not contain 'test' network"))
  1289  
  1290  }
  1291  
  1292  func (s *DockerNetworkSuite) TestDockerNetworkDisconnectContainerNonexistingNetwork(c *check.C) {
  1293  	dockerCmd(c, "network", "create", "test")
  1294  	dockerCmd(c, "run", "--net=test", "-d", "--name=foo", "busybox", "top")
  1295  	networks := inspectField(c, "foo", "NetworkSettings.Networks")
  1296  	c.Assert(networks, checker.Contains, "test", check.Commentf("Should contain 'test' network"))
  1297  
  1298  	// Stop container and remove network
  1299  	dockerCmd(c, "stop", "foo")
  1300  	dockerCmd(c, "network", "rm", "test")
  1301  
  1302  	// Test disconnecting stopped container from nonexisting network
  1303  	dockerCmd(c, "network", "disconnect", "-f", "test", "foo")
  1304  	networks = inspectField(c, "foo", "NetworkSettings.Networks")
  1305  	c.Assert(networks, checker.Not(checker.Contains), "test", check.Commentf("Should not contain 'test' network"))
  1306  }
  1307  
  1308  func (s *DockerNetworkSuite) TestDockerNetworkConnectPreferredIP(c *check.C) {
  1309  	// create two networks
  1310  	dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.28.0.0/16", "--subnet=2001:db8:1234::/64", "n0")
  1311  	assertNwIsAvailable(c, "n0")
  1312  
  1313  	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")
  1314  	assertNwIsAvailable(c, "n1")
  1315  
  1316  	// run a container on first network specifying the ip addresses
  1317  	dockerCmd(c, "run", "-d", "--name", "c0", "--net=n0", "--ip", "172.28.99.88", "--ip6", "2001:db8:1234::9988", "busybox", "top")
  1318  	c.Assert(waitRun("c0"), check.IsNil)
  1319  	verifyIPAddressConfig(c, "c0", "n0", "172.28.99.88", "2001:db8:1234::9988")
  1320  	verifyIPAddresses(c, "c0", "n0", "172.28.99.88", "2001:db8:1234::9988")
  1321  
  1322  	// connect the container to the second network specifying an ip addresses
  1323  	dockerCmd(c, "network", "connect", "--ip", "172.30.55.44", "--ip6", "2001:db8:abcd::5544", "n1", "c0")
  1324  	verifyIPAddressConfig(c, "c0", "n1", "172.30.55.44", "2001:db8:abcd::5544")
  1325  	verifyIPAddresses(c, "c0", "n1", "172.30.55.44", "2001:db8:abcd::5544")
  1326  
  1327  	// Stop and restart the container
  1328  	dockerCmd(c, "stop", "c0")
  1329  	dockerCmd(c, "start", "c0")
  1330  
  1331  	// verify requested addresses are applied and configs are still there
  1332  	verifyIPAddressConfig(c, "c0", "n0", "172.28.99.88", "2001:db8:1234::9988")
  1333  	verifyIPAddresses(c, "c0", "n0", "172.28.99.88", "2001:db8:1234::9988")
  1334  	verifyIPAddressConfig(c, "c0", "n1", "172.30.55.44", "2001:db8:abcd::5544")
  1335  	verifyIPAddresses(c, "c0", "n1", "172.30.55.44", "2001:db8:abcd::5544")
  1336  
  1337  	// Still it should fail to connect to the default network with a specified IP (whatever ip)
  1338  	out, _, err := dockerCmdWithError("network", "connect", "--ip", "172.21.55.44", "bridge", "c0")
  1339  	c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
  1340  	c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkAndIP.Error())
  1341  
  1342  }
  1343  
  1344  func (s *DockerNetworkSuite) TestDockerNetworkConnectPreferredIPStoppedContainer(c *check.C) {
  1345  	// create a container
  1346  	dockerCmd(c, "create", "--name", "c0", "busybox", "top")
  1347  
  1348  	// create a network
  1349  	dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.30.0.0/16", "--subnet=2001:db8:abcd::/64", "n0")
  1350  	assertNwIsAvailable(c, "n0")
  1351  
  1352  	// connect the container to the network specifying an ip addresses
  1353  	dockerCmd(c, "network", "connect", "--ip", "172.30.55.44", "--ip6", "2001:db8:abcd::5544", "n0", "c0")
  1354  	verifyIPAddressConfig(c, "c0", "n0", "172.30.55.44", "2001:db8:abcd::5544")
  1355  
  1356  	// start the container, verify config has not changed and ip addresses are assigned
  1357  	dockerCmd(c, "start", "c0")
  1358  	c.Assert(waitRun("c0"), check.IsNil)
  1359  	verifyIPAddressConfig(c, "c0", "n0", "172.30.55.44", "2001:db8:abcd::5544")
  1360  	verifyIPAddresses(c, "c0", "n0", "172.30.55.44", "2001:db8:abcd::5544")
  1361  
  1362  	// stop the container and check ip config has not changed
  1363  	dockerCmd(c, "stop", "c0")
  1364  	verifyIPAddressConfig(c, "c0", "n0", "172.30.55.44", "2001:db8:abcd::5544")
  1365  }
  1366  
  1367  func (s *DockerNetworkSuite) TestDockerNetworkUnsupportedRequiredIP(c *check.C) {
  1368  	// requested IP is not supported on predefined networks
  1369  	for _, mode := range []string{"none", "host", "bridge", "default"} {
  1370  		checkUnsupportedNetworkAndIP(c, mode)
  1371  	}
  1372  
  1373  	// requested IP is not supported on networks with no user defined subnets
  1374  	dockerCmd(c, "network", "create", "n0")
  1375  	assertNwIsAvailable(c, "n0")
  1376  
  1377  	out, _, err := dockerCmdWithError("run", "-d", "--ip", "172.28.99.88", "--net", "n0", "busybox", "top")
  1378  	c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
  1379  	c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkNoSubnetAndIP.Error())
  1380  
  1381  	out, _, err = dockerCmdWithError("run", "-d", "--ip6", "2001:db8:1234::9988", "--net", "n0", "busybox", "top")
  1382  	c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
  1383  	c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkNoSubnetAndIP.Error())
  1384  
  1385  	dockerCmd(c, "network", "rm", "n0")
  1386  	assertNwNotAvailable(c, "n0")
  1387  }
  1388  
  1389  func checkUnsupportedNetworkAndIP(c *check.C, nwMode string) {
  1390  	out, _, err := dockerCmdWithError("run", "-d", "--net", nwMode, "--ip", "172.28.99.88", "--ip6", "2001:db8:1234::9988", "busybox", "top")
  1391  	c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
  1392  	c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkAndIP.Error())
  1393  }
  1394  
  1395  func verifyIPAddressConfig(c *check.C, cName, nwname, ipv4, ipv6 string) {
  1396  	if ipv4 != "" {
  1397  		out := inspectField(c, cName, fmt.Sprintf("NetworkSettings.Networks.%s.IPAMConfig.IPv4Address", nwname))
  1398  		c.Assert(strings.TrimSpace(out), check.Equals, ipv4)
  1399  	}
  1400  
  1401  	if ipv6 != "" {
  1402  		out := inspectField(c, cName, fmt.Sprintf("NetworkSettings.Networks.%s.IPAMConfig.IPv6Address", nwname))
  1403  		c.Assert(strings.TrimSpace(out), check.Equals, ipv6)
  1404  	}
  1405  }
  1406  
  1407  func verifyIPAddresses(c *check.C, cName, nwname, ipv4, ipv6 string) {
  1408  	out := inspectField(c, cName, fmt.Sprintf("NetworkSettings.Networks.%s.IPAddress", nwname))
  1409  	c.Assert(strings.TrimSpace(out), check.Equals, ipv4)
  1410  
  1411  	out = inspectField(c, cName, fmt.Sprintf("NetworkSettings.Networks.%s.GlobalIPv6Address", nwname))
  1412  	c.Assert(strings.TrimSpace(out), check.Equals, ipv6)
  1413  }
  1414  
  1415  func (s *DockerNetworkSuite) TestDockerNetworkConnectLinkLocalIP(c *check.C) {
  1416  	// create one test network
  1417  	dockerCmd(c, "network", "create", "--ipv6", "--subnet=2001:db8:1234::/64", "n0")
  1418  	assertNwIsAvailable(c, "n0")
  1419  
  1420  	// run a container with incorrect link-local address
  1421  	_, _, err := dockerCmdWithError("run", "--link-local-ip", "169.253.5.5", "busybox", "top")
  1422  	c.Assert(err, check.NotNil)
  1423  	_, _, err = dockerCmdWithError("run", "--link-local-ip", "2001:db8::89", "busybox", "top")
  1424  	c.Assert(err, check.NotNil)
  1425  
  1426  	// run two containers with link-local ip on the test network
  1427  	dockerCmd(c, "run", "-d", "--name", "c0", "--net=n0", "--link-local-ip", "169.254.7.7", "--link-local-ip", "fe80::254:77", "busybox", "top")
  1428  	c.Assert(waitRun("c0"), check.IsNil)
  1429  	dockerCmd(c, "run", "-d", "--name", "c1", "--net=n0", "--link-local-ip", "169.254.8.8", "--link-local-ip", "fe80::254:88", "busybox", "top")
  1430  	c.Assert(waitRun("c1"), check.IsNil)
  1431  
  1432  	// run a container on the default network and connect it to the test network specifying a link-local address
  1433  	dockerCmd(c, "run", "-d", "--name", "c2", "busybox", "top")
  1434  	c.Assert(waitRun("c2"), check.IsNil)
  1435  	dockerCmd(c, "network", "connect", "--link-local-ip", "169.254.9.9", "n0", "c2")
  1436  
  1437  	// verify the three containers can ping each other via the link-local addresses
  1438  	_, _, err = dockerCmdWithError("exec", "c0", "ping", "-c", "1", "169.254.8.8")
  1439  	c.Assert(err, check.IsNil)
  1440  	_, _, err = dockerCmdWithError("exec", "c1", "ping", "-c", "1", "169.254.9.9")
  1441  	c.Assert(err, check.IsNil)
  1442  	_, _, err = dockerCmdWithError("exec", "c2", "ping", "-c", "1", "169.254.7.7")
  1443  	c.Assert(err, check.IsNil)
  1444  
  1445  	// Stop and restart the three containers
  1446  	dockerCmd(c, "stop", "c0")
  1447  	dockerCmd(c, "stop", "c1")
  1448  	dockerCmd(c, "stop", "c2")
  1449  	dockerCmd(c, "start", "c0")
  1450  	dockerCmd(c, "start", "c1")
  1451  	dockerCmd(c, "start", "c2")
  1452  
  1453  	// verify the ping again
  1454  	_, _, err = dockerCmdWithError("exec", "c0", "ping", "-c", "1", "169.254.8.8")
  1455  	c.Assert(err, check.IsNil)
  1456  	_, _, err = dockerCmdWithError("exec", "c1", "ping", "-c", "1", "169.254.9.9")
  1457  	c.Assert(err, check.IsNil)
  1458  	_, _, err = dockerCmdWithError("exec", "c2", "ping", "-c", "1", "169.254.7.7")
  1459  	c.Assert(err, check.IsNil)
  1460  }
  1461  
  1462  func (s *DockerSuite) TestUserDefinedNetworkConnectDisconnectLink(c *check.C) {
  1463  	testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
  1464  	dockerCmd(c, "network", "create", "-d", "bridge", "foo1")
  1465  	dockerCmd(c, "network", "create", "-d", "bridge", "foo2")
  1466  
  1467  	dockerCmd(c, "run", "-d", "--net=foo1", "--name=first", "busybox", "top")
  1468  	c.Assert(waitRun("first"), check.IsNil)
  1469  
  1470  	// run a container in a user-defined network with a link for an existing container
  1471  	// and a link for a container that doesn't exist
  1472  	dockerCmd(c, "run", "-d", "--net=foo1", "--name=second", "--link=first:FirstInFoo1",
  1473  		"--link=third:bar", "busybox", "top")
  1474  	c.Assert(waitRun("second"), check.IsNil)
  1475  
  1476  	// ping to first and its alias FirstInFoo1 must succeed
  1477  	_, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
  1478  	c.Assert(err, check.IsNil)
  1479  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo1")
  1480  	c.Assert(err, check.IsNil)
  1481  
  1482  	// connect first container to foo2 network
  1483  	dockerCmd(c, "network", "connect", "foo2", "first")
  1484  	// connect second container to foo2 network with a different alias for first container
  1485  	dockerCmd(c, "network", "connect", "--link=first:FirstInFoo2", "foo2", "second")
  1486  
  1487  	// ping the new alias in network foo2
  1488  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo2")
  1489  	c.Assert(err, check.IsNil)
  1490  
  1491  	// disconnect first container from foo1 network
  1492  	dockerCmd(c, "network", "disconnect", "foo1", "first")
  1493  
  1494  	// link in foo1 network must fail
  1495  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo1")
  1496  	c.Assert(err, check.NotNil)
  1497  
  1498  	// link in foo2 network must succeed
  1499  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo2")
  1500  	c.Assert(err, check.IsNil)
  1501  }
  1502  
  1503  func (s *DockerNetworkSuite) TestDockerNetworkDisconnectDefault(c *check.C) {
  1504  	netWorkName1 := "test1"
  1505  	netWorkName2 := "test2"
  1506  	containerName := "foo"
  1507  
  1508  	dockerCmd(c, "network", "create", netWorkName1)
  1509  	dockerCmd(c, "network", "create", netWorkName2)
  1510  	dockerCmd(c, "create", "--name", containerName, "busybox", "top")
  1511  	dockerCmd(c, "network", "connect", netWorkName1, containerName)
  1512  	dockerCmd(c, "network", "connect", netWorkName2, containerName)
  1513  	dockerCmd(c, "network", "disconnect", "bridge", containerName)
  1514  
  1515  	dockerCmd(c, "start", containerName)
  1516  	c.Assert(waitRun(containerName), checker.IsNil)
  1517  	networks := inspectField(c, containerName, "NetworkSettings.Networks")
  1518  	c.Assert(networks, checker.Contains, netWorkName1, check.Commentf(fmt.Sprintf("Should contain '%s' network", netWorkName1)))
  1519  	c.Assert(networks, checker.Contains, netWorkName2, check.Commentf(fmt.Sprintf("Should contain '%s' network", netWorkName2)))
  1520  	c.Assert(networks, checker.Not(checker.Contains), "bridge", check.Commentf("Should not contain 'bridge' network"))
  1521  }
  1522  
  1523  func (s *DockerNetworkSuite) TestDockerNetworkConnectWithAliasOnDefaultNetworks(c *check.C) {
  1524  	testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
  1525  
  1526  	defaults := []string{"bridge", "host", "none"}
  1527  	out, _ := dockerCmd(c, "run", "-d", "--net=none", "busybox", "top")
  1528  	containerID := strings.TrimSpace(out)
  1529  	for _, net := range defaults {
  1530  		res, _, err := dockerCmdWithError("network", "connect", "--alias", "alias"+net, net, containerID)
  1531  		c.Assert(err, checker.NotNil)
  1532  		c.Assert(res, checker.Contains, runconfig.ErrUnsupportedNetworkAndAlias.Error())
  1533  	}
  1534  }
  1535  
  1536  func (s *DockerSuite) TestUserDefinedNetworkConnectDisconnectAlias(c *check.C) {
  1537  	testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
  1538  	dockerCmd(c, "network", "create", "-d", "bridge", "net1")
  1539  	dockerCmd(c, "network", "create", "-d", "bridge", "net2")
  1540  
  1541  	cid, _ := dockerCmd(c, "run", "-d", "--net=net1", "--name=first", "--net-alias=foo", "busybox:glibc", "top")
  1542  	c.Assert(waitRun("first"), check.IsNil)
  1543  
  1544  	dockerCmd(c, "run", "-d", "--net=net1", "--name=second", "busybox:glibc", "top")
  1545  	c.Assert(waitRun("second"), check.IsNil)
  1546  
  1547  	// ping first container and its alias
  1548  	_, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
  1549  	c.Assert(err, check.IsNil)
  1550  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
  1551  	c.Assert(err, check.IsNil)
  1552  
  1553  	// ping first container's short-id alias
  1554  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", stringid.TruncateID(cid))
  1555  	c.Assert(err, check.IsNil)
  1556  
  1557  	// connect first container to net2 network
  1558  	dockerCmd(c, "network", "connect", "--alias=bar", "net2", "first")
  1559  	// connect second container to foo2 network with a different alias for first container
  1560  	dockerCmd(c, "network", "connect", "net2", "second")
  1561  
  1562  	// ping the new alias in network foo2
  1563  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar")
  1564  	c.Assert(err, check.IsNil)
  1565  
  1566  	// disconnect first container from net1 network
  1567  	dockerCmd(c, "network", "disconnect", "net1", "first")
  1568  
  1569  	// ping to net1 scoped alias "foo" must fail
  1570  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
  1571  	c.Assert(err, check.NotNil)
  1572  
  1573  	// ping to net2 scoped alias "bar" must still succeed
  1574  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar")
  1575  	c.Assert(err, check.IsNil)
  1576  	// ping to net2 scoped alias short-id must still succeed
  1577  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", stringid.TruncateID(cid))
  1578  	c.Assert(err, check.IsNil)
  1579  
  1580  	// verify the alias option is rejected when running on predefined network
  1581  	out, _, err := dockerCmdWithError("run", "--rm", "--name=any", "--net-alias=any", "busybox:glibc", "top")
  1582  	c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
  1583  	c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkAndAlias.Error())
  1584  
  1585  	// verify the alias option is rejected when connecting to predefined network
  1586  	out, _, err = dockerCmdWithError("network", "connect", "--alias=any", "bridge", "first")
  1587  	c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
  1588  	c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkAndAlias.Error())
  1589  }
  1590  
  1591  func (s *DockerSuite) TestUserDefinedNetworkConnectivity(c *check.C) {
  1592  	testRequires(c, DaemonIsLinux, NotUserNamespace)
  1593  	dockerCmd(c, "network", "create", "-d", "bridge", "br.net1")
  1594  
  1595  	dockerCmd(c, "run", "-d", "--net=br.net1", "--name=c1.net1", "busybox:glibc", "top")
  1596  	c.Assert(waitRun("c1.net1"), check.IsNil)
  1597  
  1598  	dockerCmd(c, "run", "-d", "--net=br.net1", "--name=c2.net1", "busybox:glibc", "top")
  1599  	c.Assert(waitRun("c2.net1"), check.IsNil)
  1600  
  1601  	// ping first container by its unqualified name
  1602  	_, _, err := dockerCmdWithError("exec", "c2.net1", "ping", "-c", "1", "c1.net1")
  1603  	c.Assert(err, check.IsNil)
  1604  
  1605  	// ping first container by its qualified name
  1606  	_, _, err = dockerCmdWithError("exec", "c2.net1", "ping", "-c", "1", "c1.net1.br.net1")
  1607  	c.Assert(err, check.IsNil)
  1608  
  1609  	// ping with first qualified name masked by an additional domain. should fail
  1610  	_, _, err = dockerCmdWithError("exec", "c2.net1", "ping", "-c", "1", "c1.net1.br.net1.google.com")
  1611  	c.Assert(err, check.NotNil)
  1612  }
  1613  
  1614  func (s *DockerSuite) TestEmbeddedDNSInvalidInput(c *check.C) {
  1615  	testRequires(c, DaemonIsLinux, NotUserNamespace)
  1616  	dockerCmd(c, "network", "create", "-d", "bridge", "nw1")
  1617  
  1618  	// Sending garbage to embedded DNS shouldn't crash the daemon
  1619  	dockerCmd(c, "run", "-i", "--net=nw1", "--name=c1", "debian:jessie", "bash", "-c", "echo InvalidQuery > /dev/udp/127.0.0.11/53")
  1620  }
  1621  
  1622  func (s *DockerSuite) TestDockerNetworkConnectFailsNoInspectChange(c *check.C) {
  1623  	dockerCmd(c, "run", "-d", "--name=bb", "busybox", "top")
  1624  	c.Assert(waitRun("bb"), check.IsNil)
  1625  	defer dockerCmd(c, "stop", "bb")
  1626  
  1627  	ns0 := inspectField(c, "bb", "NetworkSettings.Networks.bridge")
  1628  
  1629  	// A failing redundant network connect should not alter current container's endpoint settings
  1630  	_, _, err := dockerCmdWithError("network", "connect", "bridge", "bb")
  1631  	c.Assert(err, check.NotNil)
  1632  
  1633  	ns1 := inspectField(c, "bb", "NetworkSettings.Networks.bridge")
  1634  	c.Assert(ns1, check.Equals, ns0)
  1635  }
  1636  
  1637  func (s *DockerSuite) TestDockerNetworkInternalMode(c *check.C) {
  1638  	dockerCmd(c, "network", "create", "--driver=bridge", "--internal", "internal")
  1639  	assertNwIsAvailable(c, "internal")
  1640  	nr := getNetworkResource(c, "internal")
  1641  	c.Assert(nr.Internal, checker.True)
  1642  
  1643  	dockerCmd(c, "run", "-d", "--net=internal", "--name=first", "busybox:glibc", "top")
  1644  	c.Assert(waitRun("first"), check.IsNil)
  1645  	dockerCmd(c, "run", "-d", "--net=internal", "--name=second", "busybox:glibc", "top")
  1646  	c.Assert(waitRun("second"), check.IsNil)
  1647  	out, _, err := dockerCmdWithError("exec", "first", "ping", "-W", "4", "-c", "1", "8.8.8.8")
  1648  	c.Assert(err, check.NotNil)
  1649  	c.Assert(out, checker.Contains, "100% packet loss")
  1650  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
  1651  	c.Assert(err, check.IsNil)
  1652  }
  1653  
  1654  // Test for #21401
  1655  func (s *DockerNetworkSuite) TestDockerNetworkCreateDeleteSpecialCharacters(c *check.C) {
  1656  	dockerCmd(c, "network", "create", "test@#$")
  1657  	assertNwIsAvailable(c, "test@#$")
  1658  	dockerCmd(c, "network", "rm", "test@#$")
  1659  	assertNwNotAvailable(c, "test@#$")
  1660  
  1661  	dockerCmd(c, "network", "create", "kiwl$%^")
  1662  	assertNwIsAvailable(c, "kiwl$%^")
  1663  	dockerCmd(c, "network", "rm", "kiwl$%^")
  1664  	assertNwNotAvailable(c, "kiwl$%^")
  1665  }
  1666  
  1667  func (s *DockerDaemonSuite) TestDaemonRestartRestoreBridgeNetwork(t *check.C) {
  1668  	testRequires(t, DaemonIsLinux)
  1669  	s.d.StartWithBusybox(t, "--live-restore")
  1670  	defer s.d.Stop(t)
  1671  	oldCon := "old"
  1672  
  1673  	_, err := s.d.Cmd("run", "-d", "--name", oldCon, "-p", "80:80", "busybox", "top")
  1674  	if err != nil {
  1675  		t.Fatal(err)
  1676  	}
  1677  	oldContainerIP, err := s.d.Cmd("inspect", "-f", "{{ .NetworkSettings.Networks.bridge.IPAddress }}", oldCon)
  1678  	if err != nil {
  1679  		t.Fatal(err)
  1680  	}
  1681  	// Kill the daemon
  1682  	if err := s.d.Kill(); err != nil {
  1683  		t.Fatal(err)
  1684  	}
  1685  
  1686  	// restart the daemon
  1687  	s.d.Start(t, "--live-restore")
  1688  
  1689  	// start a new container, the new container's ip should not be the same with
  1690  	// old running container.
  1691  	newCon := "new"
  1692  	_, err = s.d.Cmd("run", "-d", "--name", newCon, "busybox", "top")
  1693  	if err != nil {
  1694  		t.Fatal(err)
  1695  	}
  1696  	newContainerIP, err := s.d.Cmd("inspect", "-f", "{{ .NetworkSettings.Networks.bridge.IPAddress }}", newCon)
  1697  	if err != nil {
  1698  		t.Fatal(err)
  1699  	}
  1700  	if strings.Compare(strings.TrimSpace(oldContainerIP), strings.TrimSpace(newContainerIP)) == 0 {
  1701  		t.Fatalf("new container ip should not equal to old running container  ip")
  1702  	}
  1703  
  1704  	// start a new container, the new container should ping old running container
  1705  	_, err = s.d.Cmd("run", "-t", "busybox", "ping", "-c", "1", oldContainerIP)
  1706  	if err != nil {
  1707  		t.Fatal(err)
  1708  	}
  1709  
  1710  	// start a new container, trying to publish port 80:80 should fail
  1711  	out, err := s.d.Cmd("run", "-p", "80:80", "-d", "busybox", "top")
  1712  	if err == nil || !strings.Contains(out, "Bind for 0.0.0.0:80 failed: port is already allocated") {
  1713  		t.Fatalf("80 port is allocated to old running container, it should failed on allocating to new container")
  1714  	}
  1715  
  1716  	// kill old running container and try to allocate again
  1717  	_, err = s.d.Cmd("kill", oldCon)
  1718  	if err != nil {
  1719  		t.Fatal(err)
  1720  	}
  1721  	id, err := s.d.Cmd("run", "-p", "80:80", "-d", "busybox", "top")
  1722  	if err != nil {
  1723  		t.Fatal(err)
  1724  	}
  1725  
  1726  	// Cleanup because these containers will not be shut down by daemon
  1727  	out, err = s.d.Cmd("stop", newCon)
  1728  	if err != nil {
  1729  		t.Fatalf("err: %v %v", err, string(out))
  1730  	}
  1731  	_, err = s.d.Cmd("stop", strings.TrimSpace(id))
  1732  	if err != nil {
  1733  		t.Fatal(err)
  1734  	}
  1735  }
  1736  
  1737  func (s *DockerNetworkSuite) TestDockerNetworkFlagAlias(c *check.C) {
  1738  	dockerCmd(c, "network", "create", "user")
  1739  	output, status := dockerCmd(c, "run", "--rm", "--network=user", "--network-alias=foo", "busybox", "true")
  1740  	c.Assert(status, checker.Equals, 0, check.Commentf("unexpected status code %d (%s)", status, output))
  1741  
  1742  	output, status, _ = dockerCmdWithError("run", "--rm", "--net=user", "--network=user", "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", "--network=user", "--net-alias=foo", "--network-alias=bar", "busybox", "true")
  1746  	c.Assert(status, checker.Equals, 0, check.Commentf("unexpected status code %d (%s)", status, output))
  1747  }
  1748  
  1749  func (s *DockerNetworkSuite) TestDockerNetworkValidateIP(c *check.C) {
  1750  	_, _, err := dockerCmdWithError("network", "create", "--ipv6", "--subnet=172.28.0.0/16", "--subnet=2001:db8:1234::/64", "mynet")
  1751  	c.Assert(err, check.IsNil)
  1752  	assertNwIsAvailable(c, "mynet")
  1753  
  1754  	_, _, err = dockerCmdWithError("run", "-d", "--name", "mynet0", "--net=mynet", "--ip", "172.28.99.88", "--ip6", "2001:db8:1234::9988", "busybox", "top")
  1755  	c.Assert(err, check.IsNil)
  1756  	c.Assert(waitRun("mynet0"), check.IsNil)
  1757  	verifyIPAddressConfig(c, "mynet0", "mynet", "172.28.99.88", "2001:db8:1234::9988")
  1758  	verifyIPAddresses(c, "mynet0", "mynet", "172.28.99.88", "2001:db8:1234::9988")
  1759  
  1760  	_, _, err = dockerCmdWithError("run", "--net=mynet", "--ip", "mynet_ip", "--ip6", "2001:db8:1234::9999", "busybox", "top")
  1761  	c.Assert(err.Error(), checker.Contains, "invalid IPv4 address")
  1762  	_, _, err = dockerCmdWithError("run", "--net=mynet", "--ip", "172.28.99.99", "--ip6", "mynet_ip6", "busybox", "top")
  1763  	c.Assert(err.Error(), checker.Contains, "invalid IPv6 address")
  1764  	// This is a case of IPv4 address to `--ip6`
  1765  	_, _, err = dockerCmdWithError("run", "--net=mynet", "--ip6", "172.28.99.99", "busybox", "top")
  1766  	c.Assert(err.Error(), checker.Contains, "invalid IPv6 address")
  1767  	// This is a special case of an IPv4-mapped IPv6 address
  1768  	_, _, err = dockerCmdWithError("run", "--net=mynet", "--ip6", "::ffff:172.28.99.99", "busybox", "top")
  1769  	c.Assert(err.Error(), checker.Contains, "invalid IPv6 address")
  1770  }
  1771  
  1772  // Test case for 26220
  1773  func (s *DockerNetworkSuite) TestDockerNetworkDisconnectFromBridge(c *check.C) {
  1774  	out, _ := dockerCmd(c, "network", "inspect", "--format", "{{.Id}}", "bridge")
  1775  
  1776  	network := strings.TrimSpace(out)
  1777  
  1778  	name := "test"
  1779  	dockerCmd(c, "create", "--name", name, "busybox", "top")
  1780  
  1781  	_, _, err := dockerCmdWithError("network", "disconnect", network, name)
  1782  	c.Assert(err, check.IsNil)
  1783  }
  1784  
  1785  // TestConntrackFlowsLeak covers the failure scenario of ticket: https://github.com/docker/docker/issues/8795
  1786  // Validates that conntrack is correctly cleaned once a container is destroyed
  1787  func (s *DockerNetworkSuite) TestConntrackFlowsLeak(c *check.C) {
  1788  	testRequires(c, IsAmd64, DaemonIsLinux, Network, testEnv.IsLocalDaemon)
  1789  
  1790  	// Create a new network
  1791  	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")
  1792  	assertNwIsAvailable(c, "testbind")
  1793  
  1794  	// Launch the server, this will remain listening on an exposed port and reply to any request in a ping/pong fashion
  1795  	cmd := "while true; do echo hello | nc -w 1 -lu 8080; done"
  1796  	cli.DockerCmd(c, "run", "-d", "--name", "server", "--net", "testbind", "-p", "8080:8080/udp", "appropriate/nc", "sh", "-c", cmd)
  1797  
  1798  	// Launch a container client, here the objective is to create a flow that is natted in order to expose the bug
  1799  	cmd = "echo world | nc -q 1 -u 192.168.10.1 8080"
  1800  	cli.DockerCmd(c, "run", "-d", "--name", "client", "--net=host", "appropriate/nc", "sh", "-c", cmd)
  1801  
  1802  	// Get all the flows using netlink
  1803  	flows, err := netlink.ConntrackTableList(netlink.ConntrackTable, unix.AF_INET)
  1804  	c.Assert(err, check.IsNil)
  1805  	var flowMatch int
  1806  	for _, flow := range flows {
  1807  		// count only the flows that we are interested in, skipping others that can be laying around the host
  1808  		if flow.Forward.Protocol == unix.IPPROTO_UDP &&
  1809  			flow.Forward.DstIP.Equal(net.ParseIP("192.168.10.1")) &&
  1810  			flow.Forward.DstPort == 8080 {
  1811  			flowMatch++
  1812  		}
  1813  	}
  1814  	// The client should have created only 1 flow
  1815  	c.Assert(flowMatch, checker.Equals, 1)
  1816  
  1817  	// Now delete the server, this will trigger the conntrack cleanup
  1818  	cli.DockerCmd(c, "rm", "-fv", "server")
  1819  
  1820  	// Fetch again all the flows and validate that there is no server flow in the conntrack laying around
  1821  	flows, err = netlink.ConntrackTableList(netlink.ConntrackTable, unix.AF_INET)
  1822  	c.Assert(err, check.IsNil)
  1823  	flowMatch = 0
  1824  	for _, flow := range flows {
  1825  		if flow.Forward.Protocol == unix.IPPROTO_UDP &&
  1826  			flow.Forward.DstIP.Equal(net.ParseIP("192.168.10.1")) &&
  1827  			flow.Forward.DstPort == 8080 {
  1828  			flowMatch++
  1829  		}
  1830  	}
  1831  	// All the flows have to be gone
  1832  	c.Assert(flowMatch, checker.Equals, 0)
  1833  }