diff --git a/api/v1alpha1/controllermanagerconfig_types.go b/api/v1alpha1/controllermanagerconfig_types.go index bcc37f0..a39b250 100644 --- a/api/v1alpha1/controllermanagerconfig_types.go +++ b/api/v1alpha1/controllermanagerconfig_types.go @@ -56,6 +56,9 @@ type ControllerManagerConfig struct { // SPIREServerSocketPath is the path to the SPIRE Server API socket SPIREServerSocketPath string `json:"spireServerSocketPath"` + + // LogLevel is the log level for the controller manager + LogLevel string `json:"logLevel"` } // ControllerManagerConfigurationSpec defines the desired state of GenericControllerManagerConfiguration. diff --git a/cmd/main.go b/cmd/main.go index 71fb098..17129cc 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -35,6 +35,7 @@ import ( _ "k8s.io/client-go/plugin/pkg/client/auth" "k8s.io/client-go/rest" + "go.uber.org/zap/zapcore" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" @@ -111,16 +112,8 @@ func parseConfig() (Config, error) { "Command-line flags override configuration from this file.") flag.StringVar(&spireAPISocketFlag, "spire-api-socket", "", "The path to the SPIRE API socket (deprecated; use the config file)") flag.BoolVar(&expandEnvFlag, "expand-env", false, "Expand environment variables in SPIRE Controller Manager config file") - - // Parse log flags - opts := zap.Options{ - Development: true, - } - opts.BindFlags(flag.CommandLine) flag.Parse() - ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) - // Set default values retval.ctrlConfig = spirev1alpha1.ControllerManagerConfig{ IgnoreNamespaces: []string{"kube-system", "kube-public", "spire-system"}, @@ -134,7 +127,6 @@ func parseConfig() (Config, error) { if err := spirev1alpha1.LoadOptionsFromFile(configFileFlag, scheme, &retval.options, &retval.ctrlConfig, expandEnvFlag); err != nil { return retval, fmt.Errorf("unable to load the config file: %w", err) } - for _, ignoredNamespace := range retval.ctrlConfig.IgnoreNamespaces { regex, err := regexp.Compile(ignoredNamespace) if err != nil { @@ -144,6 +136,21 @@ func parseConfig() (Config, error) { retval.ignoreNamespacesRegex = append(retval.ignoreNamespacesRegex, regex) } } + + // Parse log flags + logLevel, err := getLogLevel(retval.ctrlConfig.LogLevel) + if err != nil { + return retval, fmt.Errorf("unable to parse log level: %w", err) + } + opts := zap.Options{ + Level: logLevel, + Development: true, + } + opts.BindFlags(flag.CommandLine) + + ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) + ctrl.Log.V(0).Info("Logger configured", "level", opts.Level) + // Determine the SPIRE Server socket path switch { case retval.ctrlConfig.SPIREServerSocketPath == "" && spireAPISocketFlag == "": @@ -471,3 +478,18 @@ func parseClusterDomainCNAME(cname string) (string, error) { return clusterDomain, nil } + +func getLogLevel(logLevel string) (zapcore.Level, error) { + switch strings.ToLower(logLevel) { + case "debug": + return zapcore.DebugLevel, nil + case "warn": + return zapcore.WarnLevel, nil + case "error": + return zapcore.ErrorLevel, nil + case "info": + return zapcore.InfoLevel, nil + default: + return zapcore.InfoLevel, fmt.Errorf("invalid log level: %s", logLevel) + } +} diff --git a/demo/config/cluster1/spire/spire-controller-manager-config.yaml b/demo/config/cluster1/spire/spire-controller-manager-config.yaml index 1c0f948..bfab9d2 100644 --- a/demo/config/cluster1/spire/spire-controller-manager-config.yaml +++ b/demo/config/cluster1/spire/spire-controller-manager-config.yaml @@ -9,6 +9,7 @@ leaderElection: resourceName: 98c9c988.spiffe.io resourceNamespace: spire-system clusterName: cluster1 +logLevel: info trustDomain: cluster1.demo ignoreNamespaces: - kube-system diff --git a/demo/config/cluster2/spire/spire-controller-manager-config.yaml b/demo/config/cluster2/spire/spire-controller-manager-config.yaml index 6e24a33..4a23afe 100644 --- a/demo/config/cluster2/spire/spire-controller-manager-config.yaml +++ b/demo/config/cluster2/spire/spire-controller-manager-config.yaml @@ -9,6 +9,7 @@ leaderElection: resourceName: 98c9c988.spiffe.io resourceNamespace: spire-system clusterName: cluster2 +logLevel: info trustDomain: cluster2.demo ignoreNamespaces: - kube-system diff --git a/docs/spire-controller-manager-config.md b/docs/spire-controller-manager-config.md index 2199b61..979c90b 100644 --- a/docs/spire-controller-manager-config.md +++ b/docs/spire-controller-manager-config.md @@ -2,14 +2,17 @@ The SPIRE Controller Manager configuration is defined [here](../api/v1alpha1/controllermanagerconfig_types.go). -Beyond the standard [controller manager configuration](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/config/v1alpha1#ControllerConfigurationSpec), the following fields are defined: +Beyond the +standard [controller manager configuration](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/config/v1alpha1#ControllerConfigurationSpec), +the following fields are defined: -| Field | Required | Default | Description | -| ------------------------------------ | -------- | ------------------------------------------------ | ------------------------------------------------------------------ | -| `clusterName` | REQUIRED | | The name of the cluster | -| `trustDomain` | REQUIRED | | The trust domain name for the cluster | -| `clusterDomain` | OPTIONAL | | The domain of the cluster, ie `cluster.local`. If not specified will attempt to auto detect. | -| `ignoreNamespaces` | OPTIONAL | `["kube-system", "kube-public", "spire-system"]` | Namespaces that the controllers should ignore | -| `validatingWebhookConfigurationName` | OPTIONAL | `spire-controller-manager-webhook` | The name of the validating admission controller webhook to manage | +| Field | Required | Default | Description | +|--------------------------------------|----------|--------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `clusterName` | REQUIRED | | The name of the cluster | +| `trustDomain` | REQUIRED | | The trust domain name for the cluster | +| `clusterDomain` | OPTIONAL | | The domain of the cluster, ie `cluster.local`. If not specified will attempt to auto detect. | +| `ignoreNamespaces` | OPTIONAL | `["kube-system", "kube-public", "spire-system"]` | Namespaces that the controllers should ignore | +| `validatingWebhookConfigurationName` | OPTIONAL | `spire-controller-manager-webhook` | The name of the validating admission controller webhook to manage | | `gcInterval` | OPTIONAL | `10s` | How often the SPIRE state is reconciled when the controller is otherwise idle. This impacts how quickly SPIRE state will converge after CRDs are removed or SPIRE state is mutated underneath the controller. | -| `spireServerSocketPath` | OPTIONAL | `/spire-server/api.sock` | The path the the SPIRE Server API socket | +| `spireServerSocketPath` | OPTIONAL | `/spire-server/api.sock` | The path the the SPIRE Server API socket | +| `logLevel` | OPTIONAL | `info` | The log level for the controller manager. Supported values are `info`, `error`, `warn` and `debug`. |