github.com/openshift/installer@v1.4.17/pkg/asset/agent/manifests/util_test.go (about) 1 package manifests 2 3 import ( 4 "net" 5 "strings" 6 7 corev1 "k8s.io/api/core/v1" 8 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 "k8s.io/utils/pointer" 10 "sigs.k8s.io/yaml" 11 12 hiveext "github.com/openshift/assisted-service/api/hiveextension/v1beta1" 13 "github.com/openshift/assisted-service/api/v1beta1" 14 hivev1 "github.com/openshift/hive/apis/hive/v1" 15 "github.com/openshift/installer/pkg/asset/agent" 16 "github.com/openshift/installer/pkg/asset/agent/agentconfig" 17 "github.com/openshift/installer/pkg/asset/installconfig" 18 "github.com/openshift/installer/pkg/ipnet" 19 "github.com/openshift/installer/pkg/types" 20 agenttypes "github.com/openshift/installer/pkg/types/agent" 21 "github.com/openshift/installer/pkg/types/baremetal" 22 ) 23 24 var ( 25 testSSHKey = `| 26 ssh-rsa AAAAB3NzaC1y1LJe3zew1ghc= root@localhost.localdomain` 27 testSecret = `{"auths":{"cloud.openshift.com":{"auth":"b3BlUTA=","email":"test@redhat.com"}}}` //nolint:gosec // not real credentials 28 29 rawNMStateConfig = ` 30 interfaces: 31 - name: eth0 32 type: ethernet 33 state: up 34 mac-address: 52:54:01:aa:aa:a1 35 ipv4: 36 enabled: true 37 address: 38 - ip: 192.168.122.21 39 prefix-length: 24 40 dhcp: false 41 dns-resolver: 42 config: 43 server: 44 - 192.168.122.1 45 routes: 46 config: 47 - destination: 0.0.0.0/0 48 next-hop-address: 192.168.122.1 49 next-hop-interface: eth0 50 table-id: 254` 51 52 rawNMStateConfigNoIP = ` 53 interfaces: 54 - name: eth0 55 type: ethernet 56 state: up 57 mac-address: 52:54:01:aa:aa:a1` 58 59 // config with route but no interface is invalid. 60 invalidRawNMStateConfig = ` 61 routes: 62 config: 63 - destination: 0.0.0.0/0 64 next-hop-address: 192.168.122.1 65 next-hop-interface: eth0 66 table-id: 254` 67 ) 68 69 // GetValidOptionalInstallConfig returns a valid optional install config 70 func getValidOptionalInstallConfig() *agent.OptionalInstallConfig { 71 _, newCidr, _ := net.ParseCIDR("192.168.111.0/24") 72 _, machineNetCidr, _ := net.ParseCIDR("10.10.11.0/24") 73 74 return &agent.OptionalInstallConfig{ 75 AssetBase: installconfig.AssetBase{ 76 Config: &types.InstallConfig{ 77 ObjectMeta: metav1.ObjectMeta{ 78 Name: "ocp-edge-cluster-0", 79 Namespace: "cluster-0", 80 }, 81 BaseDomain: "testing.com", 82 PullSecret: testSecret, 83 SSHKey: testSSHKey, 84 ControlPlane: &types.MachinePool{ 85 Name: "master", 86 Replicas: pointer.Int64Ptr(3), 87 Platform: types.MachinePoolPlatform{}, 88 }, 89 Compute: []types.MachinePool{ 90 { 91 Name: "worker-machine-pool-1", 92 Replicas: pointer.Int64Ptr(2), 93 }, 94 { 95 Name: "worker-machine-pool-2", 96 Replicas: pointer.Int64Ptr(3), 97 }, 98 }, 99 Networking: &types.Networking{ 100 MachineNetwork: []types.MachineNetworkEntry{ 101 { 102 CIDR: ipnet.IPNet{IPNet: *machineNetCidr}, 103 }, 104 }, 105 ClusterNetwork: []types.ClusterNetworkEntry{ 106 { 107 CIDR: ipnet.IPNet{IPNet: *newCidr}, 108 HostPrefix: 23, 109 }, 110 }, 111 ServiceNetwork: []ipnet.IPNet{ 112 *ipnet.MustParseCIDR("172.30.0.0/16"), 113 }, 114 NetworkType: "OVNKubernetes", 115 }, 116 Platform: types.Platform{ 117 BareMetal: &baremetal.Platform{ 118 APIVIPs: []string{"192.168.122.10"}, 119 IngressVIPs: []string{"192.168.122.11"}, 120 }, 121 }, 122 }, 123 }, 124 Supplied: true, 125 } 126 } 127 128 // GetValidOptionalInstallConfigDualStack returns a valid optional install config for dual stack 129 func getValidOptionalInstallConfigDualStack() *agent.OptionalInstallConfig { 130 _, newCidr, _ := net.ParseCIDR("192.168.111.0/24") 131 _, newCidrIPv6, _ := net.ParseCIDR("2001:db8:1111:2222::/64") 132 _, machineNetCidr, _ := net.ParseCIDR("10.10.11.0/24") 133 _, machineNetCidrIPv6, _ := net.ParseCIDR("2001:db8:5dd8:c956::/64") 134 135 return &agent.OptionalInstallConfig{ 136 AssetBase: installconfig.AssetBase{ 137 Config: &types.InstallConfig{ 138 ObjectMeta: metav1.ObjectMeta{ 139 Name: "ocp-edge-cluster-0", 140 Namespace: "cluster-0", 141 }, 142 BaseDomain: "testing.com", 143 PullSecret: testSecret, 144 SSHKey: testSSHKey, 145 ControlPlane: &types.MachinePool{ 146 Name: "master", 147 Replicas: pointer.Int64Ptr(3), 148 Platform: types.MachinePoolPlatform{}, 149 }, 150 Compute: []types.MachinePool{ 151 { 152 Name: "worker-machine-pool-1", 153 Replicas: pointer.Int64Ptr(2), 154 }, 155 { 156 Name: "worker-machine-pool-2", 157 Replicas: pointer.Int64Ptr(3), 158 }, 159 }, 160 Networking: &types.Networking{ 161 MachineNetwork: []types.MachineNetworkEntry{ 162 { 163 CIDR: ipnet.IPNet{IPNet: *machineNetCidr}, 164 }, 165 { 166 CIDR: ipnet.IPNet{IPNet: *machineNetCidrIPv6}, 167 }, 168 }, 169 ClusterNetwork: []types.ClusterNetworkEntry{ 170 { 171 CIDR: ipnet.IPNet{IPNet: *newCidr}, 172 HostPrefix: 23, 173 }, 174 { 175 CIDR: ipnet.IPNet{IPNet: *newCidrIPv6}, 176 HostPrefix: 64, 177 }, 178 }, 179 ServiceNetwork: []ipnet.IPNet{ 180 *ipnet.MustParseCIDR("172.30.0.0/16"), *ipnet.MustParseCIDR("fd02::/112"), 181 }, 182 }, 183 Platform: types.Platform{ 184 BareMetal: &baremetal.Platform{ 185 APIVIPs: []string{"192.168.122.10"}, 186 IngressVIPs: []string{"192.168.122.11"}, 187 }, 188 }, 189 }, 190 }, 191 Supplied: true, 192 } 193 } 194 195 func getValidOptionalInstallConfigDualStackDualVIPs() *agent.OptionalInstallConfig { 196 installConfig := getValidOptionalInstallConfigDualStack() 197 installConfig.Config.Platform.BareMetal.APIVIPs = append(installConfig.Config.Platform.BareMetal.APIVIPs, "2001:db8:1111:2222:ffff:ffff:ffff:cafe") 198 installConfig.Config.Platform.BareMetal.IngressVIPs = append(installConfig.Config.Platform.BareMetal.IngressVIPs, "2001:db8:1111:2222:ffff:ffff:ffff:dead") 199 return installConfig 200 } 201 202 // getProxyValidOptionalInstallConfig returns a valid optional install config for proxied installation 203 func getProxyValidOptionalInstallConfig() *agent.OptionalInstallConfig { 204 validIC := getValidOptionalInstallConfig() 205 validIC.Config.Proxy = &types.Proxy{ 206 HTTPProxy: "http://10.10.10.11:80", 207 HTTPSProxy: "http://my-lab-proxy.org:443", 208 NoProxy: "internal.com", 209 } 210 return validIC 211 } 212 213 // getAdditionalTrustBundleValidOptionalInstallConfig returns a valid optional install config with AdditonalTrustBundle. 214 func getAdditionalTrustBundleValidOptionalInstallConfig() *agent.OptionalInstallConfig { 215 validIC := getValidOptionalInstallConfig() 216 validIC.Config.AdditionalTrustBundle = `-----BEGIN CERTIFICATE-----MIIDZTCCAk2gAwIBAgIURbA8lR+5xlJZUoOXK66AHFWd3uswDQYJKoZIhvcNAQELBQAwQjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDAeFw0yMjA3MDgxOTUzMTVaFw0yMjA4MDcxOTUzMTVaMEIxCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCroH9c2PLWI0O/nBrmKtS2IuReyWaR0DOMJY7C/vc12l9zlH0DxTOUfEtdqRktjVsUn1vIIiFakxd0QLIPcMyKplmbavIBUQp+MZr0pNVX+lwcctbA7FVHEnbWYNVepoV7kZkTVvMXAqFylMXU4gDmuZzIxhVMMxjialJNED+3ngqvX4w34q4KSk1ytaHGwjREIErwPJjv5PK48KVJL2nlCuA+tbxu1r8eVkOUvZlxAuNNXk/Umf3QX5EiUlTtsmRAct6fIUT3jkrsHSS/tZ66EYJ9Q0OBoX2lL/Msmi27OQvA7uYnuqYlwJzU43tCsiip9E9z/UrLcMYyXx3oPJyPAgMBAAGjUzBRMB0GA1UdDgQWBBTIahE8DDT4T1vta6cXVVaRjnel0zAfBgNVHSMEGDAWgBTIahE8DDT4T1vta6cXVVaRjnel0zAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCQbsMtPFkqPxwOAIds3IoupuyIKmsF32ECEH/OlS+7Sj7MUJnGTQrwgjrsVS5sl8AmnGx4hPdLVX98nEcKMNkph3Hkvh4EvgjSfmYGUXuJBcYU5jqNQrlrGv37rEf5FnvdHV1F3MG8A0Mj0TLtcTdtaJFoOrnQuD/k0/1d+cMiYGTSaT5XK/unARqGEMd4BlWPh5P3SflV/Vy2hHlMpv7OcZ8yaAI3htENZLus+L5kjHWKu6dxlPHKu6ef5k64su2LTNE07Vr9S655uiFW5AX2wDVUcQEDCOiEn6SI9DTt5oQjWPMxPf+rEyfQ2f1QwVez7cyr6Qc5OIUk31HnM/Fj-----END CERTIFICATE-----` 217 return validIC 218 } 219 220 // getValidOptionalInstallConfigWithProvisioning returns a valid optional install config with baremetal provisioning network settings. 221 func getValidOptionalInstallConfigWithProvisioning() *agent.OptionalInstallConfig { 222 installConfig := getValidOptionalInstallConfig() 223 installConfig.Config.Platform.BareMetal.ClusterProvisioningIP = "172.22.0.3" 224 installConfig.Config.Platform.BareMetal.ProvisioningNetwork = "Managed" 225 installConfig.Config.Platform.BareMetal.ProvisioningBridge = "ostestpr" 226 installConfig.Config.Platform.BareMetal.ProvisioningMACAddress = "52:54:00:a6:e6:87" 227 installConfig.Config.Platform.BareMetal.ProvisioningNetworkInterface = "eth0" 228 installConfig.Config.Platform.BareMetal.ProvisioningNetworkCIDR = ipnet.MustParseCIDR("172.22.0.0/24") 229 installConfig.Config.Platform.BareMetal.ProvisioningDHCPRange = "172.22.0.10,172.22.0.254" 230 return installConfig 231 } 232 233 func getValidAgentConfig() *agentconfig.AgentConfig { 234 return &agentconfig.AgentConfig{ 235 Config: &agenttypes.Config{ 236 ObjectMeta: metav1.ObjectMeta{ 237 Name: "ocp-edge-cluster-0", 238 Namespace: "cluster-0", 239 }, 240 RendezvousIP: "192.168.122.2", 241 }, 242 } 243 } 244 245 func getValidAgentHostsConfig() *agentconfig.AgentHosts { 246 return &agentconfig.AgentHosts{ 247 Hosts: []agenttypes.Host{ 248 { 249 Hostname: "control-0.example.org", 250 Role: "master", 251 RootDeviceHints: baremetal.RootDeviceHints{ 252 DeviceName: "/dev/sda", 253 HCTL: "hctl-value", 254 Model: "model-value", 255 Vendor: "vendor-value", 256 SerialNumber: "serial-number-value", 257 MinSizeGigabytes: 20, 258 WWN: "wwn-value", 259 WWNWithExtension: "wwn-with-extension-value", 260 WWNVendorExtension: "wwn-vendor-extension-value", 261 Rotational: new(bool), 262 }, 263 Interfaces: []*v1beta1.Interface{ 264 { 265 Name: "enp2s0", 266 MacAddress: "98:af:65:a5:8d:01", 267 }, 268 { 269 Name: "enp3s1", 270 MacAddress: "28:d2:44:d2:b2:1a", 271 }, 272 }, 273 NetworkConfig: v1beta1.NetConfig{ 274 Raw: unmarshalJSON([]byte(rawNMStateConfig)), 275 }, 276 }, 277 { 278 Hostname: "control-1.example.org", 279 Role: "master", 280 RootDeviceHints: baremetal.RootDeviceHints{ 281 DeviceName: "/dev/sdb", 282 HCTL: "hctl-value", 283 Model: "model-value", 284 Vendor: "vendor-value", 285 SerialNumber: "serial-number-value", 286 MinSizeGigabytes: 40, 287 WWN: "wwn-value", 288 WWNWithExtension: "wwn-with-extension-value", 289 WWNVendorExtension: "wwn-vendor-extension-value", 290 Rotational: new(bool), 291 }, 292 Interfaces: []*v1beta1.Interface{ 293 { 294 Name: "enp2t0", 295 MacAddress: "98:af:65:a5:8d:02", 296 }, 297 }, 298 NetworkConfig: v1beta1.NetConfig{ 299 Raw: unmarshalJSON([]byte(rawNMStateConfig)), 300 }, 301 }, 302 { 303 Hostname: "control-2.example.org", 304 Role: "master", 305 RootDeviceHints: baremetal.RootDeviceHints{ 306 DeviceName: "/dev/sdc", 307 HCTL: "hctl-value", 308 Model: "model-value", 309 Vendor: "vendor-value", 310 SerialNumber: "serial-number-value", 311 MinSizeGigabytes: 60, 312 WWN: "wwn-value", 313 WWNWithExtension: "wwn-with-extension-value", 314 WWNVendorExtension: "wwn-vendor-extension-value", 315 Rotational: new(bool), 316 }, 317 Interfaces: []*v1beta1.Interface{ 318 { 319 Name: "enp2u0", 320 MacAddress: "98:af:65:a5:8d:03", 321 }, 322 }, 323 NetworkConfig: v1beta1.NetConfig{ 324 Raw: unmarshalJSON([]byte(rawNMStateConfig)), 325 }, 326 }, 327 }, 328 } 329 } 330 331 func getValidAgentConfigWithAdditionalNTPSources() *agentconfig.AgentConfig { 332 validAC := getValidAgentConfig() 333 validAC.Config.AdditionalNTPSources = []string{ 334 "0.fedora.pool.ntp.org", 335 "1.fedora.pool.ntp.org", 336 } 337 return validAC 338 } 339 340 func getAgentHostsWithSomeHostsWithoutNetworkConfig() *agentconfig.AgentHosts { 341 return &agentconfig.AgentHosts{ 342 Hosts: []agenttypes.Host{ 343 { 344 Hostname: "control-0.example.org", 345 Role: "master", 346 RootDeviceHints: baremetal.RootDeviceHints{ 347 DeviceName: "/dev/sda", 348 HCTL: "hctl-value", 349 Model: "model-value", 350 Vendor: "vendor-value", 351 SerialNumber: "serial-number-value", 352 MinSizeGigabytes: 20, 353 WWN: "wwn-value", 354 WWNWithExtension: "wwn-with-extension-value", 355 WWNVendorExtension: "wwn-vendor-extension-value", 356 Rotational: new(bool), 357 }, 358 Interfaces: []*v1beta1.Interface{ 359 { 360 Name: "enp2t0", 361 MacAddress: "98:af:65:a5:8d:02", 362 }, 363 }, 364 NetworkConfig: v1beta1.NetConfig{ 365 Raw: unmarshalJSON([]byte(rawNMStateConfigNoIP)), 366 }, 367 }, 368 { 369 Hostname: "control-1.example.org", 370 Role: "master", 371 RootDeviceHints: baremetal.RootDeviceHints{ 372 DeviceName: "/dev/sdb", 373 HCTL: "hctl-value", 374 Model: "model-value", 375 Vendor: "vendor-value", 376 SerialNumber: "serial-number-value", 377 MinSizeGigabytes: 40, 378 WWN: "wwn-value", 379 WWNWithExtension: "wwn-with-extension-value", 380 WWNVendorExtension: "wwn-vendor-extension-value", 381 Rotational: new(bool), 382 }, 383 Interfaces: []*v1beta1.Interface{ 384 { 385 Name: "enp2t0", 386 MacAddress: "98:af:65:a5:8d:03", 387 }, 388 }, 389 }, 390 }, 391 } 392 } 393 394 func getAgentHostsNoHosts() *agentconfig.AgentHosts { 395 return &agentconfig.AgentHosts{} 396 } 397 398 func getAgentHostsWithBMCConfig() *agentconfig.AgentHosts { 399 return &agentconfig.AgentHosts{ 400 Hosts: []agenttypes.Host{ 401 { 402 Hostname: "control-0.example.org", 403 Role: "master", 404 Interfaces: []*v1beta1.Interface{ 405 { 406 Name: "enp2s0", 407 MacAddress: "98:af:65:a5:8d:01", 408 }, 409 }, 410 BMC: baremetal.BMC{ 411 Username: "bmc-user", 412 Password: "password", 413 Address: "172.22.0.10", 414 DisableCertificateVerification: true, 415 }, 416 }, 417 { 418 Hostname: "control-1.example.org", 419 Role: "master", 420 Interfaces: []*v1beta1.Interface{ 421 { 422 Name: "enp2s0", 423 MacAddress: "98:af:65:a5:8d:02", 424 }, 425 }, 426 BMC: baremetal.BMC{ 427 Username: "user2", 428 Password: "foo", 429 Address: "172.22.0.11", 430 DisableCertificateVerification: false, 431 }, 432 }, 433 { 434 Hostname: "control-2.example.org", 435 Role: "master", 436 Interfaces: []*v1beta1.Interface{ 437 { 438 Name: "enp2s0", 439 MacAddress: "98:af:65:a5:8d:03", 440 }, 441 }, 442 BMC: baremetal.BMC{ 443 Username: "admin", 444 Password: "bar", 445 Address: "172.22.0.12", 446 DisableCertificateVerification: true, 447 }, 448 }, 449 }, 450 } 451 } 452 453 func getGoodACI() *hiveext.AgentClusterInstall { 454 goodACI := &hiveext.AgentClusterInstall{ 455 TypeMeta: metav1.TypeMeta{ 456 Kind: "AgentClusterInstall", 457 APIVersion: "extensions.hive.openshift.io/v1beta1", 458 }, 459 ObjectMeta: metav1.ObjectMeta{ 460 Name: getAgentClusterInstallName(getValidOptionalInstallConfig()), 461 Namespace: getValidOptionalInstallConfig().ClusterNamespace(), 462 }, 463 Spec: hiveext.AgentClusterInstallSpec{ 464 ImageSetRef: &hivev1.ClusterImageSetReference{ 465 Name: getClusterImageSetReferenceName(), 466 }, 467 ClusterDeploymentRef: corev1.LocalObjectReference{ 468 Name: getClusterDeploymentName(getValidOptionalInstallConfig()), 469 }, 470 Networking: hiveext.Networking{ 471 MachineNetwork: []hiveext.MachineNetworkEntry{ 472 { 473 CIDR: "10.10.11.0/24", 474 }, 475 }, 476 ClusterNetwork: []hiveext.ClusterNetworkEntry{ 477 { 478 CIDR: "192.168.111.0/24", 479 HostPrefix: 23, 480 }, 481 }, 482 ServiceNetwork: []string{"172.30.0.0/16"}, 483 NetworkType: "OVNKubernetes", 484 }, 485 SSHPublicKey: strings.Trim(testSSHKey, "|\n\t"), 486 ProvisionRequirements: hiveext.ProvisionRequirements{ 487 ControlPlaneAgents: 3, 488 WorkerAgents: 5, 489 }, 490 APIVIPs: []string{"192.168.122.10"}, 491 IngressVIPs: []string{"192.168.122.11"}, 492 APIVIP: "192.168.122.10", 493 IngressVIP: "192.168.122.11", 494 PlatformType: hiveext.BareMetalPlatformType, 495 }, 496 } 497 return goodACI 498 } 499 500 func getInValidAgentHostsConfig() *agentconfig.AgentHosts { 501 return &agentconfig.AgentHosts{ 502 Hosts: []agenttypes.Host{ 503 { 504 Hostname: "control-0.example.org", 505 Role: "master", 506 Interfaces: []*v1beta1.Interface{ 507 { 508 Name: "enp2s0", 509 MacAddress: "98:af:65:a5:8d:01", 510 }, 511 }, 512 NetworkConfig: v1beta1.NetConfig{ 513 Raw: unmarshalJSON([]byte(invalidRawNMStateConfig)), 514 }, 515 }, 516 }, 517 } 518 } 519 520 func getGoodACIDualStack() *hiveext.AgentClusterInstall { 521 goodACI := getGoodACI() 522 goodACI.Spec.Networking.MachineNetwork = append(goodACI.Spec.Networking.MachineNetwork, hiveext.MachineNetworkEntry{ 523 CIDR: "2001:db8:5dd8:c956::/64", 524 }) 525 goodACI.Spec.Networking.ClusterNetwork = append(goodACI.Spec.Networking.ClusterNetwork, hiveext.ClusterNetworkEntry{ 526 CIDR: "2001:db8:1111:2222::/64", 527 HostPrefix: 64, 528 }) 529 goodACI.Spec.Networking.ServiceNetwork = append(goodACI.Spec.Networking.ServiceNetwork, "fd02::/112") 530 531 return goodACI 532 } 533 534 func unmarshalJSON(b []byte) []byte { 535 output, _ := yaml.JSONToYAML(b) 536 return output 537 }