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  }