From ad20045c8dfe5adfc4453824b715b6e66d95b5da Mon Sep 17 00:00:00 2001 From: Jordan Liggitt Date: Sat, 12 Mar 2016 22:46:20 -0500 Subject: [PATCH] Correctly identify namespace subresources in GetRequestInfo --- pkg/apiserver/handlers.go | 9 ++++++++- pkg/apiserver/handlers_test.go | 3 ++- pkg/master/master_test.go | 22 ++++++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/pkg/apiserver/handlers.go b/pkg/apiserver/handlers.go index 898b29799af..f0315008e7b 100644 --- a/pkg/apiserver/handlers.go +++ b/pkg/apiserver/handlers.go @@ -45,6 +45,13 @@ var specialVerbs = sets.NewString("proxy", "redirect", "watch") // specialVerbsNoSubresources contains root verbs which do not allow subresources var specialVerbsNoSubresources = sets.NewString("proxy", "redirect") +// namespaceSubresources contains subresources of namespace +// this list allows the parser to distinguish between a namespace subresource, and a namespaced resource +var namespaceSubresources = sets.NewString("status", "finalize") + +// NamespaceSubResourcesForTest exports namespaceSubresources for testing in pkg/master/master_test.go, so we never drift +var NamespaceSubResourcesForTest = sets.NewString(namespaceSubresources.List()...) + // Constant for the retry-after interval on rate limiting. // TODO: maybe make this dynamic? or user-adjustable? const RetryAfter = "1" @@ -549,7 +556,7 @@ func (r *RequestInfoResolver) GetRequestInfo(req *http.Request) (RequestInfo, er // if there is another step after the namespace name and it is not a known namespace subresource // move currentParts to include it as a resource in its own right - if len(currentParts) > 2 { + if len(currentParts) > 2 && !namespaceSubresources.Has(currentParts[2]) { currentParts = currentParts[2:] } } diff --git a/pkg/apiserver/handlers_test.go b/pkg/apiserver/handlers_test.go index 585113a1601..2dd5dbd270a 100644 --- a/pkg/apiserver/handlers_test.go +++ b/pkg/apiserver/handlers_test.go @@ -358,7 +358,8 @@ func TestGetAPIRequestInfo(t *testing.T) { // subresource identification {"GET", "/api/v1/namespaces/other/pods/foo/status", "get", "api", "", "v1", "other", "pods", "status", "foo", []string{"pods", "foo", "status"}}, {"GET", "/api/v1/namespaces/other/pods/foo/proxy/subpath", "get", "api", "", "v1", "other", "pods", "proxy", "foo", []string{"pods", "foo", "proxy", "subpath"}}, - {"PUT", "/api/v1/namespaces/other/finalize", "update", "api", "", "v1", "other", "finalize", "", "", []string{"finalize"}}, + {"PUT", "/api/v1/namespaces/other/finalize", "update", "api", "", "v1", "other", "namespaces", "finalize", "other", []string{"namespaces", "other", "finalize"}}, + {"PUT", "/api/v1/namespaces/other/status", "update", "api", "", "v1", "other", "namespaces", "status", "other", []string{"namespaces", "other", "status"}}, // verb identification {"PATCH", "/api/v1/namespaces/other/pods/foo", "patch", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}}, diff --git a/pkg/master/master_test.go b/pkg/master/master_test.go index 489d08f6e69..33c8ee8a41a 100644 --- a/pkg/master/master_test.go +++ b/pkg/master/master_test.go @@ -32,7 +32,9 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/unversioned" + "k8s.io/kubernetes/pkg/apiserver" utilnet "k8s.io/kubernetes/pkg/util/net" + "k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/apis/autoscaling" "k8s.io/kubernetes/pkg/apis/batch" @@ -132,6 +134,26 @@ func TestNew(t *testing.T) { assert.Equal(master.ProxyTransport.(*http.Transport).TLSClientConfig, config.ProxyTLSClientConfig) } +// TestNamespaceSubresources ensures the namespace subresource parsing in apiserver/handlers.go doesn't drift +func TestNamespaceSubresources(t *testing.T) { + master, etcdserver, _, _ := newMaster(t) + defer etcdserver.Terminate(t) + + expectedSubresources := apiserver.NamespaceSubResourcesForTest + foundSubresources := sets.NewString() + + for k := range master.v1ResourcesStorage { + parts := strings.Split(k, "/") + if len(parts) == 2 && parts[0] == "namespaces" { + foundSubresources.Insert(parts[1]) + } + } + + if !reflect.DeepEqual(expectedSubresources.List(), foundSubresources.List()) { + t.Errorf("Expected namespace subresources %#v, got %#v. Update apiserver/handlers.go#namespaceSubresources", expectedSubresources.List(), foundSubresources.List()) + } +} + // TestGetServersToValidate verifies the unexported getServersToValidate function func TestGetServersToValidate(t *testing.T) { master, etcdserver, config, assert := setUp(t)