Promote DS MaxSurge to GA

This commit is contained in:
Ravi Gudimetla
2022-07-15 18:11:33 -04:00
parent 5108b0a3a0
commit 7397c029e8
8 changed files with 1357 additions and 1857 deletions

View File

@@ -28,11 +28,9 @@ import (
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/apis/apps"
api "k8s.io/kubernetes/pkg/apis/core"
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
"k8s.io/kubernetes/pkg/features"
)
// ValidateStatefulSetName can be used to check whether the given StatefulSet name is valid.
@@ -373,34 +371,25 @@ func ValidateDaemonSetSpec(spec *apps.DaemonSetSpec, fldPath *field.Path, opts a
// ValidateRollingUpdateDaemonSet validates a given RollingUpdateDaemonSet.
func ValidateRollingUpdateDaemonSet(rollingUpdate *apps.RollingUpdateDaemonSet, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
if utilfeature.DefaultFeatureGate.Enabled(features.DaemonSetUpdateSurge) {
// Validate both fields are positive ints or have a percentage value
allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxSurge, fldPath.Child("maxSurge"))...)
// Validate that MaxUnavailable and MaxSurge are not more than 100%.
allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxSurge, fldPath.Child("maxSurge"))...)
// Validate both fields are positive ints or have a percentage value
allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxSurge, fldPath.Child("maxSurge"))...)
// Validate exactly one of MaxSurge or MaxUnavailable is non-zero
hasUnavailable := getIntOrPercentValue(rollingUpdate.MaxUnavailable) != 0
hasSurge := getIntOrPercentValue(rollingUpdate.MaxSurge) != 0
switch {
case hasUnavailable && hasSurge:
allErrs = append(allErrs, field.Invalid(fldPath.Child("maxSurge"), rollingUpdate.MaxSurge, "may not be set when maxUnavailable is non-zero"))
case !hasUnavailable && !hasSurge:
allErrs = append(allErrs, field.Required(fldPath.Child("maxUnavailable"), "cannot be 0 when maxSurge is 0"))
}
// Validate that MaxUnavailable and MaxSurge are not more than 100%.
allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxSurge, fldPath.Child("maxSurge"))...)
} else {
allErrs = append(allErrs, ValidatePositiveIntOrPercent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
if getIntOrPercentValue(rollingUpdate.MaxUnavailable) == 0 {
// MaxUnavailable cannot be 0.
allErrs = append(allErrs, field.Invalid(fldPath.Child("maxUnavailable"), rollingUpdate.MaxUnavailable, "cannot be 0"))
}
// Validate that MaxUnavailable is not more than 100%.
allErrs = append(allErrs, IsNotMoreThan100Percent(rollingUpdate.MaxUnavailable, fldPath.Child("maxUnavailable"))...)
// Validate exactly one of MaxSurge or MaxUnavailable is non-zero
hasUnavailable := getIntOrPercentValue(rollingUpdate.MaxUnavailable) != 0
hasSurge := getIntOrPercentValue(rollingUpdate.MaxSurge) != 0
switch {
case hasUnavailable && hasSurge:
allErrs = append(allErrs, field.Invalid(fldPath.Child("maxSurge"), rollingUpdate.MaxSurge, "may not be set when maxUnavailable is non-zero"))
case !hasUnavailable && !hasSurge:
allErrs = append(allErrs, field.Required(fldPath.Child("maxUnavailable"), "cannot be 0 when maxSurge is 0"))
}
return allErrs
}

View File

@@ -3591,7 +3591,6 @@ func TestValidateReplicaSet(t *testing.T) {
func TestDaemonSetUpdateMaxSurge(t *testing.T) {
testCases := map[string]struct {
ds *apps.RollingUpdateDaemonSet
enableSurge bool
expectError bool
}{
"invalid: unset": {
@@ -3637,45 +3636,40 @@ func TestDaemonSetUpdateMaxSurge(t *testing.T) {
MaxUnavailable: intstr.FromString("1%"),
MaxSurge: intstr.FromString("1%"),
},
expectError: true,
},
"invalid: surge enabled, unavailable zero percent": {
ds: &apps.RollingUpdateDaemonSet{
MaxUnavailable: intstr.FromString("0%"),
},
enableSurge: true,
expectError: true,
},
"invalid: surge enabled, unavailable zero": {
ds: &apps.RollingUpdateDaemonSet{
MaxUnavailable: intstr.FromInt(0),
},
enableSurge: true,
expectError: true,
},
"valid: surge enabled, unavailable one": {
ds: &apps.RollingUpdateDaemonSet{
MaxUnavailable: intstr.FromInt(1),
},
enableSurge: true,
},
"valid: surge enabled, unavailable one percent": {
ds: &apps.RollingUpdateDaemonSet{
MaxUnavailable: intstr.FromString("1%"),
},
enableSurge: true,
},
"valid: surge enabled, unavailable 100%": {
ds: &apps.RollingUpdateDaemonSet{
MaxUnavailable: intstr.FromString("100%"),
},
enableSurge: true,
},
"invalid: surge enabled, unavailable greater than 100%": {
ds: &apps.RollingUpdateDaemonSet{
MaxUnavailable: intstr.FromString("101%"),
},
enableSurge: true,
expectError: true,
},
@@ -3683,39 +3677,33 @@ func TestDaemonSetUpdateMaxSurge(t *testing.T) {
ds: &apps.RollingUpdateDaemonSet{
MaxSurge: intstr.FromString("0%"),
},
enableSurge: true,
expectError: true,
},
"invalid: surge enabled, surge zero": {
ds: &apps.RollingUpdateDaemonSet{
MaxSurge: intstr.FromInt(0),
},
enableSurge: true,
expectError: true,
},
"valid: surge enabled, surge one": {
ds: &apps.RollingUpdateDaemonSet{
MaxSurge: intstr.FromInt(1),
},
enableSurge: true,
},
"valid: surge enabled, surge one percent": {
ds: &apps.RollingUpdateDaemonSet{
MaxSurge: intstr.FromString("1%"),
},
enableSurge: true,
},
"valid: surge enabled, surge 100%": {
ds: &apps.RollingUpdateDaemonSet{
MaxSurge: intstr.FromString("100%"),
},
enableSurge: true,
},
"invalid: surge enabled, surge greater than 100%": {
ds: &apps.RollingUpdateDaemonSet{
MaxSurge: intstr.FromString("101%"),
},
enableSurge: true,
expectError: true,
},
@@ -3724,7 +3712,6 @@ func TestDaemonSetUpdateMaxSurge(t *testing.T) {
MaxUnavailable: intstr.FromString("1%"),
MaxSurge: intstr.FromString("1%"),
},
enableSurge: true,
expectError: true,
},
@@ -3733,7 +3720,6 @@ func TestDaemonSetUpdateMaxSurge(t *testing.T) {
MaxUnavailable: intstr.FromString("0%"),
MaxSurge: intstr.FromString("0%"),
},
enableSurge: true,
expectError: true,
},
"invalid: surge enabled, surge and unavailable zero": {
@@ -3741,7 +3727,6 @@ func TestDaemonSetUpdateMaxSurge(t *testing.T) {
MaxUnavailable: intstr.FromInt(0),
MaxSurge: intstr.FromInt(0),
},
enableSurge: true,
expectError: true,
},
"invalid: surge enabled, surge and unavailable mixed zero": {
@@ -3749,13 +3734,11 @@ func TestDaemonSetUpdateMaxSurge(t *testing.T) {
MaxUnavailable: intstr.FromInt(0),
MaxSurge: intstr.FromString("0%"),
},
enableSurge: true,
expectError: true,
},
}
for tcName, tc := range testCases {
t.Run(tcName, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DaemonSetUpdateSurge, tc.enableSurge)()
errs := ValidateRollingUpdateDaemonSet(tc.ds, field.NewPath("spec", "updateStrategy", "rollingUpdate"))
if tc.expectError && len(errs) == 0 {
t.Errorf("Unexpected success")