K8s: Refactor standalone apiserver initialization (#81932)

This commit is contained in:
Ryan McKinley
2024-02-06 08:40:35 -08:00
committed by GitHub
parent abaed01d7e
commit 91754bcda5
11 changed files with 256 additions and 438 deletions
+14 -43
View File
@@ -1,22 +1,28 @@
package apiserver
import (
"fmt"
"os"
"strings"
"github.com/spf13/cobra"
genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/apiserver/pkg/server/options"
"k8s.io/component-base/cli"
"github.com/grafana/grafana/pkg/server"
grafanaapiserver "github.com/grafana/grafana/pkg/services/apiserver"
"github.com/grafana/grafana/pkg/services/apiserver/standalone"
)
func newCommandStartExampleAPIServer(o *APIServerOptions, stopCh <-chan struct{}) *cobra.Command {
devAcknowledgementNotice := "The apiserver command is in heavy development. The entire setup is subject to change without notice"
runtimeConfig := ""
factory, err := server.InitializeAPIServerFactory()
if err != nil {
return nil
}
o.factory = factory
cmd := &cobra.Command{
Use: "apiserver [api group(s)]",
Short: "Run the grafana apiserver",
@@ -24,7 +30,11 @@ func newCommandStartExampleAPIServer(o *APIServerOptions, stopCh <-chan struct{}
devAcknowledgementNotice,
Example: "grafana apiserver example.grafana.app",
RunE: func(c *cobra.Command, args []string) error {
apis, err := readRuntimeConfig(runtimeConfig)
runtime, err := standalone.ReadRuntimeConfig(runtimeConfig)
if err != nil {
return err
}
apis, err := o.factory.GetEnabled(runtime)
if err != nil {
return err
}
@@ -52,6 +62,7 @@ func newCommandStartExampleAPIServer(o *APIServerOptions, stopCh <-chan struct{}
}
cmd.Flags().StringVar(&runtimeConfig, "runtime-config", "", "A set of key=value pairs that enable or disable built-in APIs.")
o.factory.InitFlags(cmd.Flags())
// Register standard k8s flags with the command line
o.RecommendedOptions = options.NewRecommendedOptions(
@@ -71,43 +82,3 @@ func RunCLI() int {
return cli.Run(cmd)
}
type apiConfig struct {
group string
version string
enabled bool
}
func (a apiConfig) String() string {
return fmt.Sprintf("%s/%s=%v", a.group, a.version, a.enabled)
}
// Supported options are:
//
// <group>/<version>=true|false for a specific API group and version (e.g. dashboards.grafana.app/v0alpha1=true)
// api/all=true|false controls all API versions
// api/ga=true|false controls all API versions of the form v[0-9]+
// api/beta=true|false controls all API versions of the form v[0-9]+beta[0-9]+
// api/alpha=true|false controls all API versions of the form v[0-9]+alpha[0-9]+`)
//
// See: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/
func readRuntimeConfig(cfg string) ([]apiConfig, error) {
if cfg == "" {
return nil, fmt.Errorf("missing --runtime-config={apiservers}")
}
parts := strings.Split(cfg, ",")
apis := make([]apiConfig, len(parts))
for i, part := range parts {
idx0 := strings.Index(part, "/")
idx1 := strings.LastIndex(part, "=")
if idx1 < idx0 || idx0 < 0 {
return nil, fmt.Errorf("expected values in the form: group/version=true")
}
apis[i] = apiConfig{
group: part[:idx0],
version: part[idx0+1 : idx1],
enabled: part[idx1+1:] == "true",
}
}
return apis, nil
}
-22
View File
@@ -1,22 +0,0 @@
package apiserver
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
)
func TestAdminAPIEndpoint(t *testing.T) {
out, err := readRuntimeConfig("all/all=true,dashboards.grafana.app/v0alpha1=false")
require.NoError(t, err)
require.Equal(t, []apiConfig{
{group: "all", version: "all", enabled: true},
{group: "dashboards.grafana.app", version: "v0alpha1", enabled: false},
}, out)
require.Equal(t, "all/all=true", fmt.Sprintf("%v", out[0]))
// Empty is an error
_, err = readRuntimeConfig("")
require.Error(t, err)
}
+9 -40
View File
@@ -6,23 +6,17 @@ import (
"net"
"path"
"k8s.io/apimachinery/pkg/runtime/schema"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/apiserver/pkg/server/options"
"k8s.io/client-go/tools/clientcmd"
netutils "k8s.io/utils/net"
"github.com/grafana/grafana/pkg/registry/apis/example"
"github.com/grafana/grafana/pkg/registry/apis/featuretoggle"
"github.com/grafana/grafana/pkg/registry/apis/query"
"github.com/grafana/grafana/pkg/registry/apis/query/runner"
"github.com/grafana/grafana/pkg/server"
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
grafanaAPIServer "github.com/grafana/grafana/pkg/services/apiserver"
"github.com/grafana/grafana/pkg/services/apiserver/builder"
"github.com/grafana/grafana/pkg/services/apiserver/standalone"
"github.com/grafana/grafana/pkg/services/apiserver/utils"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/setting"
)
const (
@@ -32,6 +26,7 @@ const (
// APIServerOptions contains the state for the apiserver
type APIServerOptions struct {
factory standalone.APIServerFactory
builders []builder.APIGroupBuilder
RecommendedOptions *options.RecommendedOptions
AlternateDNS []string
@@ -47,40 +42,14 @@ func newAPIServerOptions(out, errOut io.Writer) *APIServerOptions {
}
}
func (o *APIServerOptions) loadAPIGroupBuilders(runtime []apiConfig) error {
func (o *APIServerOptions) loadAPIGroupBuilders(apis []schema.GroupVersion) error {
o.builders = []builder.APIGroupBuilder{}
for _, gv := range runtime {
if !gv.enabled {
return fmt.Errorf("disabling apis is not yet supported")
}
switch gv.group {
case "all":
return fmt.Errorf("managing all APIs is not yet supported")
case "example.grafana.app":
o.builders = append(o.builders, example.NewTestingAPIBuilder())
// Only works with testdata
case "query.grafana.app":
o.builders = append(o.builders, query.NewQueryAPIBuilder(
featuremgmt.WithFeatures(),
runner.NewDummyTestRunner(),
runner.NewDummyRegistry(),
))
case "featuretoggle.grafana.app":
o.builders = append(o.builders,
featuretoggle.NewFeatureFlagAPIBuilder(
featuremgmt.WithFeatureManager(setting.FeatureMgmtSettings{}, nil), // none... for now
&actest.FakeAccessControl{ExpectedEvaluate: false},
),
)
case "testdata.datasource.grafana.app":
ds, err := server.InitializeDataSourceAPIServer(gv.group)
if err != nil {
return err
}
o.builders = append(o.builders, ds)
default:
return fmt.Errorf("unsupported runtime-config: %v", gv)
for _, gv := range apis {
api, err := o.factory.MakeAPIServer(gv)
if err != nil {
return err
}
o.builders = append(o.builders, api)
}
if len(o.builders) < 1 {