mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 03:41:45 +00:00
Promote DS MaxSurge to GA
This commit is contained in:
parent
5108b0a3a0
commit
7397c029e8
@ -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
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -27,12 +27,9 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/klog/v2"
|
||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||
"k8s.io/kubernetes/pkg/controller/daemon/util"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
testingclock "k8s.io/utils/clock/testing"
|
||||
)
|
||||
|
||||
@ -78,7 +75,6 @@ func TestDaemonSetUpdatesPods(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDaemonSetUpdatesPodsWithMaxSurge(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DaemonSetUpdateSurge, true)()
|
||||
ds := newDaemonSet("foo")
|
||||
manager, podControl, _, err := newTestController(ds)
|
||||
if err != nil {
|
||||
@ -191,7 +187,6 @@ func TestDaemonSetUpdatesAllOldPodsNotReady(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDaemonSetUpdatesAllOldPodsNotReadyMaxSurge(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DaemonSetUpdateSurge, true)()
|
||||
ds := newDaemonSet("foo")
|
||||
manager, podControl, _, err := newTestController(ds)
|
||||
if err != nil {
|
||||
@ -381,7 +376,6 @@ func TestGetUnavailableNumbers(t *testing.T) {
|
||||
Manager *daemonSetsController
|
||||
ds *apps.DaemonSet
|
||||
nodeToPods map[string][]*v1.Pod
|
||||
enableSurge bool
|
||||
maxSurge int
|
||||
maxUnavailable int
|
||||
emptyNodes int
|
||||
@ -536,7 +530,6 @@ func TestGetUnavailableNumbers(t *testing.T) {
|
||||
mapping["node-1"] = []*v1.Pod{pod1}
|
||||
return mapping
|
||||
}(),
|
||||
enableSurge: true,
|
||||
maxSurge: 1,
|
||||
maxUnavailable: 0,
|
||||
emptyNodes: 0,
|
||||
@ -566,7 +559,6 @@ func TestGetUnavailableNumbers(t *testing.T) {
|
||||
mapping["node-1"] = []*v1.Pod{pod1}
|
||||
return mapping
|
||||
}(),
|
||||
enableSurge: true,
|
||||
maxSurge: 2,
|
||||
maxUnavailable: 0,
|
||||
emptyNodes: 0,
|
||||
@ -605,8 +597,6 @@ func TestGetUnavailableNumbers(t *testing.T) {
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DaemonSetUpdateSurge, c.enableSurge)()
|
||||
|
||||
c.Manager.dsStore.Add(c.ds)
|
||||
nodeList, err := c.Manager.nodeLister.List(labels.Everything())
|
||||
if err != nil {
|
||||
|
@ -25,9 +25,7 @@ import (
|
||||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
intstrutil "k8s.io/apimachinery/pkg/util/intstr"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
// GetTemplateGeneration gets the template generation associated with a v1.DaemonSet by extracting it from the
|
||||
@ -137,9 +135,7 @@ func SurgeCount(ds *apps.DaemonSet, numberToSchedule int) (int, error) {
|
||||
if ds.Spec.UpdateStrategy.Type != apps.RollingUpdateDaemonSetStrategyType {
|
||||
return 0, nil
|
||||
}
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.DaemonSetUpdateSurge) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
r := ds.Spec.UpdateStrategy.RollingUpdate
|
||||
if r == nil {
|
||||
return 0, nil
|
||||
|
@ -215,6 +215,7 @@ const (
|
||||
// owner: @smarterclayton
|
||||
// alpha: v1.21
|
||||
// beta: v1.22
|
||||
// GA: v1.25
|
||||
// DaemonSets allow workloads to maintain availability during update per node
|
||||
DaemonSetUpdateSurge featuregate.Feature = "DaemonSetUpdateSurge"
|
||||
|
||||
@ -860,7 +861,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
||||
|
||||
CronJobTimeZone: {Default: false, PreRelease: featuregate.Alpha},
|
||||
|
||||
DaemonSetUpdateSurge: {Default: true, PreRelease: featuregate.Beta}, // on by default in 1.22
|
||||
DaemonSetUpdateSurge: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.27
|
||||
|
||||
DefaultPodTopologySpread: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.26
|
||||
|
||||
|
@ -24,17 +24,14 @@ import (
|
||||
apivalidation "k8s.io/apimachinery/pkg/api/validation"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/api/pod"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
"k8s.io/kubernetes/pkg/apis/apps/validation"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
||||
)
|
||||
|
||||
@ -82,7 +79,6 @@ func (daemonSetStrategy) PrepareForCreate(ctx context.Context, obj runtime.Objec
|
||||
daemonSet.Spec.TemplateGeneration = 1
|
||||
}
|
||||
|
||||
dropDaemonSetDisabledFields(daemonSet, nil)
|
||||
pod.DropDisabledTemplateFields(&daemonSet.Spec.Template, nil)
|
||||
}
|
||||
|
||||
@ -91,7 +87,6 @@ func (daemonSetStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.
|
||||
newDaemonSet := obj.(*apps.DaemonSet)
|
||||
oldDaemonSet := old.(*apps.DaemonSet)
|
||||
|
||||
dropDaemonSetDisabledFields(newDaemonSet, oldDaemonSet)
|
||||
pod.DropDisabledTemplateFields(&newDaemonSet.Spec.Template, &oldDaemonSet.Spec.Template)
|
||||
|
||||
// update is not allowed to set status
|
||||
@ -121,35 +116,6 @@ func (daemonSetStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.
|
||||
}
|
||||
}
|
||||
|
||||
// dropDaemonSetDisabledFields drops fields that are not used if their associated feature gates
|
||||
// are not enabled. The typical pattern is:
|
||||
// if !utilfeature.DefaultFeatureGate.Enabled(features.MyFeature) && !myFeatureInUse(oldSvc) {
|
||||
// newSvc.Spec.MyFeature = nil
|
||||
// }
|
||||
func dropDaemonSetDisabledFields(newDS *apps.DaemonSet, oldDS *apps.DaemonSet) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.DaemonSetUpdateSurge) {
|
||||
if r := newDS.Spec.UpdateStrategy.RollingUpdate; r != nil {
|
||||
if daemonSetSurgeFieldsInUse(oldDS) {
|
||||
// we need to ensure that MaxUnavailable is non-zero to preserve previous behavior
|
||||
if r.MaxUnavailable.IntVal == 0 && r.MaxUnavailable.StrVal == "0%" {
|
||||
r.MaxUnavailable = intstr.FromInt(1)
|
||||
}
|
||||
} else {
|
||||
// clear the MaxSurge field and let validation deal with MaxUnavailable
|
||||
r.MaxSurge = intstr.IntOrString{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// daemonSetSurgeFieldsInUse returns true if fields related to daemonset update surge are set
|
||||
func daemonSetSurgeFieldsInUse(ds *apps.DaemonSet) bool {
|
||||
if ds == nil {
|
||||
return false
|
||||
}
|
||||
return ds.Spec.UpdateStrategy.RollingUpdate != nil && (ds.Spec.UpdateStrategy.RollingUpdate.MaxSurge.IntVal != 0 || ds.Spec.UpdateStrategy.RollingUpdate.MaxSurge.StrVal != "")
|
||||
}
|
||||
|
||||
// Validate validates a new daemon set.
|
||||
func (daemonSetStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
|
||||
daemonSet := obj.(*apps.DaemonSet)
|
||||
|
@ -21,15 +21,10 @@ import (
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -139,207 +134,3 @@ func newDaemonSetWithSelectorLabels(selectorLabels map[string]string, templateGe
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func makeDaemonSetWithSurge(unavailable intstr.IntOrString, surge intstr.IntOrString) *apps.DaemonSet {
|
||||
return &apps.DaemonSet{
|
||||
Spec: apps.DaemonSetSpec{
|
||||
UpdateStrategy: apps.DaemonSetUpdateStrategy{
|
||||
Type: apps.RollingUpdateDaemonSetStrategyType,
|
||||
RollingUpdate: &apps.RollingUpdateDaemonSet{
|
||||
MaxUnavailable: unavailable,
|
||||
MaxSurge: surge,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropDisabledField(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
enableSurge bool
|
||||
ds *apps.DaemonSet
|
||||
old *apps.DaemonSet
|
||||
expect *apps.DaemonSet
|
||||
}{
|
||||
{
|
||||
name: "not surge, no update",
|
||||
enableSurge: false,
|
||||
ds: &apps.DaemonSet{},
|
||||
old: nil,
|
||||
expect: &apps.DaemonSet{},
|
||||
},
|
||||
{
|
||||
name: "not surge, field not used",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
old: nil,
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, field not used in old and new",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, field used",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromInt(1)),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromInt(1)),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromInt(1)),
|
||||
},
|
||||
{
|
||||
name: "not surge, field used, percent",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromString("1%")),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromString("1%")),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromString("1%")),
|
||||
},
|
||||
{
|
||||
name: "not surge, field used and cleared",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromInt(1)),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, field used and cleared, percent",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromString("1%")),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "surge, field not used",
|
||||
enableSurge: true,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
old: nil,
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "surge, field not used in old and new",
|
||||
enableSurge: true,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "surge, field used",
|
||||
enableSurge: true,
|
||||
ds: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
old: nil,
|
||||
expect: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
},
|
||||
{
|
||||
name: "surge, field used, percent",
|
||||
enableSurge: true,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromString("1%")),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromString("1%")),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromString("1%")),
|
||||
},
|
||||
{
|
||||
name: "surge, field used in old and new",
|
||||
enableSurge: true,
|
||||
ds: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
old: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
expect: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
},
|
||||
{
|
||||
name: "surge, allows both fields (validation must catch)",
|
||||
enableSurge: true,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromInt(1)),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromInt(1)),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.FromInt(1)),
|
||||
},
|
||||
{
|
||||
name: "surge, allows change from unavailable to surge",
|
||||
enableSurge: true,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
old: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "surge, allows change from surge to unvailable",
|
||||
enableSurge: true,
|
||||
ds: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
expect: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
},
|
||||
{
|
||||
name: "not surge, allows change from unavailable to surge",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
old: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, allows change from surge to unvailable",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromInt(1)),
|
||||
old: makeDaemonSetWithSurge(intstr.FromInt(2), intstr.IntOrString{}),
|
||||
expect: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, allows change from unavailable to surge, percent",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromString("2%"), intstr.IntOrString{}),
|
||||
old: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromString("1%")),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromString("2%"), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, allows change from surge to unvailable, percent",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.FromString("1%")),
|
||||
old: makeDaemonSetWithSurge(intstr.FromString("2%"), intstr.IntOrString{}),
|
||||
expect: makeDaemonSetWithSurge(intstr.IntOrString{}, intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, resets zero percent, one percent",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromString("0%"), intstr.FromString("1%")),
|
||||
old: makeDaemonSetWithSurge(intstr.FromString("0%"), intstr.FromString("1%")),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.FromString("1%")),
|
||||
},
|
||||
{
|
||||
name: "not surge, resets and clears when zero percent",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromString("0%"), intstr.IntOrString{}),
|
||||
old: makeDaemonSetWithSurge(intstr.FromString("0%"), intstr.FromString("1%")),
|
||||
expect: makeDaemonSetWithSurge(intstr.FromInt(1), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, sets zero percent, one percent",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromString("0%"), intstr.FromString("1%")),
|
||||
old: nil,
|
||||
expect: makeDaemonSetWithSurge(intstr.FromString("0%"), intstr.IntOrString{}),
|
||||
},
|
||||
{
|
||||
name: "not surge, sets and clears zero percent",
|
||||
enableSurge: false,
|
||||
ds: makeDaemonSetWithSurge(intstr.FromString("0%"), intstr.IntOrString{}),
|
||||
old: nil,
|
||||
expect: makeDaemonSetWithSurge(intstr.FromString("0%"), intstr.IntOrString{}),
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DaemonSetUpdateSurge, tc.enableSurge)()
|
||||
old := tc.old.DeepCopy()
|
||||
|
||||
dropDaemonSetDisabledFields(tc.ds, tc.old)
|
||||
|
||||
// old obj should never be changed
|
||||
if !reflect.DeepEqual(tc.old, old) {
|
||||
t.Fatalf("old ds changed: %v", diff.ObjectReflectDiff(tc.old, old))
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tc.ds, tc.expect) {
|
||||
t.Fatalf("unexpected ds spec: %v", diff.ObjectReflectDiff(tc.expect, tc.ds))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user