github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/integration/network/service_test.go (about)

     1  package network // import "github.com/demonoid81/moby/integration/network"
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/demonoid81/moby/api/types"
     9  	swarmtypes "github.com/demonoid81/moby/api/types/swarm"
    10  	"github.com/demonoid81/moby/api/types/versions"
    11  	"github.com/demonoid81/moby/client"
    12  	"github.com/demonoid81/moby/integration/internal/network"
    13  	"github.com/demonoid81/moby/integration/internal/swarm"
    14  	"github.com/demonoid81/moby/testutil/daemon"
    15  	"gotest.tools/v3/assert"
    16  	"gotest.tools/v3/icmd"
    17  	"gotest.tools/v3/poll"
    18  	"gotest.tools/v3/skip"
    19  )
    20  
    21  // delInterface removes given network interface
    22  func delInterface(t *testing.T, ifName string) {
    23  	icmd.RunCommand("ip", "link", "delete", ifName).Assert(t, icmd.Success)
    24  	icmd.RunCommand("iptables", "-t", "nat", "--flush").Assert(t, icmd.Success)
    25  	icmd.RunCommand("iptables", "--flush").Assert(t, icmd.Success)
    26  }
    27  
    28  func TestDaemonRestartWithLiveRestore(t *testing.T) {
    29  	skip.If(t, testEnv.OSType == "windows")
    30  	skip.If(t, testEnv.IsRemoteDaemon)
    31  	skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.38"), "skip test from new feature")
    32  	skip.If(t, testEnv.IsRootless, "rootless mode has different view of network")
    33  	d := daemon.New(t)
    34  	defer d.Stop(t)
    35  	d.Start(t)
    36  	d.Restart(t,
    37  		"--live-restore=true",
    38  		"--default-address-pool", "base=175.30.0.0/16,size=16",
    39  		"--default-address-pool", "base=175.33.0.0/16,size=24",
    40  	)
    41  
    42  	// Verify bridge network's subnet
    43  	c := d.NewClientT(t)
    44  	defer c.Close()
    45  	out, err := c.NetworkInspect(context.Background(), "bridge", types.NetworkInspectOptions{})
    46  	assert.NilError(t, err)
    47  	// Make sure docker0 doesn't get override with new IP in live restore case
    48  	assert.Equal(t, out.IPAM.Config[0].Subnet, "172.18.0.0/16")
    49  }
    50  
    51  func TestDaemonDefaultNetworkPools(t *testing.T) {
    52  	skip.If(t, testEnv.OSType == "windows")
    53  	// Remove docker0 bridge and the start daemon defining the predefined address pools
    54  	skip.If(t, testEnv.IsRemoteDaemon)
    55  	skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.38"), "skip test from new feature")
    56  	skip.If(t, testEnv.IsRootless, "rootless mode has different view of network")
    57  	defaultNetworkBridge := "docker0"
    58  	delInterface(t, defaultNetworkBridge)
    59  	d := daemon.New(t)
    60  	defer d.Stop(t)
    61  	d.Start(t,
    62  		"--default-address-pool", "base=175.30.0.0/16,size=16",
    63  		"--default-address-pool", "base=175.33.0.0/16,size=24",
    64  	)
    65  
    66  	c := d.NewClientT(t)
    67  	defer c.Close()
    68  
    69  	// Verify bridge network's subnet
    70  	out, err := c.NetworkInspect(context.Background(), "bridge", types.NetworkInspectOptions{})
    71  	assert.NilError(t, err)
    72  	assert.Equal(t, out.IPAM.Config[0].Subnet, "175.30.0.0/16")
    73  
    74  	// Create a bridge network and verify its subnet is the second default pool
    75  	name := "elango" + t.Name()
    76  	network.CreateNoError(context.Background(), t, c, name,
    77  		network.WithDriver("bridge"),
    78  	)
    79  	out, err = c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{})
    80  	assert.NilError(t, err)
    81  	assert.Equal(t, out.IPAM.Config[0].Subnet, "175.33.0.0/24")
    82  
    83  	// Create a bridge network and verify its subnet is the third default pool
    84  	name = "saanvi" + t.Name()
    85  	network.CreateNoError(context.Background(), t, c, name,
    86  		network.WithDriver("bridge"),
    87  	)
    88  	out, err = c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{})
    89  	assert.NilError(t, err)
    90  	assert.Equal(t, out.IPAM.Config[0].Subnet, "175.33.1.0/24")
    91  	delInterface(t, defaultNetworkBridge)
    92  
    93  }
    94  
    95  func TestDaemonRestartWithExistingNetwork(t *testing.T) {
    96  	skip.If(t, testEnv.OSType == "windows")
    97  	skip.If(t, testEnv.IsRemoteDaemon)
    98  	skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.38"), "skip test from new feature")
    99  	skip.If(t, testEnv.IsRootless, "rootless mode has different view of network")
   100  	defaultNetworkBridge := "docker0"
   101  	d := daemon.New(t)
   102  	d.Start(t)
   103  	defer d.Stop(t)
   104  	c := d.NewClientT(t)
   105  	defer c.Close()
   106  
   107  	// Create a bridge network
   108  	name := "elango" + t.Name()
   109  	network.CreateNoError(context.Background(), t, c, name,
   110  		network.WithDriver("bridge"),
   111  	)
   112  
   113  	// Verify bridge network's subnet
   114  	out, err := c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{})
   115  	assert.NilError(t, err)
   116  	networkip := out.IPAM.Config[0].Subnet
   117  
   118  	// Restart daemon with default address pool option
   119  	d.Restart(t,
   120  		"--default-address-pool", "base=175.30.0.0/16,size=16",
   121  		"--default-address-pool", "base=175.33.0.0/16,size=24")
   122  
   123  	out1, err := c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{})
   124  	assert.NilError(t, err)
   125  	assert.Equal(t, out1.IPAM.Config[0].Subnet, networkip)
   126  	delInterface(t, defaultNetworkBridge)
   127  }
   128  
   129  func TestDaemonRestartWithExistingNetworkWithDefaultPoolRange(t *testing.T) {
   130  	skip.If(t, testEnv.OSType == "windows")
   131  	skip.If(t, testEnv.IsRemoteDaemon)
   132  	skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.38"), "skip test from new feature")
   133  	skip.If(t, testEnv.IsRootless, "rootless mode has different view of network")
   134  	defaultNetworkBridge := "docker0"
   135  	d := daemon.New(t)
   136  	d.Start(t)
   137  	defer d.Stop(t)
   138  	c := d.NewClientT(t)
   139  	defer c.Close()
   140  
   141  	// Create a bridge network
   142  	name := "elango" + t.Name()
   143  	network.CreateNoError(context.Background(), t, c, name,
   144  		network.WithDriver("bridge"),
   145  	)
   146  
   147  	// Verify bridge network's subnet
   148  	out, err := c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{})
   149  	assert.NilError(t, err)
   150  	networkip := out.IPAM.Config[0].Subnet
   151  
   152  	// Create a bridge network
   153  	name = "sthira" + t.Name()
   154  	network.CreateNoError(context.Background(), t, c, name,
   155  		network.WithDriver("bridge"),
   156  	)
   157  	out, err = c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{})
   158  	assert.NilError(t, err)
   159  	networkip2 := out.IPAM.Config[0].Subnet
   160  
   161  	// Restart daemon with default address pool option
   162  	d.Restart(t,
   163  		"--default-address-pool", "base=175.18.0.0/16,size=16",
   164  		"--default-address-pool", "base=175.19.0.0/16,size=24",
   165  	)
   166  
   167  	// Create a bridge network
   168  	name = "saanvi" + t.Name()
   169  	network.CreateNoError(context.Background(), t, c, name,
   170  		network.WithDriver("bridge"),
   171  	)
   172  	out1, err := c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{})
   173  	assert.NilError(t, err)
   174  
   175  	assert.Check(t, out1.IPAM.Config[0].Subnet != networkip)
   176  	assert.Check(t, out1.IPAM.Config[0].Subnet != networkip2)
   177  	delInterface(t, defaultNetworkBridge)
   178  }
   179  
   180  func TestDaemonWithBipAndDefaultNetworkPool(t *testing.T) {
   181  	skip.If(t, testEnv.OSType == "windows")
   182  	skip.If(t, testEnv.IsRemoteDaemon)
   183  	skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.38"), "skip test from new feature")
   184  	skip.If(t, testEnv.IsRootless, "rootless mode has different view of network")
   185  	defaultNetworkBridge := "docker0"
   186  	d := daemon.New(t)
   187  	defer d.Stop(t)
   188  	d.Start(t,
   189  		"--bip=172.60.0.1/16",
   190  		"--default-address-pool", "base=175.30.0.0/16,size=16",
   191  		"--default-address-pool", "base=175.33.0.0/16,size=24",
   192  	)
   193  
   194  	c := d.NewClientT(t)
   195  	defer c.Close()
   196  
   197  	// Verify bridge network's subnet
   198  	out, err := c.NetworkInspect(context.Background(), "bridge", types.NetworkInspectOptions{})
   199  	assert.NilError(t, err)
   200  	// Make sure BIP IP doesn't get override with new default address pool .
   201  	assert.Equal(t, out.IPAM.Config[0].Subnet, "172.60.0.0/16")
   202  	delInterface(t, defaultNetworkBridge)
   203  }
   204  
   205  func TestServiceWithPredefinedNetwork(t *testing.T) {
   206  	skip.If(t, testEnv.OSType == "windows")
   207  	skip.If(t, testEnv.IsRootless, "rootless mode doesn't support Swarm-mode")
   208  	defer setupTest(t)()
   209  	d := swarm.NewSwarm(t, testEnv)
   210  	defer d.Stop(t)
   211  	c := d.NewClientT(t)
   212  	defer c.Close()
   213  
   214  	hostName := "host"
   215  	var instances uint64 = 1
   216  	serviceName := "TestService" + t.Name()
   217  
   218  	serviceID := swarm.CreateService(t, d,
   219  		swarm.ServiceWithReplicas(instances),
   220  		swarm.ServiceWithName(serviceName),
   221  		swarm.ServiceWithNetwork(hostName),
   222  	)
   223  
   224  	poll.WaitOn(t, swarm.RunningTasksCount(c, serviceID, instances), swarm.ServicePoll)
   225  
   226  	_, _, err := c.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
   227  	assert.NilError(t, err)
   228  
   229  	err = c.ServiceRemove(context.Background(), serviceID)
   230  	assert.NilError(t, err)
   231  }
   232  
   233  const ingressNet = "ingress"
   234  
   235  func TestServiceRemoveKeepsIngressNetwork(t *testing.T) {
   236  	t.Skip("FLAKY_TEST")
   237  	skip.If(t, testEnv.IsRootless, "rootless mode doesn't support Swarm-mode")
   238  
   239  	skip.If(t, testEnv.OSType == "windows")
   240  	defer setupTest(t)()
   241  	d := swarm.NewSwarm(t, testEnv)
   242  	defer d.Stop(t)
   243  	c := d.NewClientT(t)
   244  	defer c.Close()
   245  
   246  	poll.WaitOn(t, swarmIngressReady(c), swarm.NetworkPoll)
   247  
   248  	var instances uint64 = 1
   249  
   250  	serviceID := swarm.CreateService(t, d,
   251  		swarm.ServiceWithReplicas(instances),
   252  		swarm.ServiceWithName(t.Name()+"-service"),
   253  		swarm.ServiceWithEndpoint(&swarmtypes.EndpointSpec{
   254  			Ports: []swarmtypes.PortConfig{
   255  				{
   256  					Protocol:    swarmtypes.PortConfigProtocolTCP,
   257  					TargetPort:  80,
   258  					PublishMode: swarmtypes.PortConfigPublishModeIngress,
   259  				},
   260  			},
   261  		}),
   262  	)
   263  
   264  	poll.WaitOn(t, swarm.RunningTasksCount(c, serviceID, instances), swarm.ServicePoll)
   265  
   266  	ctx := context.Background()
   267  	_, _, err := c.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{})
   268  	assert.NilError(t, err)
   269  
   270  	err = c.ServiceRemove(ctx, serviceID)
   271  	assert.NilError(t, err)
   272  
   273  	poll.WaitOn(t, noServices(ctx, c), swarm.ServicePoll)
   274  	poll.WaitOn(t, swarm.NoTasks(ctx, c), swarm.ServicePoll)
   275  
   276  	// Ensure that "ingress" is not removed or corrupted
   277  	time.Sleep(10 * time.Second)
   278  	netInfo, err := c.NetworkInspect(ctx, ingressNet, types.NetworkInspectOptions{
   279  		Verbose: true,
   280  		Scope:   "swarm",
   281  	})
   282  	assert.NilError(t, err, "Ingress network was removed after removing service!")
   283  	assert.Assert(t, len(netInfo.Containers) != 0, "No load balancing endpoints in ingress network")
   284  	assert.Assert(t, len(netInfo.Peers) != 0, "No peers (including self) in ingress network")
   285  	_, ok := netInfo.Containers["ingress-sbox"]
   286  	assert.Assert(t, ok, "ingress-sbox not present in ingress network")
   287  }
   288  
   289  func swarmIngressReady(client client.NetworkAPIClient) func(log poll.LogT) poll.Result {
   290  	return func(log poll.LogT) poll.Result {
   291  		netInfo, err := client.NetworkInspect(context.Background(), ingressNet, types.NetworkInspectOptions{
   292  			Verbose: true,
   293  			Scope:   "swarm",
   294  		})
   295  		if err != nil {
   296  			return poll.Error(err)
   297  		}
   298  		np := len(netInfo.Peers)
   299  		nc := len(netInfo.Containers)
   300  		if np == 0 || nc == 0 {
   301  			return poll.Continue("ingress not ready: %d peers and %d containers", nc, np)
   302  		}
   303  		_, ok := netInfo.Containers["ingress-sbox"]
   304  		if !ok {
   305  			return poll.Continue("ingress not ready: does not contain the ingress-sbox")
   306  		}
   307  		return poll.Success()
   308  	}
   309  }
   310  
   311  func noServices(ctx context.Context, client client.ServiceAPIClient) func(log poll.LogT) poll.Result {
   312  	return func(log poll.LogT) poll.Result {
   313  		services, err := client.ServiceList(ctx, types.ServiceListOptions{})
   314  		switch {
   315  		case err != nil:
   316  			return poll.Error(err)
   317  		case len(services) == 0:
   318  			return poll.Success()
   319  		default:
   320  			return poll.Continue("waiting for all services to be removed: service count at %d", len(services))
   321  		}
   322  	}
   323  }
   324  
   325  func TestServiceWithDataPathPortInit(t *testing.T) {
   326  	skip.If(t, testEnv.OSType == "windows")
   327  	skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.40"), "DataPathPort was added in API v1.40")
   328  	skip.If(t, testEnv.IsRootless, "rootless mode doesn't support Swarm-mode")
   329  	defer setupTest(t)()
   330  	var datapathPort uint32 = 7777
   331  	d := swarm.NewSwarm(t, testEnv, daemon.WithSwarmDataPathPort(datapathPort))
   332  	c := d.NewClientT(t)
   333  	ctx := context.Background()
   334  	// Create a overlay network
   335  	name := "saanvisthira" + t.Name()
   336  	overlayID := network.CreateNoError(context.Background(), t, c, name,
   337  		network.WithDriver("overlay"))
   338  
   339  	var instances uint64 = 1
   340  	serviceID := swarm.CreateService(t, d,
   341  		swarm.ServiceWithReplicas(instances),
   342  		swarm.ServiceWithName(name),
   343  		swarm.ServiceWithNetwork(name),
   344  	)
   345  
   346  	poll.WaitOn(t, swarm.RunningTasksCount(c, serviceID, instances), swarm.ServicePoll)
   347  
   348  	info := d.Info(t)
   349  	assert.Equal(t, info.Swarm.Cluster.DataPathPort, datapathPort)
   350  	err := c.ServiceRemove(ctx, serviceID)
   351  	assert.NilError(t, err)
   352  	poll.WaitOn(t, noServices(ctx, c), swarm.ServicePoll)
   353  	poll.WaitOn(t, swarm.NoTasks(ctx, c), swarm.ServicePoll)
   354  	err = c.NetworkRemove(ctx, overlayID)
   355  	assert.NilError(t, err)
   356  	c.Close()
   357  	err = d.SwarmLeave(t, true)
   358  	assert.NilError(t, err)
   359  	d.Stop(t)
   360  
   361  	// Clean up , set it back to original one to make sure other tests don't fail
   362  	// call without datapath port option.
   363  	d = swarm.NewSwarm(t, testEnv)
   364  	defer d.Stop(t)
   365  	nc := d.NewClientT(t)
   366  	defer nc.Close()
   367  	// Create a overlay network
   368  	name = "not-saanvisthira" + t.Name()
   369  	overlayID = network.CreateNoError(ctx, t, nc, name,
   370  		network.WithDriver("overlay"))
   371  
   372  	serviceID = swarm.CreateService(t, d,
   373  		swarm.ServiceWithReplicas(instances),
   374  		swarm.ServiceWithName(name),
   375  		swarm.ServiceWithNetwork(name),
   376  	)
   377  
   378  	poll.WaitOn(t, swarm.RunningTasksCount(nc, serviceID, instances), swarm.ServicePoll)
   379  
   380  	info = d.Info(t)
   381  	var defaultDataPathPort uint32 = 4789
   382  	assert.Equal(t, info.Swarm.Cluster.DataPathPort, defaultDataPathPort)
   383  	err = nc.ServiceRemove(ctx, serviceID)
   384  	assert.NilError(t, err)
   385  	poll.WaitOn(t, noServices(ctx, nc), swarm.ServicePoll)
   386  	poll.WaitOn(t, swarm.NoTasks(ctx, nc), swarm.ServicePoll)
   387  	err = nc.NetworkRemove(ctx, overlayID)
   388  	assert.NilError(t, err)
   389  	err = d.SwarmLeave(t, true)
   390  	assert.NilError(t, err)
   391  }
   392  
   393  func TestServiceWithDefaultAddressPoolInit(t *testing.T) {
   394  	skip.If(t, testEnv.OSType == "windows")
   395  	skip.If(t, testEnv.IsRootless, "rootless mode doesn't support Swarm-mode")
   396  	defer setupTest(t)()
   397  	d := swarm.NewSwarm(t, testEnv,
   398  		daemon.WithSwarmDefaultAddrPool([]string{"20.20.0.0/16"}),
   399  		daemon.WithSwarmDefaultAddrPoolSubnetSize(24))
   400  	defer d.Stop(t)
   401  	cli := d.NewClientT(t)
   402  	defer cli.Close()
   403  	ctx := context.Background()
   404  
   405  	// Create a overlay network
   406  	name := "sthira" + t.Name()
   407  	overlayID := network.CreateNoError(ctx, t, cli, name,
   408  		network.WithDriver("overlay"),
   409  		network.WithCheckDuplicate(),
   410  	)
   411  
   412  	var instances uint64 = 1
   413  	serviceName := "TestService" + t.Name()
   414  	serviceID := swarm.CreateService(t, d,
   415  		swarm.ServiceWithReplicas(instances),
   416  		swarm.ServiceWithName(serviceName),
   417  		swarm.ServiceWithNetwork(name),
   418  	)
   419  
   420  	poll.WaitOn(t, swarm.RunningTasksCount(cli, serviceID, instances), swarm.ServicePoll)
   421  
   422  	_, _, err := cli.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{})
   423  	assert.NilError(t, err)
   424  
   425  	out, err := cli.NetworkInspect(ctx, overlayID, types.NetworkInspectOptions{Verbose: true})
   426  	assert.NilError(t, err)
   427  	t.Logf("%s: NetworkInspect: %+v", t.Name(), out)
   428  	assert.Assert(t, len(out.IPAM.Config) > 0)
   429  	// As of docker/swarmkit#2890, the ingress network uses the default address
   430  	// pool (whereas before, the subnet for the ingress network was hard-coded.
   431  	// This means that the ingress network gets the subnet 20.20.0.0/24, and
   432  	// the network we just created gets subnet 20.20.1.0/24.
   433  	assert.Equal(t, out.IPAM.Config[0].Subnet, "20.20.1.0/24")
   434  
   435  	// Also inspect ingress network and make sure its in the same subnet
   436  	out, err = cli.NetworkInspect(ctx, "ingress", types.NetworkInspectOptions{Verbose: true})
   437  	assert.NilError(t, err)
   438  	assert.Assert(t, len(out.IPAM.Config) > 0)
   439  	assert.Equal(t, out.IPAM.Config[0].Subnet, "20.20.0.0/24")
   440  
   441  	err = cli.ServiceRemove(ctx, serviceID)
   442  	poll.WaitOn(t, noServices(ctx, cli), swarm.ServicePoll)
   443  	poll.WaitOn(t, swarm.NoTasks(ctx, cli), swarm.ServicePoll)
   444  	assert.NilError(t, err)
   445  	err = cli.NetworkRemove(ctx, overlayID)
   446  	assert.NilError(t, err)
   447  	err = d.SwarmLeave(t, true)
   448  	assert.NilError(t, err)
   449  
   450  }