github.com/openshift/installer@v1.4.17/pkg/asset/agent/installconfig_test.go (about) 1 package agent 2 3 import ( 4 "net" 5 "testing" 6 7 "github.com/golang/mock/gomock" 8 "github.com/stretchr/testify/assert" 9 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 10 "k8s.io/utils/pointer" 11 12 "github.com/openshift/installer/pkg/asset" 13 "github.com/openshift/installer/pkg/asset/mock" 14 "github.com/openshift/installer/pkg/ipnet" 15 "github.com/openshift/installer/pkg/types" 16 "github.com/openshift/installer/pkg/types/baremetal" 17 "github.com/openshift/installer/pkg/types/external" 18 "github.com/openshift/installer/pkg/types/none" 19 "github.com/openshift/installer/pkg/types/vsphere" 20 ) 21 22 func TestInstallConfigLoad(t *testing.T) { 23 cases := []struct { 24 name string 25 data string 26 fetchError error 27 expectedFound bool 28 expectedError string 29 expectedConfig *types.InstallConfig 30 }{ 31 { 32 name: "unsupported platform", 33 data: ` 34 apiVersion: v1 35 metadata: 36 name: test-cluster 37 baseDomain: test-domain 38 platform: 39 aws: 40 region: us-east-1 41 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 42 `, 43 expectedFound: false, 44 expectedError: `invalid install-config configuration: Platform: Unsupported value: "aws": supported values: "baremetal", "vsphere", "none", "external"`, 45 }, 46 { 47 name: "apiVips not set for baremetal Compact platform", 48 data: ` 49 apiVersion: v1 50 metadata: 51 name: test-cluster 52 baseDomain: test-domain 53 networking: 54 clusterNetwork: 55 - cidr: 10.128.0.0/14 56 hostPrefix: 23 57 networkType: OVNKubernetes 58 machineNetwork: 59 - cidr: 192.168.122.0/23 60 serviceNetwork: 61 - 172.30.0.0/16 62 compute: 63 - architecture: amd64 64 hyperthreading: Enabled 65 name: worker 66 platform: {} 67 replicas: 0 68 controlPlane: 69 architecture: amd64 70 hyperthreading: Enabled 71 name: master 72 platform: {} 73 replicas: 3 74 platform: 75 baremetal: 76 externalMACAddress: "52:54:00:f6:b4:02" 77 provisioningMACAddress: "52:54:00:6e:3b:02" 78 ingressVIPs: 79 - 192.168.122.11 80 hosts: 81 - name: host1 82 bootMACAddress: 52:54:01:aa:aa:a1 83 - name: host2 84 bootMACAddress: 52:54:01:bb:bb:b1 85 - name: host3 86 bootMACAddress: 52:54:01:cc:cc:c1 87 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 88 `, 89 expectedFound: false, 90 expectedError: "invalid install-config configuration: [platform.baremetal.apiVIPs: Required value: must specify at least one VIP for the API, platform.baremetal.apiVIPs: Required value: must specify VIP for API, when VIP for ingress is set]", 91 }, 92 { 93 name: "ingressVIP missing and deprecated vSphere credentials are present", 94 data: ` 95 apiVersion: v1 96 metadata: 97 name: test-cluster 98 baseDomain: test-domain 99 platform: 100 vsphere: 101 apiVips: 102 - 192.168.122.10 103 vCenter: test.vcenter.com 104 username: testuser 105 password: testpassword 106 datacenter: testDatacenter 107 defaultDatastore: testDatastore 108 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 109 `, 110 expectedFound: false, 111 expectedError: `invalid install-config configuration: [platform.vsphere.ingressVIPs: Required value: must specify VIP for ingress, when VIP for API is set, Platform.VSphere.failureDomains.topology.folder: Required value: must specify a folder for agent-based installs]`, 112 }, 113 { 114 name: "ingressVIP missing and vcenter vSphere credentials are present", 115 data: ` 116 apiVersion: v1 117 metadata: 118 name: test-cluster 119 baseDomain: test-domain 120 platform: 121 vsphere: 122 apiVips: 123 - 192.168.122.10 124 vcenters: 125 - server: test.vcenter.com 126 user: testuser 127 password: testpassword 128 datacenters: 129 - testDatacenter 130 failureDomains: 131 - name: testFailuredomain 132 server: test.vcenter.com 133 zone: testZone 134 region: testRegion 135 topology: 136 computeCluster: "/testDatacenter/host/testcluster" 137 datacenter: testDatacenter 138 datastore: "/testDatacenter/datastore/testDatastore" 139 folder: "/testDatacenter/vm/testFolder" 140 networks: 141 - testNetwork 142 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 143 `, 144 expectedFound: false, 145 expectedError: `invalid install-config configuration: platform.vsphere.ingressVIPs: Required value: must specify VIP for ingress, when VIP for API is set`, 146 }, 147 { 148 name: "vcenter vSphere credentials are present but failureDomain server does not match", 149 data: ` 150 apiVersion: v1 151 metadata: 152 name: test-cluster 153 baseDomain: test-domain 154 platform: 155 vsphere: 156 apiVips: 157 - 192.168.122.10 158 ingressVips: 159 - 192.168.122.11 160 vcenters: 161 - server: test.vcenter.com 162 user: testuser 163 password: testpassword 164 datacenters: 165 - testDatacenter 166 failureDomains: 167 - name: testFailuredomain 168 server: diff1.vcenter.com 169 zone: testZone 170 region: testRegion 171 topology: 172 computeCluster: "/testDatacenter/host/testcluster" 173 datacenter: testDatacenter 174 datastore: "/testDatacenter/datastore/testDatastore" 175 folder: "/testDatacenter/vm/testFolder" 176 networks: 177 - testNetwork 178 - name: testFailuredomain2 179 server: diff2.vcenter.com 180 zone: testZone2 181 region: testRegion2 182 topology: 183 computeCluster: "/testDatacenter2/host/testcluster2" 184 datacenter: testDatacenter2 185 datastore: "/testDatacenter2/datastore/testDatastore2" 186 folder: "/testDatacenter2/vm/testFolder" 187 networks: 188 - testNetwork2 189 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 190 `, 191 expectedFound: false, 192 expectedError: `invalid install-config configuration: [platform.vsphere.failureDomains.server: Invalid value: "diff1.vcenter.com": server does not exist in vcenters, platform.vsphere.failureDomains.server: Invalid value: "diff2.vcenter.com": server does not exist in vcenters]`, 193 }, 194 { 195 name: "All required vSphere fields must be entered if some of them are entered - deprecated fields", 196 data: ` 197 apiVersion: v1 198 metadata: 199 name: test-cluster 200 baseDomain: test-domain 201 platform: 202 vsphere: 203 apiVips: 204 - 192.168.122.10 205 ingressVips: 206 - 192.168.122.11 207 vCenter: test.vcenter.com 208 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 209 `, 210 expectedFound: false, 211 expectedError: `invalid install-config configuration: [Platform.VSphere.username: Required value: All credential fields are required if any one is specified, Platform.VSphere.password: Required value: All credential fields are required if any one is specified, Platform.VSphere.datacenter: Required value: All credential fields are required if any one is specified, Platform.VSphere.failureDomains.topology.folder: Required value: must specify a folder for agent-based installs]`, 212 }, 213 { 214 name: "All required vSphere fields must be entered if some of them are entered - vcenter fields", 215 data: ` 216 apiVersion: v1 217 metadata: 218 name: test-cluster 219 baseDomain: test-domain 220 platform: 221 vsphere: 222 apiVips: 223 - 192.168.122.10 224 ingressVips: 225 - 192.168.122.11 226 vcenters: 227 - server: test.vcenter.com 228 user: testuser 229 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 230 `, 231 expectedFound: false, 232 expectedError: `invalid install-config configuration: [Platform.VSphere.password: Required value: All credential fields are required if any one is specified, Platform.VSphere.datacenter: Required value: All credential fields are required if any one is specified, Platform.VSphere.failureDomains.topology.folder: Required value: must specify a folder for agent-based installs]`, 233 }, 234 { 235 name: "ingressVIP missing for vSphere, credentials not provided and should not flag error", 236 data: ` 237 apiVersion: v1 238 metadata: 239 name: test-cluster 240 baseDomain: test-domain 241 platform: 242 vsphere: 243 apiVips: 244 - 192.168.122.10 245 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 246 `, 247 expectedFound: false, 248 expectedError: `invalid install-config configuration: platform.vsphere.ingressVIPs: Required value: must specify VIP for ingress, when VIP for API is set`, 249 }, 250 { 251 name: "no compute.replicas set for SNO", 252 data: ` 253 apiVersion: v1 254 metadata: 255 name: test-cluster 256 baseDomain: test-domain 257 networking: 258 networkType: OVNKubernetes 259 controlPlane: 260 architecture: amd64 261 hyperthreading: Enabled 262 name: master 263 platform: {} 264 replicas: 1 265 platform: 266 none : {} 267 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 268 `, 269 expectedFound: false, 270 expectedError: "invalid install-config configuration: Compute.Replicas: Required value: Total number of Compute.Replicas must be 0 when ControlPlane.Replicas is 1 for platform none or external. Found 3", 271 }, 272 { 273 name: "incorrect compute.replicas set", 274 data: ` 275 apiVersion: v1 276 metadata: 277 name: test-cluster 278 baseDomain: test-domain 279 networking: 280 networkType: OVNKubernetes 281 controlPlane: 282 architecture: amd64 283 hyperthreading: Enabled 284 name: master 285 platform: {} 286 replicas: 2 287 platform: 288 external: 289 platformName: oci 290 cloudControllerManager: External 291 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"authorization value\"}}}" 292 `, 293 expectedFound: false, 294 expectedError: "invalid install-config configuration: ControlPlane.Replicas: Invalid value: 2: ControlPlane.Replicas can only be set to 3 or 1. Found 2", 295 }, 296 { 297 name: "invalid platform for SNO cluster", 298 data: ` 299 apiVersion: v1 300 metadata: 301 name: test-cluster 302 baseDomain: test-domain 303 networking: 304 networkType: OVNKubernetes 305 compute: 306 - architecture: amd64 307 hyperthreading: Enabled 308 name: worker 309 platform: {} 310 replicas: 0 311 controlPlane: 312 architecture: amd64 313 hyperthreading: Enabled 314 name: master 315 platform: {} 316 replicas: 1 317 platform: 318 aws: 319 region: us-east-1 320 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 321 `, 322 expectedFound: false, 323 expectedError: "invalid install-config configuration: [Platform: Unsupported value: \"aws\": supported values: \"baremetal\", \"vsphere\", \"none\", \"external\", Platform: Invalid value: \"aws\": Only platform none and external supports 1 ControlPlane and 0 Compute nodes]", 324 }, 325 { 326 name: "invalid platform.baremetal for architecture ppc64le", 327 data: ` 328 apiVersion: v1 329 metadata: 330 name: test-cluster 331 baseDomain: test-domain 332 networking: 333 networkType: OVNKubernetes 334 machineNetwork: 335 - cidr: 192.168.122.0/23 336 compute: 337 - architecture: ppc64le 338 hyperthreading: Enabled 339 name: worker 340 platform: {} 341 replicas: 0 342 controlPlane: 343 architecture: ppc64le 344 hyperthreading: Enabled 345 name: master 346 platform: {} 347 replicas: 3 348 platform: 349 baremetal: 350 apiVIP: 192.168.122.10 351 ingressVIP: 192.168.122.11 352 hosts: 353 - name: host1 354 bootMACAddress: 52:54:01:aa:aa:a1 355 - name: host2 356 bootMACAddress: 52:54:01:bb:bb:b1 357 - name: host3 358 bootMACAddress: 52:54:01:cc:cc:c1 359 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 360 `, 361 expectedFound: false, 362 expectedError: "invalid install-config configuration: Platform: Invalid value: \"baremetal\": CPU architecture \"ppc64le\" only supports platform \"none\".", 363 }, 364 { 365 name: "invalid platform.baremetal for architecture s390x", 366 data: ` 367 apiVersion: v1 368 metadata: 369 name: test-cluster 370 baseDomain: test-domain 371 networking: 372 networkType: OVNKubernetes 373 machineNetwork: 374 - cidr: 192.168.122.0/23 375 compute: 376 - architecture: s390x 377 hyperthreading: Enabled 378 name: worker 379 platform: {} 380 replicas: 0 381 controlPlane: 382 architecture: s390x 383 hyperthreading: Enabled 384 name: master 385 platform: {} 386 replicas: 3 387 platform: 388 baremetal: 389 apiVIP: 192.168.122.10 390 ingressVIP: 192.168.122.11 391 hosts: 392 - name: host1 393 bootMACAddress: 52:54:01:aa:aa:a1 394 - name: host2 395 bootMACAddress: 52:54:01:bb:bb:b1 396 - name: host3 397 bootMACAddress: 52:54:01:cc:cc:c1 398 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 399 `, 400 expectedFound: false, 401 expectedError: "invalid install-config configuration: Platform: Invalid value: \"baremetal\": CPU architecture \"s390x\" only supports platform \"none\".", 402 }, 403 { 404 name: "generic platformName for external platform", 405 data: ` 406 apiVersion: v1 407 metadata: 408 name: test-cluster 409 baseDomain: test-domain 410 networking: 411 networkType: OVNKubernetes 412 compute: 413 - architecture: amd64 414 hyperthreading: Enabled 415 name: worker 416 platform: {} 417 replicas: 0 418 controlPlane: 419 architecture: amd64 420 hyperthreading: Enabled 421 name: master 422 platform: {} 423 replicas: 1 424 platform: 425 external: 426 platformName: some-cloud-provider 427 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 428 `, 429 expectedFound: true, 430 expectedConfig: &types.InstallConfig{ 431 TypeMeta: metav1.TypeMeta{ 432 APIVersion: types.InstallConfigVersion, 433 }, 434 ObjectMeta: metav1.ObjectMeta{ 435 Name: "test-cluster", 436 }, 437 AdditionalTrustBundlePolicy: types.PolicyProxyOnly, 438 BaseDomain: "test-domain", 439 Networking: &types.Networking{ 440 MachineNetwork: []types.MachineNetworkEntry{ 441 {CIDR: *ipnet.MustParseCIDR("10.0.0.0/16")}, 442 }, 443 NetworkType: "OVNKubernetes", 444 ServiceNetwork: []ipnet.IPNet{*ipnet.MustParseCIDR("172.30.0.0/16")}, 445 ClusterNetwork: []types.ClusterNetworkEntry{ 446 { 447 CIDR: *ipnet.MustParseCIDR("10.128.0.0/14"), 448 HostPrefix: 23, 449 }, 450 }, 451 }, 452 ControlPlane: &types.MachinePool{ 453 Name: "master", 454 Replicas: pointer.Int64(1), 455 Hyperthreading: types.HyperthreadingEnabled, 456 Architecture: types.ArchitectureAMD64, 457 }, 458 Compute: []types.MachinePool{ 459 { 460 Name: "worker", 461 Replicas: pointer.Int64(0), 462 Hyperthreading: types.HyperthreadingEnabled, 463 Architecture: types.ArchitectureAMD64, 464 }, 465 }, 466 Platform: types.Platform{ 467 External: &external.Platform{ 468 PlatformName: "some-cloud-provider", 469 CloudControllerManager: "", 470 }, 471 }, 472 PullSecret: `{"auths":{"example.com":{"auth":"c3VwZXItc2VjcmV0Cg=="}}}`, 473 Publish: types.ExternalPublishingStrategy, 474 }, 475 }, 476 { 477 name: "unsupported CloudControllerManager for external platform", 478 data: ` 479 apiVersion: v1 480 metadata: 481 name: test-cluster 482 baseDomain: test-domain 483 platform: 484 external: 485 platformName: oci 486 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 487 `, 488 expectedFound: false, 489 expectedError: `invalid install-config configuration: Platform.External.CloudControllerManager: Invalid value: "": When using external oci platform, Platform.External.CloudControllerManager must be set to External`, 490 }, 491 { 492 name: "valid configuration for none platform for sno", 493 data: ` 494 apiVersion: v1 495 metadata: 496 name: test-cluster 497 baseDomain: test-domain 498 networking: 499 networkType: OVNKubernetes 500 compute: 501 - architecture: amd64 502 hyperthreading: Enabled 503 name: worker 504 platform: {} 505 replicas: 0 506 controlPlane: 507 architecture: amd64 508 hyperthreading: Enabled 509 name: master 510 platform: {} 511 replicas: 1 512 platform: 513 none : {} 514 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 515 `, 516 expectedFound: true, 517 expectedConfig: &types.InstallConfig{ 518 TypeMeta: metav1.TypeMeta{ 519 APIVersion: types.InstallConfigVersion, 520 }, 521 ObjectMeta: metav1.ObjectMeta{ 522 Name: "test-cluster", 523 }, 524 AdditionalTrustBundlePolicy: types.PolicyProxyOnly, 525 BaseDomain: "test-domain", 526 Networking: &types.Networking{ 527 MachineNetwork: []types.MachineNetworkEntry{ 528 {CIDR: *ipnet.MustParseCIDR("10.0.0.0/16")}, 529 }, 530 NetworkType: "OVNKubernetes", 531 ServiceNetwork: []ipnet.IPNet{*ipnet.MustParseCIDR("172.30.0.0/16")}, 532 ClusterNetwork: []types.ClusterNetworkEntry{ 533 { 534 CIDR: *ipnet.MustParseCIDR("10.128.0.0/14"), 535 HostPrefix: 23, 536 }, 537 }, 538 }, 539 ControlPlane: &types.MachinePool{ 540 Name: "master", 541 Replicas: pointer.Int64(1), 542 Hyperthreading: types.HyperthreadingEnabled, 543 Architecture: types.ArchitectureAMD64, 544 }, 545 Compute: []types.MachinePool{ 546 { 547 Name: "worker", 548 Replicas: pointer.Int64(0), 549 Hyperthreading: types.HyperthreadingEnabled, 550 Architecture: types.ArchitectureAMD64, 551 }, 552 }, 553 Platform: types.Platform{None: &none.Platform{}}, 554 PullSecret: `{"auths":{"example.com":{"auth":"c3VwZXItc2VjcmV0Cg=="}}}`, 555 Publish: types.ExternalPublishingStrategy, 556 }, 557 }, 558 { 559 name: "valid configuration for none platform for HA cluster", 560 data: ` 561 apiVersion: v1 562 metadata: 563 name: test-cluster 564 baseDomain: test-domain 565 networking: 566 networkType: OVNKubernetes 567 compute: 568 - architecture: amd64 569 hyperthreading: Enabled 570 name: worker 571 platform: {} 572 replicas: 2 573 controlPlane: 574 architecture: amd64 575 hyperthreading: Enabled 576 name: master 577 platform: {} 578 replicas: 3 579 platform: 580 none : {} 581 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 582 `, 583 expectedFound: true, 584 expectedConfig: &types.InstallConfig{ 585 TypeMeta: metav1.TypeMeta{ 586 APIVersion: types.InstallConfigVersion, 587 }, 588 ObjectMeta: metav1.ObjectMeta{ 589 Name: "test-cluster", 590 }, 591 AdditionalTrustBundlePolicy: types.PolicyProxyOnly, 592 BaseDomain: "test-domain", 593 Networking: &types.Networking{ 594 MachineNetwork: []types.MachineNetworkEntry{ 595 {CIDR: *ipnet.MustParseCIDR("10.0.0.0/16")}, 596 }, 597 NetworkType: "OVNKubernetes", 598 ServiceNetwork: []ipnet.IPNet{*ipnet.MustParseCIDR("172.30.0.0/16")}, 599 ClusterNetwork: []types.ClusterNetworkEntry{ 600 { 601 CIDR: *ipnet.MustParseCIDR("10.128.0.0/14"), 602 HostPrefix: 23, 603 }, 604 }, 605 }, 606 ControlPlane: &types.MachinePool{ 607 Name: "master", 608 Replicas: pointer.Int64(3), 609 Hyperthreading: types.HyperthreadingEnabled, 610 Architecture: types.ArchitectureAMD64, 611 }, 612 Compute: []types.MachinePool{ 613 { 614 Name: "worker", 615 Replicas: pointer.Int64(2), 616 Hyperthreading: types.HyperthreadingEnabled, 617 Architecture: types.ArchitectureAMD64, 618 }, 619 }, 620 Platform: types.Platform{None: &none.Platform{}}, 621 PullSecret: `{"auths":{"example.com":{"auth":"c3VwZXItc2VjcmV0Cg=="}}}`, 622 Publish: types.ExternalPublishingStrategy, 623 }, 624 }, 625 { 626 name: "valid configuration for baremetal platform for HA cluster - deprecated and unused fields", 627 data: ` 628 apiVersion: v1 629 metadata: 630 name: test-cluster 631 baseDomain: test-domain 632 networking: 633 clusterNetwork: 634 - cidr: 10.128.0.0/14 635 hostPrefix: 23 636 networkType: OVNKubernetes 637 machineNetwork: 638 - cidr: 192.168.122.0/23 639 serviceNetwork: 640 - 172.30.0.0/16 641 compute: 642 - architecture: amd64 643 hyperthreading: Disabled 644 name: worker 645 platform: {} 646 replicas: 2 647 controlPlane: 648 architecture: amd64 649 hyperthreading: Disabled 650 name: master 651 platform: {} 652 replicas: 3 653 platform: 654 baremetal: 655 libvirtURI: qemu+ssh://root@52.116.73.24/system 656 clusterProvisioningIP: "192.168.122.90" 657 bootstrapProvisioningIP: "192.168.122.91" 658 externalBridge: "somevalue" 659 externalMACAddress: "52:54:00:f6:b4:02" 660 provisioningNetwork: "Disabled" 661 provisioningBridge: br0 662 provisioningMACAddress: "52:54:00:6e:3b:02" 663 provisioningNetworkInterface: "eth11" 664 provisioningDHCPExternal: true 665 provisioningDHCPRange: 172.22.0.10,172.22.0.254 666 apiVIP: 192.168.122.10 667 ingressVIP: 192.168.122.11 668 bootstrapOSImage: https://mirror.example.com/images/qemu.qcow2.gz?sha256=a07bd 669 clusterOSImage: https://mirror.example.com/images/metal.qcow2.gz?sha256=3b5a8 670 bootstrapExternalStaticIP: 192.1168.122.50 671 bootstrapExternalStaticGateway: gateway 672 hosts: 673 - name: host1 674 bootMACAddress: 52:54:01:aa:aa:a1 675 - name: host2 676 bootMACAddress: 52:54:01:bb:bb:b1 677 - name: host3 678 bootMACAddress: 52:54:01:cc:cc:c1 679 - name: host4 680 bootMACAddress: 52:54:01:dd:dd:d1 681 - name: host5 682 bootMACAddress: 52:54:01:ee:ee:e1 683 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 684 `, 685 expectedFound: true, 686 expectedConfig: &types.InstallConfig{ 687 TypeMeta: metav1.TypeMeta{ 688 APIVersion: types.InstallConfigVersion, 689 }, 690 ObjectMeta: metav1.ObjectMeta{ 691 Name: "test-cluster", 692 }, 693 AdditionalTrustBundlePolicy: types.PolicyProxyOnly, 694 BaseDomain: "test-domain", 695 Networking: &types.Networking{ 696 MachineNetwork: []types.MachineNetworkEntry{ 697 {CIDR: *ipnet.MustParseCIDR("192.168.122.0/23")}, 698 }, 699 NetworkType: "OVNKubernetes", 700 ServiceNetwork: []ipnet.IPNet{*ipnet.MustParseCIDR("172.30.0.0/16")}, 701 ClusterNetwork: []types.ClusterNetworkEntry{ 702 { 703 CIDR: *ipnet.MustParseCIDR("10.128.0.0/14"), 704 HostPrefix: 23, 705 }, 706 }, 707 }, 708 ControlPlane: &types.MachinePool{ 709 Name: "master", 710 Replicas: pointer.Int64(3), 711 Hyperthreading: types.HyperthreadingDisabled, 712 Architecture: types.ArchitectureAMD64, 713 }, 714 Compute: []types.MachinePool{ 715 { 716 Name: "worker", 717 Replicas: pointer.Int64(2), 718 Hyperthreading: types.HyperthreadingDisabled, 719 Architecture: types.ArchitectureAMD64, 720 }, 721 }, 722 Platform: types.Platform{ 723 BareMetal: &baremetal.Platform{ 724 LibvirtURI: "qemu+ssh://root@52.116.73.24/system", 725 ClusterProvisioningIP: "192.168.122.90", 726 BootstrapProvisioningIP: "192.168.122.91", 727 ExternalBridge: "somevalue", 728 ExternalMACAddress: "52:54:00:f6:b4:02", 729 ProvisioningNetwork: "Disabled", 730 ProvisioningBridge: "br0", 731 ProvisioningMACAddress: "52:54:00:6e:3b:02", 732 ProvisioningDHCPRange: "172.22.0.10,172.22.0.254", 733 DeprecatedProvisioningDHCPExternal: true, 734 ProvisioningNetworkCIDR: &ipnet.IPNet{ 735 IPNet: net.IPNet{ 736 IP: []byte("\xc0\xa8\x7a\x00"), 737 Mask: []byte("\xff\xff\xfe\x00"), 738 }, 739 }, 740 ProvisioningNetworkInterface: "eth11", 741 Hosts: []*baremetal.Host{ 742 { 743 Name: "host1", 744 BootMACAddress: "52:54:01:aa:aa:a1", 745 BootMode: "UEFI", 746 HardwareProfile: "default", 747 }, 748 { 749 Name: "host2", 750 BootMACAddress: "52:54:01:bb:bb:b1", 751 BootMode: "UEFI", 752 HardwareProfile: "default", 753 }, 754 { 755 Name: "host3", 756 BootMACAddress: "52:54:01:cc:cc:c1", 757 BootMode: "UEFI", 758 HardwareProfile: "default", 759 }, 760 { 761 Name: "host4", 762 BootMACAddress: "52:54:01:dd:dd:d1", 763 BootMode: "UEFI", 764 HardwareProfile: "default", 765 }, 766 { 767 Name: "host5", 768 BootMACAddress: "52:54:01:ee:ee:e1", 769 BootMode: "UEFI", 770 HardwareProfile: "default", 771 }}, 772 DeprecatedAPIVIP: "192.168.122.10", 773 APIVIPs: []string{"192.168.122.10"}, 774 DeprecatedIngressVIP: "192.168.122.11", 775 IngressVIPs: []string{"192.168.122.11"}, 776 BootstrapOSImage: "https://mirror.example.com/images/qemu.qcow2.gz?sha256=a07bd", 777 ClusterOSImage: "https://mirror.example.com/images/metal.qcow2.gz?sha256=3b5a8", 778 BootstrapExternalStaticIP: "192.1168.122.50", 779 BootstrapExternalStaticGateway: "gateway", 780 }, 781 }, 782 PullSecret: `{"auths":{"example.com":{"auth":"c3VwZXItc2VjcmV0Cg=="}}}`, 783 Publish: types.ExternalPublishingStrategy, 784 }, 785 }, 786 { 787 name: "valid configuration for vsphere platform for compact cluster - deprecated field apiVip", 788 data: ` 789 apiVersion: v1 790 metadata: 791 name: test-cluster 792 baseDomain: test-domain 793 networking: 794 clusterNetwork: 795 - cidr: 10.128.0.0/14 796 hostPrefix: 23 797 networkType: OVNKubernetes 798 machineNetwork: 799 - cidr: 192.168.122.0/23 800 serviceNetwork: 801 - 172.30.0.0/16 802 compute: 803 - architecture: amd64 804 hyperthreading: Enabled 805 name: worker 806 platform: {} 807 replicas: 0 808 controlPlane: 809 architecture: amd64 810 hyperthreading: Enabled 811 name: master 812 platform: {} 813 replicas: 3 814 platform: 815 vsphere : 816 vcenter: 192.168.122.30 817 username: testUsername 818 password: testPassword 819 datacenter: testDataCenter 820 defaultDataStore: testDefaultDataStore 821 folder: testFolder 822 cluster: testCluster 823 apiVIP: 192.168.122.10 824 ingressVIPs: 825 - 192.168.122.11 826 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 827 `, 828 expectedFound: true, 829 expectedConfig: &types.InstallConfig{ 830 TypeMeta: metav1.TypeMeta{ 831 APIVersion: types.InstallConfigVersion, 832 }, 833 ObjectMeta: metav1.ObjectMeta{ 834 Name: "test-cluster", 835 }, 836 AdditionalTrustBundlePolicy: types.PolicyProxyOnly, 837 BaseDomain: "test-domain", 838 Networking: &types.Networking{ 839 MachineNetwork: []types.MachineNetworkEntry{ 840 {CIDR: *ipnet.MustParseCIDR("192.168.122.0/23")}, 841 }, 842 NetworkType: "OVNKubernetes", 843 ServiceNetwork: []ipnet.IPNet{*ipnet.MustParseCIDR("172.30.0.0/16")}, 844 ClusterNetwork: []types.ClusterNetworkEntry{ 845 { 846 CIDR: *ipnet.MustParseCIDR("10.128.0.0/14"), 847 HostPrefix: 23, 848 }, 849 }, 850 }, 851 ControlPlane: &types.MachinePool{ 852 Name: "master", 853 Replicas: pointer.Int64(3), 854 Hyperthreading: types.HyperthreadingEnabled, 855 Architecture: types.ArchitectureAMD64, 856 }, 857 Compute: []types.MachinePool{ 858 { 859 Name: "worker", 860 Replicas: pointer.Int64(0), 861 Hyperthreading: types.HyperthreadingEnabled, 862 Architecture: types.ArchitectureAMD64, 863 }, 864 }, 865 Platform: types.Platform{ 866 VSphere: &vsphere.Platform{ 867 DeprecatedVCenter: "192.168.122.30", 868 DeprecatedUsername: "testUsername", 869 DeprecatedPassword: "testPassword", 870 DeprecatedDatacenter: "testDataCenter", 871 DeprecatedCluster: "testCluster", 872 DeprecatedDefaultDatastore: "testDefaultDataStore", 873 DeprecatedFolder: "testFolder", 874 DeprecatedAPIVIP: "192.168.122.10", 875 APIVIPs: []string{"192.168.122.10"}, 876 IngressVIPs: []string{"192.168.122.11"}, 877 VCenters: []vsphere.VCenter{{ 878 Server: "192.168.122.30", 879 Port: 443, 880 Username: "testUsername", 881 Password: "testPassword", 882 Datacenters: []string{"testDataCenter"}, 883 }}, 884 FailureDomains: []vsphere.FailureDomain{{ 885 Name: "generated-failure-domain", 886 Region: "generated-region", 887 Zone: "generated-zone", 888 Server: "192.168.122.30", 889 Topology: vsphere.Topology{ 890 Datacenter: "testDataCenter", 891 ComputeCluster: "/testDataCenter/host/testCluster", 892 Networks: []string{""}, 893 Datastore: "/testDataCenter/datastore/testDefaultDataStore", 894 ResourcePool: "/testDataCenter/host/testCluster/Resources", 895 Folder: "/testDataCenter/vm/testFolder", 896 }, 897 }}, 898 }, 899 }, 900 PullSecret: `{"auths":{"example.com":{"auth":"c3VwZXItc2VjcmV0Cg=="}}}`, 901 Publish: types.ExternalPublishingStrategy, 902 }, 903 }, 904 { 905 name: "provisioningNetwork invalid for baremetal cluster", 906 data: ` 907 apiVersion: v1 908 metadata: 909 name: test-cluster 910 baseDomain: test-domain 911 networking: 912 clusterNetwork: 913 - cidr: 10.128.0.0/14 914 hostPrefix: 23 915 networkType: OVNKubernetes 916 machineNetwork: 917 - cidr: 192.168.122.0/23 918 serviceNetwork: 919 - 172.30.0.0/16 920 compute: 921 - architecture: amd64 922 name: worker 923 replicas: 0 924 controlPlane: 925 architecture: amd64 926 name: master 927 replicas: 3 928 platform: 929 baremetal: 930 provisioningNetwork: "UNMANAGED" 931 ingressVIPs: 932 - 192.168.122.11 933 apiVIPs: 934 - 192.168.122.10 935 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 936 `, 937 expectedFound: false, 938 expectedError: "invalid install-config configuration: platform.baremetal.provisioningNetwork: Unsupported value: \"UNMANAGED\": supported values: \"Disabled\", \"Managed\", \"Unmanaged\"", 939 }, 940 { 941 name: "Provisioning validation failures for baremetal cluster", 942 data: ` 943 apiVersion: v1 944 metadata: 945 name: test-cluster 946 baseDomain: test-domain 947 networking: 948 clusterNetwork: 949 - cidr: 10.128.0.0/14 950 hostPrefix: 23 951 networkType: OVNKubernetes 952 machineNetwork: 953 - cidr: 192.168.122.0/23 954 serviceNetwork: 955 - 172.30.0.0/16 956 compute: 957 - architecture: amd64 958 name: worker 959 replicas: 0 960 controlPlane: 961 architecture: amd64 962 name: master 963 replicas: 3 964 platform: 965 baremetal: 966 ingressVIPs: 967 - 192.168.122.11 968 apiVIPs: 969 - 192.168.122.10 970 clusterProvisioningIP: "172.22.0.11" 971 provisioningNetwork: "Managed" 972 provisioningMACAddress: "52:54:00:6e:3b:02" 973 provisioningNetworkInterface: "eth11" 974 provisioningDHCPExternal: true 975 provisioningDHCPRange: 172.22.0.10,172.22.0.254 976 hosts: 977 - name: host1 978 bootMACAddress: 52:54:01:aa:aa:a1 979 bmc: 980 username: "admin" 981 password: "password" 982 address: "redfish+http://10.10.10.1:8000/redfish/v1/Systems/1234" 983 - name: host2 984 bootMACAddress: 52:54:01:bb:bb:b1 985 bmc: 986 username: "admin" 987 password: "password" 988 address: "redfish+http://10.10.10.2:8000/redfish/v1/Systems/1234" 989 - name: host3 990 bootMACAddress: 52:54:01:cc:cc:c1 991 bmc: 992 username: "admin" 993 password: "password" 994 address: "redfish+http://10.10.10.2:8000/redfish/v1/Systems/1234" 995 pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}" 996 `, 997 expectedFound: false, 998 expectedError: `invalid install-config configuration: [Platform.BareMetal.clusterProvisioningIP: Invalid value: "172.22.0.11": "172.22.0.11" overlaps with the allocated DHCP range, Platform.BareMetal.hosts[2].BMC.Address: Duplicate value: "redfish+http://10.10.10.2:8000/redfish/v1/Systems/1234"]`, 999 }, 1000 } 1001 for _, tc := range cases { 1002 t.Run(tc.name, func(t *testing.T) { 1003 mockCtrl := gomock.NewController(t) 1004 defer mockCtrl.Finish() 1005 1006 fileFetcher := mock.NewMockFileFetcher(mockCtrl) 1007 fileFetcher.EXPECT().FetchByName(InstallConfigFilename). 1008 Return( 1009 &asset.File{ 1010 Filename: InstallConfigFilename, 1011 Data: []byte(tc.data)}, 1012 tc.fetchError, 1013 ).MaxTimes(2) 1014 1015 asset := &OptionalInstallConfig{} 1016 found, err := asset.Load(fileFetcher) 1017 assert.Equal(t, tc.expectedFound, found, "unexpected found value returned from Load") 1018 if tc.expectedError != "" { 1019 assert.Equal(t, tc.expectedError, err.Error()) 1020 } else { 1021 assert.NoError(t, err) 1022 } 1023 if tc.expectedFound { 1024 assert.Equal(t, tc.expectedConfig, asset.Config, "unexpected Config in InstallConfig") 1025 } 1026 }) 1027 } 1028 }