Skip to content

Commit

Permalink
Merge pull request #1905 from kaitoii11/ingressclass
Browse files Browse the repository at this point in the history
Add ingress class metrics
  • Loading branch information
k8s-ci-robot committed Nov 24, 2022
2 parents 6e28b18 + df2d8f1 commit 3cf1b16
Show file tree
Hide file tree
Showing 11 changed files with 272 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ See each file for specific documentation about the exposed metrics:

- [ClusterRole Metrics](clusterrole-metrics.md)
- [ClusterRoleBinding Metrics](clusterrolebinding-metrics.md)
- [IngressClass Metrics](ingressclass-metrics.md)
- [Role Metrics](role-metrics.md)
- [RoleBinding Metrics](rolebinding-metrics.md)
- [ServiceAccount Metrics](serviceaccount-metrics.md)
Expand Down
8 changes: 8 additions & 0 deletions docs/ingressclass-metrics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# IngressClass Metrics

| Metric name| Metric type | Labels/tags | Status |
| ---------- | ----------- | ----------- | ----------- |
| kube_ingressclass_annotations | Gauge | `ingressclass`=&lt;ingressclass-name&gt; <br> `annotation_INGRESSCLASS_ANNOTATION`=&lt;INGRESSCLASS_ANNOTATION&gt; | EXPERIMENTAL |
| kube_ingressclass_info | Gauge | `ingressclass`=&lt;ingressclass-name&gt; <br> `controller`=&lt;ingress-controller-name&gt; <br> | EXPERIMENTAL |
| kube_ingressclass_labels | Gauge | `ingressclass`=&lt;ingressclass-name&gt; <br> `label_INGRESSCLASS_LABEL`=&lt;INGRESSCLASS_LABEL&gt; | EXPERIMENTAL|
| kube_ingressclass_created | Gauge | `ingressclass`=&lt;ingressclass-name&gt; | EXPERIMENTAL|
1 change: 1 addition & 0 deletions examples/autosharding/cluster-role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ rules:
- networking.k8s.io
resources:
- networkpolicies
- ingressclasses
- ingresses
verbs:
- list
Expand Down
1 change: 1 addition & 0 deletions examples/standard/cluster-role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ rules:
- networking.k8s.io
resources:
- networkpolicies
- ingressclasses
- ingresses
verbs:
- list
Expand Down
5 changes: 5 additions & 0 deletions internal/store/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ var availableStores = map[string]func(f *Builder) []cache.Store{
"endpoints": func(b *Builder) []cache.Store { return b.buildEndpointsStores() },
"horizontalpodautoscalers": func(b *Builder) []cache.Store { return b.buildHPAStores() },
"ingresses": func(b *Builder) []cache.Store { return b.buildIngressStores() },
"ingressclasses": func(b *Builder) []cache.Store { return b.buildIngressClassStores() },
"jobs": func(b *Builder) []cache.Store { return b.buildJobStores() },
"leases": func(b *Builder) []cache.Store { return b.buildLeasesStores() },
"limitranges": func(b *Builder) []cache.Store { return b.buildLimitRangeStores() },
Expand Down Expand Up @@ -470,6 +471,10 @@ func (b *Builder) buildRoleBindingStores() []cache.Store {
return b.buildStoresFunc(roleBindingMetricFamilies(b.allowAnnotationsList["rolebindings"], b.allowLabelsList["rolebindings"]), &rbacv1.RoleBinding{}, createRoleBindingListWatch, b.useAPIServerCache)
}

func (b *Builder) buildIngressClassStores() []cache.Store {
return b.buildStoresFunc(ingressClassMetricFamilies(b.allowAnnotationsList["ingressclasses"], b.allowLabelsList["ingressclasses"]), &networkingv1.IngressClass{}, createIngressClassListWatch, b.useAPIServerCache)
}

func (b *Builder) buildStores(
metricFamilies []generator.FamilyGenerator,
expectedType interface{},
Expand Down
140 changes: 140 additions & 0 deletions internal/store/ingressclass.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*
Copyright 2022 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package store

import (
"context"

basemetrics "k8s.io/component-base/metrics"

"k8s.io/kube-state-metrics/v2/pkg/metric"
generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator"

networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
)

var (
descIngressClassAnnotationsName = "kube_ingressclass_annotations"
descIngressClassAnnotationsHelp = "Kubernetes annotations converted to Prometheus labels."
descIngressClassLabelsName = "kube_ingressclass_labels"
descIngressClassLabelsHelp = "Kubernetes labels converted to Prometheus labels."
descIngressClassLabelsDefaultLabels = []string{"ingressclass"}
)

func ingressClassMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generator.FamilyGenerator {
return []generator.FamilyGenerator{
*generator.NewFamilyGeneratorWithStability(
"kube_ingressclass_info",
"Information about ingressclass.",
metric.Gauge,
basemetrics.ALPHA,
"",
wrapIngressClassFunc(func(s *networkingv1.IngressClass) *metric.Family {

m := metric.Metric{
LabelKeys: []string{"controller"},
LabelValues: []string{s.Spec.Controller},
Value: 1,
}
return &metric.Family{Metrics: []*metric.Metric{&m}}
}),
),
*generator.NewFamilyGeneratorWithStability(
"kube_ingressclass_created",
"Unix creation timestamp",
metric.Gauge,
basemetrics.ALPHA,
"",
wrapIngressClassFunc(func(s *networkingv1.IngressClass) *metric.Family {
ms := []*metric.Metric{}
if !s.CreationTimestamp.IsZero() {
ms = append(ms, &metric.Metric{
Value: float64(s.CreationTimestamp.Unix()),
})
}
return &metric.Family{
Metrics: ms,
}
}),
),
*generator.NewFamilyGeneratorWithStability(
descIngressClassAnnotationsName,
descIngressClassAnnotationsHelp,
metric.Gauge,
basemetrics.ALPHA,
"",
wrapIngressClassFunc(func(s *networkingv1.IngressClass) *metric.Family {
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", s.Annotations, allowAnnotationsList)
return &metric.Family{
Metrics: []*metric.Metric{
{
LabelKeys: annotationKeys,
LabelValues: annotationValues,
Value: 1,
},
},
}
}),
),
*generator.NewFamilyGeneratorWithStability(
descIngressClassLabelsName,
descIngressClassLabelsHelp,
metric.Gauge,
basemetrics.ALPHA,
"",
wrapIngressClassFunc(func(s *networkingv1.IngressClass) *metric.Family {
labelKeys, labelValues := createPrometheusLabelKeysValues("label", s.Labels, allowLabelsList)
return &metric.Family{
Metrics: []*metric.Metric{
{
LabelKeys: labelKeys,
LabelValues: labelValues,
Value: 1,
},
},
}
}),
),
}
}

func wrapIngressClassFunc(f func(*networkingv1.IngressClass) *metric.Family) func(interface{}) *metric.Family {
return func(obj interface{}) *metric.Family {
ingressClass := obj.(*networkingv1.IngressClass)

metricFamily := f(ingressClass)

for _, m := range metricFamily.Metrics {
m.LabelKeys, m.LabelValues = mergeKeyValues(descIngressClassLabelsDefaultLabels, []string{ingressClass.Name}, m.LabelKeys, m.LabelValues)
}

return metricFamily
}
}

func createIngressClassListWatch(kubeClient clientset.Interface, ns string, fieldSelector string) cache.ListerWatcher {
return &cache.ListWatch{
ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
return kubeClient.NetworkingV1().IngressClasses().List(context.TODO(), opts)
},
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
return kubeClient.NetworkingV1().IngressClasses().Watch(context.TODO(), opts)
},
}
}
105 changes: 105 additions & 0 deletions internal/store/ingressclass_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
Copyright 2022 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package store

