Merge remote-tracking branch 'upstream/main'

This commit is contained in:
dfredell 2023-08-28 14:21:56 -05:00
commit 66a6caecc9
72 changed files with 436 additions and 231 deletions

View File

@ -21,7 +21,7 @@ env:
E2E_SETUP_KUBECTL: yes
SUDO: sudo
GO_VERSION: "^1.20"
GOLANGCI_LINT_VERSION: "v1.53.3"
GOLANGCI_LINT_VERSION: "v1.54.2"
jobs:
ci-go-lint:

View File

@ -15,8 +15,8 @@ GIT_COMMIT ?= $(shell git rev-parse --short HEAD)
OS ?= $(shell uname -s | tr A-Z a-z)
ALL_ARCH = amd64 arm arm64 ppc64le s390x
PKG = github.com/prometheus/common
PROMETHEUS_VERSION = 2.45.0
GO_VERSION = 1.20.6
PROMETHEUS_VERSION = 2.46.0
GO_VERSION = 1.20.7
IMAGE = $(REGISTRY)/kube-state-metrics
MULTI_ARCH_IMG = $(IMAGE)-$(ARCH)
USER ?= $(shell id -u -n)

View File

@ -53,9 +53,9 @@ Flags:
--log_file_max_size uint Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
--logtostderr log to standard error instead of files (default true)
--metric-allowlist string Comma-separated list of metrics to be exposed. This list comprises of exact metric names and/or regex patterns. The allowlist and denylist are mutually exclusive.
--metric-annotations-allowlist string Comma-separated list of Kubernetes annotations keys that will be used in the resource' labels metric. By default the metric contains only name and namespace labels. To include additional annotations provide a list of resource names in their plural form and Kubernetes annotation keys you would like to allow for them (Example: '=namespaces=[kubernetes.io/team,...],pods=[kubernetes.io/team],...)'. A single '*' can be provided per resource instead to allow any annotations, but that has severe performance implications (Example: '=pods=[*]').
--metric-annotations-allowlist string Comma-separated list of Kubernetes annotations keys that will be used in the resource' labels metric. By default the annotations metrics are not exposed. To include them, provide a list of resource names in their plural form and Kubernetes annotation keys you would like to allow for them (Example: '=namespaces=[kubernetes.io/team,...],pods=[kubernetes.io/team],...)'. A single '*' can be provided per resource instead to allow any annotations, but that has severe performance implications (Example: '=pods=[*]').
--metric-denylist string Comma-separated list of metrics not to be enabled. This list comprises of exact metric names and/or regex patterns. The allowlist and denylist are mutually exclusive.
--metric-labels-allowlist string Comma-separated list of additional Kubernetes label keys that will be used in the resource' labels metric. By default the metric contains only name and namespace labels. To include additional labels provide a list of resource names in their plural form and Kubernetes label keys you would like to allow for them (Example: '=namespaces=[k8s-label-1,k8s-label-n,...],pods=[app],...)'. A single '*' can be provided per resource instead to allow any labels, but that has severe performance implications (Example: '=pods=[*]'). Additionally, an asterisk (*) can be provided as a key, which will resolve to all resources, i.e., assuming '--resources=deployments,pods', '=*=[*]' will resolve to '=deployments=[*],pods=[*]'.
--metric-labels-allowlist string Comma-separated list of additional Kubernetes label keys that will be used in the resource' labels metric. By default the labels metrics are not exposed. To include them, provide a list of resource names in their plural form and Kubernetes label keys you would like to allow for them (Example: '=namespaces=[k8s-label-1,k8s-label-n,...],pods=[app],...)'. A single '*' can be provided per resource instead to allow any labels, but that has severe performance implications (Example: '=pods=[*]'). Additionally, an asterisk (*) can be provided as a key, which will resolve to all resources, i.e., assuming '--resources=deployments,pods', '=*=[*]' will resolve to '=deployments=[*],pods=[*]'.
--metric-opt-in-list string Comma-separated list of metrics which are opt-in and not enabled by default. This is in addition to the metric allow- and denylists
--namespaces string Comma-separated list of namespaces to be enabled. Defaults to ""
--namespaces-denylist string Comma-separated list of namespaces not to be enabled. If namespaces and namespaces-denylist are both set, only namespaces that are excluded in namespaces-denylist will be used.

View File

@ -24,6 +24,7 @@
| kube_pod_container_status_last_terminated_reason | Gauge | Describes the last reason the container was in terminated state | | `container`=&lt;container-name&gt; <br> `pod`=&lt;pod-name&gt; <br> `namespace`=&lt;pod-namespace&gt; <br> `reason`=&lt;last-terminated-reason&gt; <br> `uid`=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_container_status_last_terminated_exitcode | Gauge | Describes the exit code for the last container in terminated state. | | `container`=&lt;container-name&gt; <br> `pod`=&lt;pod-name&gt; <br> `namespace`=&lt;pod-namespace&gt; <br> `uid`=&lt;pod-uid&gt; | EXPERIMENTAL | - |
| kube_pod_container_status_ready | Gauge | Describes whether the containers readiness check succeeded | | `container`=&lt;container-name&gt; <br> `pod`=&lt;pod-name&gt; <br> `namespace`=&lt;pod-namespace&gt; <br> `uid`=&lt;pod-uid&gt; | STABLE | - |
| kube_pod_status_initialized_time | Gauge | Time when the pod is initialized. | seconds | `pod`=&lt;pod-name&gt; <br> `namespace`=&lt;pod-namespace&gt; <br> `uid`=&lt;pod-uid&gt; | EXPERIMENTAL |
| kube_pod_status_ready_time | Gauge | Time when pod passed readiness probes. | seconds | `pod`=&lt;pod-name&gt; <br> `namespace`=&lt;pod-namespace&gt; <br> `uid`=&lt;pod-uid&gt; | EXPERIMENTAL |
| kube_pod_status_container_ready_time | Gauge | Time when the container of the pod entered Ready state. | seconds | `pod`=&lt;pod-name&gt; <br> `namespace`=&lt;pod-namespace&gt; <br> `uid`=&lt;pod-uid&gt; | EXPERIMENTAL |
| kube_pod_container_status_restarts_total | Counter | The number of container restarts per container | | `container`=&lt;container-name&gt; <br> `namespace`=&lt;pod-namespace&gt; <br> `pod`=&lt;pod-name&gt; <br> `uid`=&lt;pod-uid&gt; | STABLE | - |

View File

@ -1,6 +1,8 @@
# ResourceQuota Metrics
| Metric name | Metric type | Labels/tags | Status |
| -------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------ |
| ------------------------------ | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| kube_resourcequota | Gauge | `resourcequota`=&lt;quota-name&gt; <br> `namespace`=&lt;namespace&gt; <br> `resource`=&lt;ResourceName&gt; <br> `type`=&lt;quota-type&gt; | STABLE |
| kube_resourcequota_created | Gauge | `resourcequota`=&lt;quota-name&gt; <br> `namespace`=&lt;namespace&gt; | STABLE |
| kube_resourcequota_annotations | Gauge | `resourcequota`=&lt;quota-name&gt; <br> `namespace`=&lt;namespace&gt; <br> `annotation_RESOURCE_QUOTA_ANNOTATION`=&lt;RESOURCE_QUOTA_ANNOTATION&gt; | EXPERIMENTAL |
| kube_resourcequota_labels | Gauge | `resourcequota`=&lt;quota-name&gt; <br> `namespace`=&lt;namespace&gt; <br> `label_RESOURCE_QUOTA_LABEL`=&lt;RESOURCE_QUOTA_LABEL&gt; | EXPERIMENTAL |

12
go.mod
View File

