mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
APIServer: Move shared code to a utility/helper function (#80261)
This commit is contained in:
parent
4f832c4c69
commit
ee7daeb2a7
@ -4,11 +4,13 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/grafana/grafana/pkg/aggregator"
|
||||
"github.com/grafana/grafana/pkg/services/grafana-apiserver/utils"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/aggregator"
|
||||
grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver"
|
||||
"github.com/grafana/grafana/pkg/services/grafana-apiserver/utils"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/apiserver/pkg/server/options"
|
||||
@ -56,7 +58,7 @@ func newCommandStartExampleAPIServer(o *APIServerOptions, stopCh <-chan struct{}
|
||||
// Register standard k8s flags with the command line
|
||||
o.RecommendedOptions = options.NewRecommendedOptions(
|
||||
defaultEtcdPathPrefix,
|
||||
Codecs.LegacyCodec(), // the codec is passed to etcd and not used
|
||||
grafanaapiserver.Codecs.LegacyCodec(), // the codec is passed to etcd and not used
|
||||
)
|
||||
o.RecommendedOptions.AddFlags(cmd.Flags())
|
||||
|
||||
@ -111,20 +113,10 @@ func run(serverOptions *aggregator.AggregatorServerOptions) error {
|
||||
}
|
||||
|
||||
// Install the API Group+version
|
||||
for _, b := range serverOptions.Builders {
|
||||
g, err := b.GetAPIGroupInfo(Scheme, Codecs, config.GenericConfig.RESTOptionsGetter)
|
||||
if err != nil {
|
||||
klog.Errorf("Error getting group info for prerequisite API group: %s", err)
|
||||
return err
|
||||
}
|
||||
if g == nil || len(g.PrioritizedVersions) < 1 {
|
||||
continue
|
||||
}
|
||||
err = aggregator.GenericAPIServer.InstallAPIGroup(g)
|
||||
if err != nil {
|
||||
klog.Errorf("Error installing prerequisite API groups for aggregator: %s", err)
|
||||
return err
|
||||
}
|
||||
err = grafanaapiserver.InstallAPIs(aggregator.GenericAPIServer, config.GenericConfig.RESTOptionsGetter, serverOptions.Builders)
|
||||
if err != nil {
|
||||
klog.Errorf("Error installing apis: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := clientcmd.WriteToFile(
|
||||
|
@ -6,22 +6,15 @@ import (
|
||||
"net"
|
||||
"path"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/apiserver/pkg/server/options"
|
||||
"k8s.io/apiserver/pkg/util/openapi"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
netutils "k8s.io/utils/net"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/grafana-apiserver/utils"
|
||||
|
||||
"github.com/grafana/grafana/pkg/registry/apis/example"
|
||||
grafanaAPIServer "github.com/grafana/grafana/pkg/services/grafana-apiserver"
|
||||
"github.com/grafana/grafana/pkg/services/grafana-apiserver/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -29,26 +22,6 @@ const (
|
||||
dataPath = "data/grafana-apiserver" // same as grafana core
|
||||
)
|
||||
|
||||
var (
|
||||
Scheme = runtime.NewScheme()
|
||||
Codecs = serializer.NewCodecFactory(Scheme)
|
||||
)
|
||||
|
||||
func init() {
|
||||
unversionedVersion := schema.GroupVersion{Group: "", Version: "v1"}
|
||||
unversionedTypes := []runtime.Object{
|
||||
&metav1.Status{},
|
||||
&metav1.WatchEvent{},
|
||||
&metav1.APIVersions{},
|
||||
&metav1.APIGroupList{},
|
||||
&metav1.APIGroup{},
|
||||
&metav1.APIResourceList{},
|
||||
}
|
||||
// we need to add the options to empty v1
|
||||
metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Group: "", Version: "v1"})
|
||||
Scheme.AddUnversionedTypes(unversionedVersion, unversionedTypes...)
|
||||
}
|
||||
|
||||
// APIServerOptions contains the state for the apiserver
|
||||
type APIServerOptions struct {
|
||||
builders []grafanaAPIServer.APIGroupBuilder
|
||||
@ -84,7 +57,7 @@ func (o *APIServerOptions) LoadAPIGroupBuilders(args []string) error {
|
||||
|
||||
// Install schemas
|
||||
for _, b := range o.builders {
|
||||
if err := b.InstallSchema(Scheme); err != nil {
|
||||
if err := b.InstallSchema(grafanaAPIServer.Scheme); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -160,7 +133,7 @@ func (o *APIServerOptions) Config() (*genericapiserver.RecommendedConfig, error)
|
||||
o.RecommendedOptions.CoreAPI = nil
|
||||
}
|
||||
|
||||
serverConfig := genericapiserver.NewRecommendedConfig(Codecs)
|
||||
serverConfig := genericapiserver.NewRecommendedConfig(grafanaAPIServer.Codecs)
|
||||
|
||||
if o.RecommendedOptions.CoreAPI == nil {
|
||||
if err := o.ModifiedApplyTo(serverConfig); err != nil {
|
||||
@ -176,16 +149,8 @@ func (o *APIServerOptions) Config() (*genericapiserver.RecommendedConfig, error)
|
||||
serverConfig.DisabledPostStartHooks = serverConfig.DisabledPostStartHooks.Insert("priority-and-fairness-config-consumer")
|
||||
|
||||
// Add OpenAPI specs for each group+version
|
||||
defsGetter := grafanaAPIServer.GetOpenAPIDefinitions(o.builders)
|
||||
serverConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(
|
||||
openapi.GetOpenAPIDefinitionsWithoutDisabledFeatures(defsGetter),
|
||||
openapinamer.NewDefinitionNamer(Scheme))
|
||||
|
||||
serverConfig.OpenAPIV3Config = genericapiserver.DefaultOpenAPIV3Config(
|
||||
openapi.GetOpenAPIDefinitionsWithoutDisabledFeatures(defsGetter),
|
||||
openapinamer.NewDefinitionNamer(Scheme))
|
||||
|
||||
return serverConfig, nil
|
||||
err := grafanaAPIServer.SetupConfig(serverConfig, o.builders)
|
||||
return serverConfig, err
|
||||
}
|
||||
|
||||
// Validate validates APIServerOptions
|
||||
@ -212,18 +177,9 @@ func (o *APIServerOptions) RunAPIServer(config *genericapiserver.RecommendedConf
|
||||
}
|
||||
|
||||
// Install the API Group+version
|
||||
for _, b := range o.builders {
|
||||
g, err := b.GetAPIGroupInfo(Scheme, Codecs, completedConfig.RESTOptionsGetter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if g == nil || len(g.PrioritizedVersions) < 1 {
|
||||
continue
|
||||
}
|
||||
err = server.InstallAPIGroup(g)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = grafanaAPIServer.InstallAPIs(server, config.RESTOptionsGetter, o.builders)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// write the local config to disk
|
||||
|
@ -25,7 +25,7 @@ type APIGroupBuilder interface {
|
||||
// Build the group+version behavior
|
||||
GetAPIGroupInfo(
|
||||
scheme *runtime.Scheme,
|
||||
codecs serializer.CodecFactory, // pointer?
|
||||
codecs serializer.CodecFactory,
|
||||
optsGetter generic.RESTOptionsGetter,
|
||||
) (*genericapiserver.APIGroupInfo, error)
|
||||
|
||||
|
89
pkg/services/grafana-apiserver/helper.go
Normal file
89
pkg/services/grafana-apiserver/helper.go
Normal file
@ -0,0 +1,89 @@
|
||||
package grafanaapiserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
goruntime "runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/apiserver/pkg/util/openapi"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func SetupConfig(serverConfig *genericapiserver.RecommendedConfig, builders []APIGroupBuilder) error {
|
||||
defsGetter := GetOpenAPIDefinitions(builders)
|
||||
serverConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(
|
||||
openapi.GetOpenAPIDefinitionsWithoutDisabledFeatures(defsGetter),
|
||||
openapinamer.NewDefinitionNamer(Scheme, scheme.Scheme))
|
||||
|
||||
serverConfig.OpenAPIV3Config = genericapiserver.DefaultOpenAPIV3Config(
|
||||
openapi.GetOpenAPIDefinitionsWithoutDisabledFeatures(defsGetter),
|
||||
openapinamer.NewDefinitionNamer(Scheme, scheme.Scheme))
|
||||
|
||||
// Add the custom routes to service discovery
|
||||
serverConfig.OpenAPIV3Config.PostProcessSpec = getOpenAPIPostProcessor(builders)
|
||||
|
||||
// Set the swagger build versions
|
||||
serverConfig.OpenAPIConfig.Info.Version = setting.BuildVersion
|
||||
serverConfig.OpenAPIV3Config.Info.Version = setting.BuildVersion
|
||||
|
||||
serverConfig.SkipOpenAPIInstallation = false
|
||||
serverConfig.BuildHandlerChainFunc = func(delegateHandler http.Handler, c *genericapiserver.Config) http.Handler {
|
||||
// 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(
|
||||
delegateHandler,
|
||||
c.LoopbackClientConfig,
|
||||
builders)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("could not build handler chain func: %s", err.Error()))
|
||||
}
|
||||
return genericapiserver.DefaultBuildHandlerChain(requestHandler, c)
|
||||
}
|
||||
|
||||
k8sVersion, err := getK8sApiserverVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
before, after, _ := strings.Cut(setting.BuildVersion, ".")
|
||||
serverConfig.Version = &version.Info{
|
||||
Major: before,
|
||||
Minor: after,
|
||||
GoVersion: goruntime.Version(),
|
||||
Platform: fmt.Sprintf("%s/%s", goruntime.GOOS, goruntime.GOARCH),
|
||||
Compiler: goruntime.Compiler,
|
||||
GitTreeState: setting.BuildBranch,
|
||||
GitCommit: setting.BuildCommit,
|
||||
BuildDate: time.Unix(setting.BuildStamp, 0).UTC().Format(time.DateTime),
|
||||
GitVersion: k8sVersion,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func InstallAPIs(server *genericapiserver.GenericAPIServer,
|
||||
optsGetter generic.RESTOptionsGetter,
|
||||
builders []APIGroupBuilder,
|
||||
) error {
|
||||
for _, b := range builders {
|
||||
g, err := b.GetAPIGroupInfo(Scheme, Codecs, optsGetter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if g == nil || len(g.PrioritizedVersions) < 1 {
|
||||
continue
|
||||
}
|
||||
err = server.InstallAPIGroup(g)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
@ -16,7 +16,7 @@ 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()
|
||||
|
||||
@ -120,7 +120,7 @@ func (h *methodNotAllowedHandler) ServeHTTP(w http.ResponseWriter, req *http.Req
|
||||
// Modify the the OpenAPI spec to include the additional routes.
|
||||
// Currently this requires: https://github.com/kubernetes/kube-openapi/pull/420
|
||||
// In future k8s release, the hook will use Config3 rather than the same hook for both v2 and v3
|
||||
func GetOpenAPIPostProcessor(builders []APIGroupBuilder) func(*spec3.OpenAPI) (*spec3.OpenAPI, error) {
|
||||
func getOpenAPIPostProcessor(builders []APIGroupBuilder) func(*spec3.OpenAPI) (*spec3.OpenAPI, error) {
|
||||
return func(s *spec3.OpenAPI) (*spec3.OpenAPI, error) {
|
||||
if s.Paths == nil {
|
||||
return s, nil
|
||||
|
@ -6,11 +6,9 @@ import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path"
|
||||
goruntime "runtime"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/grafana/dskit/services"
|
||||
@ -21,13 +19,9 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
|
||||
"k8s.io/apiserver/pkg/endpoints/responsewriter"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/apiserver/pkg/server/options"
|
||||
"k8s.io/apiserver/pkg/util/openapi"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
clientrest "k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/component-base/logs"
|
||||
@ -325,53 +319,10 @@ func (s *service) start(ctx context.Context) error {
|
||||
serverConfig.TracerProvider = s.tracing.GetTracerProvider()
|
||||
|
||||
// Add OpenAPI specs for each group+version
|
||||
defsGetter := GetOpenAPIDefinitions(builders)
|
||||
serverConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(
|
||||
openapi.GetOpenAPIDefinitionsWithoutDisabledFeatures(defsGetter),
|
||||
openapinamer.NewDefinitionNamer(Scheme, scheme.Scheme))
|
||||
|
||||
serverConfig.OpenAPIV3Config = genericapiserver.DefaultOpenAPIV3Config(
|
||||
openapi.GetOpenAPIDefinitionsWithoutDisabledFeatures(defsGetter),
|
||||
openapinamer.NewDefinitionNamer(Scheme, scheme.Scheme))
|
||||
|
||||
// Add the custom routes to service discovery
|
||||
serverConfig.OpenAPIV3Config.PostProcessSpec = GetOpenAPIPostProcessor(builders)
|
||||
|
||||
// Set the swagger build versions
|
||||
serverConfig.OpenAPIConfig.Info.Version = setting.BuildVersion
|
||||
serverConfig.OpenAPIV3Config.Info.Version = setting.BuildVersion
|
||||
|
||||
serverConfig.SkipOpenAPIInstallation = false
|
||||
serverConfig.BuildHandlerChainFunc = func(delegateHandler http.Handler, c *genericapiserver.Config) http.Handler {
|
||||
// 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(
|
||||
delegateHandler,
|
||||
c.LoopbackClientConfig,
|
||||
builders)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("could not build handler chain func: %s", err.Error()))
|
||||
}
|
||||
return genericapiserver.DefaultBuildHandlerChain(requestHandler, c)
|
||||
}
|
||||
|
||||
k8sVersion, err := getK8sApiserverVersion()
|
||||
err := SetupConfig(serverConfig, builders)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
before, after, _ := strings.Cut(setting.BuildVersion, ".")
|
||||
serverConfig.Version = &version.Info{
|
||||
Major: before,
|
||||
Minor: after,
|
||||
GoVersion: goruntime.Version(),
|
||||
Platform: fmt.Sprintf("%s/%s", goruntime.GOOS, goruntime.GOARCH),
|
||||
Compiler: goruntime.Compiler,
|
||||
GitTreeState: setting.BuildBranch,
|
||||
GitCommit: setting.BuildCommit,
|
||||
BuildDate: time.Unix(setting.BuildStamp, 0).UTC().Format(time.DateTime),
|
||||
GitVersion: k8sVersion,
|
||||
}
|
||||
|
||||
// Create the server
|
||||
server, err := serverConfig.Complete().New("grafana-apiserver", genericapiserver.NewEmptyDelegate())
|
||||
@ -380,18 +331,9 @@ func (s *service) start(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// Install the API Group+version
|
||||
for _, b := range builders {
|
||||
g, err := b.GetAPIGroupInfo(Scheme, Codecs, serverConfig.RESTOptionsGetter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if g == nil || len(g.PrioritizedVersions) < 1 {
|
||||
continue
|
||||
}
|
||||
err = server.InstallAPIGroup(g)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = InstallAPIs(server, serverConfig.RESTOptionsGetter, builders)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Used by the proxy wrapper registered in ProvideService
|
||||
|
Loading…
Reference in New Issue
Block a user