From 466443d9e979fb7dd81c01ce318adb0daba611e9 Mon Sep 17 00:00:00 2001 From: swamyan Date: Wed, 13 Sep 2023 19:43:39 +0530 Subject: [PATCH] Move experimental API v1beta1 webhooks to separate package --- exp/internal/webhooks/doc.go | 18 +++ .../webhooks/machinepool.go} | 73 ++++++---- .../webhooks/machinepool_test.go} | 137 ++++++++++-------- exp/webhooks/alias.go | 31 ++++ exp/webhooks/doc.go | 18 +++ internal/test/envtest/environment.go | 3 +- main.go | 3 +- 7 files changed, 195 insertions(+), 88 deletions(-) create mode 100644 exp/internal/webhooks/doc.go rename exp/{api/v1beta1/machinepool_webhook.go => internal/webhooks/machinepool.go} (62%) rename exp/{api/v1beta1/machinepool_webhook_test.go => internal/webhooks/machinepool_test.go} (74%) create mode 100644 exp/webhooks/alias.go create mode 100644 exp/webhooks/doc.go diff --git a/exp/internal/webhooks/doc.go b/exp/internal/webhooks/doc.go new file mode 100644 index 000000000000..ad3cd005e864 --- /dev/null +++ b/exp/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 contains external webhook implementations for some of our API types. +package webhooks diff --git a/exp/api/v1beta1/machinepool_webhook.go b/exp/internal/webhooks/machinepool.go similarity index 62% rename from exp/api/v1beta1/machinepool_webhook.go rename to exp/internal/webhooks/machinepool.go index 8dfd0d6b07e9..d06fcf778367 100644 --- a/exp/api/v1beta1/machinepool_webhook.go +++ b/exp/internal/webhooks/machinepool.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" "strings" @@ -29,24 +30,37 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1" "sigs.k8s.io/cluster-api/feature" "sigs.k8s.io/cluster-api/util/version" ) -func (m *MachinePool) SetupWebhookWithManager(mgr ctrl.Manager) error { +// MachinePool implements a validation and defaulting webhook for MachinePool. +type MachinePool struct { + *expv1.MachinePool +} + +func (webhook *MachinePool) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). - For(m). + For(&expv1.MachinePool{}). + WithDefaulter(webhook). + WithValidator(webhook). Complete() } // +kubebuilder:webhook:verbs=create;update,path=/validate-cluster-x-k8s-io-v1beta1-machinepool,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=cluster.x-k8s.io,resources=machinepools,versions=v1beta1,name=validation.machinepool.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 // +kubebuilder:webhook:verbs=create;update,path=/mutate-cluster-x-k8s-io-v1beta1-machinepool,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=cluster.x-k8s.io,resources=machinepools,versions=v1beta1,name=default.machinepool.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 -var _ webhook.Defaulter = &MachinePool{} -var _ webhook.Validator = &MachinePool{} +var _ webhook.CustomDefaulter = &MachinePool{} +var _ webhook.CustomValidator = &MachinePool{} // Default implements webhook.Defaulter so a webhook will be registered for the type. -func (m *MachinePool) Default() { +func (webhook *MachinePool) Default(_ context.Context, obj runtime.Object) error { + m, ok := obj.(*expv1.MachinePool) + if !ok { + return apierrors.NewBadRequest(fmt.Sprintf("expected a MachinePool but got a %T", obj)) + } + if m.Labels == nil { m.Labels = make(map[string]string) } @@ -73,30 +87,35 @@ func (m *MachinePool) Default() { normalizedVersion := "v" + *m.Spec.Template.Spec.Version m.Spec.Template.Spec.Version = &normalizedVersion } + return nil } // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (m *MachinePool) ValidateCreate() (admission.Warnings, error) { - return nil, m.validate(nil) +func (webhook *MachinePool) ValidateCreate(_ context.Context, _ runtime.Object) (admission.Warnings, error) { + return nil, webhook.validate(nil, nil) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. -func (m *MachinePool) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { - oldMP, ok := old.(*MachinePool) +func (webhook *MachinePool) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { + oldMP, ok := oldObj.(*MachinePool) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a MachinePool but got a %T", oldObj)) + } + newMP, ok := newObj.(*MachinePool) if !ok { - return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a MachinePool but got a %T", old)) + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a MachinePool but got a %T", newObj)) } - return nil, m.validate(oldMP) + return nil, webhook.validate(oldMP, newMP) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type. -func (m *MachinePool) ValidateDelete() (admission.Warnings, error) { - return nil, m.validate(nil) +func (webhook *MachinePool) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { + return nil, webhook.validate(nil, nil) } -func (m *MachinePool) validate(old *MachinePool) error { +func (webhook *MachinePool) validate(oldObj, newObj *MachinePool) error { // NOTE: MachinePool is behind MachinePool feature gate flag; the web hook - // must prevent creating new objects when the feature flag is disabled. + // must prevent creating newObj objects when the feature flag is disabled. specPath := field.NewPath("spec") if !feature.Gates.Enabled(feature.MachinePool) { return field.Forbidden( @@ -105,7 +124,7 @@ func (m *MachinePool) validate(old *MachinePool) error { ) } var allErrs field.ErrorList - if m.Spec.Template.Spec.Bootstrap.ConfigRef == nil && m.Spec.Template.Spec.Bootstrap.DataSecretName == nil { + if newObj.Spec.Template.Spec.Bootstrap.ConfigRef == nil && newObj.Spec.Template.Spec.Bootstrap.DataSecretName == nil { allErrs = append( allErrs, field.Required( @@ -115,29 +134,29 @@ func (m *MachinePool) validate(old *MachinePool) error { ) } - if m.Spec.Template.Spec.Bootstrap.ConfigRef != nil && m.Spec.Template.Spec.Bootstrap.ConfigRef.Namespace != m.Namespace { + if newObj.Spec.Template.Spec.Bootstrap.ConfigRef != nil && newObj.Spec.Template.Spec.Bootstrap.ConfigRef.Namespace != newObj.Namespace { allErrs = append( allErrs, field.Invalid( specPath.Child("template", "spec", "bootstrap", "configRef", "namespace"), - m.Spec.Template.Spec.Bootstrap.ConfigRef.Namespace, + newObj.Spec.Template.Spec.Bootstrap.ConfigRef.Namespace, "must match metadata.namespace", ), ) } - if m.Spec.Template.Spec.InfrastructureRef.Namespace != m.Namespace { + if newObj.Spec.Template.Spec.InfrastructureRef.Namespace != newObj.Namespace { allErrs = append( allErrs, field.Invalid( specPath.Child("infrastructureRef", "namespace"), - m.Spec.Template.Spec.InfrastructureRef.Namespace, + newObj.Spec.Template.Spec.InfrastructureRef.Namespace, "must match metadata.namespace", ), ) } - if old != nil && old.Spec.ClusterName != m.Spec.ClusterName { + if oldObj != nil && oldObj.Spec.ClusterName != newObj.Spec.ClusterName { allErrs = append( allErrs, field.Forbidden( @@ -146,17 +165,17 @@ func (m *MachinePool) validate(old *MachinePool) error { ) } - if m.Spec.Template.Spec.Version != nil { - if !version.KubeSemver.MatchString(*m.Spec.Template.Spec.Version) { - allErrs = append(allErrs, field.Invalid(specPath.Child("template", "spec", "version"), *m.Spec.Template.Spec.Version, "must be a valid semantic version")) + if newObj.Spec.Template.Spec.Version != nil { + if !version.KubeSemver.MatchString(*newObj.Spec.Template.Spec.Version) { + allErrs = append(allErrs, field.Invalid(specPath.Child("template", "spec", "version"), *newObj.Spec.Template.Spec.Version, "must be a valid semantic version")) } } // Validate the metadata of the MachinePool template. - allErrs = append(allErrs, m.Spec.Template.ObjectMeta.Validate(specPath.Child("template", "metadata"))...) + allErrs = append(allErrs, newObj.Spec.Template.ObjectMeta.Validate(specPath.Child("template", "metadata"))...) if len(allErrs) == 0 { return nil } - return apierrors.NewInvalid(GroupVersion.WithKind("MachinePool").GroupKind(), m.Name, allErrs) + return apierrors.NewInvalid(clusterv1.GroupVersion.WithKind("MachinePool").GroupKind(), newObj.Name, allErrs) } diff --git a/exp/api/v1beta1/machinepool_webhook_test.go b/exp/internal/webhooks/machinepool_test.go similarity index 74% rename from exp/api/v1beta1/machinepool_webhook_test.go rename to exp/internal/webhooks/machinepool_test.go index 3b115bd2d1c1..e2c8a58c5218 100644 --- a/exp/api/v1beta1/machinepool_webhook_test.go +++ b/exp/internal/webhooks/machinepool_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" @@ -25,12 +25,16 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilfeature "k8s.io/component-base/featuregate/testing" "k8s.io/utils/pointer" + ctrl "sigs.k8s.io/controller-runtime" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1" "sigs.k8s.io/cluster-api/feature" - utildefaulting "sigs.k8s.io/cluster-api/util/defaulting" + "sigs.k8s.io/cluster-api/internal/webhooks/util" ) +var ctx = ctrl.SetupSignalHandler() + func TestMachinePoolDefault(t *testing.T) { // NOTE: MachinePool feature flag is disabled by default, thus preventing to create or update MachinePool. // Enabling the feature flag temporarily for this test. @@ -39,20 +43,23 @@ func TestMachinePoolDefault(t *testing.T) { g := NewWithT(t) m := &MachinePool{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "foobar", - }, - Spec: MachinePoolSpec{ - Template: clusterv1.MachineTemplateSpec{ - Spec: clusterv1.MachineSpec{ - Bootstrap: clusterv1.Bootstrap{ConfigRef: &corev1.ObjectReference{}}, - Version: pointer.String("1.20.0"), + &expv1.MachinePool{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "foobar", + }, + Spec: expv1.MachinePoolSpec{ + Template: clusterv1.MachineTemplateSpec{ + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ConfigRef: &corev1.ObjectReference{}}, + Version: pointer.String("1.20.0"), + }, }, }, }, } - t.Run("for MachinePool", utildefaulting.DefaultValidateTest(m)) - m.Default() + webhook := &MachinePool{} + t.Run("for Machine", util.CustomDefaultValidateTest(ctx, m, webhook)) + g.Expect(m.Default(ctx, m)).To(Succeed()) g.Expect(m.Labels[clusterv1.ClusterNameLabel]).To(Equal(m.Spec.ClusterName)) g.Expect(m.Spec.Replicas).To(Equal(pointer.Int32(1))) @@ -92,27 +99,29 @@ func TestMachinePoolBootstrapValidation(t *testing.T) { t.Run(tt.name, func(t *testing.T) { g := NewWithT(t) m := &MachinePool{ - Spec: MachinePoolSpec{ - Template: clusterv1.MachineTemplateSpec{ - Spec: clusterv1.MachineSpec{ - Bootstrap: tt.bootstrap, + &expv1.MachinePool{ + Spec: expv1.MachinePoolSpec{ + Template: clusterv1.MachineTemplateSpec{ + Spec: clusterv1.MachineSpec{ + Bootstrap: tt.bootstrap, + }, }, }, }, } if tt.expectErr { - warnings, err := m.ValidateCreate() + warnings, err := m.ValidateCreate(ctx, m) g.Expect(err).To(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) - warnings, err = m.ValidateUpdate(m) + warnings, err = m.ValidateUpdate(ctx, m, m) g.Expect(err).To(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) } else { - warnings, err := m.ValidateCreate() + warnings, err := m.ValidateCreate(ctx, m) g.Expect(err).ToNot(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) - warnings, err = m.ValidateUpdate(m) + warnings, err = m.ValidateUpdate(ctx, m, m) g.Expect(err).ToNot(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) } @@ -166,29 +175,31 @@ func TestMachinePoolNamespaceValidation(t *testing.T) { g := NewWithT(t) m := &MachinePool{ - ObjectMeta: metav1.ObjectMeta{Namespace: tt.namespace}, - Spec: MachinePoolSpec{ - Template: clusterv1.MachineTemplateSpec{ - Spec: clusterv1.MachineSpec{ - Bootstrap: tt.bootstrap, - InfrastructureRef: tt.infraRef, + &expv1.MachinePool{ + ObjectMeta: metav1.ObjectMeta{Namespace: tt.namespace}, + Spec: expv1.MachinePoolSpec{ + Template: clusterv1.MachineTemplateSpec{ + Spec: clusterv1.MachineSpec{ + Bootstrap: tt.bootstrap, + InfrastructureRef: tt.infraRef, + }, }, }, }, } if tt.expectErr { - warnings, err := m.ValidateCreate() + warnings, err := m.ValidateCreate(ctx, m) g.Expect(err).To(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) - warnings, err = m.ValidateUpdate(m) + warnings, err = m.ValidateUpdate(ctx, m, m) g.Expect(err).To(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) } else { - warnings, err := m.ValidateCreate() + warnings, err := m.ValidateCreate(ctx, m) g.Expect(err).ToNot(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) - warnings, err = m.ValidateUpdate(m) + warnings, err = m.ValidateUpdate(ctx, m, m) g.Expect(err).ToNot(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) } @@ -225,28 +236,32 @@ func TestMachinePoolClusterNameImmutable(t *testing.T) { g := NewWithT(t) newMP := &MachinePool{ - Spec: MachinePoolSpec{ - ClusterName: tt.newClusterName, - Template: clusterv1.MachineTemplateSpec{ - Spec: clusterv1.MachineSpec{ - Bootstrap: clusterv1.Bootstrap{ConfigRef: &corev1.ObjectReference{}}, + &expv1.MachinePool{ + Spec: expv1.MachinePoolSpec{ + ClusterName: tt.newClusterName, + Template: clusterv1.MachineTemplateSpec{ + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ConfigRef: &corev1.ObjectReference{}}, + }, }, }, }, } oldMP := &MachinePool{ - Spec: MachinePoolSpec{ - ClusterName: tt.oldClusterName, - Template: clusterv1.MachineTemplateSpec{ - Spec: clusterv1.MachineSpec{ - Bootstrap: clusterv1.Bootstrap{ConfigRef: &corev1.ObjectReference{}}, + &expv1.MachinePool{ + Spec: expv1.MachinePoolSpec{ + ClusterName: tt.oldClusterName, + Template: clusterv1.MachineTemplateSpec{ + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ConfigRef: &corev1.ObjectReference{}}, + }, }, }, }, } - warnings, err := newMP.ValidateUpdate(oldMP) + warnings, err := newMP.ValidateUpdate(ctx, oldMP, newMP) if tt.expectErr { g.Expect(err).To(HaveOccurred()) } else { @@ -293,28 +308,30 @@ func TestMachinePoolVersionValidation(t *testing.T) { g := NewWithT(t) m := &MachinePool{ - Spec: MachinePoolSpec{ - Template: clusterv1.MachineTemplateSpec{ - Spec: clusterv1.MachineSpec{ - Bootstrap: clusterv1.Bootstrap{ConfigRef: &corev1.ObjectReference{}}, - Version: &tt.version, + &expv1.MachinePool{ + Spec: expv1.MachinePoolSpec{ + Template: clusterv1.MachineTemplateSpec{ + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ConfigRef: &corev1.ObjectReference{}}, + Version: &tt.version, + }, }, }, }, } if tt.expectErr { - warnings, err := m.ValidateCreate() + warnings, err := m.ValidateCreate(ctx, m) g.Expect(err).To(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) - warnings, err = m.ValidateUpdate(m) + warnings, err = m.ValidateUpdate(ctx, m, m) g.Expect(err).To(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) } else { - warnings, err := m.ValidateCreate() + warnings, err := m.ValidateCreate(ctx, m) g.Expect(err).ToNot(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) - warnings, err = m.ValidateUpdate(m) + warnings, err = m.ValidateUpdate(ctx, m, m) g.Expect(err).ToNot(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) } @@ -347,27 +364,29 @@ func TestMachinePoolMetadataValidation(t *testing.T) { t.Run(tt.name, func(t *testing.T) { g := NewWithT(t) mp := &MachinePool{ - Spec: MachinePoolSpec{ - Template: clusterv1.MachineTemplateSpec{ - ObjectMeta: clusterv1.ObjectMeta{ - Labels: tt.labels, - Annotations: tt.annotations, + &expv1.MachinePool{ + Spec: expv1.MachinePoolSpec{ + Template: clusterv1.MachineTemplateSpec{ + ObjectMeta: clusterv1.ObjectMeta{ + Labels: tt.labels, + Annotations: tt.annotations, + }, }, }, }, } if tt.expectErr { - warnings, err := mp.ValidateCreate() + warnings, err := mp.ValidateCreate(ctx, mp) g.Expect(err).To(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) - warnings, err = mp.ValidateUpdate(mp) + warnings, err = mp.ValidateUpdate(ctx, mp, mp) g.Expect(err).To(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) } else { - warnings, err := mp.ValidateCreate() + warnings, err := mp.ValidateCreate(ctx, mp) g.Expect(err).ToNot(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) - warnings, err = mp.ValidateUpdate(mp) + warnings, err = mp.ValidateUpdate(ctx, mp, mp) g.Expect(err).ToNot(HaveOccurred()) g.Expect(warnings).To(BeEmpty()) } diff --git a/exp/webhooks/alias.go b/exp/webhooks/alias.go new file mode 100644 index 000000000000..21deef6e7651 --- /dev/null +++ b/exp/webhooks/alias.go @@ -0,0 +1,31 @@ +/* +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/exp/internal/webhooks" +) + +// MachinePool implements a validating and defaulting webhook for MachinePool. +type MachinePool struct{} + +// SetupWebhookWithManager sets up MachinePool webhooks. +func (webhook *MachinePool) SetupWebhookWithManager(mgr ctrl.Manager) error { + return (&webhooks.MachinePool{}).SetupWebhookWithManager(mgr) +} diff --git a/exp/webhooks/doc.go b/exp/webhooks/doc.go new file mode 100644 index 000000000000..5f6f8fd76b15 --- /dev/null +++ b/exp/webhooks/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2021 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 external webhook implementations for some of our API types. +package webhooks diff --git a/internal/test/envtest/environment.go b/internal/test/envtest/environment.go index e6028ce1f0ca..29389a14c612 100644 --- a/internal/test/envtest/environment.go +++ b/internal/test/envtest/environment.go @@ -59,6 +59,7 @@ import ( ipamv1 "sigs.k8s.io/cluster-api/exp/ipam/api/v1alpha1" expipamwebhooks "sigs.k8s.io/cluster-api/exp/ipam/webhooks" runtimev1 "sigs.k8s.io/cluster-api/exp/runtime/api/v1alpha1" + expapiwebhooks "sigs.k8s.io/cluster-api/exp/webhooks" "sigs.k8s.io/cluster-api/internal/test/builder" internalwebhooks "sigs.k8s.io/cluster-api/internal/webhooks" runtimewebhooks "sigs.k8s.io/cluster-api/internal/webhooks/runtime" @@ -309,7 +310,7 @@ func newEnvironment(uncachedObjs ...client.Object) *Environment { if err := (&addonsv1.ClusterResourceSetBinding{}).SetupWebhookWithManager(mgr); err != nil { klog.Fatalf("unable to create webhook for ClusterResourceSetBinding: %+v", err) } - if err := (&expv1.MachinePool{}).SetupWebhookWithManager(mgr); err != nil { + if err := (&expapiwebhooks.MachinePool{}).SetupWebhookWithManager(mgr); err != nil { klog.Fatalf("unable to create webhook for machinepool: %+v", err) } if err := (&runtimewebhooks.ExtensionConfig{}).SetupWebhookWithManager(mgr); err != nil { diff --git a/main.go b/main.go index 1e3ce3d974d2..97533eff7e92 100644 --- a/main.go +++ b/main.go @@ -63,6 +63,7 @@ import ( runtimecatalog "sigs.k8s.io/cluster-api/exp/runtime/catalog" runtimecontrollers "sigs.k8s.io/cluster-api/exp/runtime/controllers" runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1" + expapiwebhooks "sigs.k8s.io/cluster-api/exp/webhooks" "sigs.k8s.io/cluster-api/feature" runtimeclient "sigs.k8s.io/cluster-api/internal/runtime/client" runtimeregistry "sigs.k8s.io/cluster-api/internal/runtime/registry" @@ -588,7 +589,7 @@ func setupWebhooks(mgr ctrl.Manager) { // NOTE: MachinePool is behind MachinePool feature gate flag; the webhook // is going to prevent creating or updating new objects in case the feature flag is disabled - if err := (&expv1.MachinePool{}).SetupWebhookWithManager(mgr); err != nil { + if err := (&expapiwebhooks.MachinePool{}).SetupWebhookWithManager(mgr); err != nil { setupLog.Error(err, "unable to create webhook", "webhook", "MachinePool") os.Exit(1) }