diff --git a/pkg/registry/apis/alerting/notifications/register.go b/pkg/registry/apis/alerting/notifications/register.go index 3b26328d684..0fd8c19da4d 100644 --- a/pkg/registry/apis/alerting/notifications/register.go +++ b/pkg/registry/apis/alerting/notifications/register.go @@ -108,10 +108,6 @@ func (t *NotificationsAPIBuilder) GetOpenAPIDefinitions() common.GetOpenAPIDefin return notificationsModels.GetOpenAPIDefinitions } -func (t *NotificationsAPIBuilder) GetAPIRoutes() *builder.APIRoutes { - return nil -} - // PostProcessOpenAPI is a hook to alter OpenAPI3 specification of the API server. func (t *NotificationsAPIBuilder) PostProcessOpenAPI(oas *spec3.OpenAPI) (*spec3.OpenAPI, error) { // The plugin description diff --git a/pkg/registry/apis/dashboard/register.go b/pkg/registry/apis/dashboard/register.go index 15a5b3ed40c..202273d64e5 100644 --- a/pkg/registry/apis/dashboard/register.go +++ b/pkg/registry/apis/dashboard/register.go @@ -74,7 +74,3 @@ func (b *DashboardsAPIBuilder) GetOpenAPIDefinitions() common.GetOpenAPIDefiniti func (b *DashboardsAPIBuilder) PostProcessOpenAPI(oas *spec3.OpenAPI) (*spec3.OpenAPI, error) { return oas, nil } - -func (b *DashboardsAPIBuilder) GetAPIRoutes() *builder.APIRoutes { - return nil // no custom API routes -} diff --git a/pkg/registry/apis/dashboard/v1alpha1/register.go b/pkg/registry/apis/dashboard/v1alpha1/register.go index d2acd73ff86..24f020cf962 100644 --- a/pkg/registry/apis/dashboard/v1alpha1/register.go +++ b/pkg/registry/apis/dashboard/v1alpha1/register.go @@ -197,7 +197,3 @@ func (b *DashboardsAPIBuilder) PostProcessOpenAPI(oas *spec3.OpenAPI) (*spec3.Op } return oas, nil } - -func (b *DashboardsAPIBuilder) GetAPIRoutes() *builder.APIRoutes { - return nil // no custom API routes -} diff --git a/pkg/registry/apis/dashboard/v2alpha1/register.go b/pkg/registry/apis/dashboard/v2alpha1/register.go index eb5c5e4541a..aba5b8c4e9d 100644 --- a/pkg/registry/apis/dashboard/v2alpha1/register.go +++ b/pkg/registry/apis/dashboard/v2alpha1/register.go @@ -197,7 +197,3 @@ func (b *DashboardsAPIBuilder) PostProcessOpenAPI(oas *spec3.OpenAPI) (*spec3.Op } return oas, nil } - -func (b *DashboardsAPIBuilder) GetAPIRoutes() *builder.APIRoutes { - return nil // no custom API routes -} diff --git a/pkg/registry/apis/datasource/register.go b/pkg/registry/apis/datasource/register.go index bac6da1f8d9..67aafa8cb14 100644 --- a/pkg/registry/apis/datasource/register.go +++ b/pkg/registry/apis/datasource/register.go @@ -281,8 +281,3 @@ func (b *DataSourceAPIBuilder) PostProcessOpenAPI(oas *spec3.OpenAPI) (*spec3.Op } return oas, err } - -// Register additional routes with the server -func (b *DataSourceAPIBuilder) GetAPIRoutes() *builder.APIRoutes { - return nil -} diff --git a/pkg/registry/apis/folders/register.go b/pkg/registry/apis/folders/register.go index b1fe170b3d1..8ade6030cf7 100644 --- a/pkg/registry/apis/folders/register.go +++ b/pkg/registry/apis/folders/register.go @@ -146,10 +146,6 @@ func (b *FolderAPIBuilder) GetOpenAPIDefinitions() common.GetOpenAPIDefinitions return v0alpha1.GetOpenAPIDefinitions } -func (b *FolderAPIBuilder) GetAPIRoutes() *builder.APIRoutes { - return nil // no custom API routes -} - func (b *FolderAPIBuilder) PostProcessOpenAPI(oas *spec3.OpenAPI) (*spec3.OpenAPI, error) { // The plugin description oas.Info.Description = "Grafana folders" diff --git a/pkg/registry/apis/iam/register.go b/pkg/registry/apis/iam/register.go index cdc67eff0fd..70bd96c86f0 100644 --- a/pkg/registry/apis/iam/register.go +++ b/pkg/registry/apis/iam/register.go @@ -125,11 +125,6 @@ func (b *IdentityAccessManagementAPIBuilder) GetOpenAPIDefinitions() common.GetO return iamv0.GetOpenAPIDefinitions } -func (b *IdentityAccessManagementAPIBuilder) GetAPIRoutes() *builder.APIRoutes { - // no custom API routes - return nil -} - func (b *IdentityAccessManagementAPIBuilder) GetAuthorizer() authorizer.Authorizer { return b.authorizer } diff --git a/pkg/registry/apis/query/register.go b/pkg/registry/apis/query/register.go index fdbcb9c119b..61499f78f03 100644 --- a/pkg/registry/apis/query/register.go +++ b/pkg/registry/apis/query/register.go @@ -165,11 +165,6 @@ func (b *QueryAPIBuilder) GetOpenAPIDefinitions() common.GetOpenAPIDefinitions { return query.GetOpenAPIDefinitions } -// Register additional routes with the server -func (b *QueryAPIBuilder) GetAPIRoutes() *builder.APIRoutes { - return nil -} - func (b *QueryAPIBuilder) GetAuthorizer() authorizer.Authorizer { return nil // default is OK } diff --git a/pkg/registry/apis/scope/register.go b/pkg/registry/apis/scope/register.go index 733f966aebf..e413a6c7d47 100644 --- a/pkg/registry/apis/scope/register.go +++ b/pkg/registry/apis/scope/register.go @@ -157,11 +157,6 @@ func (b *ScopeAPIBuilder) GetOpenAPIDefinitions() common.GetOpenAPIDefinitions { return scope.GetOpenAPIDefinitions } -// Register additional routes with the server -func (b *ScopeAPIBuilder) GetAPIRoutes() *builder.APIRoutes { - return nil -} - func (b *ScopeAPIBuilder) PostProcessOpenAPI(oas *spec3.OpenAPI) (*spec3.OpenAPI, error) { // The plugin description oas.Info.Description = "Grafana scopes" diff --git a/pkg/registry/apis/service/register.go b/pkg/registry/apis/service/register.go index 24827a36ace..b98c8835fef 100644 --- a/pkg/registry/apis/service/register.go +++ b/pkg/registry/apis/service/register.go @@ -88,8 +88,3 @@ func (b *ServiceAPIBuilder) UpdateAPIGroupInfo(apiGroupInfo *genericapiserver.AP func (b *ServiceAPIBuilder) GetOpenAPIDefinitions() common.GetOpenAPIDefinitions { return service.GetOpenAPIDefinitions } - -// Register additional routes with the server -func (b *ServiceAPIBuilder) GetAPIRoutes() *builder.APIRoutes { - return nil -} diff --git a/pkg/registry/apis/userstorage/register.go b/pkg/registry/apis/userstorage/register.go index f96f258d4ea..b9e01681649 100644 --- a/pkg/registry/apis/userstorage/register.go +++ b/pkg/registry/apis/userstorage/register.go @@ -3,6 +3,7 @@ package userstorage import ( "context" + "github.com/prometheus/client_golang/prometheus" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -13,8 +14,6 @@ import ( "github.com/grafana/grafana/pkg/apimachinery/identity" userstorage "github.com/grafana/grafana/pkg/apis/userstorage/v0alpha1" - "github.com/prometheus/client_golang/prometheus" - "github.com/grafana/grafana/pkg/services/apiserver/builder" "github.com/grafana/grafana/pkg/services/featuremgmt" ) @@ -78,10 +77,6 @@ func (b *UserStorageAPIBuilder) GetOpenAPIDefinitions() common.GetOpenAPIDefinit return userstorage.GetOpenAPIDefinitions } -func (b *UserStorageAPIBuilder) GetAPIRoutes() *builder.APIRoutes { - return nil -} - func (b *UserStorageAPIBuilder) GetAuthorizer() authorizer.Authorizer { return authorizer.AuthorizerFunc( func(ctx context.Context, attr authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) { diff --git a/pkg/services/apiserver/builder/common.go b/pkg/services/apiserver/builder/common.go index 6d70c6c3b3e..4dfff1abc2d 100644 --- a/pkg/services/apiserver/builder/common.go +++ b/pkg/services/apiserver/builder/common.go @@ -39,9 +39,6 @@ type APIGroupBuilder interface { // Get OpenAPI definitions GetOpenAPIDefinitions() common.GetOpenAPIDefinitions - // Get the API routes for each version - GetAPIRoutes() *APIRoutes - // Optionally add an authorization hook // Standard namespace checking will happen before this is called, specifically // the namespace must matches an org|stack that the user belongs to @@ -60,6 +57,11 @@ type APIGroupValidation interface { Validate(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) (err error) } +type APIGroupRouteProvider interface { + // Support direct HTTP routes from an APIGroup + GetAPIRoutes() *APIRoutes +} + type APIGroupOptions struct { Scheme *runtime.Scheme OptsGetter generic.RESTOptionsGetter diff --git a/pkg/services/apiserver/builder/openapi.go b/pkg/services/apiserver/builder/openapi.go index 98bd88fca7c..0830af9838c 100644 --- a/pkg/services/apiserver/builder/openapi.go +++ b/pkg/services/apiserver/builder/openapi.go @@ -4,11 +4,11 @@ import ( "maps" "strings" - data "github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1" common "k8s.io/kube-openapi/pkg/common" "k8s.io/kube-openapi/pkg/spec3" spec "k8s.io/kube-openapi/pkg/validation/spec" + data "github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1" ) @@ -48,7 +48,6 @@ func getOpenAPIPostProcessor(version string, builders []APIGroupBuilder) func(*s return s, nil } for _, b := range builders { - routes := b.GetAPIRoutes() gv := b.GetGroupVersion() prefix := "/apis/" + gv.String() + "/" if s.Paths.Paths[prefix] != nil { @@ -66,19 +65,22 @@ func getOpenAPIPostProcessor(version string, builders []APIGroupBuilder) func(*s Paths: s.Paths, } - if routes == nil { - routes = &APIRoutes{} - } - - for _, route := range routes.Root { - copy.Paths.Paths[prefix+route.Path] = &spec3.Path{ - PathProps: *route.Spec, - } - } + // Optionally include raw http handlers + provider, ok := b.(APIGroupRouteProvider) + if ok && provider != nil { + routes := provider.GetAPIRoutes() + if routes != nil { + for _, route := range routes.Root { + copy.Paths.Paths[prefix+route.Path] = &spec3.Path{ + PathProps: *route.Spec, + } + } - for _, route := range routes.Namespace { - copy.Paths.Paths[prefix+"namespaces/{namespace}/"+route.Path] = &spec3.Path{ - PathProps: *route.Spec, + for _, route := range routes.Namespace { + copy.Paths.Paths[prefix+"namespaces/{namespace}/"+route.Path] = &spec3.Path{ + PathProps: *route.Spec, + } + } } } diff --git a/pkg/services/apiserver/builder/request_handler.go b/pkg/services/apiserver/builder/request_handler.go index 41e5e3e7e0d..42f84155159 100644 --- a/pkg/services/apiserver/builder/request_handler.go +++ b/pkg/services/apiserver/builder/request_handler.go @@ -18,7 +18,12 @@ func GetCustomRoutesHandler(delegateHandler http.Handler, restConfig *restclient router := mux.NewRouter() for _, builder := range builders { - routes := builder.GetAPIRoutes() + provider, ok := builder.(APIGroupRouteProvider) + if !ok || provider == nil { + continue + } + + routes := provider.GetAPIRoutes() if routes == nil { continue } diff --git a/pkg/services/apiserver/builder/runner/builder.go b/pkg/services/apiserver/builder/runner/builder.go index c58401e9e2c..1bc052fb46e 100644 --- a/pkg/services/apiserver/builder/runner/builder.go +++ b/pkg/services/apiserver/builder/runner/builder.go @@ -1,8 +1,6 @@ package runner import ( - "github.com/grafana/grafana-app-sdk/app" - "github.com/grafana/grafana-app-sdk/resource" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/authorization/authorizer" @@ -10,6 +8,8 @@ import ( genericapiserver "k8s.io/apiserver/pkg/server" "k8s.io/kube-openapi/pkg/common" + "github.com/grafana/grafana-app-sdk/app" + "github.com/grafana/grafana-app-sdk/resource" "github.com/grafana/grafana/pkg/apimachinery/utils" grafanaregistry "github.com/grafana/grafana/pkg/apiserver/registry/generic" grafanarest "github.com/grafana/grafana/pkg/apiserver/rest" @@ -116,12 +116,6 @@ func (b *appBuilder) GetOpenAPIDefinitions() common.GetOpenAPIDefinitions { return b.config.OpenAPIDefGetter } -// GetAPIRoutes implements APIGroupBuilder.GetAPIRoutes -func (b *appBuilder) GetAPIRoutes() *builder.APIRoutes { - // TODO: The API routes are not yet exposed by the app.App interface. - return nil -} - // GetAuthorizer implements APIGroupBuilder.GetAuthorizer func (b *appBuilder) GetAuthorizer() authorizer.Authorizer { return b.config.Authorizer