diff --git a/go.mod b/go.mod index 846513924..2d97530f9 100644 --- a/go.mod +++ b/go.mod @@ -44,7 +44,7 @@ require ( gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/square/go-jose.v2 v2.2.2 k8s.io/api v0.0.0-20220104023900-7289fed567b9 - k8s.io/apimachinery v0.0.0-20220104211627-ea11419e6b79 + k8s.io/apimachinery v0.0.0-20220105211620-b76ef24635f1 k8s.io/client-go v0.0.0-20220105172055-255c79651356 k8s.io/component-base v0.0.0-20220104212607-e7b8df8cf100 k8s.io/klog/v2 v2.40.1 @@ -58,7 +58,7 @@ require ( replace ( k8s.io/api => k8s.io/api v0.0.0-20220104023900-7289fed567b9 - k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20220104211627-ea11419e6b79 + k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20220105211620-b76ef24635f1 k8s.io/client-go => k8s.io/client-go v0.0.0-20220105172055-255c79651356 k8s.io/component-base => k8s.io/component-base v0.0.0-20220104212607-e7b8df8cf100 ) diff --git a/go.sum b/go.sum index e9b205ac4..7cda9ff6f 100644 --- a/go.sum +++ b/go.sum @@ -953,8 +953,8 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.0.0-20220104023900-7289fed567b9 h1:HghyPmUKTDSohvaoMdU8NmSTLV3GMrwWfUjJX33U7aE= k8s.io/api v0.0.0-20220104023900-7289fed567b9/go.mod h1:nKerto6bPj5aBqqPdGEHYEtwdsvWd6LAIUE0QPgQzoE= -k8s.io/apimachinery v0.0.0-20220104211627-ea11419e6b79 h1:vLDmYX/AUxrvjZE7baCJ4xdUMMM2R4hFAOiOTBtNjrk= -k8s.io/apimachinery v0.0.0-20220104211627-ea11419e6b79/go.mod h1:vcZg0n5bcYADuuKUza0y2en2OCM/UIxFaAI7N0cN6Ik= +k8s.io/apimachinery v0.0.0-20220105211620-b76ef24635f1 h1:JN5l8vsJbanXY+UEBvVC2AUaIHfPL64YTlrLGviEBE8= +k8s.io/apimachinery v0.0.0-20220105211620-b76ef24635f1/go.mod h1:vcZg0n5bcYADuuKUza0y2en2OCM/UIxFaAI7N0cN6Ik= k8s.io/client-go v0.0.0-20220105172055-255c79651356 h1:uNiuxb+Z7sPRSIWJiR20WrwpvSmMT5RMkBaxCdaLS2k= k8s.io/client-go v0.0.0-20220105172055-255c79651356/go.mod h1:8wJ34MBqSNCHmQ1mGLLHqI68ERylfM0lr3UK2WQOShk= k8s.io/component-base v0.0.0-20220104212607-e7b8df8cf100 h1:MtcO/Ysm2eaDif2wEngbGDI72FIHId/80y+x0koGLrg= diff --git a/pkg/endpoints/metrics/metrics.go b/pkg/endpoints/metrics/metrics.go index 7dd40a373..445dfb1c2 100644 --- a/pkg/endpoints/metrics/metrics.go +++ b/pkg/endpoints/metrics/metrics.go @@ -562,7 +562,7 @@ func CanonicalVerb(verb string, scope string) string { // LIST and APPLY from PATCH. func CleanVerb(verb string, request *http.Request) string { reportedVerb := verb - if verb == "LIST" && checkIfWatch(request) { + if suggestedVerb := getVerbIfWatch(request); suggestedVerb == "WATCH" { reportedVerb = "WATCH" } // normalize the legacy WATCHLIST to WATCH to ensure users aren't surprised by metrics @@ -593,27 +593,19 @@ func cleanVerb(verb, suggestedVerb string, request *http.Request) string { return OtherRequestMethod } -//getVerbIfWatch additionally ensures that GET or List would be transformed to WATCH +// getVerbIfWatch additionally ensures that GET or List would be transformed to WATCH func getVerbIfWatch(req *http.Request) string { if strings.ToUpper(req.Method) == "GET" || strings.ToUpper(req.Method) == "LIST" { - if checkIfWatch(req) { - return "WATCH" + // see apimachinery/pkg/runtime/conversion.go Convert_Slice_string_To_bool + if values := req.URL.Query()["watch"]; len(values) > 0 { + if value := strings.ToLower(values[0]); value != "0" && value != "false" { + return "WATCH" + } } } return "" } -//checkIfWatch check request is watch -func checkIfWatch(req *http.Request) bool { - // see apimachinery/pkg/runtime/conversion.go Convert_Slice_string_To_bool - if values := req.URL.Query()["watch"]; len(values) > 0 { - if value := strings.ToLower(values[0]); value != "0" && value != "false" { - return true - } - } - return false -} - func cleanDryRun(u *url.URL) string { // avoid allocating when we don't see dryRun in the query if !strings.Contains(u.RawQuery, "dryRun") { diff --git a/pkg/endpoints/metrics/metrics_test.go b/pkg/endpoints/metrics/metrics_test.go index a1fa6ba95..5da5a8500 100644 --- a/pkg/endpoints/metrics/metrics_test.go +++ b/pkg/endpoints/metrics/metrics_test.go @@ -49,6 +49,7 @@ func TestCleanVerb(t *testing.T) { desc: "LIST should be transformed to WATCH if we have the right query param on the request", initialVerb: "LIST", request: &http.Request{ + Method: "GET", URL: &url.URL{ RawQuery: "watch=true", }, @@ -59,6 +60,7 @@ func TestCleanVerb(t *testing.T) { desc: "LIST isn't transformed to WATCH if we have query params that do not include watch", initialVerb: "LIST", request: &http.Request{ + Method: "GET", URL: &url.URL{ RawQuery: "blah=asdf&something=else", }, @@ -66,20 +68,25 @@ func TestCleanVerb(t *testing.T) { expectedVerb: "LIST", }, { - desc: "GET isn't be transformed to WATCH if we have the right query param on the request", + // The above may seem counter-intuitive, but it actually is needed for cases like + // watching a single item, e.g.: + // /api/v1/namespaces/foo/pods/bar?fieldSelector=metadata.name=baz&watch=true + desc: "GET is transformed to WATCH if we have the right query param on the request", initialVerb: "GET", request: &http.Request{ + Method: "GET", URL: &url.URL{ RawQuery: "watch=true", }, }, - expectedVerb: "GET", + expectedVerb: "WATCH", }, { desc: "LIST is transformed to WATCH for the old pattern watch", initialVerb: "LIST", suggestedVerb: "WATCH", request: &http.Request{ + Method: "GET", URL: &url.URL{ RawQuery: "/api/v1/watch/pods", }, @@ -91,6 +98,7 @@ func TestCleanVerb(t *testing.T) { initialVerb: "LIST", suggestedVerb: "WATCHLIST", request: &http.Request{ + Method: "GET", URL: &url.URL{ RawQuery: "/api/v1/watch/pods", },