mirror of
https://github.com/optim-enterprises-bv/kubernetes.git
synced 2025-11-01 18:58:18 +00:00
validation: Handle presence of api introduced
When the StatefulSetMinReadySeconds feature gate is disabled, the registry and validation must properly handle dropping the minReadySeconds and AvailableReplicas fields
This commit is contained in:
@@ -386,18 +386,94 @@ func TestValidateStatefulSet(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// generateStatefulSetSpec generates a valid StatefulSet spec
|
||||
func generateStatefulSetSpec(minSeconds int32) *apps.StatefulSetSpec {
|
||||
labels := map[string]string{"a": "b"}
|
||||
podTemplate := api.PodTemplate{
|
||||
Template: api.PodTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: labels,
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
RestartPolicy: api.RestartPolicyAlways,
|
||||
DNSPolicy: api.DNSClusterFirst,
|
||||
Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
ss := &apps.StatefulSetSpec{
|
||||
PodManagementPolicy: "OrderedReady",
|
||||
Selector: &metav1.LabelSelector{MatchLabels: labels},
|
||||
Template: podTemplate.Template,
|
||||
Replicas: 3,
|
||||
UpdateStrategy: apps.StatefulSetUpdateStrategy{Type: apps.RollingUpdateStatefulSetStrategyType},
|
||||
MinReadySeconds: minSeconds,
|
||||
}
|
||||
return ss
|
||||
}
|
||||
|
||||
// TestValidateStatefulSetMinReadySeconds tests the StatefulSet Spec's minReadySeconds field
|
||||
func TestValidateStatefulSetMinReadySeconds(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
ss *apps.StatefulSetSpec
|
||||
enableMinReadySeconds bool
|
||||
expectErr bool
|
||||
}{
|
||||
"valid : minReadySeconds enabled, zero": {
|
||||
ss: generateStatefulSetSpec(0),
|
||||
enableMinReadySeconds: true,
|
||||
expectErr: false,
|
||||
},
|
||||
"invalid : minReadySeconds enabled, negative": {
|
||||
ss: generateStatefulSetSpec(-1),
|
||||
enableMinReadySeconds: true,
|
||||
expectErr: true,
|
||||
},
|
||||
"valid : minReadySeconds enabled, very large value": {
|
||||
ss: generateStatefulSetSpec(2147483647),
|
||||
enableMinReadySeconds: true,
|
||||
expectErr: false,
|
||||
},
|
||||
"invalid : minReadySeconds enabled, large negative": {
|
||||
ss: generateStatefulSetSpec(-2147483648),
|
||||
enableMinReadySeconds: true,
|
||||
expectErr: true,
|
||||
},
|
||||
"valid : minReadySeconds disabled, we don't validate anything": {
|
||||
ss: generateStatefulSetSpec(-2147483648),
|
||||
enableMinReadySeconds: false,
|
||||
expectErr: false,
|
||||
},
|
||||
}
|
||||
for tcName, tc := range testCases {
|
||||
t.Run(tcName, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.StatefulSetMinReadySeconds, tc.enableMinReadySeconds)()
|
||||
errs := ValidateStatefulSetSpec(tc.ss, field.NewPath("spec", "minReadySeconds"),
|
||||
corevalidation.PodValidationOptions{})
|
||||
if tc.expectErr && len(errs) == 0 {
|
||||
t.Errorf("Unexpected success")
|
||||
}
|
||||
if !tc.expectErr && len(errs) != 0 {
|
||||
t.Errorf("Unexpected error(s): %v", errs)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateStatefulSetStatus(t *testing.T) {
|
||||
observedGenerationMinusOne := int64(-1)
|
||||
collisionCountMinusOne := int32(-1)
|
||||
tests := []struct {
|
||||
name string
|
||||
replicas int32
|
||||
readyReplicas int32
|
||||
currentReplicas int32
|
||||
updatedReplicas int32
|
||||
observedGeneration *int64
|
||||
collisionCount *int32
|
||||
expectedErr bool
|
||||
name string
|
||||
replicas int32
|
||||
readyReplicas int32
|
||||
currentReplicas int32
|
||||
updatedReplicas int32
|
||||
availableReplicas int32
|
||||
enableMinReadySeconds bool
|
||||
observedGeneration *int64
|
||||
collisionCount *int32
|
||||
expectedErr bool
|
||||
}{
|
||||
{
|
||||
name: "valid status",
|
||||
@@ -481,10 +557,65 @@ func TestValidateStatefulSetStatus(t *testing.T) {
|
||||
updatedReplicas: 4,
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid: number of available replicas",
|
||||
replicas: 3,
|
||||
readyReplicas: 3,
|
||||
currentReplicas: 2,
|
||||
availableReplicas: int32(-1),
|
||||
expectedErr: true,
|
||||
enableMinReadySeconds: true,
|
||||
},
|
||||
{
|
||||
name: "invalid: available replicas greater than replicas",
|
||||
replicas: 3,
|
||||
readyReplicas: 3,
|
||||
currentReplicas: 2,
|
||||
availableReplicas: int32(4),
|
||||
expectedErr: true,
|
||||
enableMinReadySeconds: true,
|
||||
},
|
||||
{
|
||||
name: "invalid: available replicas greater than ready replicas",
|
||||
replicas: 3,
|
||||
readyReplicas: 2,
|
||||
currentReplicas: 2,
|
||||
availableReplicas: int32(3),
|
||||
expectedErr: true,
|
||||
enableMinReadySeconds: true,
|
||||
},
|
||||
{
|
||||
name: "minReadySeconds flag not set, no validation: number of available replicas",
|
||||
replicas: 3,
|
||||
readyReplicas: 3,
|
||||
currentReplicas: 2,
|
||||
availableReplicas: int32(-1),
|
||||
expectedErr: false,
|
||||
enableMinReadySeconds: false,
|
||||
},
|
||||
{
|
||||
name: "minReadySeconds flag not set, no validation: available replicas greater than replicas",
|
||||
replicas: 3,
|
||||
readyReplicas: 3,
|
||||
currentReplicas: 2,
|
||||
availableReplicas: int32(4),
|
||||
expectedErr: false,
|
||||
enableMinReadySeconds: false,
|
||||
},
|
||||
{
|
||||
name: "minReadySeconds flag not set, no validation: available replicas greater than ready replicas",
|
||||
replicas: 3,
|
||||
readyReplicas: 2,
|
||||
currentReplicas: 2,
|
||||
availableReplicas: int32(3),
|
||||
expectedErr: false,
|
||||
enableMinReadySeconds: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.StatefulSetMinReadySeconds, test.enableMinReadySeconds)()
|
||||
status := apps.StatefulSetStatus{
|
||||
Replicas: test.replicas,
|
||||
ReadyReplicas: test.readyReplicas,
|
||||
@@ -492,6 +623,7 @@ func TestValidateStatefulSetStatus(t *testing.T) {
|
||||
UpdatedReplicas: test.updatedReplicas,
|
||||
ObservedGeneration: test.observedGeneration,
|
||||
CollisionCount: test.collisionCount,
|
||||
AvailableReplicas: test.availableReplicas,
|
||||
}
|
||||
|
||||
errs := ValidateStatefulSetStatus(&status, field.NewPath("status"))
|
||||
|
||||
Reference in New Issue
Block a user