in pkg/providers/vsphere/validator.go [64:207]
func (v *Validator) ValidateClusterMachineConfigs(ctx context.Context, vsphereClusterSpec *Spec) error {
var etcdMachineConfig *anywherev1.VSphereMachineConfig
// TODO: move this to api Cluster validations
if len(vsphereClusterSpec.Cluster.Spec.ControlPlaneConfiguration.Endpoint.Host) <= 0 {
return errors.New("cluster controlPlaneConfiguration.Endpoint.Host is not set or is empty")
}
if vsphereClusterSpec.Cluster.Spec.ControlPlaneConfiguration.MachineGroupRef == nil {
return errors.New("must specify machineGroupRef for control plane")
}
controlPlaneMachineConfig := vsphereClusterSpec.controlPlaneMachineConfig()
if controlPlaneMachineConfig == nil {
return fmt.Errorf("cannot find VSphereMachineConfig %v for control plane", vsphereClusterSpec.Cluster.Spec.ControlPlaneConfiguration.MachineGroupRef.Name)
}
if len(controlPlaneMachineConfig.Spec.Datastore) <= 0 {
return errors.New("VSphereMachineConfig datastore for control plane is not set or is empty")
}
if len(controlPlaneMachineConfig.Spec.Folder) <= 0 {
logger.Info("VSphereMachineConfig folder for control plane is not set or is empty. Will default to root vSphere folder.")
}
if len(controlPlaneMachineConfig.Spec.ResourcePool) <= 0 {
return errors.New("VSphereMachineConfig VM resourcePool for control plane is not set or is empty")
}
if controlPlaneMachineConfig.Spec.OSFamily != anywherev1.Bottlerocket && controlPlaneMachineConfig.Spec.OSFamily != anywherev1.Ubuntu {
return fmt.Errorf("control plane osFamily: %s is not supported, please use one of the following: %s, %s", controlPlaneMachineConfig.Spec.OSFamily, anywherev1.Bottlerocket, anywherev1.Ubuntu)
}
workerNodeGroupConfigs := vsphereClusterSpec.Cluster.Spec.WorkerNodeGroupConfigurations
for _, workerNodeGroupConfig := range workerNodeGroupConfigs {
if workerNodeGroupConfig.Name == "" {
return errors.New("must specify name for worker nodes")
}
}
var workerNodeGroupMachineConfigs []*anywherev1.VSphereMachineConfig
for _, workerNodeGroupConfiguration := range vsphereClusterSpec.Cluster.Spec.WorkerNodeGroupConfigurations {
if workerNodeGroupConfiguration.MachineGroupRef == nil {
return errors.New("must specify machineGroupRef for worker nodes")
}
workerNodeGroupMachineConfig := vsphereClusterSpec.workerMachineConfig(workerNodeGroupConfiguration)
workerNodeGroupMachineConfigs = append(workerNodeGroupMachineConfigs, workerNodeGroupMachineConfig)
if workerNodeGroupMachineConfig == nil {
return fmt.Errorf("cannot find VSphereMachineConfig %v for worker nodes", workerNodeGroupConfiguration.MachineGroupRef.Name)
}
if len(workerNodeGroupMachineConfig.Spec.Datastore) <= 0 {
return errors.New("VSphereMachineConfig datastore for worker nodes is not set or is empty")
}
if len(workerNodeGroupMachineConfig.Spec.Folder) <= 0 {
logger.Info("VSphereMachineConfig folder for worker nodes is not set or is empty. Will default to root vSphere folder.")
}
if len(workerNodeGroupMachineConfig.Spec.ResourcePool) <= 0 {
return errors.New("VSphereMachineConfig VM resourcePool for worker nodes is not set or is empty")
}
if workerNodeGroupMachineConfig.Spec.OSFamily != anywherev1.Bottlerocket && workerNodeGroupMachineConfig.Spec.OSFamily != anywherev1.Ubuntu {
return fmt.Errorf("worker node osFamily: %s is not supported, please use one of the following: %s, %s", workerNodeGroupMachineConfig.Spec.OSFamily, anywherev1.Bottlerocket, anywherev1.Ubuntu)
}
if controlPlaneMachineConfig.Spec.OSFamily != workerNodeGroupMachineConfig.Spec.OSFamily {
return errors.New("control plane and worker nodes must have the same osFamily specified")
}
if controlPlaneMachineConfig.Spec.Template != workerNodeGroupMachineConfig.Spec.Template {
return errors.New("control plane and worker nodes must have the same template specified")
}
}
if vsphereClusterSpec.Cluster.Spec.ExternalEtcdConfiguration != nil {
if vsphereClusterSpec.Cluster.Spec.ExternalEtcdConfiguration.MachineGroupRef == nil {
return errors.New("must specify machineGroupRef for etcd machines")
}
etcdMachineConfig = vsphereClusterSpec.etcdMachineConfig()
if etcdMachineConfig == nil {
return fmt.Errorf("cannot find VSphereMachineConfig %v for etcd machines", vsphereClusterSpec.Cluster.Spec.ExternalEtcdConfiguration.MachineGroupRef.Name)
}
if len(etcdMachineConfig.Spec.Datastore) <= 0 {
return errors.New("VSphereMachineConfig datastore for etcd machines is not set or is empty")
}
if len(etcdMachineConfig.Spec.Folder) <= 0 {
logger.Info("VSphereMachineConfig folder for etcd machines is not set or is empty. Will default to root vSphere folder.")
}
if len(etcdMachineConfig.Spec.ResourcePool) <= 0 {
return errors.New("VSphereMachineConfig VM resourcePool for etcd machines is not set or is empty")
}
}
// TODO: move this to api Cluster validations
if err := v.validateControlPlaneIp(vsphereClusterSpec.Cluster.Spec.ControlPlaneConfiguration.Endpoint.Host); err != nil {
return err
}
for _, config := range vsphereClusterSpec.machineConfigsLookup {
var b bool // Temporary until we remove the need to pass a bool pointer
err := v.govc.ValidateVCenterSetupMachineConfig(ctx, vsphereClusterSpec.datacenterConfig, config, &b) // TODO: remove side effects from this implementation or directly move it to set defaults (pointer to bool is not needed)
if err != nil {
return fmt.Errorf("error validating vCenter setup for VSphereMachineConfig %v: %v", config.Name, err)
}
}
if etcdMachineConfig != nil && etcdMachineConfig.Spec.OSFamily != anywherev1.Bottlerocket && etcdMachineConfig.Spec.OSFamily != anywherev1.Ubuntu {
return fmt.Errorf("etcd node osFamily: %s is not supported, please use one of the following: %s, %s", etcdMachineConfig.Spec.OSFamily, anywherev1.Bottlerocket, anywherev1.Ubuntu)
}
if etcdMachineConfig != nil && controlPlaneMachineConfig.Spec.OSFamily != etcdMachineConfig.Spec.OSFamily {
return errors.New("control plane and etcd machines must have the same osFamily specified")
}
if err := v.validateSSHUsername(controlPlaneMachineConfig); err == nil {
for _, wnConfig := range workerNodeGroupMachineConfigs {
if err = v.validateSSHUsername(wnConfig); err != nil {
return fmt.Errorf("error validating SSHUsername for worker node VSphereMachineConfig %v: %v", wnConfig.Name, err)
}
}
if etcdMachineConfig != nil {
if err = v.validateSSHUsername(etcdMachineConfig); err != nil {
return fmt.Errorf("error validating SSHUsername for etcd VSphereMachineConfig %v: %v", etcdMachineConfig.Name, err)
}
}
} else {
return fmt.Errorf("error validating SSHUsername for control plane VSphereMachineConfig %v: %v", controlPlaneMachineConfig.Name, err)
}
for _, machineConfig := range vsphereClusterSpec.machineConfigsLookup {
if machineConfig.Namespace != vsphereClusterSpec.Cluster.Namespace {
return errors.New("VSphereMachineConfig and Cluster objects must have the same namespace specified")
}
}
if vsphereClusterSpec.datacenterConfig.Namespace != vsphereClusterSpec.Cluster.Namespace {
return errors.New("VSphereDatacenterConfig and Cluster objects must have the same namespace specified")
}
if err := v.validateTemplate(ctx, vsphereClusterSpec, controlPlaneMachineConfig); err != nil {
logger.V(1).Info("Control plane template validation failed.")
return err
}
logger.MarkPass("Control plane and Workload templates validated")
if etcdMachineConfig != nil {
if etcdMachineConfig.Spec.Template != controlPlaneMachineConfig.Spec.Template {
return errors.New("control plane and etcd machines must have the same template specified")
}
}
return v.validateDatastoreUsage(ctx, vsphereClusterSpec, controlPlaneMachineConfig, etcdMachineConfig)
}