1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 07:57:07 +00:00
kyverno/pkg/config/metricsconfig.go
Charles-Edouard Brétéché f9f01fc70d
chore: refactor metrics namespace check (#5489)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
2022-11-28 16:53:26 +01:00

137 lines
4.2 KiB
Go

package config
import (
"context"
"encoding/json"
"os"
"time"
"golang.org/x/exp/slices"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
// metricsConfigEnvVar is the name of an environment variable containing the name of the configmap
// that stores the information associated with Kyverno's metrics exposure
const metricsConfigEnvVar string = "METRICS_CONFIG"
// MetricsConfig stores the config for metrics
type MetricsConfiguration interface {
// GetExcludeNamespaces returns the namespaces to ignore for metrics exposure
GetExcludeNamespaces() []string
// GetIncludeNamespaces returns the namespaces to specifically consider for metrics exposure
GetIncludeNamespaces() []string
// GetMetricsRefreshInterval returns the refresh interval for the metrics
GetMetricsRefreshInterval() time.Duration
// CheckNamespace returns `true` if the namespace has to be considered
CheckNamespace(string) bool
}
type namespacesConfig struct {
IncludeNamespaces []string `json:"include,omitempty"`
ExcludeNamespaces []string `json:"exclude,omitempty"`
}
// metricsConfig stores the config for metrics
type metricsConfig struct {
namespaces namespacesConfig
metricsRefreshInterval time.Duration
}
// GetExcludeNamespaces returns the namespaces to ignore for metrics exposure
func (mcd *metricsConfig) GetExcludeNamespaces() []string {
return mcd.namespaces.ExcludeNamespaces
}
// GetIncludeNamespaces returns the namespaces to specifically consider for metrics exposure
func (mcd *metricsConfig) GetIncludeNamespaces() []string {
return mcd.namespaces.IncludeNamespaces
}
// GetMetricsRefreshInterval returns the refresh interval for the metrics
func (mcd *metricsConfig) GetMetricsRefreshInterval() time.Duration {
return mcd.metricsRefreshInterval
}
// CheckNamespace returns `true` if the namespace has to be considered
func (mcd *metricsConfig) CheckNamespace(namespace string) bool {
// TODO(eddycharly): check we actually need `"-"`
if namespace == "" || namespace == "-" {
return true
}
if slices.Contains(mcd.namespaces.ExcludeNamespaces, namespace) {
return false
}
if len(mcd.namespaces.IncludeNamespaces) == 0 {
return true
}
return slices.Contains(mcd.namespaces.IncludeNamespaces, namespace)
}
func (cd *metricsConfig) load(cm *corev1.ConfigMap) {
logger := logger.WithValues("name", cm.Name, "namespace", cm.Namespace)
if cm.Data == nil {
return
}
// reset
cd.metricsRefreshInterval = 0
cd.namespaces = namespacesConfig{
IncludeNamespaces: []string{},
ExcludeNamespaces: []string{},
}
// load metricsRefreshInterval
metricsRefreshInterval, found := cm.Data["metricsRefreshInterval"]
if found {
metricsRefreshInterval, err := time.ParseDuration(metricsRefreshInterval)
if err != nil {
logger.Error(err, "failed to parse metricsRefreshInterval")
} else {
cd.metricsRefreshInterval = metricsRefreshInterval
}
}
// load namespaces
namespaces, ok := cm.Data["namespaces"]
if ok {
namespaces, err := parseIncludeExcludeNamespacesFromNamespacesConfig(namespaces)
if err != nil {
logger.Error(err, "failed to parse namespaces")
} else {
cd.namespaces = namespaces
}
}
}
// NewDefaultMetricsConfiguration ...
func NewDefaultMetricsConfiguration() *metricsConfig {
return &metricsConfig{
metricsRefreshInterval: 0,
namespaces: namespacesConfig{
IncludeNamespaces: []string{},
ExcludeNamespaces: []string{},
},
}
}
// NewMetricsConfiguration ...
func NewMetricsConfiguration(client kubernetes.Interface) (MetricsConfiguration, error) {
configuration := NewDefaultMetricsConfiguration()
cmName := os.Getenv(metricsConfigEnvVar)
if cmName != "" {
if cm, err := client.CoreV1().ConfigMaps(kyvernoNamespace).Get(context.TODO(), cmName, metav1.GetOptions{}); err != nil {
if !errors.IsNotFound(err) {
return nil, err
}
} else {
configuration.load(cm)
}
}
return configuration, nil
}
func parseIncludeExcludeNamespacesFromNamespacesConfig(jsonStr string) (namespacesConfig, error) {
var namespacesConfigObject namespacesConfig
err := json.Unmarshal([]byte(jsonStr), &namespacesConfigObject)
return namespacesConfigObject, err
}