mirror of
https://github.com/grafana/grafana.git
synced 2025-07-29 05:42:28 +08:00
146 lines
5.4 KiB
Go
146 lines
5.4 KiB
Go
package builder
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
"k8s.io/apiserver/pkg/admission"
|
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
|
"k8s.io/apiserver/pkg/registry/generic"
|
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
|
"k8s.io/kube-openapi/pkg/common"
|
|
"k8s.io/kube-openapi/pkg/spec3"
|
|
|
|
grafanarest "github.com/grafana/grafana/pkg/apiserver/rest"
|
|
"github.com/grafana/grafana/pkg/services/apiserver/options"
|
|
"github.com/grafana/grafana/pkg/storage/unified/apistore"
|
|
)
|
|
|
|
// TODO: this (or something like it) belongs in grafana-app-sdk,
|
|
// but lets keep it here while we iterate on a few simple examples
|
|
type APIGroupBuilder interface {
|
|
// Add the kinds to the server scheme
|
|
InstallSchema(scheme *runtime.Scheme) error
|
|
|
|
// UpdateAPIGroupInfo used to be a getter until we ran into the issue
|
|
// where separate API Group Info for the same group (different versions) aren't handled well by
|
|
// the InstallAPIGroup facility of genericapiserver. Also, we can only ever call InstallAPIGroup
|
|
// once on the genericapiserver per group, or we run into double registration startup errors.
|
|
//
|
|
// The caller should share the apiGroupInfo passed into this function across builder versions of the same group.
|
|
// UpdateAPIGroupInfo builds the group+version behavior updating the passed in apiGroupInfo in place
|
|
UpdateAPIGroupInfo(apiGroupInfo *genericapiserver.APIGroupInfo, opts APIGroupOptions) error
|
|
|
|
// Get OpenAPI definitions
|
|
GetOpenAPIDefinitions() common.GetOpenAPIDefinitions
|
|
|
|
// Do not return anything unless you have special circumstances! This is a list of resources that are allowed to be accessed in v0alpha1, with AllResourcesAllowed allowing all in the group.
|
|
// This is to prevent accidental exposure of experimental APIs. While developing, use the feature flag `grafanaAPIServerWithExperimentalAPIs`.
|
|
// And then, when you're ready to expose this to the end user, go to v1beta1 instead.
|
|
AllowedV0Alpha1Resources() []string
|
|
}
|
|
|
|
const AllResourcesAllowed = "*"
|
|
|
|
type APIGroupVersionProvider interface {
|
|
GetGroupVersion() schema.GroupVersion
|
|
}
|
|
|
|
type APIGroupVersionsProvider interface {
|
|
GetGroupVersions() []schema.GroupVersion
|
|
}
|
|
|
|
type APIGroupAuthorizer interface {
|
|
GetAuthorizer() authorizer.Authorizer
|
|
}
|
|
|
|
type APIGroupMutation interface {
|
|
// Mutate allows the builder to make changes to the object before it is persisted.
|
|
// Context is used only for timeout/deadline/cancellation and tracing information.
|
|
Mutate(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) (err error)
|
|
}
|
|
|
|
type APIGroupValidation interface {
|
|
// Validate makes an admission decision based on the request attributes. It is NOT allowed to mutate
|
|
// Context is used only for timeout/deadline/cancellation and tracing information.
|
|
Validate(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) (err error)
|
|
}
|
|
|
|
type APIGroupRouteProvider interface {
|
|
// Support direct HTTP routes from an APIGroup
|
|
GetAPIRoutes(gv schema.GroupVersion) *APIRoutes
|
|
}
|
|
|
|
type APIGroupPostStartHookProvider interface {
|
|
// GetPostStartHooks returns a list of functions that will be called after the server has started
|
|
GetPostStartHooks() (map[string]genericapiserver.PostStartHookFunc, error)
|
|
}
|
|
|
|
type APIGroupOptions struct {
|
|
Scheme *runtime.Scheme
|
|
OptsGetter generic.RESTOptionsGetter
|
|
DualWriteBuilder grafanarest.DualWriteBuilder
|
|
MetricsRegister prometheus.Registerer
|
|
StorageOptsRegister apistore.StorageOptionsRegister
|
|
StorageOpts *options.StorageOptions
|
|
}
|
|
|
|
// Builders that implement OpenAPIPostProcessor are given a chance to modify the schema directly
|
|
type OpenAPIPostProcessor interface {
|
|
PostProcessOpenAPI(*spec3.OpenAPI) (*spec3.OpenAPI, error)
|
|
}
|
|
|
|
// This is used to implement dynamic sub-resources like pods/x/logs
|
|
type APIRouteHandler struct {
|
|
Path string // added to the appropriate level
|
|
Spec *spec3.PathProps // Exposed in the open api service discovery
|
|
Handler http.HandlerFunc // when Level = resource, the resource will be available in context
|
|
}
|
|
|
|
// APIRoutes define explicit HTTP handlers in an apiserver
|
|
// TBD: is this actually necessary -- there may be more k8s native options for this
|
|
type APIRoutes struct {
|
|
// Root handlers are registered directly after the apiVersion identifier
|
|
Root []APIRouteHandler
|
|
|
|
// Namespace handlers are mounted under the namespace
|
|
Namespace []APIRouteHandler
|
|
}
|
|
|
|
type APIRegistrar interface {
|
|
RegisterAPI(builder APIGroupBuilder)
|
|
}
|
|
|
|
func getGroup(builder APIGroupBuilder) (string, error) {
|
|
if v, ok := builder.(APIGroupVersionProvider); ok {
|
|
return v.GetGroupVersion().Group, nil
|
|
}
|
|
|
|
if v, ok := builder.(APIGroupVersionsProvider); ok {
|
|
if len(v.GetGroupVersions()) == 0 {
|
|
return "", fmt.Errorf("unable to get group: builder returned no versions")
|
|
}
|
|
|
|
return v.GetGroupVersions()[0].Group, nil
|
|
}
|
|
|
|
return "", fmt.Errorf("unable to get group: builder does not implement APIGroupVersionProvider or APIGroupVersionsProvider")
|
|
}
|
|
|
|
func GetGroupVersions(builder APIGroupBuilder) []schema.GroupVersion {
|
|
if v, ok := builder.(APIGroupVersionProvider); ok {
|
|
return []schema.GroupVersion{v.GetGroupVersion()}
|
|
}
|
|
|
|
if v, ok := builder.(APIGroupVersionsProvider); ok {
|
|
return v.GetGroupVersions()
|
|
}
|
|
|
|
// this should never happen
|
|
panic("builder does not implement APIGroupVersionProvider or APIGroupVersionsProvider")
|
|
}
|