diff --git a/api/bases/mariadb.openstack.org_galeras.yaml b/api/bases/mariadb.openstack.org_galeras.yaml index b787239e..65bb07c7 100644 --- a/api/bases/mariadb.openstack.org_galeras.yaml +++ b/api/bases/mariadb.openstack.org_galeras.yaml @@ -69,11 +69,9 @@ spec: replicas: default: 1 description: Size of the galera cluster deployment - enum: - - 1 - - 3 format: int32 - minimum: 1 + maximum: 3 + minimum: 0 type: integer secret: description: Name of the secret to look for password keys diff --git a/api/v1beta1/galera_types.go b/api/v1beta1/galera_types.go index 5415a4d0..08bfeba5 100644 --- a/api/v1beta1/galera_types.go +++ b/api/v1beta1/galera_types.go @@ -57,9 +57,9 @@ type GaleraSpecCore struct { // Storage size allocated for the mariadb databases // +kubebuilder:validation:Required StorageRequest string `json:"storageRequest"` - // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=3 // +kubebuilder:default=1 - // +kubebuilder:validation:Enum=1;3 // Size of the galera cluster deployment Replicas *int32 `json:"replicas"` // +kubebuilder:validation:Optional diff --git a/api/v1beta1/galera_webhook.go b/api/v1beta1/galera_webhook.go index dc19d408..8406abe7 100644 --- a/api/v1beta1/galera_webhook.go +++ b/api/v1beta1/galera_webhook.go @@ -120,11 +120,15 @@ func (spec *GaleraSpecCore) ValidateCreate(basePath *field.Path) (admission.Warn warn, _ := common_webhook.ValidateStorageRequest(basePath, spec.StorageRequest, storageRequestProdMin, false) allWarn = append(allWarn, warn...) + warn = spec.ValidateGaleraReplicas(basePath) + allWarn = append(allWarn, warn...) + return allWarn, allErrs } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type func (r *Galera) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + allWarn := []string{} galeralog.Info("validate update", "name", r.Name) oldGalera, ok := old.(*Galera) @@ -132,8 +136,12 @@ func (r *Galera) ValidateUpdate(old runtime.Object) (admission.Warnings, error) return nil, apierrors.NewInternalError(fmt.Errorf("unable to convert existing object")) } + basePath := field.NewPath("spec") + warn := r.Spec.ValidateGaleraReplicas(basePath) + allWarn = append(allWarn, warn...) + // TODO(user): fill in your validation logic upon object update. - return nil, nil + return allWarn, nil } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type @@ -149,3 +157,15 @@ func SetupGaleraDefaults(defaults GaleraDefaults) { galeraDefaults = defaults galeralog.Info("Galera defaults initialized", "defaults", defaults) } + +// SetupGaleraDefaults - Check whether replica count is valid for quorum +func (spec *GaleraSpecCore) ValidateGaleraReplicas(basePath *field.Path) admission.Warnings { + replicas := int(*spec.Replicas) + if replicas > 0 && (replicas%2 == 0) { + res := fmt.Sprintf("%s: %d is not appropriate for quorum! Use an odd value!", + basePath.Child("replicas").String(), replicas) + return []string{res} + } else { + return nil + } +} diff --git a/config/crd/bases/mariadb.openstack.org_galeras.yaml b/config/crd/bases/mariadb.openstack.org_galeras.yaml index b787239e..65bb07c7 100644 --- a/config/crd/bases/mariadb.openstack.org_galeras.yaml +++ b/config/crd/bases/mariadb.openstack.org_galeras.yaml @@ -69,11 +69,9 @@ spec: replicas: default: 1 description: Size of the galera cluster deployment - enum: - - 1 - - 3 format: int32 - minimum: 1 + maximum: 3 + minimum: 0 type: integer secret: description: Name of the secret to look for password keys diff --git a/controllers/galera_controller.go b/controllers/galera_controller.go index 7f27c087..c11e6c76 100644 --- a/controllers/galera_controller.go +++ b/controllers/galera_controller.go @@ -819,7 +819,7 @@ func (r *GaleraReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res } // Check if we have enough info to bootstrap the cluster now - if !found { + if !found && int(*instance.Spec.Replicas) > 0 { node, found = findBestCandidate(instance) } if found {