From 139025af1e655af7fb3adecc0e1bb3cc475cadf7 Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Fri, 15 Dec 2023 07:53:35 -0800 Subject: [PATCH] K8s: Update OpenAPI post processing structures (#79553) * add prefix * update extra paths --- pkg/registry/apis/example/register.go | 6 +-- .../grafana-apiserver/request_handler.go | 54 ++++++++----------- pkg/services/grafana-apiserver/service.go | 2 +- 3 files changed, 27 insertions(+), 35 deletions(-) diff --git a/pkg/registry/apis/example/register.go b/pkg/registry/apis/example/register.go index 4d2a97e6ab2..298084b33d9 100644 --- a/pkg/registry/apis/example/register.go +++ b/pkg/registry/apis/example/register.go @@ -103,7 +103,7 @@ func (b *TestingAPIBuilder) GetAPIRoutes() *grafanaapiserver.APIRoutes { return &grafanaapiserver.APIRoutes{ Root: []grafanaapiserver.APIRouteHandler{ { - Path: "/aaa", + Path: "aaa", Spec: &spec3.PathProps{ Summary: "an example at the root level", Description: "longer description here?", @@ -144,7 +144,7 @@ func (b *TestingAPIBuilder) GetAPIRoutes() *grafanaapiserver.APIRoutes { }, }, { - Path: "/bbb", + Path: "bbb", Spec: &spec3.PathProps{ Summary: "an example at the root level", Description: "longer description here?", @@ -165,7 +165,7 @@ func (b *TestingAPIBuilder) GetAPIRoutes() *grafanaapiserver.APIRoutes { }, Namespace: []grafanaapiserver.APIRouteHandler{ { - Path: "/ccc", + Path: "ccc", Spec: &spec3.PathProps{ Summary: "an example at the root level", Description: "longer description here?", diff --git a/pkg/services/grafana-apiserver/request_handler.go b/pkg/services/grafana-apiserver/request_handler.go index 3091c4cf6e5..9fb0e0a44ea 100644 --- a/pkg/services/grafana-apiserver/request_handler.go +++ b/pkg/services/grafana-apiserver/request_handler.go @@ -3,21 +3,22 @@ package grafanaapiserver import ( "fmt" "net/http" - "strings" "github.com/gorilla/mux" restclient "k8s.io/client-go/rest" "k8s.io/kube-openapi/pkg/spec3" + "k8s.io/kube-openapi/pkg/validation/spec" + + "github.com/grafana/grafana/pkg/setting" ) type requestHandler struct { router *mux.Router } -func getAPIHandler(delegateHandler http.Handler, restConfig *restclient.Config, builders []APIGroupBuilder) (http.Handler, error) { +func GetAPIHandler(delegateHandler http.Handler, restConfig *restclient.Config, builders []APIGroupBuilder) (http.Handler, error) { useful := false // only true if any routes exist anywhere router := mux.NewRouter() - var err error for _, builder := range builders { routes := builder.GetAPIRoutes() @@ -31,11 +32,6 @@ func getAPIHandler(delegateHandler http.Handler, restConfig *restclient.Config, // Root handlers var sub *mux.Router for _, route := range routes.Root { - err = validPath(route.Path) - if err != nil { - return nil, err - } - if sub == nil { sub = router.PathPrefix(prefix).Subrouter() sub.MethodNotAllowedHandler = &methodNotAllowedHandler{} @@ -54,10 +50,6 @@ func getAPIHandler(delegateHandler http.Handler, restConfig *restclient.Config, sub = nil prefix += "/namespaces/{namespace}" for _, route := range routes.Namespace { - err = validPath(route.Path) - if err != nil { - return nil, err - } if sub == nil { sub = router.PathPrefix(prefix).Subrouter() sub.MethodNotAllowedHandler = &methodNotAllowedHandler{} @@ -86,17 +78,6 @@ func getAPIHandler(delegateHandler http.Handler, restConfig *restclient.Config, }, nil } -// The registered path must start with a slash, and (for now) not have any more -func validPath(p string) error { - if !strings.HasPrefix(p, "/") { - return fmt.Errorf("path must start with slash") - } - if strings.Count(p, "/") > 1 { - return fmt.Errorf("path can only have one slash (for now)") - } - return nil -} - func (h *requestHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { h.router.ServeHTTP(w, req) } @@ -146,15 +127,26 @@ func GetOpenAPIPostProcessor(builders []APIGroupBuilder) func(*spec3.OpenAPI) (* } for _, builder := range builders { routes := builder.GetAPIRoutes() - if routes == nil { - continue - } - gv := builder.GetGroupVersion() - prefix := "/apis/" + gv.String() + prefix := "/apis/" + gv.String() + "/" if s.Paths.Paths[prefix] != nil { - copy := *s // will copy the rest of the properties - copy.Info.Title = "Grafana API server: " + gv.Group + copy := spec3.OpenAPI{ + Version: s.Version, + Info: &spec.Info{ + InfoProps: spec.InfoProps{ + Title: gv.String(), + Version: setting.BuildVersion, + }, + }, + Components: s.Components, + ExternalDocs: s.ExternalDocs, + Servers: s.Servers, + Paths: s.Paths, + } + + if routes == nil { + routes = &APIRoutes{} + } for _, route := range routes.Root { copy.Paths.Paths[prefix+route.Path] = &spec3.Path{ @@ -163,7 +155,7 @@ func GetOpenAPIPostProcessor(builders []APIGroupBuilder) func(*spec3.OpenAPI) (* } for _, route := range routes.Namespace { - copy.Paths.Paths[prefix+"/namespaces/{namespace}"+route.Path] = &spec3.Path{ + copy.Paths.Paths[prefix+"namespaces/{namespace}/"+route.Path] = &spec3.Path{ PathProps: *route.Spec, } } diff --git a/pkg/services/grafana-apiserver/service.go b/pkg/services/grafana-apiserver/service.go index 81e671212ee..c99ec36a6f6 100644 --- a/pkg/services/grafana-apiserver/service.go +++ b/pkg/services/grafana-apiserver/service.go @@ -339,7 +339,7 @@ func (s *service) start(ctx context.Context) error { // Call DefaultBuildHandlerChain on the main entrypoint http.Handler // See https://github.com/kubernetes/apiserver/blob/v0.28.0/pkg/server/config.go#L906 // DefaultBuildHandlerChain provides many things, notably CORS, HSTS, cache-control, authz and latency tracking - requestHandler, err := getAPIHandler( + requestHandler, err := GetAPIHandler( delegateHandler, c.LoopbackClientConfig, builders)