Skip to content

Commit 9c83d85

Browse files
committed
fix AzureCluster Webhooks
1 parent 5e5d3a1 commit 9c83d85

File tree

1 file changed

+50
-38
lines changed

1 file changed

+50
-38
lines changed

api/v1beta1/azurecluster_webhook.go

Lines changed: 50 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,136 +24,148 @@ import (
2424
"k8s.io/apimachinery/pkg/runtime"
2525
"k8s.io/apimachinery/pkg/util/validation/field"
2626
ctrl "sigs.k8s.io/controller-runtime"
27+
"sigs.k8s.io/controller-runtime/pkg/webhook"
2728
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
2829

2930
webhookutils "sigs.k8s.io/cluster-api-provider-azure/util/webhook"
3031
)
3132

3233
// SetupWebhookWithManager sets up and registers the webhook with the manager.
3334
func (c *AzureCluster) SetupWebhookWithManager(mgr ctrl.Manager) error {
35+
w := new(azureClusterWebhook)
3436
return ctrl.NewWebhookManagedBy(mgr).
3537
For(c).
36-
WithDefaulter(&AzureCluster{}).
37-
WithValidator(&AzureCluster{}).
38+
WithDefaulter(w).
39+
WithValidator(w).
3840
Complete()
3941
}
4042

4143
// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-azurecluster,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=azureclusters,versions=v1beta1,name=validation.azurecluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1
4244
// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1beta1-azurecluster,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=azureclusters,versions=v1beta1,name=default.azurecluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1
4345

