diff --git a/data/data/install.openshift.io_installconfigs.yaml b/data/data/install.openshift.io_installconfigs.yaml index b511e7d3c8e..6e32a346b1a 100644 --- a/data/data/install.openshift.io_installconfigs.yaml +++ b/data/data/install.openshift.io_installconfigs.yaml @@ -1514,7 +1514,7 @@ spec: name: type: string networkConfig: - type: string + x-kubernetes-preserve-unknown-fields: true role: type: string rootDeviceHints: diff --git a/docs/user/metal/install_ipi.md b/docs/user/metal/install_ipi.md index 7cb82e6e947..471277f1c3b 100644 --- a/docs/user/metal/install_ipi.md +++ b/docs/user/metal/install_ipi.md @@ -233,7 +233,7 @@ should be used to build the cluster. The number of assets must be at least great | `bootMACAddress` | | The MAC address of the NIC the host will use to boot on the provisioning network. It must be unique. | | `rootDeviceHints` | | How to choose the target disk for the OS during provisioning - for more details see [upstream docs](https://github.com/metal3-io/baremetal-operator/blob/master/docs/api.md). | | `bootMode` | `UEFI` | Choose `legacy` (BIOS) or `UEFI` mode for booting. Use `UEFISecureBoot` to enable UEFI and secure boot on the server. Only some drivers support UEFI secure boot (notably, IPMI does not). | -| `networkConfig` | | Yaml string describing the desired host networking settings. Must be compatible with NMState (for more details see https://nmstate.io/) | +| `networkConfig` | | Yaml block describing the desired host networking settings. Must be compatible with NMState (for more details see https://nmstate.io/) | The `bmc` parameter for each host is a set of values for accessing the baseboard management controller in the host. diff --git a/pkg/asset/machines/baremetal/hosts.go b/pkg/asset/machines/baremetal/hosts.go index 0b16b62da52..951d9b884d9 100644 --- a/pkg/asset/machines/baremetal/hosts.go +++ b/pkg/asset/machines/baremetal/hosts.go @@ -3,7 +3,9 @@ package baremetal import ( "fmt" + "github.com/ghodss/yaml" "github.com/metal3-io/baremetal-operator/pkg/hardware" + "github.com/pkg/errors" machineapi "github.com/openshift/api/machine/v1beta1" corev1 "k8s.io/api/core/v1" @@ -29,8 +31,14 @@ type HostSettings struct { NetworkConfigSecrets []corev1.Secret } -func createNetworkConfigSecret(host *baremetal.Host) corev1.Secret { - return corev1.Secret{ +func createNetworkConfigSecret(host *baremetal.Host) (*corev1.Secret, error) { + + yamlNetworkConfig, err := yaml.Marshal(host.NetworkConfig) + if err != nil { + return nil, errors.Wrap(err, "Error while creating network config secret") + } + + return &corev1.Secret{ TypeMeta: metav1.TypeMeta{ APIVersion: "v1", Kind: "Secret", @@ -39,8 +47,8 @@ func createNetworkConfigSecret(host *baremetal.Host) corev1.Secret { Name: fmt.Sprintf("%s-network-config-secret", host.Name), Namespace: "openshift-machine-api", }, - Data: map[string][]byte{"nmstate": []byte(host.NetworkConfig)}, - } + Data: map[string][]byte{"nmstate": yamlNetworkConfig}, + }, nil } func createSecret(host *baremetal.Host) (*corev1.Secret, baremetalhost.BMCDetails) { @@ -120,9 +128,12 @@ func Hosts(config *types.InstallConfig, machines []machineapi.Machine) (*HostSet } newHost := createBaremetalHost(host, bmc) - if host.NetworkConfig != "" { - networkConfigSecret := createNetworkConfigSecret(host) - settings.NetworkConfigSecrets = append(settings.NetworkConfigSecrets, networkConfigSecret) + if host.NetworkConfig != nil { + networkConfigSecret, err := createNetworkConfigSecret(host) + if err != nil { + return nil, err + } + settings.NetworkConfigSecrets = append(settings.NetworkConfigSecrets, *networkConfigSecret) newHost.Spec.PreprovisioningNetworkDataName = networkConfigSecret.Name } diff --git a/pkg/asset/machines/baremetal/hosts_test.go b/pkg/asset/machines/baremetal/hosts_test.go index e56e0d8c3c5..5c23d7106fd 100644 --- a/pkg/asset/machines/baremetal/hosts_test.go +++ b/pkg/asset/machines/baremetal/hosts_test.go @@ -4,18 +4,32 @@ import ( "fmt" "testing" - machineapi "github.com/openshift/api/machine/v1beta1" + "github.com/ghodss/yaml" + baremetalhost "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1" "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + machineapi "github.com/openshift/api/machine/v1beta1" "github.com/openshift/installer/pkg/types" baremetaltypes "github.com/openshift/installer/pkg/types/baremetal" - - baremetalhost "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1" ) func TestHosts(t *testing.T) { + + nmstate := `interfaces: +- name: eth0 + type: ethernet +routes: + config: + - destination: 198.51.100.0/24 + metric: 150 + next-hop-address: 192.0.2.1 + next-hop-interface: eth1 + table-id: 254 +` + testCases := []struct { Scenario string Machines []machineapi.Machine @@ -65,11 +79,11 @@ func TestHosts(t *testing.T) { Config: configHosts( hostType("master-0"). bmc("usr0", "pwd0"). - networkConfig("interface:")), + networkConfig(nmstate)), ExpectedSetting: settings(). secrets(secret("master-0-bmc-secret").creds("usr0", "pwd0")). - networkConfigSecrets(secret("master-0-network-config-secret").nmstate("interface:")). + networkConfigSecrets(secret("master-0-network-config-secret").nmstate(nmstate)). hosts( host("master-0"). consumerRef("machine-0"). @@ -341,7 +355,7 @@ func (htb *hostTypeBuilder) bmc(user, password string) *hostTypeBuilder { } func (htb *hostTypeBuilder) networkConfig(config string) *hostTypeBuilder { - htb.NetworkConfig = config + yaml.Unmarshal([]byte(config), &htb.NetworkConfig) return htb } diff --git a/pkg/asset/machines/master_test.go b/pkg/asset/machines/master_test.go index 5e3171b4a0e..cb8938f418a 100644 --- a/pkg/asset/machines/master_test.go +++ b/pkg/asset/machines/master_test.go @@ -8,6 +8,7 @@ import ( "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/pointer" @@ -251,7 +252,7 @@ func TestBaremetalGeneratedAssetFiles(t *testing.T) { Username: "usr-0", Password: "pwd-0", }, - NetworkConfig: "interface:", + NetworkConfig: networkConfig("interfaces:"), }, { Name: "worker-0", @@ -305,7 +306,7 @@ func TestBaremetalGeneratedAssetFiles(t *testing.T) { verifySecret(t, master.SecretFiles[1], "openshift/99_openshift-cluster-api_host-bmc-secrets-1.yaml", "worker-0-bmc-secret", "map[password:[112 119 100 45 49] username:[117 115 114 45 49]]") assert.Len(t, master.NetworkConfigSecretFiles, 1) - verifySecret(t, master.NetworkConfigSecretFiles[0], "openshift/99_openshift-cluster-api_host-network-config-secrets-0.yaml", "master-0-network-config-secret", "map[nmstate:[105 110 116 101 114 102 97 99 101 58]]") + verifySecret(t, master.NetworkConfigSecretFiles[0], "openshift/99_openshift-cluster-api_host-network-config-secrets-0.yaml", "master-0-network-config-secret", "map[nmstate:[105 110 116 101 114 102 97 99 101 115 58 32 110 117 108 108 10]]") } func verifyHost(t *testing.T, a *asset.File, eFilename, eName string) { @@ -322,3 +323,9 @@ func verifySecret(t *testing.T, a *asset.File, eFilename, eName, eData string) { assert.Equal(t, eName, secret.Name) assert.Equal(t, eData, fmt.Sprintf("%v", secret.Data)) } + +func networkConfig(config string) *v1.JSON { + var nc v1.JSON + yaml.Unmarshal([]byte(config), &nc) + return &nc +} diff --git a/pkg/types/baremetal/platform.go b/pkg/types/baremetal/platform.go index 9ca538eb61c..032e7987bdc 100644 --- a/pkg/types/baremetal/platform.go +++ b/pkg/types/baremetal/platform.go @@ -2,6 +2,7 @@ package baremetal import ( "github.com/openshift/installer/pkg/ipnet" + apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" ) // BMC stores the information about a baremetal host's management controller. @@ -39,7 +40,7 @@ type Host struct { HardwareProfile string `json:"hardwareProfile"` RootDeviceHints *RootDeviceHints `json:"rootDeviceHints,omitempty"` BootMode BootMode `json:"bootMode,omitempty"` - NetworkConfig string `json:"networkConfig,omitempty"` + NetworkConfig *apiextv1.JSON `json:"networkConfig,omitempty"` } // IsMaster checks if the current host is a master diff --git a/pkg/types/baremetal/validation/platform.go b/pkg/types/baremetal/validation/platform.go index 8ae91ad6261..82cc998b6ae 100644 --- a/pkg/types/baremetal/validation/platform.go +++ b/pkg/types/baremetal/validation/platform.go @@ -329,10 +329,12 @@ func validateHostsCount(hosts []*baremetal.Host, installConfig *types.InstallCon // ensure that the NetworkConfig field contains a valid Yaml string func validateNetworkConfig(hosts []*baremetal.Host, fldPath *field.Path) (errors field.ErrorList) { for idx, host := range hosts { - networkConfig := make(map[string]interface{}) - err := yaml.Unmarshal([]byte(host.NetworkConfig), &networkConfig) - if err != nil { - errors = append(errors, field.Invalid(fldPath.Index(idx).Child("networkConfig"), host.NetworkConfig, fmt.Sprintf("Not a valid yaml: %s", err.Error()))) + if host.NetworkConfig != nil { + networkConfig := make(map[string]interface{}) + err := yaml.Unmarshal(host.NetworkConfig.Raw, &networkConfig) + if err != nil { + errors = append(errors, field.Invalid(fldPath.Index(idx).Child("networkConfig"), host.NetworkConfig, fmt.Sprintf("Not a valid yaml: %s", err.Error()))) + } } } return diff --git a/pkg/types/baremetal/validation/platform_test.go b/pkg/types/baremetal/validation/platform_test.go index fbb4d2c93d3..e3594c0603f 100644 --- a/pkg/types/baremetal/validation/platform_test.go +++ b/pkg/types/baremetal/validation/platform_test.go @@ -10,6 +10,8 @@ import ( "github.com/openshift/installer/pkg/types" "github.com/openshift/installer/pkg/types/baremetal" "github.com/openshift/installer/pkg/types/baremetal/defaults" + + "github.com/ghodss/yaml" "github.com/stretchr/testify/assert" "k8s.io/apimachinery/pkg/util/validation/field" ) @@ -765,7 +767,7 @@ func (hb *hostBuilder) Role(value string) *hostBuilder { } func (hb *hostBuilder) NetworkConfig(value string) *hostBuilder { - hb.Host.NetworkConfig = value + yaml.Unmarshal([]byte(value), &hb.Host.NetworkConfig) return hb }