mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 10:51:29 +00:00
Enforce nodeName cannot be set along with non empty schedulingGates
This commit is contained in:
parent
dfb976e25a
commit
feed8c683d
@ -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)...)
|
||||||
|
@ -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",
|
||||||
|
@ -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
|
||||||
|
@ -789,34 +789,42 @@ func TestEtcdCreateWithSchedulingGates(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
for _, flipFeatureGateBeforeBinding := range []bool{false, true} {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodSchedulingReadiness, tt.featureEnabled)()
|
if flipFeatureGateBeforeBinding {
|
||||||
storage, bindingStorage, _, server := newStorage(t)
|
tt.name = fmt.Sprintf("%v and flipped before binding", tt.name)
|
||||||
defer server.Terminate(t)
|
}
|
||||||
defer storage.Store.DestroyFunc()
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
ctx := genericapirequest.NewDefaultContext()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodSchedulingReadiness, tt.featureEnabled)()
|
||||||
|
storage, bindingStorage, _, server := newStorage(t)
|
||||||
|
defer server.Terminate(t)
|
||||||
|
defer storage.Store.DestroyFunc()
|
||||||
|
ctx := genericapirequest.NewDefaultContext()
|
||||||
|
|
||||||
pod := validNewPod()
|
pod := validNewPod()
|
||||||
pod.Spec.SchedulingGates = tt.schedulingGates
|
pod.Spec.SchedulingGates = tt.schedulingGates
|
||||||
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)
|
||||||
}
|
|
||||||
_, err := bindingStorage.Create(ctx, "foo", &api.Binding{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "foo"},
|
|
||||||
Target: api.ObjectReference{Name: "machine"},
|
|
||||||
}, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
|
||||||
if tt.wantErr == nil {
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Want nil err, but got %v", err)
|
|
||||||
}
|
}
|
||||||
} else {
|
if flipFeatureGateBeforeBinding {
|
||||||
if err == nil {
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodSchedulingReadiness, !tt.featureEnabled)()
|
||||||
t.Errorf("Want %v, but got nil err", tt.wantErr)
|
|
||||||
} else if tt.wantErr.Error() != err.Error() {
|
|
||||||
t.Errorf("Want %v, but got %v", tt.wantErr, err)
|
|
||||||
}
|
}
|
||||||
}
|
_, err := bindingStorage.Create(ctx, "foo", &api.Binding{
|
||||||
})
|
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "foo"},
|
||||||
|
Target: api.ObjectReference{Name: "machine"},
|
||||||
|
}, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
|
||||||
|
if tt.wantErr == nil {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Want nil err, but got %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Want %v, but got nil err", tt.wantErr)
|
||||||
|
} else if tt.wantErr.Error() != err.Error() {
|
||||||
|
t.Errorf("Want %v, but got %v", tt.wantErr, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user