Merge pull request #115569 from Huang-Wei/psr-unconditional-validation

Enforce nodeName cannot be set along with non-empty schedulingGates
This commit is contained in:
Kubernetes Prow Robot 2023-02-08 16:16:47 -08:00 committed by GitHub
commit 9b09d0600a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 31 deletions

View File

@ -4417,8 +4417,7 @@ func ValidatePodCreate(pod *core.Pod, opts PodValidationOptions) field.ErrorList
allErrs = append(allErrs, field.Forbidden(fldPath.Child("ephemeralContainers"), "cannot be set on create")) allErrs = append(allErrs, field.Forbidden(fldPath.Child("ephemeralContainers"), "cannot be set on create"))
} }
// A Pod cannot be assigned a Node if there are remaining scheduling gates. // A Pod cannot be assigned a Node if there are remaining scheduling gates.
if utilfeature.DefaultFeatureGate.Enabled(features.PodSchedulingReadiness) && if pod.Spec.NodeName != "" && len(pod.Spec.SchedulingGates) != 0 {
pod.Spec.NodeName != "" && len(pod.Spec.SchedulingGates) != 0 {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("nodeName"), "cannot be set until all schedulingGates have been cleared")) allErrs = append(allErrs, field.Forbidden(fldPath.Child("nodeName"), "cannot be set until all schedulingGates have been cleared"))
} }
allErrs = append(allErrs, validateSeccompAnnotationsAndFields(pod.ObjectMeta, &pod.Spec, fldPath)...) allErrs = append(allErrs, validateSeccompAnnotationsAndFields(pod.ObjectMeta, &pod.Spec, fldPath)...)

View File

@ -10817,7 +10817,7 @@ func TestValidatePodCreateWithSchedulingGates(t *testing.T) {
}, },
}, },
featureEnabled: false, featureEnabled: false,
wantFieldErrors: nil, wantFieldErrors: []*field.Error{field.Forbidden(fldPath.Child("nodeName"), "cannot be set until all schedulingGates have been cleared")},
}, },
{ {
name: "create a Pod with nodeName and schedulingGates, feature enabled", name: "create a Pod with nodeName and schedulingGates, feature enabled",

View File

@ -33,12 +33,10 @@ import (
"k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage"
storeerr "k8s.io/apiserver/pkg/storage/errors" storeerr "k8s.io/apiserver/pkg/storage/errors"
"k8s.io/apiserver/pkg/util/dryrun" "k8s.io/apiserver/pkg/util/dryrun"
utilfeature "k8s.io/apiserver/pkg/util/feature"
policyclient "k8s.io/client-go/kubernetes/typed/policy/v1" policyclient "k8s.io/client-go/kubernetes/typed/policy/v1"
podutil "k8s.io/kubernetes/pkg/api/pod" podutil "k8s.io/kubernetes/pkg/api/pod"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/core/validation" "k8s.io/kubernetes/pkg/apis/core/validation"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/kubelet/client" "k8s.io/kubernetes/pkg/kubelet/client"
"k8s.io/kubernetes/pkg/printers" "k8s.io/kubernetes/pkg/printers"
printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
@ -225,7 +223,7 @@ func (r *BindingREST) setPodHostAndAnnotations(ctx context.Context, podUID types
return nil, fmt.Errorf("pod %v is already assigned to node %q", pod.Name, pod.Spec.NodeName) return nil, fmt.Errorf("pod %v is already assigned to node %q", pod.Name, pod.Spec.NodeName)
} }
// Reject binding to a scheduling un-ready Pod. // Reject binding to a scheduling un-ready Pod.
if utilfeature.DefaultFeatureGate.Enabled(features.PodSchedulingReadiness) && len(pod.Spec.SchedulingGates) != 0 { if len(pod.Spec.SchedulingGates) != 0 {
return nil, fmt.Errorf("pod %v has non-empty .spec.schedulingGates", pod.Name) return nil, fmt.Errorf("pod %v has non-empty .spec.schedulingGates", pod.Name)
} }
pod.Spec.NodeName = machine pod.Spec.NodeName = machine

View File

@ -789,6 +789,10 @@ func TestEtcdCreateWithSchedulingGates(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
for _, flipFeatureGateBeforeBinding := range []bool{false, true} {
if flipFeatureGateBeforeBinding {
tt.name = fmt.Sprintf("%v and flipped before binding", tt.name)
}
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodSchedulingReadiness, tt.featureEnabled)() defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodSchedulingReadiness, tt.featureEnabled)()
storage, bindingStorage, _, server := newStorage(t) storage, bindingStorage, _, server := newStorage(t)
@ -801,6 +805,9 @@ func TestEtcdCreateWithSchedulingGates(t *testing.T) {
if _, err := storage.Create(ctx, pod, rest.ValidateAllObjectFunc, &metav1.CreateOptions{}); err != nil { if _, err := storage.Create(ctx, pod, rest.ValidateAllObjectFunc, &metav1.CreateOptions{}); err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
if flipFeatureGateBeforeBinding {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodSchedulingReadiness, !tt.featureEnabled)()
}
_, err := bindingStorage.Create(ctx, "foo", &api.Binding{ _, err := bindingStorage.Create(ctx, "foo", &api.Binding{
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "foo"}, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "foo"},
Target: api.ObjectReference{Name: "machine"}, Target: api.ObjectReference{Name: "machine"},
@ -818,6 +825,7 @@ func TestEtcdCreateWithSchedulingGates(t *testing.T) {
} }
}) })
} }
}
} }
func validNewBinding() *api.Binding { func validNewBinding() *api.Binding {