Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add a craned webserver #126

Merged
merged 1 commit into from
Feb 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,12 @@ manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and Cust
go mod vendor; \
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" rbac:roleName=manager-role crd webhook paths="./vendor/github.com/gocrane/api/..." output:crd:artifacts:config=deploy/manifests

.PHONY: mockgen
mockgen: ## Run go mockgen to gen mock code.
go generate ./...

.PHONY: generate
generate: manifests ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
generate: manifests mockgen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.

.PHONY: fmt
fmt: ## Run go fmt against code.
Expand Down Expand Up @@ -223,3 +227,20 @@ GO_IMPORTS=$(shell go env GOPATH)/bin/goimports
else
GO_IMPORTS=$(shell which goimports)
endif


mockgen:
ifeq (, $(shell which mockgen))
@{ \
set -e ;\
export GO111MODULE=on; \
GO_IMPORTS_TMP_DIR=$$(mktemp -d) ;\
cd $$GO_IMPORTS_TMP_DIR ;\
go mod init tmp ;\
go get github.com/golang/mock@v1.5.0 ;\
rm -rf $$GO_IMPORTS_TMP_DIR ;\
}
GO_IMPORTS=$(shell go env GOPATH)/bin/mockgen
else
GO_IMPORTS=$(shell which mockgen)
endif
42 changes: 36 additions & 6 deletions cmd/craned/app/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"os"
"strings"

"github.com/gocrane/crane/pkg/recommend"
"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
utilfeature "k8s.io/apiserver/pkg/util/feature"
Expand Down Expand Up @@ -39,6 +39,9 @@ import (
"github.com/gocrane/crane/pkg/providers"
"github.com/gocrane/crane/pkg/providers/mock"
"github.com/gocrane/crane/pkg/providers/prom"
"github.com/gocrane/crane/pkg/recommend"
"github.com/gocrane/crane/pkg/server"
serverconfig "github.com/gocrane/crane/pkg/server/config"
"github.com/gocrane/crane/pkg/webhooks"
)

