Skip to content

Commit e5c40a4

Browse files
committed
add validations for control plane outbound lb
1 parent 217c1d7 commit e5c40a4

File tree

4 files changed

+141
-0
lines changed

4 files changed

+141
-0
lines changed

api/v1alpha4/azurecluster_validation.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ func validateNetworkSpec(networkSpec NetworkSpec, old NetworkSpec, fldPath *fiel
137137

138138
allErrs = append(allErrs, validateNodeOutboundLB(networkSpec.NodeOutboundLB, old.NodeOutboundLB, networkSpec.APIServerLB, nodeSubnet, fldPath.Child("nodeOutboundLB"))...)
139139

140+
allErrs = append(allErrs, validateControlPlaneOutboundLB(networkSpec.ControlPlaneOutboundLB, networkSpec.APIServerLB, fldPath.Child("controlPlaneOutboundLB"))...)
141+
140142
allErrs = append(allErrs, validatePrivateDNSZoneName(networkSpec, fldPath)...)
141143

142144
if len(allErrs) == 0 {
@@ -420,6 +422,34 @@ func validateNodeOutboundLB(lb *LoadBalancerSpec, old *LoadBalancerSpec, apiserv
420422
return allErrs
421423
}
422424

425+
func validateControlPlaneOutboundLB(lb *LoadBalancerSpec, apiserverLB LoadBalancerSpec, fldPath *field.Path) field.ErrorList {
426+
var allErrs field.ErrorList
427+
428+
switch apiserverLB.Type {
429+
case Public:
430+
if lb != nil {
431+
allErrs = append(allErrs, field.Forbidden(fldPath, "Control plane outbound load balancer cannot be set for public clusters."))
432+
}
433+
case Internal:
434+
// Control plane outbound lb can be nil when it's disabled for private clusters.
435+
if lb == nil {
436+
return nil
437+
}
438+
439+
if lb.FrontendIPsCount != nil && *lb.FrontendIPsCount > MaxLoadBalancerOutboundIPs {
440+
allErrs = append(allErrs, field.Invalid(fldPath.Child("frontendIPsCount"), *lb.FrontendIPsCount,
441+
fmt.Sprintf("Max front end ips allowed is %d", MaxLoadBalancerOutboundIPs)))
442+
}
443+
444+
if lb.IdleTimeoutInMinutes != nil && (*lb.IdleTimeoutInMinutes < MinLBIdleTimeoutInMinutes || *lb.IdleTimeoutInMinutes > MaxLBIdleTimeoutInMinutes) {
445+
allErrs = append(allErrs, field.Invalid(fldPath.Child("idleTimeoutInMinutes"), *lb.IdleTimeoutInMinutes,
446+
fmt.Sprintf("Control plane outbound idle timeout should be between %d and %d minutes", MinLBIdleTimeoutInMinutes, MaxLoadBalancerOutboundIPs)))
447+
}
448+
}
449+
450+
return allErrs
451+
}
452+
423453
// validatePrivateDNSZoneName validate the PrivateDNSZoneName.
424454
func validatePrivateDNSZoneName(networkSpec NetworkSpec, fldPath *field.Path) field.ErrorList {
425455
var allErrs field.ErrorList

api/v1alpha4/azurecluster_validation_test.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,78 @@ func TestValidateNodeOutboundLB(t *testing.T) {
11181118
}
11191119
}
11201120

1121+
func TestValidateControlPlaneNodeOutboundLB(t *testing.T) {
1122+
g := NewWithT(t)
1123+
1124+
testcases := []struct {
1125+
name string
1126+
lb *LoadBalancerSpec
1127+
old *LoadBalancerSpec
1128+
apiServerLB LoadBalancerSpec
1129+
wantErr bool
1130+
expectedErr field.Error
1131+
}{
1132+
{
1133+
name: "cp outbound lb cannot be set for public clusters",
1134+
lb: &LoadBalancerSpec{Name: "foo"},
1135+
apiServerLB: LoadBalancerSpec{Type: Public},
1136+
wantErr: true,
1137+
expectedErr: field.Error{
1138+
Type: "FieldValueForbidden",
1139+
Field: "controlPlaneOutboundLB",
1140+
BadValue: LoadBalancerSpec{Name: "foo"},
1141+
Detail: "Control plane outbound load balancer cannot be set for public clusters.",
1142+
},
1143+
},
1144+
{
1145+
name: "cp outbound lb can be set for private clusters",
1146+
lb: &LoadBalancerSpec{Name: "foo"},
1147+
apiServerLB: LoadBalancerSpec{Type: Internal},
1148+
wantErr: false,
1149+
},
1150+
{
1151+
name: "cp outbound lb can be nil for private clusters",
1152+
lb: nil,
1153+
apiServerLB: LoadBalancerSpec{Type: Internal},
1154+
wantErr: false,
1155+
},
1156+
{
1157+
name: "frontend ips count exceeds max value",
1158+
lb: &LoadBalancerSpec{
1159+
FrontendIPsCount: pointer.Int32Ptr(100),
1160+
},
1161+
apiServerLB: LoadBalancerSpec{Type: Internal},
1162+
wantErr: true,
1163+
expectedErr: field.Error{
1164+
Type: "FieldValueInvalid",
1165+
Field: "controlPlaneOutboundLB.frontendIPsCount",
1166+
BadValue: 100,
1167+
Detail: "Max front end ips allowed is 16",
1168+
},
1169+
},
1170+
}
1171+
1172+
for _, test := range testcases {
1173+
test := test
1174+
t.Run(test.name, func(t *testing.T) {
1175+
t.Parallel()
1176+
err := validateControlPlaneOutboundLB(test.lb, test.apiServerLB, field.NewPath("controlPlaneOutboundLB"))
1177+
if test.wantErr {
1178+
g.Expect(err).NotTo(HaveLen(0))
1179+
found := false
1180+
for _, actual := range err {
1181+
if actual.Error() == test.expectedErr.Error() {
1182+
found = true
1183+
}
1184+
}
1185+
g.Expect(found).To(BeTrue())
1186+
} else {
1187+
g.Expect(err).To(HaveLen(0))
1188+
}
1189+
})
1190+
}
1191+
}
1192+
11211193
func TestValidateCloudProviderConfigOverrides(t *testing.T) {
11221194
g := NewWithT(t)
11231195

api/v1alpha4/azurecluster_webhook.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ func (c *AzureCluster) ValidateUpdate(oldRaw runtime.Object) error {
106106
)
107107
}
108108

109+
if !reflect.DeepEqual(c.Spec.NetworkSpec.ControlPlaneOutboundLB, old.Spec.NetworkSpec.ControlPlaneOutboundLB) {
110+
allErrs = append(allErrs,
111+
field.Invalid(field.NewPath("spec", "networkSpec", "controlPlaneOutboundLB"),
112+
c.Spec.NetworkSpec.ControlPlaneOutboundLB, "field is immutable"),
113+
)
114+
}
115+
109116
if len(allErrs) == 0 {
110117
return c.validateCluster(old)
111118
}

api/v1alpha4/azurecluster_webhook_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,38 @@ func TestAzureCluster_ValidateUpdate(t *testing.T) {
214214
},
215215
wantErr: true,
216216
},
217+
{
218+
name: "azurecluster azureEnvironment is immutable",
219+
oldCluster: &AzureCluster{
220+
Spec: AzureClusterSpec{
221+
AzureEnvironment: "AzureGermanCloud",
222+
},
223+
},
224+
cluster: &AzureCluster{
225+
Spec: AzureClusterSpec{
226+
AzureEnvironment: "AzureChinaCloud",
227+
},
228+
},
229+
wantErr: true,
230+
},
231+
{
232+
name: "control plane outbound lb is immutable",
233+
oldCluster: &AzureCluster{
234+
Spec: AzureClusterSpec{
235+
NetworkSpec: NetworkSpec{
236+
ControlPlaneOutboundLB: &LoadBalancerSpec{Name: "cp-lb"},
237+
},
238+
},
239+
},
240+
cluster: &AzureCluster{
241+
Spec: AzureClusterSpec{
242+
NetworkSpec: NetworkSpec{
243+
ControlPlaneOutboundLB: &LoadBalancerSpec{Name: "cp-lb-new"},
244+
},
245+
},
246+
},
247+
wantErr: true,
248+
},
217249
}
218250
for _, tc := range tests {
219251
t.Run(tc.name, func(t *testing.T) {

0 commit comments

Comments
 (0)