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 }