@@ -14,9 +14,10 @@ See the License for the specific language governing permissions and
1414limitations under the License.
1515*/
1616
17- package v1beta1
17+ package webhooks
1818
1919import (
20+ "context"
2021 "fmt"
2122 "strings"
2223
@@ -29,24 +30,35 @@ import (
2930 "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
3031
3132 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
33+ expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1"
3234 "sigs.k8s.io/cluster-api/feature"
3335 "sigs.k8s.io/cluster-api/util/version"
3436)
3537
36- func (m * MachinePool ) SetupWebhookWithManager (mgr ctrl.Manager ) error {
38+ func (webhook * MachinePool ) SetupWebhookWithManager (mgr ctrl.Manager ) error {
3739 return ctrl .NewWebhookManagedBy (mgr ).
38- For (m ).
40+ For (& expv1.MachinePool {}).
41+ WithDefaulter (webhook ).
42+ WithValidator (webhook ).
3943 Complete ()
4044}
4145
4246// +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
4347// +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
4448
45- var _ webhook.Defaulter = & MachinePool {}
46- var _ webhook.Validator = & MachinePool {}
49+ // MachinePool implements a validation and defaulting webhook for MachinePool.
50+ type MachinePool struct {}
51+
52+ var _ webhook.CustomValidator = & MachinePool {}
53+ var _ webhook.CustomDefaulter = & MachinePool {}
4754
4855// Default implements webhook.Defaulter so a webhook will be registered for the type.
49- func (m * MachinePool ) Default () {
56+ func (webhook * MachinePool ) Default (_ context.Context , obj runtime.Object ) error {
57+ m , ok := obj .(* expv1.MachinePool )
58+ if ! ok {
59+ return apierrors .NewBadRequest (fmt .Sprintf ("expected a MachinePool but got a %T" , obj ))
60+ }
61+
5062 if m .Labels == nil {
5163 m .Labels = make (map [string ]string )
5264 }
@@ -73,30 +85,45 @@ func (m *MachinePool) Default() {
7385 normalizedVersion := "v" + * m .Spec .Template .Spec .Version
7486 m .Spec .Template .Spec .Version = & normalizedVersion
7587 }
88+ return nil
7689}
7790
7891// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
79- func (m * MachinePool ) ValidateCreate () (admission.Warnings , error ) {
80- return nil , m .validate (nil )
92+ func (webhook * MachinePool ) ValidateCreate (_ context.Context , obj runtime.Object ) (admission.Warnings , error ) {
93+ mp , ok := obj .(* expv1.MachinePool )
94+ if ! ok {
95+ return nil , apierrors .NewBadRequest (fmt .Sprintf ("expected a MachinePool but got a %T" , obj ))
96+ }
97+
98+ return nil , webhook .validate (nil , mp )
8199}
82100
83101// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
84- func (m * MachinePool ) ValidateUpdate (old runtime.Object ) (admission.Warnings , error ) {
85- oldMP , ok := old .(* MachinePool )
102+ func (webhook * MachinePool ) ValidateUpdate (_ context.Context , oldObj , newObj runtime.Object ) (admission.Warnings , error ) {
103+ oldMP , ok := oldObj .(* expv1.MachinePool )
104+ if ! ok {
105+ return nil , apierrors .NewBadRequest (fmt .Sprintf ("expected a MachinePool but got a %T" , oldObj ))
106+ }
107+ newMP , ok := newObj .(* expv1.MachinePool )
86108 if ! ok {
87- return nil , apierrors .NewBadRequest (fmt .Sprintf ("expected a MachinePool but got a %T" , old ))
109+ return nil , apierrors .NewBadRequest (fmt .Sprintf ("expected a MachinePool but got a %T" , newObj ))
88110 }
89- return nil , m .validate (oldMP )
111+ return nil , webhook .validate (oldMP , newMP )
90112}
91113
92114// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
93- func (m * MachinePool ) ValidateDelete () (admission.Warnings , error ) {
94- return nil , m .validate (nil )
115+ func (webhook * MachinePool ) ValidateDelete (_ context.Context , obj runtime.Object ) (admission.Warnings , error ) {
116+ mp , ok := obj .(* expv1.MachinePool )
117+ if ! ok {
118+ return nil , apierrors .NewBadRequest (fmt .Sprintf ("expected a MachinePool but got a %T" , obj ))
119+ }
120+
121+ return nil , webhook .validate (nil , mp )
95122}
96123
97- func (m * MachinePool ) validate (old * MachinePool ) error {
124+ func (webhook * MachinePool ) validate (oldObj , newObj * expv1. MachinePool ) error {
98125 // NOTE: MachinePool is behind MachinePool feature gate flag; the web hook
99- // must prevent creating new objects when the feature flag is disabled.
126+ // must prevent creating newObj objects when the feature flag is disabled.
100127 specPath := field .NewPath ("spec" )
101128 if ! feature .Gates .Enabled (feature .MachinePool ) {
102129 return field .Forbidden (
@@ -105,7 +132,7 @@ func (m *MachinePool) validate(old *MachinePool) error {
105132 )
106133 }
107134 var allErrs field.ErrorList
108- if m .Spec .Template .Spec .Bootstrap .ConfigRef == nil && m .Spec .Template .Spec .Bootstrap .DataSecretName == nil {
135+ if newObj .Spec .Template .Spec .Bootstrap .ConfigRef == nil && newObj .Spec .Template .Spec .Bootstrap .DataSecretName == nil {
109136 allErrs = append (
110137 allErrs ,
111138 field .Required (
@@ -115,29 +142,29 @@ func (m *MachinePool) validate(old *MachinePool) error {
115142 )
116143 }
117144
118- if m .Spec .Template .Spec .Bootstrap .ConfigRef != nil && m .Spec .Template .Spec .Bootstrap .ConfigRef .Namespace != m .Namespace {
145+ if newObj .Spec .Template .Spec .Bootstrap .ConfigRef != nil && newObj .Spec .Template .Spec .Bootstrap .ConfigRef .Namespace != newObj .Namespace {
119146 allErrs = append (
120147 allErrs ,
121148 field .Invalid (
122149 specPath .Child ("template" , "spec" , "bootstrap" , "configRef" , "namespace" ),
123- m .Spec .Template .Spec .Bootstrap .ConfigRef .Namespace ,
150+ newObj .Spec .Template .Spec .Bootstrap .ConfigRef .Namespace ,
124151 "must match metadata.namespace" ,
125152 ),
126153 )
127154 }
128155
129- if m .Spec .Template .Spec .InfrastructureRef .Namespace != m .Namespace {
156+ if newObj .Spec .Template .Spec .InfrastructureRef .Namespace != newObj .Namespace {
130157 allErrs = append (
131158 allErrs ,
132159 field .Invalid (
133160 specPath .Child ("infrastructureRef" , "namespace" ),
134- m .Spec .Template .Spec .InfrastructureRef .Namespace ,
161+ newObj .Spec .Template .Spec .InfrastructureRef .Namespace ,
135162 "must match metadata.namespace" ,
136163 ),
137164 )
138165 }
139166
140- if old != nil && old .Spec .ClusterName != m .Spec .ClusterName {
167+ if oldObj != nil && oldObj .Spec .ClusterName != newObj .Spec .ClusterName {
141168 allErrs = append (
142169 allErrs ,
143170 field .Forbidden (
@@ -146,17 +173,17 @@ func (m *MachinePool) validate(old *MachinePool) error {
146173 )
147174 }
148175
149- if m .Spec .Template .Spec .Version != nil {
150- if ! version .KubeSemver .MatchString (* m .Spec .Template .Spec .Version ) {
151- allErrs = append (allErrs , field .Invalid (specPath .Child ("template" , "spec" , "version" ), * m .Spec .Template .Spec .Version , "must be a valid semantic version" ))
176+ if newObj .Spec .Template .Spec .Version != nil {
177+ if ! version .KubeSemver .MatchString (* newObj .Spec .Template .Spec .Version ) {
178+ allErrs = append (allErrs , field .Invalid (specPath .Child ("template" , "spec" , "version" ), * newObj .Spec .Template .Spec .Version , "must be a valid semantic version" ))
152179 }
153180 }
154181
155182 // Validate the metadata of the MachinePool template.
156- allErrs = append (allErrs , m .Spec .Template .ObjectMeta .Validate (specPath .Child ("template" , "metadata" ))... )
183+ allErrs = append (allErrs , newObj .Spec .Template .ObjectMeta .Validate (specPath .Child ("template" , "metadata" ))... )
157184
158185 if len (allErrs ) == 0 {
159186 return nil
160187 }
161- return apierrors .NewInvalid (GroupVersion .WithKind ("MachinePool" ).GroupKind (), m .Name , allErrs )
188+ return apierrors .NewInvalid (clusterv1 . GroupVersion .WithKind ("MachinePool" ).GroupKind (), newObj .Name , allErrs )
162189}
0 commit comments