github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/allocator/cnmallocator/networkallocator_test.go (about)

     1  package cnmallocator
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"testing"
     7  
     8  	"github.com/docker/libnetwork/discoverapi"
     9  	"github.com/docker/libnetwork/types"
    10  	"github.com/docker/swarmkit/api"
    11  	"github.com/docker/swarmkit/manager/allocator/networkallocator"
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  func newNetworkAllocator(t *testing.T) networkallocator.NetworkAllocator {
    16  	na, err := New(nil, nil)
    17  	assert.NoError(t, err)
    18  	assert.NotNil(t, na)
    19  	return na
    20  }
    21  
    22  func TestNew(t *testing.T) {
    23  	newNetworkAllocator(t)
    24  }
    25  
    26  func TestAllocateInvalidIPAM(t *testing.T) {
    27  	na := newNetworkAllocator(t)
    28  	n := &api.Network{
    29  		ID: "testID",
    30  		Spec: api.NetworkSpec{
    31  			Annotations: api.Annotations{
    32  				Name: "test",
    33  			},
    34  			DriverConfig: &api.Driver{},
    35  			IPAM: &api.IPAMOptions{
    36  				Driver: &api.Driver{
    37  					Name: "invalidipam,",
    38  				},
    39  			},
    40  		},
    41  	}
    42  	err := na.Allocate(n)
    43  	assert.Error(t, err)
    44  }
    45  
    46  func TestAllocateInvalidDriver(t *testing.T) {
    47  	na := newNetworkAllocator(t)
    48  	n := &api.Network{
    49  		ID: "testID",
    50  		Spec: api.NetworkSpec{
    51  			Annotations: api.Annotations{
    52  				Name: "test",
    53  			},
    54  			DriverConfig: &api.Driver{
    55  				Name: "invaliddriver",
    56  			},
    57  		},
    58  	}
    59  
    60  	err := na.Allocate(n)
    61  	assert.Error(t, err)
    62  }
    63  
    64  func TestNetworkDoubleAllocate(t *testing.T) {
    65  	na := newNetworkAllocator(t)
    66  	n := &api.Network{
    67  		ID: "testID",
    68  		Spec: api.NetworkSpec{
    69  			Annotations: api.Annotations{
    70  				Name: "test",
    71  			},
    72  		},
    73  	}
    74  
    75  	err := na.Allocate(n)
    76  	assert.NoError(t, err)
    77  
    78  	err = na.Allocate(n)
    79  	assert.Error(t, err)
    80  }
    81  
    82  func TestAllocateEmptyConfig(t *testing.T) {
    83  	na1 := newNetworkAllocator(t)
    84  	na2 := newNetworkAllocator(t)
    85  	n1 := &api.Network{
    86  		ID: "testID1",
    87  		Spec: api.NetworkSpec{
    88  			Annotations: api.Annotations{
    89  				Name: "test1",
    90  			},
    91  		},
    92  	}
    93  
    94  	n2 := &api.Network{
    95  		ID: "testID2",
    96  		Spec: api.NetworkSpec{
    97  			Annotations: api.Annotations{
    98  				Name: "test2",
    99  			},
   100  		},
   101  	}
   102  
   103  	err := na1.Allocate(n1)
   104  	assert.NoError(t, err)
   105  	assert.NotEqual(t, n1.IPAM.Configs, nil)
   106  	assert.Equal(t, len(n1.IPAM.Configs), 1)
   107  	assert.Equal(t, n1.IPAM.Configs[0].Range, "")
   108  	assert.Equal(t, len(n1.IPAM.Configs[0].Reserved), 0)
   109  
   110  	_, subnet11, err := net.ParseCIDR(n1.IPAM.Configs[0].Subnet)
   111  	assert.NoError(t, err)
   112  
   113  	gwip11 := net.ParseIP(n1.IPAM.Configs[0].Gateway)
   114  	assert.NotEqual(t, gwip11, nil)
   115  
   116  	err = na1.Allocate(n2)
   117  	assert.NoError(t, err)
   118  	assert.NotEqual(t, n2.IPAM.Configs, nil)
   119  	assert.Equal(t, len(n2.IPAM.Configs), 1)
   120  	assert.Equal(t, n2.IPAM.Configs[0].Range, "")
   121  	assert.Equal(t, len(n2.IPAM.Configs[0].Reserved), 0)
   122  
   123  	_, subnet21, err := net.ParseCIDR(n2.IPAM.Configs[0].Subnet)
   124  	assert.NoError(t, err)
   125  
   126  	gwip21 := net.ParseIP(n2.IPAM.Configs[0].Gateway)
   127  	assert.NotEqual(t, gwip21, nil)
   128  
   129  	// Allocate n1 ans n2 with another allocator instance but in
   130  	// intentionally reverse order.
   131  	err = na2.Allocate(n2)
   132  	assert.NoError(t, err)
   133  	assert.NotEqual(t, n2.IPAM.Configs, nil)
   134  	assert.Equal(t, len(n2.IPAM.Configs), 1)
   135  	assert.Equal(t, n2.IPAM.Configs[0].Range, "")
   136  	assert.Equal(t, len(n2.IPAM.Configs[0].Reserved), 0)
   137  
   138  	_, subnet22, err := net.ParseCIDR(n2.IPAM.Configs[0].Subnet)
   139  	assert.NoError(t, err)
   140  	assert.Equal(t, subnet21, subnet22)
   141  
   142  	gwip22 := net.ParseIP(n2.IPAM.Configs[0].Gateway)
   143  	assert.Equal(t, gwip21, gwip22)
   144  
   145  	err = na2.Allocate(n1)
   146  	assert.NoError(t, err)
   147  	assert.NotEqual(t, n1.IPAM.Configs, nil)
   148  	assert.Equal(t, len(n1.IPAM.Configs), 1)
   149  	assert.Equal(t, n1.IPAM.Configs[0].Range, "")
   150  	assert.Equal(t, len(n1.IPAM.Configs[0].Reserved), 0)
   151  
   152  	_, subnet12, err := net.ParseCIDR(n1.IPAM.Configs[0].Subnet)
   153  	assert.NoError(t, err)
   154  	assert.Equal(t, subnet11, subnet12)
   155  
   156  	gwip12 := net.ParseIP(n1.IPAM.Configs[0].Gateway)
   157  	assert.Equal(t, gwip11, gwip12)
   158  }
   159  
   160  func TestAllocateWithOneSubnet(t *testing.T) {
   161  	na := newNetworkAllocator(t)
   162  	n := &api.Network{
   163  		ID: "testID",
   164  		Spec: api.NetworkSpec{
   165  			Annotations: api.Annotations{
   166  				Name: "test",
   167  			},
   168  			DriverConfig: &api.Driver{},
   169  			IPAM: &api.IPAMOptions{
   170  				Driver: &api.Driver{},
   171  				Configs: []*api.IPAMConfig{
   172  					{
   173  						Subnet: "192.168.1.0/24",
   174  					},
   175  				},
   176  			},
   177  		},
   178  	}
   179  
   180  	err := na.Allocate(n)
   181  	assert.NoError(t, err)
   182  	assert.Equal(t, len(n.IPAM.Configs), 1)
   183  	assert.Equal(t, n.IPAM.Configs[0].Range, "")
   184  	assert.Equal(t, len(n.IPAM.Configs[0].Reserved), 0)
   185  	assert.Equal(t, n.IPAM.Configs[0].Subnet, "192.168.1.0/24")
   186  
   187  	ip := net.ParseIP(n.IPAM.Configs[0].Gateway)
   188  	assert.NotEqual(t, ip, nil)
   189  }
   190  
   191  func TestAllocateWithOneSubnetGateway(t *testing.T) {
   192  	na := newNetworkAllocator(t)
   193  	n := &api.Network{
   194  		ID: "testID",
   195  		Spec: api.NetworkSpec{
   196  			Annotations: api.Annotations{
   197  				Name: "test",
   198  			},
   199  			DriverConfig: &api.Driver{},
   200  			IPAM: &api.IPAMOptions{
   201  				Driver: &api.Driver{},
   202  				Configs: []*api.IPAMConfig{
   203  					{
   204  						Subnet:  "192.168.1.0/24",
   205  						Gateway: "192.168.1.1",
   206  					},
   207  				},
   208  			},
   209  		},
   210  	}
   211  
   212  	err := na.Allocate(n)
   213  	assert.NoError(t, err)
   214  	assert.Equal(t, len(n.IPAM.Configs), 1)
   215  	assert.Equal(t, n.IPAM.Configs[0].Range, "")
   216  	assert.Equal(t, len(n.IPAM.Configs[0].Reserved), 0)
   217  	assert.Equal(t, n.IPAM.Configs[0].Subnet, "192.168.1.0/24")
   218  	assert.Equal(t, n.IPAM.Configs[0].Gateway, "192.168.1.1")
   219  }
   220  
   221  func TestAllocateWithOneSubnetInvalidGateway(t *testing.T) {
   222  	na := newNetworkAllocator(t)
   223  	n := &api.Network{
   224  		ID: "testID",
   225  		Spec: api.NetworkSpec{
   226  			Annotations: api.Annotations{
   227  				Name: "test",
   228  			},
   229  			DriverConfig: &api.Driver{},
   230  			IPAM: &api.IPAMOptions{
   231  				Driver: &api.Driver{},
   232  				Configs: []*api.IPAMConfig{
   233  					{
   234  						Subnet:  "192.168.1.0/24",
   235  						Gateway: "192.168.2.1",
   236  					},
   237  				},
   238  			},
   239  		},
   240  	}
   241  
   242  	err := na.Allocate(n)
   243  	assert.Error(t, err)
   244  }
   245  
   246  func TestAllocateWithInvalidSubnet(t *testing.T) {
   247  	na := newNetworkAllocator(t)
   248  	n := &api.Network{
   249  		ID: "testID",
   250  		Spec: api.NetworkSpec{
   251  			Annotations: api.Annotations{
   252  				Name: "test",
   253  			},
   254  			DriverConfig: &api.Driver{},
   255  			IPAM: &api.IPAMOptions{
   256  				Driver: &api.Driver{},
   257  				Configs: []*api.IPAMConfig{
   258  					{
   259  						Subnet: "1.1.1.1/32",
   260  					},
   261  				},
   262  			},
   263  		},
   264  	}
   265  
   266  	err := na.Allocate(n)
   267  	assert.Error(t, err)
   268  }
   269  
   270  func TestAllocateWithTwoSubnetsNoGateway(t *testing.T) {
   271  	na := newNetworkAllocator(t)
   272  	n := &api.Network{
   273  		ID: "testID",
   274  		Spec: api.NetworkSpec{
   275  			Annotations: api.Annotations{
   276  				Name: "test",
   277  			},
   278  			DriverConfig: &api.Driver{},
   279  			IPAM: &api.IPAMOptions{
   280  				Driver: &api.Driver{},
   281  				Configs: []*api.IPAMConfig{
   282  					{
   283  						Subnet: "192.168.1.0/24",
   284  					},
   285  					{
   286  						Subnet: "192.168.2.0/24",
   287  					},
   288  				},
   289  			},
   290  		},
   291  	}
   292  
   293  	err := na.Allocate(n)
   294  	assert.NoError(t, err)
   295  	assert.Equal(t, len(n.IPAM.Configs), 2)
   296  	assert.Equal(t, n.IPAM.Configs[0].Range, "")
   297  	assert.Equal(t, len(n.IPAM.Configs[0].Reserved), 0)
   298  	assert.Equal(t, n.IPAM.Configs[0].Subnet, "192.168.1.0/24")
   299  	assert.Equal(t, n.IPAM.Configs[1].Range, "")
   300  	assert.Equal(t, len(n.IPAM.Configs[1].Reserved), 0)
   301  	assert.Equal(t, n.IPAM.Configs[1].Subnet, "192.168.2.0/24")
   302  
   303  	ip := net.ParseIP(n.IPAM.Configs[0].Gateway)
   304  	assert.NotEqual(t, ip, nil)
   305  	ip = net.ParseIP(n.IPAM.Configs[1].Gateway)
   306  	assert.NotEqual(t, ip, nil)
   307  }
   308  
   309  func TestFree(t *testing.T) {
   310  	na := newNetworkAllocator(t)
   311  	n := &api.Network{
   312  		ID: "testID",
   313  		Spec: api.NetworkSpec{
   314  			Annotations: api.Annotations{
   315  				Name: "test",
   316  			},
   317  			DriverConfig: &api.Driver{},
   318  			IPAM: &api.IPAMOptions{
   319  				Driver: &api.Driver{},
   320  				Configs: []*api.IPAMConfig{
   321  					{
   322  						Subnet:  "192.168.1.0/24",
   323  						Gateway: "192.168.1.1",
   324  					},
   325  				},
   326  			},
   327  		},
   328  	}
   329  
   330  	err := na.Allocate(n)
   331  	assert.NoError(t, err)
   332  
   333  	err = na.Deallocate(n)
   334  	assert.NoError(t, err)
   335  
   336  	// Reallocate again to make sure it succeeds.
   337  	err = na.Allocate(n)
   338  	assert.NoError(t, err)
   339  }
   340  
   341  func TestAllocateTaskFree(t *testing.T) {
   342  	na1 := newNetworkAllocator(t)
   343  	na2 := newNetworkAllocator(t)
   344  	n1 := &api.Network{
   345  		ID: "testID1",
   346  		Spec: api.NetworkSpec{
   347  			Annotations: api.Annotations{
   348  				Name: "test1",
   349  			},
   350  			DriverConfig: &api.Driver{},
   351  			IPAM: &api.IPAMOptions{
   352  				Driver: &api.Driver{},
   353  				Configs: []*api.IPAMConfig{
   354  					{
   355  						Subnet:  "192.168.1.0/24",
   356  						Gateway: "192.168.1.1",
   357  					},
   358  				},
   359  			},
   360  		},
   361  	}
   362  
   363  	n2 := &api.Network{
   364  		ID: "testID2",
   365  		Spec: api.NetworkSpec{
   366  			Annotations: api.Annotations{
   367  				Name: "test2",
   368  			},
   369  			DriverConfig: &api.Driver{},
   370  			IPAM: &api.IPAMOptions{
   371  				Driver: &api.Driver{},
   372  				Configs: []*api.IPAMConfig{
   373  					{
   374  						Subnet:  "192.168.2.0/24",
   375  						Gateway: "192.168.2.1",
   376  					},
   377  				},
   378  			},
   379  		},
   380  	}
   381  
   382  	task1 := &api.Task{
   383  		Networks: []*api.NetworkAttachment{
   384  			{
   385  				Network: n1,
   386  			},
   387  			{
   388  				Network: n2,
   389  			},
   390  		},
   391  	}
   392  
   393  	task2 := &api.Task{
   394  		Networks: []*api.NetworkAttachment{
   395  			{
   396  				Network: n1,
   397  			},
   398  			{
   399  				Network: n2,
   400  			},
   401  		},
   402  	}
   403  
   404  	err := na1.Allocate(n1)
   405  	assert.NoError(t, err)
   406  
   407  	err = na1.Allocate(n2)
   408  	assert.NoError(t, err)
   409  
   410  	err = na1.AllocateTask(task1)
   411  	assert.NoError(t, err)
   412  	assert.Equal(t, len(task1.Networks[0].Addresses), 1)
   413  	assert.Equal(t, len(task1.Networks[1].Addresses), 1)
   414  
   415  	_, subnet1, _ := net.ParseCIDR("192.168.1.0/24")
   416  	_, subnet2, _ := net.ParseCIDR("192.168.2.0/24")
   417  
   418  	// variable coding: network/task/allocator
   419  	ip111, _, err := net.ParseCIDR(task1.Networks[0].Addresses[0])
   420  	assert.NoError(t, err)
   421  
   422  	ip211, _, err := net.ParseCIDR(task1.Networks[1].Addresses[0])
   423  	assert.NoError(t, err)
   424  
   425  	assert.Equal(t, subnet1.Contains(ip111), true)
   426  	assert.Equal(t, subnet2.Contains(ip211), true)
   427  
   428  	err = na1.AllocateTask(task2)
   429  	assert.NoError(t, err)
   430  	assert.Equal(t, len(task2.Networks[0].Addresses), 1)
   431  	assert.Equal(t, len(task2.Networks[1].Addresses), 1)
   432  
   433  	ip121, _, err := net.ParseCIDR(task2.Networks[0].Addresses[0])
   434  	assert.NoError(t, err)
   435  
   436  	ip221, _, err := net.ParseCIDR(task2.Networks[1].Addresses[0])
   437  	assert.NoError(t, err)
   438  
   439  	assert.Equal(t, subnet1.Contains(ip121), true)
   440  	assert.Equal(t, subnet2.Contains(ip221), true)
   441  
   442  	// Now allocate the same the same tasks in a second allocator
   443  	// but intentionally in reverse order.
   444  	err = na2.Allocate(n1)
   445  	assert.NoError(t, err)
   446  
   447  	err = na2.Allocate(n2)
   448  	assert.NoError(t, err)
   449  
   450  	err = na2.AllocateTask(task2)
   451  	assert.NoError(t, err)
   452  	assert.Equal(t, len(task2.Networks[0].Addresses), 1)
   453  	assert.Equal(t, len(task2.Networks[1].Addresses), 1)
   454  
   455  	ip122, _, err := net.ParseCIDR(task2.Networks[0].Addresses[0])
   456  	assert.NoError(t, err)
   457  
   458  	ip222, _, err := net.ParseCIDR(task2.Networks[1].Addresses[0])
   459  	assert.NoError(t, err)
   460  
   461  	assert.Equal(t, subnet1.Contains(ip122), true)
   462  	assert.Equal(t, subnet2.Contains(ip222), true)
   463  	assert.Equal(t, ip121, ip122)
   464  	assert.Equal(t, ip221, ip222)
   465  
   466  	err = na2.AllocateTask(task1)
   467  	assert.NoError(t, err)
   468  	assert.Equal(t, len(task1.Networks[0].Addresses), 1)
   469  	assert.Equal(t, len(task1.Networks[1].Addresses), 1)
   470  
   471  	ip112, _, err := net.ParseCIDR(task1.Networks[0].Addresses[0])
   472  	assert.NoError(t, err)
   473  
   474  	ip212, _, err := net.ParseCIDR(task1.Networks[1].Addresses[0])
   475  	assert.NoError(t, err)
   476  
   477  	assert.Equal(t, subnet1.Contains(ip112), true)
   478  	assert.Equal(t, subnet2.Contains(ip212), true)
   479  	assert.Equal(t, ip111, ip112)
   480  	assert.Equal(t, ip211, ip212)
   481  
   482  	// Deallocate task
   483  	err = na1.DeallocateTask(task1)
   484  	assert.NoError(t, err)
   485  	assert.Equal(t, len(task1.Networks[0].Addresses), 0)
   486  	assert.Equal(t, len(task1.Networks[1].Addresses), 0)
   487  
   488  	// Try allocation after free
   489  	err = na1.AllocateTask(task1)
   490  	assert.NoError(t, err)
   491  	assert.Equal(t, len(task1.Networks[0].Addresses), 1)
   492  	assert.Equal(t, len(task1.Networks[1].Addresses), 1)
   493  
   494  	ip111, _, err = net.ParseCIDR(task1.Networks[0].Addresses[0])
   495  	assert.NoError(t, err)
   496  
   497  	ip211, _, err = net.ParseCIDR(task1.Networks[1].Addresses[0])
   498  	assert.NoError(t, err)
   499  
   500  	assert.Equal(t, subnet1.Contains(ip111), true)
   501  	assert.Equal(t, subnet2.Contains(ip211), true)
   502  
   503  	err = na1.DeallocateTask(task1)
   504  	assert.NoError(t, err)
   505  	assert.Equal(t, len(task1.Networks[0].Addresses), 0)
   506  	assert.Equal(t, len(task1.Networks[1].Addresses), 0)
   507  
   508  	// Try to free endpoints on an already freed task
   509  	err = na1.DeallocateTask(task1)
   510  	assert.NoError(t, err)
   511  }
   512  
   513  func TestAllocateService(t *testing.T) {
   514  	na := newNetworkAllocator(t)
   515  	n := &api.Network{
   516  		ID: "testID",
   517  		Spec: api.NetworkSpec{
   518  			Annotations: api.Annotations{
   519  				Name: "test",
   520  			},
   521  		},
   522  	}
   523  
   524  	s := &api.Service{
   525  		ID: "testID1",
   526  		Spec: api.ServiceSpec{
   527  			Task: api.TaskSpec{
   528  				Networks: []*api.NetworkAttachmentConfig{
   529  					{
   530  						Target: "testID",
   531  					},
   532  				},
   533  			},
   534  			Endpoint: &api.EndpointSpec{
   535  				Ports: []*api.PortConfig{
   536  					{
   537  						Name:       "http",
   538  						TargetPort: 80,
   539  					},
   540  					{
   541  						Name:       "https",
   542  						TargetPort: 443,
   543  					},
   544  				},
   545  			},
   546  		},
   547  	}
   548  
   549  	err := na.Allocate(n)
   550  	assert.NoError(t, err)
   551  	assert.NotEqual(t, n.IPAM.Configs, nil)
   552  	assert.Equal(t, len(n.IPAM.Configs), 1)
   553  	assert.Equal(t, n.IPAM.Configs[0].Range, "")
   554  	assert.Equal(t, len(n.IPAM.Configs[0].Reserved), 0)
   555  
   556  	_, subnet, err := net.ParseCIDR(n.IPAM.Configs[0].Subnet)
   557  	assert.NoError(t, err)
   558  
   559  	gwip := net.ParseIP(n.IPAM.Configs[0].Gateway)
   560  	assert.NotEqual(t, gwip, nil)
   561  
   562  	err = na.AllocateService(s)
   563  	assert.NoError(t, err)
   564  	assert.Equal(t, 2, len(s.Endpoint.Ports))
   565  	assert.True(t, s.Endpoint.Ports[0].PublishedPort >= dynamicPortStart &&
   566  		s.Endpoint.Ports[0].PublishedPort <= dynamicPortEnd)
   567  	assert.True(t, s.Endpoint.Ports[1].PublishedPort >= dynamicPortStart &&
   568  		s.Endpoint.Ports[1].PublishedPort <= dynamicPortEnd)
   569  
   570  	assert.Equal(t, 1, len(s.Endpoint.VirtualIPs))
   571  
   572  	assert.Equal(t, s.Endpoint.Spec, s.Spec.Endpoint)
   573  
   574  	ip, _, err := net.ParseCIDR(s.Endpoint.VirtualIPs[0].Addr)
   575  	assert.NoError(t, err)
   576  
   577  	assert.Equal(t, true, subnet.Contains(ip))
   578  }
   579  
   580  func TestAllocateServiceUserDefinedPorts(t *testing.T) {
   581  	na := newNetworkAllocator(t)
   582  	s := &api.Service{
   583  		ID: "testID1",
   584  		Spec: api.ServiceSpec{
   585  			Endpoint: &api.EndpointSpec{
   586  				Ports: []*api.PortConfig{
   587  					{
   588  						Name:          "some_tcp",
   589  						TargetPort:    1234,
   590  						PublishedPort: 1234,
   591  					},
   592  					{
   593  						Name:          "some_udp",
   594  						TargetPort:    1234,
   595  						PublishedPort: 1234,
   596  						Protocol:      api.ProtocolUDP,
   597  					},
   598  				},
   599  			},
   600  		},
   601  	}
   602  
   603  	err := na.AllocateService(s)
   604  	assert.NoError(t, err)
   605  	assert.Equal(t, 2, len(s.Endpoint.Ports))
   606  	assert.Equal(t, uint32(1234), s.Endpoint.Ports[0].PublishedPort)
   607  	assert.Equal(t, uint32(1234), s.Endpoint.Ports[1].PublishedPort)
   608  }
   609  
   610  func TestAllocateServiceConflictingUserDefinedPorts(t *testing.T) {
   611  	na := newNetworkAllocator(t)
   612  	s := &api.Service{
   613  		ID: "testID1",
   614  		Spec: api.ServiceSpec{
   615  			Endpoint: &api.EndpointSpec{
   616  				Ports: []*api.PortConfig{
   617  					{
   618  						Name:          "some_tcp",
   619  						TargetPort:    1234,
   620  						PublishedPort: 1234,
   621  					},
   622  					{
   623  						Name:          "some_other_tcp",
   624  						TargetPort:    1234,
   625  						PublishedPort: 1234,
   626  					},
   627  				},
   628  			},
   629  		},
   630  	}
   631  
   632  	err := na.AllocateService(s)
   633  	assert.Error(t, err)
   634  }
   635  
   636  func TestDeallocateServiceAllocate(t *testing.T) {
   637  	na := newNetworkAllocator(t)
   638  	s := &api.Service{
   639  		ID: "testID1",
   640  		Spec: api.ServiceSpec{
   641  			Endpoint: &api.EndpointSpec{
   642  				Ports: []*api.PortConfig{
   643  					{
   644  						Name:          "some_tcp",
   645  						TargetPort:    1234,
   646  						PublishedPort: 1234,
   647  					},
   648  				},
   649  			},
   650  		},
   651  	}
   652  
   653  	err := na.AllocateService(s)
   654  	assert.NoError(t, err)
   655  	assert.Equal(t, 1, len(s.Endpoint.Ports))
   656  	assert.Equal(t, uint32(1234), s.Endpoint.Ports[0].PublishedPort)
   657  
   658  	err = na.DeallocateService(s)
   659  	assert.NoError(t, err)
   660  	assert.Equal(t, 0, len(s.Endpoint.Ports))
   661  	// Allocate again.
   662  	err = na.AllocateService(s)
   663  	assert.NoError(t, err)
   664  	assert.Equal(t, 1, len(s.Endpoint.Ports))
   665  	assert.Equal(t, uint32(1234), s.Endpoint.Ports[0].PublishedPort)
   666  }
   667  
   668  func TestDeallocateServiceAllocateIngressMode(t *testing.T) {
   669  	na := newNetworkAllocator(t)
   670  
   671  	n := &api.Network{
   672  		ID: "testNetID1",
   673  		Spec: api.NetworkSpec{
   674  			Annotations: api.Annotations{
   675  				Name: "test",
   676  			},
   677  			Ingress: true,
   678  		},
   679  	}
   680  
   681  	err := na.Allocate(n)
   682  	assert.NoError(t, err)
   683  
   684  	s := &api.Service{
   685  		ID: "testID1",
   686  		Spec: api.ServiceSpec{
   687  			Endpoint: &api.EndpointSpec{
   688  				Ports: []*api.PortConfig{
   689  					{
   690  						Name:          "some_tcp",
   691  						TargetPort:    1234,
   692  						PublishedPort: 1234,
   693  						PublishMode:   api.PublishModeIngress,
   694  					},
   695  				},
   696  			},
   697  		},
   698  		Endpoint: &api.Endpoint{},
   699  	}
   700  
   701  	s.Endpoint.VirtualIPs = append(s.Endpoint.VirtualIPs,
   702  		&api.Endpoint_VirtualIP{NetworkID: n.ID})
   703  
   704  	err = na.AllocateService(s)
   705  	assert.NoError(t, err)
   706  	assert.Len(t, s.Endpoint.Ports, 1)
   707  	assert.Equal(t, uint32(1234), s.Endpoint.Ports[0].PublishedPort)
   708  	assert.Len(t, s.Endpoint.VirtualIPs, 1)
   709  
   710  	err = na.DeallocateService(s)
   711  	assert.NoError(t, err)
   712  	assert.Len(t, s.Endpoint.Ports, 0)
   713  	assert.Len(t, s.Endpoint.VirtualIPs, 0)
   714  	// Allocate again.
   715  	s.Endpoint.VirtualIPs = append(s.Endpoint.VirtualIPs,
   716  		&api.Endpoint_VirtualIP{NetworkID: n.ID})
   717  
   718  	err = na.AllocateService(s)
   719  	assert.NoError(t, err)
   720  	assert.Len(t, s.Endpoint.Ports, 1)
   721  	assert.Equal(t, uint32(1234), s.Endpoint.Ports[0].PublishedPort)
   722  	assert.Len(t, s.Endpoint.VirtualIPs, 1)
   723  }
   724  
   725  func TestServiceAddRemovePortsIngressMode(t *testing.T) {
   726  	na := newNetworkAllocator(t)
   727  
   728  	n := &api.Network{
   729  		ID: "testNetID1",
   730  		Spec: api.NetworkSpec{
   731  			Annotations: api.Annotations{
   732  				Name: "test",
   733  			},
   734  			Ingress: true,
   735  		},
   736  	}
   737  
   738  	err := na.Allocate(n)
   739  	assert.NoError(t, err)
   740  
   741  	s := &api.Service{
   742  		ID: "testID1",
   743  		Spec: api.ServiceSpec{
   744  			Endpoint: &api.EndpointSpec{
   745  				Ports: []*api.PortConfig{
   746  					{
   747  						Name:          "some_tcp",
   748  						TargetPort:    1234,
   749  						PublishedPort: 1234,
   750  						PublishMode:   api.PublishModeIngress,
   751  					},
   752  				},
   753  			},
   754  		},
   755  		Endpoint: &api.Endpoint{},
   756  	}
   757  
   758  	s.Endpoint.VirtualIPs = append(s.Endpoint.VirtualIPs,
   759  		&api.Endpoint_VirtualIP{NetworkID: n.ID})
   760  
   761  	err = na.AllocateService(s)
   762  	assert.NoError(t, err)
   763  	assert.Len(t, s.Endpoint.Ports, 1)
   764  	assert.Equal(t, uint32(1234), s.Endpoint.Ports[0].PublishedPort)
   765  	assert.Len(t, s.Endpoint.VirtualIPs, 1)
   766  	allocatedVIP := s.Endpoint.VirtualIPs[0].Addr
   767  
   768  	//Unpublish port
   769  	s.Spec.Endpoint.Ports = s.Spec.Endpoint.Ports[:0]
   770  	err = na.AllocateService(s)
   771  	assert.NoError(t, err)
   772  	assert.Len(t, s.Endpoint.Ports, 0)
   773  	assert.Len(t, s.Endpoint.VirtualIPs, 0)
   774  
   775  	// Publish port again and ensure VIP is not the same that was deallocated.
   776  	// Since IP allocation is serial we should  receive the next available IP.
   777  	s.Spec.Endpoint.Ports = append(s.Spec.Endpoint.Ports, &api.PortConfig{Name: "some_tcp",
   778  		TargetPort:    1234,
   779  		PublishedPort: 1234,
   780  		PublishMode:   api.PublishModeIngress,
   781  	})
   782  	s.Endpoint.VirtualIPs = append(s.Endpoint.VirtualIPs,
   783  		&api.Endpoint_VirtualIP{NetworkID: n.ID})
   784  	err = na.AllocateService(s)
   785  	assert.NoError(t, err)
   786  	assert.Len(t, s.Endpoint.Ports, 1)
   787  	assert.Equal(t, uint32(1234), s.Endpoint.Ports[0].PublishedPort)
   788  	assert.Len(t, s.Endpoint.VirtualIPs, 1)
   789  	assert.NotEqual(t, allocatedVIP, s.Endpoint.VirtualIPs[0].Addr)
   790  }
   791  
   792  func TestServiceUpdate(t *testing.T) {
   793  	na1 := newNetworkAllocator(t)
   794  	na2 := newNetworkAllocator(t)
   795  	s := &api.Service{
   796  		ID: "testID1",
   797  		Spec: api.ServiceSpec{
   798  			Endpoint: &api.EndpointSpec{
   799  				Ports: []*api.PortConfig{
   800  					{
   801  						Name:          "some_tcp",
   802  						TargetPort:    1234,
   803  						PublishedPort: 1234,
   804  					},
   805  					{
   806  						Name:          "some_other_tcp",
   807  						TargetPort:    1235,
   808  						PublishedPort: 0,
   809  					},
   810  				},
   811  			},
   812  		},
   813  	}
   814  
   815  	err := na1.AllocateService(s)
   816  	assert.NoError(t, err)
   817  	assert.True(t, na1.IsServiceAllocated(s))
   818  	assert.Equal(t, 2, len(s.Endpoint.Ports))
   819  	assert.Equal(t, uint32(1234), s.Endpoint.Ports[0].PublishedPort)
   820  	assert.NotEqual(t, 0, s.Endpoint.Ports[1].PublishedPort)
   821  
   822  	// Cache the secode node port
   823  	allocatedPort := s.Endpoint.Ports[1].PublishedPort
   824  
   825  	// Now allocate the same service in another allocator instance
   826  	err = na2.AllocateService(s)
   827  	assert.NoError(t, err)
   828  	assert.True(t, na2.IsServiceAllocated(s))
   829  	assert.Equal(t, 2, len(s.Endpoint.Ports))
   830  	assert.Equal(t, uint32(1234), s.Endpoint.Ports[0].PublishedPort)
   831  	// Make sure we got the same port
   832  	assert.Equal(t, allocatedPort, s.Endpoint.Ports[1].PublishedPort)
   833  
   834  	s.Spec.Endpoint.Ports[1].PublishedPort = 1235
   835  	assert.False(t, na1.IsServiceAllocated(s))
   836  
   837  	err = na1.AllocateService(s)
   838  	assert.NoError(t, err)
   839  	assert.True(t, na1.IsServiceAllocated(s))
   840  	assert.Equal(t, 2, len(s.Endpoint.Ports))
   841  	assert.Equal(t, uint32(1234), s.Endpoint.Ports[0].PublishedPort)
   842  	assert.Equal(t, uint32(1235), s.Endpoint.Ports[1].PublishedPort)
   843  }
   844  
   845  func TestServiceNetworkUpdate(t *testing.T) {
   846  	na := newNetworkAllocator(t)
   847  
   848  	n1 := &api.Network{
   849  		ID: "testID1",
   850  		Spec: api.NetworkSpec{
   851  			Annotations: api.Annotations{
   852  				Name: "test",
   853  			},
   854  		},
   855  	}
   856  
   857  	n2 := &api.Network{
   858  		ID: "testID2",
   859  		Spec: api.NetworkSpec{
   860  			Annotations: api.Annotations{
   861  				Name: "test2",
   862  			},
   863  		},
   864  	}
   865  
   866  	//Allocate both networks
   867  	err := na.Allocate(n1)
   868  	assert.NoError(t, err)
   869  
   870  	err = na.Allocate(n2)
   871  	assert.NoError(t, err)
   872  
   873  	//Attach a network to a service spec nd allocate a service
   874  	s := &api.Service{
   875  		ID: "testID1",
   876  		Spec: api.ServiceSpec{
   877  			Task: api.TaskSpec{
   878  				Networks: []*api.NetworkAttachmentConfig{
   879  					{
   880  						Target: "testID1",
   881  					},
   882  				},
   883  			},
   884  			Endpoint: &api.EndpointSpec{
   885  				Mode: api.ResolutionModeVirtualIP,
   886  			},
   887  		},
   888  	}
   889  
   890  	err = na.AllocateService(s)
   891  	assert.NoError(t, err)
   892  	assert.True(t, na.IsServiceAllocated(s))
   893  	assert.Len(t, s.Endpoint.VirtualIPs, 1)
   894  
   895  	// Now update the same service with another network
   896  	s.Spec.Task.Networks = append(s.Spec.Task.Networks, &api.NetworkAttachmentConfig{Target: "testID2"})
   897  
   898  	assert.False(t, na.IsServiceAllocated(s))
   899  	err = na.AllocateService(s)
   900  	assert.NoError(t, err)
   901  
   902  	assert.True(t, na.IsServiceAllocated(s))
   903  	assert.Len(t, s.Endpoint.VirtualIPs, 2)
   904  
   905  	s.Spec.Task.Networks = s.Spec.Task.Networks[:1]
   906  
   907  	//Check if service needs update and allocate with updated service spec
   908  	assert.False(t, na.IsServiceAllocated(s))
   909  
   910  	err = na.AllocateService(s)
   911  	assert.NoError(t, err)
   912  	assert.True(t, na.IsServiceAllocated(s))
   913  	assert.Len(t, s.Endpoint.VirtualIPs, 1)
   914  
   915  	s.Spec.Task.Networks = s.Spec.Task.Networks[:0]
   916  	//Check if service needs update with all the networks removed and allocate with updated service spec
   917  	assert.False(t, na.IsServiceAllocated(s))
   918  
   919  	err = na.AllocateService(s)
   920  	assert.NoError(t, err)
   921  	assert.True(t, na.IsServiceAllocated(s))
   922  	assert.Len(t, s.Endpoint.VirtualIPs, 0)
   923  
   924  	//Attach a network and allocate service
   925  	s.Spec.Task.Networks = append(s.Spec.Task.Networks, &api.NetworkAttachmentConfig{Target: "testID2"})
   926  	assert.False(t, na.IsServiceAllocated(s))
   927  
   928  	err = na.AllocateService(s)
   929  	assert.NoError(t, err)
   930  
   931  	assert.True(t, na.IsServiceAllocated(s))
   932  	assert.Len(t, s.Endpoint.VirtualIPs, 1)
   933  
   934  }
   935  
   936  type mockIpam struct {
   937  	actualIpamOptions map[string]string
   938  }
   939  
   940  func (a *mockIpam) GetDefaultAddressSpaces() (string, string, error) {
   941  	return "defaultAS", "defaultAS", nil
   942  }
   943  
   944  func (a *mockIpam) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) {
   945  	a.actualIpamOptions = options
   946  
   947  	poolCidr, _ := types.ParseCIDR(pool)
   948  	return fmt.Sprintf("%s/%s", "defaultAS", pool), poolCidr, nil, nil
   949  }
   950  
   951  func (a *mockIpam) ReleasePool(poolID string) error {
   952  	return nil
   953  }
   954  
   955  func (a *mockIpam) RequestAddress(poolID string, ip net.IP, opts map[string]string) (*net.IPNet, map[string]string, error) {
   956  	return nil, nil, nil
   957  }
   958  
   959  func (a *mockIpam) ReleaseAddress(poolID string, ip net.IP) error {
   960  	return nil
   961  }
   962  
   963  func (a *mockIpam) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
   964  	return nil
   965  }
   966  
   967  func (a *mockIpam) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
   968  	return nil
   969  }
   970  
   971  func (a *mockIpam) IsBuiltIn() bool {
   972  	return true
   973  }
   974  
   975  func TestCorrectlyPassIPAMOptions(t *testing.T) {
   976  	var err error
   977  	expectedIpamOptions := map[string]string{"network-name": "freddie"}
   978  
   979  	na := newNetworkAllocator(t)
   980  	ipamDriver := &mockIpam{}
   981  
   982  	err = na.(*cnmNetworkAllocator).drvRegistry.RegisterIpamDriver("mockipam", ipamDriver)
   983  	assert.NoError(t, err)
   984  
   985  	n := &api.Network{
   986  		ID: "testID",
   987  		Spec: api.NetworkSpec{
   988  			Annotations: api.Annotations{
   989  				Name: "test",
   990  			},
   991  			DriverConfig: &api.Driver{},
   992  			IPAM: &api.IPAMOptions{
   993  				Driver: &api.Driver{
   994  					Name:    "mockipam",
   995  					Options: expectedIpamOptions,
   996  				},
   997  				Configs: []*api.IPAMConfig{
   998  					{
   999  						Subnet:  "192.168.1.0/24",
  1000  						Gateway: "192.168.1.1",
  1001  					},
  1002  				},
  1003  			},
  1004  		},
  1005  	}
  1006  	err = na.Allocate(n)
  1007  
  1008  	assert.Equal(t, expectedIpamOptions, ipamDriver.actualIpamOptions)
  1009  	assert.NoError(t, err)
  1010  }