mirror of
https://github.com/grafana/grafana.git
synced 2024-11-21 16:38:03 -06:00
K8s: Use grafana executable for standalone api service (#77904)
Co-authored-by: Dan Cech <dcech@grafana.com>
This commit is contained in:
parent
49d6066609
commit
d410ef3439
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@ -69,7 +69,7 @@
|
||||
/pkg/apis/ @grafana/grafana-app-platform-squad
|
||||
/pkg/bus/ @grafana/backend-platform
|
||||
/pkg/cmd/ @grafana/backend-platform
|
||||
/pkg/cmd/grafana-example-apiserver @grafana/grafana-app-platform-squad
|
||||
/pkg/cmd/grafana/apiserver @grafana/grafana-app-platform-squad
|
||||
/pkg/components/apikeygen/ @grafana/identity-access-team
|
||||
/pkg/components/satokengen/ @grafana/identity-access-team
|
||||
/pkg/components/dashdiffs/ @grafana/backend-platform
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -78,7 +78,7 @@ public/css/*.min.css
|
||||
/data/*
|
||||
/bin/*
|
||||
|
||||
# any certificates generated by grafana-example-apiserver
|
||||
# any certificates generated by grafana apiserver
|
||||
apiserver.local.config/
|
||||
|
||||
# devenv
|
||||
|
6
Makefile
6
Makefile
@ -7,7 +7,7 @@ WIRE_TAGS = "oss"
|
||||
-include local/Makefile
|
||||
include .bingo/Variables.mk
|
||||
|
||||
.PHONY: all deps-go deps-js deps build-go build-backend build-example-apiserver build-server build-cli build-js build build-docker-full build-docker-full-ubuntu lint-go golangci-lint test-go test-js gen-ts test run run-frontend clean devenv devenv-down protobuf drone help gen-go gen-cue fix-cue
|
||||
.PHONY: all deps-go deps-js deps build-go build-backend build-server build-cli build-js build build-docker-full build-docker-full-ubuntu lint-go golangci-lint test-go test-js gen-ts test run run-frontend clean devenv devenv-down protobuf drone help gen-go gen-cue fix-cue
|
||||
|
||||
GO = go
|
||||
GO_FILES ?= ./pkg/...
|
||||
@ -132,10 +132,6 @@ build-server: ## Build Grafana server.
|
||||
@echo "build server"
|
||||
$(GO) run build.go $(GO_BUILD_FLAGS) build-server
|
||||
|
||||
build-example-apiserver: ## Build Grafana example-apiserver application.
|
||||
@echo "build grafana-cli"
|
||||
$(GO) run build.go $(GO_BUILD_FLAGS) build-example-apiserver
|
||||
|
||||
build-cli: ## Build Grafana CLI application.
|
||||
@echo "build grafana-cli"
|
||||
$(GO) run build.go $(GO_BUILD_FLAGS) build-cli
|
||||
|
@ -17,13 +17,12 @@ const (
|
||||
GoOSWindows = "windows"
|
||||
GoOSLinux = "linux"
|
||||
|
||||
BackendBinary = "grafana"
|
||||
ExampleAPIServerBinary = "grafana-example-apiserver"
|
||||
ServerBinary = "grafana-server"
|
||||
CLIBinary = "grafana-cli"
|
||||
BackendBinary = "grafana"
|
||||
ServerBinary = "grafana-server"
|
||||
CLIBinary = "grafana-cli"
|
||||
)
|
||||
|
||||
var binaries = []string{BackendBinary, ExampleAPIServerBinary, ServerBinary, CLIBinary}
|
||||
var binaries = []string{BackendBinary, ServerBinary, CLIBinary}
|
||||
|
||||
func logError(message string, err error) int {
|
||||
log.Println(message, err)
|
||||
@ -86,13 +85,6 @@ func RunCmd() int {
|
||||
return 1
|
||||
}
|
||||
|
||||
case "build-example-apiserver":
|
||||
clean(opts)
|
||||
if err := doBuild("grafana-example-apiserver", "./pkg/cmd/grafana-example-apiserver", opts); err != nil {
|
||||
log.Println(err)
|
||||
return 1
|
||||
}
|
||||
|
||||
case "build-cli":
|
||||
clean(opts)
|
||||
if err := doBuild("grafana-cli", "./pkg/cmd/grafana-cli", opts); err != nil {
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/build/golangutils"
|
||||
)
|
||||
|
||||
var binaries = []string{"grafana", "grafana-example-apiserver", "grafana-server", "grafana-cli"}
|
||||
var binaries = []string{"grafana", "grafana-server", "grafana-cli"}
|
||||
|
||||
const (
|
||||
SuffixEnterprise2 = "-enterprise2"
|
||||
|
@ -1,50 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/component-base/cli"
|
||||
)
|
||||
|
||||
func NewCommandStartExampleAPIServer(defaults *ExampleServerOptions, stopCh <-chan struct{}) *cobra.Command {
|
||||
o := *defaults
|
||||
cmd := &cobra.Command{
|
||||
Short: "Launch the example API server",
|
||||
Long: "Launch the example API server",
|
||||
RunE: func(c *cobra.Command, args []string) error {
|
||||
if err := o.Complete(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config, err := o.Config()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := o.RunExampleServer(config, stopCh); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
o.RecommendedOptions.AddFlags(flags)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func main() {
|
||||
stopCh := genericapiserver.SetupSignalHandler()
|
||||
options, err := NewExampleServerOptions(os.Stdout, os.Stderr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cmd := NewCommandStartExampleAPIServer(options, stopCh)
|
||||
|
||||
code := cli.Run(cmd)
|
||||
os.Exit(code)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
# grafana-example-apiserver
|
||||
# grafana apiserver (standalone)
|
||||
|
||||
The example-apiserver closely resembles the
|
||||
[sample-apiserver](https://github.com/kubernetes/sample-apiserver/tree/master) project in code and thus
|
||||
@ -19,7 +19,7 @@ can be used as a root server for this example-apiserver (in aggregated mode). He
|
||||
kind cluster and that you can provide its kubeconfig in the parameters to the example-apiserver.
|
||||
|
||||
```shell
|
||||
go run ./pkg/cmd/grafana-example-apiserver \
|
||||
go run ./pkg/cmd/grafana apiserver example.grafana.app\
|
||||
--authentication-kubeconfig ~/.kube/config \
|
||||
--authorization-kubeconfig ~/.kube/config \
|
||||
--kubeconfig ~/.kube/config \
|
75
pkg/cmd/grafana/apiserver/cmd.go
Normal file
75
pkg/cmd/grafana/apiserver/cmd.go
Normal file
@ -0,0 +1,75 @@
|
||||
package apiserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/apiserver/pkg/server/options"
|
||||
"k8s.io/component-base/cli"
|
||||
)
|
||||
|
||||
func newCommandStartExampleAPIServer(o *ExampleServerOptions, stopCh <-chan struct{}) *cobra.Command {
|
||||
// While this exists as an experimental feature, we require adding the scarry looking command line
|
||||
devAcknowledgementFlag := "grafana-enable-experimental-apiserver"
|
||||
devAcknowledgementNotice := "The apiserver command is in heavy development. The entire setup is subject to change without notice"
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "apiserver [api group(s)]",
|
||||
Short: "Run the grafana apiserver",
|
||||
Long: "Run a standalone kubernetes based apiserver that can be aggregated by a root apiserver. " +
|
||||
devAcknowledgementNotice,
|
||||
Example: fmt.Sprintf("grafana apiserver example.grafana.app --%s", devAcknowledgementFlag),
|
||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||
ok, err := cmd.Flags().GetBool(devAcknowledgementFlag)
|
||||
if !ok || err != nil {
|
||||
fmt.Printf("requires running with the flag: --%s\n\n%s\n\n",
|
||||
devAcknowledgementFlag, devAcknowledgementNotice)
|
||||
os.Exit(1)
|
||||
}
|
||||
},
|
||||
RunE: func(c *cobra.Command, args []string) error {
|
||||
// Load each group from the args
|
||||
if err := o.LoadAPIGroupBuilders(args[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Finish the config (applies all defaults)
|
||||
if err := o.Complete(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config, err := o.Config()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := o.RunExampleServer(config, stopCh); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// Register grafana flags
|
||||
cmd.PersistentFlags().Bool(devAcknowledgementFlag, false, devAcknowledgementNotice)
|
||||
|
||||
// Register standard k8s flags with the command line
|
||||
o.RecommendedOptions = options.NewRecommendedOptions(
|
||||
defaultEtcdPathPrefix,
|
||||
Codecs.LegacyCodec(), // the codec is passed to etcd and not used
|
||||
)
|
||||
o.RecommendedOptions.AddFlags(cmd.Flags())
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func RunCLI() int {
|
||||
stopCh := genericapiserver.SetupSignalHandler()
|
||||
|
||||
options := newExampleServerOptions(os.Stdout, os.Stderr)
|
||||
cmd := newCommandStartExampleAPIServer(options, stopCh)
|
||||
|
||||
return cli.Run(cmd)
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
package main
|
||||
package apiserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
exampleAPI "github.com/grafana/grafana/pkg/registry/apis/example"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/example"
|
||||
grafanaAPIServer "github.com/grafana/grafana/pkg/services/grafana-apiserver"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@ -43,34 +43,47 @@ func init() {
|
||||
|
||||
// ExampleServerOptions contains the state for the apiserver
|
||||
type ExampleServerOptions struct {
|
||||
builders []grafanaAPIServer.APIGroupBuilder
|
||||
RecommendedOptions *options.RecommendedOptions
|
||||
Builders []grafanaAPIServer.APIGroupBuilder
|
||||
AlternateDNS []string
|
||||
|
||||
StdOut io.Writer
|
||||
StdErr io.Writer
|
||||
}
|
||||
|
||||
func NewExampleServerOptions(out, errOut io.Writer) (*ExampleServerOptions, error) {
|
||||
builder := &exampleAPI.TestingAPIBuilder{}
|
||||
|
||||
// Install schema
|
||||
if err := builder.InstallSchema(Scheme); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func newExampleServerOptions(out, errOut io.Writer) *ExampleServerOptions {
|
||||
return &ExampleServerOptions{
|
||||
Builders: []grafanaAPIServer.APIGroupBuilder{builder},
|
||||
RecommendedOptions: options.NewRecommendedOptions(
|
||||
defaultEtcdPathPrefix,
|
||||
Codecs.LegacyCodec(builder.GetGroupVersion()),
|
||||
),
|
||||
StdOut: out,
|
||||
StdErr: errOut,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (o ExampleServerOptions) Config() (*genericapiserver.RecommendedConfig, error) {
|
||||
func (o *ExampleServerOptions) LoadAPIGroupBuilders(args []string) error {
|
||||
o.builders = []grafanaAPIServer.APIGroupBuilder{}
|
||||
for _, g := range args {
|
||||
switch g {
|
||||
// No dependencies for testing
|
||||
case "example.grafana.app":
|
||||
o.builders = append(o.builders, &example.TestingAPIBuilder{})
|
||||
default:
|
||||
return fmt.Errorf("unknown group: %s", g)
|
||||
}
|
||||
}
|
||||
|
||||
if len(o.builders) < 1 {
|
||||
return fmt.Errorf("expected group name(s) in the command line arguments")
|
||||
}
|
||||
|
||||
// Install schemas
|
||||
for _, b := range o.builders {
|
||||
if err := b.InstallSchema(Scheme); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *ExampleServerOptions) Config() (*genericapiserver.RecommendedConfig, error) {
|
||||
if err := o.RecommendedOptions.SecureServing.MaybeDefaultWithSelfSignedCerts("localhost", o.AlternateDNS, []net.IP{netutils.ParseIPSloppy("127.0.0.1")}); err != nil {
|
||||
return nil, fmt.Errorf("error creating self-signed certificates: %v", err)
|
||||
}
|
||||
@ -94,18 +107,18 @@ func (o ExampleServerOptions) Config() (*genericapiserver.RecommendedConfig, err
|
||||
// Validate validates ExampleServerOptions
|
||||
// NOTE: we don't call validate on the top level recommended options as it doesn't like skipping etcd-servers
|
||||
// the function is left here for troubleshooting any other config issues
|
||||
func (o ExampleServerOptions) Validate(args []string) error {
|
||||
func (o *ExampleServerOptions) Validate(args []string) error {
|
||||
errors := []error{}
|
||||
errors = append(errors, o.RecommendedOptions.Validate()...)
|
||||
return utilerrors.NewAggregate(errors)
|
||||
}
|
||||
|
||||
// Complete fills in fields required to have valid data
|
||||
func (o ExampleServerOptions) Complete() error {
|
||||
func (o *ExampleServerOptions) Complete() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o ExampleServerOptions) RunExampleServer(config *genericapiserver.RecommendedConfig, stopCh <-chan struct{}) error {
|
||||
func (o *ExampleServerOptions) RunExampleServer(config *genericapiserver.RecommendedConfig, stopCh <-chan struct{}) error {
|
||||
delegationTarget := genericapiserver.NewEmptyDelegate()
|
||||
completedConfig := config.Complete()
|
||||
server, err := completedConfig.New("example-apiserver", delegationTarget)
|
||||
@ -114,7 +127,7 @@ func (o ExampleServerOptions) RunExampleServer(config *genericapiserver.Recommen
|
||||
}
|
||||
|
||||
// Install the API Group+version
|
||||
for _, b := range o.Builders {
|
||||
for _, b := range o.builders {
|
||||
g, err := b.GetAPIGroupInfo(Scheme, Codecs, completedConfig.RESTOptionsGetter)
|
||||
if err != nil {
|
||||
return err
|
@ -9,6 +9,7 @@ import (
|
||||
|
||||
gcli "github.com/grafana/grafana/pkg/cmd/grafana-cli/commands"
|
||||
gsrv "github.com/grafana/grafana/pkg/cmd/grafana-server/commands"
|
||||
"github.com/grafana/grafana/pkg/cmd/grafana/apiserver"
|
||||
)
|
||||
|
||||
// The following variables cannot be constants, since they can be overridden through the -X link flag
|
||||
@ -32,6 +33,18 @@ func main() {
|
||||
Commands: []*cli.Command{
|
||||
gcli.CLICommand(version),
|
||||
gsrv.ServerCommand(version, commit, enterpriseCommit, buildBranch, buildstamp),
|
||||
{
|
||||
// The kubernetes standalone apiserver service runner
|
||||
Name: "apiserver",
|
||||
Usage: "run a standalone api service (experimental)",
|
||||
// Skip parsing flags because the command line is actually managed by cobra
|
||||
SkipFlagParsing: true,
|
||||
Action: func(context *cli.Context) error {
|
||||
// exit here because apiserver handles its own error output
|
||||
os.Exit(apiserver.RunCLI())
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
CommandNotFound: cmdNotFound,
|
||||
EnableBashCompletion: true,
|
||||
|
Loading…
Reference in New Issue
Block a user