Allow system critical priority classes in API validation
This commit is contained in:
@@ -17,11 +17,16 @@ limitations under the License.
|
||||
package storage
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
schedulingapi "k8s.io/kubernetes/pkg/apis/scheduling"
|
||||
"k8s.io/kubernetes/pkg/apis/scheduling"
|
||||
"k8s.io/kubernetes/pkg/registry/scheduling/priorityclass"
|
||||
)
|
||||
|
||||
@@ -33,9 +38,9 @@ type REST struct {
|
||||
// NewREST returns a RESTStorage object that will work against priority classes.
|
||||
func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
|
||||
store := &genericregistry.Store{
|
||||
NewFunc: func() runtime.Object { return &schedulingapi.PriorityClass{} },
|
||||
NewListFunc: func() runtime.Object { return &schedulingapi.PriorityClassList{} },
|
||||
DefaultQualifiedResource: schedulingapi.Resource("priorityclasses"),
|
||||
NewFunc: func() runtime.Object { return &scheduling.PriorityClass{} },
|
||||
NewListFunc: func() runtime.Object { return &scheduling.PriorityClassList{} },
|
||||
DefaultQualifiedResource: scheduling.Resource("priorityclasses"),
|
||||
|
||||
CreateStrategy: priorityclass.Strategy,
|
||||
UpdateStrategy: priorityclass.Strategy,
|
||||
@@ -56,3 +61,14 @@ var _ rest.ShortNamesProvider = &REST{}
|
||||
func (r *REST) ShortNames() []string {
|
||||
return []string{"pc"}
|
||||
}
|
||||
|
||||
// Delete ensures that system priority classes are not deleted.
|
||||
func (r *REST) Delete(ctx genericapirequest.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) {
|
||||
for _, spc := range scheduling.SystemPriorityClasses() {
|
||||
if name == spc.Name {
|
||||
return nil, false, apierrors.NewForbidden(scheduling.Resource("priorityclasses"), spc.Name, errors.New("this is a system priority class and cannot be deleted"))
|
||||
}
|
||||
}
|
||||
|
||||
return r.Store.Delete(ctx, name, options)
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
genericregistrytest "k8s.io/apiserver/pkg/registry/generic/testing"
|
||||
etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing"
|
||||
@@ -105,6 +106,22 @@ func TestDelete(t *testing.T) {
|
||||
test.TestDelete(validNewPriorityClass())
|
||||
}
|
||||
|
||||
// TestDeleteSystemPriorityClass checks that system priority classes cannot be deleted.
|
||||
func TestDeleteSystemPriorityClass(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.Store.DestroyFunc()
|
||||
key := "test/system-node-critical"
|
||||
ctx := genericapirequest.NewContext()
|
||||
pc := scheduling.SystemPriorityClasses()[0]
|
||||
if err := storage.Store.Storage.Create(ctx, key, pc, nil, 0); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if _, _, err := storage.Delete(ctx, pc.Name, nil); err == nil {
|
||||
t.Error("expected to receive an error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
|
@@ -68,9 +68,7 @@ func (priorityClassStrategy) AllowCreateOnUpdate() bool {
|
||||
|
||||
// ValidateUpdate is the default update validation for an end user.
|
||||
func (priorityClassStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList {
|
||||
validationErrorList := validation.ValidatePriorityClass(obj.(*scheduling.PriorityClass))
|
||||
updateErrorList := validation.ValidatePriorityClassUpdate(obj.(*scheduling.PriorityClass), old.(*scheduling.PriorityClass))
|
||||
return append(validationErrorList, updateErrorList...)
|
||||
return validation.ValidatePriorityClassUpdate(obj.(*scheduling.PriorityClass), old.(*scheduling.PriorityClass))
|
||||
}
|
||||
|
||||
// AllowUnconditionalUpdate is the default update policy for PriorityClass objects.
|
||||
|
@@ -68,22 +68,6 @@ func (p RESTStorageProvider) PostStartHook() (string, genericapiserver.PostStart
|
||||
}
|
||||
|
||||
func AddSystemPriorityClasses() genericapiserver.PostStartHookFunc {
|
||||
priorityClasses := []*scheduling.PriorityClass{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: scheduling.SystemNodeCritical,
|
||||
},
|
||||
Value: scheduling.SystemCriticalPriority + 1000,
|
||||
Description: "Used for system critical pods that must not be moved from their current node.",
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: scheduling.SystemClusterCritical,
|
||||
},
|
||||
Value: scheduling.SystemCriticalPriority,
|
||||
Description: "Used for system critical pods that must run in the cluster, but can be moved to another node if necessary.",
|
||||
},
|
||||
}
|
||||
return func(hookContext genericapiserver.PostStartHookContext) error {
|
||||
// Adding system priority classes is important. If they fail to add, many critical system
|
||||
// components may fail and cluster may break.
|
||||
@@ -94,7 +78,7 @@ func AddSystemPriorityClasses() genericapiserver.PostStartHookFunc {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
for _, pc := range priorityClasses {
|
||||
for _, pc := range scheduling.SystemPriorityClasses() {
|
||||
_, err := schedClientSet.PriorityClasses().Get(pc.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
@@ -106,11 +90,12 @@ func AddSystemPriorityClasses() genericapiserver.PostStartHookFunc {
|
||||
}
|
||||
} else {
|
||||
// Unable to get the priority class for reasons other than "not found".
|
||||
glog.Warningf("unable to get PriorityClass %v: %v. Retrying...", pc.Name, err)
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
}
|
||||
glog.Infof("all system priority classes are created successfully.")
|
||||
glog.Infof("all system priority classes are created successfully or already exist.")
|
||||
return true, nil
|
||||
})
|
||||
// if we're never able to make it through initialization, kill the API server.
|
||||
|
Reference in New Issue
Block a user