From 0b76e7d4f484e8eb7f71f06c66b679ab9e119d11 Mon Sep 17 00:00:00 2001 From: Lili Cosic Date: Thu, 29 Oct 2020 13:51:25 +0100 Subject: [PATCH] internal/store: Rework label allow list for label metrics --- internal/store/builder.go | 54 ++++++------ internal/store/certificatesigningrequest.go | 8 +- .../store/certificatesigningrequest_test.go | 16 ++-- internal/store/cronjob.go | 8 +- internal/store/cronjob_test.go | 10 +-- internal/store/daemonset.go | 8 +- internal/store/daemonset_test.go | 10 +-- internal/store/deployment.go | 8 +- internal/store/deployment_test.go | 8 +- internal/store/endpoint.go | 8 +- internal/store/endpoint_test.go | 82 ++++++++++++++++++- internal/store/horizontalpodautoscaler.go | 8 +- .../store/horizontalpodautoscaler_test.go | 8 +- internal/store/ingress.go | 8 +- internal/store/ingress_test.go | 10 +-- internal/store/job.go | 8 +- internal/store/job_test.go | 12 +-- .../store/mutatingwebhookconfiguration.go | 1 - internal/store/namespace.go | 8 +- internal/store/namespace_test.go | 8 +- internal/store/networkpolicy.go | 8 +- internal/store/networkpolicy_test.go | 2 +- internal/store/node.go | 8 +- internal/store/node_test.go | 6 +- internal/store/persistentvolume.go | 8 +- internal/store/persistentvolume_test.go | 6 +- internal/store/persistentvolumeclaim.go | 8 +- internal/store/persistentvolumeclaim_test.go | 6 +- internal/store/pod.go | 44 +++++----- internal/store/pod_test.go | 8 +- internal/store/replicaset.go | 10 ++- internal/store/replicaset_test.go | 8 +- internal/store/secret.go | 9 +- internal/store/secret_test.go | 6 +- internal/store/service.go | 9 +- internal/store/service_test.go | 16 ++-- internal/store/statefulset.go | 9 +- internal/store/statefulset_test.go | 10 +-- internal/store/storageclass.go | 8 +- internal/store/storageclass_test.go | 6 +- internal/store/utils.go | 25 ++++-- .../store/validatingwebhookconfiguration.go | 1 - internal/store/verticalpodautoscaler.go | 8 +- internal/store/verticalpodautoscaler_test.go | 6 +- pkg/options/types.go | 22 ++++- 45 files changed, 338 insertions(+), 210 deletions(-) diff --git a/internal/store/builder.go b/internal/store/builder.go index a6129892cc..87b4590c36 100644 --- a/internal/store/builder.go +++ b/internal/store/builder.go @@ -63,7 +63,7 @@ type Builder struct { shard int32 totalShards int buildStoreFunc ksmtypes.BuildStoreFunc - allowLabels ksmtypes.AllowLabels + allowLabelsList map[string][]string } // NewBuilder returns a new builder. @@ -138,7 +138,9 @@ func (b *Builder) DefaultGenerateStoreFunc() ksmtypes.BuildStoreFunc { // WithAllowLabels configures which labels can be returned for metrics func (b *Builder) WithAllowLabels(labels map[string][]string) { - b.allowLabels = sanitizeAllowLabels(labels) + if len(labels) > 0 { + b.allowLabelsList = labels + } } // Build initializes and registers all enabled stores. @@ -214,31 +216,31 @@ func (b *Builder) buildConfigMapStore() cache.Store { } func (b *Builder) buildCronJobStore() cache.Store { - return b.buildStoreFunc(cronJobMetricFamilies, &batchv1beta1.CronJob{}, createCronJobListWatch) + return b.buildStoreFunc(cronJobMetricFamilies(b.allowLabelsList["cronjobs"]), &batchv1beta1.CronJob{}, createCronJobListWatch) } func (b *Builder) buildDaemonSetStore() cache.Store { - return b.buildStoreFunc(daemonSetMetricFamilies, &appsv1.DaemonSet{}, createDaemonSetListWatch) + return b.buildStoreFunc(daemonSetMetricFamilies(b.allowLabelsList["daemonsets"]), &appsv1.DaemonSet{}, createDaemonSetListWatch) } func (b *Builder) buildDeploymentStore() cache.Store { - return b.buildStoreFunc(deploymentMetricFamilies, &appsv1.Deployment{}, createDeploymentListWatch) + return b.buildStoreFunc(deploymentMetricFamilies(b.allowLabelsList["deployments"]), &appsv1.Deployment{}, createDeploymentListWatch) } func (b *Builder) buildEndpointsStore() cache.Store { - return b.buildStoreFunc(endpointMetricFamilies, &v1.Endpoints{}, createEndpointsListWatch) + return b.buildStoreFunc(endpointMetricFamilies(b.allowLabelsList["endpoints"]), &v1.Endpoints{}, createEndpointsListWatch) } func (b *Builder) buildHPAStore() cache.Store { - return b.buildStoreFunc(hpaMetricFamilies, &autoscaling.HorizontalPodAutoscaler{}, createHPAListWatch) + return b.buildStoreFunc(hpaMetricFamilies(b.allowLabelsList["horizontalpodautoscalers"]), &autoscaling.HorizontalPodAutoscaler{}, createHPAListWatch) } func (b *Builder) buildIngressStore() cache.Store { - return b.buildStoreFunc(ingressMetricFamilies, &networkingv1.Ingress{}, createIngressListWatch) + return b.buildStoreFunc(ingressMetricFamilies(b.allowLabelsList["ingresses"]), &networkingv1.Ingress{}, createIngressListWatch) } func (b *Builder) buildJobStore() cache.Store { - return b.buildStoreFunc(jobMetricFamilies, &batchv1.Job{}, createJobListWatch) + return b.buildStoreFunc(jobMetricFamilies(b.allowLabelsList["jobs"]), &batchv1.Job{}, createJobListWatch) } func (b *Builder) buildLimitRangeStore() cache.Store { @@ -250,23 +252,23 @@ func (b *Builder) buildMutatingWebhookConfigurationStore() cache.Store { } func (b *Builder) buildNamespaceStore() cache.Store { - return b.buildStoreFunc(namespaceMetricFamilies, &v1.Namespace{}, createNamespaceListWatch) + return b.buildStoreFunc(namespaceMetricFamilies(b.allowLabelsList["namespaces"]), &v1.Namespace{}, createNamespaceListWatch) } func (b *Builder) buildNetworkPolicyStore() cache.Store { - return b.buildStoreFunc(networkpolicyMetricFamilies, &networkingv1.NetworkPolicy{}, createNetworkPolicyListWatch) + return b.buildStoreFunc(networkPolicyMetricFamilies(b.allowLabelsList["networkpolicies"]), &networkingv1.NetworkPolicy{}, createNetworkPolicyListWatch) } func (b *Builder) buildNodeStore() cache.Store { - return b.buildStoreFunc(nodeMetricFamilies, &v1.Node{}, createNodeListWatch) + return b.buildStoreFunc(nodeMetricFamilies(b.allowLabelsList["nodes"]), &v1.Node{}, createNodeListWatch) } func (b *Builder) buildPersistentVolumeClaimStore() cache.Store { - return b.buildStoreFunc(persistentVolumeClaimMetricFamilies, &v1.PersistentVolumeClaim{}, createPersistentVolumeClaimListWatch) + return b.buildStoreFunc(persistentVolumeClaimMetricFamilies(b.allowLabelsList["persistentvolumeclaims"]), &v1.PersistentVolumeClaim{}, createPersistentVolumeClaimListWatch) } func (b *Builder) buildPersistentVolumeStore() cache.Store { - return b.buildStoreFunc(persistentVolumeMetricFamilies, &v1.PersistentVolume{}, createPersistentVolumeListWatch) + return b.buildStoreFunc(persistentVolumeMetricFamilies(b.allowLabelsList["persistentvolumes"]), &v1.PersistentVolume{}, createPersistentVolumeListWatch) } func (b *Builder) buildPodDisruptionBudgetStore() cache.Store { @@ -274,7 +276,7 @@ func (b *Builder) buildPodDisruptionBudgetStore() cache.Store { } func (b *Builder) buildReplicaSetStore() cache.Store { - return b.buildStoreFunc(replicaSetMetricFamilies, &appsv1.ReplicaSet{}, createReplicaSetListWatch) + return b.buildStoreFunc(replicaSetMetricFamilies(b.allowLabelsList["replicasets"]), &appsv1.ReplicaSet{}, createReplicaSetListWatch) } func (b *Builder) buildReplicationControllerStore() cache.Store { @@ -286,27 +288,27 @@ func (b *Builder) buildResourceQuotaStore() cache.Store { } func (b *Builder) buildSecretStore() cache.Store { - return b.buildStoreFunc(secretMetricFamilies, &v1.Secret{}, createSecretListWatch) + return b.buildStoreFunc(secretMetricFamilies(b.allowLabelsList["secrets"]), &v1.Secret{}, createSecretListWatch) } func (b *Builder) buildServiceStore() cache.Store { - return b.buildStoreFunc(serviceMetricFamilies, &v1.Service{}, createServiceListWatch) + return b.buildStoreFunc(serviceMetricFamilies(b.allowLabelsList["services"]), &v1.Service{}, createServiceListWatch) } func (b *Builder) buildStatefulSetStore() cache.Store { - return b.buildStoreFunc(statefulSetMetricFamilies, &appsv1.StatefulSet{}, createStatefulSetListWatch) + return b.buildStoreFunc(statefulSetMetricFamilies(b.allowLabelsList["statefulsets"]), &appsv1.StatefulSet{}, createStatefulSetListWatch) } func (b *Builder) buildStorageClassStore() cache.Store { - return b.buildStoreFunc(storageClassMetricFamilies, &storagev1.StorageClass{}, createStorageClassListWatch) + return b.buildStoreFunc(storageClassMetricFamilies(b.allowLabelsList["storageclasses"]), &storagev1.StorageClass{}, createStorageClassListWatch) } func (b *Builder) buildPodStore() cache.Store { - return b.buildStoreFunc(podMetricFamilies, &v1.Pod{}, createPodListWatch) + return b.buildStoreFunc(podMetricFamilies(b.allowLabelsList["pods"]), &v1.Pod{}, createPodListWatch) } func (b *Builder) buildCsrStore() cache.Store { - return b.buildStoreFunc(csrMetricFamilies, &certv1.CertificateSigningRequest{}, createCSRListWatch) + return b.buildStoreFunc(csrMetricFamilies(b.allowLabelsList["certificatesigningrequests"]), &certv1.CertificateSigningRequest{}, createCSRListWatch) } func (b *Builder) buildValidatingWebhookConfigurationStore() cache.Store { @@ -318,7 +320,7 @@ func (b *Builder) buildVolumeAttachmentStore() cache.Store { } func (b *Builder) buildVPAStore() cache.Store { - return b.buildStoreFunc(vpaMetricFamilies, &vpaautoscaling.VerticalPodAutoscaler{}, createVPAListWatchFunc(b.vpaClient)) + return b.buildStoreFunc(vpaMetricFamilies(b.allowLabelsList["verticalpodautoscalers"]), &vpaautoscaling.VerticalPodAutoscaler{}, createVPAListWatchFunc(b.vpaClient)) } func (b *Builder) buildLeases() cache.Store { @@ -330,11 +332,9 @@ func (b *Builder) buildStore( expectedType interface{}, listWatchFunc func(kubeClient clientset.Interface, ns string) cache.ListerWatcher, ) cache.Store { - filteredMetricFamilies := generator.FilterMetricFamilies(b.allowDenyList, metricFamilies) - filteredMetricFamiliesLabels := generator.FilterMetricFamiliesLabels(b.allowLabels, filteredMetricFamilies) - composedMetricGenFuncs := generator.ComposeMetricGenFuncs(filteredMetricFamiliesLabels) - - familyHeaders := generator.ExtractMetricFamilyHeaders(filteredMetricFamiliesLabels) + metricFamilies = generator.FilterMetricFamilies(b.allowDenyList, metricFamilies) + composedMetricGenFuncs := generator.ComposeMetricGenFuncs(metricFamilies) + familyHeaders := generator.ExtractMetricFamilyHeaders(metricFamilies) store := metricsstore.NewMetricsStore( familyHeaders, diff --git a/internal/store/certificatesigningrequest.go b/internal/store/certificatesigningrequest.go index 8e86a41880..02452b013d 100644 --- a/internal/store/certificatesigningrequest.go +++ b/internal/store/certificatesigningrequest.go @@ -34,15 +34,17 @@ var ( descCSRLabelsName = "kube_certificatesigningrequest_labels" descCSRLabelsHelp = "Kubernetes labels converted to Prometheus labels." descCSRLabelsDefaultLabels = []string{"certificatesigningrequest"} +) - csrMetricFamilies = []generator.FamilyGenerator{ +func csrMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( descCSRLabelsName, descCSRLabelsHelp, metric.Gauge, "", wrapCSRFunc(func(j *certv1.CertificateSigningRequest) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(j.Labels) + labelKeys, labelValues := createLabelKeysValues(j.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -103,7 +105,7 @@ var ( }), ), } -) +} func wrapCSRFunc(f func(*certv1.CertificateSigningRequest) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/certificatesigningrequest_test.go b/internal/store/certificatesigningrequest_test.go index d041350880..5e5e7ec3c7 100644 --- a/internal/store/certificatesigningrequest_test.go +++ b/internal/store/certificatesigningrequest_test.go @@ -55,7 +55,7 @@ func TestCsrStore(t *testing.T) { kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test"} 1.5e+09 kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="approved"} 0 kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="denied"} 0 - kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",label_cert="test"} 1 + kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test"} 1 kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test"} 0 `, MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"}, @@ -83,7 +83,7 @@ func TestCsrStore(t *testing.T) { kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test"} 1.5e+09 kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="approved"} 0 kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="denied"} 1 - kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",label_cert="test"} 1 + kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test"} 1 kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test"} 0 `, MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"}, @@ -111,7 +111,7 @@ func TestCsrStore(t *testing.T) { kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test"} 1.5e+09 kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="approved"} 1 kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="denied"} 0 - kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",label_cert="test"} 1 + kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test"} 1 kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test"} 0 `, MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"}, @@ -139,7 +139,7 @@ func TestCsrStore(t *testing.T) { kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test"} 1.5e+09 kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="approved"} 1 kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="denied"} 0 - kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",label_cert="test"} 1 + kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test"} 1 kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test"} 13 `, MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"}, @@ -169,7 +169,7 @@ func TestCsrStore(t *testing.T) { kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test"} 1.5e+09 kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="approved"} 1 kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="denied"} 1 - kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",label_cert="test"} 1 + kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test"} 1 kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test"} 0 `, MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"}, @@ -205,15 +205,15 @@ func TestCsrStore(t *testing.T) { kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test"} 1.5e+09 kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="approved"} 2 kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="denied"} 2 - kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",label_cert="test"} 1 + kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test"} 1 kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test"} 0 `, MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"}, }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(csrMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(csrMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(csrMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(csrMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected error when collecting result in %vth run:\n%s", i, err) } diff --git a/internal/store/cronjob.go b/internal/store/cronjob.go index a50ff7dad5..8c6d714cc2 100644 --- a/internal/store/cronjob.go +++ b/internal/store/cronjob.go @@ -37,15 +37,17 @@ var ( descCronJobLabelsName = "kube_cronjob_labels" descCronJobLabelsHelp = "Kubernetes labels converted to Prometheus labels." descCronJobLabelsDefaultLabels = []string{"namespace", "cronjob"} +) - cronJobMetricFamilies = []generator.FamilyGenerator{ +func cronJobMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( descCronJobLabelsName, descCronJobLabelsHelp, metric.Gauge, "", wrapCronJobFunc(func(j *batchv1beta1.CronJob) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(j.Labels) + labelKeys, labelValues := createLabelKeysValues(j.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -201,7 +203,7 @@ var ( }), ), } -) +} func wrapCronJobFunc(f func(*batchv1beta1.CronJob) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/cronjob_test.go b/internal/store/cronjob_test.go index e76e8782d9..e379da508d 100644 --- a/internal/store/cronjob_test.go +++ b/internal/store/cronjob_test.go @@ -139,7 +139,7 @@ func TestCronJobStore(t *testing.T) { # TYPE kube_cronjob_status_active gauge # TYPE kube_cronjob_status_last_schedule_time gauge kube_cronjob_info{concurrency_policy="Forbid",cronjob="ActiveRunningCronJob1",namespace="ns1",schedule="0 */6 * * *"} 1 - kube_cronjob_labels{cronjob="ActiveRunningCronJob1",label_app="example-active-running-1",namespace="ns1"} 1 + kube_cronjob_labels{cronjob="ActiveRunningCronJob1",namespace="ns1"} 1 kube_cronjob_spec_starting_deadline_seconds{cronjob="ActiveRunningCronJob1",namespace="ns1"} 300 kube_cronjob_spec_suspend{cronjob="ActiveRunningCronJob1",namespace="ns1"} 0 kube_cronjob_status_active{cronjob="ActiveRunningCronJob1",namespace="ns1"} 2 @@ -185,7 +185,7 @@ func TestCronJobStore(t *testing.T) { # TYPE kube_cronjob_status_active gauge # TYPE kube_cronjob_status_last_schedule_time gauge kube_cronjob_info{concurrency_policy="Forbid",cronjob="SuspendedCronJob1",namespace="ns1",schedule="0 */3 * * *"} 1 - kube_cronjob_labels{cronjob="SuspendedCronJob1",label_app="example-suspended-1",namespace="ns1"} 1 + kube_cronjob_labels{cronjob="SuspendedCronJob1",namespace="ns1"} 1 kube_cronjob_spec_starting_deadline_seconds{cronjob="SuspendedCronJob1",namespace="ns1"} 300 kube_cronjob_spec_suspend{cronjob="SuspendedCronJob1",namespace="ns1"} 1 kube_cronjob_status_active{cronjob="SuspendedCronJob1",namespace="ns1"} 0 @@ -235,7 +235,7 @@ func TestCronJobStore(t *testing.T) { kube_cronjob_spec_suspend{cronjob="ActiveCronJob1NoLastScheduled",namespace="ns1"} 0 kube_cronjob_info{concurrency_policy="Forbid",cronjob="ActiveCronJob1NoLastScheduled",namespace="ns1",schedule="25 * * * *"} 1 kube_cronjob_created{cronjob="ActiveCronJob1NoLastScheduled",namespace="ns1"} 1.520766296e+09 - kube_cronjob_labels{cronjob="ActiveCronJob1NoLastScheduled",label_app="example-active-no-last-scheduled-1",namespace="ns1"} 1 + kube_cronjob_labels{cronjob="ActiveCronJob1NoLastScheduled",namespace="ns1"} 1 ` + fmt.Sprintf("kube_cronjob_next_schedule_time{cronjob=\"ActiveCronJob1NoLastScheduled\",namespace=\"ns1\"} %ve+09\n", float64(ActiveCronJob1NoLastScheduledNextScheduleTime.Unix())/math.Pow10(9)), @@ -243,8 +243,8 @@ func TestCronJobStore(t *testing.T) { }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(cronJobMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(cronJobMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(cronJobMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(cronJobMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } diff --git a/internal/store/daemonset.go b/internal/store/daemonset.go index de1bb9a4a1..fc5886263b 100644 --- a/internal/store/daemonset.go +++ b/internal/store/daemonset.go @@ -34,8 +34,10 @@ var ( descDaemonSetLabelsName = "kube_daemonset_labels" descDaemonSetLabelsHelp = "Kubernetes labels converted to Prometheus labels." descDaemonSetLabelsDefaultLabels = []string{"namespace", "daemonset"} +) - daemonSetMetricFamilies = []generator.FamilyGenerator{ +func daemonSetMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( "kube_daemonset_created", "Unix creation timestamp", @@ -214,7 +216,7 @@ var ( metric.Gauge, "", wrapDaemonSetFunc(func(d *v1.DaemonSet) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(d.ObjectMeta.Labels) + labelKeys, labelValues := createLabelKeysValues(d.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -227,7 +229,7 @@ var ( }), ), } -) +} func wrapDaemonSetFunc(f func(*v1.DaemonSet) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/daemonset_test.go b/internal/store/daemonset_test.go index e975ada64c..20709f7ae6 100644 --- a/internal/store/daemonset_test.go +++ b/internal/store/daemonset_test.go @@ -76,7 +76,7 @@ func TestDaemonSetStore(t *testing.T) { kube_daemonset_status_number_unavailable{daemonset="ds1",namespace="ns1"} 0 kube_daemonset_status_observed_generation{daemonset="ds1",namespace="ns1"} 2 kube_daemonset_status_updated_number_scheduled{daemonset="ds1",namespace="ns1"} 0 - kube_daemonset_labels{daemonset="ds1",label_app="example1",namespace="ns1"} 1 + kube_daemonset_labels{daemonset="ds1",namespace="ns1"} 1 `, MetricNames: []string{ "kube_daemonset_labels", @@ -138,7 +138,7 @@ func TestDaemonSetStore(t *testing.T) { kube_daemonset_status_number_ready{daemonset="ds2",namespace="ns2"} 0 kube_daemonset_status_number_unavailable{daemonset="ds2",namespace="ns2"} 0 kube_daemonset_status_updated_number_scheduled{daemonset="ds2",namespace="ns2"} 0 - kube_daemonset_labels{daemonset="ds2",label_app="example2",namespace="ns2"} 1 + kube_daemonset_labels{daemonset="ds2",namespace="ns2"} 1 kube_daemonset_created{namespace="ns2",daemonset="ds2"} 1.5e+09 `, MetricNames: []string{ @@ -205,7 +205,7 @@ func TestDaemonSetStore(t *testing.T) { kube_daemonset_status_number_ready{daemonset="ds3",namespace="ns3"} 5 kube_daemonset_status_number_unavailable{daemonset="ds3",namespace="ns3"} 5 kube_daemonset_status_updated_number_scheduled{daemonset="ds3",namespace="ns3"} 5 - kube_daemonset_labels{daemonset="ds3",label_app="example3",namespace="ns3"} 1 + kube_daemonset_labels{daemonset="ds3",namespace="ns3"} 1 `, MetricNames: []string{ "kube_daemonset_created", @@ -222,8 +222,8 @@ func TestDaemonSetStore(t *testing.T) { }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(daemonSetMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(daemonSetMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(daemonSetMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(daemonSetMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } diff --git a/internal/store/deployment.go b/internal/store/deployment.go index 97ecbd9e64..41d17f55c8 100644 --- a/internal/store/deployment.go +++ b/internal/store/deployment.go @@ -35,8 +35,10 @@ var ( descDeploymentLabelsName = "kube_deployment_labels" descDeploymentLabelsHelp = "Kubernetes labels converted to Prometheus labels." descDeploymentLabelsDefaultLabels = []string{"namespace", "deployment"} +) - deploymentMetricFamilies = []generator.FamilyGenerator{ +func deploymentMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( "kube_deployment_created", "Unix creation timestamp", @@ -255,7 +257,7 @@ var ( metric.Gauge, "", wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(d.Labels) + labelKeys, labelValues := createLabelKeysValues(d.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -268,7 +270,7 @@ var ( }), ), } -) +} func wrapDeploymentFunc(f func(*v1.Deployment) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/deployment_test.go b/internal/store/deployment_test.go index 2e49f4da15..c4b246fbd6 100644 --- a/internal/store/deployment_test.go +++ b/internal/store/deployment_test.go @@ -105,7 +105,7 @@ func TestDeploymentStore(t *testing.T) { }, Want: metadata + ` kube_deployment_created{deployment="depl1",namespace="ns1"} 1.5e+09 - kube_deployment_labels{deployment="depl1",label_app="example1",namespace="ns1"} 1 + kube_deployment_labels{deployment="depl1",namespace="ns1"} 1 kube_deployment_metadata_generation{deployment="depl1",namespace="ns1"} 21 kube_deployment_spec_paused{deployment="depl1",namespace="ns1"} 0 kube_deployment_spec_replicas{deployment="depl1",namespace="ns1"} 200 @@ -158,7 +158,7 @@ func TestDeploymentStore(t *testing.T) { }, }, Want: metadata + ` - kube_deployment_labels{deployment="depl2",label_app="example2",namespace="ns2"} 1 + kube_deployment_labels{deployment="depl2",namespace="ns2"} 1 kube_deployment_metadata_generation{deployment="depl2",namespace="ns2"} 14 kube_deployment_spec_paused{deployment="depl2",namespace="ns2"} 1 kube_deployment_spec_replicas{deployment="depl2",namespace="ns2"} 5 @@ -183,8 +183,8 @@ func TestDeploymentStore(t *testing.T) { } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(deploymentMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(deploymentMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(deploymentMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(deploymentMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } diff --git a/internal/store/endpoint.go b/internal/store/endpoint.go index 1ceee2dda2..f86ee654a0 100644 --- a/internal/store/endpoint.go +++ b/internal/store/endpoint.go @@ -34,8 +34,10 @@ var ( descEndpointLabelsName = "kube_endpoint_labels" descEndpointLabelsHelp = "Kubernetes labels converted to Prometheus labels." descEndpointLabelsDefaultLabels = []string{"namespace", "endpoint"} +) - endpointMetricFamilies = []generator.FamilyGenerator{ +func endpointMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( "kube_endpoint_info", "Information about endpoint.", @@ -77,7 +79,7 @@ var ( metric.Gauge, "", wrapEndpointFunc(func(e *v1.Endpoints) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(e.Labels) + labelKeys, labelValues := createLabelKeysValues(e.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -129,7 +131,7 @@ var ( }), ), } -) +} func wrapEndpointFunc(f func(*v1.Endpoints) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/endpoint_test.go b/internal/store/endpoint_test.go index 5db734fd26..b1033ff93f 100644 --- a/internal/store/endpoint_test.go +++ b/internal/store/endpoint_test.go @@ -27,6 +27,81 @@ import ( ) func TestEndpointStore(t *testing.T) { + // Fixed metadata on type and help text. We prepend this to every expected + // output so we only have to modify a single place when doing adjustments. + const metadata = ` + # HELP kube_endpoint_address_available Number of addresses available in endpoint. + # TYPE kube_endpoint_address_available gauge + # HELP kube_endpoint_address_not_ready Number of addresses not ready in endpoint + # TYPE kube_endpoint_address_not_ready gauge + # HELP kube_endpoint_created Unix creation timestamp + # TYPE kube_endpoint_created gauge + # HELP kube_endpoint_info Information about endpoint. + # TYPE kube_endpoint_info gauge + # HELP kube_endpoint_labels Kubernetes labels converted to Prometheus labels. + # TYPE kube_endpoint_labels gauge + ` + cases := []generateMetricsTestCase{ + { + Obj: &v1.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-endpoint", + CreationTimestamp: metav1.Time{Time: time.Unix(1500000000, 0)}, + Namespace: "default", + Labels: map[string]string{ + "app": "foobar", + }, + }, + Subsets: []v1.EndpointSubset{ + {Addresses: []v1.EndpointAddress{ + {IP: "127.0.0.1"}, {IP: "10.0.0.1"}, + }, + Ports: []v1.EndpointPort{ + {Port: 8080}, {Port: 8081}, + }, + }, + {Addresses: []v1.EndpointAddress{ + {IP: "172.22.23.202"}, + }, + Ports: []v1.EndpointPort{ + {Port: 8443}, {Port: 9090}, + }, + }, + {NotReadyAddresses: []v1.EndpointAddress{ + {IP: "192.168.1.1"}, + }, + Ports: []v1.EndpointPort{ + {Port: 1234}, {Port: 5678}, + }, + }, + {NotReadyAddresses: []v1.EndpointAddress{ + {IP: "192.168.1.3"}, {IP: "192.168.2.2"}, + }, + Ports: []v1.EndpointPort{ + {Port: 1234}, {Port: 5678}, + }, + }, + }, + }, + Want: metadata + ` + kube_endpoint_address_available{endpoint="test-endpoint",namespace="default"} 6 + kube_endpoint_address_not_ready{endpoint="test-endpoint",namespace="default"} 6 + kube_endpoint_created{endpoint="test-endpoint",namespace="default"} 1.5e+09 + kube_endpoint_info{endpoint="test-endpoint",namespace="default"} 1 + kube_endpoint_labels{endpoint="test-endpoint",namespace="default"} 1 + `, + }, + } + for i, c := range cases { + c.Func = generator.ComposeMetricGenFuncs(endpointMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(endpointMetricFamilies(nil)) + if err := c.run(); err != nil { + t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) + } + } +} + +func TestEndpointStoreWithLabels(t *testing.T) { // Fixed metadata on type and help text. We prepend this to every expected // output so we only have to modify a single place when doing adjustments. const metadata = ` @@ -93,8 +168,11 @@ func TestEndpointStore(t *testing.T) { }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(endpointMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(endpointMetricFamilies) + allowLabels := []string{ + "app", + } + c.Func = generator.ComposeMetricGenFuncs(endpointMetricFamilies(allowLabels)) + c.Headers = generator.ExtractMetricFamilyHeaders(endpointMetricFamilies(allowLabels)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } diff --git a/internal/store/horizontalpodautoscaler.go b/internal/store/horizontalpodautoscaler.go index 2822105827..55af5bcfb0 100644 --- a/internal/store/horizontalpodautoscaler.go +++ b/internal/store/horizontalpodautoscaler.go @@ -50,8 +50,10 @@ var ( descHorizontalPodAutoscalerLabelsDefaultLabels = []string{"namespace", "horizontalpodautoscaler"} targetMetricLabels = []string{"metric_name", "metric_target_type"} +) - hpaMetricFamilies = []generator.FamilyGenerator{ +func hpaMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( "kube_horizontalpodautoscaler_metadata_generation", "The generation observed by the HorizontalPodAutoscaler controller.", @@ -196,7 +198,7 @@ var ( metric.Gauge, "", wrapHPAFunc(func(a *autoscaling.HorizontalPodAutoscaler) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(a.Labels) + labelKeys, labelValues := createLabelKeysValues(a.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -233,7 +235,7 @@ var ( }), ), } -) +} func wrapHPAFunc(f func(*autoscaling.HorizontalPodAutoscaler) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/horizontalpodautoscaler_test.go b/internal/store/horizontalpodautoscaler_test.go index 89475738f3..09e20ba468 100644 --- a/internal/store/horizontalpodautoscaler_test.go +++ b/internal/store/horizontalpodautoscaler_test.go @@ -157,7 +157,7 @@ func TestHPAStore(t *testing.T) { }, }, Want: metadata + ` - kube_horizontalpodautoscaler_labels{horizontalpodautoscaler="hpa1",label_app="foobar",namespace="ns1"} 1 + kube_horizontalpodautoscaler_labels{horizontalpodautoscaler="hpa1",namespace="ns1"} 1 kube_horizontalpodautoscaler_metadata_generation{horizontalpodautoscaler="hpa1",namespace="ns1"} 2 kube_horizontalpodautoscaler_spec_max_replicas{horizontalpodautoscaler="hpa1",namespace="ns1"} 4 kube_horizontalpodautoscaler_spec_min_replicas{horizontalpodautoscaler="hpa1",namespace="ns1"} 2 @@ -282,7 +282,7 @@ func TestHPAStore(t *testing.T) { }, }, Want: metadata + ` - kube_horizontalpodautoscaler_labels{horizontalpodautoscaler="hpa2",label_app="foobar",namespace="ns1"} 1 + kube_horizontalpodautoscaler_labels{horizontalpodautoscaler="hpa2",namespace="ns1"} 1 kube_horizontalpodautoscaler_metadata_generation{horizontalpodautoscaler="hpa2",namespace="ns1"} 2 kube_horizontalpodautoscaler_spec_max_replicas{horizontalpodautoscaler="hpa2",namespace="ns1"} 4 kube_horizontalpodautoscaler_spec_min_replicas{horizontalpodautoscaler="hpa2",namespace="ns1"} 2 @@ -309,8 +309,8 @@ func TestHPAStore(t *testing.T) { }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(hpaMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(hpaMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(hpaMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(hpaMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } diff --git a/internal/store/ingress.go b/internal/store/ingress.go index d8e52e563c..85c0b001ee 100644 --- a/internal/store/ingress.go +++ b/internal/store/ingress.go @@ -35,8 +35,10 @@ var ( descIngressLabelsName = "kube_ingress_labels" descIngressLabelsHelp = "Kubernetes labels converted to Prometheus labels." descIngressLabelsDefaultLabels = []string{"namespace", "ingress"} +) - ingressMetricFamilies = []generator.FamilyGenerator{ +func ingressMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( "kube_ingress_info", "Information about ingress.", @@ -57,7 +59,7 @@ var ( metric.Gauge, "", wrapIngressFunc(func(i *networkingv1.Ingress) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(i.Labels) + labelKeys, labelValues := createLabelKeysValues(i.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -144,7 +146,7 @@ var ( }), ), } -) +} func wrapIngressFunc(f func(*networkingv1.Ingress) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/ingress_test.go b/internal/store/ingress_test.go index 191881f371..790c04807d 100644 --- a/internal/store/ingress_test.go +++ b/internal/store/ingress_test.go @@ -91,7 +91,7 @@ func TestIngressStore(t *testing.T) { Want: metadata + ` kube_ingress_info{namespace="ns3",ingress="ingress3"} 1 kube_ingress_created{namespace="ns3",ingress="ingress3"} 1.501569018e+09 - kube_ingress_labels{label_test_3="test-3",namespace="ns3",ingress="ingress3"} 1 + kube_ingress_labels{namespace="ns3",ingress="ingress3"} 1 `, MetricNames: []string{"kube_ingress_info", "kube_ingress_metadata_resource_version", "kube_ingress_created", "kube_ingress_labels", "kube_ingress_path", "kube_ingress_tls"}, }, @@ -135,7 +135,7 @@ func TestIngressStore(t *testing.T) { Want: metadata + ` kube_ingress_info{namespace="ns4",ingress="ingress4"} 1 kube_ingress_created{namespace="ns4",ingress="ingress4"} 1.501569018e+09 - kube_ingress_labels{label_test_4="test-4",namespace="ns4",ingress="ingress4"} 1 + kube_ingress_labels{namespace="ns4",ingress="ingress4"} 1 kube_ingress_path{namespace="ns4",ingress="ingress4",host="somehost",path="/somepath",service_name="someservice",service_port="1234"} 1 `, MetricNames: []string{"kube_ingress_info", "kube_ingress_metadata_resource_version", "kube_ingress_created", "kube_ingress_labels", "kube_ingress_path", "kube_ingress_tls"}, @@ -161,7 +161,7 @@ func TestIngressStore(t *testing.T) { Want: metadata + ` kube_ingress_info{namespace="ns5",ingress="ingress5"} 1 kube_ingress_created{namespace="ns5",ingress="ingress5"} 1.501569018e+09 - kube_ingress_labels{label_test_5="test-5",namespace="ns5",ingress="ingress5"} 1 + kube_ingress_labels{namespace="ns5",ingress="ingress5"} 1 kube_ingress_tls{namespace="ns5",ingress="ingress5",tls_host="somehost1",secret="somesecret"} 1 kube_ingress_tls{namespace="ns5",ingress="ingress5",tls_host="somehost2",secret="somesecret"} 1 `, @@ -169,8 +169,8 @@ func TestIngressStore(t *testing.T) { }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(ingressMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(ingressMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(ingressMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(ingressMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } diff --git a/internal/store/job.go b/internal/store/job.go index 2807dc6beb..5cf2ab74b6 100644 --- a/internal/store/job.go +++ b/internal/store/job.go @@ -36,15 +36,17 @@ var ( descJobLabelsHelp = "Kubernetes labels converted to Prometheus labels." descJobLabelsDefaultLabels = []string{"namespace", "job_name"} jobFailureReasons = []string{"BackoffLimitExceeded", "DeadLineExceeded", "Evicted"} +) - jobMetricFamilies = []generator.FamilyGenerator{ +func jobMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( descJobLabelsName, descJobLabelsHelp, metric.Gauge, "", wrapJobFunc(func(j *v1batch.Job) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(j.Labels) + labelKeys, labelValues := createLabelKeysValues(j.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -356,7 +358,7 @@ var ( }), ), } -) +} func wrapJobFunc(f func(*v1batch.Job) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/job_test.go b/internal/store/job_test.go index da2dca1c91..c81de4f15a 100644 --- a/internal/store/job_test.go +++ b/internal/store/job_test.go @@ -113,7 +113,7 @@ func TestJobStore(t *testing.T) { kube_job_owner{job_name="RunningJob1",namespace="ns1",owner_is_controller="true",owner_kind="CronJob",owner_name="cronjob-name"} 1 kube_job_created{job_name="RunningJob1",namespace="ns1"} 1.5e+09 kube_job_info{job_name="RunningJob1",namespace="ns1"} 1 - kube_job_labels{job_name="RunningJob1",label_app="example-running-1",namespace="ns1"} 1 + kube_job_labels{job_name="RunningJob1",namespace="ns1"} 1 kube_job_spec_active_deadline_seconds{job_name="RunningJob1",namespace="ns1"} 900 kube_job_spec_completions{job_name="RunningJob1",namespace="ns1"} 1 kube_job_spec_parallelism{job_name="RunningJob1",namespace="ns1"} 1 @@ -155,7 +155,7 @@ func TestJobStore(t *testing.T) { kube_job_complete{condition="true",job_name="SuccessfulJob1",namespace="ns1"} 1 kube_job_complete{condition="unknown",job_name="SuccessfulJob1",namespace="ns1"} 0 kube_job_info{job_name="SuccessfulJob1",namespace="ns1"} 1 - kube_job_labels{job_name="SuccessfulJob1",label_app="example-successful-1",namespace="ns1"} 1 + kube_job_labels{job_name="SuccessfulJob1",namespace="ns1"} 1 kube_job_spec_active_deadline_seconds{job_name="SuccessfulJob1",namespace="ns1"} 900 kube_job_spec_completions{job_name="SuccessfulJob1",namespace="ns1"} 1 kube_job_spec_parallelism{job_name="SuccessfulJob1",namespace="ns1"} 1 @@ -198,7 +198,7 @@ func TestJobStore(t *testing.T) { kube_job_failed{condition="true",job_name="FailedJob1",namespace="ns1"} 1 kube_job_failed{condition="unknown",job_name="FailedJob1",namespace="ns1"} 0 kube_job_info{job_name="FailedJob1",namespace="ns1"} 1 - kube_job_labels{job_name="FailedJob1",label_app="example-failed-1",namespace="ns1"} 1 + kube_job_labels{job_name="FailedJob1",namespace="ns1"} 1 kube_job_spec_active_deadline_seconds{job_name="FailedJob1",namespace="ns1"} 900 kube_job_spec_completions{job_name="FailedJob1",namespace="ns1"} 1 kube_job_spec_parallelism{job_name="FailedJob1",namespace="ns1"} 1 @@ -244,7 +244,7 @@ func TestJobStore(t *testing.T) { kube_job_complete{condition="unknown",job_name="SuccessfulJob2NoActiveDeadlineSeconds",namespace="ns1"} 0 kube_job_info{job_name="SuccessfulJob2NoActiveDeadlineSeconds",namespace="ns1"} 1 - kube_job_labels{job_name="SuccessfulJob2NoActiveDeadlineSeconds",label_app="example-successful-2",namespace="ns1"} 1 + kube_job_labels{job_name="SuccessfulJob2NoActiveDeadlineSeconds",namespace="ns1"} 1 kube_job_spec_completions{job_name="SuccessfulJob2NoActiveDeadlineSeconds",namespace="ns1"} 1 kube_job_spec_parallelism{job_name="SuccessfulJob2NoActiveDeadlineSeconds",namespace="ns1"} 1 kube_job_status_active{job_name="SuccessfulJob2NoActiveDeadlineSeconds",namespace="ns1"} 0 @@ -256,8 +256,8 @@ func TestJobStore(t *testing.T) { }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(jobMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(jobMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(jobMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(jobMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } diff --git a/internal/store/mutatingwebhookconfiguration.go b/internal/store/mutatingwebhookconfiguration.go index 23bc9b287a..c05d2f1eaf 100644 --- a/internal/store/mutatingwebhookconfiguration.go +++ b/internal/store/mutatingwebhookconfiguration.go @@ -31,7 +31,6 @@ import ( ) var ( - descMutatingWebhookConfigurationHelp = "Kubernetes labels converted to Prometheus labels." descMutatingWebhookConfigurationDefaultLabels = []string{"namespace", "mutatingwebhookconfiguration"} mutatingWebhookConfigurationMetricFamilies = []generator.FamilyGenerator{ diff --git a/internal/store/namespace.go b/internal/store/namespace.go index dba1c3b440..c1e994f543 100644 --- a/internal/store/namespace.go +++ b/internal/store/namespace.go @@ -34,8 +34,10 @@ var ( descNamespaceLabelsName = "kube_namespace_labels" descNamespaceLabelsHelp = "Kubernetes labels converted to Prometheus labels." descNamespaceLabelsDefaultLabels = []string{"namespace"} +) - namespaceMetricFamilies = []generator.FamilyGenerator{ +func namespaceMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( "kube_namespace_created", "Unix creation timestamp", @@ -60,7 +62,7 @@ var ( metric.Gauge, "", wrapNamespaceFunc(func(n *v1.Namespace) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(n.Labels) + labelKeys, labelValues := createLabelKeysValues(n.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -124,7 +126,7 @@ var ( }), ), } -) +} func wrapNamespaceFunc(f func(*v1.Namespace) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/namespace_test.go b/internal/store/namespace_test.go index d9d20e6288..1849ff665e 100644 --- a/internal/store/namespace_test.go +++ b/internal/store/namespace_test.go @@ -128,7 +128,7 @@ func TestNamespaceStore(t *testing.T) { }, Want: metadata + ` kube_namespace_created{namespace="ns1"} 1.5e+09 - kube_namespace_labels{label_app="example1",namespace="ns1"} 1 + kube_namespace_labels{namespace="ns1"} 1 kube_namespace_status_phase{namespace="ns1",phase="Active"} 1 kube_namespace_status_phase{namespace="ns1",phase="Terminating"} 0 `, @@ -150,7 +150,7 @@ func TestNamespaceStore(t *testing.T) { }, }, Want: metadata + ` - kube_namespace_labels{label_app="example2",label_l2="label2",namespace="ns2"} 1 + kube_namespace_labels{namespace="ns2"} 1 kube_namespace_status_phase{namespace="ns2",phase="Active"} 1 kube_namespace_status_phase{namespace="ns2",phase="Terminating"} 0 `, @@ -158,8 +158,8 @@ func TestNamespaceStore(t *testing.T) { } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(namespaceMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(namespaceMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(namespaceMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(namespaceMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } diff --git a/internal/store/networkpolicy.go b/internal/store/networkpolicy.go index 5e1d50981d..96d095299b 100644 --- a/internal/store/networkpolicy.go +++ b/internal/store/networkpolicy.go @@ -32,8 +32,10 @@ import ( var ( descNetworkPolicyLabelsDefaultLabels = []string{"namespace", "networkpolicy"} +) - networkpolicyMetricFamilies = []generator.FamilyGenerator{ +func networkPolicyMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( "kube_networkpolicy_created", "Unix creation timestamp of network policy", @@ -57,7 +59,7 @@ var ( metric.Gauge, "", wrapNetworkPolicyFunc(func(n *networkingv1.NetworkPolicy) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(n.Labels) + labelKeys, labelValues := createLabelKeysValues(n.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -104,7 +106,7 @@ var ( }), ), } -) +} func wrapNetworkPolicyFunc(f func(*networkingv1.NetworkPolicy) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/networkpolicy_test.go b/internal/store/networkpolicy_test.go index e3e9226310..5a5ef2bb03 100644 --- a/internal/store/networkpolicy_test.go +++ b/internal/store/networkpolicy_test.go @@ -68,7 +68,7 @@ func TestNetworkPolicyStore(t *testing.T) { }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(networkpolicyMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(networkPolicyMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %dth run:\n%s", i, err) } diff --git a/internal/store/node.go b/internal/store/node.go index 5b065d0685..f88bab30d2 100644 --- a/internal/store/node.go +++ b/internal/store/node.go @@ -36,8 +36,10 @@ var ( descNodeLabelsName = "kube_node_labels" descNodeLabelsHelp = "Kubernetes labels converted to Prometheus labels." descNodeLabelsDefaultLabels = []string{"node"} +) - nodeMetricFamilies = []generator.FamilyGenerator{ +func nodeMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( "kube_node_info", "Information about a cluster node.", @@ -109,7 +111,7 @@ var ( metric.Gauge, "", wrapNodeFunc(func(n *v1.Node) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(n.Labels) + labelKeys, labelValues := createLabelKeysValues(n.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -373,7 +375,7 @@ var ( }), ), } -) +} func wrapNodeFunc(f func(*v1.Node) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/node_test.go b/internal/store/node_test.go index b9d803999d..ce5f00cfbd 100644 --- a/internal/store/node_test.go +++ b/internal/store/node_test.go @@ -140,7 +140,7 @@ func TestNodeStore(t *testing.T) { # TYPE kube_node_status_capacity gauge kube_node_created{node="127.0.0.1"} 1.5e+09 kube_node_info{container_runtime_version="rkt",kernel_version="kernel",kubelet_version="kubelet",kubeproxy_version="kubeproxy",node="127.0.0.1",os_image="osimage",pod_cidr="172.24.10.0/24",provider_id="provider://i-randomidentifier",internal_ip="1.2.3.4"} 1 - kube_node_labels{label_node_role_kubernetes_io_master="",node="127.0.0.1"} 1 + kube_node_labels{node="127.0.0.1"} 1 kube_node_role{node="127.0.0.1",role="master"} 1 kube_node_spec_unschedulable{node="127.0.0.1"} 1 kube_node_status_allocatable{node="127.0.0.1",resource="cpu",unit="core"} 3 @@ -276,8 +276,8 @@ func TestNodeStore(t *testing.T) { }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(nodeMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(nodeMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(nodeMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(nodeMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } diff --git a/internal/store/persistentvolume.go b/internal/store/persistentvolume.go index ed6a5ac207..5bbe5b3868 100644 --- a/internal/store/persistentvolume.go +++ b/internal/store/persistentvolume.go @@ -39,8 +39,10 @@ var ( descPersistentVolumeLabelsName = "kube_persistentvolume_labels" descPersistentVolumeLabelsHelp = "Kubernetes labels converted to Prometheus labels." descPersistentVolumeLabelsDefaultLabels = []string{"persistentvolume"} +) - persistentVolumeMetricFamilies = []generator.FamilyGenerator{ +func persistentVolumeMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( descPersistentVolumeClaimRefName, descPersistentVolumeClaimRefHelp, @@ -77,7 +79,7 @@ var ( metric.Gauge, "", wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(p.Labels) + labelKeys, labelValues := createLabelKeysValues(p.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -231,7 +233,7 @@ var ( }), ), } -) +} func wrapPersistentVolumeFunc(f func(*v1.PersistentVolume) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/persistentvolume_test.go b/internal/store/persistentvolume_test.go index 16b46f7838..a29544d263 100644 --- a/internal/store/persistentvolume_test.go +++ b/internal/store/persistentvolume_test.go @@ -379,7 +379,7 @@ func TestPersistentVolumeStore(t *testing.T) { Want: ` # HELP kube_persistentvolume_labels Kubernetes labels converted to Prometheus labels. # TYPE kube_persistentvolume_labels gauge - kube_persistentvolume_labels{label_app="mysql-server",persistentvolume="test-labeled-pv"} 1 + kube_persistentvolume_labels{persistentvolume="test-labeled-pv"} 1 `, MetricNames: []string{"kube_persistentvolume_labels"}, }, @@ -459,8 +459,8 @@ func TestPersistentVolumeStore(t *testing.T) { }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(persistentVolumeMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(persistentVolumeMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(persistentVolumeMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(persistentVolumeMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } diff --git a/internal/store/persistentvolumeclaim.go b/internal/store/persistentvolumeclaim.go index 56a37871ee..e68928898c 100644 --- a/internal/store/persistentvolumeclaim.go +++ b/internal/store/persistentvolumeclaim.go @@ -34,15 +34,17 @@ var ( descPersistentVolumeClaimLabelsName = "kube_persistentvolumeclaim_labels" descPersistentVolumeClaimLabelsHelp = "Kubernetes labels converted to Prometheus labels." descPersistentVolumeClaimLabelsDefaultLabels = []string{"namespace", "persistentvolumeclaim"} +) - persistentVolumeClaimMetricFamilies = []generator.FamilyGenerator{ +func persistentVolumeClaimMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( descPersistentVolumeClaimLabelsName, descPersistentVolumeClaimLabelsHelp, metric.Gauge, "", wrapPersistentVolumeClaimFunc(func(p *v1.PersistentVolumeClaim) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(p.Labels) + labelKeys, labelValues := createLabelKeysValues(p.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -179,7 +181,7 @@ var ( }), ), } -) +} func wrapPersistentVolumeClaimFunc(f func(*v1.PersistentVolumeClaim) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/persistentvolumeclaim_test.go b/internal/store/persistentvolumeclaim_test.go index a4f9e5eed9..7a87986553 100644 --- a/internal/store/persistentvolumeclaim_test.go +++ b/internal/store/persistentvolumeclaim_test.go @@ -78,7 +78,7 @@ func TestPersistentVolumeClaimStore(t *testing.T) { kube_persistentvolumeclaim_status_phase{namespace="default",persistentvolumeclaim="mysql-data",phase="Lost"} 0 kube_persistentvolumeclaim_status_phase{namespace="default",persistentvolumeclaim="mysql-data",phase="Pending"} 0 kube_persistentvolumeclaim_resource_requests_storage_bytes{namespace="default",persistentvolumeclaim="mysql-data"} 1.073741824e+09 - kube_persistentvolumeclaim_labels{label_app="mysql-server",namespace="default",persistentvolumeclaim="mysql-data"} 1 + kube_persistentvolumeclaim_labels{namespace="default",persistentvolumeclaim="mysql-data"} 1 kube_persistentvolumeclaim_access_mode{namespace="default",persistentvolumeclaim="mysql-data",access_mode="ReadWriteOnce"} 1 kube_persistentvolumeclaim_status_condition{namespace="default",persistentvolumeclaim="mysql-data",status="false",condition="CustomizedType"} 0 kube_persistentvolumeclaim_status_condition{namespace="default",persistentvolumeclaim="mysql-data",status="false",condition="FileSystemResizePending"} 1 @@ -183,8 +183,8 @@ func TestPersistentVolumeClaimStore(t *testing.T) { }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(persistentVolumeClaimMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(persistentVolumeClaimMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(persistentVolumeClaimMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(persistentVolumeClaimMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } diff --git a/internal/store/pod.go b/internal/store/pod.go index b57554925b..091108dc42 100644 --- a/internal/store/pod.go +++ b/internal/store/pod.go @@ -37,8 +37,10 @@ var ( containerWaitingReasons = []string{"ContainerCreating", "CrashLoopBackOff", "CreateContainerConfigError", "ErrImagePull", "ImagePullBackOff", "CreateContainerError", "InvalidImageName"} containerTerminatedReasons = []string{"OOMKilled", "Completed", "Error", "ContainerCannotRun", "DeadlineExceeded", "Evicted"} podStatusReasons = []string{"NodeLost", "Evicted", "UnexpectedAdmissionError"} +) - podMetricFamilies = []generator.FamilyGenerator{ +func podMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( "kube_pod_info", "Information about pod.", @@ -193,7 +195,7 @@ var ( metric.Gauge, "", wrapPodFunc(func(p *v1.Pod) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(p.Labels) + labelKeys, labelValues := createLabelKeysValues(p.Labels, allowLabelsList) m := metric.Metric{ LabelKeys: labelKeys, LabelValues: labelValues, @@ -272,15 +274,12 @@ var ( ms := []*metric.Metric{} for _, c := range p.Status.Conditions { - switch c.Type { - case v1.PodScheduled: - if c.Status == v1.ConditionTrue { - ms = append(ms, &metric.Metric{ - LabelKeys: []string{}, - LabelValues: []string{}, - Value: float64(c.LastTransitionTime.Unix()), - }) - } + if c.Type == v1.PodScheduled && c.Status == v1.ConditionTrue { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{}, + LabelValues: []string{}, + Value: float64(c.LastTransitionTime.Unix()), + }) } } @@ -298,15 +297,12 @@ var ( ms := []*metric.Metric{} for _, c := range p.Status.Conditions { - switch c.Type { - case v1.PodScheduled: - if c.Status == v1.ConditionFalse { - ms = append(ms, &metric.Metric{ - LabelKeys: []string{}, - LabelValues: []string{}, - Value: 1, - }) - } + if c.Type == v1.PodScheduled && c.Status == v1.ConditionFalse { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{}, + LabelValues: []string{}, + Value: 1, + }) } } @@ -364,8 +360,7 @@ var ( ms := []*metric.Metric{} for _, c := range p.Status.Conditions { - switch c.Type { - case v1.PodReady: + if c.Type == v1.PodReady { conditionMetrics := addConditionMetrics(c.Status) for _, m := range conditionMetrics { @@ -390,8 +385,7 @@ var ( ms := []*metric.Metric{} for _, c := range p.Status.Conditions { - switch c.Type { - case v1.PodScheduled: + if c.Type == v1.PodScheduled { conditionMetrics := addConditionMetrics(c.Status) for _, m := range conditionMetrics { @@ -1357,7 +1351,7 @@ var ( }), ), } -) +} func wrapPodFunc(f func(*v1.Pod) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/pod_test.go b/internal/store/pod_test.go index 73265969e7..57ab5b3127 100644 --- a/internal/store/pod_test.go +++ b/internal/store/pod_test.go @@ -1520,7 +1520,7 @@ kube_pod_container_status_last_terminated_reason{container="container7",namespac Want: ` # HELP kube_pod_labels Kubernetes labels converted to Prometheus labels. # TYPE kube_pod_labels gauge - kube_pod_labels{label_app="example",namespace="ns1",pod="pod1"} 1 + kube_pod_labels{namespace="ns1",pod="pod1"} 1 `, MetricNames: []string{ "kube_pod_labels", @@ -1607,8 +1607,8 @@ kube_pod_container_status_last_terminated_reason{container="container7",namespac } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(podMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(podMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(podMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(podMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } @@ -1618,7 +1618,7 @@ kube_pod_container_status_last_terminated_reason{container="container7",namespac func BenchmarkPodStore(b *testing.B) { b.ReportAllocs() - f := generator.ComposeMetricGenFuncs(podMetricFamilies) + f := generator.ComposeMetricGenFuncs(podMetricFamilies(nil)) pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ diff --git a/internal/store/replicaset.go b/internal/store/replicaset.go index b1a8fd2267..6c8a259365 100644 --- a/internal/store/replicaset.go +++ b/internal/store/replicaset.go @@ -35,8 +35,10 @@ var ( descReplicaSetLabelsDefaultLabels = []string{"namespace", "replicaset"} descReplicaSetLabelsName = "kube_replicaset_labels" descReplicaSetLabelsHelp = "Kubernetes labels converted to Prometheus labels." +) - replicaSetMetricFamilies = []generator.FamilyGenerator{ +func replicaSetMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( "kube_replicaset_created", "Unix creation timestamp", @@ -200,8 +202,8 @@ var ( descReplicaSetLabelsHelp, metric.Gauge, "", - wrapReplicaSetFunc(func(d *v1.ReplicaSet) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(d.Labels) + wrapReplicaSetFunc(func(r *v1.ReplicaSet) *metric.Family { + labelKeys, labelValues := createLabelKeysValues(r.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -214,7 +216,7 @@ var ( }), ), } -) +} func wrapReplicaSetFunc(f func(*v1.ReplicaSet) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/replicaset_test.go b/internal/store/replicaset_test.go index bf2335ac4a..3972fb8b25 100644 --- a/internal/store/replicaset_test.go +++ b/internal/store/replicaset_test.go @@ -85,7 +85,7 @@ func TestReplicaSetStore(t *testing.T) { }, }, Want: metadata + ` - kube_replicaset_labels{replicaset="rs1",namespace="ns1",label_app="example1"} 1 + kube_replicaset_labels{replicaset="rs1",namespace="ns1"} 1 kube_replicaset_created{namespace="ns1",replicaset="rs1"} 1.5e+09 kube_replicaset_metadata_generation{namespace="ns1",replicaset="rs1"} 21 kube_replicaset_status_replicas{namespace="ns1",replicaset="rs1"} 5 @@ -118,7 +118,7 @@ func TestReplicaSetStore(t *testing.T) { }, }, Want: metadata + ` - kube_replicaset_labels{replicaset="rs2",namespace="ns2",label_app="example2",label_env="ex"} 1 + kube_replicaset_labels{replicaset="rs2",namespace="ns2"} 1 kube_replicaset_metadata_generation{namespace="ns2",replicaset="rs2"} 14 kube_replicaset_status_replicas{namespace="ns2",replicaset="rs2"} 0 kube_replicaset_status_observed_generation{namespace="ns2",replicaset="rs2"} 5 @@ -130,8 +130,8 @@ func TestReplicaSetStore(t *testing.T) { }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(replicaSetMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(replicaSetMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(replicaSetMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(replicaSetMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } diff --git a/internal/store/secret.go b/internal/store/secret.go index d5a9996864..9b1599798e 100644 --- a/internal/store/secret.go +++ b/internal/store/secret.go @@ -34,8 +34,10 @@ var ( descSecretLabelsName = "kube_secret_labels" descSecretLabelsHelp = "Kubernetes labels converted to Prometheus labels." descSecretLabelsDefaultLabels = []string{"namespace", "secret"} +) - secretMetricFamilies = []generator.FamilyGenerator{ +func secretMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( "kube_secret_info", "Information about secret.", @@ -74,7 +76,7 @@ var ( metric.Gauge, "", wrapSecretFunc(func(s *v1.Secret) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(s.Labels) + labelKeys, labelValues := createLabelKeysValues(s.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -118,7 +120,8 @@ var ( }), ), } -) + +} func wrapSecretFunc(f func(*v1.Secret) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/secret_test.go b/internal/store/secret_test.go index dab8dd8d36..052021ff72 100644 --- a/internal/store/secret_test.go +++ b/internal/store/secret_test.go @@ -110,14 +110,14 @@ func TestSecretStore(t *testing.T) { kube_secret_type{namespace="ns3",secret="secret3",type="kubernetes.io/dockercfg"} 1 kube_secret_created{namespace="ns3",secret="secret3"} 1.501569018e+09 kube_secret_metadata_resource_version{namespace="ns3",secret="secret3"} 0 - kube_secret_labels{label_test_3="test-3",namespace="ns3",secret="secret3"} 1 + kube_secret_labels{namespace="ns3",secret="secret3"} 1 `, MetricNames: []string{"kube_secret_info", "kube_secret_metadata_resource_version", "kube_secret_created", "kube_secret_labels", "kube_secret_type"}, }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(secretMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(secretMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(secretMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(secretMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } diff --git a/internal/store/service.go b/internal/store/service.go index 47372ac73f..15a1393a24 100644 --- a/internal/store/service.go +++ b/internal/store/service.go @@ -34,8 +34,10 @@ var ( descServiceLabelsName = "kube_service_labels" descServiceLabelsHelp = "Kubernetes labels converted to Prometheus labels." descServiceLabelsDefaultLabels = []string{"namespace", "service"} +) - serviceMetricFamilies = []generator.FamilyGenerator{ +func serviceMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( "kube_service_info", "Information about service.", @@ -88,9 +90,8 @@ var ( metric.Gauge, "", wrapSvcFunc(func(s *v1.Service) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(s.Labels) + labelKeys, labelValues := createLabelKeysValues(s.Labels, allowLabelsList) m := metric.Metric{ - LabelKeys: labelKeys, LabelValues: labelValues, Value: 1, @@ -153,7 +154,7 @@ var ( }), ), } -) +} func wrapSvcFunc(f func(*v1.Service) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/service_test.go b/internal/store/service_test.go index 62a4d042e4..b9545d7ad0 100644 --- a/internal/store/service_test.go +++ b/internal/store/service_test.go @@ -70,7 +70,7 @@ func TestServiceStore(t *testing.T) { # TYPE kube_service_spec_type gauge kube_service_created{namespace="default",service="test-service1"} 1.5e+09 kube_service_info{cluster_ip="1.2.3.4",external_name="",load_balancer_ip="",namespace="default",service="test-service1"} 1 - kube_service_labels{label_app="example1",namespace="default",service="test-service1"} 1 + kube_service_labels{namespace="default",service="test-service1"} 1 kube_service_spec_type{namespace="default",service="test-service1",type="ClusterIP"} 1 `, MetricNames: []string{ @@ -99,7 +99,7 @@ func TestServiceStore(t *testing.T) { Want: metadata + ` kube_service_created{namespace="default",service="test-service2"} 1.5e+09 kube_service_info{cluster_ip="1.2.3.5",external_name="",load_balancer_ip="",namespace="default",service="test-service2"} 1 - kube_service_labels{label_app="example2",namespace="default",service="test-service2"} 1 + kube_service_labels{namespace="default",service="test-service2"} 1 kube_service_spec_type{namespace="default",service="test-service2",type="NodePort"} 1 `, }, @@ -122,7 +122,7 @@ func TestServiceStore(t *testing.T) { Want: metadata + ` kube_service_created{namespace="default",service="test-service3"} 1.5e+09 kube_service_info{cluster_ip="1.2.3.6",external_name="",load_balancer_ip="1.2.3.7",namespace="default",service="test-service3"} 1 - kube_service_labels{label_app="example3",namespace="default",service="test-service3"} 1 + kube_service_labels{namespace="default",service="test-service3"} 1 kube_service_spec_type{namespace="default",service="test-service3",type="LoadBalancer"} 1 `, }, @@ -144,7 +144,7 @@ func TestServiceStore(t *testing.T) { Want: metadata + ` kube_service_created{namespace="default",service="test-service4"} 1.5e+09 kube_service_info{cluster_ip="",external_name="www.example.com",load_balancer_ip="",namespace="default",service="test-service4"} 1 - kube_service_labels{label_app="example4",namespace="default",service="test-service4"} 1 + kube_service_labels{namespace="default",service="test-service4"} 1 kube_service_spec_type{namespace="default",service="test-service4",type="ExternalName"} 1 `, }, @@ -175,7 +175,7 @@ func TestServiceStore(t *testing.T) { Want: metadata + ` kube_service_created{namespace="default",service="test-service5"} 1.5e+09 kube_service_info{cluster_ip="",external_name="",load_balancer_ip="",namespace="default",service="test-service5"} 1 - kube_service_labels{label_app="example5",namespace="default",service="test-service5"} 1 + kube_service_labels{namespace="default",service="test-service5"} 1 kube_service_spec_type{namespace="default",service="test-service5",type="LoadBalancer"} 1 kube_service_status_load_balancer_ingress{hostname="www.example.com",ip="1.2.3.8",namespace="default",service="test-service5"} 1 `, @@ -201,7 +201,7 @@ func TestServiceStore(t *testing.T) { Want: metadata + ` kube_service_created{namespace="default",service="test-service6"} 1.5e+09 kube_service_info{cluster_ip="",external_name="",load_balancer_ip="",namespace="default",service="test-service6"} 1 - kube_service_labels{label_app="example6",namespace="default",service="test-service6"} 1 + kube_service_labels{namespace="default",service="test-service6"} 1 kube_service_spec_type{namespace="default",service="test-service6",type="ClusterIP"} 1 kube_service_spec_external_ip{external_ip="1.2.3.9",namespace="default",service="test-service6"} 1 kube_service_spec_external_ip{external_ip="1.2.3.10",namespace="default",service="test-service6"} 1 @@ -209,8 +209,8 @@ func TestServiceStore(t *testing.T) { }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(serviceMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(serviceMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(serviceMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(serviceMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } diff --git a/internal/store/statefulset.go b/internal/store/statefulset.go index 57289c9c7e..624e5aba96 100644 --- a/internal/store/statefulset.go +++ b/internal/store/statefulset.go @@ -34,8 +34,10 @@ var ( descStatefulSetLabelsName = "kube_statefulset_labels" descStatefulSetLabelsHelp = "Kubernetes labels converted to Prometheus labels." descStatefulSetLabelsDefaultLabels = []string{"namespace", "statefulset"} +) - statefulSetMetricFamilies = []generator.FamilyGenerator{ +func statefulSetMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( "kube_statefulset_created", "Unix creation timestamp", @@ -170,7 +172,7 @@ var ( metric.Gauge, "", wrapStatefulSetFunc(func(s *v1.StatefulSet) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(s.Labels) + labelKeys, labelValues := createLabelKeysValues(s.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -217,8 +219,7 @@ var ( }), ), } -) - +} func wrapStatefulSetFunc(f func(*v1.StatefulSet) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { statefulSet := obj.(*v1.StatefulSet) diff --git a/internal/store/statefulset_test.go b/internal/store/statefulset_test.go index 867d7c2a31..d9ef6670ee 100644 --- a/internal/store/statefulset_test.go +++ b/internal/store/statefulset_test.go @@ -92,7 +92,7 @@ func TestStatefulSetStore(t *testing.T) { kube_statefulset_status_observed_generation{namespace="ns1",statefulset="statefulset1"} 1 kube_statefulset_replicas{namespace="ns1",statefulset="statefulset1"} 3 kube_statefulset_metadata_generation{namespace="ns1",statefulset="statefulset1"} 3 - kube_statefulset_labels{label_app="example1",namespace="ns1",statefulset="statefulset1"} 1 + kube_statefulset_labels{namespace="ns1",statefulset="statefulset1"} 1 `, MetricNames: []string{ "kube_statefulset_created", @@ -161,7 +161,7 @@ func TestStatefulSetStore(t *testing.T) { kube_statefulset_status_observed_generation{namespace="ns2",statefulset="statefulset2"} 2 kube_statefulset_replicas{namespace="ns2",statefulset="statefulset2"} 6 kube_statefulset_metadata_generation{namespace="ns2",statefulset="statefulset2"} 21 - kube_statefulset_labels{label_app="example2",namespace="ns2",statefulset="statefulset2"} 1 + kube_statefulset_labels{namespace="ns2",statefulset="statefulset2"} 1 kube_statefulset_status_current_revision{namespace="ns2",revision="cr2",statefulset="statefulset2"} 1 `, MetricNames: []string{ @@ -224,7 +224,7 @@ func TestStatefulSetStore(t *testing.T) { kube_statefulset_status_replicas_updated{namespace="ns3",statefulset="statefulset3"} 0 kube_statefulset_replicas{namespace="ns3",statefulset="statefulset3"} 9 kube_statefulset_metadata_generation{namespace="ns3",statefulset="statefulset3"} 36 - kube_statefulset_labels{label_app="example3",namespace="ns3",statefulset="statefulset3"} 1 + kube_statefulset_labels{namespace="ns3",statefulset="statefulset3"} 1 kube_statefulset_status_current_revision{namespace="ns3",revision="cr3",statefulset="statefulset3"} 1 `, MetricNames: []string{ @@ -241,8 +241,8 @@ func TestStatefulSetStore(t *testing.T) { }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(statefulSetMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(statefulSetMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(statefulSetMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(statefulSetMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } diff --git a/internal/store/storageclass.go b/internal/store/storageclass.go index 0be4f5fb2b..f4c4538e44 100644 --- a/internal/store/storageclass.go +++ b/internal/store/storageclass.go @@ -34,8 +34,10 @@ var ( descStorageClassLabelsDefaultLabels = []string{"storageclass"} defaultReclaimPolicy = v1.PersistentVolumeReclaimDelete defaultVolumeBindingMode = storagev1.VolumeBindingImmediate +) - storageClassMetricFamilies = []generator.FamilyGenerator{ +func storageClassMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( "kube_storageclass_info", "Information about storageclass.", @@ -83,7 +85,7 @@ var ( metric.Gauge, "", wrapStorageClassFunc(func(s *storagev1.StorageClass) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(s.Labels) + labelKeys, labelValues := createLabelKeysValues(s.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -96,7 +98,7 @@ var ( }), ), } -) +} func wrapStorageClassFunc(f func(*storagev1.StorageClass) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/storageclass_test.go b/internal/store/storageclass_test.go index e44729e054..d3ee764fc8 100644 --- a/internal/store/storageclass_test.go +++ b/internal/store/storageclass_test.go @@ -100,7 +100,7 @@ func TestStorageClassStore(t *testing.T) { Want: ` # HELP kube_storageclass_labels Kubernetes labels converted to Prometheus labels. # TYPE kube_storageclass_labels gauge - kube_storageclass_labels{storageclass="test_storageclass-labels",label_foo="bar"} 1 + kube_storageclass_labels{storageclass="test_storageclass-labels"} 1 `, MetricNames: []string{ "kube_storageclass_labels", @@ -108,8 +108,8 @@ func TestStorageClassStore(t *testing.T) { }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(storageClassMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(storageClassMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(storageClassMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(storageClassMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } diff --git a/internal/store/utils.go b/internal/store/utils.go index 4a0b4b0128..c76b7136f1 100644 --- a/internal/store/utils.go +++ b/internal/store/utils.go @@ -26,7 +26,6 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/validation" - "k8s.io/kube-state-metrics/v2/pkg/allow" "k8s.io/kube-state-metrics/v2/pkg/metric" ) @@ -73,14 +72,6 @@ func addConditionMetrics(cs v1.ConditionStatus) []*metric.Metric { return ms } -func sanitizeAllowLabels(l map[string][]string) allow.Labels { - allowLabels := make(map[string][]string) - for m, labels := range l { - allowLabels[sanitizeLabelName(m)] = labels - } - return allowLabels -} - func kubeLabelsToPrometheusLabels(labels map[string]string) ([]string, []string) { return mapToPrometheusLabels(labels, "label") } @@ -179,3 +170,19 @@ func isNativeResource(name v1.ResourceName) bool { func isPrefixedNativeResource(name v1.ResourceName) bool { return strings.Contains(string(name), v1.ResourceDefaultNamespacePrefix) } + +// createLabelKeysValues takes in passed kubernetes labels and allowed list in kubernetes label format +// it returns only those allowed labels that exist in the list converting them to Prometheus labels. +func createLabelKeysValues(allKubeLabels map[string]string, allowList []string) ([]string, []string) { + allowedKubeLabels := make(map[string]string) + + if len(allowList) > 0 { + for _, l := range allowList { + v, found := allKubeLabels[l] + if found { + allowedKubeLabels[l] = v + } + } + } + return kubeLabelsToPrometheusLabels(allowedKubeLabels) +} diff --git a/internal/store/validatingwebhookconfiguration.go b/internal/store/validatingwebhookconfiguration.go index 0ee8c15e9d..8bc82b5474 100644 --- a/internal/store/validatingwebhookconfiguration.go +++ b/internal/store/validatingwebhookconfiguration.go @@ -31,7 +31,6 @@ import ( ) var ( - descValidatingWebhookConfigurationHelp = "Kubernetes labels converted to Prometheus labels." descValidatingWebhookConfigurationDefaultLabels = []string{"namespace", "validatingwebhookconfiguration"} validatingWebhookConfigurationMetricFamilies = []generator.FamilyGenerator{ diff --git a/internal/store/verticalpodautoscaler.go b/internal/store/verticalpodautoscaler.go index 15ce67ee47..3093a2c13b 100644 --- a/internal/store/verticalpodautoscaler.go +++ b/internal/store/verticalpodautoscaler.go @@ -37,15 +37,17 @@ var ( descVerticalPodAutoscalerLabelsName = "kube_verticalpodautoscaler_labels" descVerticalPodAutoscalerLabelsHelp = "Kubernetes labels converted to Prometheus labels." descVerticalPodAutoscalerLabelsDefaultLabels = []string{"namespace", "verticalpodautoscaler", "target_api_version", "target_kind", "target_name"} +) - vpaMetricFamilies = []generator.FamilyGenerator{ +func vpaMetricFamilies(allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGenerator( descVerticalPodAutoscalerLabelsName, descVerticalPodAutoscalerLabelsHelp, metric.Gauge, "", wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { - labelKeys, labelValues := kubeLabelsToPrometheusLabels(a.Labels) + labelKeys, labelValues := createLabelKeysValues(a.Labels, allowLabelsList) return &metric.Family{ Metrics: []*metric.Metric{ { @@ -221,7 +223,7 @@ var ( }), ), } -) +} func vpaResourcesToMetrics(containerName string, resources v1.ResourceList) []*metric.Metric { ms := []*metric.Metric{} diff --git a/internal/store/verticalpodautoscaler_test.go b/internal/store/verticalpodautoscaler_test.go index 7d6fb0d6e5..465fc13f85 100644 --- a/internal/store/verticalpodautoscaler_test.go +++ b/internal/store/verticalpodautoscaler_test.go @@ -114,7 +114,7 @@ func TestVPAStore(t *testing.T) { kube_verticalpodautoscaler_status_recommendation_containerrecommendations_uncappedtarget{container="container1",namespace="ns1",resource="memory",target_api_version="extensions/v1beta1",target_kind="Deployment",target_name="deployment1",unit="byte",verticalpodautoscaler="vpa1"} 1.073741824e+10 kube_verticalpodautoscaler_status_recommendation_containerrecommendations_upperbound{container="container1",namespace="ns1",resource="cpu",target_api_version="extensions/v1beta1",target_kind="Deployment",target_name="deployment1",unit="core",verticalpodautoscaler="vpa1"} 4 kube_verticalpodautoscaler_status_recommendation_containerrecommendations_upperbound{container="container1",namespace="ns1",resource="memory",target_api_version="extensions/v1beta1",target_kind="Deployment",target_name="deployment1",unit="byte",verticalpodautoscaler="vpa1"} 8.589934592e+09 - kube_verticalpodautoscaler_labels{label_app="foobar",namespace="ns1",target_api_version="extensions/v1beta1",target_kind="Deployment",target_name="deployment1",verticalpodautoscaler="vpa1"} 1 + kube_verticalpodautoscaler_labels{namespace="ns1",target_api_version="extensions/v1beta1",target_kind="Deployment",target_name="deployment1",verticalpodautoscaler="vpa1"} 1 kube_verticalpodautoscaler_spec_updatepolicy_updatemode{namespace="ns1",target_api_version="extensions/v1beta1",target_kind="Deployment",target_name="deployment1",update_mode="Auto",verticalpodautoscaler="vpa1"} 0 kube_verticalpodautoscaler_spec_updatepolicy_updatemode{namespace="ns1",target_api_version="extensions/v1beta1",target_kind="Deployment",target_name="deployment1",update_mode="Initial",verticalpodautoscaler="vpa1"} 0 kube_verticalpodautoscaler_spec_updatepolicy_updatemode{namespace="ns1",target_api_version="extensions/v1beta1",target_kind="Deployment",target_name="deployment1",update_mode="Off",verticalpodautoscaler="vpa1"} 0 @@ -133,8 +133,8 @@ func TestVPAStore(t *testing.T) { }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(vpaMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(vpaMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(vpaMetricFamilies(nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(vpaMetricFamilies(nil)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) } diff --git a/pkg/options/types.go b/pkg/options/types.go index 73101d178f..8d1d26c30d 100644 --- a/pkg/options/types.go +++ b/pkg/options/types.go @@ -18,16 +18,18 @@ package options import ( "errors" + "fmt" "regexp" "sort" "strings" "text/scanner" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/validation" ) var errLabelsAllowListFormat = errors.New("invalid format, metric=[label1,label2,labeln...],metricN=[]") -var labelsAllowListFormat = regexp.MustCompile("^[a-zA-Z0-9_]+$") +var labelsAllowListFormat = regexp.MustCompile("^[a-zA-Z0-9]+$") // MetricSet represents a collection which has a unique set of metrics. type MetricSet map[string]struct{} @@ -138,6 +140,8 @@ type LabelsAllowList map[string][]string // Set converts a comma-separated string of metrics and their allowed labels and appends to the LabelsAllowList. func (l *LabelsAllowList) Set(value string) error { + fmt.Println("value:") + fmt.Println(value) var s scanner.Scanner s.Init(strings.NewReader(value)) @@ -174,14 +178,24 @@ func (l *LabelsAllowList) Set(value string) error { continue default: text := s.TokenText() - if !labelsAllowListFormat.MatchString(text) { - return errLabelsAllowListFormat - } + // it's either a resource name or a label key name + fmt.Println("text") if !inLabels { name = text m[name] = []string{} + fmt.Printf("not in labels: %s\n", text) } else { m[name] = append(m[name], text) + m[name] = append(m[name], "managed-by") + fmt.Printf("yes in labels: %s\n", text) + + // Validate label key name. + // TODO: fix k + k := "app.kubernetes.io/component" + if errs := validation.IsQualifiedName(k); len(errs) != 0 { + return fmt.Errorf("invalid label key %q: %s", k, strings.Join(errs, "; ")) + } + } } previous = tok