-
Notifications
You must be signed in to change notification settings - Fork 4
Add addmission webhook for shoot object #203
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| // SPDX-FileCopyrightText: SAP SE or an SAP affiliate company and Gardener contributors | ||
| // | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| package validator | ||
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
|
|
||
| extensionswebhook "github.com/gardener/gardener/extensions/pkg/webhook" | ||
| "github.com/gardener/gardener/pkg/apis/core" | ||
| "k8s.io/apimachinery/pkg/util/validation/field" | ||
| "sigs.k8s.io/controller-runtime/pkg/client" | ||
| "sigs.k8s.io/controller-runtime/pkg/manager" | ||
|
|
||
| "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/apis/stackit/helper" | ||
| stackitvalidation "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/apis/stackit/validation" | ||
| ) | ||
|
|
||
| // NewShootValidator returns a new instance of a shoot validator. | ||
| func NewShootValidator(mgr manager.Manager) extensionswebhook.Validator { | ||
| return &shoot{} | ||
| } | ||
|
|
||
| type shoot struct{} | ||
|
|
||
| // Validate validates the given shoot objects. | ||
| func (s *shoot) Validate(_ context.Context, newObj, oldObj client.Object) error { | ||
| shoot, ok := newObj.(*core.Shoot) | ||
| if !ok { | ||
| return fmt.Errorf("wrong object type %T", newObj) | ||
| } | ||
|
|
||
| if shoot.Spec.Provider.ControlPlaneConfig == nil { | ||
| return nil | ||
| } | ||
|
|
||
| cpConfig, err := helper.ControlPlaneConfigFromRawExtension(shoot.Spec.Provider.ControlPlaneConfig) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| infraConfig, err := helper.InfrastructureConfigFromRawExtension(shoot.Spec.Provider.InfrastructureConfig) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| allErrs := field.ErrorList{} | ||
|
|
||
| allErrs = append(allErrs, stackitvalidation.ValidateControlPlaneConfig(cpConfig, shoot.Spec.Kubernetes.Version, field.NewPath("spec").Child("providerConfig"))...) | ||
|
|
||
| allErrs = append(allErrs, stackitvalidation.ValidateInfrastructureConfig(infraConfig, shoot.Spec.Networking.Nodes, field.NewPath("spec").Child("providerConfig").Child("infrastructureConfig"))...) | ||
|
|
||
| if oldObj != nil { | ||
| oldShoot, ok := oldObj.(*core.Shoot) | ||
| if !ok { | ||
| return fmt.Errorf("wrong object type %T for old object", oldObj) | ||
| } | ||
| oldInfraConfig, err := helper.InfrastructureConfigFromRawExtension(oldShoot.Spec.Provider.InfrastructureConfig) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| allErrs = append(allErrs, stackitvalidation.ValidateInfrastructureConfigUpdate(oldInfraConfig, infraConfig, field.NewPath("spec").Child("providerConfig").Child("infrastructureConfig"))...) | ||
| } | ||
|
|
||
| return allErrs.ToAggregate() | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,13 +21,10 @@ var ( | |
| ) | ||
|
|
||
| // ValidateControlPlaneConfig validates a ControlPlaneConfig object. | ||
| func ValidateControlPlaneConfig(controlPlaneConfig *stackitv1alpha1.ControlPlaneConfig, infraConfig *stackitv1alpha1.InfrastructureConfig, version string, fldPath *field.Path) field.ErrorList { | ||
| allErrs := field.ErrorList{} | ||
| func ValidateControlPlaneConfig(controlPlaneConfig *stackitv1alpha1.ControlPlaneConfig, version string, fldPath *field.Path) field.ErrorList { | ||
| allErrs := field.ErrorList{} // nolint:prealloc // size is not known yet | ||
|
|
||
| if controlPlaneConfig.CloudControllerManager != nil { | ||
| allErrs = append(allErrs, featurevalidation.ValidateFeatureGates(controlPlaneConfig.CloudControllerManager.FeatureGates, version, fldPath.Child("cloudControllerManager", "featureGates"))...) | ||
| allErrs = append(allErrs, validateCloudController(controlPlaneConfig.CloudControllerManager, fldPath.Child("cloudControllerManager"))...) | ||
| } | ||
| allErrs = append(allErrs, validateCloudController(controlPlaneConfig.CloudControllerManager, version, fldPath.Child("cloudControllerManager"))...) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
ah okay CloudControllerManager is defaulted
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The nil check is still done. It was also done in |
||
|
|
||
| allErrs = append(allErrs, validateStorage(controlPlaneConfig.Storage, fldPath.Child("storage"))...) | ||
|
|
||
|
|
@@ -48,14 +45,16 @@ func ValidateControlPlaneConfigAgainstCloudProfile(oldCpConfig, cpConfig *stacki | |
| return allErrs | ||
| } | ||
|
|
||
| func validateCloudController(cloudcontroller *stackitv1alpha1.CloudControllerManagerConfig, fldPath *field.Path) field.ErrorList { | ||
| func validateCloudController(cloudcontroller *stackitv1alpha1.CloudControllerManagerConfig, version string, fldPath *field.Path) field.ErrorList { | ||
| var allErrs field.ErrorList | ||
| if cloudcontroller == nil { | ||
| return allErrs | ||
| } | ||
| if cloudcontroller.Name != "" && !slices.Contains(validControllers, stackitv1alpha1.ControllerName(cloudcontroller.Name)) { | ||
| allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), cloudcontroller.Name, "not supported ccm driver")) | ||
| } | ||
| allErrs = append(allErrs, featurevalidation.ValidateFeatureGates(cloudcontroller.FeatureGates, version, fldPath.Child("featureGates"))...) | ||
|
|
||
| return allErrs | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,18 +23,9 @@ func ValidateInfrastructureConfig(infra *stackitv1alpha1.InfrastructureConfig, n | |
| allErrs = append(allErrs, field.Required(fldPath.Child("floatingPoolName"), "must provide the name of a floating pool")) | ||
| } | ||
|
|
||
| networkingPath := field.NewPath("networking") | ||
| var nodes cidrvalidation.CIDR | ||
| if nodesCIDR != nil { | ||
| nodes = cidrvalidation.NewCIDR(*nodesCIDR, networkingPath.Child("nodes")) | ||
| } | ||
|
|
||
| networksPath := fldPath.Child("networks") | ||
| //nolint:staticcheck // SA1019: needed for migration purposes | ||
| if len(infra.Networks.Worker) == 0 && len(infra.Networks.Workers) == 0 { | ||
| allErrs = append(allErrs, field.Required(networksPath.Child("workers"), "must specify the network range for the worker network")) | ||
| } | ||
|
|
||
| // check InfrastructureConfig.networks.worker(s) is a valid cidr and not be set if a network id is provided. | ||
| var workerCIDR cidrvalidation.CIDR | ||
| //nolint:staticcheck // SA1019: needed for migration purposes | ||
| if infra.Networks.Worker != "" { | ||
|
|
@@ -43,23 +34,38 @@ func ValidateInfrastructureConfig(infra *stackitv1alpha1.InfrastructureConfig, n | |
| allErrs = append(allErrs, cidrvalidation.ValidateCIDRParse(workerCIDR)...) | ||
| //nolint:staticcheck // SA1019: needed for migration purposes | ||
| allErrs = append(allErrs, cidrvalidation.ValidateCIDRIsCanonical(networksPath.Child("worker"), infra.Networks.Worker)...) | ||
| if infra.Networks.ID != nil { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. where was the different again between
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes |
||
| allErrs = append(allErrs, field.Forbidden(networksPath.Child("worker"), "cant be set if a network id is provided")) | ||
| } | ||
| } | ||
| if infra.Networks.Workers != "" { | ||
| workerCIDR = cidrvalidation.NewCIDR(infra.Networks.Workers, networksPath.Child("workers")) | ||
| allErrs = append(allErrs, cidrvalidation.ValidateCIDRParse(workerCIDR)...) | ||
| allErrs = append(allErrs, cidrvalidation.ValidateCIDRIsCanonical(networksPath.Child("workers"), infra.Networks.Workers)...) | ||
| if infra.Networks.ID != nil { | ||
| allErrs = append(allErrs, field.Forbidden(networksPath.Child("workers"), "cant be set if a network id is provided")) | ||
| } | ||
| } | ||
|
|
||
| if nodes != nil { | ||
| // check if InfrastructureConfig.networks.worker(s) is a subset of spec.networking.nodes | ||
| var nodes cidrvalidation.CIDR | ||
| if nodesCIDR != nil { | ||
| nodes = cidrvalidation.NewCIDR(*nodesCIDR, field.NewPath("spec").Child("networking").Child("nodes")) | ||
| allErrs = append(allErrs, nodes.ValidateSubset(workerCIDR)...) | ||
| } | ||
|
|
||
| // validate that InfrastructureConfig.networks.id is a valid uuid | ||
| if infra.Networks.ID != nil { | ||
| if _, err := uuid.Parse(*infra.Networks.ID); err != nil { | ||
| allErrs = append(allErrs, field.Invalid(networksPath.Child("id"), infra.Networks.ID, "if network ID is provided it must be a valid OpenStack UUID")) | ||
| allErrs = append(allErrs, field.Invalid(networksPath.Child("id"), infra.Networks.ID, "if network ID is provided it must be a valid STACKIT Network ID")) | ||
| } | ||
| } | ||
|
|
||
| // eather InfrastructureConfig.networks.id or InfrastructureConfig.networks.worker(s) has to be set | ||
| if workerCIDR == nil && infra.Networks.ID == nil { | ||
| allErrs = append(allErrs, field.Required(networksPath.Child("workers"), "must specify the network range for the worker network or provide a network ID for the network")) | ||
| } | ||
|
|
||
| if infra.Networks.SubnetID != nil { | ||
| if infra.Networks.ID == nil { | ||
| allErrs = append(allErrs, field.Invalid(networksPath.Child("subnetId"), infra.Networks.SubnetID, "if subnet ID is provided a networkID must be provided")) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this on the oldObj?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It has both it validates updates and checks for immutable fields.