Return the error from validateOverhead in RuntimeClass#Validate

This commit is contained in:
Ted Yu 2019-07-10 17:32:51 -07:00 committed by Ted Yu
parent 6a2d0f67d1
commit 059243fbd2
3 changed files with 81 additions and 19 deletions

View File

@ -32,6 +32,7 @@ go_test(
"//staging/src/k8s.io/api/node/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",

View File

@ -112,9 +112,10 @@ func (r *RuntimeClass) Validate(attributes admission.Attributes, o admission.Obj
if err != nil {
return err
}
if utilfeature.DefaultFeatureGate.Enabled(features.PodOverhead) {
err = validateOverhead(attributes, pod, runtimeClass)
if err = validateOverhead(attributes, pod, runtimeClass); err != nil {
return err
}
}
return nil
@ -136,28 +137,17 @@ func (r *RuntimeClass) prepareObjects(attributes admission.Attributes) (pod *api
}
// get RuntimeClass object
runtimeClass, err = r.getRuntimeClass(pod, pod.Spec.RuntimeClassName)
if err != nil {
return pod, nil, err
if pod.Spec.RuntimeClassName != nil {
runtimeClass, err = r.runtimeClassLister.Get(*pod.Spec.RuntimeClassName)
if err != nil {
return pod, nil, err
}
}
// return the pod and runtimeClass. If no RuntimeClass is specified in PodSpec, runtimeClass will be nil
return pod, runtimeClass, nil
}
// getRuntimeClass will return a reference to the RuntimeClass object if it is found. If it cannot be found, or a RuntimeClassName
// is not provided in the pod spec, *node.RuntimeClass returned will be nil
func (r *RuntimeClass) getRuntimeClass(pod *api.Pod, runtimeClassName *string) (runtimeClass *v1beta1.RuntimeClass, err error) {
runtimeClass = nil
if runtimeClassName != nil {
runtimeClass, err = r.runtimeClassLister.Get(*runtimeClassName)
}
return runtimeClass, err
}
func setOverhead(a admission.Attributes, pod *api.Pod, runtimeClass *v1beta1.RuntimeClass) (err error) {
if runtimeClass != nil {

View File

@ -21,6 +21,7 @@ import (
"k8s.io/api/node/v1beta1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/authentication/user"
utilfeature "k8s.io/apiserver/pkg/util/feature"
@ -154,9 +155,79 @@ func TestSetOverhead(t *testing.T) {
})
}
}
func NewObjectInterfacesForTest() admission.ObjectInterfaces {
scheme := runtime.NewScheme()
corev1.AddToScheme(scheme)
return admission.NewObjectInterfacesFromScheme(scheme)
}
func TestValidate(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodOverhead, true)()
tests := []struct {
name string
runtimeClass *v1beta1.RuntimeClass
pod *core.Pod
expectError bool
}{
{
name: "No Overhead in RunntimeClass, Overhead set in pod",
runtimeClass: &v1beta1.RuntimeClass{
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Handler: "bar",
},
pod: validPod("no-resource-req-no-overhead", 1, getGuaranteedRequirements(), true),
expectError: true,
},
{
name: "Non-matching Overheads",
runtimeClass: &v1beta1.RuntimeClass{
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Handler: "bar",
Overhead: &v1beta1.Overhead{
PodFixed: corev1.ResourceList{
corev1.ResourceName(corev1.ResourceCPU): resource.MustParse("10"),
corev1.ResourceName(corev1.ResourceMemory): resource.MustParse("10G"),
},
},
},
pod: validPod("no-resource-req-no-overhead", 1, core.ResourceRequirements{}, true),
expectError: true,
},
{
name: "Matching Overheads",
runtimeClass: &v1beta1.RuntimeClass{
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
Handler: "bar",
Overhead: &v1beta1.Overhead{
PodFixed: corev1.ResourceList{
corev1.ResourceName(corev1.ResourceCPU): resource.MustParse("100m"),
corev1.ResourceName(corev1.ResourceMemory): resource.MustParse("1"),
},
},
},
pod: validPod("no-resource-req-no-overhead", 1, core.ResourceRequirements{}, false),
expectError: false,
},
}
rt := NewRuntimeClass()
o := NewObjectInterfacesForTest()
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
attrs := admission.NewAttributesRecord(tc.pod, nil, core.Kind("Pod").WithVersion("version"), tc.pod.Namespace, tc.pod.Name, core.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, &user.DefaultInfo{})
errs := rt.Validate(attrs, o)
if tc.expectError {
assert.NotEmpty(t, errs)
} else {
assert.Empty(t, errs)
}
})
}
}
func TestValidateOverhead(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodOverhead, true)()
tests := []struct {