From 6793b6881d3b2e046d9a2cae30443104f3a74aa4 Mon Sep 17 00:00:00 2001 From: Haoran Wang Date: Thu, 31 Jan 2019 19:30:17 +0800 Subject: [PATCH] Add collector for csr --- docs/README.md | 1 + docs/certificatessigningrequest-metrics.md | 8 + internal/collector/builder.go | 59 +++-- .../collector/certificatesigningrequest.go | 152 ++++++++++++ .../certificatesigningrequest_test.go | 220 ++++++++++++++++++ pkg/options/collector.go | 43 ++-- tests/manifests/csr.yaml | 14 ++ vendor/modules.txt | 2 +- 8 files changed, 456 insertions(+), 43 deletions(-) create mode 100644 docs/certificatessigningrequest-metrics.md create mode 100644 internal/collector/certificatesigningrequest.go create mode 100644 internal/collector/certificatesigningrequest_test.go create mode 100644 tests/manifests/csr.yaml diff --git a/docs/README.md b/docs/README.md index a42528d390..dda212dee6 100644 --- a/docs/README.md +++ b/docs/README.md @@ -65,6 +65,7 @@ Per group of metrics there is one file for each metrics. See each file for speci - [Secret Metrics](secret-metrics.md) - [ConfigMap Metrics](configmap-metrics.md) - [Ingress Metrics](ingress-metrics.md) +- [CertificateSigningRequest Metrics](certificatessigningrequest-metrics.md) ## Join Metrics diff --git a/docs/certificatessigningrequest-metrics.md b/docs/certificatessigningrequest-metrics.md new file mode 100644 index 0000000000..52548ab535 --- /dev/null +++ b/docs/certificatessigningrequest-metrics.md @@ -0,0 +1,8 @@ +# CertificateSigningRequest Metrics + +| Metric name| Metric type | Labels/tags | Status | +| ---------- | ----------- | ----------- | ----------- | +| kube_certificatesigningrequest_created| Gauge | `certificatesigningrequest`=<certificatesigningrequest-name>| STABLE | +| kube_certificatesigningrequest_condition | Gauge | `certificatesigningrequest`=<certificatesigningrequest-name>
`condition`=<approved\|denied> | STABLE | +| kube_certificatesigningrequest_labels | Gauge | `certificatesigningrequest`=<certificatesigningrequest-name>| STABLE | +| kube_certificatesigningrequest_cert_length | Gauge | `certificatesigningrequest`=<certificatesigningrequest-name>| STABLE | diff --git a/internal/collector/builder.go b/internal/collector/builder.go index 57a33a7892..b2758cc543 100644 --- a/internal/collector/builder.go +++ b/internal/collector/builder.go @@ -27,6 +27,7 @@ import ( autoscaling "k8s.io/api/autoscaling/v2beta1" batchv1 "k8s.io/api/batch/v1" batchv1beta1 "k8s.io/api/batch/v1beta1" + certv1beta1 "k8s.io/api/certificates/v1beta1" v1 "k8s.io/api/core/v1" extensions "k8s.io/api/extensions/v1beta1" policy "k8s.io/api/policy/v1beta1" @@ -112,27 +113,28 @@ func (b *Builder) Build() []*coll.Collector { } var availableCollectors = map[string]func(f *Builder) *coll.Collector{ - "configmaps": func(b *Builder) *coll.Collector { return b.buildConfigMapCollector() }, - "cronjobs": func(b *Builder) *coll.Collector { return b.buildCronJobCollector() }, - "daemonsets": func(b *Builder) *coll.Collector { return b.buildDaemonSetCollector() }, - "deployments": func(b *Builder) *coll.Collector { return b.buildDeploymentCollector() }, - "endpoints": func(b *Builder) *coll.Collector { return b.buildEndpointsCollector() }, - "horizontalpodautoscalers": func(b *Builder) *coll.Collector { return b.buildHPACollector() }, - "ingresses": func(b *Builder) *coll.Collector { return b.buildIngressCollector() }, - "jobs": func(b *Builder) *coll.Collector { return b.buildJobCollector() }, - "limitranges": func(b *Builder) *coll.Collector { return b.buildLimitRangeCollector() }, - "namespaces": func(b *Builder) *coll.Collector { return b.buildNamespaceCollector() }, - "nodes": func(b *Builder) *coll.Collector { return b.buildNodeCollector() }, - "persistentvolumeclaims": func(b *Builder) *coll.Collector { return b.buildPersistentVolumeClaimCollector() }, - "persistentvolumes": func(b *Builder) *coll.Collector { return b.buildPersistentVolumeCollector() }, - "poddisruptionbudgets": func(b *Builder) *coll.Collector { return b.buildPodDisruptionBudgetCollector() }, - "pods": func(b *Builder) *coll.Collector { return b.buildPodCollector() }, - "replicasets": func(b *Builder) *coll.Collector { return b.buildReplicaSetCollector() }, - "replicationcontrollers": func(b *Builder) *coll.Collector { return b.buildReplicationControllerCollector() }, - "resourcequotas": func(b *Builder) *coll.Collector { return b.buildResourceQuotaCollector() }, - "secrets": func(b *Builder) *coll.Collector { return b.buildSecretCollector() }, - "services": func(b *Builder) *coll.Collector { return b.buildServiceCollector() }, - "statefulsets": func(b *Builder) *coll.Collector { return b.buildStatefulSetCollector() }, + "certificatesigningrequests": func(b *Builder) *coll.Collector { return b.buildCsrCollector() }, + "configmaps": func(b *Builder) *coll.Collector { return b.buildConfigMapCollector() }, + "cronjobs": func(b *Builder) *coll.Collector { return b.buildCronJobCollector() }, + "daemonsets": func(b *Builder) *coll.Collector { return b.buildDaemonSetCollector() }, + "deployments": func(b *Builder) *coll.Collector { return b.buildDeploymentCollector() }, + "endpoints": func(b *Builder) *coll.Collector { return b.buildEndpointsCollector() }, + "horizontalpodautoscalers": func(b *Builder) *coll.Collector { return b.buildHPACollector() }, + "ingresses": func(b *Builder) *coll.Collector { return b.buildIngressCollector() }, + "jobs": func(b *Builder) *coll.Collector { return b.buildJobCollector() }, + "limitranges": func(b *Builder) *coll.Collector { return b.buildLimitRangeCollector() }, + "namespaces": func(b *Builder) *coll.Collector { return b.buildNamespaceCollector() }, + "nodes": func(b *Builder) *coll.Collector { return b.buildNodeCollector() }, + "persistentvolumeclaims": func(b *Builder) *coll.Collector { return b.buildPersistentVolumeClaimCollector() }, + "persistentvolumes": func(b *Builder) *coll.Collector { return b.buildPersistentVolumeCollector() }, + "poddisruptionbudgets": func(b *Builder) *coll.Collector { return b.buildPodDisruptionBudgetCollector() }, + "pods": func(b *Builder) *coll.Collector { return b.buildPodCollector() }, + "replicasets": func(b *Builder) *coll.Collector { return b.buildReplicaSetCollector() }, + "replicationcontrollers": func(b *Builder) *coll.Collector { return b.buildReplicationControllerCollector() }, + "resourcequotas": func(b *Builder) *coll.Collector { return b.buildResourceQuotaCollector() }, + "secrets": func(b *Builder) *coll.Collector { return b.buildSecretCollector() }, + "services": func(b *Builder) *coll.Collector { return b.buildServiceCollector() }, + "statefulsets": func(b *Builder) *coll.Collector { return b.buildStatefulSetCollector() }, } func (b *Builder) buildConfigMapCollector() *coll.Collector { @@ -450,6 +452,21 @@ func (b *Builder) buildPodCollector() *coll.Collector { return coll.NewCollector(store) } +func (b *Builder) buildCsrCollector() *coll.Collector { + filteredMetricFamilies := metric.FilterMetricFamilies(b.whiteBlackList, csrMetricFamilies) + composedMetricGenFuncs := metric.ComposeMetricGenFuncs(filteredMetricFamilies) + + familyHeaders := metric.ExtractMetricFamilyHeaders(filteredMetricFamilies) + + store := metricsstore.NewMetricsStore( + familyHeaders, + composedMetricGenFuncs, + ) + reflectorPerNamespace(b.ctx, b.kubeClient, &certv1beta1.CertificateSigningRequest{}, store, b.namespaces, createCSRListWatch) + + return coll.NewCollector(store) +} + // reflectorPerNamespace creates a Kubernetes client-go reflector with the given // listWatchFunc for each given namespace and registers it with the given store. func reflectorPerNamespace( diff --git a/internal/collector/certificatesigningrequest.go b/internal/collector/certificatesigningrequest.go new file mode 100644 index 0000000000..f4b9a16aca --- /dev/null +++ b/internal/collector/certificatesigningrequest.go @@ -0,0 +1,152 @@ +/* +Copyright 2019 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 collector + +import ( + "k8s.io/kube-state-metrics/pkg/metric" + + certv1beta1 "k8s.io/api/certificates/v1beta1" + 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 ( + descCSRLabelsName = "kube_certificatesigningrequest_labels" + descCSRLabelsHelp = "Kubernetes labels converted to Prometheus labels." + descCSRLabelsDefaultLabels = []string{"certificatesigningrequest"} + + csrMetricFamilies = []metric.FamilyGenerator{ + { + Name: descCSRLabelsName, + Type: metric.Gauge, + Help: descCSRLabelsHelp, + GenerateFunc: wrapCSRFunc(func(j *certv1beta1.CertificateSigningRequest) *metric.Family { + labelKeys, labelValues := kubeLabelsToPrometheusLabels(j.Labels) + return &metric.Family{ + Metrics: []*metric.Metric{ + { + LabelKeys: labelKeys, + LabelValues: labelValues, + Value: 1, + }, + }, + } + }), + }, + { + Name: "kube_certificatesigningrequest_created", + Type: metric.Gauge, + Help: "Unix creation timestamp", + GenerateFunc: wrapCSRFunc(func(csr *certv1beta1.CertificateSigningRequest) *metric.Family { + ms := []*metric.Metric{} + if !csr.CreationTimestamp.IsZero() { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{}, + LabelValues: []string{}, + Value: float64(csr.CreationTimestamp.Unix()), + }) + } + + return &metric.Family{ + Metrics: ms, + } + }), + }, + { + Name: "kube_certificatesigningrequest_condition", + Type: metric.Gauge, + Help: "The number of each certificatesigningrequest condition", + GenerateFunc: wrapCSRFunc(func(csr *certv1beta1.CertificateSigningRequest) *metric.Family { + return &metric.Family{ + Metrics: addCSRConditionMetrics(csr.Status), + } + }), + }, + { + Name: "kube_certificatesigningrequest_cert_length", + Type: metric.Gauge, + Help: "Length of the issued cert", + GenerateFunc: wrapCSRFunc(func(csr *certv1beta1.CertificateSigningRequest) *metric.Family { + return &metric.Family{ + Metrics: []*metric.Metric{ + { + LabelKeys: []string{}, + LabelValues: []string{}, + Value: float64(len(csr.Status.Certificate)), + }, + }, + } + }), + }, + } +) + +func wrapCSRFunc(f func(*certv1beta1.CertificateSigningRequest) *metric.Family) func(interface{}) *metric.Family { + return func(obj interface{}) *metric.Family { + csr := obj.(*certv1beta1.CertificateSigningRequest) + + metricFamily := f(csr) + + for _, m := range metricFamily.Metrics { + m.LabelKeys = append(descCSRLabelsDefaultLabels, m.LabelKeys...) + m.LabelValues = append([]string{csr.Name}, m.LabelValues...) + } + + return metricFamily + } +} + +func createCSRListWatch(kubeClient clientset.Interface, ns string) cache.ListWatch { + return cache.ListWatch{ + ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { + return kubeClient.CertificatesV1beta1().CertificateSigningRequests().List(opts) + }, + WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { + return kubeClient.CertificatesV1beta1().CertificateSigningRequests().Watch(opts) + }, + } +} + +// addCSRConditionMetrics generates one metric for each possible csr condition status +func addCSRConditionMetrics(cs certv1beta1.CertificateSigningRequestStatus) []*metric.Metric { + cApproved := 0 + cDenied := 0 + for _, s := range cs.Conditions { + if s.Type == certv1beta1.CertificateApproved { + cApproved++ + } + if s.Type == certv1beta1.CertificateDenied { + cDenied++ + } + } + + return []*metric.Metric{ + { + LabelValues: []string{"approved"}, + Value: float64(cApproved), + LabelKeys: []string{"condition"}, + }, + { + LabelValues: []string{"denied"}, + Value: float64(cDenied), + LabelKeys: []string{"condition"}, + }, + } +} diff --git a/internal/collector/certificatesigningrequest_test.go b/internal/collector/certificatesigningrequest_test.go new file mode 100644 index 0000000000..007d3ba6ce --- /dev/null +++ b/internal/collector/certificatesigningrequest_test.go @@ -0,0 +1,220 @@ +/* +Copyright 2019 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 collector + +import ( + "testing" + "time" + + certv1beta1 "k8s.io/api/certificates/v1beta1" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kube-state-metrics/pkg/metric" +) + +func TestCsrCollector(t *testing.T) { + const metadata = ` + # HELP kube_certificatesigningrequest_labels Kubernetes labels converted to Prometheus labels. + # TYPE kube_certificatesigningrequest_labels gauge + # HELP kube_certificatesigningrequest_created Unix creation timestamp + # TYPE kube_certificatesigningrequest_created gauge + # HELP kube_certificatesigningrequest_condition The number of each certificatesigningrequest condition + # TYPE kube_certificatesigningrequest_condition gauge + # HELP kube_certificatesigningrequest_cert_length Length of the issued cert + # TYPE kube_certificatesigningrequest_cert_length gauge + ` + cases := []generateMetricsTestCase{ + { + Obj: &certv1beta1.CertificateSigningRequest{ + ObjectMeta: metav1.ObjectMeta{ + Name: "certificate-test", + Generation: 1, + Labels: map[string]string{ + "cert": "test", + }, + CreationTimestamp: metav1.Time{Time: time.Unix(1500000000, 0)}, + }, + Status: certv1beta1.CertificateSigningRequestStatus{}, + Spec: certv1beta1.CertificateSigningRequestSpec{}, + }, + Want: ` + kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test"} 1.5e+09 + kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="approved"} 0 + kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="denied"} 0 + kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",label_cert="test"} 1 + kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test"} 0 +`, + MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"}, + }, + { + Obj: &certv1beta1.CertificateSigningRequest{ + ObjectMeta: metav1.ObjectMeta{ + Name: "certificate-test", + Generation: 1, + Labels: map[string]string{ + "cert": "test", + }, + CreationTimestamp: metav1.Time{Time: time.Unix(1500000000, 0)}, + }, + Status: certv1beta1.CertificateSigningRequestStatus{ + Conditions: []certv1beta1.CertificateSigningRequestCondition{ + { + Type: certv1beta1.CertificateDenied, + }, + }, + }, + Spec: certv1beta1.CertificateSigningRequestSpec{}, + }, + Want: ` + kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test"} 1.5e+09 + kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="approved"} 0 + kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="denied"} 1 + kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",label_cert="test"} 1 + kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test"} 0 +`, + MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"}, + }, + { + Obj: &certv1beta1.CertificateSigningRequest{ + ObjectMeta: metav1.ObjectMeta{ + Name: "certificate-test", + Generation: 1, + Labels: map[string]string{ + "cert": "test", + }, + CreationTimestamp: metav1.Time{Time: time.Unix(1500000000, 0)}, + }, + Status: certv1beta1.CertificateSigningRequestStatus{ + Conditions: []certv1beta1.CertificateSigningRequestCondition{ + { + Type: certv1beta1.CertificateApproved, + }, + }, + }, + Spec: certv1beta1.CertificateSigningRequestSpec{}, + }, + Want: ` + kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test"} 1.5e+09 + kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="approved"} 1 + kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="denied"} 0 + kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",label_cert="test"} 1 + kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test"} 0 +`, + MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"}, + }, + { + Obj: &certv1beta1.CertificateSigningRequest{ + ObjectMeta: metav1.ObjectMeta{ + Name: "certificate-test", + Generation: 1, + Labels: map[string]string{ + "cert": "test", + }, + CreationTimestamp: metav1.Time{Time: time.Unix(1500000000, 0)}, + }, + Status: certv1beta1.CertificateSigningRequestStatus{ + Certificate: []byte("just for test"), + Conditions: []certv1beta1.CertificateSigningRequestCondition{ + { + Type: certv1beta1.CertificateApproved, + }, + }, + }, + }, + Want: ` + kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test"} 1.5e+09 + kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="approved"} 1 + kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="denied"} 0 + kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",label_cert="test"} 1 + kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test"} 13 +`, + MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"}, + }, + { + Obj: &certv1beta1.CertificateSigningRequest{ + ObjectMeta: metav1.ObjectMeta{ + Name: "certificate-test", + Generation: 1, + Labels: map[string]string{ + "cert": "test", + }, + CreationTimestamp: metav1.Time{Time: time.Unix(1500000000, 0)}, + }, + Status: certv1beta1.CertificateSigningRequestStatus{ + Conditions: []certv1beta1.CertificateSigningRequestCondition{ + { + Type: certv1beta1.CertificateApproved, + }, + { + Type: certv1beta1.CertificateDenied, + }, + }, + }, + }, + Want: ` + kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test"} 1.5e+09 + kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="approved"} 1 + kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="denied"} 1 + kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",label_cert="test"} 1 + kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test"} 0 +`, + MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"}, + }, + { + Obj: &certv1beta1.CertificateSigningRequest{ + ObjectMeta: metav1.ObjectMeta{ + Name: "certificate-test", + Generation: 1, + Labels: map[string]string{ + "cert": "test", + }, + CreationTimestamp: metav1.Time{Time: time.Unix(1500000000, 0)}, + }, + Status: certv1beta1.CertificateSigningRequestStatus{ + Conditions: []certv1beta1.CertificateSigningRequestCondition{ + { + Type: certv1beta1.CertificateApproved, + }, + { + Type: certv1beta1.CertificateDenied, + }, + { + Type: certv1beta1.CertificateApproved, + }, + { + Type: certv1beta1.CertificateDenied, + }, + }, + }, + }, + Want: ` + kube_certificatesigningrequest_created{certificatesigningrequest="certificate-test"} 1.5e+09 + kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="approved"} 2 + kube_certificatesigningrequest_condition{certificatesigningrequest="certificate-test",condition="denied"} 2 + kube_certificatesigningrequest_labels{certificatesigningrequest="certificate-test",label_cert="test"} 1 + kube_certificatesigningrequest_cert_length{certificatesigningrequest="certificate-test"} 0 +`, + MetricNames: []string{"kube_certificatesigningrequest_created", "kube_certificatesigningrequest_condition", "kube_certificatesigningrequest_labels", "kube_certificatesigningrequest_cert_length"}, + }, + } + for i, c := range cases { + c.Func = metric.ComposeMetricGenFuncs(csrMetricFamilies) + if err := c.run(); err != nil { + t.Errorf("unexpected error when collecting result in %vth run:\n%s", i, err) + } + } +} diff --git a/pkg/options/collector.go b/pkg/options/collector.go index 2bc1a3954c..7ecc1751d7 100644 --- a/pkg/options/collector.go +++ b/pkg/options/collector.go @@ -26,26 +26,27 @@ var ( // DefaultCollectors represents the default set of collectors in kube-state-metrics. DefaultCollectors = CollectorSet{ - "configmaps": struct{}{}, - "cronjobs": struct{}{}, - "daemonsets": struct{}{}, - "deployments": struct{}{}, - "endpoints": struct{}{}, - "horizontalpodautoscalers": struct{}{}, - "ingresses": struct{}{}, - "jobs": struct{}{}, - "limitranges": struct{}{}, - "namespaces": struct{}{}, - "nodes": struct{}{}, - "persistentvolumes": struct{}{}, - "persistentvolumeclaims": struct{}{}, - "poddisruptionbudgets": struct{}{}, - "pods": struct{}{}, - "replicasets": struct{}{}, - "replicationcontrollers": struct{}{}, - "resourcequotas": struct{}{}, - "secrets": struct{}{}, - "services": struct{}{}, - "statefulsets": struct{}{}, + "certificatesigningrequests": struct{}{}, + "configmaps": struct{}{}, + "cronjobs": struct{}{}, + "daemonsets": struct{}{}, + "deployments": struct{}{}, + "endpoints": struct{}{}, + "horizontalpodautoscalers": struct{}{}, + "ingresses": struct{}{}, + "jobs": struct{}{}, + "limitranges": struct{}{}, + "namespaces": struct{}{}, + "nodes": struct{}{}, + "persistentvolumes": struct{}{}, + "persistentvolumeclaims": struct{}{}, + "poddisruptionbudgets": struct{}{}, + "pods": struct{}{}, + "replicasets": struct{}{}, + "replicationcontrollers": struct{}{}, + "resourcequotas": struct{}{}, + "secrets": struct{}{}, + "services": struct{}{}, + "statefulsets": struct{}{}, } ) diff --git a/tests/manifests/csr.yaml b/tests/manifests/csr.yaml new file mode 100644 index 0000000000..9f6a718633 --- /dev/null +++ b/tests/manifests/csr.yaml @@ -0,0 +1,14 @@ +apiVersion: certificates.k8s.io/v1beta1 +kind: CertificateSigningRequest +metadata: + name: my-svc.my-namespace +spec: + groups: + - system:masters + - system:authenticated + request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQllqQ0NBUWdDQVFBd01ERXVNQ3dHQTFVRUF4TWxiWGt0Y0c5a0xtMTVMVzVoYldWemNHRmpaUzV3YjJRdQpZMngxYzNSbGNpNXNiMk5oYkRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkpHai9CazNkTVNjCmNmQWdqbWk2d2wxdVYrQVNIR1g1ZHluWHFWdmJsaUd4clFBL2FFOWY0NDc5eFpVR0lDNjFPSmwrR0JJVGhBV0cKWlFiTEhDQ0xscXVnZGpCMEJna3Foa2lHOXcwQkNRNHhaekJsTUdNR0ExVWRFUVJjTUZxQ0pXMTVMWE4yWXk1dAplUzF1WVcxbGMzQmhZMlV1YzNaakxtTnNkWE4wWlhJdWJHOWpZV3lDSlcxNUxYQnZaQzV0ZVMxdVlXMWxjM0JoClkyVXVjRzlrTG1Oc2RYTjBaWEl1Ykc5allXeUhCS3lvQUJpSEJBb0FJZ0l3Q2dZSUtvWkl6ajBFQXdJRFNBQXcKUlFJZ1psb0J6Vkp4UkpjeUlweHZ1WGhTWFRhM3lPaXJDVVRCZytqQk5DUUcyT29DSVFDQVV6c2IzYWxuV1ljdAp5eGxEVEgxZkF6dms3R0ZINVVhd3RwaitWREFJNHc9PQotLS0tLUVORCBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0K + usages: + - digital signature + - key encipherment + - server auth + username: system:admin diff --git a/vendor/modules.txt b/vendor/modules.txt index afab9a943b..36335a3cc1 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -122,6 +122,7 @@ k8s.io/api/apps/v1beta1 k8s.io/api/autoscaling/v2beta1 k8s.io/api/batch/v1 k8s.io/api/batch/v1beta1 +k8s.io/api/certificates/v1beta1 k8s.io/api/core/v1 k8s.io/api/extensions/v1beta1 k8s.io/api/policy/v1beta1 @@ -134,7 +135,6 @@ k8s.io/api/authorization/v1 k8s.io/api/authorization/v1beta1 k8s.io/api/autoscaling/v1 k8s.io/api/batch/v2alpha1 -k8s.io/api/certificates/v1beta1 k8s.io/api/events/v1beta1 k8s.io/api/networking/v1 k8s.io/api/rbac/v1