From 634c04ef90846ddd4e09a3e55fafdfd6a7329186 Mon Sep 17 00:00:00 2001 From: opeco17 Date: Mon, 28 Aug 2023 13:03:38 +0000 Subject: [PATCH] feat: enable metric-annotations-allowlist and metric-labels-allowlist for ResourceQuota --- docs/resourcequota-metrics.md | 2 ++ internal/store/builder.go | 2 +- internal/store/resourcequota.go | 54 ++++++++++++++++++++++++++-- internal/store/resourcequota_test.go | 36 +++++++++++++++++-- 4 files changed, 89 insertions(+), 5 deletions(-) diff --git a/docs/resourcequota-metrics.md b/docs/resourcequota-metrics.md index e98eb4158a..485d0a6b6a 100644 --- a/docs/resourcequota-metrics.md +++ b/docs/resourcequota-metrics.md @@ -4,3 +4,5 @@ | ---------- | ----------- | ----------- | ----------- | | kube_resourcequota | Gauge | `resourcequota`=<quota-name>
`namespace`=<namespace>
`resource`=<ResourceName>
`type`=<quota-type> | STABLE | | kube_resourcequota_created | Gauge | `resourcequota`=<quota-name>
`namespace`=<namespace> | STABLE | +| kube_resourcequota_annotations | Gauge | `resourcequota`=<quota-name>
`namespace`=<namespace>
`annotation_RESOURCE_QUOTA_ANNOTATION`=<RESOURCE_QUOTA_ANNOTATION> | EXPERIMENTAL | +| kube_resourcequota_labels | Gauge | `resourcequota`=<quota-name>
`namespace`=<namespace>
`label_RESOURCE_QUOTA_LABEL`=<RESOURCE_QUOTA_LABEL> | EXPERIMENTAL | diff --git a/internal/store/builder.go b/internal/store/builder.go index 31e9f2e450..2c71c23fea 100644 --- a/internal/store/builder.go +++ b/internal/store/builder.go @@ -431,7 +431,7 @@ func (b *Builder) buildReplicationControllerStores() []cache.Store { } func (b *Builder) buildResourceQuotaStores() []cache.Store { - return b.buildStoresFunc(resourceQuotaMetricFamilies, &v1.ResourceQuota{}, createResourceQuotaListWatch, b.useAPIServerCache) + return b.buildStoresFunc(resourceQuotaMetricFamilies(b.allowAnnotationsList["resourcequotas"], b.allowLabelsList["resourcequotas"]), &v1.ResourceQuota{}, createResourceQuotaListWatch, b.useAPIServerCache) } func (b *Builder) buildSecretStores() []cache.Store { diff --git a/internal/store/resourcequota.go b/internal/store/resourcequota.go index fe55f98f0b..adaf4a838e 100644 --- a/internal/store/resourcequota.go +++ b/internal/store/resourcequota.go @@ -32,9 +32,15 @@ import ( ) var ( + descResourceQuotaAnnotationsName = "kube_resourcequota_annotations" + descResourceQuotaAnnotationsHelp = "Kubernetes annotations converted to Prometheus labels." + descResourceQuotaLabelsName = "kube_resourcequota_labels" + descResourceQuotaLabelsHelp = "Kubernetes labels converted to Prometheus labels." descResourceQuotaLabelsDefaultLabels = []string{"namespace", "resourcequota"} +) - resourceQuotaMetricFamilies = []generator.FamilyGenerator{ +func resourceQuotaMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ *generator.NewFamilyGeneratorWithStability( "kube_resourcequota_created", "Unix creation timestamp", @@ -87,8 +93,52 @@ var ( } }), ), + *generator.NewFamilyGeneratorWithStability( + descResourceQuotaAnnotationsName, + descResourceQuotaAnnotationsHelp, + metric.Gauge, + basemetrics.ALPHA, + "", + wrapResourceQuotaFunc(func(d *v1.ResourceQuota) *metric.Family { + if len(allowAnnotationsList) == 0 { + return &metric.Family{} + } + annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", d.Annotations, allowAnnotationsList) + return &metric.Family{ + Metrics: []*metric.Metric{ + { + LabelKeys: annotationKeys, + LabelValues: annotationValues, + Value: 1, + }, + }, + } + }), + ), + *generator.NewFamilyGeneratorWithStability( + descResourceQuotaLabelsName, + descResourceQuotaLabelsHelp, + metric.Gauge, + basemetrics.STABLE, + "", + wrapResourceQuotaFunc(func(d *v1.ResourceQuota) *metric.Family { + if len(allowLabelsList) == 0 { + return &metric.Family{} + } + labelKeys, labelValues := createPrometheusLabelKeysValues("label", d.Labels, allowLabelsList) + return &metric.Family{ + Metrics: []*metric.Metric{ + { + LabelKeys: labelKeys, + LabelValues: labelValues, + Value: 1, + }, + }, + } + }), + ), } -) +} func wrapResourceQuotaFunc(f func(*v1.ResourceQuota) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { diff --git a/internal/store/resourcequota_test.go b/internal/store/resourcequota_test.go index f342065cc3..2d60650f12 100644 --- a/internal/store/resourcequota_test.go +++ b/internal/store/resourcequota_test.go @@ -32,9 +32,13 @@ func TestResourceQuotaStore(t *testing.T) { // output so we only have to modify a single place when doing adjustments. const metadata = ` # HELP kube_resourcequota [STABLE] Information about resource quota. + # HELP kube_resourcequota_annotations Kubernetes annotations converted to Prometheus labels. # TYPE kube_resourcequota gauge # HELP kube_resourcequota_created [STABLE] Unix creation timestamp + # HELP kube_resourcequota_labels [STABLE] Kubernetes labels converted to Prometheus labels. + # TYPE kube_resourcequota_annotations gauge # TYPE kube_resourcequota_created gauge + # TYPE kube_resourcequota_labels gauge ` cases := []generateMetricsTestCase{ // Verify populating base metric and that metric for unset fields are skipped. @@ -132,10 +136,38 @@ func TestResourceQuotaStore(t *testing.T) { kube_resourcequota{namespace="testNS",resource="storage",resourcequota="quotaTest",type="used"} 9e+09 `, }, + // Verify kube_resourcequota_annotations and kube_resourcequota_labels are shown. + { + AllowAnnotationsList: []string{ + "foo", + }, + AllowLabelsList: []string{ + "hello", + }, + Obj: &v1.ResourceQuota{ + ObjectMeta: metav1.ObjectMeta{ + Name: "quotaTest", + CreationTimestamp: metav1.Time{Time: time.Unix(1500000000, 0)}, + Namespace: "testNS", + Annotations: map[string]string{ + "foo": "bar", + }, + Labels: map[string]string{ + "hello": "world", + }, + }, + Status: v1.ResourceQuotaStatus{}, + }, + Want: metadata + ` + kube_resourcequota_annotations{annotation_foo="bar",namespace="testNS",resourcequota="quotaTest"} 1 + kube_resourcequota_created{namespace="testNS",resourcequota="quotaTest"} 1.5e+09 + kube_resourcequota_labels{label_hello="world",namespace="testNS",resourcequota="quotaTest"} 1 + `, + }, } for i, c := range cases { - c.Func = generator.ComposeMetricGenFuncs(resourceQuotaMetricFamilies) - c.Headers = generator.ExtractMetricFamilyHeaders(resourceQuotaMetricFamilies) + c.Func = generator.ComposeMetricGenFuncs(resourceQuotaMetricFamilies(c.AllowAnnotationsList, c.AllowLabelsList)) + c.Headers = generator.ExtractMetricFamilyHeaders(resourceQuotaMetricFamilies(c.AllowAnnotationsList, c.AllowLabelsList)) if err := c.run(); err != nil { t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) }