Expand All @@ -65,9 +68,10 @@ func NewManagerCommand(ctx context.Context) *cobra.Command {
if err := opts.Complete(); err != nil {
klog.Exit(err)
}
if err := opts.Validate(); err != nil {
klog.Exit(err)
if errs := opts.Validate(); len(errs) != 0 {
klog.Exit(errs)
}

if err := Run(ctx, opts); err != nil {
klog.Exit(err)
}
Expand Down Expand Up @@ -115,9 +119,35 @@ func Run(ctx context.Context, opts *options.Options) error {
// initialization custom collector metrics
initializationMetricCollector(mgr)

if err := mgr.Start(ctx); err != nil {
klog.Error(err, "problem running crane manager")
return err
var eg errgroup.Group

eg.Go(func() error {
if err := mgr.Start(ctx); err != nil {
klog.Error(err, "problem running crane manager")
klog.Exit(err)
}
return nil
})

eg.Go(func() error {
// Start the craned web server
serverConfig := serverconfig.NewServerConfig()
if err := opts.ApplyTo(serverConfig); err != nil {
klog.Exit(err)
}
// use controller runtime rest config, we can not refer kubeconfig option directly because it is unexported variable in vendor/sigs.k8s.io/controller-runtime/pkg/client/config/config.go
serverConfig.KubeRestConfig = mgr.GetConfig()
craneServer, err := server.NewServer(serverConfig)
if err != nil {
klog.Exit(err)
}
craneServer.Run(ctx)
return nil
})

// wait for all components exit
if err := eg.Wait(); err != nil {
klog.Fatal(err)
}

return nil
Expand Down
22 changes: 17 additions & 5 deletions cmd/craned/app/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import (

"github.com/gocrane/crane/pkg/prediction/config"
"github.com/gocrane/crane/pkg/providers"
serverconfig "github.com/gocrane/crane/pkg/server/config"
"github.com/gocrane/crane/pkg/webhooks"
)

// Options hold the command-line options about crane manager
// Options hold the command-line options about craned
type Options struct {
// ApiQps for rest client
ApiQps int
Expand Down Expand Up @@ -41,25 +42,36 @@ type Options struct {
// RecommendationConfigFile is the configuration file for resource/HPA recommendations.
// If unspecified, a default is provided.
RecommendationConfigFile string

// ServerOptions hold the craned web server options
ServerOptions *ServerOptions
}

// NewOptions builds an empty options.
func NewOptions() *Options {
return &Options{}
return &Options{
ServerOptions: NewServerOptions(),
}
}

// Complete completes all the required options.
func (o *Options) Complete() error {
return nil
return o.ServerOptions.Complete()
}

// Validate all required options.
func (o *Options) Validate() error {
return nil
func (o *Options) Validate() []error {
return o.ServerOptions.Validate()
}

func (o *Options) ApplyTo(cfg *serverconfig.Config) error {
return o.ServerOptions.ApplyTo(cfg)
}

// AddFlags adds flags to the specified FlagSet.
func (o *Options) AddFlags(flags *pflag.FlagSet) {
o.ServerOptions.AddFlags(flags)

flags.IntVar(&o.ApiQps, "api-qps", 300, "QPS of rest config.")
flags.IntVar(&o.ApiBurst, "api-burst", 400, "Burst of rest config.")
flags.StringVar(&o.MetricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
Expand Down
124 changes: 124 additions & 0 deletions cmd/craned/app/options/server_options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package options

import (
"fmt"
"os"
"strings"

"github.com/gin-gonic/gin"
"github.com/spf13/pflag"
"gopkg.in/gcfg.v1"

serverconfig "github.com/gocrane/crane/pkg/server/config"
"github.com/gocrane/crane/pkg/server/service/dashboard"
"github.com/gocrane/crane/pkg/server/store/secret"
)

// ServerOptions used for craned web server
type ServerOptions struct {
BindAddress string
BindPort int

EnableProfiling bool
EnableMetrics bool
Mode string

EnableGrafana bool
GrafanaConfigFile string
dashboard.GrafanaConfig

StoreType string
}

func NewServerOptions() *ServerOptions {
return &ServerOptions{}
}

func (o *ServerOptions) Complete() error {
if o.EnableGrafana {
var gconfig dashboard.GrafanaConfig
grafanaConfig, err := os.Open(o.GrafanaConfigFile)
if err != nil {
return err
}
defer grafanaConfig.Close()

if err := gcfg.FatalOnly(gcfg.ReadInto(&gconfig, grafanaConfig)); err != nil {
return err
}
o.GrafanaConfig = gconfig
}
return nil
}

func (o *ServerOptions) ApplyTo(cfg *serverconfig.Config) error {
cfg.BindAddress = o.BindAddress
cfg.BindPort = o.BindPort

cfg.Mode = o.Mode
cfg.EnableMetrics = o.EnableMetrics
cfg.EnableProfiling = o.EnableProfiling

cfg.EnableGrafana = o.EnableGrafana
cfg.GrafanaConfig = &o.GrafanaConfig
cfg.StoreType = o.StoreType
return nil
}

func (o *ServerOptions) Validate() []error {
var errors []error

if o.EnableGrafana {
if o.APIKey == "" && o.Username == "" && o.Password == "" {
errors = append(errors, fmt.Errorf("no apikey or username&password specified"))
}
}

if o.BindPort < 0 || o.BindPort > 65535 {
errors = append(
errors,
fmt.Errorf(
"--server-bind-port %v must be between 0 and 65535, inclusive. 0 for turning off insecure (HTTP) port",
o.BindPort,
),
)
}

if strings.ToLower(o.StoreType) != secret.StoreType {
errors = append(errors, fmt.Errorf("--server-store only support secret now"))
}

return errors
}

// AddFlags adds flags related to features for a specific server option to the
// specified FlagSet.
func (o *ServerOptions) AddFlags(fs *pflag.FlagSet) {
if fs == nil {
return
}

fs.StringVar(&o.BindAddress, "server-bind-address", "0.0.0.0", ""+
"The IP address on which to serve the --server-bind-port "+
"(set to 0.0.0.0 for all IPv4 interfaces and :: for all IPv6 interfaces).")
fs.IntVar(&o.BindPort, "server-bind-port", 8082,
"The port on which to serve unsecured, unauthenticated access")

fs.BoolVar(&o.EnableProfiling, "server-enable-profiling", o.EnableProfiling,
"Enable profiling via web interface host:port/debug/pprof/")

fs.BoolVar(&o.EnableMetrics, "server-enable-metrics", o.EnableMetrics,
"Enables metrics on the server at /metrics")

fs.StringVar(&o.Mode, "server-mode", gin.ReleaseMode,
"Debug mode of the gin server, support release,debug,test")

fs.BoolVar(&o.EnableGrafana, "server-enable-grafana", o.EnableGrafana,
"Enable grafana will read grafana config file to requests grafana dashboard")

fs.StringVar(&o.GrafanaConfigFile, "server-grafana-config", o.GrafanaConfigFile,
"Grafana config file, file contents is grafana config")

fs.StringVar(&o.StoreType, "server-store", secret.StoreType, "Server storage type, support secret now")

}
7 changes: 7 additions & 0 deletions examples/grafana.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[service]
Scheme=
Host=127.0.0.1:3000
[auth]
APIKey=
Username=admin
Password=admin
Loading