46+
type azureClusterWebhook struct{}
47+
48+
var (
49+
_ webhook.CustomValidator = &azureClusterWebhook{}
50+
_ webhook.CustomDefaulter = &azureClusterWebhook{}
51+
)
52+
4453
// Default implements webhook.Defaulter so a webhook will be registered for the type.
45-
func (c *AzureCluster) Default(_ context.Context, _ runtime.Object) error {
54+
func (_ *azureClusterWebhook) Default(_ context.Context, obj runtime.Object) error {
55+
c := obj.(*AzureCluster)
4656
c.setDefaults()
4757
return nil
4858
}
4959

5060
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
51-
func (c *AzureCluster) ValidateCreate(_ context.Context, _ runtime.Object) (admission.Warnings, error) {
61+
func (_ *azureClusterWebhook) ValidateCreate(_ context.Context, newObj runtime.Object) (admission.Warnings, error) {
62+
c := newObj.(*AzureCluster)
5263
return c.validateCluster(nil)
5364
}
5465

5566
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
56-
func (c *AzureCluster) ValidateUpdate(_ context.Context, _ runtime.Object, oldRaw runtime.Object) (admission.Warnings, error) {
67+
func (_ *azureClusterWebhook) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
5768
var allErrs field.ErrorList
58-
old := oldRaw.(*AzureCluster)
69+
oldAzureCluster := oldObj.(*AzureCluster)
70+
newAzureCluster := newObj.(*AzureCluster)
5971

6072
if err := webhookutils.ValidateImmutable(
6173
field.NewPath("spec", "resourceGroup"),
62-
old.Spec.ResourceGroup,
63-
c.Spec.ResourceGroup); err != nil {
74+
oldAzureCluster.Spec.ResourceGroup,
75+
newAzureCluster.Spec.ResourceGroup); err != nil {
6476
allErrs = append(allErrs, err)
6577
}
6678

6779
if err := webhookutils.ValidateImmutable(
6880
field.NewPath("spec", "subscriptionID"),
69-
old.Spec.SubscriptionID,
70-
c.Spec.SubscriptionID); err != nil {
81+
oldAzureCluster.Spec.SubscriptionID,
82+
newAzureCluster.Spec.SubscriptionID); err != nil {
7183
allErrs = append(allErrs, err)
7284
}
7385

7486
if err := webhookutils.ValidateImmutable(
7587
field.NewPath("spec", "location"),
76-
old.Spec.Location,
77-
c.Spec.Location); err != nil {
88+
oldAzureCluster.Spec.Location,
89+
newAzureCluster.Spec.Location); err != nil {
7890
allErrs = append(allErrs, err)
7991
}
8092

81-
if old.Spec.ControlPlaneEndpoint.Host != "" && c.Spec.ControlPlaneEndpoint.Host != old.Spec.ControlPlaneEndpoint.Host {
93+
if oldAzureCluster.Spec.ControlPlaneEndpoint.Host != "" && newAzureCluster.Spec.ControlPlaneEndpoint.Host != oldAzureCluster.Spec.ControlPlaneEndpoint.Host {
8294
allErrs = append(allErrs,
8395
field.Invalid(field.NewPath("spec", "controlPlaneEndpoint", "host"),
84-
c.Spec.ControlPlaneEndpoint.Host, "field is immutable"),
96+
newAzureCluster.Spec.ControlPlaneEndpoint.Host, "field is immutable"),
8597
)
8698
}
8799

88-
if old.Spec.ControlPlaneEndpoint.Port != 0 && c.Spec.ControlPlaneEndpoint.Port != old.Spec.ControlPlaneEndpoint.Port {
100+
if oldAzureCluster.Spec.ControlPlaneEndpoint.Port != 0 && newAzureCluster.Spec.ControlPlaneEndpoint.Port != oldAzureCluster.Spec.ControlPlaneEndpoint.Port {
89101
allErrs = append(allErrs,
90102
field.Invalid(field.NewPath("spec", "controlPlaneEndpoint", "port"),
91-
c.Spec.ControlPlaneEndpoint.Port, "field is immutable"),
103+
newAzureCluster.Spec.ControlPlaneEndpoint.Port, "field is immutable"),
92104
)
93105
}
94106

95-
if !reflect.DeepEqual(c.Spec.AzureEnvironment, old.Spec.AzureEnvironment) {
107+
if !reflect.DeepEqual(newAzureCluster.Spec.AzureEnvironment, oldAzureCluster.Spec.AzureEnvironment) {
96108
// The equality failure could be because of default mismatch between v1alpha3 and v1beta1. This happens because
97-
// the new object `r` will have run through the default webhooks but the old object `old` would not have so.
109+
// the new object `r` will have run through the default webhooks but the old object `oldAzureCluster` would not have so.
98110
// This means if the old object was in v1alpha3, it would not get the new defaults set in v1beta1 resulting
99111
// in object inequality. To workaround this, we set the v1beta1 defaults here so that the old object also gets
100112
// the new defaults.
101-
old.setAzureEnvironmentDefault()
113+
oldAzureCluster.setAzureEnvironmentDefault()
102114

103115
// if it's still not equal, return error.
104-
if !reflect.DeepEqual(c.Spec.AzureEnvironment, old.Spec.AzureEnvironment) {
116+
if !reflect.DeepEqual(newAzureCluster.Spec.AzureEnvironment, oldAzureCluster.Spec.AzureEnvironment) {
105117
allErrs = append(allErrs,
106118
field.Invalid(field.NewPath("spec", "azureEnvironment"),
107-
c.Spec.AzureEnvironment, "field is immutable"),
119+
newAzureCluster.Spec.AzureEnvironment, "field is immutable"),
108120
)
109121
}
110122
}
111123

112124
if err := webhookutils.ValidateImmutable(
113125
field.NewPath("spec", "networkSpec", "privateDNSZoneName"),
114-
old.Spec.NetworkSpec.PrivateDNSZoneName,
115-
c.Spec.NetworkSpec.PrivateDNSZoneName); err != nil {
126+
oldAzureCluster.Spec.NetworkSpec.PrivateDNSZoneName,
127+
newAzureCluster.Spec.NetworkSpec.PrivateDNSZoneName); err != nil {
116128
allErrs = append(allErrs, err)
117129
}
118130

119131
if err := webhookutils.ValidateImmutable(
120132
field.NewPath("spec", "networkSpec", "privateDNSZoneResourceGroup"),
121-
old.Spec.NetworkSpec.PrivateDNSZoneResourceGroup,
122-
c.Spec.NetworkSpec.PrivateDNSZoneResourceGroup); err != nil {
133+
oldAzureCluster.Spec.NetworkSpec.PrivateDNSZoneResourceGroup,
134+
newAzureCluster.Spec.NetworkSpec.PrivateDNSZoneResourceGroup); err != nil {
123135
allErrs = append(allErrs, err)
124136
}
125137

126138
// Allow enabling azure bastion but avoid disabling it.
127-
if old.Spec.BastionSpec.AzureBastion != nil && !reflect.DeepEqual(old.Spec.BastionSpec.AzureBastion, c.Spec.BastionSpec.AzureBastion) {
139+
if oldAzureCluster.Spec.BastionSpec.AzureBastion != nil && !reflect.DeepEqual(oldAzureCluster.Spec.BastionSpec.AzureBastion, newAzureCluster.Spec.BastionSpec.AzureBastion) {
128140
allErrs = append(allErrs,
129141
field.Invalid(field.NewPath("spec", "bastionSpec", "azureBastion"),
130-
c.Spec.BastionSpec.AzureBastion, "azure bastion cannot be removed from a cluster"),
142+
newAzureCluster.Spec.BastionSpec.AzureBastion, "azure bastion cannot be removed from a cluster"),
131143
)
132144
}
133145

134146
if err := webhookutils.ValidateImmutable(
135147
field.NewPath("spec", "networkSpec", "controlPlaneOutboundLB"),
136-
old.Spec.NetworkSpec.ControlPlaneOutboundLB,
137-
c.Spec.NetworkSpec.ControlPlaneOutboundLB); err != nil {
148+
oldAzureCluster.Spec.NetworkSpec.ControlPlaneOutboundLB,
149+
newAzureCluster.Spec.NetworkSpec.ControlPlaneOutboundLB); err != nil {
138150
allErrs = append(allErrs, err)
139151
}
140152

141-
allErrs = append(allErrs, c.validateSubnetUpdate(old)...)
153+
allErrs = append(allErrs, newAzureCluster.validateSubnetUpdate(oldAzureCluster)...)
142154

143155
if len(allErrs) == 0 {
144-
return c.validateCluster(old)
156+
return newAzureCluster.validateCluster(oldAzureCluster)
145157
}
146158

147-
return nil, apierrors.NewInvalid(GroupVersion.WithKind(AzureClusterKind).GroupKind(), c.Name, allErrs)
159+
return nil, apierrors.NewInvalid(GroupVersion.WithKind(AzureClusterKind).GroupKind(), newAzureCluster.Name, allErrs)
148160
}
149161

150162
// validateSubnetUpdate validates a ClusterSpec.NetworkSpec.Subnets for immutability.
151-
func (c *AzureCluster) validateSubnetUpdate(old *AzureCluster) field.ErrorList {
163+
func (c *AzureCluster) validateSubnetUpdate(oldAzureCluster *AzureCluster) field.ErrorList {
152164
var allErrs field.ErrorList
153165

154-
oldSubnetMap := make(map[string]SubnetSpec, len(old.Spec.NetworkSpec.Subnets))
155-
oldSubnetIndex := make(map[string]int, len(old.Spec.NetworkSpec.Subnets))
156-
for i, subnet := range old.Spec.NetworkSpec.Subnets {
166+
oldSubnetMap := make(map[string]SubnetSpec, len(oldAzureCluster.Spec.NetworkSpec.Subnets))
167+
oldSubnetIndex := make(map[string]int, len(oldAzureCluster.Spec.NetworkSpec.Subnets))
168+
for i, subnet := range oldAzureCluster.Spec.NetworkSpec.Subnets {
157169
oldSubnetMap[subnet.Name] = subnet
158170
oldSubnetIndex[subnet.Name] = i
159171
}
@@ -165,7 +177,7 @@ func (c *AzureCluster) validateSubnetUpdate(old *AzureCluster) field.ErrorList {
165177
// This technically allows the cidr block to be modified in the brief
166178
// moments before the Vnet is created (because the tags haven't been
167179
// set yet) but once the Vnet has been created it becomes immutable.
168-
if old.Spec.NetworkSpec.Vnet.Tags.HasOwned(old.Name) && !reflect.DeepEqual(subnet.CIDRBlocks, oldSubnet.CIDRBlocks) {
180+
if oldAzureCluster.Spec.NetworkSpec.Vnet.Tags.HasOwned(oldAzureCluster.Name) && !reflect.DeepEqual(subnet.CIDRBlocks, oldSubnet.CIDRBlocks) {
169181
allErrs = append(allErrs,
170182
field.Invalid(field.NewPath("spec", "networkSpec", "subnets").Index(oldSubnetIndex[subnet.Name]).Child("CIDRBlocks"),
171183
c.Spec.NetworkSpec.Subnets[i].CIDRBlocks, "field is immutable"),
@@ -196,6 +208,6 @@ func (c *AzureCluster) validateSubnetUpdate(old *AzureCluster) field.ErrorList {
196208
}
197209

198210
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
199-
func (c *AzureCluster) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) {
211+
func (_ *azureClusterWebhook) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) {
200212
return nil, nil
201213
}

0 commit comments

Comments
 (0)