diff --git a/plugin/pkg/admission/limitranger/admission.go b/plugin/pkg/admission/limitranger/admission.go index 7ff6cbb42d8..274b7693859 100644 --- a/plugin/pkg/admission/limitranger/admission.go +++ b/plugin/pkg/admission/limitranger/admission.go @@ -48,6 +48,12 @@ type limitRanger struct { // Admit admits resources into cluster that do not violate any defined LimitRange in the namespace func (l *limitRanger) Admit(a admission.Attributes) (err error) { + + // Ignore all calls to subresources + if a.GetSubresource() != "" { + return nil + } + obj := a.GetObject() resource := a.GetResource() name := "Unknown" diff --git a/plugin/pkg/admission/limitranger/admission_test.go b/plugin/pkg/admission/limitranger/admission_test.go index 9765509b19b..5e62a0a648a 100644 --- a/plugin/pkg/admission/limitranger/admission_test.go +++ b/plugin/pkg/admission/limitranger/admission_test.go @@ -20,8 +20,11 @@ import ( "strconv" "testing" + "github.com/GoogleCloudPlatform/kubernetes/pkg/admission" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource" + "github.com/GoogleCloudPlatform/kubernetes/pkg/client/cache" + "github.com/GoogleCloudPlatform/kubernetes/pkg/client/testclient" ) func getResourceList(cpu, memory string) api.ResourceList { @@ -45,7 +48,8 @@ func getResourceRequirements(limits, requests api.ResourceList) api.ResourceRequ func validLimitRange() api.LimitRange { return api.LimitRange{ ObjectMeta: api.ObjectMeta{ - Name: "abc", + Name: "abc", + Namespace: "test", }, Spec: api.LimitRangeSpec{ Limits: []api.LimitRangeItem{ @@ -65,9 +69,32 @@ func validLimitRange() api.LimitRange { } } +func validLimitRangeNoDefaults() api.LimitRange { + return api.LimitRange{ + ObjectMeta: api.ObjectMeta{ + Name: "abc", + Namespace: "test", + }, + Spec: api.LimitRangeSpec{ + Limits: []api.LimitRangeItem{ + { + Type: api.LimitTypePod, + Max: getResourceList("200m", "4Gi"), + Min: getResourceList("50m", "2Mi"), + }, + { + Type: api.LimitTypeContainer, + Max: getResourceList("100m", "2Gi"), + Min: getResourceList("25m", "1Mi"), + }, + }, + }, + } +} + func validPod(name string, numContainers int, resources api.ResourceRequirements) api.Pod { pod := api.Pod{ - ObjectMeta: api.ObjectMeta{Name: name}, + ObjectMeta: api.ObjectMeta{Name: name, Namespace: "test"}, Spec: api.PodSpec{}, } pod.Spec.Containers = make([]api.Container, 0, numContainers) @@ -192,3 +219,29 @@ func TestPodLimitFuncApplyDefault(t *testing.T) { } } } + +func TestLimitRangerIgnoresSubresource(t *testing.T) { + client := testclient.NewSimpleFake() + indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}) + handler := &limitRanger{ + Handler: admission.NewHandler(admission.Create, admission.Update), + client: client, + limitFunc: Limit, + indexer: indexer, + } + + limitRange := validLimitRangeNoDefaults() + testPod := validPod("testPod", 1, api.ResourceRequirements{}) + + indexer.Add(&limitRange) + err := handler.Admit(admission.NewAttributesRecord(&testPod, "Pod", limitRange.Namespace, "pods", "", admission.Update, nil)) + if err == nil { + t.Errorf("Expected an error since the pod did not specify resource limits in its update call") + } + + err = handler.Admit(admission.NewAttributesRecord(&testPod, "Pod", limitRange.Namespace, "pods", "status", admission.Update, nil)) + if err != nil { + t.Errorf("Should have ignored calls to any subresource of pod %v", err) + } + +}