K8s: use --runtime-config={group}/{version}=true to enabled APIs (#81614)

This commit is contained in:
Ryan McKinley 2024-02-01 22:06:28 -08:00 committed by GitHub
parent 7464ea4346
commit 810d14d88f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 91 additions and 9 deletions

View File

@ -1,7 +1,9 @@
package apiserver
import (
"fmt"
"os"
"strings"
"github.com/spf13/cobra"
genericapiserver "k8s.io/apiserver/pkg/server"
@ -13,6 +15,7 @@ import (
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 := ""
cmd := &cobra.Command{
Use: "apiserver [api group(s)]",
@ -21,8 +24,13 @@ 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)
if err != nil {
return err
}
// Load each group from the args
if err := o.loadAPIGroupBuilders(args[1:]); err != nil {
if err := o.loadAPIGroupBuilders(apis); err != nil {
return err
}
@ -43,6 +51,8 @@ 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.")
// Register standard k8s flags with the command line
o.RecommendedOptions = options.NewRecommendedOptions(
defaultEtcdPathPrefix,
@ -61,3 +71,43 @@ 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
}

View File

@ -0,0 +1,22 @@
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)
}

View File

@ -47,11 +47,15 @@ func newAPIServerOptions(out, errOut io.Writer) *APIServerOptions {
}
}
func (o *APIServerOptions) loadAPIGroupBuilders(args []string) error {
func (o *APIServerOptions) loadAPIGroupBuilders(runtime []apiConfig) error {
o.builders = []builder.APIGroupBuilder{}
for _, g := range args {
switch g {
// No dependencies for testing
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
@ -69,18 +73,18 @@ func (o *APIServerOptions) loadAPIGroupBuilders(args []string) error {
),
)
case "testdata.datasource.grafana.app":
ds, err := server.InitializeDataSourceAPIServer(g)
ds, err := server.InitializeDataSourceAPIServer(gv.group)
if err != nil {
return err
}
o.builders = append(o.builders, ds)
default:
return fmt.Errorf("unknown group: %s", g)
return fmt.Errorf("unsupported runtime-config: %v", gv)
}
}
if len(o.builders) < 1 {
return fmt.Errorf("expected group name(s) in the command line arguments")
return fmt.Errorf("no apis matched ")
}
// Install schemas

View File

@ -210,7 +210,13 @@ func (b *DataSourceAPIBuilder) getPluginContext(ctx context.Context, uid string)
}
func (b *DataSourceAPIBuilder) GetOpenAPIDefinitions() openapi.GetOpenAPIDefinitions {
return v0alpha1.GetOpenAPIDefinitions
return func(ref openapi.ReferenceCallback) map[string]openapi.OpenAPIDefinition {
defs := query.GetOpenAPIDefinitions(ref) // required when running standalone
for k, v := range v0alpha1.GetOpenAPIDefinitions(ref) {
defs[k] = v
}
return defs
}
}
// Register additional routes with the server