import (
"testing"

networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator"
)

func TestIngressClassStore(t *testing.T) {
startTime := 1501569018
metav1StartTime := metav1.Unix(int64(startTime), 0)

cases := []generateMetricsTestCase{
{
Obj: &networkingv1.IngressClass{
ObjectMeta: metav1.ObjectMeta{
Name: "test_ingressclass-info",
},
Spec: networkingv1.IngressClassSpec{
Controller: "controller",
},
},
Want: `
# HELP kube_ingressclass_info Information about ingressclass.
# TYPE kube_ingressclass_info gauge
kube_ingressclass_info{ingressclass="test_ingressclass-info",controller="controller"} 1
`,
MetricNames: []string{
"kube_ingressclass_info",
},
},
{
Obj: &networkingv1.IngressClass{
ObjectMeta: metav1.ObjectMeta{
Name: "test_kube_ingressclass-created",
CreationTimestamp: metav1StartTime,
},
Spec: networkingv1.IngressClassSpec{
Controller: "controller",
},
},
Want: `
# HELP kube_ingressclass_created Unix creation timestamp
# TYPE kube_ingressclass_created gauge
kube_ingressclass_created{ingressclass="test_kube_ingressclass-created"} 1.501569018e+09
`,
MetricNames: []string{
"kube_ingressclass_created",
},
},
{
AllowAnnotationsList: []string{
"ingressclass.kubernetes.io/is-default-class",
},
Obj: &networkingv1.IngressClass{
ObjectMeta: metav1.ObjectMeta{
Name: "test_ingressclass-labels",
Annotations: map[string]string{
"ingressclass.kubernetes.io/is-default-class": "true",
},
Labels: map[string]string{
"foo": "bar",
},
},
Spec: networkingv1.IngressClassSpec{
Controller: "controller",
},
},
Want: `
# HELP kube_ingressclass_annotations Kubernetes annotations converted to Prometheus labels.
# HELP kube_ingressclass_labels Kubernetes labels converted to Prometheus labels.
# 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",
},
},
}
for i, c := range cases {
c.Func = generator.ComposeMetricGenFuncs(ingressClassMetricFamilies(c.AllowAnnotationsList, nil))
c.Headers = generator.ExtractMetricFamilyHeaders(ingressClassMetricFamilies(c.AllowAnnotationsList, nil))
if err := c.run(); err != nil {
t.Errorf("unexpected collecting result in %vth run:\n%s", i, err)
}
}
}
1 change: 1 addition & 0 deletions jsonnet/kube-state-metrics/kube-state-metrics.libsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
apiGroups: ['networking.k8s.io'],
resources: [
'networkpolicies',
'ingressclasses',
'ingresses',
],
verbs: ['list', 'watch'],
Expand Down
1 change: 1 addition & 0 deletions tests/e2e/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ func TestDefaultCollectorMetricsAvailable(t *testing.T) {
nonDefaultResources := map[string]bool{
"clusterrole": true,
"clusterrolebinding": true,
"ingressclass": true,
"role": true,
"rolebinding": true,
"serviceaccount": true,
Expand Down
2 changes: 1 addition & 1 deletion tests/manifests/ingress.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
apiVersion: networking.k8s.io/v1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
Expand Down
8 changes: 8 additions & 0 deletions tests/manifests/ingressclass.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: example-ingressclass
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: example-ingress/controller

0 comments on commit 3cf1b16

Please sign in to comment.