From 2396a520171d5109fde9ba44926f858be49456d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Martins?= Date: Thu, 21 Feb 2019 20:25:36 +0100 Subject: [PATCH] client-go/rest: fix finalURLTemplate for url base == "/" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some environments, where url base is "/", it can cause all paths to be presented in metrics with "{prefix}" as `groupIndex` is with the wrong index. To fix the behavior in such environments, it was added a conditional branch to check if the URL base is "/" and, thus, print the metrics with the correct path, for example "api/v1/nodes/{name}" instead of "{prefix}". Fixes: 99248b8fe1fe ("Rewrite finalURLTemplate used only for metrics because of dynamic client change") Signed-off-by: André Martins Kubernetes-commit: c039b02fa7281fc061455e23b6530ed8b4d19645 --- rest/request.go | 20 +++++++++++++++----- rest/request_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/rest/request.go b/rest/request.go index 2f747a28..1ccc0daf 100644 --- a/rest/request.go +++ b/rest/request.go @@ -511,13 +511,23 @@ func (r Request) finalURLTemplate() url.URL { } r.params = newParams url := r.URL() - segments := strings.Split(r.URL().Path, "/") + + segments := strings.Split(url.Path, "/") groupIndex := 0 index := 0 - if r.URL() != nil && r.c.base != nil && strings.Contains(r.URL().Path, r.c.base.Path) { - groupIndex += len(strings.Split(r.c.base.Path, "/")) + trimmedBasePath := "" + if url != nil && r.c.base != nil && strings.Contains(url.Path, r.c.base.Path) { + p := strings.TrimPrefix(url.Path, r.c.base.Path) + if !strings.HasPrefix(p, "/") { + p = "/" + p + } + // store the base path that we have trimmed so we can append it + // before returning the URL + trimmedBasePath = r.c.base.Path + segments = strings.Split(p, "/") + groupIndex = 1 } - if groupIndex >= len(segments) { + if len(segments) <= 2 { return *url } @@ -563,7 +573,7 @@ func (r Request) finalURLTemplate() url.URL { segments[index+3] = "{name}" } } - url.Path = path.Join(segments...) + url.Path = path.Join(trimmedBasePath, path.Join(segments...)) return *url } diff --git a/rest/request_test.go b/rest/request_test.go index e4412f28..645512b7 100644 --- a/rest/request_test.go +++ b/rest/request_test.go @@ -338,6 +338,7 @@ func TestResultIntoWithNoBodyReturnsErr(t *testing.T) { func TestURLTemplate(t *testing.T) { uri, _ := url.Parse("http://localhost/some/base/url/path") + uriSingleSlash, _ := url.Parse("http://localhost/") testCases := []struct { Request *Request ExpectedFullURL string @@ -485,6 +486,38 @@ func TestURLTemplate(t *testing.T) { ExpectedFullURL: "http://localhost/some/base/url/path/pre1/namespaces/namespaces/namespaces/namespaces/namespaces/namespaces/finalize", ExpectedFinalURL: "http://localhost/%7Bprefix%7D", }, + { + // dynamic client with core group + namespace + resourceResource (with name) where baseURL is a single / + // /api/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME + Request: NewRequestWithClient(uriSingleSlash, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE"). + Prefix("/api/v1/namespaces/ns/r2/name1"), + ExpectedFullURL: "http://localhost/api/v1/namespaces/ns/r2/name1", + ExpectedFinalURL: "http://localhost/api/v1/namespaces/%7Bnamespace%7D/r2/%7Bname%7D", + }, + { + // dynamic client with core group + namespace + resourceResource (with name) where baseURL is 'some/base/url/path' + // /api/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME + Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE"). + Prefix("/api/v1/namespaces/ns/r3/name1"), + ExpectedFullURL: "http://localhost/some/base/url/path/api/v1/namespaces/ns/r3/name1", + ExpectedFinalURL: "http://localhost/some/base/url/path/api/v1/namespaces/%7Bnamespace%7D/r3/%7Bname%7D", + }, + { + // dynamic client where baseURL is a single / + // / + Request: NewRequestWithClient(uriSingleSlash, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE"). + Prefix("/"), + ExpectedFullURL: "http://localhost/", + ExpectedFinalURL: "http://localhost/", + }, + { + // dynamic client where baseURL is a single / + // /version + Request: NewRequestWithClient(uriSingleSlash, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE"). + Prefix("/version"), + ExpectedFullURL: "http://localhost/version", + ExpectedFinalURL: "http://localhost/version", + }, } for i, testCase := range testCases { r := testCase.Request