From a7a1249c41e32759690c87ba2fa9c7a67a683d0e Mon Sep 17 00:00:00 2001 From: swamyan Date: Tue, 19 Sep 2023 14:43:17 +0530 Subject: [PATCH] Move docker infrastructure API v1beta1 webhooks to separate package --- Makefile | 3 +- .../docker/config/webhook/manifests.yaml | 122 ------------------ .../docker/internal/webhooks/doc.go | 18 +++ .../webhooks}/dockercluster_webhook.go | 47 +++++-- .../dockerclustertemplate_webhook.go | 55 +++++--- .../dockerclustertemplate_webhook_test.go | 39 +++--- .../dockermachinetemplate_webhook.go | 31 ++--- .../dockermachinetemplate_webhook_test.go | 17 +-- test/infrastructure/docker/main.go | 11 +- test/infrastructure/docker/webhooks/alias.go | 47 +++++++ test/infrastructure/docker/webhooks/doc.go | 18 +++ 11 files changed, 210 insertions(+), 198 deletions(-) delete mode 100644 test/infrastructure/docker/config/webhook/manifests.yaml create mode 100644 test/infrastructure/docker/internal/webhooks/doc.go rename test/infrastructure/docker/{api/v1beta1 => internal/webhooks}/dockercluster_webhook.go (57%) rename test/infrastructure/docker/{api/v1beta1 => internal/webhooks}/dockerclustertemplate_webhook.go (56%) rename test/infrastructure/docker/{api/v1beta1 => internal/webhooks}/dockerclustertemplate_webhook_test.go (76%) rename test/infrastructure/docker/{api/v1beta1 => internal/webhooks}/dockermachinetemplate_webhook.go (71%) rename test/infrastructure/docker/{api/v1beta1 => internal/webhooks}/dockermachinetemplate_webhook_test.go (88%) create mode 100644 test/infrastructure/docker/webhooks/alias.go create mode 100644 test/infrastructure/docker/webhooks/doc.go diff --git a/Makefile b/Makefile index ada862215e1d..2a0916a12748 100644 --- a/Makefile +++ b/Makefile @@ -334,7 +334,7 @@ generate-manifests-kubeadm-control-plane: $(CONTROLLER_GEN) ## Generate manifest .PHONY: generate-manifests-docker-infrastructure generate-manifests-docker-infrastructure: $(CONTROLLER_GEN) ## Generate manifests e.g. CRD, RBAC etc. for docker infrastructure provider - $(MAKE) clean-generated-yaml SRC_DIRS="$(CAPD_DIR)/config/crd/bases" + $(MAKE) clean-generated-yaml SRC_DIRS="$(CAPD_DIR)/config/crd/bases,$(CAPD_DIR)/config/webhook/manifests.yaml" cd $(CAPD_DIR); $(CONTROLLER_GEN) \ paths=./ \ paths=./api/... \ @@ -377,6 +377,7 @@ generate-go-deepcopy-core: $(CONTROLLER_GEN) ## Generate deepcopy go code for co paths=./$(EXP_DIR)/runtime/api/... \ paths=./$(EXP_DIR)/runtime/hooks/api/... \ paths=./internal/runtime/test/... \ + paths=./internal/webhooks/... \ paths=./cmd/clusterctl/... \ paths=./internal/test/builder/... diff --git a/test/infrastructure/docker/config/webhook/manifests.yaml b/test/infrastructure/docker/config/webhook/manifests.yaml deleted file mode 100644 index 640f08cc71d9..000000000000 --- a/test/infrastructure/docker/config/webhook/manifests.yaml +++ /dev/null @@ -1,122 +0,0 @@ ---- -apiVersion: admissionregistration.k8s.io/v1 -kind: MutatingWebhookConfiguration -metadata: - name: mutating-webhook-configuration -webhooks: -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: webhook-service - namespace: system - path: /mutate-infrastructure-cluster-x-k8s-io-v1beta1-dockercluster - failurePolicy: Fail - matchPolicy: Equivalent - name: default.dockercluster.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1beta1 - operations: - - CREATE - - UPDATE - resources: - - dockerclusters - sideEffects: None -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: webhook-service - namespace: system - path: /mutate-infrastructure-cluster-x-k8s-io-v1beta1-dockerclustertemplate - failurePolicy: Fail - matchPolicy: Equivalent - name: default.dockerclustertemplate.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1beta1 - operations: - - CREATE - - UPDATE - resources: - - dockerclustertemplates - sideEffects: None ---- -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: validating-webhook-configuration -webhooks: -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: webhook-service - namespace: system - path: /validate-infrastructure-cluster-x-k8s-io-v1beta1-dockercluster - failurePolicy: Fail - matchPolicy: Equivalent - name: validation.dockercluster.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1beta1 - operations: - - CREATE - - UPDATE - resources: - - dockerclusters - sideEffects: None -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: webhook-service - namespace: system - path: /validate-infrastructure-cluster-x-k8s-io-v1beta1-dockerclustertemplate - failurePolicy: Fail - matchPolicy: Equivalent - name: validation.dockerclustertemplate.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1beta1 - operations: - - CREATE - - UPDATE - resources: - - dockerclustertemplates - sideEffects: None -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: webhook-service - namespace: system - path: /validate-infrastructure-cluster-x-k8s-io-v1beta1-dockermachinetemplate - failurePolicy: Fail - matchPolicy: Equivalent - name: validation.dockermachinetemplate.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1beta1 - operations: - - CREATE - - UPDATE - resources: - - dockermachinetemplates - sideEffects: None diff --git a/test/infrastructure/docker/internal/webhooks/doc.go b/test/infrastructure/docker/internal/webhooks/doc.go new file mode 100644 index 000000000000..414d736e1098 --- /dev/null +++ b/test/infrastructure/docker/internal/webhooks/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2023 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 webhooks implements docker infrastructure webhooks. +package webhooks diff --git a/test/infrastructure/docker/api/v1beta1/dockercluster_webhook.go b/test/infrastructure/docker/internal/webhooks/dockercluster_webhook.go similarity index 57% rename from test/infrastructure/docker/api/v1beta1/dockercluster_webhook.go rename to test/infrastructure/docker/internal/webhooks/dockercluster_webhook.go index f748fc56cc3a..1b3b7399def8 100644 --- a/test/infrastructure/docker/api/v1beta1/dockercluster_webhook.go +++ b/test/infrastructure/docker/internal/webhooks/dockercluster_webhook.go @@ -14,60 +14,79 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1beta1 +package webhooks import ( + "context" + "fmt" + apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + infrav1 "sigs.k8s.io/cluster-api/test/infrastructure/docker/api/v1beta1" ) -func (c *DockerCluster) SetupWebhookWithManager(mgr ctrl.Manager) error { +// DockerCluster implements a validating and defaulting webhook for DockerCluster. +type DockerCluster struct{} + +func (webhook *DockerCluster) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). - For(c). + For(&infrav1.DockerCluster{}). + WithDefaulter(webhook). + WithValidator(webhook). Complete() } // +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1beta1-dockercluster,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=dockerclusters,versions=v1beta1,name=default.dockercluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 -var _ webhook.Defaulter = &DockerCluster{} +var _ webhook.CustomDefaulter = &DockerCluster{} // Default implements webhook.Defaulter so a webhook will be registered for the type. -func (c *DockerCluster) Default() { - defaultDockerClusterSpec(&c.Spec) +func (webhook *DockerCluster) Default(_ context.Context, obj runtime.Object) error { + cluster, ok := obj.(*infrav1.DockerCluster) + if !ok { + return apierrors.NewBadRequest(fmt.Sprintf("expected a DockerCluster but got a %T", obj)) + } + defaultDockerClusterSpec(&cluster.Spec) + return nil } // +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-dockercluster,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=dockerclusters,versions=v1beta1,name=validation.dockercluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 -var _ webhook.Validator = &DockerCluster{} +var _ webhook.CustomValidator = &DockerCluster{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (c *DockerCluster) ValidateCreate() (admission.Warnings, error) { - if allErrs := validateDockerClusterSpec(c.Spec); len(allErrs) > 0 { - return nil, apierrors.NewInvalid(GroupVersion.WithKind("DockerCluster").GroupKind(), c.Name, allErrs) +func (webhook *DockerCluster) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { + cluster, ok := obj.(*infrav1.DockerCluster) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a DockerCluster but got a %T", obj)) + } + if allErrs := validateDockerClusterSpec(cluster.Spec); len(allErrs) > 0 { + return nil, apierrors.NewInvalid(infrav1.GroupVersion.WithKind("DockerCluster").GroupKind(), cluster.Name, allErrs) } return nil, nil } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (c *DockerCluster) ValidateUpdate(_ runtime.Object) (admission.Warnings, error) { +func (webhook *DockerCluster) ValidateUpdate(_ context.Context, _, _ runtime.Object) (admission.Warnings, error) { return nil, nil } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (c *DockerCluster) ValidateDelete() (admission.Warnings, error) { +func (webhook *DockerCluster) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { return nil, nil } -func defaultDockerClusterSpec(s *DockerClusterSpec) { +func defaultDockerClusterSpec(s *infrav1.DockerClusterSpec) { if s.ControlPlaneEndpoint.Port == 0 { s.ControlPlaneEndpoint.Port = 6443 } } -func validateDockerClusterSpec(_ DockerClusterSpec) field.ErrorList { +func validateDockerClusterSpec(_ infrav1.DockerClusterSpec) field.ErrorList { return nil } diff --git a/test/infrastructure/docker/api/v1beta1/dockerclustertemplate_webhook.go b/test/infrastructure/docker/internal/webhooks/dockerclustertemplate_webhook.go similarity index 56% rename from test/infrastructure/docker/api/v1beta1/dockerclustertemplate_webhook.go rename to test/infrastructure/docker/internal/webhooks/dockerclustertemplate_webhook.go index 5492ec952a4a..b77f0868a228 100644 --- a/test/infrastructure/docker/api/v1beta1/dockerclustertemplate_webhook.go +++ b/test/infrastructure/docker/internal/webhooks/dockerclustertemplate_webhook.go @@ -14,9 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1beta1 +package webhooks import ( + "context" "fmt" "reflect" @@ -28,31 +29,42 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "sigs.k8s.io/cluster-api/feature" + infrav1 "sigs.k8s.io/cluster-api/test/infrastructure/docker/api/v1beta1" ) const dockerClusterTemplateImmutableMsg = "DockerClusterTemplate spec.template.spec field is immutable. Please create a new resource instead." -func (r *DockerClusterTemplate) SetupWebhookWithManager(mgr ctrl.Manager) error { +// DockerClusterTemplate implements a validating and defaulting webhook for DockerClusterTemplate. +type DockerClusterTemplate struct{} + +func (webhook *DockerClusterTemplate) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). - For(r). + For(&infrav1.DockerClusterTemplate{}). + WithDefaulter(webhook). + WithValidator(webhook). Complete() } // +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1beta1-dockerclustertemplate,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=dockerclustertemplates,versions=v1beta1,name=default.dockerclustertemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 -var _ webhook.Defaulter = &DockerClusterTemplate{} +var _ webhook.CustomDefaulter = &DockerClusterTemplate{} // Default implements webhook.Defaulter so a webhook will be registered for the type. -func (r *DockerClusterTemplate) Default() { - defaultDockerClusterSpec(&r.Spec.Template.Spec) +func (webhook *DockerClusterTemplate) Default(_ context.Context, obj runtime.Object) error { + clusterTemplate, ok := obj.(*infrav1.DockerClusterTemplate) + if !ok { + return apierrors.NewBadRequest(fmt.Sprintf("expected a DockerClusterTemplate but got a %T", obj)) + } + defaultDockerClusterSpec(&clusterTemplate.Spec.Template.Spec) + return nil } // +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-dockerclustertemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=dockerclustertemplates,versions=v1beta1,name=validation.dockerclustertemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 -var _ webhook.Validator = &DockerClusterTemplate{} +var _ webhook.CustomValidator = &DockerClusterTemplate{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (r *DockerClusterTemplate) ValidateCreate() (admission.Warnings, error) { +func (webhook *DockerClusterTemplate) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { // NOTE: DockerClusterTemplate is behind ClusterTopology feature gate flag; the web hook // must prevent creating new objects in case the feature flag is disabled. if !feature.Gates.Enabled(feature.ClusterTopology) { @@ -62,34 +74,43 @@ func (r *DockerClusterTemplate) ValidateCreate() (admission.Warnings, error) { ) } - allErrs := validateDockerClusterSpec(r.Spec.Template.Spec) + clusterTemplate, ok := obj.(*infrav1.DockerClusterTemplate) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a DockerClusterTemplate but got a %T", obj)) + } + + allErrs := validateDockerClusterSpec(clusterTemplate.Spec.Template.Spec) // Validate the metadata of the template. - allErrs = append(allErrs, r.Spec.Template.ObjectMeta.Validate(field.NewPath("spec", "template", "metadata"))...) + allErrs = append(allErrs, clusterTemplate.Spec.Template.ObjectMeta.Validate(field.NewPath("spec", "template", "metadata"))...) if len(allErrs) > 0 { - return nil, apierrors.NewInvalid(GroupVersion.WithKind("DockerClusterTemplate").GroupKind(), r.Name, allErrs) + return nil, apierrors.NewInvalid(infrav1.GroupVersion.WithKind("DockerClusterTemplate").GroupKind(), clusterTemplate.Name, allErrs) } return nil, nil } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (r *DockerClusterTemplate) ValidateUpdate(oldRaw runtime.Object) (admission.Warnings, error) { +func (webhook *DockerClusterTemplate) ValidateUpdate(_ context.Context, oldRaw, newRaw runtime.Object) (admission.Warnings, error) { var allErrs field.ErrorList - old, ok := oldRaw.(*DockerClusterTemplate) + oldTemplate, ok := oldRaw.(*infrav1.DockerClusterTemplate) if !ok { return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a DockerClusterTemplate but got a %T", oldRaw)) } - if !reflect.DeepEqual(r.Spec.Template.Spec, old.Spec.Template.Spec) { - allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "template", "spec"), r, dockerClusterTemplateImmutableMsg)) + newTemplate, ok := newRaw.(*infrav1.DockerClusterTemplate) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a DockerClusterTemplate but got a %T", newRaw)) + } + if !reflect.DeepEqual(newTemplate.Spec.Template.Spec, oldTemplate.Spec.Template.Spec) { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "template", "spec"), newTemplate, dockerClusterTemplateImmutableMsg)) } if len(allErrs) == 0 { return nil, nil } - return nil, apierrors.NewInvalid(GroupVersion.WithKind("DockerClusterTemplate").GroupKind(), r.Name, allErrs) + return nil, apierrors.NewInvalid(infrav1.GroupVersion.WithKind("DockerClusterTemplate").GroupKind(), newTemplate.Name, allErrs) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (r *DockerClusterTemplate) ValidateDelete() (admission.Warnings, error) { +func (webhook *DockerClusterTemplate) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { return nil, nil } diff --git a/test/infrastructure/docker/api/v1beta1/dockerclustertemplate_webhook_test.go b/test/infrastructure/docker/internal/webhooks/dockerclustertemplate_webhook_test.go similarity index 76% rename from test/infrastructure/docker/api/v1beta1/dockerclustertemplate_webhook_test.go rename to test/infrastructure/docker/internal/webhooks/dockerclustertemplate_webhook_test.go index 4244684d4a68..8be0ebb8d2d0 100644 --- a/test/infrastructure/docker/api/v1beta1/dockerclustertemplate_webhook_test.go +++ b/test/infrastructure/docker/internal/webhooks/dockerclustertemplate_webhook_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1beta1 +package webhooks import ( "strings" @@ -23,28 +23,33 @@ import ( . "github.com/onsi/gomega" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilfeature "k8s.io/component-base/featuregate/testing" + ctrl "sigs.k8s.io/controller-runtime" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/feature" + infrav1 "sigs.k8s.io/cluster-api/test/infrastructure/docker/api/v1beta1" ) +var ctx = ctrl.SetupSignalHandler() + func TestDockerClusterTemplateValidationFeatureGateEnabled(t *testing.T) { defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.ClusterTopology, true)() t.Run("create dockerclustertemplate should pass if gate enabled and valid dockerclustertemplate", func(t *testing.T) { g := NewWithT(t) - dct := &DockerClusterTemplate{ + dct := &infrav1.DockerClusterTemplate{ ObjectMeta: metav1.ObjectMeta{ Name: "dockerclustertemplate-test", Namespace: "test-namespace", }, - Spec: DockerClusterTemplateSpec{ - Template: DockerClusterTemplateResource{ - Spec: DockerClusterSpec{}, + Spec: infrav1.DockerClusterTemplateSpec{ + Template: infrav1.DockerClusterTemplateResource{ + Spec: infrav1.DockerClusterSpec{}, }, }, } - warnings, err := dct.ValidateCreate() + webhook := DockerClusterTemplate{} + warnings, err := webhook.ValidateCreate(ctx, dct) g.Expect(err).ToNot(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) }) @@ -54,18 +59,19 @@ func TestDockerClusterTemplateValidationFeatureGateDisabled(t *testing.T) { // NOTE: ClusterTopology feature flag is disabled by default, thus preventing to create DockerClusterTemplate. t.Run("create dockerclustertemplate should not pass if gate disabled and valid dockerclustertemplate", func(t *testing.T) { g := NewWithT(t) - dct := &DockerClusterTemplate{ + dct := &infrav1.DockerClusterTemplate{ ObjectMeta: metav1.ObjectMeta{ Name: "dockerclustertemplate-test", Namespace: "test-namespace", }, - Spec: DockerClusterTemplateSpec{ - Template: DockerClusterTemplateResource{ - Spec: DockerClusterSpec{}, + Spec: infrav1.DockerClusterTemplateSpec{ + Template: infrav1.DockerClusterTemplateResource{ + Spec: infrav1.DockerClusterSpec{}, }, }, } - warnings, err := dct.ValidateCreate() + webhook := DockerClusterTemplate{} + warnings, err := webhook.ValidateCreate(ctx, dct) g.Expect(err).To(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) }) @@ -97,13 +103,13 @@ func TestDockerClusterTemplateValidationMetadata(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { g := NewWithT(t) - dct := &DockerClusterTemplate{ + dct := &infrav1.DockerClusterTemplate{ ObjectMeta: metav1.ObjectMeta{ Name: "dockerclustertemplate-test", Namespace: "test-namespace", }, - Spec: DockerClusterTemplateSpec{ - Template: DockerClusterTemplateResource{ + Spec: infrav1.DockerClusterTemplateSpec{ + Template: infrav1.DockerClusterTemplateResource{ ObjectMeta: clusterv1.ObjectMeta{ Labels: map[string]string{ "foo": "$invalid-key", @@ -114,11 +120,12 @@ func TestDockerClusterTemplateValidationMetadata(t *testing.T) { "/invalid-key": "foo", }, }, - Spec: DockerClusterSpec{}, + Spec: infrav1.DockerClusterSpec{}, }, }, } - warnings, err := dct.ValidateCreate() + webhook := DockerClusterTemplate{} + warnings, err := webhook.ValidateCreate(ctx, dct) if tt.expectErr { g.Expect(err).To(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) diff --git a/test/infrastructure/docker/api/v1beta1/dockermachinetemplate_webhook.go b/test/infrastructure/docker/internal/webhooks/dockermachinetemplate_webhook.go similarity index 71% rename from test/infrastructure/docker/api/v1beta1/dockermachinetemplate_webhook.go rename to test/infrastructure/docker/internal/webhooks/dockermachinetemplate_webhook.go index 52d1e1f50a53..38225d49d6b2 100644 --- a/test/infrastructure/docker/api/v1beta1/dockermachinetemplate_webhook.go +++ b/test/infrastructure/docker/internal/webhooks/dockermachinetemplate_webhook.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1beta1 +package webhooks import ( "context" @@ -28,47 +28,48 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + infrav1 "sigs.k8s.io/cluster-api/test/infrastructure/docker/api/v1beta1" "sigs.k8s.io/cluster-api/util/topology" ) const dockerMachineTemplateImmutableMsg = "DockerMachineTemplate spec.template.spec field is immutable. Please create a new resource instead." -func (m *DockerMachineTemplateWebhook) SetupWebhookWithManager(mgr ctrl.Manager) error { +func (webhook *DockerMachineTemplate) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). - For(&DockerMachineTemplate{}). - WithValidator(m). + For(&infrav1.DockerMachineTemplate{}). + WithValidator(webhook). Complete() } // +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-dockermachinetemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=dockermachinetemplates,versions=v1beta1,name=validation.dockermachinetemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 -// DockerMachineTemplateWebhook implements a custom validation webhook for DockerMachineTemplate. +// DockerMachineTemplate implements a custom validation webhook for DockerMachineTemplate. // +kubebuilder:object:generate=false -type DockerMachineTemplateWebhook struct{} +type DockerMachineTemplate struct{} -var _ webhook.CustomValidator = &DockerMachineTemplateWebhook{} +var _ webhook.CustomValidator = &DockerMachineTemplate{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (*DockerMachineTemplateWebhook) ValidateCreate(_ context.Context, raw runtime.Object) (admission.Warnings, error) { - obj, ok := raw.(*DockerMachineTemplate) +func (webhook *DockerMachineTemplate) ValidateCreate(_ context.Context, raw runtime.Object) (admission.Warnings, error) { + obj, ok := raw.(*infrav1.DockerMachineTemplate) if !ok { return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a DockerMachineTemplate but got a %T", raw)) } // Validate the metadata of the template. allErrs := obj.Spec.Template.ObjectMeta.Validate(field.NewPath("spec", "template", "metadata")) if len(allErrs) > 0 { - return nil, apierrors.NewInvalid(GroupVersion.WithKind("DockerClusterTemplate").GroupKind(), obj.Name, allErrs) + return nil, apierrors.NewInvalid(infrav1.GroupVersion.WithKind("DockerClusterTemplate").GroupKind(), obj.Name, allErrs) } return nil, nil } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (*DockerMachineTemplateWebhook) ValidateUpdate(ctx context.Context, oldRaw runtime.Object, newRaw runtime.Object) (admission.Warnings, error) { - newObj, ok := newRaw.(*DockerMachineTemplate) +func (webhook *DockerMachineTemplate) ValidateUpdate(ctx context.Context, oldRaw runtime.Object, newRaw runtime.Object) (admission.Warnings, error) { + newObj, ok := newRaw.(*infrav1.DockerMachineTemplate) if !ok { return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a DockerMachineTemplate but got a %T", newRaw)) } - oldObj, ok := oldRaw.(*DockerMachineTemplate) + oldObj, ok := oldRaw.(*infrav1.DockerMachineTemplate) if !ok { return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a DockerMachineTemplate but got a %T", oldRaw)) } @@ -89,10 +90,10 @@ func (*DockerMachineTemplateWebhook) ValidateUpdate(ctx context.Context, oldRaw if len(allErrs) == 0 { return nil, nil } - return nil, apierrors.NewInvalid(GroupVersion.WithKind("DockerMachineTemplate").GroupKind(), newObj.Name, allErrs) + return nil, apierrors.NewInvalid(infrav1.GroupVersion.WithKind("DockerMachineTemplate").GroupKind(), newObj.Name, allErrs) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (*DockerMachineTemplateWebhook) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { +func (webhook *DockerMachineTemplate) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { return nil, nil } diff --git a/test/infrastructure/docker/api/v1beta1/dockermachinetemplate_webhook_test.go b/test/infrastructure/docker/internal/webhooks/dockermachinetemplate_webhook_test.go similarity index 88% rename from test/infrastructure/docker/api/v1beta1/dockermachinetemplate_webhook_test.go rename to test/infrastructure/docker/internal/webhooks/dockermachinetemplate_webhook_test.go index 0d11343c9a4e..cc51e96cbeb9 100644 --- a/test/infrastructure/docker/api/v1beta1/dockermachinetemplate_webhook_test.go +++ b/test/infrastructure/docker/internal/webhooks/dockermachinetemplate_webhook_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1beta1 +package webhooks import ( "context" @@ -28,18 +28,19 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + infrav1 "sigs.k8s.io/cluster-api/test/infrastructure/docker/api/v1beta1" ) func TestDockerMachineTemplateInvalid(t *testing.T) { - oldTemplate := DockerMachineTemplate{ + oldTemplate := infrav1.DockerMachineTemplate{ ObjectMeta: metav1.ObjectMeta{}, - Spec: DockerMachineTemplateSpec{ - Template: DockerMachineTemplateResource{}, + Spec: infrav1.DockerMachineTemplateSpec{ + Template: infrav1.DockerMachineTemplateResource{}, }, } newTemplate := oldTemplate.DeepCopy() - newTemplate.Spec.Template.Spec.ExtraMounts = append(newTemplate.Spec.Template.Spec.ExtraMounts, []Mount{{ContainerPath: "/var/run/docker.sock", HostPath: "/var/run/docker.sock"}}...) + newTemplate.Spec.Template.Spec.ExtraMounts = append(newTemplate.Spec.Template.Spec.ExtraMounts, []infrav1.Mount{{ContainerPath: "/var/run/docker.sock", HostPath: "/var/run/docker.sock"}}...) newTemplateSkipImmutabilityAnnotationSet := newTemplate.DeepCopy() newTemplateSkipImmutabilityAnnotationSet.SetAnnotations(map[string]string{clusterv1.TopologyDryRunAnnotation: ""}) @@ -57,8 +58,8 @@ func TestDockerMachineTemplateInvalid(t *testing.T) { tests := []struct { name string - newTemplate *DockerMachineTemplate - oldTemplate *DockerMachineTemplate + newTemplate *infrav1.DockerMachineTemplate + oldTemplate *infrav1.DockerMachineTemplate req *admission.Request wantError bool }{ @@ -108,7 +109,7 @@ func TestDockerMachineTemplateInvalid(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { g := NewWithT(t) - wh := &DockerMachineTemplateWebhook{} + wh := &DockerMachineTemplate{} ctx := context.Background() if tt.req != nil { ctx = admission.NewContextWithRequest(ctx, *tt.req) diff --git a/test/infrastructure/docker/main.go b/test/infrastructure/docker/main.go index 15b0ca43b70d..061661d43f60 100644 --- a/test/infrastructure/docker/main.go +++ b/test/infrastructure/docker/main.go @@ -55,7 +55,8 @@ import ( infraexpv1alpha4 "sigs.k8s.io/cluster-api/test/infrastructure/docker/exp/api/v1alpha4" infraexpv1 "sigs.k8s.io/cluster-api/test/infrastructure/docker/exp/api/v1beta1" expcontrollers "sigs.k8s.io/cluster-api/test/infrastructure/docker/exp/controllers" - "sigs.k8s.io/cluster-api/test/infrastructure/docker/exp/webhooks" + infraexpwebhooks "sigs.k8s.io/cluster-api/test/infrastructure/docker/exp/webhooks" + infrawebhooks "sigs.k8s.io/cluster-api/test/infrastructure/docker/webhooks" "sigs.k8s.io/cluster-api/util/flags" "sigs.k8s.io/cluster-api/version" ) @@ -362,23 +363,23 @@ func setupReconcilers(ctx context.Context, mgr ctrl.Manager) { } func setupWebhooks(mgr ctrl.Manager) { - if err := (&infrav1.DockerMachineTemplateWebhook{}).SetupWebhookWithManager(mgr); err != nil { + if err := (&infrawebhooks.DockerMachineTemplate{}).SetupWebhookWithManager(mgr); err != nil { setupLog.Error(err, "unable to create webhook", "webhook", "DockerMachineTemplate") os.Exit(1) } - if err := (&infrav1.DockerCluster{}).SetupWebhookWithManager(mgr); err != nil { + if err := (&infrawebhooks.DockerCluster{}).SetupWebhookWithManager(mgr); err != nil { setupLog.Error(err, "unable to create webhook", "webhook", "DockerCluster") os.Exit(1) } - if err := (&infrav1.DockerClusterTemplate{}).SetupWebhookWithManager(mgr); err != nil { + if err := (&infrawebhooks.DockerClusterTemplate{}).SetupWebhookWithManager(mgr); err != nil { setupLog.Error(err, "unable to create webhook", "webhook", "DockerClusterTemplate") os.Exit(1) } if feature.Gates.Enabled(feature.MachinePool) { - if err := (&webhooks.DockerMachinePool{}).SetupWebhookWithManager(mgr); err != nil { + if err := (&infraexpwebhooks.DockerMachinePool{}).SetupWebhookWithManager(mgr); err != nil { setupLog.Error(err, "unable to create webhook", "webhook", "DockerMachinePool") os.Exit(1) } diff --git a/test/infrastructure/docker/webhooks/alias.go b/test/infrastructure/docker/webhooks/alias.go new file mode 100644 index 000000000000..099943b364bd --- /dev/null +++ b/test/infrastructure/docker/webhooks/alias.go @@ -0,0 +1,47 @@ +/* +Copyright 2023 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 webhooks + +import ( + ctrl "sigs.k8s.io/controller-runtime" + + "sigs.k8s.io/cluster-api/test/infrastructure/docker/internal/webhooks" +) + +// DockerCluster implements a validating and defaulting webhook for DockerCluster. +type DockerCluster struct{} + +// SetupWebhookWithManager sets up ClusterResourceSet webhooks. +func (webhook *DockerCluster) SetupWebhookWithManager(mgr ctrl.Manager) error { + return (&webhooks.DockerCluster{}).SetupWebhookWithManager(mgr) +} + +// DockerClusterTemplate implements a validating webhook for DockerClusterTemplate. +type DockerClusterTemplate struct{} + +// SetupWebhookWithManager sets up ClusterResourceSet webhooks. +func (webhook *DockerClusterTemplate) SetupWebhookWithManager(mgr ctrl.Manager) error { + return (&webhooks.DockerClusterTemplate{}).SetupWebhookWithManager(mgr) +} + +// DockerMachineTemplate implements a validating webhook for DockerMachineTemplate. +type DockerMachineTemplate struct{} + +// SetupWebhookWithManager sets up ClusterResourceSet webhooks. +func (webhook *DockerMachineTemplate) SetupWebhookWithManager(mgr ctrl.Manager) error { + return (&webhooks.DockerMachineTemplate{}).SetupWebhookWithManager(mgr) +} diff --git a/test/infrastructure/docker/webhooks/doc.go b/test/infrastructure/docker/webhooks/doc.go new file mode 100644 index 000000000000..ee04e4e6deeb --- /dev/null +++ b/test/infrastructure/docker/webhooks/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2023 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 webhooks contains docker infrastructure webhook implementations for some of our API types. +package webhooks