diff --git a/cmd/cleanup-controller/main.go b/cmd/cleanup-controller/main.go index 374c8d02c8..8f958f7cfc 100644 --- a/cmd/cleanup-controller/main.go +++ b/cmd/cleanup-controller/main.go @@ -32,16 +32,6 @@ const ( resyncPeriod = 15 * time.Minute ) -func parseFlags(config internal.Configuration) { - internal.InitFlags(config) - flag.StringVar(&otel, "otelConfig", "prometheus", "Set this flag to 'grpc', to enable exporting metrics to an Opentelemetry Collector. The default collector is set to \"prometheus\"") - flag.StringVar(&otelCollector, "otelCollector", "opentelemetrycollector.kyverno.svc.cluster.local", "Set this flag to the OpenTelemetry Collector Service Address. Kyverno will try to connect to this on the metrics port.") - flag.StringVar(&transportCreds, "transportCreds", "", "Set this flag to the CA secret containing the certificate which is used by our Opentelemetry Metrics Client. If empty string is set, means an insecure connection will be used") - flag.StringVar(&metricsPort, "metricsPort", "8000", "Expose prometheus metrics at the given port, default to 8000.") - flag.BoolVar(&disableMetricsExport, "disableMetrics", false, "Set this flag to 'true' to disable metrics.") - flag.Parse() -} - func setupMetrics(logger logr.Logger, kubeClient kubernetes.Interface) (*metrics.MetricsConfig, context.CancelFunc, error) { logger = logger.WithName("metrics") logger.Info("setup metrics...", "otel", otel, "port", metricsPort, "collector", otelCollector, "creds", transportCreds) @@ -82,23 +72,29 @@ func setupMetrics(logger logr.Logger, kubeClient kubernetes.Interface) (*metrics } func main() { + // application flags + flagset := flag.NewFlagSet("application", flag.ExitOnError) + flagset.StringVar(&otel, "otelConfig", "prometheus", "Set this flag to 'grpc', to enable exporting metrics to an Opentelemetry Collector. The default collector is set to \"prometheus\"") + flagset.StringVar(&otelCollector, "otelCollector", "opentelemetrycollector.kyverno.svc.cluster.local", "Set this flag to the OpenTelemetry Collector Service Address. Kyverno will try to connect to this on the metrics port.") + flagset.StringVar(&transportCreds, "transportCreds", "", "Set this flag to the CA secret containing the certificate which is used by our Opentelemetry Metrics Client. If empty string is set, means an insecure connection will be used") + flagset.StringVar(&metricsPort, "metricsPort", "8000", "Expose prometheus metrics at the given port, default to 8000.") + flagset.BoolVar(&disableMetricsExport, "disableMetrics", false, "Set this flag to 'true' to disable metrics.") // config appConfig := internal.NewConfiguration( internal.WithProfiling(), internal.WithTracing(), internal.WithKubeconfig(), + internal.WithFlagSets(flagset), ) // parse flags - parseFlags(appConfig) + internal.ParseFlags(appConfig) // setup logger - logger := internal.SetupLogger() - // setup maxprocs - undo := internal.SetupMaxProcs(logger) - defer undo() // show version - internal.ShowVersion(logger) // start profiling - internal.SetupProfiling(logger) + // setup signals + // setup maxprocs + ctx, logger, sdown := internal.Setup() + defer sdown() // create raw client rawClient := internal.CreateKubernetesClient(logger) // setup signals @@ -128,7 +124,7 @@ func main() { secretLister := kubeKyvernoInformer.Core().V1().Secrets().Lister() // start informers and wait for cache sync // we need to call start again because we potentially registered new informers - if !internal.StartInformersAndWaitForCacheSync(signalCtx, kubeKyvernoInformer) { + if !internal.StartInformersAndWaitForCacheSync(ctx, kubeKyvernoInformer) { os.Exit(1) } server := NewServer( @@ -142,7 +138,7 @@ func main() { }, ) // start webhooks server - server.Run(signalCtx.Done()) + server.Run(ctx.Done()) // wait for termination signal - <-signalCtx.Done() + <-ctx.Done() } diff --git a/cmd/initContainer/main.go b/cmd/initContainer/main.go index 32b5eb2c92..5e4bdab1f6 100644 --- a/cmd/initContainer/main.go +++ b/cmd/initContainer/main.go @@ -6,7 +6,6 @@ package main import ( "context" "encoding/json" - "flag" "os" "sync" "time" @@ -34,46 +33,29 @@ const ( convertGenerateRequest string = "ConvertGenerateRequest" ) -func parseFlags(config internal.Configuration) { - internal.InitFlags(config) - flag.Parse() -} - func main() { // config appConfig := internal.NewConfiguration( internal.WithKubeconfig(), ) // parse flags - parseFlags(appConfig) + internal.ParseFlags(appConfig) // setup logger - logger := internal.SetupLogger() - // setup maxprocs - undo := internal.SetupMaxProcs(logger) - defer undo() // show version - internal.ShowVersion(logger) - // os signal handler - signalCtx, signalCancel := internal.SetupSignals(logger) - defer signalCancel() - + // start profiling + // setup signals + // setup maxprocs + ctx, logger, sdown := internal.Setup() + defer sdown() + // create clients kubeClient := internal.CreateKubernetesClient(logger) dynamicClient := internal.CreateDynamicClient(logger) kyvernoClient := internal.CreateKyvernoClient(logger) - - // DYNAMIC CLIENT - // - client for all registered resources - client, err := dclient.NewClient( - signalCtx, - dynamicClient, - kubeClient, - 15*time.Minute, - ) + client, err := dclient.NewClient(ctx, dynamicClient, kubeClient, 15*time.Minute) if err != nil { logger.Error(err, "Failed to create client") os.Exit(1) } - // Exit for unsupported version of kubernetes cluster if !utils.HigherThanKubernetesVersion(kubeClient.Discovery(), logging.GlobalLogger(), 1, 16, 0) { os.Exit(1) @@ -86,8 +68,8 @@ func main() { } go func() { - defer signalCancel() - <-signalCtx.Done() + defer sdown() + <-ctx.Done() }() done := make(chan struct{}) @@ -113,19 +95,19 @@ func main() { } } - if err = acquireLeader(signalCtx, kubeClient); err != nil { + if err = acquireLeader(ctx, kubeClient); err != nil { logging.V(2).Info("Failed to create lease 'kyvernopre-lock'") os.Exit(1) } // use pipeline to pass request to cleanup resources - in := gen(done, signalCtx.Done(), requests...) + in := gen(done, ctx.Done(), requests...) // process requests // processing routine count : 2 - p1 := process(client, kyvernoClient, done, signalCtx.Done(), in) - p2 := process(client, kyvernoClient, done, signalCtx.Done(), in) + p1 := process(client, kyvernoClient, done, ctx.Done(), in) + p2 := process(client, kyvernoClient, done, ctx.Done(), in) // merge results from processing routines - for err := range merge(done, signalCtx.Done(), p1, p2) { + for err := range merge(done, ctx.Done(), p1, p2) { if err != nil { failure = true logging.Error(err, "failed to cleanup resource") @@ -155,7 +137,7 @@ func main() { os.Exit(1) } - le.Run(signalCtx) + le.Run(ctx) } func acquireLeader(ctx context.Context, kubeClient kubernetes.Interface) error { diff --git a/cmd/internal/config.go b/cmd/internal/config.go index 3d46325cea..3c38338784 100644 --- a/cmd/internal/config.go +++ b/cmd/internal/config.go @@ -1,9 +1,12 @@ package internal +import "flag" + type Configuration interface { UsesTracing() bool UsesProfiling() bool UsesKubeconfig() bool + FlagSets() []*flag.FlagSet } func NewConfiguration(options ...ConfigurationOption) Configuration { @@ -34,10 +37,17 @@ func WithKubeconfig() ConfigurationOption { } } +func WithFlagSets(flagsets ...*flag.FlagSet) ConfigurationOption { + return func(c *configuration) { + c.flagSets = append(c.flagSets, flagsets...) + } +} + type configuration struct { usesTracing bool usesProfiling bool usesKubeconfig bool + flagSets []*flag.FlagSet } func (c *configuration) UsesTracing() bool { @@ -51,3 +61,7 @@ func (c *configuration) UsesProfiling() bool { func (c *configuration) UsesKubeconfig() bool { return c.usesKubeconfig } + +func (c *configuration) FlagSets() []*flag.FlagSet { + return c.flagSets +} diff --git a/cmd/internal/flag.go b/cmd/internal/flag.go index c433c40497..1c66c1e7e3 100644 --- a/cmd/internal/flag.go +++ b/cmd/internal/flag.go @@ -64,4 +64,14 @@ func InitFlags(config Configuration) { if config.UsesKubeconfig() { initKubeconfigFlags() } + for _, flagset := range config.FlagSets() { + flagset.VisitAll(func(f *flag.Flag) { + flag.CommandLine.Var(f.Value, f.Name, f.Usage) + }) + } +} + +func ParseFlags(config Configuration) { + InitFlags(config) + flag.Parse() } diff --git a/cmd/internal/setup.go b/cmd/internal/setup.go new file mode 100644 index 0000000000..8ded9f6989 --- /dev/null +++ b/cmd/internal/setup.go @@ -0,0 +1,25 @@ +package internal + +import ( + "context" + + "github.com/go-logr/logr" +) + +func shutdown(logger logr.Logger, sdowns ...context.CancelFunc) context.CancelFunc { + return func() { + for i := range sdowns { + logger.Info("shuting down...") + defer sdowns[i]() + } + } +} + +func Setup() (context.Context, logr.Logger, context.CancelFunc) { + logger := SetupLogger() + ShowVersion(logger) + sdownMaxProcs := SetupMaxProcs(logger) + SetupProfiling(logger) + ctx, sdownSignals := SetupSignals(logger) + return ctx, logger, shutdown(logger.WithName("shutdown"), sdownMaxProcs, sdownSignals) +}