DisallowInvalidLabelValueInNodeSelector

This commit is contained in:
AxeZhan
2024-10-23 17:28:27 +08:00
parent 1e55df4985
commit ae11c7deb1
10 changed files with 366 additions and 13 deletions

View File

@@ -704,9 +704,28 @@ func TestValidatePersistentVolumeSpec(t *testing.T) {
MountOptions: []string{"soft", "read-write"},
},
},
"invalid-node-affinity": {
isExpectedFailure: true,
isInlineSpec: false,
pvSpec: &core.PersistentVolumeSpec{
NodeAffinity: &core.VolumeNodeAffinity{
Required: &core.NodeSelector{
NodeSelectorTerms: []core.NodeSelectorTerm{{
MatchExpressions: []core.NodeSelectorRequirement{{
Key: "foo",
Operator: core.NodeSelectorOpIn,
Values: []string{"-1"},
}},
}},
},
},
},
},
}
for name, scenario := range scenarios {
opts := PersistentVolumeSpecValidationOptions{}
opts := ValidationOptionsForPersistentVolume(&core.PersistentVolume{
Spec: *scenario.pvSpec.DeepCopy(),
}, nil)
errs := ValidatePersistentVolumeSpec(scenario.pvSpec, "", scenario.isInlineSpec, field.NewPath("field"), opts)
if len(errs) == 0 && scenario.isExpectedFailure {
t.Errorf("Unexpected success for scenario: %s", name)
@@ -998,6 +1017,24 @@ func TestValidationOptionsForPersistentVolume(t *testing.T) {
enableVolumeAttributesClass: false,
expectValidationOpts: PersistentVolumeSpecValidationOptions{EnableVolumeAttributesClass: true},
},
"old pv has invalid label-value in node affinity": {
oldPv: &core.PersistentVolume{
Spec: core.PersistentVolumeSpec{
NodeAffinity: &core.VolumeNodeAffinity{
Required: &core.NodeSelector{
NodeSelectorTerms: []core.NodeSelectorTerm{{
MatchExpressions: []core.NodeSelectorRequirement{{
Key: "foo",
Operator: core.NodeSelectorOpIn,
Values: []string{"-1"},
}},
}},
},
},
},
},
expectValidationOpts: PersistentVolumeSpecValidationOptions{AllowInvalidLabelValueInRequiredNodeAffinity: true},
},
}
for name, tc := range tests {
@@ -1464,6 +1501,11 @@ func TestValidateVolumeNodeAffinityUpdate(t *testing.T) {
oldPV: testVolumeWithNodeAffinity(simpleVolumeNodeAffinity("foo", "bar")),
newPV: testVolumeWithNodeAffinity(nil),
},
"old affinity already has invalid label-value": {
isExpectedFailure: false,
oldPV: testVolumeWithNodeAffinity(simpleVolumeNodeAffinity(v1.LabelInstanceType, "-1")),
newPV: testVolumeWithNodeAffinity(simpleVolumeNodeAffinity(v1.LabelInstanceTypeStable, "-1")),
},
}
for name, scenario := range scenarios {
@@ -12242,6 +12284,23 @@ func TestValidatePod(t *testing.T) {
podtest.SetAnnotations(map[string]string{core.PodDeletionCost: "+10"}),
),
},
"invalid required node affinity, value of NodeSelectorRequirement should be a valid label value": {
expectedError: "spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].values[0]: Invalid value: \"-1\": a valid label must be an empty string or consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character (e.g. 'MyValue', or 'my_value', or '12345', regex used for validation is '(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?')",
spec: *podtest.MakePod("123",
podtest.SetAffinity(&core.Affinity{
NodeAffinity: &core.NodeAffinity{
RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{
NodeSelectorTerms: []core.NodeSelectorTerm{{
MatchExpressions: []core.NodeSelectorRequirement{{
Key: "foo",
Operator: core.NodeSelectorOpIn,
Values: []string{"-1"},
}},
}},
}},
}),
),
},
}
for k, v := range errorCases {
@@ -12316,6 +12375,7 @@ func TestValidatePodUpdate(t *testing.T) {
old core.Pod
new core.Pod
err string
opts PodValidationOptions
}{
{new: *podtest.MakePod(""), old: *podtest.MakePod(""), err: "", test: "nothing"}, {
new: *podtest.MakePod("foo"),
@@ -13669,6 +13729,73 @@ func TestValidatePodUpdate(t *testing.T) {
err: "pod updates may not change fields other than",
test: "the podAntiAffinity cannot be updated on gated pods",
},
{
old: *podtest.MakePod("foo",
podtest.SetAffinity(&core.Affinity{
NodeAffinity: &core.NodeAffinity{
RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{
NodeSelectorTerms: []core.NodeSelectorTerm{{
MatchExpressions: []core.NodeSelectorRequirement{{
Key: "expr",
Operator: core.NodeSelectorOpIn,
Values: []string{"-1"},
}},
}},
}},
}),
podtest.SetSchedulingGates(core.PodSchedulingGate{Name: "baz"}),
),
new: *podtest.MakePod("foo",
podtest.SetAffinity(&core.Affinity{
NodeAffinity: &core.NodeAffinity{
RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{
NodeSelectorTerms: []core.NodeSelectorTerm{{
MatchExpressions: []core.NodeSelectorRequirement{{
Key: "expr",
Operator: core.NodeSelectorOpIn,
Values: []string{"-1"},
}},
}},
}},
}),
),
test: "allow update pod if old pod already has invalid label-value in node affinity",
opts: PodValidationOptions{AllowInvalidLabelValueInRequiredNodeAffinity: true},
},
{
old: *podtest.MakePod("foo",
podtest.SetAffinity(&core.Affinity{
NodeAffinity: &core.NodeAffinity{
RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{
NodeSelectorTerms: []core.NodeSelectorTerm{{
MatchExpressions: []core.NodeSelectorRequirement{{
Key: "expr",
Operator: core.NodeSelectorOpIn,
Values: []string{"bar"},
}},
}},
}},
}),
podtest.SetSchedulingGates(core.PodSchedulingGate{Name: "baz"}),
),
new: *podtest.MakePod("foo",
podtest.SetAffinity(&core.Affinity{
NodeAffinity: &core.NodeAffinity{
RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{
NodeSelectorTerms: []core.NodeSelectorTerm{{
MatchExpressions: []core.NodeSelectorRequirement{{
Key: "expr",
Operator: core.NodeSelectorOpIn,
Values: []string{"-1"},
}},
}},
}},
}),
podtest.SetSchedulingGates(core.PodSchedulingGate{Name: "baz"}),
),
err: `a valid label must be an empty string or consist of alphanumeric characters, '-', '_' or '.'`,
test: "not allow update node affinity to an invalid label-value",
},
{
new: *podtest.MakePod("pod",
podtest.SetContainers(podtest.MakeContainer("container",
@@ -13730,7 +13857,7 @@ func TestValidatePodUpdate(t *testing.T) {
test.old.Spec.RestartPolicy = "Always"
}
errs := ValidatePodUpdate(&test.new, &test.old, PodValidationOptions{})
errs := ValidatePodUpdate(&test.new, &test.old, test.opts)
if test.err == "" {
if len(errs) != 0 {
t.Errorf("unexpected invalid: %s (%+v)\nA: %+v\nB: %+v", test.test, errs, test.new, test.old)