Skip to content

Commit

Permalink
add config
Browse files Browse the repository at this point in the history
Signed-off-by: Pavel Okhlopkov <[email protected]>
  • Loading branch information
Pavel Okhlopkov committed Dec 5, 2024
1 parent 7cbd786 commit 6e89b47
Show file tree
Hide file tree
Showing 10 changed files with 237 additions and 39 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ require (
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/caarlos0/env/v11 v11.2.2 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:o
github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/caarlos0/env/v11 v11.2.2 h1:95fApNrUyueipoZN/EhA8mMxiNxrBwDa+oAZrMWl3Kg=
github.com/caarlos0/env/v11 v11.2.2/go.mod h1:JBfcdeQiBoI3Zh1QRAWfe+tpiNTmDtcCj/hHHHMx0vc=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
Expand Down
7 changes: 1 addition & 6 deletions pkg/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ var CommonFlagsInfo = map[string]FlagInfo{
"SHELL_OPERATOR_PROMETHEUS_METRICS_PREFIX",
true,
},
// unused?
"hook-metrics-listen-port": {
"hook-metrics-listen-port",
"Port to use to serve hooks’ custom metrics to Prometheus. Can be set with $SHELL_OPERATOR_HOOK_METRICS_LISTEN_PORT. Equal to listen-port if empty.",
Expand All @@ -86,47 +87,41 @@ func DefineStartCommandFlags(kpApp *kingpin.Application, cmd *kingpin.CmdClause)
flag = CommonFlagsInfo["hooks-dir"]
if flag.Define {
cmd.Flag(flag.Name, flag.Help).
Envar(flag.Envar).
Default(HooksDir).
StringVar(&HooksDir)
}

flag = CommonFlagsInfo["tmp-dir"]
if flag.Define {
cmd.Flag(flag.Name, flag.Help).
Envar(flag.Envar).
Default(TempDir).
StringVar(&TempDir)
}

flag = CommonFlagsInfo["listen-address"]
if flag.Define {
cmd.Flag(flag.Name, flag.Help).
Envar(flag.Envar).
Default(ListenAddress).
StringVar(&ListenAddress)
}

flag = CommonFlagsInfo["listen-port"]
if flag.Define {
cmd.Flag(flag.Name, flag.Help).
Envar(flag.Envar).
Default(ListenPort).
StringVar(&ListenPort)
}

flag = CommonFlagsInfo["prometheus-metrics-prefix"]
if flag.Define {
cmd.Flag(flag.Name, flag.Help).
Envar(flag.Envar).
Default(PrometheusMetricsPrefix).
StringVar(&PrometheusMetricsPrefix)
}

flag = CommonFlagsInfo["namespace"]
if flag.Define {
cmd.Flag(flag.Name, flag.Help).
Envar(flag.Envar).
Default(Namespace).
StringVar(&Namespace)
}
Expand Down
226 changes: 226 additions & 0 deletions pkg/app/app_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
package app

import (
"fmt"
"time"

env "github.com/caarlos0/env/v11"

"github.com/deckhouse/deckhouse/pkg/log"
)

type appConfig struct {
HooksDir string `env:"HOOKS_DIR" envDefault:"hooks"`
TmpDir string `env:"TMP_DIR" envDefault:"/tmp/shell-operator"`
ListenAddress string `env:"LISTEN_ADDRESS" envDefault:"0.0.0.0"`
ListenPort string `env:"LISTEN_PORT" envDefault:"9115"`
PrometheusMetricsPrefix string `env:"PROMETHEUS_METRICS_PREFIX" envDefault:"shell_operator_"`
// unused?
HooksMetricsListenPort string `env:"HOOK_METRICS_LISTEN_PORT" envDefault:"9115"`
Namespace string `env:"Namespace"`
}

func newAppConfig() *appConfig {
return &appConfig{}
}

type debugConfig struct {
HTTPServerAddress string `env:"HTTP_SERVER_ADDR"`
KeepTemporaryFiles string `env:"KEEP_TMP_FILES" envDefault:"no"`
KubernetesAPI bool `env:"KUBERNETES_API" envDefault:"false"`
UnixSocket string `env:"UNIX_SOCKET" envDefault:"/var/run/shell-operator/debug.socket"`
}

func newDebugConfig() *debugConfig {
return &debugConfig{}
}

type jqConfig struct {
LibraryPath string `env:"LIBRARY_PATH"`
}

func newJQConfig() *jqConfig {
return &jqConfig{}
}

type kubeConfig struct {
// Settings for Kubernetes connection.
ContextName string `env:"CONTEXT"`
ConfigPath string `env:"CONFIG"`
ServerAddress string `env:"SERVER"`
// Rate limit settings for 'main' kube client
ClientQPS float32 `env:"CLIENT_QPS" envDefault:"5"`
ClientBurst int `env:"CLIENT_BURST" envDefault:"10"`
}

func newKubeConfig() *kubeConfig {
return &kubeConfig{}
}

type objectPatcherConfig struct {
// Settings for 'object_patcher' kube client
KubeClientQPS float32 `env:"KUBE_CLIENT_QPS" envDefault:"4"`
KubeClisntBurst int `env:"KUBE_CLIENT_BURST" envDefault:"10"`
KubeClientTimeout time.Duration `env:"KUBE_CLIENT_TIMEOUT" envDefault:"10s"`
}

func newObjectPatcherConfig() *objectPatcherConfig {
return &objectPatcherConfig{}
}

type validatingWebhookConfig struct {
ConfigurationName string `env:"CONFIGURATION_NAME" envDefault:"shell-operator-hooks"`
ServiceName string `env:"SERVICE_NAME" envDefault:"shell-operator-validating-svc"`
ServerCert string `env:"SERVER_CERT" envDefault:"/validating-certs/tls.crt"`
ServerKey string `env:"SERVER_KEY" envDefault:"/validating-certs/tls.key"`
CA string `env:"CA" envDefault:"/validating-certs/ca.crt"`
// check separator?
ClientCA []string `env:"CLIENT_CA" envSeparator:","`
// enum "Fail" || "Ignore"
FailurePolicy string `env:"FAILURE_POLICY" envDefault:"Fail"`
ListenPort string `env:"LISTEN_PORT" envDefault:"9680"`
ListenAddress string `env:"LISTEN_ADDRESS" envDefault:"0.0.0.0"`
}

func newValidatingWebhookConfig() *validatingWebhookConfig {
return &validatingWebhookConfig{}
}

type conversionWebhookConfig struct {
ServiceName string `env:"SERVICE_NAME" envDefault:"shell-operator-conversion-svc"`
ServerCert string `env:"SERVER_CERT" envDefault:"/conversion-certs/tls.crt"`
ServerKey string `env:"SERVER_KEY" envDefault:"/conversion-certs/tls.key"`
CA string `env:"CA" envDefault:"/conversion-certs/ca.crt"`
// check separator?
ClientCA []string `env:"CLIENT_CA" envSeparator:","`
ListenPort string `env:"LISTEN_PORT" envDefault:"9681"`
ListenAddress string `env:"LISTEN_ADDRESS" envDefault:"0.0.0.0"`
}

func newConversionWebhookConfig() *conversionWebhookConfig {
return &conversionWebhookConfig{}
}

type logConfig struct {
Level string `env:"LEVEL" envDefault:"info"`
Type string `env:"TYPE" envDefault:"text"`
NoTime bool `env:"NO_TIME" envDefault:"false"`
ProxyHookJson bool `env:"PROXY_HOOK_JSON" envDefault:"false"`
}

func newLogConfig() *logConfig {
return &logConfig{}
}

type Config struct {
AppConfig *appConfig `envPrefix:"SHELL_OPERATOR_"`
JQConfig *jqConfig `envPrefix:"JQ_"`
KubeConfig *kubeConfig `envPrefix:"KUBE_"`
ObjectPatcherConfig *objectPatcherConfig `envPrefix:"OBJECT_PATCHER_"`
ValidatingWebhookConfig *validatingWebhookConfig `envPrefix:"VALIDATING_WEBHOOK_"`
ConversionWebhookConfig *conversionWebhookConfig `envPrefix:"CONVERSION_WEBHOOK_"`

DebugConfig *debugConfig `envPrefix:"DEBUG_"`

LogConfig *logConfig `envPrefix:"LOG_"`
LogLevel log.Level `env:"-"`
}

func NewConfig() *Config {
return &Config{
AppConfig: newAppConfig(),
JQConfig: newJQConfig(),
KubeConfig: newKubeConfig(),
ObjectPatcherConfig: newObjectPatcherConfig(),
ValidatingWebhookConfig: newValidatingWebhookConfig(),
ConversionWebhookConfig: newConversionWebhookConfig(),
DebugConfig: newDebugConfig(),
LogConfig: newLogConfig(),
}
}

func (cfg *Config) Parse() error {
opts := env.Options{
Prefix: "",
}

err := env.ParseWithOptions(cfg, opts)
if err != nil {
return fmt.Errorf("failed to parse config: %w", err)
}

cfg.LogLevel = log.LogLevelFromStr(cfg.LogConfig.Level)

return nil
}

func (cfg *Config) SetupGlobalVars() {
setIfNotEmpty(&HooksDir, cfg.AppConfig.HooksDir)
setIfNotEmpty(&TempDir, cfg.AppConfig.TmpDir)
setIfNotEmpty(&ListenAddress, cfg.AppConfig.ListenAddress)
setIfNotEmpty(&ListenPort, cfg.AppConfig.ListenPort)
setIfNotEmpty(&PrometheusMetricsPrefix, cfg.AppConfig.PrometheusMetricsPrefix)
setIfNotEmpty(&Namespace, cfg.AppConfig.Namespace)

setIfNotEmpty(&DebugHttpServerAddr, cfg.DebugConfig.HTTPServerAddress)
setIfNotEmpty(&DebugKeepTmpFilesVar, cfg.DebugConfig.KeepTemporaryFiles)
setIfNotEmpty(&DebugKeepTmpFiles, cfg.DebugConfig.KeepTemporaryFiles == "yes")
setIfNotEmpty(&DebugKubernetesAPI, cfg.DebugConfig.KubernetesAPI)
setIfNotEmpty(&DebugUnixSocket, cfg.DebugConfig.UnixSocket)

fmt.Println("LOL UNIX SOCKET")
fmt.Println(DebugUnixSocket)
fmt.Println("LOL UNIX SOCKET FROM CFG")
fmt.Println(cfg.DebugConfig.UnixSocket)

setIfNotEmpty(&JqLibraryPath, cfg.JQConfig.LibraryPath)

setIfNotEmpty(&KubeContext, cfg.KubeConfig.ContextName)
setIfNotEmpty(&KubeConfig, cfg.KubeConfig.ConfigPath)
setIfNotEmpty(&KubeServer, cfg.KubeConfig.ServerAddress)
setIfNotEmpty(&KubeClientQps, cfg.KubeConfig.ClientQPS)
setIfNotEmpty(&KubeClientBurst, cfg.KubeConfig.ClientBurst)

setIfNotEmpty(&ObjectPatcherKubeClientQps, cfg.ObjectPatcherConfig.KubeClientQPS)
setIfNotEmpty(&ObjectPatcherKubeClientBurst, cfg.ObjectPatcherConfig.KubeClisntBurst)
setIfNotEmpty(&ObjectPatcherKubeClientTimeout, cfg.ObjectPatcherConfig.KubeClientTimeout)

setIfNotEmpty(&LogLevel, cfg.LogConfig.Level)
setIfNotEmpty(&LogNoTime, cfg.LogConfig.NoTime)
setIfNotEmpty(&LogType, cfg.LogConfig.Type)
setIfNotEmpty(&LogProxyHookJSON, cfg.LogConfig.ProxyHookJson)

setIfNotEmpty(&ValidatingWebhookSettings.ConfigurationName, cfg.ValidatingWebhookConfig.ConfigurationName)
setIfNotEmpty(&ValidatingWebhookSettings.ServiceName, cfg.ValidatingWebhookConfig.ServiceName)
setIfNotEmpty(&ValidatingWebhookSettings.ServerCertPath, cfg.ValidatingWebhookConfig.ServerCert)
setIfNotEmpty(&ValidatingWebhookSettings.ServerKeyPath, cfg.ValidatingWebhookConfig.ServerKey)
setIfNotEmpty(&ValidatingWebhookSettings.CAPath, cfg.ValidatingWebhookConfig.CA)
setSliceIfNotEmpty(&ValidatingWebhookSettings.ClientCAPaths, cfg.ValidatingWebhookConfig.ClientCA)
setIfNotEmpty(&ValidatingWebhookSettings.DefaultFailurePolicy, cfg.ValidatingWebhookConfig.FailurePolicy)
setIfNotEmpty(&ValidatingWebhookSettings.ListenPort, cfg.ValidatingWebhookConfig.ListenPort)
setIfNotEmpty(&ValidatingWebhookSettings.ListenAddr, cfg.ValidatingWebhookConfig.ListenAddress)

setIfNotEmpty(&ConversionWebhookSettings.ServiceName, cfg.ValidatingWebhookConfig.ServiceName)
setIfNotEmpty(&ConversionWebhookSettings.ServerCertPath, cfg.ValidatingWebhookConfig.ServerCert)
setIfNotEmpty(&ConversionWebhookSettings.ServerKeyPath, cfg.ValidatingWebhookConfig.ServerKey)
setIfNotEmpty(&ConversionWebhookSettings.CAPath, cfg.ValidatingWebhookConfig.CA)
setSliceIfNotEmpty(&ConversionWebhookSettings.ClientCAPaths, cfg.ValidatingWebhookConfig.ClientCA)
setIfNotEmpty(&ConversionWebhookSettings.ListenPort, cfg.ValidatingWebhookConfig.ListenPort)
setIfNotEmpty(&ConversionWebhookSettings.ListenAddr, cfg.ValidatingWebhookConfig.ListenAddress)
}

func setIfNotEmpty[T comparable](v *T, env T) {
if !isZero(env) {
*v = env
}
}

func setSliceIfNotEmpty[T any](v *[]T, env []T) {
if len(env) != 0 {
*v = env
}
}

func isZero[T comparable](v T) bool {
return v == *new(T)
}
4 changes: 0 additions & 4 deletions pkg/app/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,11 @@ func DefineDebugFlags(kpApp *kingpin.Application, cmd *kingpin.CmdClause) {
DefineDebugUnixSocketFlag(cmd)

cmd.Flag("debug-http-addr", "http addr for a debug endpoint").
Envar("DEBUG_HTTP_SERVER_ADDR").
Hidden().
Default(DebugHttpServerAddr).
StringVar(&DebugHttpServerAddr)

cmd.Flag("debug-keep-tmp-files", "set to yes to disable cleanup of temporary files").
Envar("DEBUG_KEEP_TMP_FILES").
Hidden().
Default(DebugKeepTmpFilesVar).Action(func(_ *kingpin.ParseContext) error {
DebugKeepTmpFiles = DebugKeepTmpFilesVar == "yes"
Expand All @@ -38,7 +36,6 @@ func DefineDebugFlags(kpApp *kingpin.Application, cmd *kingpin.CmdClause) {
StringVar(&DebugKeepTmpFilesVar)

cmd.Flag("debug-kubernetes-api", "enable client-go debug messages").
Envar("DEBUG_KUBERNETES_API").
Hidden().
Default("false").
BoolVar(&DebugKubernetesAPI)
Expand Down Expand Up @@ -85,7 +82,6 @@ Debug flags:

func DefineDebugUnixSocketFlag(cmd *kingpin.CmdClause) {
cmd.Flag("debug-unix-socket", "a path to a unix socket for a debug endpoint").
Envar("DEBUG_UNIX_SOCKET").
Hidden().
Default(DebugUnixSocket).
StringVar(&DebugUnixSocket)
Expand Down
1 change: 0 additions & 1 deletion pkg/app/jq.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ var JqLibraryPath = ""
// DefineJqFlags set flag for jq library
func DefineJqFlags(cmd *kingpin.CmdClause) {
cmd.Flag("jq-library-path", "Prepend directory to the search list for jq modules (-L flag). Can be set with $JQ_LIBRARY_PATH.").
Envar("JQ_LIBRARY_PATH").
Default(JqLibraryPath).
StringVar(&JqLibraryPath)
}
8 changes: 0 additions & 8 deletions pkg/app/kube-client.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,39 +31,31 @@ var (
func DefineKubeClientFlags(cmd *kingpin.CmdClause) {
// Settings for Kubernetes connection.
cmd.Flag("kube-context", "The name of the kubeconfig context to use. Can be set with $KUBE_CONTEXT.").
Envar("KUBE_CONTEXT").
Default(KubeContext).
StringVar(&KubeContext)
cmd.Flag("kube-config", "Path to the kubeconfig file. Can be set with $KUBE_CONFIG.").
Envar("KUBE_CONFIG").
Default(KubeConfig).
StringVar(&KubeConfig)
cmd.Flag("kube-server", "The address and port of the Kubernetes API server. Can be set with $KUBE_SERVER.").
Envar("KUBE_SERVER").
Default(KubeServer).
StringVar(&KubeServer)

// Rate limit settings for 'main' kube client
cmd.Flag("kube-client-qps", "QPS for a rate limiter of a Kubernetes client for hook events. Can be set with $KUBE_CLIENT_QPS.").
Envar("KUBE_CLIENT_QPS").
Default(KubeClientQpsDefault).
Float32Var(&KubeClientQps)
cmd.Flag("kube-client-burst", "Burst for a rate limiter of a Kubernetes client for hook events. Can be set with $KUBE_CLIENT_BURST.").
Envar("KUBE_CLIENT_BURST").
Default(KubeClientBurstDefault).
IntVar(&KubeClientBurst)

// Settings for 'object_patcher' kube client
cmd.Flag("object-patcher-kube-client-qps", "QPS for a rate limiter of a Kubernetes client for Object patcher. Can be set with $OBJECT_PATCHER_KUBE_CLIENT_QPS.").
Envar("OBJECT_PATCHER_KUBE_CLIENT_QPS").
Default(ObjectPatcherKubeClientQpsDefault).
Float32Var(&ObjectPatcherKubeClientQps)
cmd.Flag("object-patcher-kube-client-burst", "Burst for a rate limiter of a Kubernetes client for Object patcher. Can be set with $OBJECT_PATCHER_KUBE_CLIENT_BURST.").
Envar("OBJECT_PATCHER_KUBE_CLIENT_BURST").
Default(ObjectPatcherKubeClientBurstDefault).
IntVar(&ObjectPatcherKubeClientBurst)
cmd.Flag("object-patcher-kube-client-timeout", "Timeout for object patcher requests to the Kubernetes API server. Can be set with $OBJECT_PATCHER_KUBE_CLIENT_TIMEOUT").
Envar("OBJECT_PATCHER_KUBE_CLIENT_TIMEOUT").
Default(ObjectPatcherKubeClientTimeoutDefault).
DurationVar(&ObjectPatcherKubeClientTimeout)
}
4 changes: 0 additions & 4 deletions pkg/app/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,14 @@ const (
// DefineLoggingFlags defines flags for logger settings.
func DefineLoggingFlags(cmd *kingpin.CmdClause) {
cmd.Flag("log-level", "Logging level: debug, info, error. Default is info. Can be set with $LOG_LEVEL.").
Envar("LOG_LEVEL").
Default(LogLevel).
StringVar(&LogLevel)
cmd.Flag("log-type", "Logging formatter type: json, text or color. Default is text. Can be set with $LOG_TYPE.").
Envar("LOG_TYPE").
Default(LogType).
StringVar(&LogType)
cmd.Flag("log-no-time", "Disable timestamp logging if flag is present. Useful when output is redirected to logging system that already adds timestamps. Can be set with $LOG_NO_TIME.").
Envar("LOG_NO_TIME").
BoolVar(&LogNoTime)
cmd.Flag("log-proxy-hook-json", "Delegate hook stdout/ stderr JSON logging to the hooks and act as a proxy that adds some extra fields before just printing the output").
Envar("LOG_PROXY_HOOK_JSON").
BoolVar(&LogProxyHookJSON)
}

Expand Down
Loading

0 comments on commit 6e89b47

Please sign in to comment.