@ -17,13 +17,13 @@ require (
github.com/spf13/viper v1.16.0
github.com/stretchr/testify v1.8.4
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.27.4
k8s.io/apimachinery v0.27.4
k8s.io/client-go v0.27.4
k8s.io/component-base v0.27.4
k8s.io/api v0.27.5
k8s.io/apimachinery v0.27.5
k8s.io/client-go v0.27.5
k8s.io/component-base v0.27.5
k8s.io/klog/v2 v2.100.1
k8s.io/sample-controller v0.27.4
k8s.io/utils v0.0.0-20230711102312-30195339c3c7
k8s.io/sample-controller v0.27.5
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
)
require (

24
go.sum
View File

@ -606,22 +606,22 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.27.4 h1:0pCo/AN9hONazBKlNUdhQymmnfLRbSZjd5H5H3f0bSs=
k8s.io/api v0.27.4/go.mod h1:O3smaaX15NfxjzILfiln1D8Z3+gEYpjEpiNA/1EVK1Y=
k8s.io/apimachinery v0.27.4 h1:CdxflD4AF61yewuid0fLl6bM4a3q04jWel0IlP+aYjs=
k8s.io/apimachinery v0.27.4/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E=
k8s.io/client-go v0.27.4 h1:vj2YTtSJ6J4KxaC88P4pMPEQECWMY8gqPqsTgUKzvjk=
k8s.io/client-go v0.27.4/go.mod h1:ragcly7lUlN0SRPk5/ZkGnDjPknzb37TICq07WhI6Xc=
k8s.io/component-base v0.27.4 h1:Wqc0jMKEDGjKXdae8hBXeskRP//vu1m6ypC+gwErj4c=
k8s.io/component-base v0.27.4/go.mod h1:hoiEETnLc0ioLv6WPeDt8vD34DDeB35MfQnxCARq3kY=
k8s.io/api v0.27.5 h1:49hIzqJNSuOQpA53MMihgAS4YDcQitTy58B9PMFthLc=
k8s.io/api v0.27.5/go.mod h1:zjBZB+c0KDU55Wxb9Bob9WZGxu9zdKHitzHxBtaIVoA=
k8s.io/apimachinery v0.27.5 h1:6Q5HBXYJJPisd6yDVAprLe6FQsmw7a7Cu69dcrpQET8=
k8s.io/apimachinery v0.27.5/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E=
k8s.io/client-go v0.27.5 h1:sH/fkqzk35kuf0GPx+dZuN7fhEswBSAVCrWFq3E1km0=
k8s.io/client-go v0.27.5/go.mod h1:u+IKnqPZSPw51snIMKiIAV8LQQ+hya5bvxpOOPTUXPI=
k8s.io/component-base v0.27.5 h1:IXo80yOVx7qXG2g1loPpo2g1HUK3CnxNpq9LtGmXAmM=
k8s.io/component-base v0.27.5/go.mod h1:AGJyFHmaxplY4C4lu18UrJBNHcxdv0o6jOL/+HcC0S0=
k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg=
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg=
k8s.io/sample-controller v0.27.4 h1:oeKVVOWw+fVaZVWCw3l9myrAoNUqR8A4BcA91fyyZaU=
k8s.io/sample-controller v0.27.4/go.mod h1:bfGT2cEyzWjfCqVSrWPbNsym9MkgKz7Z7Bwl0tjysOo=
k8s.io/utils v0.0.0-20230711102312-30195339c3c7 h1:ZgnF1KZsYxWIifwSNZFZgNtWE89WI5yiP5WwlfDoIyc=
k8s.io/utils v0.0.0-20230711102312-30195339c3c7/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
k8s.io/sample-controller v0.27.5 h1:N3mMPdEFJ8gdn7HMCIecnTU7h6YVfVJjSDt72nxAocc=
k8s.io/sample-controller v0.27.5/go.mod h1:KtTxV9H5DpvbU5WpM2o/Cpv/fuZykJhqBqCJdNfFRpg=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

View File

@ -38,10 +38,6 @@ import (
policyv1 "k8s.io/api/policy/v1"
rbacv1 "k8s.io/api/rbac/v1"
storagev1 "k8s.io/api/storage/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/discovery"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
"k8s.io/klog/v2"
@ -431,7 +427,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 {
@ -544,10 +540,7 @@ func (b *Builder) buildCustomResourceStores(resourceName string,
metricFamilies = generator.FilterFamilyGenerators(b.familyGeneratorFilter, metricFamilies)
composedMetricGenFuncs := generator.ComposeMetricGenFuncs(metricFamilies)
var familyHeaders []string
if b.hasResources(resourceName, expectedType) {
familyHeaders = generator.ExtractMetricFamilyHeaders(metricFamilies)
}
familyHeaders := generator.ExtractMetricFamilyHeaders(metricFamilies)
gvr := util.GVRFromType(resourceName, expectedType)
var gvrString string
@ -590,65 +583,6 @@ func (b *Builder) buildCustomResourceStores(resourceName string,
return stores
}
func (b *Builder) hasResources(resourceName string, expectedType interface{}) bool {
gvr := util.GVRFromType(resourceName, expectedType)
if gvr == nil {
return true
}
discoveryClient, err := util.CreateDiscoveryClient(b.utilOptions.Apiserver, b.utilOptions.Kubeconfig)
if err != nil {
klog.ErrorS(err, "Failed to create discovery client")
return false
}
g := gvr.Group
v := gvr.Version
r := gvr.Resource
isCRDInstalled, err := discovery.IsResourceEnabled(discoveryClient, schema.GroupVersionResource{
Group: g,
Version: v,
Resource: r,
})
if err != nil {
klog.ErrorS(err, "Failed to check if CRD is enabled", "group", g, "version", v, "resource", r)
return false
}
if !isCRDInstalled {
klog.InfoS("CRD is not installed", "group", g, "version", v, "resource", r)
return false
}
// Wait for the resource to come up.
timer := time.NewTimer(ResourceDiscoveryTimeout)
ticker := time.NewTicker(ResourceDiscoveryInterval)
dynamicClient, err := util.CreateDynamicClient(b.utilOptions.Apiserver, b.utilOptions.Kubeconfig)
if err != nil {
klog.ErrorS(err, "Failed to create dynamic client")
return false
}
var list *unstructured.UnstructuredList
for range ticker.C {
select {
case <-timer.C:
klog.InfoS("No CRs found for GVR", "group", g, "version", v, "resource", r)
return false
default:
list, err = dynamicClient.Resource(schema.GroupVersionResource{
Group: g,
Version: v,
Resource: r,
}).List(b.ctx, metav1.ListOptions{})
if err != nil {
klog.ErrorS(err, "Failed to list objects", "group", g, "version", v, "resource", r)
return false
}
}
if len(list.Items) > 0 {
break
}
}
return true
}
// startReflector starts a Kubernetes client-go reflector with the given
// listWatcher and registers it with the given store.
func (b *Builder) startReflector(

View File

@ -49,6 +49,9 @@ func csrMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat
basemetrics.ALPHA,
"",
wrapCSRFunc(func(j *certv1.CertificateSigningRequest) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", j.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -68,6 +71,9 @@ func csrMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat
basemetrics.STABLE,
"",
wrapCSRFunc(func(j *certv1.CertificateSigningRequest) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", j.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -57,7 +57,6 @@ func TestCsrStore(t *testing.T) {
kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test",signer_name="signer"} 1.5e+09
kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",signer_name="signer",condition="approved"} 0
kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",signer_name="signer",condition="denied"} 0
kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",signer_name="signer"} 1
kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test",signer_name="signer"} 0
`,
MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"},
@ -87,7 +86,6 @@ func TestCsrStore(t *testing.T) {
kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test",signer_name="signer"} 1.5e+09
kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",signer_name="signer",condition="approved"} 0
kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",signer_name="signer",condition="denied"} 1
kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",signer_name="signer"} 1
kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test",signer_name="signer"} 0
`,
MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"},
@ -117,7 +115,6 @@ func TestCsrStore(t *testing.T) {
kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test",signer_name="signer"} 1.5e+09
kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",signer_name="signer",condition="approved"} 1
kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",signer_name="signer",condition="denied"} 0
kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",signer_name="signer"} 1
kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test",signer_name="signer"} 0
`,
MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"},
@ -148,7 +145,6 @@ func TestCsrStore(t *testing.T) {
kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test",signer_name="signer"} 1.5e+09
kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",signer_name="signer",condition="approved"} 1
kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",signer_name="signer",condition="denied"} 0
kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",signer_name="signer"} 1
kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test",signer_name="signer"} 13
`,
MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"},
@ -181,7 +177,6 @@ func TestCsrStore(t *testing.T) {
kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test",signer_name="signer"} 1.5e+09
kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",signer_name="signer",condition="approved"} 1
kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",signer_name="signer",condition="denied"} 1
kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",signer_name="signer"} 1
kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test",signer_name="signer"} 0
`,
MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"},
@ -220,7 +215,6 @@ func TestCsrStore(t *testing.T) {
kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test",signer_name="signer"} 1.5e+09
kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",signer_name="signer",condition="approved"} 2
kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",signer_name="signer",condition="denied"} 2
kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",signer_name="signer"} 1
kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test",signer_name="signer"} 0
`,
MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"},

View File

@ -48,6 +48,9 @@ func clusterRoleMetricFamilies(allowAnnotationsList, allowLabelsList []string) [
basemetrics.ALPHA,
"",
wrapClusterRoleFunc(func(r *rbacv1.ClusterRole) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", r.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -67,6 +70,9 @@ func clusterRoleMetricFamilies(allowAnnotationsList, allowLabelsList []string) [
basemetrics.ALPHA,
"",
wrapClusterRoleFunc(func(r *rbacv1.ClusterRole) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", r.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -48,6 +48,9 @@ func clusterRoleBindingMetricFamilies(allowAnnotationsList, allowLabelsList []st
basemetrics.ALPHA,
"",
wrapClusterRoleBindingFunc(func(r *rbacv1.ClusterRoleBinding) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", r.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -67,6 +70,9 @@ func clusterRoleBindingMetricFamilies(allowAnnotationsList, allowLabelsList []st
basemetrics.ALPHA,
"",
wrapClusterRoleBindingFunc(func(r *rbacv1.ClusterRoleBinding) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", r.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -44,6 +44,9 @@ func configMapMetricFamilies(allowAnnotationsList, allowLabelsList []string) []g
basemetrics.ALPHA,
"",
wrapConfigMapFunc(func(c *v1.ConfigMap) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", c.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -63,6 +66,9 @@ func configMapMetricFamilies(allowAnnotationsList, allowLabelsList []string) []g
basemetrics.STABLE,
"",
wrapConfigMapFunc(func(c *v1.ConfigMap) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", c.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -36,7 +36,7 @@ import (
)
var (
descCronJobAnnotationsName = "kube_cronjob_annotations"
descCronJobAnnotationsName = "kube_cronjob_annotations" //nolint:gosec
descCronJobAnnotationsHelp = "Kubernetes annotations converted to Prometheus labels."
descCronJobLabelsName = "kube_cronjob_labels"
descCronJobLabelsHelp = "Kubernetes labels converted to Prometheus labels."
@ -52,6 +52,9 @@ func cronJobMetricFamilies(allowAnnotationsList, allowLabelsList []string) []gen
basemetrics.ALPHA,
"",
wrapCronJobFunc(func(j *batchv1.CronJob) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", j.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -71,6 +74,9 @@ func cronJobMetricFamilies(allowAnnotationsList, allowLabelsList []string) []gen
basemetrics.STABLE,
"",
wrapCronJobFunc(func(j *batchv1.CronJob) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", j.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -161,7 +161,6 @@ func TestCronJobStore(t *testing.T) {
# TYPE kube_cronjob_status_last_schedule_time gauge
kube_cronjob_info{concurrency_policy="Forbid",cronjob="ActiveRunningCronJob1",namespace="ns1",schedule="0 */6 * * *"} 1
kube_cronjob_annotations{annotation_app_k8s_io_owner="@foo",cronjob="ActiveRunningCronJob1",namespace="ns1"} 1
kube_cronjob_labels{cronjob="ActiveRunningCronJob1",namespace="ns1"} 1
kube_cronjob_spec_failed_job_history_limit{cronjob="ActiveRunningCronJob1",namespace="ns1"} 1
kube_cronjob_spec_starting_deadline_seconds{cronjob="ActiveRunningCronJob1",namespace="ns1"} 300
kube_cronjob_spec_successful_job_history_limit{cronjob="ActiveRunningCronJob1",namespace="ns1"} 3
@ -235,7 +234,6 @@ func TestCronJobStore(t *testing.T) {
# TYPE kube_cronjob_status_last_schedule_time gauge
# TYPE kube_cronjob_status_last_successful_time gauge
kube_cronjob_info{concurrency_policy="Forbid",cronjob="SuspendedCronJob1",namespace="ns1",schedule="0 */3 * * *"} 1
kube_cronjob_labels{cronjob="SuspendedCronJob1",namespace="ns1"} 1
kube_cronjob_spec_failed_job_history_limit{cronjob="SuspendedCronJob1",namespace="ns1"} 1
kube_cronjob_spec_starting_deadline_seconds{cronjob="SuspendedCronJob1",namespace="ns1"} 300
kube_cronjob_spec_successful_job_history_limit{cronjob="SuspendedCronJob1",namespace="ns1"} 3
@ -295,7 +293,6 @@ func TestCronJobStore(t *testing.T) {
# TYPE kube_cronjob_status_last_schedule_time gauge
# TYPE kube_cronjob_status_last_successful_time gauge
kube_cronjob_info{concurrency_policy="Forbid",cronjob="SuspendedCronJob1",namespace="ns1",schedule="0 */3 * * *"} 1
kube_cronjob_labels{cronjob="SuspendedCronJob1",namespace="ns1"} 1
kube_cronjob_spec_failed_job_history_limit{cronjob="SuspendedCronJob1",namespace="ns1"} 1
kube_cronjob_spec_starting_deadline_seconds{cronjob="SuspendedCronJob1",namespace="ns1"} 300
kube_cronjob_spec_successful_job_history_limit{cronjob="SuspendedCronJob1",namespace="ns1"} 3
@ -364,7 +361,6 @@ 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",namespace="ns1"} 1
` +
fmt.Sprintf("kube_cronjob_next_schedule_time{cronjob=\"ActiveCronJob1NoLastScheduled\",namespace=\"ns1\"} %ve+09\n",
float64(ActiveCronJob1NoLastScheduledNextScheduleTime.Unix())/math.Pow10(9)),

View File

@ -230,6 +230,9 @@ func daemonSetMetricFamilies(allowAnnotationsList, allowLabelsList []string) []g
basemetrics.ALPHA,
"",
wrapDaemonSetFunc(func(d *v1.DaemonSet) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", d.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -249,6 +252,9 @@ func daemonSetMetricFamilies(allowAnnotationsList, allowLabelsList []string) []g
basemetrics.STABLE,
"",
wrapDaemonSetFunc(func(d *v1.DaemonSet) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", d.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -86,7 +86,6 @@ func TestDaemonSetStore(t *testing.T) {
kube_daemonset_status_observed_generation{daemonset="ds1",namespace="ns1"} 2
kube_daemonset_status_updated_number_scheduled{daemonset="ds1",namespace="ns1"} 0
kube_daemonset_annotations{annotation_app_k8s_io_owner="@foo",daemonset="ds1",namespace="ns1"} 1
kube_daemonset_labels{daemonset="ds1",namespace="ns1"} 1
`,
MetricNames: []string{
"kube_daemonset_annotations",
@ -149,7 +148,6 @@ 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",namespace="ns2"} 1
kube_daemonset_created{namespace="ns2",daemonset="ds2"} 1.5e+09
`,
MetricNames: []string{
@ -216,7 +214,6 @@ 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",namespace="ns3"} 1
`,
MetricNames: []string{
"kube_daemonset_created",

View File

@ -290,6 +290,9 @@ func deploymentMetricFamilies(allowAnnotationsList, allowLabelsList []string) []
basemetrics.ALPHA,
"",
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", d.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -309,6 +312,9 @@ func deploymentMetricFamilies(allowAnnotationsList, allowLabelsList []string) []
basemetrics.STABLE,
"",
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", d.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -115,7 +115,6 @@ func TestDeploymentStore(t *testing.T) {
Want: metadata + `
kube_deployment_annotations{annotation_company_io_team="my-brilliant-team",deployment="depl1",namespace="ns1"} 1
kube_deployment_created{deployment="depl1",namespace="ns1"} 1.5e+09
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
@ -170,8 +169,6 @@ func TestDeploymentStore(t *testing.T) {
},
},
Want: metadata + `
kube_deployment_annotations{deployment="depl2",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

View File

@ -86,6 +86,9 @@ func endpointMetricFamilies(allowAnnotationsList, allowLabelsList []string) []ge
basemetrics.ALPHA,
"",
wrapEndpointFunc(func(e *v1.Endpoints) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", e.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -105,6 +108,9 @@ func endpointMetricFamilies(allowAnnotationsList, allowLabelsList []string) []ge
basemetrics.STABLE,
"",
wrapEndpointFunc(func(e *v1.Endpoints) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", e.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -89,12 +89,10 @@ func TestEndpointStore(t *testing.T) {
},
},
Want: metadata + `
kube_endpoint_annotations{endpoint="test-endpoint",namespace="default"} 1
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
kube_endpoint_ports{endpoint="test-endpoint",namespace="default",port_name="http",port_protocol="TCP",port_number="8080"} 1
kube_endpoint_ports{endpoint="test-endpoint",namespace="default",port_name="app",port_protocol="TCP",port_number="8081"} 1
kube_endpoint_ports{endpoint="test-endpoint",namespace="default",port_name="https",port_protocol="TCP",port_number="8443"} 1
@ -134,12 +132,10 @@ func TestEndpointStore(t *testing.T) {
},
},
Want: metadata + `
kube_endpoint_annotations{endpoint="single-port-endpoint",namespace="default"} 1
kube_endpoint_address_available{endpoint="single-port-endpoint",namespace="default"} 2
kube_endpoint_address_not_ready{endpoint="single-port-endpoint",namespace="default"} 1
kube_endpoint_created{endpoint="single-port-endpoint",namespace="default"} 1.5e+09
kube_endpoint_info{endpoint="single-port-endpoint",namespace="default"} 1
kube_endpoint_labels{endpoint="single-port-endpoint",namespace="default"} 1
kube_endpoint_ports{endpoint="single-port-endpoint",namespace="default",port_name="",port_number="8080",port_protocol="TCP"} 1
kube_endpoint_address{endpoint="single-port-endpoint",namespace="default",ip="127.0.0.1",ready="true"} 1
kube_endpoint_address{endpoint="single-port-endpoint",namespace="default",ip="10.0.0.1",ready="true"} 1

View File

@ -174,6 +174,9 @@ func endpointSliceMetricFamilies(allowAnnotationsList, allowLabelsList []string)
basemetrics.ALPHA,
"",
wrapEndpointSliceFunc(func(s *discoveryv1.EndpointSlice) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", s.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -193,6 +196,9 @@ func endpointSliceMetricFamilies(allowAnnotationsList, allowLabelsList []string)
basemetrics.ALPHA,
"",
wrapEndpointSliceFunc(func(s *discoveryv1.EndpointSlice) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", s.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -144,7 +144,6 @@ func TestEndpointSliceStore(t *testing.T) {
# TYPE kube_endpointslice_annotations gauge
# TYPE kube_endpointslice_labels gauge
kube_endpointslice_annotations{endpointslice="test_endpointslice-labels",annotation_foo="baz"} 1
kube_endpointslice_labels{endpointslice="test_endpointslice-labels"} 1
`,
MetricNames: []string{
"kube_endpointslice_annotations", "kube_endpointslice_labels",

View File

@ -344,6 +344,9 @@ func createHPAAnnotations(allowAnnotationsList []string) generator.FamilyGenerat
basemetrics.ALPHA,
"",
wrapHPAFunc(func(a *autoscaling.HorizontalPodAutoscaler) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", a.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -366,6 +369,9 @@ func createHPALabels(allowLabelsList []string) generator.FamilyGenerator {
basemetrics.STABLE,
"",
wrapHPAFunc(func(a *autoscaling.HorizontalPodAutoscaler) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", a.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -210,8 +210,6 @@ func TestHPAStore(t *testing.T) {
},
Want: metadata + `
kube_horizontalpodautoscaler_info{horizontalpodautoscaler="hpa1",namespace="ns1",scaletargetref_api_version="apps/v1",scaletargetref_kind="Deployment",scaletargetref_name="deployment1"} 1
kube_horizontalpodautoscaler_annotations{horizontalpodautoscaler="hpa1",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
@ -389,7 +387,6 @@ func TestHPAStore(t *testing.T) {
Want: metadata + `
kube_horizontalpodautoscaler_info{horizontalpodautoscaler="hpa2",namespace="ns1",scaletargetref_kind="Deployment",scaletargetref_name="deployment1"} 1
kube_horizontalpodautoscaler_annotations{annotation_app_k8s_io_owner="@foo",horizontalpodautoscaler="hpa2",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

View File

@ -34,7 +34,7 @@ import (
)
var (
descIngressAnnotationsName = "kube_ingress_annotations"
descIngressAnnotationsName = "kube_ingress_annotations" //nolint:gosec
descIngressAnnotationsHelp = "Kubernetes annotations converted to Prometheus labels."
descIngressLabelsName = "kube_ingress_labels"
descIngressLabelsHelp = "Kubernetes labels converted to Prometheus labels."
@ -75,6 +75,9 @@ func ingressMetricFamilies(allowAnnotationsList, allowLabelsList []string) []gen
basemetrics.ALPHA,
"",
wrapIngressFunc(func(i *networkingv1.Ingress) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", i.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -94,6 +97,9 @@ func ingressMetricFamilies(allowAnnotationsList, allowLabelsList []string) []gen
basemetrics.STABLE,
"",
wrapIngressFunc(func(i *networkingv1.Ingress) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", i.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -75,7 +75,6 @@ func TestIngressStore(t *testing.T) {
kube_ingress_info{namespace="ns1",ingress="ingress1",ingressclass="_default"} 1
kube_ingress_metadata_resource_version{namespace="ns1",ingress="ingress1"} 0
kube_ingress_annotations{annotation_app_k8s_io_owner="@foo",namespace="ns1",ingress="ingress1"} 1
kube_ingress_labels{namespace="ns1",ingress="ingress1"} 1
`,
MetricNames: []string{
"kube_ingress_info",
@ -97,7 +96,6 @@ func TestIngressStore(t *testing.T) {
kube_ingress_info{namespace="ns2",ingress="ingress2",ingressclass="_default"} 1
kube_ingress_created{namespace="ns2",ingress="ingress2"} 1.501569018e+09
kube_ingress_metadata_resource_version{namespace="ns2",ingress="ingress2"} 123456
kube_ingress_labels{namespace="ns2",ingress="ingress2"} 1
`,
MetricNames: []string{"kube_ingress_info", "kube_ingress_metadata_resource_version", "kube_ingress_created", "kube_ingress_labels", "kube_ingress_path", "kube_ingress_tls"},
},
@ -114,7 +112,6 @@ func TestIngressStore(t *testing.T) {
Want: metadata + `
kube_ingress_info{namespace="ns3",ingress="ingress3",ingressclass="_default"} 1
kube_ingress_created{namespace="ns3",ingress="ingress3"} 1.501569018e+09
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"},
},
@ -167,7 +164,6 @@ func TestIngressStore(t *testing.T) {
Want: metadata + `
kube_ingress_info{namespace="ns4",ingress="ingress4",ingressclass="_default"} 1
kube_ingress_created{namespace="ns4",ingress="ingress4"} 1.501569018e+09
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
kube_ingress_path{namespace="ns4",ingress="ingress4",host="somehost",path="/somepath2",service_name="",service_port=""} 1
`,
@ -194,7 +190,6 @@ func TestIngressStore(t *testing.T) {
Want: metadata + `
kube_ingress_info{namespace="ns5",ingress="ingress5",ingressclass="_default"} 1
kube_ingress_created{namespace="ns5",ingress="ingress5"} 1.501569018e+09
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
`,
@ -216,7 +211,6 @@ func TestIngressStore(t *testing.T) {
kube_ingress_info{namespace="ns6",ingress="ingress6",ingressclass="test"} 1
kube_ingress_created{namespace="ns6",ingress="ingress6"} 1.501569018e+09
kube_ingress_metadata_resource_version{namespace="ns6",ingress="ingress6"} 123456
kube_ingress_labels{namespace="ns6",ingress="ingress6"} 1
`,
MetricNames: []string{"kube_ingress_info", "kube_ingress_metadata_resource_version", "kube_ingress_created", "kube_ingress_labels", "kube_ingress_path", "kube_ingress_tls"},
},
@ -236,7 +230,6 @@ func TestIngressStore(t *testing.T) {
kube_ingress_info{namespace="ns7",ingress="ingress7",ingressclass="test"} 1
kube_ingress_created{namespace="ns7",ingress="ingress7"} 1.501569018e+09
kube_ingress_metadata_resource_version{namespace="ns7",ingress="ingress7"} 123456
kube_ingress_labels{namespace="ns7",ingress="ingress7"} 1
`,
MetricNames: []string{"kube_ingress_info", "kube_ingress_metadata_resource_version", "kube_ingress_created", "kube_ingress_labels", "kube_ingress_path", "kube_ingress_tls"},
},

View File

@ -32,7 +32,7 @@ import (
var (
descIngressClassAnnotationsName = "kube_ingressclass_annotations"
descIngressClassAnnotationsHelp = "Kubernetes annotations converted to Prometheus labels."
descIngressClassLabelsName = "kube_ingressclass_labels"
descIngressClassLabelsName = "kube_ingressclass_labels" //nolint:gosec
descIngressClassLabelsHelp = "Kubernetes labels converted to Prometheus labels."
descIngressClassLabelsDefaultLabels = []string{"ingressclass"}
)
@ -80,6 +80,9 @@ func ingressClassMetricFamilies(allowAnnotationsList, allowLabelsList []string)
basemetrics.ALPHA,
"",
wrapIngressClassFunc(func(s *networkingv1.IngressClass) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", s.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -99,6 +102,9 @@ func ingressClassMetricFamilies(allowAnnotationsList, allowLabelsList []string)
basemetrics.ALPHA,
"",
wrapIngressClassFunc(func(s *networkingv1.IngressClass) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", s.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -88,7 +88,6 @@ func TestIngressClassStore(t *testing.T) {
# TYPE kube_ingressclass_annotations gauge
# TYPE kube_ingressclass_labels gauge
kube_ingressclass_annotations{ingressclass="test_ingressclass-labels",annotation_ingressclass_kubernetes_io_is_default_class="true"} 1
kube_ingressclass_labels{ingressclass="test_ingressclass-labels"} 1
`,
MetricNames: []string{
"kube_ingressclass_annotations", "kube_ingressclass_labels",

View File

@ -51,6 +51,9 @@ func jobMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat
basemetrics.ALPHA,
"",
wrapJobFunc(func(j *v1batch.Job) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", j.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -70,6 +73,9 @@ func jobMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat
basemetrics.STABLE,
"",
wrapJobFunc(func(j *v1batch.Job) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", j.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -112,11 +112,9 @@ func TestJobStore(t *testing.T) {
},
},
Want: metadata + `
kube_job_annotations{job_name="RunningJob1",namespace="ns1"} 1
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",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
@ -153,13 +151,11 @@ func TestJobStore(t *testing.T) {
},
},
Want: metadata + `
kube_job_annotations{job_name="SuccessfulJob1",namespace="ns1"} 1
kube_job_owner{job_name="SuccessfulJob1",namespace="ns1",owner_is_controller="",owner_kind="",owner_name=""} 1
kube_job_complete{condition="false",job_name="SuccessfulJob1",namespace="ns1"} 0
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",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
@ -197,13 +193,11 @@ func TestJobStore(t *testing.T) {
},
},
Want: metadata + `
kube_job_annotations{job_name="FailedJob1",namespace="ns1"} 1
kube_job_owner{job_name="FailedJob1",namespace="ns1",owner_is_controller="",owner_kind="",owner_name=""} 1
kube_job_failed{condition="false",job_name="FailedJob1",namespace="ns1"} 0
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",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
@ -247,10 +241,8 @@ func TestJobStore(t *testing.T) {
kube_job_complete{condition="false",job_name="SuccessfulJob2NoActiveDeadlineSeconds",namespace="ns1"} 0
kube_job_complete{condition="true",job_name="SuccessfulJob2NoActiveDeadlineSeconds",namespace="ns1"} 1
kube_job_annotations{job_name="SuccessfulJob2NoActiveDeadlineSeconds",namespace="ns1"} 1
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",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

View File

@ -68,6 +68,10 @@ func namespaceMetricFamilies(allowAnnotationsList, allowLabelsList []string) []g
basemetrics.ALPHA,
"",
wrapNamespaceFunc(func(n *v1.Namespace) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", n.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -87,6 +91,9 @@ func namespaceMetricFamilies(allowAnnotationsList, allowLabelsList []string) []g
basemetrics.STABLE,
"",
wrapNamespaceFunc(func(n *v1.Namespace) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", n.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -56,8 +56,6 @@ func TestNamespaceStore(t *testing.T) {
},
},
Want: metadata + `
kube_namespace_annotations{namespace="nsActiveTest"} 1
kube_namespace_labels{namespace="nsActiveTest"} 1
kube_namespace_status_phase{namespace="nsActiveTest",phase="Active"} 1
kube_namespace_status_phase{namespace="nsActiveTest",phase="Terminating"} 0
`,
@ -75,8 +73,6 @@ func TestNamespaceStore(t *testing.T) {
},
},
Want: metadata + `
kube_namespace_annotations{namespace="nsTerminateTest"} 1
kube_namespace_labels{namespace="nsTerminateTest"} 1
kube_namespace_status_phase{namespace="nsTerminateTest",phase="Active"} 0
kube_namespace_status_phase{namespace="nsTerminateTest",phase="Terminating"} 1
`,
@ -99,8 +95,6 @@ func TestNamespaceStore(t *testing.T) {
},
},
Want: metadata + `
kube_namespace_annotations{namespace="nsTerminateWithConditionTest"} 1
kube_namespace_labels{namespace="nsTerminateWithConditionTest"} 1
kube_namespace_status_phase{namespace="nsTerminateWithConditionTest",phase="Active"} 0
kube_namespace_status_phase{namespace="nsTerminateWithConditionTest",phase="Terminating"} 1
kube_namespace_status_condition{condition="NamespaceDeletionContentFailure",namespace="nsTerminateWithConditionTest",status="false"} 0
@ -132,9 +126,7 @@ func TestNamespaceStore(t *testing.T) {
},
},
Want: metadata + `
kube_namespace_annotations{namespace="ns1"} 1
kube_namespace_created{namespace="ns1"} 1.5e+09
kube_namespace_labels{namespace="ns1"} 1
kube_namespace_status_phase{namespace="ns1",phase="Active"} 1
kube_namespace_status_phase{namespace="ns1",phase="Terminating"} 0
`,
@ -156,8 +148,6 @@ func TestNamespaceStore(t *testing.T) {
},
},
Want: metadata + `
kube_namespace_annotations{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
`,

View File

@ -66,6 +66,9 @@ func networkPolicyMetricFamilies(allowAnnotationsList, allowLabelsList []string)
basemetrics.ALPHA,
"",
wrapNetworkPolicyFunc(func(n *networkingv1.NetworkPolicy) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", n.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -85,6 +88,9 @@ func networkPolicyMetricFamilies(allowAnnotationsList, allowLabelsList []string)
basemetrics.ALPHA,
"",
wrapNetworkPolicyFunc(func(n *networkingv1.NetworkPolicy) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", n.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -55,7 +55,6 @@ func TestNetworkPolicyStore(t *testing.T) {
},
Want: `
kube_networkpolicy_created{namespace="ns1",networkpolicy="netpol1"} 1.501569018e+09
kube_networkpolicy_labels{namespace="ns1",networkpolicy="netpol1"} 1
kube_networkpolicy_spec_egress_rules{namespace="ns1",networkpolicy="netpol1"} 3
kube_networkpolicy_spec_ingress_rules{namespace="ns1",networkpolicy="netpol1"} 2
`,

View File

@ -164,6 +164,9 @@ func createNodeAnnotationsGenerator(allowAnnotationsList []string) generator.Fam
basemetrics.ALPHA,
"",
wrapNodeFunc(func(n *v1.Node) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", n.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -186,6 +189,9 @@ func createNodeLabelsGenerator(allowLabelsList []string) generator.FamilyGenerat
basemetrics.STABLE,
"",
wrapNodeFunc(func(n *v1.Node) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", n.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -61,7 +61,6 @@ func TestNodeStore(t *testing.T) {
# TYPE kube_node_labels gauge
# TYPE kube_node_spec_unschedulable gauge
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-uniqueid",internal_ip="1.2.3.4",system_uuid="6a934e21-5207-4a84-baea-3a952d926c80"} 1
kube_node_labels{node="127.0.0.1"} 1
kube_node_spec_unschedulable{node="127.0.0.1"} 0
`,
MetricNames: []string{"kube_node_spec_unschedulable", "kube_node_labels", "kube_node_info"},
@ -142,7 +141,6 @@ 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",system_uuid="6a934e21-5207-4a84-baea-3a952d926c80"} 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

View File

@ -85,6 +85,9 @@ func persistentVolumeMetricFamilies(allowAnnotationsList, allowLabelsList []stri
basemetrics.ALPHA,
"",
wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", p.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -104,6 +107,9 @@ func persistentVolumeMetricFamilies(allowAnnotationsList, allowLabelsList []stri
basemetrics.STABLE,
"",
wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", p.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -23,7 +23,7 @@ import (
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/pointer"
"k8s.io/utils/ptr"
generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator"
)
@ -415,7 +415,7 @@ func TestPersistentVolumeStore(t *testing.T) {
Spec: v1.PersistentVolumeSpec{
PersistentVolumeSource: v1.PersistentVolumeSource{
Local: &v1.LocalVolumeSource{
FSType: pointer.String("ext4"),
FSType: ptr.To("ext4"),
Path: "/mnt/data",
},
},
@ -522,7 +522,6 @@ func TestPersistentVolumeStore(t *testing.T) {
Want: `
# HELP kube_persistentvolume_labels [STABLE] Kubernetes labels converted to Prometheus labels.
# TYPE kube_persistentvolume_labels gauge
kube_persistentvolume_labels{persistentvolume="test-labeled-pv"} 1
`,
MetricNames: []string{"kube_persistentvolume_labels"},
},
@ -538,7 +537,6 @@ func TestPersistentVolumeStore(t *testing.T) {
Want: `
# HELP kube_persistentvolume_labels [STABLE] Kubernetes labels converted to Prometheus labels.
# TYPE kube_persistentvolume_labels gauge
kube_persistentvolume_labels{persistentvolume="test-unlabeled-pv"} 1
`,
MetricNames: []string{"kube_persistentvolume_labels"},
},
@ -658,8 +656,6 @@ func TestPersistentVolumeStore(t *testing.T) {
# HELP kube_persistentvolume_labels [STABLE] Kubernetes labels converted to Prometheus labels.
# TYPE kube_persistentvolume_annotations gauge
# TYPE kube_persistentvolume_labels gauge
kube_persistentvolume_annotations{persistentvolume="test-defaul-labels-annotations"} 1
kube_persistentvolume_labels{persistentvolume="test-defaul-labels-annotations"} 1
`,
MetricNames: []string{
"kube_persistentvolume_annotations",

View File

@ -49,6 +49,9 @@ func persistentVolumeClaimMetricFamilies(allowAnnotationsList, allowLabelsList [
basemetrics.STABLE,
"",
wrapPersistentVolumeClaimFunc(func(p *v1.PersistentVolumeClaim) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", p.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -68,6 +71,9 @@ func persistentVolumeClaimMetricFamilies(allowAnnotationsList, allowLabelsList [
basemetrics.ALPHA,
"",
wrapPersistentVolumeClaimFunc(func(p *v1.PersistentVolumeClaim) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", p.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -92,7 +92,6 @@ func TestPersistentVolumeClaimStore(t *testing.T) {
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_annotations{annotation_app_k8s_io_owner="@foo",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
@ -164,7 +163,6 @@ 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_annotations{namespace="default",persistentvolumeclaim="mysql-data"} 1
kube_persistentvolumeclaim_labels{label_app="mysql-server",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
@ -218,7 +216,6 @@ func TestPersistentVolumeClaimStore(t *testing.T) {
kube_persistentvolumeclaim_status_phase{namespace="default",persistentvolumeclaim="prometheus-data",phase="Bound"} 0
kube_persistentvolumeclaim_status_phase{namespace="default",persistentvolumeclaim="prometheus-data",phase="Lost"} 0
kube_persistentvolumeclaim_status_phase{namespace="default",persistentvolumeclaim="prometheus-data",phase="Pending"} 1
kube_persistentvolumeclaim_labels{namespace="default",persistentvolumeclaim="prometheus-data"} 1
kube_persistentvolumeclaim_access_mode{namespace="default",persistentvolumeclaim="prometheus-data",access_mode="ReadWriteOnce"} 1
`,
MetricNames: []string{"kube_persistentvolumeclaim_info", "kube_persistentvolumeclaim_status_phase", "kube_persistentvolumeclaim_resource_requests_storage_bytes", "kube_persistentvolumeclaim_labels", "kube_persistentvolumeclaim_access_mode", "kube_persistentvolumeclaim_status_condition", "kube_persistentvolumeclaim_created"},
@ -266,8 +263,6 @@ func TestPersistentVolumeClaimStore(t *testing.T) {
kube_persistentvolumeclaim_status_phase{namespace="",persistentvolumeclaim="mongo-data",phase="Bound"} 0
kube_persistentvolumeclaim_status_phase{namespace="",persistentvolumeclaim="mongo-data",phase="Lost"} 1
kube_persistentvolumeclaim_status_phase{namespace="",persistentvolumeclaim="mongo-data",phase="Pending"} 0
kube_persistentvolumeclaim_labels{namespace="",persistentvolumeclaim="mongo-data"} 1
kube_persistentvolumeclaim_annotations{namespace="",persistentvolumeclaim="mongo-data"} 1
kube_persistentvolumeclaim_access_mode{namespace="",persistentvolumeclaim="mongo-data",access_mode="ReadWriteOnce"} 1
kube_persistentvolumeclaim_status_condition{namespace="",persistentvolumeclaim="mongo-data",status="false",condition="CustomizedType"} 1
kube_persistentvolumeclaim_status_condition{namespace="",persistentvolumeclaim="mongo-data",status="false",condition="FileSystemResizePending"} 0

View File

@ -85,6 +85,7 @@ func podMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat
createPodStatusQosClassFamilyGenerator(),
createPodStatusReadyFamilyGenerator(),
createPodStatusReadyTimeFamilyGenerator(),
createPodStatusInitializedTimeFamilyGenerator(),
createPodStatusContainerReadyTimeFamilyGenerator(),
createPodStatusReasonFamilyGenerator(),
createPodStatusScheduledFamilyGenerator(),
@ -1034,6 +1035,9 @@ func createPodAnnotationsGenerator(allowAnnotations []string) generator.FamilyGe
basemetrics.ALPHA,
"",
wrapPodFunc(func(p *v1.Pod) *metric.Family {
if len(allowAnnotations) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", p.Annotations, allowAnnotations)
m := metric.Metric{
LabelKeys: annotationKeys,
@ -1055,6 +1059,9 @@ func createPodLabelsGenerator(allowLabelsList []string) generator.FamilyGenerato
basemetrics.STABLE,
"",
wrapPodFunc(func(p *v1.Pod) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", p.Labels, allowLabelsList)
m := metric.Metric{
LabelKeys: labelKeys,
@ -1337,6 +1344,33 @@ func createPodStatusPhaseFamilyGenerator() generator.FamilyGenerator {
)
}
func createPodStatusInitializedTimeFamilyGenerator() generator.FamilyGenerator {
return *generator.NewFamilyGeneratorWithStability(
"kube_pod_status_initialized_time",
"Initialized time in unix timestamp for a pod.",
metric.Gauge,
basemetrics.ALPHA,
"",
wrapPodFunc(func(p *v1.Pod) *metric.Family {
ms := []*metric.Metric{}
for _, c := range p.Status.Conditions {
if c.Type == v1.PodInitialized && c.Status == v1.ConditionTrue {
ms = append(ms, &metric.Metric{
LabelKeys: []string{},
LabelValues: []string{},
Value: float64((c.LastTransitionTime).Unix()),
})
}
}
return &metric.Family{
Metrics: ms,
}
}),
)
}
func createPodStatusContainerReadyTimeFamilyGenerator() generator.FamilyGenerator {
return *generator.NewFamilyGeneratorWithStability(
"kube_pod_status_container_ready_time",

View File

@ -1434,6 +1434,57 @@ func TestPodStore(t *testing.T) {
`,
MetricNames: []string{"kube_pod_status_reason"},
},
{
Obj: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod1",
Namespace: "ns1",
UID: "uid1",
},
Status: v1.PodStatus{
Conditions: []v1.PodCondition{
{
Type: v1.PodInitialized,
Status: v1.ConditionTrue,
LastTransitionTime: metav1.Time{
Time: time.Unix(1501666018, 0),
},
},
},
},
},
Want: `
# HELP kube_pod_status_initialized_time Initialized time in unix timestamp for a pod.
# TYPE kube_pod_status_initialized_time gauge
kube_pod_status_initialized_time{namespace="ns1",pod="pod1",uid="uid1"} 1.501666018e+09
`,
MetricNames: []string{"kube_pod_status_initialized_time"},
},
{
Obj: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod1",
Namespace: "ns1",
UID: "uid1",
},
Status: v1.PodStatus{
Conditions: []v1.PodCondition{
{
Type: v1.PodInitialized,
Status: v1.ConditionFalse,
LastTransitionTime: metav1.Time{
Time: time.Unix(1501666018, 0),
},
},
},
},
},
Want: `
# HELP kube_pod_status_initialized_time Initialized time in unix timestamp for a pod.
# TYPE kube_pod_status_initialized_time gauge
`,
MetricNames: []string{"kube_pod_status_initialized_time"},
},
{
Obj: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
@ -1826,7 +1877,6 @@ func TestPodStore(t *testing.T) {
Want: `
# HELP kube_pod_labels [STABLE] Kubernetes labels converted to Prometheus labels.
# TYPE kube_pod_labels gauge
kube_pod_labels{namespace="ns1",pod="pod1",uid="uid1"} 1
`,
MetricNames: []string{
"kube_pod_labels",
@ -2181,7 +2231,7 @@ func BenchmarkPodStore(b *testing.B) {
},
}
expectedFamilies := 51
expectedFamilies := 52
for n := 0; n < b.N; n++ {
families := f(pod)
if len(families) != expectedFamilies {

View File

@ -48,6 +48,9 @@ func podDisruptionBudgetMetricFamilies(allowAnnotationsList, allowLabelsList []s
basemetrics.ALPHA,
"",
wrapPodDisruptionBudgetFunc(func(p *policyv1.PodDisruptionBudget) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", p.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -67,6 +70,9 @@ func podDisruptionBudgetMetricFamilies(allowAnnotationsList, allowLabelsList []s
basemetrics.ALPHA,
"",
wrapPodDisruptionBudgetFunc(func(p *policyv1.PodDisruptionBudget) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", p.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -67,8 +67,6 @@ func TestPodDisruptionBudgetStore(t *testing.T) {
},
},
Want: metadata + `
kube_poddisruptionbudget_annotations{namespace="ns1",poddisruptionbudget="pdb1"} 1
kube_poddisruptionbudget_labels{namespace="ns1",poddisruptionbudget="pdb1"} 1
kube_poddisruptionbudget_created{namespace="ns1",poddisruptionbudget="pdb1"} 1.5e+09
kube_poddisruptionbudget_status_current_healthy{namespace="ns1",poddisruptionbudget="pdb1"} 12
kube_poddisruptionbudget_status_desired_healthy{namespace="ns1",poddisruptionbudget="pdb1"} 10
@ -93,8 +91,6 @@ func TestPodDisruptionBudgetStore(t *testing.T) {
},
},
Want: metadata + `
kube_poddisruptionbudget_annotations{namespace="ns2",poddisruptionbudget="pdb2"} 1
kube_poddisruptionbudget_labels{namespace="ns2",poddisruptionbudget="pdb2"} 1
kube_poddisruptionbudget_status_current_healthy{namespace="ns2",poddisruptionbudget="pdb2"} 8
kube_poddisruptionbudget_status_desired_healthy{namespace="ns2",poddisruptionbudget="pdb2"} 9
kube_poddisruptionbudget_status_pod_disruptions_allowed{namespace="ns2",poddisruptionbudget="pdb2"} 0

View File

@ -216,6 +216,9 @@ func replicaSetMetricFamilies(allowAnnotationsList, allowLabelsList []string) []
basemetrics.ALPHA,
"",
wrapReplicaSetFunc(func(r *v1.ReplicaSet) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", r.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -235,6 +238,9 @@ func replicaSetMetricFamilies(allowAnnotationsList, allowLabelsList []string) []
basemetrics.STABLE,
"",
wrapReplicaSetFunc(func(r *v1.ReplicaSet) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", r.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -87,8 +87,6 @@ func TestReplicaSetStore(t *testing.T) {
},
},
Want: metadata + `
kube_replicaset_annotations{replicaset="rs1",namespace="ns1"} 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
@ -121,8 +119,6 @@ func TestReplicaSetStore(t *testing.T) {
},
},
Want: metadata + `
kube_replicaset_annotations{replicaset="rs2",namespace="ns2"} 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

View File

@ -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 {

View File

@ -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)
}

View File

@ -48,6 +48,9 @@ func roleMetricFamilies(allowAnnotationsList, allowLabelsList []string) []genera
basemetrics.ALPHA,
"",
wrapRoleFunc(func(r *rbacv1.Role) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", r.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -67,6 +70,9 @@ func roleMetricFamilies(allowAnnotationsList, allowLabelsList []string) []genera
basemetrics.ALPHA,
"",
wrapRoleFunc(func(r *rbacv1.Role) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", r.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -48,6 +48,9 @@ func roleBindingMetricFamilies(allowAnnotationsList, allowLabelsList []string) [
basemetrics.ALPHA,
"",
wrapRoleBindingFunc(func(r *rbacv1.RoleBinding) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", r.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -67,6 +70,9 @@ func roleBindingMetricFamilies(allowAnnotationsList, allowLabelsList []string) [
basemetrics.ALPHA,
"",
wrapRoleBindingFunc(func(r *rbacv1.RoleBinding) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", r.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -82,6 +82,9 @@ func secretMetricFamilies(allowAnnotationsList, allowLabelsList []string) []gene
basemetrics.ALPHA,
"",
wrapSecretFunc(func(s *v1.Secret) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", s.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -102,6 +105,9 @@ func secretMetricFamilies(allowAnnotationsList, allowLabelsList []string) []gene
basemetrics.STABLE,
"",
wrapSecretFunc(func(s *v1.Secret) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", s.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -52,7 +52,6 @@ func TestSecretStore(t *testing.T) {
kube_secret_info{namespace="ns1",secret="secret1"} 1
kube_secret_type{namespace="ns1",secret="secret1",type="Opaque"} 1
kube_secret_metadata_resource_version{namespace="ns1",secret="secret1"} 0
kube_secret_labels{namespace="ns1",secret="secret1"} 1
`,
MetricNames: []string{"kube_secret_info", "kube_secret_metadata_resource_version", "kube_secret_created", "kube_secret_labels", "kube_secret_type"},
},
@ -80,7 +79,6 @@ func TestSecretStore(t *testing.T) {
kube_secret_info{namespace="ns2",secret="secret2"} 1
kube_secret_type{namespace="ns2",secret="secret2",type="kubernetes.io/service-account-token"} 1
kube_secret_created{namespace="ns2",secret="secret2"} 1.501569018e+09
kube_secret_labels{namespace="ns2",secret="secret2"} 1
`,
MetricNames: []string{"kube_secret_info", "kube_secret_metadata_resource_version", "kube_secret_created", "kube_secret_labels", "kube_secret_type"},
},
@ -110,7 +108,6 @@ 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{namespace="ns3",secret="secret3"} 1
`,
MetricNames: []string{"kube_secret_info", "kube_secret_metadata_resource_version", "kube_secret_created", "kube_secret_labels", "kube_secret_type"},
},

View File

@ -97,6 +97,9 @@ func serviceMetricFamilies(allowAnnotationsList, allowLabelsList []string) []gen
basemetrics.ALPHA,
"",
wrapSvcFunc(func(s *v1.Service) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", s.Annotations, allowAnnotationsList)
m := metric.Metric{
LabelKeys: annotationKeys,
@ -113,6 +116,9 @@ func serviceMetricFamilies(allowAnnotationsList, allowLabelsList []string) []gen
basemetrics.STABLE,
"",
wrapSvcFunc(func(s *v1.Service) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", s.Labels, allowLabelsList)
m := metric.Metric{
LabelKeys: labelKeys,

View File

@ -73,10 +73,8 @@ func TestServiceStore(t *testing.T) {
# TYPE kube_service_info gauge
# TYPE kube_service_labels gauge
# TYPE kube_service_spec_type gauge
kube_service_annotations{namespace="default",service="test-service1",uid="uid1"} 1
kube_service_created{namespace="default",service="test-service1",uid="uid1"} 1.5e+09
kube_service_info{cluster_ip="1.2.3.4",external_name="",load_balancer_ip="",namespace="default",service="test-service1",uid="uid1"} 1
kube_service_labels{namespace="default",service="test-service1",uid="uid1"} 1
kube_service_spec_type{namespace="default",service="test-service1",type="ClusterIP",uid="uid1"} 1
`,
MetricNames: []string{
@ -105,10 +103,8 @@ func TestServiceStore(t *testing.T) {
},
},
Want: metadata + `
kube_service_annotations{namespace="default",service="test-service2",uid="uid2"} 1
kube_service_created{namespace="default",service="test-service2",uid="uid2"} 1.5e+09
kube_service_info{cluster_ip="1.2.3.5",external_name="",load_balancer_ip="",namespace="default",service="test-service2",uid="uid2"} 1
kube_service_labels{namespace="default",service="test-service2",uid="uid2"} 1
kube_service_spec_type{namespace="default",service="test-service2",uid="uid2",type="NodePort"} 1
`,
},
@ -130,10 +126,8 @@ func TestServiceStore(t *testing.T) {
},
},
Want: metadata + `
kube_service_annotations{namespace="default",service="test-service3",uid="uid3"} 1
kube_service_created{namespace="default",service="test-service3",uid="uid3"} 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",uid="uid3"} 1
kube_service_labels{namespace="default",service="test-service3",uid="uid3"} 1
kube_service_spec_type{namespace="default",service="test-service3",type="LoadBalancer",uid="uid3"} 1
`,
},
@ -154,10 +148,8 @@ func TestServiceStore(t *testing.T) {
},
},
Want: metadata + `
kube_service_annotations{namespace="default",service="test-service4",uid="uid4"} 1
kube_service_created{namespace="default",service="test-service4",uid="uid4"} 1.5e+09
kube_service_info{cluster_ip="",external_name="www.example.com",load_balancer_ip="",namespace="default",service="test-service4",uid="uid4"} 1
kube_service_labels{namespace="default",service="test-service4",uid="uid4"} 1
kube_service_spec_type{namespace="default",service="test-service4",uid="uid4",type="ExternalName"} 1
`,
},
@ -187,10 +179,8 @@ func TestServiceStore(t *testing.T) {
},
},
Want: metadata + `
kube_service_annotations{namespace="default",service="test-service5",uid="uid5"} 1
kube_service_created{namespace="default",service="test-service5",uid="uid5"} 1.5e+09
kube_service_info{cluster_ip="",external_name="",load_balancer_ip="",namespace="default",service="test-service5",uid="uid5"} 1
kube_service_labels{namespace="default",service="test-service5",uid="uid5"} 1
kube_service_spec_type{namespace="default",service="test-service5",type="LoadBalancer",uid="uid5"} 1
kube_service_status_load_balancer_ingress{hostname="www.example.com",ip="1.2.3.8",namespace="default",service="test-service5",uid="uid5"} 1
`,
@ -215,10 +205,8 @@ func TestServiceStore(t *testing.T) {
},
},
Want: metadata + `
kube_service_annotations{namespace="default",service="test-service6",uid="uid6"} 1
kube_service_created{namespace="default",service="test-service6",uid="uid6"} 1.5e+09
kube_service_info{cluster_ip="",external_name="",load_balancer_ip="",namespace="default",service="test-service6",uid="uid6"} 1
kube_service_labels{namespace="default",service="test-service6",uid="uid6"} 1
kube_service_spec_type{namespace="default",service="test-service6",uid="uid6",type="ClusterIP"} 1
kube_service_spec_external_ip{external_ip="1.2.3.9",namespace="default",service="test-service6",uid="uid6"} 1
kube_service_spec_external_ip{external_ip="1.2.3.10",namespace="default",service="test-service6",uid="uid6"} 1

View File

@ -183,6 +183,9 @@ func createServiceAccountAnnotationsGenerator(allowAnnotations []string) generat
basemetrics.ALPHA,
"",
wrapServiceAccountFunc(func(sa *v1.ServiceAccount) *metric.Family {
if len(allowAnnotations) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", sa.Annotations, allowAnnotations)
m := metric.Metric{
LabelKeys: annotationKeys,
@ -204,6 +207,9 @@ func createServiceAccountLabelsGenerator(allowLabelsList []string) generator.Fam
basemetrics.ALPHA,
"",
wrapServiceAccountFunc(func(sa *v1.ServiceAccount) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", sa.Labels, allowLabelsList)
m := metric.Metric{
LabelKeys: labelKeys,

View File

@ -22,7 +22,7 @@ import (
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/pointer"
"k8s.io/utils/ptr"
generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator"
)
@ -38,7 +38,7 @@ func TestServiceAccountStore(t *testing.T) {
Namespace: "serviceAccountNS",
UID: "serviceAccountUID",
},
AutomountServiceAccountToken: pointer.Bool(true),
AutomountServiceAccountToken: ptr.To(true),
Secrets: []v1.ObjectReference{
{
APIVersion: "v1",

View File

@ -248,6 +248,9 @@ func statefulSetMetricFamilies(allowAnnotationsList, allowLabelsList []string) [
basemetrics.ALPHA,
"",
wrapStatefulSetFunc(func(s *v1.StatefulSet) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", s.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -267,6 +270,9 @@ func statefulSetMetricFamilies(allowAnnotationsList, allowLabelsList []string) [
basemetrics.STABLE,
"",
wrapStatefulSetFunc(func(s *v1.StatefulSet) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", s.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -99,7 +99,6 @@ 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{namespace="ns1",statefulset="statefulset1"} 1
`,
MetricNames: []string{
"kube_statefulset_created",
@ -177,7 +176,6 @@ 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{namespace="ns2",statefulset="statefulset2"} 1
kube_statefulset_status_current_revision{namespace="ns2",revision="cr2",statefulset="statefulset2"} 1
`,
MetricNames: []string{
@ -247,7 +245,6 @@ 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{namespace="ns3",statefulset="statefulset3"} 1
kube_statefulset_status_current_revision{namespace="ns3",revision="cr3",statefulset="statefulset3"} 1
`,
MetricNames: []string{
@ -321,7 +318,6 @@ func TestStatefulSetStore(t *testing.T) {
kube_statefulset_replicas{namespace="ns4",statefulset="statefulset4"} 3
kube_statefulset_metadata_generation{namespace="ns4",statefulset="statefulset4"} 1
kube_statefulset_persistentvolumeclaim_retention_policy{namespace="ns4",statefulset="statefulset4",when_deleted="Retain",when_scaled="Delete"} 1
kube_statefulset_labels{namespace="ns4",statefulset="statefulset4"} 1
kube_statefulset_status_current_revision{namespace="ns4",revision="cr3",statefulset="statefulset4"} 1
`,
MetricNames: []string{
@ -397,7 +393,6 @@ func TestStatefulSetStore(t *testing.T) {
kube_statefulset_replicas{namespace="ns5",statefulset="statefulset5"} 3
kube_statefulset_ordinals_start{namespace="ns5",statefulset="statefulset5"} 2
kube_statefulset_metadata_generation{namespace="ns5",statefulset="statefulset5"} 1
kube_statefulset_labels{namespace="ns5",statefulset="statefulset5"} 1
kube_statefulset_status_current_revision{namespace="ns5",revision="cr5",statefulset="statefulset5"} 1
`,
MetricNames: []string{

View File

@ -92,6 +92,9 @@ func storageClassMetricFamilies(allowAnnotationsList, allowLabelsList []string)
basemetrics.ALPHA,
"",
wrapStorageClassFunc(func(s *storagev1.StorageClass) *metric.Family {
if len(allowAnnotationsList) == 0 {
return &metric.Family{}
}
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", s.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
@ -111,6 +114,9 @@ func storageClassMetricFamilies(allowAnnotationsList, allowLabelsList []string)
basemetrics.STABLE,
"",
wrapStorageClassFunc(func(s *storagev1.StorageClass) *metric.Family {
if len(allowLabelsList) == 0 {
return &metric.Family{}
}
labelKeys, labelValues := createPrometheusLabelKeysValues("label", s.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{

View File

@ -100,7 +100,6 @@ func TestStorageClassStore(t *testing.T) {
Want: `
# HELP kube_storageclass_labels [STABLE] Kubernetes labels converted to Prometheus labels.
# TYPE kube_storageclass_labels gauge
kube_storageclass_labels{storageclass="test_storageclass-labels"} 1
`,
MetricNames: []string{
"kube_storageclass_labels",

View File

@ -242,6 +242,7 @@ func TestFullScrapeCycle(t *testing.T) {
# HELP kube_pod_spec_volumes_persistentvolumeclaims_readonly [STABLE] Describes whether a persistentvolumeclaim is mounted read only.
# HELP kube_pod_start_time [STABLE] Start time in unix timestamp for a pod.
# HELP kube_pod_status_container_ready_time Readiness achieved time in unix timestamp for a pod containers.
# HELP kube_pod_status_initialized_time Initialized time in unix timestamp for a pod.
# HELP kube_pod_status_qos_class The pods current qosClass.
# HELP kube_pod_status_phase [STABLE] The pods current phase.
# HELP kube_pod_status_ready_time Readiness achieved time in unix timestamp for a pod.
@ -292,6 +293,7 @@ func TestFullScrapeCycle(t *testing.T) {
# TYPE kube_pod_spec_volumes_persistentvolumeclaims_readonly gauge
# TYPE kube_pod_start_time gauge
# TYPE kube_pod_status_container_ready_time gauge
# TYPE kube_pod_status_initialized_time gauge
# TYPE kube_pod_status_phase gauge
# TYPE kube_pod_status_qos_class gauge
# TYPE kube_pod_status_ready gauge
@ -301,7 +303,6 @@ func TestFullScrapeCycle(t *testing.T) {
# TYPE kube_pod_status_scheduled_time gauge
# TYPE kube_pod_status_unschedulable gauge
# TYPE kube_pod_tolerations gauge
kube_pod_annotations{namespace="default",pod="pod0",uid="abc-0"} 1
kube_pod_container_info{namespace="default",pod="pod0",uid="abc-0",container="pod1_con1",image_spec="k8s.gcr.io/hyperkube2_spec",image="k8s.gcr.io/hyperkube2",image_id="docker://sha256:bbb",container_id="docker://cd456"} 1
kube_pod_container_info{namespace="default",pod="pod0",uid="abc-0",container="pod1_con2",image_spec="k8s.gcr.io/hyperkube3_spec",image="k8s.gcr.io/hyperkube3",image_id="docker://sha256:ccc",container_id="docker://ef789"} 1
kube_pod_container_resource_limits{namespace="default",pod="pod0",uid="abc-0",container="pod1_con1",node="node1",resource="cpu",unit="core"} 0.2
@ -333,7 +334,6 @@ kube_pod_container_status_waiting{namespace="default",pod="pod0",uid="abc-0",con
kube_pod_container_status_waiting{namespace="default",pod="pod0",uid="abc-0",container="pod1_con2"} 0
kube_pod_created{namespace="default",pod="pod0",uid="abc-0"} 1.5e+09
kube_pod_info{namespace="default",pod="pod0",uid="abc-0",host_ip="1.1.1.1",pod_ip="1.2.3.4",node="node1",created_by_kind="",created_by_name="",priority_class="",host_network="false"} 1
kube_pod_labels{namespace="default",pod="pod0",uid="abc-0"} 1
kube_pod_owner{namespace="default",pod="pod0",uid="abc-0",owner_kind="",owner_name="",owner_is_controller=""} 1
kube_pod_restart_policy{namespace="default",pod="pod0",uid="abc-0",type="Always"} 1
kube_pod_service_account{namespace="default",pod="pod0",uid="abc-0",service_account=""} 1

View File

@ -22,7 +22,7 @@ import (
"testing"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/utils/pointer"
"k8s.io/utils/ptr"
)
func TestNewCustomResourceMetrics(t *testing.T) {
@ -130,7 +130,7 @@ func TestNewCustomResourceMetrics(t *testing.T) {
},
},
},
MetricNamePrefix: pointer.String("apps_deployment"),
MetricNamePrefix: ptr.To("apps_deployment"),
},
wantErr: false,
wantResult: &customResourceMetrics{
@ -193,7 +193,7 @@ func TestNewCustomResourceMetrics(t *testing.T) {
},
},
},
MetricNamePrefix: pointer.String("apps_deployment"),
MetricNamePrefix: ptr.To("apps_deployment"),
},
wantErr: true,
wantResult: &customResourceMetrics{

View File

@ -196,7 +196,7 @@ func newCompiledMetric(m Metric) (compiledMetric, error) {
}
valueFromPath, err := compilePath(m.StateSet.ValueFrom)
if err != nil {
return nil, fmt.Errorf("each.gauge.valueFrom: %w", err)
return nil, fmt.Errorf("each.stateSet.valueFrom: %w", err)
}
return &compiledStateSet{
compiledCommon: *cc,

View File

@ -23,7 +23,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"k8s.io/utils/pointer"
"k8s.io/utils/ptr"
"k8s.io/kube-state-metrics/v2/pkg/metric"
)
@ -454,7 +454,7 @@ func Test_fullName(t *testing.T) {
{
name: "no prefix",
args: args{
resource: r(pointer.String("")),
resource: r(ptr.To("")),
f: count,
},
want: "count",
@ -462,7 +462,7 @@ func Test_fullName(t *testing.T) {
{
name: "custom",
args: args{
resource: r(pointer.String("bar_baz")),
resource: r(ptr.To("bar_baz")),
f: count,
},
want: "bar_baz_count",

View File

@ -58,21 +58,17 @@ func (m MetricsWriter) WriteAll(w io.Writer) error {
}(s)
}
// If the first store has no headers, but has metrics, we need to write out
// an empty header to ensure that the metrics are written out correctly.
if m.stores[0].headers == nil && m.stores[0].metrics != nil {
m.stores[0].headers = []string{""}
}
for i, help := range m.stores[0].headers {
if help != "" && help != "\n" {
help += "\n"
}
// TODO: This writes out the help text for each metric family, before checking if the metrics for it exist,
// TODO: which is not ideal, and furthermore, diverges from the OpenMetrics standard.
if len(m.stores[0].metrics) > 0 {
_, err := w.Write([]byte(help))
if err != nil {
return fmt.Errorf("failed to write help text: %v", err)
}
}
for _, s := range m.stores {
for _, metricFamilies := range s.metrics {
@ -91,6 +87,7 @@ func (m MetricsWriter) WriteAll(w io.Writer) error {
func SanitizeHeaders(writers MetricsWriterList) MetricsWriterList {
var lastHeader string
for _, writer := range writers {
if len(writer.stores) > 0 {
for i, header := range writer.stores[0].headers {
if header == lastHeader {
writer.stores[0].headers[i] = ""
@ -99,5 +96,6 @@ func SanitizeHeaders(writers MetricsWriterList) MetricsWriterList {
}
}
}
}
return writers
}

View File

@ -17,6 +17,7 @@ limitations under the License.
package metricsstore_test
import (
"fmt"
"strings"
"testing"
@ -231,3 +232,34 @@ func TestWriteAllWithMultipleStores(t *testing.T) {
}
}
}
// TestWriteAllWithEmptyStores checks that nothing is printed if no metrics exist for metric families.
func TestWriteAllWithEmptyStores(t *testing.T) {
genFunc := func(obj interface{}) []metric.FamilyInterface {
mf1 := metric.Family{
Name: "kube_service_info_1",
Metrics: []*metric.Metric{},
}
mf2 := metric.Family{
Name: "kube_service_info_2",
Metrics: []*metric.Metric{},
}
return []metric.FamilyInterface{&mf1, &mf2}
}
store := metricsstore.NewMetricsStore([]string{"Info 1 about services", "Info 2 about services"}, genFunc)
multiNsWriter := metricsstore.NewMetricsWriter(store)
w := strings.Builder{}
err := multiNsWriter.WriteAll(&w)
if err != nil {
t.Fatalf("failed to write metrics: %v", err)
}
result := w.String()
fmt.Println(result)
if result != "" {
t.Fatalf("Unexpected output, got %q, want %q", result, "")
}
}

View File

@ -137,8 +137,8 @@ func (o *Options) AddFlags(cmd *cobra.Command) {
o.cmd.Flags().StringVar(&o.TelemetryHost, "telemetry-host", "::", `Host to expose kube-state-metrics self metrics on.`)
o.cmd.Flags().StringVar(&o.Config, "config", "", "Path to the kube-state-metrics options config file")
o.cmd.Flags().StringVar((*string)(&o.Node), "node", "", "Name of the node that contains the kube-state-metrics pod. Most likely it should be passed via the downward API. This is used for daemonset sharding. Only available for resources (pod metrics) that support spec.nodeName fieldSelector. This is experimental.")
o.cmd.Flags().Var(&o.AnnotationsAllowList, "metric-annotations-allowlist", "Comma-separated list of Kubernetes annotations keys that will be used in the resource' labels metric. By default the metric contains only name and namespace labels. To include additional annotations provide a list of resource names in their plural form and Kubernetes annotation keys you would like to allow for them (Example: '=namespaces=[kubernetes.io/team,...],pods=[kubernetes.io/team],...)'. A single '*' can be provided per resource instead to allow any annotations, but that has severe performance implications (Example: '=pods=[*]').")
o.cmd.Flags().Var(&o.LabelsAllowList, "metric-labels-allowlist", "Comma-separated list of additional Kubernetes label keys that will be used in the resource' labels metric. By default the metric contains only name and namespace labels. To include additional labels provide a list of resource names in their plural form and Kubernetes label keys you would like to allow for them (Example: '=namespaces=[k8s-label-1,k8s-label-n,...],pods=[app],...)'. A single '*' can be provided per resource instead to allow any labels, but that has severe performance implications (Example: '=pods=[*]'). Additionally, an asterisk (*) can be provided as a key, which will resolve to all resources, i.e., assuming '--resources=deployments,pods', '=*=[*]' will resolve to '=deployments=[*],pods=[*]'.")
o.cmd.Flags().Var(&o.AnnotationsAllowList, "metric-annotations-allowlist", "Comma-separated list of Kubernetes annotations keys that will be used in the resource' labels metric. By default the annotations metrics are not exposed. To include them, provide a list of resource names in their plural form and Kubernetes annotation keys you would like to allow for them (Example: '=namespaces=[kubernetes.io/team,...],pods=[kubernetes.io/team],...)'. A single '*' can be provided per resource instead to allow any annotations, but that has severe performance implications (Example: '=pods=[*]').")
o.cmd.Flags().Var(&o.LabelsAllowList, "metric-labels-allowlist", "Comma-separated list of additional Kubernetes label keys that will be used in the resource' labels metric. By default the labels metrics are not exposed. To include them, provide a list of resource names in their plural form and Kubernetes label keys you would like to allow for them (Example: '=namespaces=[k8s-label-1,k8s-label-n,...],pods=[app],...)'. A single '*' can be provided per resource instead to allow any labels, but that has severe performance implications (Example: '=pods=[*]'). Additionally, an asterisk (*) can be provided as a key, which will resolve to all resources, i.e., assuming '--resources=deployments,pods', '=*=[*]' will resolve to '=deployments=[*],pods=[*]'.")
o.cmd.Flags().Var(&o.MetricAllowlist, "metric-allowlist", "Comma-separated list of metrics to be exposed. This list comprises of exact metric names and/or regex patterns. The allowlist and denylist are mutually exclusive.")
o.cmd.Flags().Var(&o.MetricDenylist, "metric-denylist", "Comma-separated list of metrics not to be enabled. This list comprises of exact metric names and/or regex patterns. The allowlist and denylist are mutually exclusive.")
o.cmd.Flags().Var(&o.MetricOptInList, "metric-opt-in-list", "Comma-separated list of metrics which are opt-in and not enabled by default. This is in addition to the metric allow- and denylists")

View File

@ -109,8 +109,8 @@ func TestNamespaceList_GetNamespaces(t *testing.T) {
},
}
for _, test := range tests {
ns := &test.Namespaces
for i, test := range tests {
ns := &tests[i].Namespaces
allowedNamespaces := ns.GetNamespaces()
if !reflect.DeepEqual(allowedNamespaces, test.Wanted) {
t.Errorf("Test error for Desc: %s. Want: %+v. Got: %+v.", test.Desc, test.Wanted, allowedNamespaces)

View File

@ -30,7 +30,7 @@ KUBE_STATE_METRICS_CURRENT_IMAGE_NAME="registry.k8s.io/kube-state-metrics/kube-s
KUBE_STATE_METRICS_IMAGE_NAME="registry.k8s.io/kube-state-metrics/kube-state-metrics-${ARCH}"
E2E_SETUP_KIND=${E2E_SETUP_KIND:-}
E2E_SETUP_KUBECTL=${E2E_SETUP_KUBECTL:-}
KIND_VERSION=v0.19.0
KIND_VERSION=v0.20.0
SUDO=${SUDO:-}
OS=$(uname -s | awk '{print tolower($0)}')

View File

@ -7,7 +7,7 @@ require (
github.com/campoy/embedmd v1.0.0
github.com/google/go-jsonnet v0.20.0
github.com/jsonnet-bundler/jsonnet-bundler v0.5.1
golang.org/x/perf v0.0.0-20230427221525-d343f6398b76
golang.org/x/perf v0.0.0-20230822165715-3c60af34b3f4
)
require (

View File

@ -114,8 +114,8 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20170207211851-4464e7848382/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/perf v0.0.0-20230427221525-d343f6398b76 h1:cPGZx8Liyx5Pq/yX80/6WMKe2yidT0xvVCQBOGa8WHU=
golang.org/x/perf v0.0.0-20230427221525-d343f6398b76/go.mod h1:UBKtEnL8aqnd+0JHqZ+2qoMDwtuy6cYhhKNoHLBiTQc=
golang.org/x/perf v0.0.0-20230822165715-3c60af34b3f4 h1:ua24l69kDXo72PNOVfgBXbbwGyV322MjcIBBV5ExoYA=
golang.org/x/perf v0.0.0-20230822165715-3c60af34b3f4/go.mod h1:UBKtEnL8aqnd+0JHqZ+2qoMDwtuy6cYhhKNoHLBiTQc=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=