feat: add NodeInclusionPolicy to TopologySpreadConstraint in PodSpec

Signed-off-by: kerthcet <kerthcet@gmail.com>
This commit is contained in:
kerthcet
2022-05-10 12:54:49 +08:00
parent bf52c1fd46
commit 02f0a3ee91
82 changed files with 1666 additions and 934 deletions

View File

@@ -580,6 +580,7 @@ func dropDisabledFields(
}
dropDisabledTopologySpreadConstraintsFields(podSpec, oldPodSpec)
dropDisabledNodeInclusionPolicyFields(podSpec, oldPodSpec)
}
// dropDisabledTopologySpreadConstraintsFields removes disabled fields from PodSpec related
@@ -647,6 +648,51 @@ func dropDisabledCSIVolumeSourceAlphaFields(podSpec, oldPodSpec *api.PodSpec) {
}
}
// dropDisabledNodeInclusionPolicyFields removes disabled fields from PodSpec related
// to NodeInclusionPolicy only if it is not used by the old spec.
func dropDisabledNodeInclusionPolicyFields(podSpec, oldPodSpec *api.PodSpec) {
if !utilfeature.DefaultFeatureGate.Enabled(features.NodeInclusionPolicyInPodTopologySpread) && podSpec != nil {
if !nodeTaintsPolicyInUse(oldPodSpec) {
for i := range podSpec.TopologySpreadConstraints {
podSpec.TopologySpreadConstraints[i].NodeTaintsPolicy = nil
}
}
if !nodeAffinityPolicyInUse(oldPodSpec) {
for i := range podSpec.TopologySpreadConstraints {
podSpec.TopologySpreadConstraints[i].NodeAffinityPolicy = nil
}
}
}
}
// nodeAffinityPolicyInUse returns true if the pod spec is non-nil and has NodeAffinityPolicy field set
// in TopologySpreadConstraints
func nodeAffinityPolicyInUse(podSpec *api.PodSpec) bool {
if podSpec == nil {
return false
}
for _, c := range podSpec.TopologySpreadConstraints {
if c.NodeAffinityPolicy != nil {
return true
}
}
return false
}
// nodeTaintsPolicyInUse returns true if the pod spec is non-nil and has NodeTaintsPolicy field set
// in TopologySpreadConstraints
func nodeTaintsPolicyInUse(podSpec *api.PodSpec) bool {
if podSpec == nil {
return false
}
for _, c := range podSpec.TopologySpreadConstraints {
if c.NodeTaintsPolicy != nil {
return true
}
}
return false
}
func ephemeralContainersInUse(podSpec *api.PodSpec) bool {
if podSpec == nil {
return false

View File

@@ -1768,3 +1768,247 @@ func TestDropOSField(t *testing.T) {
}
}
}
func TestDropNodeInclusionPolicyFields(t *testing.T) {
ignore := api.NodeInclusionPolicyIgnore
honor := api.NodeInclusionPolicyHonor
tests := []struct {
name string
enabled bool
podSpec *api.PodSpec
oldPodSpec *api.PodSpec
wantPodSpec *api.PodSpec
}{
{
name: "feature disabled, both pods don't use the fields",
enabled: false,
oldPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{},
},
podSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{},
},
wantPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{},
},
},
{
name: "feature disabled, only old pod use NodeAffinityPolicy field",
enabled: false,
oldPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{NodeAffinityPolicy: &honor},
},
},
podSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{},
},
wantPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{},
},
},
{
name: "feature disabled, only old pod use NodeTaintsPolicy field",
enabled: false,
oldPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{NodeTaintsPolicy: &ignore},
},
},
podSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{},
},
wantPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{},
},
},
{
name: "feature disabled, only current pod use NodeAffinityPolicy field",
enabled: false,
oldPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{},
},
podSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{NodeAffinityPolicy: &honor},
},
},
wantPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{{
NodeAffinityPolicy: nil,
}},
},
},
{
name: "feature disabled, only current pod use NodeTaintsPolicy field",
enabled: false,
oldPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{},
},
podSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{NodeTaintsPolicy: &ignore},
},
},
wantPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{NodeTaintsPolicy: nil},
},
},
},
{
name: "feature disabled, both pods use NodeAffinityPolicy fields",
enabled: false,
oldPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{NodeAffinityPolicy: &honor},
},
},
podSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{NodeAffinityPolicy: &ignore},
},
},
wantPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{NodeAffinityPolicy: &ignore},
},
},
},
{
name: "feature disabled, both pods use NodeTaintsPolicy fields",
enabled: false,
oldPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{NodeTaintsPolicy: &ignore},
},
},
podSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{NodeTaintsPolicy: &honor},
},
},
wantPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{NodeTaintsPolicy: &honor},
},
},
},
{
name: "feature enabled, both pods use the fields",
enabled: true,
oldPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{
NodeAffinityPolicy: &ignore,
NodeTaintsPolicy: &honor,
},
},
},
podSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{
NodeAffinityPolicy: &honor,
NodeTaintsPolicy: &ignore,
},
},
},
wantPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{
NodeAffinityPolicy: &honor,
NodeTaintsPolicy: &ignore,
},
},
},
},
{
name: "feature enabled, only old pod use NodeAffinityPolicy field",
enabled: true,
oldPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{
NodeAffinityPolicy: &honor,
},
},
},
podSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{},
},
wantPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{},
},
},
{
name: "feature enabled, only old pod use NodeTaintsPolicy field",
enabled: true,
oldPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{
NodeTaintsPolicy: &ignore,
},
},
},
podSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{},
},
wantPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{},
},
},
{
name: "feature enabled, only current pod use NodeAffinityPolicy field",
enabled: true,
oldPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{},
},
podSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{
NodeAffinityPolicy: &ignore,
},
},
},
wantPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{
NodeAffinityPolicy: &ignore,
},
},
},
},
{
name: "feature enabled, only current pod use NodeTaintsPolicy field",
enabled: true,
oldPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{},
},
podSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{
NodeTaintsPolicy: &honor,
},
},
},
wantPodSpec: &api.PodSpec{
TopologySpreadConstraints: []api.TopologySpreadConstraint{
{
NodeTaintsPolicy: &honor,
},
},
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.NodeInclusionPolicyInPodTopologySpread, test.enabled)()
dropDisabledFields(test.podSpec, nil, test.oldPodSpec, nil)
if diff := cmp.Diff(test.wantPodSpec, test.podSpec); diff != "" {
t.Errorf("unexpected pod spec (-want, +got):\n%s", diff)
}
})
}
}