github.com/jlmeeker/kismatic@v1.10.1-0.20180612190640-57f9005a1f1a/pkg/install/validate_test.go (about) 1 package install 2 3 import ( 4 "fmt" 5 "testing" 6 ) 7 8 func validPlan() Plan { 9 return Plan{ 10 Cluster: Cluster{ 11 Name: "test", 12 Version: "v1.10.3", 13 Networking: NetworkConfig{ 14 Type: "overlay", 15 PodCIDRBlock: "172.16.0.0/16", 16 ServiceCIDRBlock: "172.20.0.0/16", 17 }, 18 Certificates: CertsConfig{ 19 Expiry: "17250h", 20 }, 21 SSH: SSHConfig{ 22 User: "root", 23 Key: "/bin/sh", 24 Port: 22, 25 }, 26 }, 27 AdditionalFiles: []AdditionalFile{ 28 { 29 Source: "/bin/sh", 30 Destination: "/bin/sh", 31 Hosts: []string{"master01"}, 32 }, 33 }, 34 AddOns: AddOns{ 35 CNI: &CNI{ 36 Provider: "calico", 37 Options: CNIOptions{ 38 Calico: CalicoOptions{ 39 Mode: "overlay", 40 LogLevel: "info", 41 }, 42 }, 43 }, 44 DNS: DNS{ 45 Provider: "kubedns", 46 }, 47 Dashboard: Dashboard{ 48 Options: DashboardOptions{ 49 ServiceType: "ClusterIP", 50 }, 51 }, 52 HeapsterMonitoring: &HeapsterMonitoring{ 53 Options: HeapsterOptions{ 54 Heapster: Heapster{ 55 Replicas: 2, 56 ServiceType: "ClusterIP", 57 }, 58 }, 59 }, 60 }, 61 Etcd: NodeGroup{ 62 ExpectedCount: 1, 63 Nodes: []Node{ 64 { 65 Host: "etcd01", 66 IP: "192.168.205.10", 67 }, 68 }, 69 }, 70 Master: MasterNodeGroup{ 71 ExpectedCount: 1, 72 Nodes: []Node{ 73 { 74 Host: "master01", 75 IP: "192.168.205.11", 76 }, 77 }, 78 LoadBalancedFQDN: "test", 79 LoadBalancedShortName: "test", 80 }, 81 Worker: NodeGroup{ 82 ExpectedCount: 1, 83 Nodes: []Node{ 84 { 85 Host: "worker01", 86 IP: "192.168.205.12", 87 }, 88 }, 89 }, 90 Ingress: OptionalNodeGroup{ 91 ExpectedCount: 1, 92 Nodes: []Node{ 93 { 94 Host: "etcd01", 95 IP: "192.168.205.10", 96 }, 97 }, 98 }, 99 NFS: &NFS{ 100 Volumes: []NFSVolume{ 101 { 102 Host: "10.10.2.20", 103 Path: "/", 104 }, 105 }, 106 }, 107 } 108 } 109 110 func assertInvalidPlan(t *testing.T, p Plan) { 111 valid, _ := ValidatePlan(&p) 112 if valid { 113 t.Errorf("expected invalid, but got valid") 114 } 115 } 116 117 func TestValidateBlankPlan(t *testing.T) { 118 p := Plan{} 119 assertInvalidPlan(t, p) 120 } 121 122 func TestValidateValidPlan(t *testing.T) { 123 p := validPlan() 124 valid, errs := ValidatePlan(&p) 125 if !valid { 126 t.Errorf("expected valid, but got invalid") 127 } 128 fmt.Println(errs) 129 } 130 131 func TestClusterVersion(t *testing.T) { 132 tests := []struct { 133 c Cluster 134 valid bool 135 }{ 136 {c: Cluster{ 137 Name: "test", 138 Version: "v1.10.3", 139 Networking: NetworkConfig{ 140 Type: "overlay", 141 PodCIDRBlock: "172.16.0.0/16", 142 ServiceCIDRBlock: "172.20.0.0/16", 143 }, 144 Certificates: CertsConfig{ 145 Expiry: "17250h", 146 }, 147 SSH: SSHConfig{ 148 User: "root", 149 Key: "/bin/sh", 150 Port: 22, 151 }, 152 }, 153 valid: true, 154 }, 155 {c: Cluster{ 156 Name: "test", 157 Version: "v1.10.3", 158 Networking: NetworkConfig{ 159 Type: "overlay", 160 PodCIDRBlock: "172.16.0.0/16", 161 ServiceCIDRBlock: "172.20.0.0/16", 162 }, 163 Certificates: CertsConfig{ 164 Expiry: "17250h", 165 }, 166 SSH: SSHConfig{ 167 User: "root", 168 Key: "/bin/sh", 169 Port: 22, 170 }, 171 }, 172 valid: true, 173 }, 174 {c: Cluster{ 175 Name: "test", 176 Version: "foo", 177 Networking: NetworkConfig{ 178 Type: "overlay", 179 PodCIDRBlock: "172.16.0.0/16", 180 ServiceCIDRBlock: "172.20.0.0/16", 181 }, 182 Certificates: CertsConfig{ 183 Expiry: "17250h", 184 }, 185 SSH: SSHConfig{ 186 User: "root", 187 Key: "/bin/sh", 188 Port: 22, 189 }, 190 }, 191 valid: false, 192 }, 193 {c: Cluster{ 194 Name: "test", 195 Version: "v1.10.300", 196 Networking: NetworkConfig{ 197 Type: "overlay", 198 PodCIDRBlock: "172.16.0.0/16", 199 ServiceCIDRBlock: "172.20.0.0/16", 200 }, 201 Certificates: CertsConfig{ 202 Expiry: "17250h", 203 }, 204 SSH: SSHConfig{ 205 User: "root", 206 Key: "/bin/sh", 207 Port: 22, 208 }, 209 }, 210 valid: false, 211 }, 212 {c: Cluster{ 213 Name: "test", 214 Version: "v1.8.0", 215 Networking: NetworkConfig{ 216 Type: "overlay", 217 PodCIDRBlock: "172.16.0.0/16", 218 ServiceCIDRBlock: "172.20.0.0/16", 219 }, 220 Certificates: CertsConfig{ 221 Expiry: "17250h", 222 }, 223 SSH: SSHConfig{ 224 User: "root", 225 Key: "/bin/sh", 226 Port: 22, 227 }, 228 }, 229 valid: false, 230 }, 231 {c: Cluster{ 232 Name: "test", 233 Version: "v1.20.0", 234 Networking: NetworkConfig{ 235 Type: "overlay", 236 PodCIDRBlock: "172.16.0.0/16", 237 ServiceCIDRBlock: "172.20.0.0/16", 238 }, 239 Certificates: CertsConfig{ 240 Expiry: "17250h", 241 }, 242 SSH: SSHConfig{ 243 User: "root", 244 Key: "/bin/sh", 245 Port: 22, 246 }, 247 }, 248 valid: false, 249 }, 250 {c: Cluster{ 251 Name: "test", 252 Version: "v1.8.0", 253 DisconnectedInstallation: true, 254 Networking: NetworkConfig{ 255 Type: "overlay", 256 PodCIDRBlock: "172.16.0.0/16", 257 ServiceCIDRBlock: "172.20.0.0/16", 258 }, 259 Certificates: CertsConfig{ 260 Expiry: "17250h", 261 }, 262 SSH: SSHConfig{ 263 User: "root", 264 Key: "/bin/sh", 265 Port: 22, 266 }, 267 }, 268 valid: false, 269 }, 270 {c: Cluster{ 271 Name: "test", 272 Version: "v1.20.0", 273 DisconnectedInstallation: true, 274 Networking: NetworkConfig{ 275 Type: "overlay", 276 PodCIDRBlock: "172.16.0.0/16", 277 ServiceCIDRBlock: "172.20.0.0/16", 278 }, 279 Certificates: CertsConfig{ 280 Expiry: "17250h", 281 }, 282 SSH: SSHConfig{ 283 User: "root", 284 Key: "/bin/sh", 285 Port: 22, 286 }, 287 }, 288 valid: false, 289 }, 290 } 291 for n, test := range tests { 292 if valid, _ := test.c.validate(); valid != test.valid { 293 t.Errorf("%d: expected %v with %+v, but got %v - %q", n, test.valid, test.c, !test.valid) 294 } 295 } 296 } 297 298 func TestValidatePlanEmptyPodCIDR(t *testing.T) { 299 p := validPlan() 300 p.Cluster.Networking.PodCIDRBlock = "" 301 assertInvalidPlan(t, p) 302 } 303 304 func TestValidatePlanInvalidPodCIDR(t *testing.T) { 305 p := validPlan() 306 p.Cluster.Networking.PodCIDRBlock = "foo" 307 assertInvalidPlan(t, p) 308 } 309 310 func TestValidatePlanEmptyServicesCIDR(t *testing.T) { 311 p := validPlan() 312 p.Cluster.Networking.ServiceCIDRBlock = "" 313 assertInvalidPlan(t, p) 314 } 315 316 func TestValidatePlanInvalidServicesCIDR(t *testing.T) { 317 p := validPlan() 318 p.Cluster.Networking.ServiceCIDRBlock = "foo" 319 assertInvalidPlan(t, p) 320 } 321 322 func TestValidatePlanEmptyCertificatesExpiry(t *testing.T) { 323 p := validPlan() 324 p.Cluster.Certificates.Expiry = "" 325 assertInvalidPlan(t, p) 326 } 327 328 func TestValidatePlanInvalidCertExpiry(t *testing.T) { 329 p := validPlan() 330 p.Cluster.Certificates.Expiry = "foo" 331 assertInvalidPlan(t, p) 332 } 333 334 func TestValidatePlanEmptyCACertExpiryIsValid(t *testing.T) { 335 p := validPlan() 336 p.Cluster.Certificates.CAExpiry = "" 337 valid, _ := p.validate() 338 if !valid { 339 t.Errorf("plan was found invalid") 340 } 341 } 342 343 func TestValidatePlanInvalidCACertificatesExpiry(t *testing.T) { 344 p := validPlan() 345 p.Cluster.Certificates.CAExpiry = "foo" 346 assertInvalidPlan(t, p) 347 } 348 349 func TestValidatePlanEmptySSHUser(t *testing.T) { 350 p := validPlan() 351 p.Cluster.SSH.User = "" 352 assertInvalidPlan(t, p) 353 } 354 355 func TestValidatePlanEmptySSHKey(t *testing.T) { 356 p := validPlan() 357 p.Cluster.SSH.Key = "" 358 assertInvalidPlan(t, p) 359 } 360 361 func TestValidatePlanNonExistentSSHKey(t *testing.T) { 362 p := validPlan() 363 p.Cluster.SSH.Key = "/foo" 364 assertInvalidPlan(t, p) 365 } 366 367 func TestValidatePlanNegativeSSHPort(t *testing.T) { 368 p := validPlan() 369 p.Cluster.SSH.Port = -1 370 assertInvalidPlan(t, p) 371 } 372 373 func TestValidatePlanEmptyLoadBalancedFQDN(t *testing.T) { 374 p := validPlan() 375 p.Master.LoadBalancedFQDN = "" 376 assertInvalidPlan(t, p) 377 } 378 379 func TestValidatePlanEmptyLoadBalancedShortName(t *testing.T) { 380 p := validPlan() 381 p.Master.LoadBalancedShortName = "" 382 assertInvalidPlan(t, p) 383 } 384 385 func TestValidatePlanNoEtcdNodes(t *testing.T) { 386 p := validPlan() 387 p.Etcd.ExpectedCount = 0 388 p.Etcd.Nodes = []Node{} 389 assertInvalidPlan(t, p) 390 } 391 392 func TestValidatePlanNoMasterNodes(t *testing.T) { 393 p := validPlan() 394 p.Master.ExpectedCount = 0 395 p.Master.Nodes = []Node{} 396 assertInvalidPlan(t, p) 397 } 398 399 func TestValidatePlanNoWorkerNodes(t *testing.T) { 400 p := validPlan() 401 p.Worker.ExpectedCount = 0 402 p.Worker.Nodes = []Node{} 403 assertInvalidPlan(t, p) 404 } 405 406 func TestValidatePlanEtcdNodesMismatch(t *testing.T) { 407 p := validPlan() 408 p.Etcd.ExpectedCount = 100 409 assertInvalidPlan(t, p) 410 } 411 412 func TestValidatePlanMasterNodesMismatch(t *testing.T) { 413 p := validPlan() 414 p.Master.ExpectedCount = 100 415 assertInvalidPlan(t, p) 416 } 417 418 func TestValidatePlanWorkerNodesMismatch(t *testing.T) { 419 p := validPlan() 420 p.Worker.ExpectedCount = 100 421 assertInvalidPlan(t, p) 422 } 423 424 func TestValidatePlanUnexpectedEtcdNodes(t *testing.T) { 425 p := validPlan() 426 p.Etcd.ExpectedCount = 1 427 p.Etcd.Nodes = []Node{ 428 { 429 Host: "etcd01", 430 IP: "192.168.205.10", 431 }, 432 { 433 Host: "etcd02", 434 IP: "192.168.205.11", 435 }, 436 } 437 assertInvalidPlan(t, p) 438 } 439 440 func TestValidatePlanUnexpectedMasterNodes(t *testing.T) { 441 p := validPlan() 442 p.Master.ExpectedCount = 1 443 p.Master.Nodes = []Node{ 444 { 445 Host: "master01", 446 IP: "192.168.205.10", 447 }, 448 { 449 Host: "master02", 450 IP: "192.168.205.11", 451 }, 452 } 453 assertInvalidPlan(t, p) 454 } 455 456 func TestValidatePlanUnexpectedWorkerNodes(t *testing.T) { 457 p := validPlan() 458 p.Worker.ExpectedCount = 1 459 p.Worker.Nodes = []Node{ 460 { 461 Host: "worker01", 462 IP: "192.168.205.10", 463 }, 464 { 465 Host: "worker02", 466 IP: "192.168.205.11", 467 }, 468 } 469 assertInvalidPlan(t, p) 470 } 471 472 func TestValidatePlanNoIngress(t *testing.T) { 473 p := validPlan() 474 p.Ingress.ExpectedCount = 0 475 p.Ingress.Nodes = []Node{} 476 valid, _ := ValidatePlan(&p) 477 if !valid { 478 t.Errorf("expected valid, but got invalid") 479 } 480 } 481 482 func TestValidatePlanIngressExpected(t *testing.T) { 483 p := validPlan() 484 p.Ingress.ExpectedCount = 1 485 p.Ingress.Nodes = []Node{} 486 assertInvalidPlan(t, p) 487 } 488 489 func TestValidatePlanIngressProvidedNotExpected(t *testing.T) { 490 p := validPlan() 491 p.Ingress.ExpectedCount = 0 492 p.Ingress.Nodes = []Node{ 493 { 494 Host: "ingress", 495 IP: "192.168.205.10", 496 }, 497 } 498 assertInvalidPlan(t, p) 499 } 500 501 func TestValidateStorageVolume(t *testing.T) { 502 tests := []struct { 503 sv StorageVolume 504 valid bool 505 }{ 506 { 507 sv: StorageVolume{ 508 Name: "foo", 509 SizeGB: 100, 510 DistributionCount: 2, 511 ReplicateCount: 2, 512 ReclaimPolicy: "Retain", 513 AccessModes: []string{"ReadWriteMany"}, 514 }, 515 valid: true, 516 }, 517 { 518 sv: StorageVolume{ 519 Name: "foo", 520 SizeGB: 100, 521 DistributionCount: 1, 522 ReplicateCount: 1, 523 ReclaimPolicy: "Retain", 524 AccessModes: []string{"ReadWriteMany"}, 525 }, 526 valid: true, 527 }, 528 { 529 sv: StorageVolume{ 530 Name: "foo", 531 SizeGB: 100, 532 DistributionCount: 0, 533 ReplicateCount: 1, 534 ReclaimPolicy: "Retain", 535 AccessModes: []string{"ReadWriteMany"}, 536 }, 537 valid: false, 538 }, 539 { 540 sv: StorageVolume{ 541 Name: "foo", 542 SizeGB: 100, 543 DistributionCount: 1, 544 ReplicateCount: 0, 545 ReclaimPolicy: "Retain", 546 AccessModes: []string{"ReadWriteMany"}, 547 }, 548 valid: false, 549 }, 550 { 551 sv: StorageVolume{ 552 Name: "bad name with spaces", 553 SizeGB: 100, 554 DistributionCount: 2, 555 ReplicateCount: 2, 556 ReclaimPolicy: "Retain", 557 AccessModes: []string{"ReadWriteMany"}, 558 }, 559 valid: false, 560 }, 561 { 562 sv: StorageVolume{ 563 Name: "bad:name2", 564 SizeGB: 100, 565 DistributionCount: 2, 566 ReplicateCount: 2, 567 ReclaimPolicy: "Retain", 568 AccessModes: []string{"ReadWriteMany"}, 569 }, 570 valid: false, 571 }, 572 { 573 sv: StorageVolume{ 574 Name: "goodName", 575 SizeGB: 0, 576 DistributionCount: 2, 577 ReplicateCount: 2, 578 ReclaimPolicy: "Retain", 579 AccessModes: []string{"ReadWriteMany"}, 580 }, 581 valid: false, 582 }, 583 { 584 sv: StorageVolume{ 585 Name: "goodName", 586 SizeGB: -1, 587 DistributionCount: 2, 588 ReplicateCount: 2, 589 ReclaimPolicy: "Retain", 590 AccessModes: []string{"ReadWriteMany"}, 591 }, 592 valid: false, 593 }, 594 { 595 sv: StorageVolume{ 596 Name: "goodName", 597 SizeGB: 100, 598 DistributionCount: -1, 599 ReplicateCount: 2, 600 ReclaimPolicy: "Retain", 601 AccessModes: []string{"ReadWriteMany"}, 602 }, 603 valid: false, 604 }, 605 { 606 sv: StorageVolume{ 607 Name: "goodName", 608 SizeGB: 100, 609 DistributionCount: 2, 610 ReplicateCount: -1, 611 ReclaimPolicy: "Retain", 612 AccessModes: []string{"ReadWriteMany"}, 613 }, 614 valid: false, 615 }, 616 { 617 sv: StorageVolume{}, 618 valid: false, 619 }, 620 { 621 sv: StorageVolume{ 622 Name: "goodName", 623 SizeGB: 100, 624 DistributionCount: 1, 625 ReplicateCount: 1, 626 ReclaimPolicy: "", 627 AccessModes: []string{"ReadWriteMany"}, 628 }, 629 valid: false, 630 }, 631 { 632 sv: StorageVolume{ 633 Name: "goodName", 634 SizeGB: 100, 635 DistributionCount: 1, 636 ReplicateCount: 1, 637 ReclaimPolicy: "foo", 638 AccessModes: []string{"ReadWriteMany"}, 639 }, 640 valid: false, 641 }, 642 { 643 sv: StorageVolume{ 644 Name: "goodName", 645 SizeGB: 100, 646 DistributionCount: 1, 647 ReplicateCount: 1, 648 ReclaimPolicy: "Retain", 649 AccessModes: []string{"ReadWriteMany"}, 650 }, 651 valid: true, 652 }, 653 { 654 sv: StorageVolume{ 655 Name: "goodName", 656 SizeGB: 100, 657 DistributionCount: 1, 658 ReplicateCount: 1, 659 ReclaimPolicy: "Recycle", 660 AccessModes: []string{"ReadWriteMany"}, 661 }, 662 valid: true, 663 }, 664 { 665 sv: StorageVolume{ 666 Name: "goodName", 667 SizeGB: 100, 668 DistributionCount: 1, 669 ReplicateCount: 1, 670 ReclaimPolicy: "Delete", 671 AccessModes: []string{"ReadWriteMany"}, 672 }, 673 valid: true, 674 }, 675 { 676 sv: StorageVolume{ 677 Name: "goodName", 678 SizeGB: 100, 679 DistributionCount: 1, 680 ReplicateCount: 1, 681 ReclaimPolicy: "Delete", 682 AccessModes: []string{"ReadWriteOnce"}, 683 }, 684 valid: true, 685 }, 686 { 687 sv: StorageVolume{ 688 Name: "goodName", 689 SizeGB: 100, 690 DistributionCount: 1, 691 ReplicateCount: 1, 692 ReclaimPolicy: "Delete", 693 AccessModes: []string{"ReadOnlyMany"}, 694 }, 695 valid: true, 696 }, 697 { 698 sv: StorageVolume{ 699 Name: "goodName", 700 SizeGB: 100, 701 DistributionCount: 1, 702 ReplicateCount: 1, 703 ReclaimPolicy: "Delete", 704 AccessModes: []string{"ReadWriteMany", "ReadWriteOnce", "ReadOnlyMany"}, 705 }, 706 valid: true, 707 }, 708 { 709 sv: StorageVolume{ 710 Name: "goodName", 711 SizeGB: 100, 712 DistributionCount: 1, 713 ReplicateCount: 1, 714 ReclaimPolicy: "Delete", 715 AccessModes: []string{"someBadAccessMode"}, 716 }, 717 valid: false, 718 }, 719 } 720 for _, test := range tests { 721 if valid, _ := test.sv.validate(); valid != test.valid { 722 t.Errorf("expected %v with %+v, but got %v", test.valid, test.sv, !test.valid) 723 } 724 } 725 } 726 727 func TestValidateAllowAddress(t *testing.T) { 728 tests := []struct { 729 address string 730 valid bool 731 }{ 732 {"192.168.205.10", true}, 733 {"192.168.205.*", true}, 734 {"192.168.*.*", true}, 735 {"192.*.*.*", true}, 736 {"*.168.205.10", true}, 737 {"*.*.205.10", true}, 738 {"*.*.*.10", true}, 739 {"*.*.*.*", true}, 740 {"-1.-1.-1.-1", false}, 741 {"-1.*.*.*", false}, 742 {"*.-1.*.*", false}, 743 {"*.*.-1.*", false}, 744 {"*.*.*.-1", false}, 745 {"256.256.256.256", false}, 746 {"256.*.*.*", false}, 747 {"*.256.*.*", false}, 748 {"*.*.256.*", false}, 749 {"*.*.*.256", false}, 750 {"a.a.a.a", false}, 751 {"*.*.*.a", false}, 752 {"*.*.a.*", false}, 753 {"*.a.*.*", false}, 754 {"a.*.*.*", false}, 755 {"", false}, 756 {"foo", false}, 757 {"192", false}, 758 {"192.168", false}, 759 {"192.168.205", false}, 760 {"...", false}, 761 {"192...", false}, 762 {"192.168..", false}, 763 {"192.168.205.", false}, 764 } 765 for _, test := range tests { 766 if validateAllowedAddress(test.address) != test.valid { 767 t.Errorf("expected %v with address %q, but got %v", test.valid, test.address, !test.valid) 768 } 769 } 770 } 771 772 func TestValidatePlanNFSDupes(t *testing.T) { 773 p := validPlan() 774 775 p.NFS.Volumes = append(p.NFS.Volumes, NFSVolume{ 776 Host: "10.10.2.20", 777 Path: "/", 778 }) 779 780 assertInvalidPlan(t, p) 781 } 782 783 func TestValidateNFSVolume(t *testing.T) { 784 tests := []struct { 785 host string 786 path string 787 valid bool 788 }{ 789 { 790 host: "10.10.2.10", 791 path: "/foo", 792 valid: true, 793 }, 794 { 795 host: "10.10.2.10", 796 path: "", 797 valid: false, 798 }, 799 { 800 host: "10.10.2.10", 801 path: "../someRelativePath", 802 valid: false, 803 }, 804 { 805 host: "", 806 path: "/foo", 807 valid: false, 808 }, 809 } 810 for _, test := range tests { 811 v := NFSVolume{ 812 Host: test.host, 813 Path: test.path, 814 } 815 if valid, _ := v.validate(); valid != test.valid { 816 t.Errorf("Expected valid = %v, but got %v", test.valid, valid) 817 } 818 } 819 } 820 821 func TestValidatePlanCerts(t *testing.T) { 822 p := validPlan() 823 824 pki := getPKI(t) 825 defer cleanup(pki.GeneratedCertsDirectory, t) 826 ca, err := pki.GenerateClusterCA(&p) 827 if err != nil { 828 t.Fatalf("error generating CA for test: %v", err) 829 } 830 proxyClientCA, err := pki.GenerateProxyClientCA(&p) 831 if err != nil { 832 t.Fatalf("error generating proxy-client CA for test: %v", err) 833 } 834 if err := pki.GenerateClusterCertificates(&p, ca, proxyClientCA); err != nil { 835 t.Fatalf("failed to generate certs: %v", err) 836 } 837 838 valid, errs := ValidateCertificates(&p, &pki) 839 if !valid { 840 t.Errorf("expected valid, but got invalid") 841 fmt.Println(errs) 842 } 843 } 844 845 func TestValidatePlanBadCerts(t *testing.T) { 846 p := validPlan() 847 848 pki := getPKI(t) 849 defer cleanup(pki.GeneratedCertsDirectory, t) 850 851 ca, err := pki.GenerateClusterCA(&p) 852 if err != nil { 853 t.Fatalf("error generating CA for test: %v", err) 854 } 855 proxyClientCA, err := pki.GenerateProxyClientCA(&p) 856 if err != nil { 857 t.Fatalf("error generating proxy-client CA for test: %v", err) 858 } 859 if err := pki.GenerateClusterCertificates(&p, ca, proxyClientCA); err != nil { 860 t.Fatalf("failed to generate certs: %v", err) 861 } 862 p.Master.Nodes[0] = Node{ 863 Host: "master01", 864 IP: "11.12.13.14", 865 InternalIP: "22.33.44.55", 866 } 867 868 valid, _ := ValidateCertificates(&p, &pki) 869 if valid { 870 t.Errorf("expected an error, but got valid") 871 } 872 } 873 874 func TestValidatePlanMissingCerts(t *testing.T) { 875 p := validPlan() 876 877 pki := getPKI(t) 878 defer cleanup(pki.GeneratedCertsDirectory, t) 879 880 valid, errs := ValidateCertificates(&p, &pki) 881 if !valid { 882 t.Errorf("expected valid, but got invalid") 883 fmt.Println(errs) 884 } 885 } 886 887 func TestValidatePlanMissingSomeCerts(t *testing.T) { 888 p := validPlan() 889 890 pki := getPKI(t) 891 defer cleanup(pki.GeneratedCertsDirectory, t) 892 893 ca, err := pki.GenerateClusterCA(&p) 894 if err != nil { 895 t.Fatalf("error generating CA for test: %v", err) 896 } 897 proxyClientCA, err := pki.GenerateProxyClientCA(&p) 898 if err != nil { 899 t.Fatalf("error generating proxy-client CA for test: %v", err) 900 } 901 if err := pki.GenerateClusterCertificates(&p, ca, proxyClientCA); err != nil { 902 t.Fatalf("failed to generate certs: %v", err) 903 } 904 905 newNode := Node{ 906 Host: "master2", 907 IP: "11.12.13.14", 908 InternalIP: "22.33.44.55", 909 } 910 p.Master.Nodes = append(p.Master.Nodes, newNode) 911 912 valid, errs := ValidateCertificates(&p, &pki) 913 if !valid { 914 t.Errorf("expected valid, but got invalid") 915 fmt.Println(errs) 916 } 917 } 918 919 func TestValidateNodeListDuplicate(t *testing.T) { 920 tests := []struct { 921 nl nodeList 922 valid bool 923 }{ 924 { 925 nl: nodeList{ 926 []Node{ 927 { 928 Host: "host1", 929 IP: "10.0.0.1", 930 }, 931 }, 932 }, 933 valid: true, 934 }, 935 { 936 nl: nodeList{ 937 []Node{ 938 { 939 Host: "host1", 940 IP: "10.0.0.1", 941 }, 942 { 943 Host: "host1", 944 IP: "10.0.0.1", 945 }, 946 }, 947 }, 948 valid: true, 949 }, 950 { 951 nl: nodeList{ 952 []Node{ 953 { 954 Host: "host1", 955 IP: "10.0.0.1", 956 }, 957 { 958 Host: "host2", 959 IP: "10.0.0.2", 960 }, 961 }, 962 }, 963 valid: true, 964 }, 965 { 966 nl: nodeList{ 967 []Node{ 968 { 969 Host: "host1", 970 IP: "10.0.0.1", 971 }, 972 { 973 Host: "host1", 974 IP: "10.0.0.2", 975 }, 976 }, 977 }, 978 valid: false, 979 }, 980 { 981 nl: nodeList{ 982 []Node{ 983 { 984 Host: "host1", 985 IP: "10.0.0.2", 986 }, 987 { 988 Host: "host2", 989 IP: "10.0.0.2", 990 }, 991 }, 992 }, 993 valid: false, 994 }, 995 { 996 nl: nodeList{ 997 []Node{ 998 { 999 Host: "host1", 1000 IP: "10.0.0.1", 1001 InternalIP: "192.168.205.10", 1002 }, 1003 { 1004 Host: "host2", 1005 IP: "10.0.0.2", 1006 InternalIP: "192.168.205.10", 1007 }, 1008 }, 1009 }, 1010 valid: false, 1011 }, 1012 } 1013 for i, test := range tests { 1014 ok, _ := test.nl.validate() 1015 if ok != test.valid { 1016 t.Errorf("test %d: expect %t, but got %t", i, test.valid, ok) 1017 } 1018 } 1019 } 1020 1021 func TestValidatePlanDisconnectedInstallationFailsDueToMissingRegistry(t *testing.T) { 1022 plan := validPlan() 1023 plan.Cluster.DisconnectedInstallation = true 1024 ok, errs := plan.validate() 1025 if ok { 1026 t.Errorf("expected validation to fail due to missing external registry information in plan") 1027 } 1028 var found bool 1029 for _, err := range errs { 1030 if err.Error() == "A container image registry is required when disconnected_installation is true" { 1031 found = true 1032 } 1033 } 1034 if !found { 1035 t.Errorf("validation did not return the expected failure message") 1036 } 1037 } 1038 1039 func TestValidatePlanDisconnectedInstallationSucceeds(t *testing.T) { 1040 plan := validPlan() 1041 plan.Cluster.DisconnectedInstallation = true 1042 plan.DockerRegistry.Server = "localhost:5000" 1043 if ok, errs := plan.validate(); !ok { 1044 t.Error("expected validation to succeed, but it failed") 1045 t.Logf("errors were: %v\n", errs) 1046 } 1047 } 1048 1049 func TestDockerRegistry(t *testing.T) { 1050 tests := []struct { 1051 d DockerRegistry 1052 valid bool 1053 }{ 1054 { 1055 d: DockerRegistry{}, 1056 valid: true, 1057 }, 1058 { 1059 d: DockerRegistry{ 1060 Server: "172.0.0.1", 1061 CAPath: "/bin/sh", 1062 }, 1063 valid: true, 1064 }, 1065 { 1066 d: DockerRegistry{ 1067 Server: "172.0.0.1", 1068 Username: "user", 1069 Password: "password", 1070 }, 1071 valid: true, 1072 }, 1073 { 1074 d: DockerRegistry{ 1075 Address: "172.0.0.1", 1076 CAPath: "/bin/sh", 1077 }, 1078 valid: true, 1079 }, 1080 { 1081 d: DockerRegistry{ 1082 Address: "172.0.0.1", 1083 Username: "user", 1084 Password: "password", 1085 }, 1086 valid: true, 1087 }, 1088 { 1089 d: DockerRegistry{ 1090 CAPath: "user", 1091 }, 1092 valid: false, 1093 }, 1094 { 1095 d: DockerRegistry{ 1096 Username: "user", 1097 }, 1098 valid: false, 1099 }, 1100 { 1101 d: DockerRegistry{ 1102 Password: "password", 1103 }, 1104 valid: false, 1105 }, 1106 } 1107 for i, test := range tests { 1108 ok, _ := test.d.validate() 1109 if ok != test.valid { 1110 t.Errorf("test %d: expect %t, but got %t", i, test.valid, ok) 1111 } 1112 } 1113 } 1114 1115 func TestValidateDockerStorage(t *testing.T) { 1116 tests := []struct { 1117 storage DockerStorage 1118 valid bool 1119 }{ 1120 { 1121 storage: DockerStorage{ 1122 Driver: "devicemapper", 1123 }, 1124 valid: true, 1125 }, 1126 { 1127 storage: DockerStorage{ 1128 Driver: "overlay2", 1129 }, 1130 valid: true, 1131 }, 1132 { 1133 storage: DockerStorage{ 1134 Driver: "foo", 1135 }, 1136 valid: true, 1137 }, 1138 { 1139 storage: DockerStorage{ 1140 Driver: "devicemapper", 1141 DirectLVMBlockDevice: DirectLVMBlockDevice{ 1142 Path: "", 1143 }, 1144 }, 1145 valid: true, 1146 }, 1147 { 1148 storage: DockerStorage{ 1149 Driver: "devicemapper", 1150 DirectLVMBlockDevice: DirectLVMBlockDevice{ 1151 Path: "foo", 1152 }, 1153 }, 1154 valid: false, 1155 }, 1156 { 1157 storage: DockerStorage{ 1158 Driver: "devicemapper", 1159 DirectLVMBlockDevice: DirectLVMBlockDevice{ 1160 Path: "/foo/bar", 1161 }, 1162 }, 1163 valid: true, 1164 }, 1165 { 1166 storage: DockerStorage{ 1167 Driver: "foo", 1168 DirectLVMBlockDevice: DirectLVMBlockDevice{ 1169 Path: "/foo/bar", 1170 }, 1171 }, 1172 valid: false, 1173 }, 1174 } 1175 for i, test := range tests { 1176 ok, _ := test.storage.validate() 1177 if ok != test.valid { 1178 t.Errorf("test %d: expect valid, but got invalid", i) 1179 } 1180 } 1181 } 1182 1183 func TestValidateDockerStorageDirectLVM(t *testing.T) { 1184 tests := []struct { 1185 config DockerStorageDirectLVMDeprecated 1186 valid bool 1187 }{ 1188 { 1189 config: DockerStorageDirectLVMDeprecated{ 1190 Enabled: false, 1191 }, 1192 valid: true, 1193 }, 1194 { 1195 config: DockerStorageDirectLVMDeprecated{ 1196 Enabled: true, 1197 }, 1198 valid: false, 1199 }, 1200 { 1201 config: DockerStorageDirectLVMDeprecated{ 1202 Enabled: true, 1203 BlockDevice: "foo", 1204 }, 1205 valid: false, 1206 }, 1207 { 1208 config: DockerStorageDirectLVMDeprecated{ 1209 Enabled: true, 1210 BlockDevice: "/dev/sdb", 1211 }, 1212 valid: true, 1213 }, 1214 } 1215 for i, test := range tests { 1216 ok, _ := test.config.validate() 1217 if ok != test.valid { 1218 t.Errorf("test %d: expect valid, but got invalid", i) 1219 } 1220 } 1221 } 1222 1223 func TestCNIAddOn(t *testing.T) { 1224 tests := []struct { 1225 n CNI 1226 valid bool 1227 }{ 1228 { 1229 n: CNI{ 1230 Provider: "calico", 1231 Options: CNIOptions{ 1232 Calico: CalicoOptions{ 1233 Mode: "overlay", 1234 }, 1235 }, 1236 }, 1237 valid: true, 1238 }, 1239 { 1240 n: CNI{ 1241 Provider: "calico", 1242 Options: CNIOptions{ 1243 Calico: CalicoOptions{ 1244 Mode: "routed", 1245 }, 1246 }, 1247 }, 1248 valid: true, 1249 }, 1250 { 1251 n: CNI{ 1252 Provider: "weave", 1253 }, 1254 valid: true, 1255 }, 1256 { 1257 n: CNI{ 1258 Provider: "contiv", 1259 }, 1260 valid: true, 1261 }, 1262 { 1263 n: CNI{ 1264 Provider: "foo", 1265 Options: CNIOptions{ 1266 Calico: CalicoOptions{ 1267 Mode: "overlay", 1268 }, 1269 }, 1270 }, 1271 valid: false, 1272 }, 1273 { 1274 n: CNI{ 1275 Provider: "calico", 1276 Options: CNIOptions{ 1277 Calico: CalicoOptions{ 1278 Mode: "foo", 1279 }, 1280 }, 1281 }, 1282 valid: false, 1283 }, 1284 { 1285 n: CNI{ 1286 Provider: "foo", 1287 Disable: true, 1288 Options: CNIOptions{ 1289 Calico: CalicoOptions{ 1290 Mode: "overlay", 1291 }, 1292 }, 1293 }, 1294 valid: true, 1295 }, 1296 { 1297 n: CNI{ 1298 Provider: "calico", 1299 Disable: true, 1300 Options: CNIOptions{ 1301 Calico: CalicoOptions{ 1302 Mode: "foo", 1303 }, 1304 }, 1305 }, 1306 valid: true, 1307 }, 1308 { 1309 n: CNI{ 1310 Provider: "calico", 1311 Options: CNIOptions{ 1312 Calico: CalicoOptions{ 1313 Mode: "overlay", 1314 LogLevel: "", 1315 }, 1316 }, 1317 }, 1318 valid: true, 1319 }, 1320 { 1321 n: CNI{ 1322 Provider: "calico", 1323 Options: CNIOptions{ 1324 Calico: CalicoOptions{ 1325 Mode: "overlay", 1326 LogLevel: "info", 1327 }, 1328 }, 1329 }, 1330 valid: true, 1331 }, 1332 { 1333 n: CNI{ 1334 Provider: "calico", 1335 Options: CNIOptions{ 1336 Calico: CalicoOptions{ 1337 Mode: "overlay", 1338 LogLevel: "warning", 1339 }, 1340 }, 1341 }, 1342 valid: true, 1343 }, 1344 { 1345 n: CNI{ 1346 Provider: "calico", 1347 Options: CNIOptions{ 1348 Calico: CalicoOptions{ 1349 Mode: "overlay", 1350 LogLevel: "debug", 1351 }, 1352 }, 1353 }, 1354 valid: true, 1355 }, 1356 { 1357 n: CNI{ 1358 Provider: "calico", 1359 Options: CNIOptions{ 1360 Calico: CalicoOptions{ 1361 Mode: "overlay", 1362 LogLevel: "INFO", 1363 }, 1364 }, 1365 }, 1366 valid: false, 1367 }, 1368 { 1369 n: CNI{ 1370 Provider: "calico", 1371 Options: CNIOptions{ 1372 Calico: CalicoOptions{ 1373 Mode: "overlay", 1374 LogLevel: "foo", 1375 }, 1376 }, 1377 }, 1378 valid: false, 1379 }, 1380 } 1381 for i, test := range tests { 1382 ok, _ := test.n.validate() 1383 if ok != test.valid { 1384 t.Errorf("test %d: expect %t, but got %t", i, test.valid, ok) 1385 } 1386 } 1387 } 1388 1389 func TestDNSProvider(t *testing.T) { 1390 tests := []struct { 1391 d DNS 1392 valid bool 1393 }{ 1394 { 1395 d: DNS{ 1396 Provider: "kubedns", 1397 }, 1398 valid: true, 1399 }, 1400 { 1401 d: DNS{ 1402 Provider: "coredns", 1403 }, 1404 valid: true, 1405 }, 1406 { 1407 d: DNS{ 1408 Disable: true, 1409 Provider: "foo", 1410 }, 1411 valid: true, 1412 }, 1413 { 1414 d: DNS{ 1415 Provider: "foo", 1416 }, 1417 valid: false, 1418 }, 1419 } 1420 for i, test := range tests { 1421 ok, _ := test.d.validate() 1422 if ok != test.valid { 1423 t.Errorf("test %d: expect %t, but got %t", i, test.valid, ok) 1424 } 1425 } 1426 } 1427 1428 func TestHeapsterAddOn(t *testing.T) { 1429 tests := []struct { 1430 h HeapsterMonitoring 1431 valid bool 1432 }{ 1433 { 1434 h: HeapsterMonitoring{ 1435 Options: HeapsterOptions{ 1436 Heapster: Heapster{ 1437 Replicas: 0, 1438 ServiceType: "ClusterIP", 1439 }, 1440 }, 1441 }, 1442 valid: false, 1443 }, 1444 { 1445 h: HeapsterMonitoring{ 1446 Options: HeapsterOptions{ 1447 Heapster: Heapster{ 1448 Replicas: 1, 1449 ServiceType: "Foo", 1450 }, 1451 }, 1452 }, 1453 valid: false, 1454 }, 1455 { 1456 h: HeapsterMonitoring{ 1457 Options: HeapsterOptions{ 1458 Heapster: Heapster{ 1459 Replicas: -1, 1460 ServiceType: "ClusterIP", 1461 }, 1462 }, 1463 }, 1464 valid: false, 1465 }, 1466 { 1467 h: HeapsterMonitoring{ 1468 Options: HeapsterOptions{ 1469 Heapster: Heapster{ 1470 Replicas: 1, 1471 ServiceType: "ClusterIP", 1472 }, 1473 }, 1474 }, 1475 valid: true, 1476 }, 1477 } 1478 for i, test := range tests { 1479 ok, _ := test.h.validate() 1480 if ok != test.valid { 1481 t.Errorf("test %d: expect %t, but got %t", i, test.valid, ok) 1482 } 1483 } 1484 } 1485 1486 func TestDashbordAddOn(t *testing.T) { 1487 tests := []struct { 1488 d Dashboard 1489 valid bool 1490 }{ 1491 { 1492 d: Dashboard{ 1493 Options: DashboardOptions{ 1494 ServiceType: "ClusterIP", 1495 }, 1496 }, 1497 valid: true, 1498 }, 1499 { 1500 d: Dashboard{ 1501 Options: DashboardOptions{ 1502 ServiceType: "Foo", 1503 }, 1504 }, 1505 valid: false, 1506 }, 1507 { 1508 d: Dashboard{ 1509 Options: DashboardOptions{ 1510 ServiceType: "ClusterIP", 1511 NodePort: "32500", 1512 }, 1513 }, 1514 valid: false, 1515 }, 1516 { 1517 d: Dashboard{ 1518 Options: DashboardOptions{ 1519 ServiceType: "NodePort", 1520 NodePort: "32500", 1521 }, 1522 }, 1523 valid: true, 1524 }, 1525 } 1526 for i, test := range tests { 1527 ok, _ := test.d.validate() 1528 if ok != test.valid { 1529 t.Errorf("test %d: expect %t, but got %t", i, test.valid, ok) 1530 } 1531 } 1532 } 1533 1534 func TestPackageManagerAddOn(t *testing.T) { 1535 tests := []struct { 1536 p PackageManager 1537 valid bool 1538 }{ 1539 { 1540 p: PackageManager{ 1541 Disable: false, 1542 Provider: "helm", 1543 }, 1544 valid: true, 1545 }, 1546 { 1547 p: PackageManager{ 1548 Disable: true, 1549 Provider: "", 1550 }, 1551 valid: true, 1552 }, 1553 { 1554 p: PackageManager{ 1555 Disable: true, 1556 Provider: "foo", 1557 }, 1558 valid: true, 1559 }, 1560 { 1561 p: PackageManager{ 1562 Disable: false, 1563 Provider: "", 1564 }, 1565 valid: true, 1566 }, 1567 { 1568 p: PackageManager{ 1569 Disable: false, 1570 Provider: "foo", 1571 }, 1572 valid: false, 1573 }, 1574 } 1575 for i, test := range tests { 1576 ok, _ := test.p.validate() 1577 if ok != test.valid { 1578 t.Errorf("test %d: expect %t, but got %t", i, test.valid, ok) 1579 } 1580 } 1581 } 1582 1583 func TestCloudProvider(t *testing.T) { 1584 tests := []struct { 1585 c CloudProvider 1586 valid bool 1587 }{ 1588 { 1589 c: CloudProvider{ 1590 Provider: "", 1591 }, 1592 valid: true, 1593 }, 1594 { 1595 c: CloudProvider{ 1596 Provider: "aws", 1597 }, 1598 valid: true, 1599 }, 1600 { 1601 c: CloudProvider{ 1602 Provider: "awss", 1603 }, 1604 valid: false, 1605 }, 1606 { 1607 c: CloudProvider{ 1608 Provider: "gce", 1609 Config: "/bin/sh", 1610 }, 1611 valid: true, 1612 }, 1613 { 1614 c: CloudProvider{ 1615 Provider: "gce", 1616 Config: "/bin/foo", 1617 }, 1618 valid: false, 1619 }, 1620 { 1621 c: CloudProvider{ 1622 Provider: "gce", 1623 Config: "foo", 1624 }, 1625 valid: false, 1626 }, 1627 } 1628 for i, test := range tests { 1629 ok, _ := test.c.validate() 1630 if ok != test.valid { 1631 t.Errorf("test %d: expect %t, but got %t", i, test.valid, ok) 1632 } 1633 } 1634 } 1635 1636 func TestNodeLabels(t *testing.T) { 1637 tests := []struct { 1638 n Node 1639 valid bool 1640 }{ 1641 { 1642 n: Node{ 1643 Host: "foo", 1644 IP: "192.1.1.1", 1645 }, 1646 valid: true, 1647 }, 1648 { 1649 n: Node{ 1650 Host: "foo", 1651 IP: "192.1.1.1", 1652 Labels: map[string]string{}, 1653 }, 1654 valid: true, 1655 }, 1656 { 1657 n: Node{ 1658 Host: "foo", 1659 IP: "192.1.1.1", 1660 Labels: map[string]string{"com.foo/bar": ""}, 1661 }, 1662 valid: true, 1663 }, 1664 { 1665 n: Node{ 1666 Host: "foo", 1667 IP: "192.1.1.1", 1668 Labels: map[string]string{"com.foo/bar": "foobar"}, 1669 }, 1670 valid: true, 1671 }, 1672 { 1673 n: Node{ 1674 Host: "foo", 1675 IP: "192.1.1.1", 1676 Labels: map[string]string{"com.foo/bar": "foobar", "com.foo/xyz": "xyz"}, 1677 }, 1678 valid: true, 1679 }, 1680 { 1681 n: Node{ 1682 Host: "foo", 1683 IP: "192.1.1.1", 1684 Labels: map[string]string{"kismatic/foo": "bar"}, 1685 }, 1686 valid: false, 1687 }, 1688 { 1689 n: Node{ 1690 Host: "foo", 1691 IP: "192.1.1.1", 1692 Labels: map[string]string{"com.foo/kismatic-version": "v1.0.0"}, 1693 }, 1694 valid: true, 1695 }, 1696 { 1697 n: Node{ 1698 Host: "foo", 1699 IP: "192.1.1.1", 1700 Labels: map[string]string{"": "com.foo/worker"}, 1701 }, 1702 valid: false, 1703 }, 1704 { 1705 n: Node{ 1706 Host: "foo", 1707 IP: "192.1.1.1", 1708 Labels: map[string]string{"": ""}, 1709 }, 1710 valid: false, 1711 }, 1712 { 1713 n: Node{ 1714 Host: "foo", 1715 IP: "192.1.1.1", 1716 Labels: map[string]string{"node-type:test": "test"}, 1717 }, 1718 valid: false, 1719 }, 1720 { 1721 n: Node{ 1722 Host: "foo", 1723 IP: "192.1.1.1", 1724 Labels: map[string]string{"com.foo/invalid": ":test"}, 1725 }, 1726 valid: false, 1727 }, 1728 { 1729 n: Node{ 1730 Host: "foo", 1731 IP: "192.1.1.1", 1732 Labels: map[string]string{"node-type:test": ":test"}, 1733 }, 1734 valid: false, 1735 }, 1736 } 1737 for i, test := range tests { 1738 ok, _ := test.n.validate() 1739 if ok != test.valid { 1740 t.Errorf("test %d: expect %t, but got %t", i, test.valid, ok) 1741 } 1742 } 1743 } 1744 1745 func TestNodeTaints(t *testing.T) { 1746 tests := []struct { 1747 n Node 1748 valid bool 1749 }{ 1750 { 1751 n: Node{ 1752 Host: "foo", 1753 IP: "192.1.1.1", 1754 }, 1755 valid: true, 1756 }, 1757 { 1758 n: Node{ 1759 Host: "foo", 1760 IP: "192.1.1.1", 1761 Taints: []Taint{}, 1762 }, 1763 valid: true, 1764 }, 1765 { 1766 n: Node{ 1767 Host: "foo", 1768 IP: "192.1.1.1", 1769 Taints: []Taint{ 1770 Taint{ 1771 Key: "com.foo/bar", 1772 Value: "", 1773 Effect: "NoSchedule", 1774 }, 1775 }, 1776 }, 1777 valid: true, 1778 }, 1779 { 1780 n: Node{ 1781 Host: "foo", 1782 IP: "192.1.1.1", 1783 Taints: []Taint{ 1784 Taint{ 1785 Key: "com.foo/bar", 1786 Value: "foobar", 1787 Effect: "NoSchedule", 1788 }, 1789 }, 1790 }, 1791 valid: true, 1792 }, 1793 { 1794 n: Node{ 1795 Host: "foo", 1796 IP: "192.1.1.1", 1797 Taints: []Taint{ 1798 Taint{ 1799 Key: "com.foo/bar", 1800 Value: "foobar", 1801 Effect: "NoSchedule", 1802 }, 1803 Taint{ 1804 Key: "com.foo/xyz", 1805 Value: "xyz", 1806 Effect: "NoSchedule", 1807 }, 1808 }, 1809 }, 1810 valid: true, 1811 }, 1812 { 1813 n: Node{ 1814 Host: "foo", 1815 IP: "192.1.1.1", 1816 Taints: []Taint{ 1817 Taint{ 1818 Key: "kismatic/foo", 1819 Value: "bar", 1820 Effect: "NoSchedule", 1821 }, 1822 }, 1823 }, 1824 valid: false, 1825 }, 1826 { 1827 n: Node{ 1828 Host: "foo", 1829 IP: "192.1.1.1", 1830 Taints: []Taint{ 1831 Taint{ 1832 Key: "com.foo/kismatic-version", 1833 Value: "v1.0.0", 1834 Effect: "NoSchedule", 1835 }, 1836 }, 1837 }, 1838 valid: true, 1839 }, 1840 { 1841 n: Node{ 1842 Host: "foo", 1843 IP: "192.1.1.1", 1844 Taints: []Taint{ 1845 Taint{ 1846 Key: "", 1847 Value: "v1.0.0", 1848 Effect: "NoSchedule", 1849 }, 1850 }, 1851 }, 1852 valid: false, 1853 }, 1854 { 1855 n: Node{ 1856 Host: "foo", 1857 IP: "192.1.1.1", 1858 Taints: []Taint{ 1859 Taint{ 1860 Key: "", 1861 Value: "", 1862 Effect: "NoSchedule", 1863 }, 1864 }, 1865 Labels: map[string]string{"": ""}, 1866 }, 1867 valid: false, 1868 }, 1869 { 1870 n: Node{ 1871 Host: "foo", 1872 IP: "192.1.1.1", 1873 Taints: []Taint{ 1874 Taint{ 1875 Key: "", 1876 Value: "", 1877 Effect: "", 1878 }, 1879 }, 1880 Labels: map[string]string{"": ""}, 1881 }, 1882 valid: false, 1883 }, 1884 { 1885 n: Node{ 1886 Host: "foo", 1887 IP: "192.1.1.1", 1888 Taints: []Taint{ 1889 Taint{ 1890 Key: "node-type:test", 1891 Value: "test", 1892 Effect: "NoSchedule", 1893 }, 1894 }, 1895 Labels: map[string]string{"node-type:test": "test"}, 1896 }, 1897 valid: false, 1898 }, 1899 { 1900 n: Node{ 1901 Host: "foo", 1902 IP: "192.1.1.1", 1903 Taints: []Taint{ 1904 Taint{ 1905 Key: "com.foo/invalid", 1906 Value: ":test", 1907 Effect: "NoSchedule", 1908 }, 1909 }, 1910 }, 1911 valid: false, 1912 }, 1913 { 1914 n: Node{ 1915 Host: "foo", 1916 IP: "192.1.1.1", 1917 Taints: []Taint{ 1918 Taint{ 1919 Key: "node-type:test", 1920 Value: ":test", 1921 Effect: "NoSchedule", 1922 }, 1923 }, 1924 }, 1925 valid: false, 1926 }, 1927 { 1928 n: Node{ 1929 Host: "foo", 1930 IP: "192.1.1.1", 1931 Taints: []Taint{ 1932 Taint{ 1933 Key: "kismatic/foo", 1934 Value: "bar", 1935 Effect: "", 1936 }, 1937 }, 1938 }, 1939 valid: false, 1940 }, 1941 { 1942 n: Node{ 1943 Host: "foo", 1944 IP: "192.1.1.1", 1945 Taints: []Taint{ 1946 Taint{ 1947 Key: "kismatic/foo", 1948 Value: "bar", 1949 Effect: "Foo", 1950 }, 1951 }, 1952 }, 1953 valid: false, 1954 }, 1955 } 1956 for i, test := range tests { 1957 ok, _ := test.n.validate() 1958 if ok != test.valid { 1959 t.Errorf("test %d: expect %t, but got %t", i, test.valid, ok) 1960 } 1961 } 1962 } 1963 1964 func TestNodeKubeletOptions(t *testing.T) { 1965 tests := []struct { 1966 nl nodeList 1967 valid bool 1968 }{ 1969 { 1970 nl: nodeList{ 1971 []Node{ 1972 { 1973 Host: "host1", 1974 IP: "10.0.0.1", 1975 KubeletOptions: KubeletOptions{ 1976 Overrides: map[string]string{ 1977 "v": "2", 1978 }, 1979 }, 1980 }, 1981 { 1982 Host: "host2", 1983 IP: "10.0.0.2", 1984 KubeletOptions: KubeletOptions{ 1985 Overrides: map[string]string{ 1986 "v": "2", 1987 }, 1988 }, 1989 }, 1990 }, 1991 }, 1992 valid: true, 1993 }, 1994 { 1995 nl: nodeList{ 1996 []Node{ 1997 { 1998 Host: "host1", 1999 IP: "10.0.0.1", 2000 KubeletOptions: KubeletOptions{ 2001 Overrides: map[string]string{ 2002 "v": "2", 2003 }, 2004 }, 2005 }, 2006 { 2007 Host: "host1", 2008 IP: "10.0.0.1", 2009 KubeletOptions: KubeletOptions{ 2010 Overrides: map[string]string{ 2011 "v": "2", 2012 }, 2013 }, 2014 }, 2015 }, 2016 }, 2017 valid: true, 2018 }, 2019 { 2020 nl: nodeList{ 2021 []Node{ 2022 { 2023 Host: "host1", 2024 IP: "10.0.0.1", 2025 KubeletOptions: KubeletOptions{ 2026 Overrides: map[string]string{ 2027 "v": "2", 2028 }, 2029 }, 2030 }, 2031 { 2032 Host: "host1", 2033 IP: "10.0.0.1", 2034 KubeletOptions: KubeletOptions{ 2035 Overrides: map[string]string{ 2036 "foo": "bar", 2037 }, 2038 }, 2039 }, 2040 }, 2041 }, 2042 valid: false, 2043 }, 2044 { 2045 nl: nodeList{ 2046 []Node{ 2047 { 2048 Host: "host1", 2049 IP: "10.0.0.1", 2050 KubeletOptions: KubeletOptions{ 2051 Overrides: map[string]string{ 2052 "v": "2", 2053 }, 2054 }, 2055 }, 2056 { 2057 Host: "host1", 2058 IP: "10.0.0.1", 2059 KubeletOptions: KubeletOptions{ 2060 Overrides: map[string]string{ 2061 "v": "3", 2062 }, 2063 }, 2064 }, 2065 }, 2066 }, 2067 valid: false, 2068 }, 2069 { 2070 nl: nodeList{ 2071 []Node{ 2072 { 2073 Host: "host1", 2074 IP: "10.0.0.1", 2075 KubeletOptions: KubeletOptions{ 2076 Overrides: map[string]string{ 2077 "v": "2", 2078 }, 2079 }, 2080 }, 2081 { 2082 Host: "host1", 2083 IP: "10.0.0.1", 2084 KubeletOptions: KubeletOptions{ 2085 Overrides: map[string]string{ 2086 "v": "2", 2087 "foo": "bar", 2088 }, 2089 }, 2090 }, 2091 }, 2092 }, 2093 valid: false, 2094 }, 2095 } 2096 for i, test := range tests { 2097 ok, _ := test.nl.validate() 2098 if ok != test.valid { 2099 t.Errorf("test %d: expect %t, but got %t", i, test.valid, ok) 2100 } 2101 } 2102 } 2103 2104 func TestValidateFile(t *testing.T) { 2105 tests := []struct { 2106 srcPath string 2107 destPath string 2108 hosts []string 2109 skipValidation bool 2110 valid bool 2111 }{ 2112 { 2113 srcPath: "/bin/sh", 2114 destPath: "/tmp/copy_xa.yaml", 2115 hosts: []string{"master01"}, 2116 valid: true, 2117 }, 2118 { 2119 srcPath: "/bin/sh", 2120 destPath: "/tmp/copy_xa.yaml", 2121 hosts: []string{"worker01"}, 2122 valid: true, 2123 }, 2124 { 2125 srcPath: "/bin/sh", 2126 destPath: "/tmp/copy_xa.yaml", 2127 hosts: []string{"etcd01"}, 2128 valid: true, 2129 }, 2130 { 2131 srcPath: "/tmp/xa.yaml", 2132 destPath: "/tmp/copy_xa.yaml", 2133 hosts: []string{"master01"}, 2134 skipValidation: true, 2135 valid: true, 2136 }, 2137 { 2138 srcPath: "/bin/sh", 2139 destPath: "/tmp/copy_xa.yaml", 2140 hosts: []string{"worker"}, 2141 valid: true, 2142 }, 2143 { 2144 srcPath: "/bin/sh", 2145 destPath: "/tmp/copy_xa.yaml", 2146 hosts: []string{"all"}, 2147 valid: true, 2148 }, 2149 { 2150 srcPath: "/bin/sh", 2151 destPath: "/tmp/copy_xa.yaml", 2152 hosts: []string{"master", "worker"}, 2153 valid: true, 2154 }, 2155 { 2156 srcPath: "/bin/sh", 2157 destPath: "/tmp/copy_xa.yaml", 2158 hosts: []string{"master", "worker", "worker100"}, 2159 valid: false, 2160 }, 2161 { 2162 srcPath: "", 2163 destPath: "", 2164 hosts: []string{"master01"}, 2165 valid: false, 2166 }, 2167 { 2168 srcPath: "", 2169 destPath: "/tmp/copy_xa.yaml", 2170 hosts: []string{"master01"}, 2171 valid: false, 2172 }, 2173 { 2174 srcPath: "/bin/sh", 2175 destPath: "", 2176 hosts: []string{"master01"}, 2177 valid: false, 2178 }, 2179 { 2180 srcPath: "../someRelativePath", 2181 destPath: "../someRelativePath", 2182 hosts: []string{"master01"}, 2183 valid: false, 2184 }, 2185 { 2186 srcPath: "/bin/sh", 2187 destPath: "../someRelativePath", 2188 hosts: []string{"master01"}, 2189 valid: false, 2190 }, 2191 { 2192 srcPath: "/bin/sh", 2193 destPath: "/bin/sh", 2194 hosts: []string{}, 2195 valid: false, 2196 }, 2197 { 2198 srcPath: "/bin/sh", 2199 destPath: "/bin/sh", 2200 hosts: []string{"master02"}, 2201 valid: false, 2202 }, 2203 { 2204 srcPath: "/bin/sh", 2205 destPath: "/bin/sh", 2206 hosts: []string{"foo"}, 2207 valid: false, 2208 }, 2209 } 2210 for n, test := range tests { 2211 v := []AdditionalFile{ 2212 AdditionalFile{ 2213 Source: test.srcPath, 2214 Destination: test.destPath, 2215 Hosts: test.hosts, 2216 SkipValidation: test.skipValidation, 2217 }, 2218 } 2219 plan := validPlan() 2220 fg := additionalFilesGroup{AdditionalFiles: v, Plan: &plan} 2221 if valid, errs := fg.validate(); valid != test.valid { 2222 t.Errorf("test %d: expect valid = %t, but got %t", n, test.valid, valid) 2223 if !valid { 2224 t.Errorf("error %v", errs) 2225 } 2226 } 2227 } 2228 }