diff --git a/pkg/types/baremetal/validation/platform.go b/pkg/types/baremetal/validation/platform.go index 3547951075b..682089c8eb0 100644 --- a/pkg/types/baremetal/validation/platform.go +++ b/pkg/types/baremetal/validation/platform.go @@ -17,6 +17,13 @@ func validateIPinMachineCIDR(vip string, n *types.Networking) error { return nil } +func validateIPNotinMachineCIDR(ip string, n *types.Networking) error { + if n.MachineCIDR.Contains(net.ParseIP(ip)) { + return fmt.Errorf("the IP must not be in %s subnet", n.MachineCIDR.String()) + } + return nil +} + // ValidatePlatform checks that the specified platform is valid. func ValidatePlatform(p *baremetal.Platform, n *types.Networking, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} @@ -71,6 +78,12 @@ func ValidatePlatform(p *baremetal.Platform, n *types.Networking, fldPath *field if err := validateIPinMachineCIDR(p.DNSVIP, n); err != nil { allErrs = append(allErrs, field.Invalid(fldPath.Child("dnsVIP"), p.DNSVIP, err.Error())) } + if err := validateIPNotinMachineCIDR(p.ClusterProvisioningIP, n); err != nil { + allErrs = append(allErrs, field.Invalid(fldPath.Child("provisioningHostIP"), p.ClusterProvisioningIP, err.Error())) + } + if err := validateIPNotinMachineCIDR(p.BootstrapProvisioningIP, n); err != nil { + allErrs = append(allErrs, field.Invalid(fldPath.Child("bootstrapHostIP"), p.BootstrapProvisioningIP, err.Error())) + } return allErrs } diff --git a/pkg/types/baremetal/validation/platform_test.go b/pkg/types/baremetal/validation/platform_test.go new file mode 100644 index 00000000000..4f3f01dacbb --- /dev/null +++ b/pkg/types/baremetal/validation/platform_test.go @@ -0,0 +1,194 @@ +package validation + +import ( + "net" + "testing" + + "github.com/openshift/installer/pkg/ipnet" + "github.com/openshift/installer/pkg/types" + "github.com/openshift/installer/pkg/types/baremetal" + "github.com/stretchr/testify/assert" + "k8s.io/apimachinery/pkg/util/validation/field" +) + +func TestValidatePlatform(t *testing.T) { + iface, _ := net.Interfaces() + network := &types.Networking{MachineCIDR: ipnet.MustParseCIDR("192.168.111.0/24")} + cases := []struct { + name string + platform *baremetal.Platform + network *types.Networking + expected string + }{ + { + name: "valid", + platform: &baremetal.Platform{ + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: iface[0].Name, + ProvisioningBridge: iface[0].Name, + }, + network: network, + }, + { + name: "invalid_apivip", + platform: &baremetal.Platform{ + APIVIP: "192.168.222.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: iface[0].Name, + ProvisioningBridge: iface[0].Name, + }, + network: network, + expected: "Invalid value: \"192.168.222.2\": the virtual IP is expected to be in 192.168.111.0/24 subnet", + }, + { + name: "invalid_dnsvip", + platform: &baremetal.Platform{ + APIVIP: "192.168.111.2", + DNSVIP: "192.168.222.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: iface[0].Name, + ProvisioningBridge: iface[0].Name, + }, + network: network, + expected: "Invalid value: \"192.168.222.3\": the virtual IP is expected to be in 192.168.111.0/24 subnet", + }, + { + name: "invalid_ingressvip", + platform: &baremetal.Platform{ + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.222.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: iface[0].Name, + ProvisioningBridge: iface[0].Name, + }, + network: network, + expected: "Invalid value: \"192.168.222.4\": the virtual IP is expected to be in 192.168.111.0/24 subnet", + }, + { + name: "invalid_hosts", + platform: &baremetal.Platform{ + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: nil, + LibvirtURI: "qemu://system", + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: iface[0].Name, + ProvisioningBridge: iface[0].Name, + }, + network: network, + expected: "bare metal hosts are missing", + }, + { + name: "invalid_libvirturi", + platform: &baremetal.Platform{ + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "", + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: iface[0].Name, + ProvisioningBridge: iface[0].Name, + }, + network: network, + expected: "invalid URI \"\"", + }, + { + name: "invalid_extbridge", + platform: &baremetal.Platform{ + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: "noexist", + ProvisioningBridge: iface[0].Name, + }, + network: network, + expected: "Invalid value: \"noexist\": noexist is not a valid network interface", + }, + { + name: "invalid_provbridge", + platform: &baremetal.Platform{ + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: iface[0].Name, + ProvisioningBridge: "noexist", + }, + network: network, + expected: "Invalid value: \"noexist\": noexist is not a valid network interface", + }, + { + name: "invalid_clusterprovip", + platform: &baremetal.Platform{ + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ClusterProvisioningIP: "192.168.111.5", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: iface[0].Name, + ProvisioningBridge: iface[0].Name, + }, + network: network, + expected: "Invalid value: \"192.168.111.5\": the IP must not be in 192.168.111.0/24 subnet", + }, + { + name: "invalid_bootstrapprovip", + platform: &baremetal.Platform{ + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "192.168.111.5", + ExternalBridge: iface[0].Name, + ProvisioningBridge: iface[0].Name, + }, + network: network, + expected: "Invalid value: \"192.168.111.5\": the IP must not be in 192.168.111.0/24 subnet", + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + err := ValidatePlatform(tc.platform, tc.network, field.NewPath("test-path")).ToAggregate() + if tc.expected == "" { + assert.NoError(t, err) + } else { + assert.Regexp(t, tc.expected, err) + } + }) + } +}