From 31e5ac8ad23a21b7ced15fec019ac967636fab73 Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Mon, 17 Oct 2022 10:11:59 -0700 Subject: [PATCH] add more generic validation funcs --- .../azuremanagedmachinepool_webhook.go | 144 ++++-------------- exp/api/v1beta1/webhook.go | 117 ++++++++++++++ 2 files changed, 144 insertions(+), 117 deletions(-) create mode 100644 exp/api/v1beta1/webhook.go diff --git a/exp/api/v1beta1/azuremanagedmachinepool_webhook.go b/exp/api/v1beta1/azuremanagedmachinepool_webhook.go index 7186f13a231..38bd2aa0930 100644 --- a/exp/api/v1beta1/azuremanagedmachinepool_webhook.go +++ b/exp/api/v1beta1/azuremanagedmachinepool_webhook.go @@ -98,31 +98,18 @@ func (m *AzureManagedMachinePool) ValidateUpdate(oldRaw runtime.Object, client c allErrs = append(allErrs, err) } - if m.Spec.SKU != old.Spec.SKU { - allErrs = append(allErrs, - field.Invalid( - field.NewPath("Spec", "SKU"), - m.Spec.SKU, - "field is immutable")) + if err := validateStringImmutable( + field.NewPath("Spec", "SKU"), + old.Spec.SKU, + m.Spec.SKU); err != nil { + allErrs = append(allErrs, err) } - if old.Spec.OSDiskSizeGB != nil { - // Prevent OSDiskSizeGB modification if it was already set to some value - if m.Spec.OSDiskSizeGB == nil { - // unsetting the field is not allowed - allErrs = append(allErrs, - field.Invalid( - field.NewPath("Spec", "OSDiskSizeGB"), - m.Spec.OSDiskSizeGB, - "field is immutable, unsetting is not allowed")) - } else if *m.Spec.OSDiskSizeGB != *old.Spec.OSDiskSizeGB { - // changing the field is not allowed - allErrs = append(allErrs, - field.Invalid( - field.NewPath("Spec", "OSDiskSizeGB"), - *m.Spec.OSDiskSizeGB, - "field is immutable")) - } + if err := validateInt32PtrImmutable( + field.NewPath("Spec", "OSDiskSizeGB"), + old.Spec.OSDiskSizeGB, + m.Spec.OSDiskSizeGB); err != nil { + allErrs = append(allErrs, err) } // custom headers are immutable @@ -153,49 +140,25 @@ func (m *AzureManagedMachinePool) ValidateUpdate(oldRaw runtime.Object, client c } } - if old.Spec.MaxPods != nil { - // Prevent MaxPods modification if it was already set to some value - if m.Spec.MaxPods == nil { - // unsetting the field is not allowed - allErrs = append(allErrs, - field.Invalid( - field.NewPath("Spec", "MaxPods"), - m.Spec.MaxPods, - "field is immutable, unsetting is not allowed")) - } else if *m.Spec.MaxPods != *old.Spec.MaxPods { - // changing the field is not allowed - allErrs = append(allErrs, - field.Invalid( - field.NewPath("Spec", "MaxPods"), - *m.Spec.MaxPods, - "field is immutable")) - } + if err := validateInt32PtrImmutable( + field.NewPath("Spec", "MaxPods"), + old.Spec.MaxPods, + m.Spec.MaxPods); err != nil { + allErrs = append(allErrs, err) } - if old.Spec.OsDiskType != nil { - // Prevent OSDiskType modification if it was already set to some value - if m.Spec.OsDiskType == nil || to.String(m.Spec.OsDiskType) == "" { - // unsetting the field is not allowed - allErrs = append(allErrs, - field.Invalid( - field.NewPath("Spec", "OsDiskType"), - m.Spec.OsDiskType, - "field is immutable, unsetting is not allowed")) - } else if *m.Spec.OsDiskType != *old.Spec.OsDiskType { - // changing the field is not allowed - allErrs = append(allErrs, - field.Invalid( - field.NewPath("Spec", "OsDiskType"), - m.Spec.OsDiskType, - "field is immutable")) - } + if err := validateStringPtrImmutable( + field.NewPath("Spec", "OsDiskType"), + old.Spec.OsDiskType, + m.Spec.OsDiskType); err != nil { + allErrs = append(allErrs, err) } - if !reflect.DeepEqual(m.Spec.ScaleSetPriority, old.Spec.ScaleSetPriority) { - allErrs = append(allErrs, - field.Invalid(field.NewPath("Spec", "ScaleSetPriority"), - m.Spec.ScaleSetPriority, "field is immutable"), - ) + if err := validateStringPtrImmutable( + field.NewPath("Spec", "ScaleSetPriority"), + old.Spec.ScaleSetPriority, + m.Spec.ScaleSetPriority); err != nil { + allErrs = append(allErrs, err) } if err := validateBoolPtrImmutable( @@ -204,6 +167,7 @@ func (m *AzureManagedMachinePool) ValidateUpdate(oldRaw runtime.Object, client c m.Spec.EnableUltraSSD); err != nil { allErrs = append(allErrs, err) } + if err := validateBoolPtrImmutable( field.NewPath("Spec", "EnableNodePublicIP"), old.Spec.EnableNodePublicIP, @@ -269,7 +233,7 @@ func (m *AzureManagedMachinePool) validateLastSystemNodePool(cli client.Client) return err } - if len(ammpList.Items) <= 1 { + if len(ammpList.Items) < 1 { return errors.New("AKS Cluster must have at least one system pool") } return nil @@ -346,57 +310,3 @@ func (m *AzureManagedMachinePool) validateEnableNodePublicIP() error { } return nil } - -func ensureStringSlicesAreEqual(a []string, b []string) bool { - if len(a) != len(b) { - return false - } - - m := map[string]bool{} - for _, v := range a { - m[v] = true - } - - for _, v := range b { - if _, ok := m[v]; !ok { - return false - } - } - return true -} - -func validateBoolPtrImmutable(path *field.Path, oldVal, newVal *bool) *field.Error { - if oldVal != nil { - // Prevent modification if it was already set to some value - if newVal == nil { - // unsetting the field is not allowed - return field.Invalid(path, newVal, "field is immutable, unsetting is not allowed") - } - if *newVal != *oldVal { - // changing the field is not allowed - return field.Invalid(path, newVal, "field is immutable") - } - } else if newVal != nil { - return field.Invalid(path, newVal, "field is immutable, setting is not allowed") - } - - return nil -} - -func validateStringPtrImmutable(path *field.Path, oldVal, newVal *string) *field.Error { - if oldVal != nil { - // Prevent modification if it was already set to some value - if newVal == nil { - // unsetting the field is not allowed - return field.Invalid(path, newVal, "field is immutable, unsetting is not allowed") - } - if *newVal != *oldVal { - // changing the field is not allowed - return field.Invalid(path, newVal, "field is immutable") - } - } else if newVal != nil { - return field.Invalid(path, newVal, "field is immutable, setting is not allowed") - } - - return nil -} diff --git a/exp/api/v1beta1/webhook.go b/exp/api/v1beta1/webhook.go new file mode 100644 index 00000000000..632e66f6acb --- /dev/null +++ b/exp/api/v1beta1/webhook.go @@ -0,0 +1,117 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "k8s.io/apimachinery/pkg/util/validation/field" +) + +const ( + unsetMessage = "field is immutable, unsetting is not allowed" + setMessage = "field is immutable, setting is not allowed" + immutableMessage = "field is immutable" +) + +func ensureStringSlicesAreEqual(a []string, b []string) bool { + if len(a) != len(b) { + return false + } + + m := map[string]bool{} + for _, v := range a { + m[v] = true + } + + for _, v := range b { + if _, ok := m[v]; !ok { + return false + } + } + return true +} + +func validateBoolPtrImmutable(path *field.Path, oldVal, newVal *bool) *field.Error { + if oldVal != nil { + // Prevent modification if it was already set to some value + if newVal == nil { + // unsetting the field is not allowed + return field.Invalid(path, newVal, unsetMessage) + } + if *newVal != *oldVal { + // changing the field is not allowed + return field.Invalid(path, newVal, immutableMessage) + } + } else if newVal != nil { + return field.Invalid(path, newVal, setMessage) + } + + return nil +} + +func validateStringImmutable(path *field.Path, oldVal, newVal string) *field.Error { + if oldVal != "" { + // Prevent modification if it was already set to some value + if newVal == "" { + // unsetting the field is not allowed + return field.Invalid(path, newVal, unsetMessage) + } + if newVal != oldVal { + // changing the field is not allowed + return field.Invalid(path, newVal, immutableMessage) + } + } else if newVal != "" { + return field.Invalid(path, newVal, setMessage) + } + + return nil +} + +func validateStringPtrImmutable(path *field.Path, oldVal, newVal *string) *field.Error { + if oldVal != nil { + // Prevent modification if it was already set to some value + if newVal == nil { + // unsetting the field is not allowed + return field.Invalid(path, newVal, unsetMessage) + } + if *newVal != *oldVal { + // changing the field is not allowed + return field.Invalid(path, newVal, immutableMessage) + } + } else if newVal != nil { + return field.Invalid(path, newVal, setMessage) + } + + return nil +} + +func validateInt32PtrImmutable(path *field.Path, oldVal, newVal *int32) *field.Error { + if oldVal != nil { + // Prevent modification if it was already set to some value + if newVal == nil { + // unsetting the field is not allowed + return field.Invalid(path, newVal, unsetMessage) + } + if *newVal != *oldVal { + // changing the field is not allowed + return field.Invalid(path, newVal, immutableMessage) + } + } else if newVal != nil { + return field.Invalid(path, newVal, setMessage) + } + + return nil +}