From 386eafd05fa46bde9fd2fb83d10df0a959370564 Mon Sep 17 00:00:00 2001 From: whitebear009 Date: Tue, 13 Sep 2022 17:16:33 +0800 Subject: [PATCH 01/70] add ContainerResourceSourceType for hpa metrics and reduce cyclomatic complexity --- internal/store/horizontalpodautoscaler.go | 86 ++++++++----------- .../store/horizontalpodautoscaler_test.go | 24 ++++++ 2 files changed, 60 insertions(+), 50 deletions(-) diff --git a/internal/store/horizontalpodautoscaler.go b/internal/store/horizontalpodautoscaler.go index 1b0de5241a..ba069a816b 100644 --- a/internal/store/horizontalpodautoscaler.go +++ b/internal/store/horizontalpodautoscaler.go @@ -131,48 +131,41 @@ func hpaMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat ms := make([]*metric.Metric, 0, len(a.Spec.Metrics)) for _, m := range a.Spec.Metrics { var metricName string - + var metricTarget autoscaling.MetricTarget // The variable maps the type of metric to the corresponding value metricMap := make(map[metricTargetType]float64) switch m.Type { case autoscaling.ObjectMetricSourceType: metricName = m.Object.Metric.Name - - if m.Object.Target.Value != nil { - metricMap[value] = float64(m.Object.Target.Value.MilliValue()) / 1000 - } - if m.Object.Target.AverageValue != nil { - metricMap[average] = float64(m.Object.Target.AverageValue.MilliValue()) / 1000 - } + metricTarget = m.Object.Target case autoscaling.PodsMetricSourceType: metricName = m.Pods.Metric.Name - - metricMap[average] = float64(m.Pods.Target.AverageValue.MilliValue()) / 1000 + metricTarget = m.Pods.Target case autoscaling.ResourceMetricSourceType: metricName = string(m.Resource.Name) - - if m.Resource.Target.AverageUtilization != nil { - metricMap[utilization] = float64(*m.Resource.Target.AverageUtilization) - } - - if m.Resource.Target.AverageValue != nil { - metricMap[average] = float64(m.Resource.Target.AverageValue.MilliValue()) / 1000 - } + metricTarget = m.Resource.Target + case autoscaling.ContainerResourceMetricSourceType: + metricName = string(m.ContainerResource.Name) + metricTarget = m.ContainerResource.Target case autoscaling.ExternalMetricSourceType: metricName = m.External.Metric.Name - - if m.External.Target.Value != nil { - metricMap[value] = float64(m.External.Target.Value.MilliValue()) / 1000 - } - if m.External.Target.AverageValue != nil { - metricMap[average] = float64(m.External.Target.AverageValue.MilliValue()) / 1000 - } + metricTarget = m.External.Target default: // Skip unsupported metric type continue } + if metricTarget.Value != nil { + metricMap[value] = float64(metricTarget.Value.MilliValue()) / 1000 + } + if metricTarget.AverageValue != nil { + metricMap[average] = float64(metricTarget.AverageValue.MilliValue()) / 1000 + } + if metricTarget.AverageUtilization != nil { + metricMap[utilization] = float64(*metricTarget.AverageUtilization) + } + for metricTypeIndex, metricValue := range metricMap { ms = append(ms, &metric.Metric{ LabelKeys: targetMetricLabels, @@ -193,48 +186,41 @@ func hpaMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat ms := make([]*metric.Metric, 0, len(a.Status.CurrentMetrics)) for _, m := range a.Status.CurrentMetrics { var metricName string - + var currentMetric autoscaling.MetricValueStatus // The variable maps the type of metric to the corresponding value metricMap := make(map[metricTargetType]float64) switch m.Type { case autoscaling.ObjectMetricSourceType: metricName = m.Object.Metric.Name - - if m.Object.Current.Value != nil { - metricMap[value] = float64(m.Object.Current.Value.MilliValue()) / 1000 - } - if m.Object.Current.AverageValue != nil { - metricMap[average] = float64(m.Object.Current.AverageValue.MilliValue()) / 1000 - } + currentMetric = m.Object.Current case autoscaling.PodsMetricSourceType: metricName = m.Pods.Metric.Name - - metricMap[average] = float64(m.Pods.Current.AverageValue.MilliValue()) / 1000 + currentMetric = m.Pods.Current case autoscaling.ResourceMetricSourceType: metricName = string(m.Resource.Name) - - if m.Resource.Current.AverageUtilization != nil { - metricMap[utilization] = float64(*m.Resource.Current.AverageUtilization) - } - - if m.Resource.Current.AverageValue != nil { - metricMap[average] = float64(m.Resource.Current.AverageValue.MilliValue()) / 1000 - } + currentMetric = m.Resource.Current + case autoscaling.ContainerResourceMetricSourceType: + metricName = string(m.ContainerResource.Name) + currentMetric = m.ContainerResource.Current case autoscaling.ExternalMetricSourceType: metricName = m.External.Metric.Name - - if m.External.Current.Value != nil { - metricMap[value] = float64(m.External.Current.Value.MilliValue()) / 1000 - } - if m.External.Current.AverageValue != nil { - metricMap[average] = float64(m.External.Current.AverageValue.MilliValue()) / 1000 - } + currentMetric = m.External.Current default: // Skip unsupported metric type continue } + if currentMetric.Value != nil { + metricMap[value] = float64(currentMetric.Value.MilliValue()) / 1000 + } + if currentMetric.AverageValue != nil { + metricMap[average] = float64(currentMetric.AverageValue.MilliValue()) / 1000 + } + if currentMetric.AverageUtilization != nil { + metricMap[utilization] = float64(*currentMetric.AverageUtilization) + } + for metricTypeIndex, metricValue := range metricMap { ms = append(ms, &metric.Metric{ LabelKeys: targetMetricLabels, diff --git a/internal/store/horizontalpodautoscaler_test.go b/internal/store/horizontalpodautoscaler_test.go index d573113a70..41c8d9c49b 100644 --- a/internal/store/horizontalpodautoscaler_test.go +++ b/internal/store/horizontalpodautoscaler_test.go @@ -128,6 +128,16 @@ func TestHPAStore(t *testing.T) { }, }, }, + { + Type: autoscaling.ContainerResourceMetricSourceType, + ContainerResource: &autoscaling.ContainerResourceMetricSource{ + Name: "cpu", + Container: "container1", + Target: autoscaling.MetricTarget{ + AverageUtilization: int32ptr(80), + }, + }, + }, // No targets, this metric should be ignored { Type: autoscaling.ResourceMetricSourceType, @@ -211,6 +221,7 @@ func TestHPAStore(t *testing.T) { kube_horizontalpodautoscaler_spec_target_metric{horizontalpodautoscaler="hpa1",metric_name="hits",metric_target_type="value",namespace="ns1"} 10 kube_horizontalpodautoscaler_spec_target_metric{horizontalpodautoscaler="hpa1",metric_name="connections",metric_target_type="average",namespace="ns1"} 0.7 kube_horizontalpodautoscaler_spec_target_metric{horizontalpodautoscaler="hpa1",metric_name="connections",metric_target_type="value",namespace="ns1"} 0.5 + kube_horizontalpodautoscaler_spec_target_metric{horizontalpodautoscaler="hpa1",metric_name="cpu",metric_target_type="utilization",namespace="ns1"} 80 kube_horizontalpodautoscaler_spec_target_metric{horizontalpodautoscaler="hpa1",metric_name="memory",metric_target_type="average",namespace="ns1"} 819200 kube_horizontalpodautoscaler_spec_target_metric{horizontalpodautoscaler="hpa1",metric_name="memory",metric_target_type="utilization",namespace="ns1"} 80 kube_horizontalpodautoscaler_spec_target_metric{horizontalpodautoscaler="hpa1",metric_name="sqs_jobs",metric_target_type="value",namespace="ns1"} 30 @@ -338,6 +349,17 @@ func TestHPAStore(t *testing.T) { }, }, }, + { + Type: "ContainerResource", + ContainerResource: &autoscaling.ContainerResourceMetricStatus{ + Name: "cpu", + Container: "container1", + Current: autoscaling.MetricValueStatus{ + AverageValue: resourcePtr(resource.MustParse("80m")), + AverageUtilization: int32ptr(10), + }, + }, + }, { Type: "External", External: &autoscaling.ExternalMetricStatus{ @@ -379,6 +401,8 @@ func TestHPAStore(t *testing.T) { kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa2",metric_name="memory",metric_target_type="utilization",namespace="ns1"} 28 kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa2",metric_name="cpu",metric_target_type="average",namespace="ns1"} 0.062 kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa2",metric_name="cpu",metric_target_type="utilization",namespace="ns1"} 6 + kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa2",metric_name="cpu",metric_target_type="average",namespace="ns1"} 0.08 + kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa2",metric_name="cpu",metric_target_type="utilization",namespace="ns1"} 10 kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa2",metric_name="traefik_backend_requests_per_second",metric_target_type="value",namespace="ns1"} 0 kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa2",metric_name="traefik_backend_requests_per_second",metric_target_type="average",namespace="ns1"} 2.9 kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa2",metric_name="traefik_backend_errors_per_second",metric_target_type="value",namespace="ns1"} 0 From 052f572ae7c91ac982a142d5b24d3c2ee4853f1c Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Sat, 3 Sep 2022 02:17:28 +0530 Subject: [PATCH 02/70] Handle singular labels in allowlist Handle singular labels in allowlist failing when such a label is supplied, in order to keep the behaviour in sync with --resources. Signed-off-by: Pranshu Srivastava --- internal/store/builder.go | 8 +++++++- pkg/app/server.go | 4 +++- pkg/builder/types/interfaces.go | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/internal/store/builder.go b/internal/store/builder.go index b8d3c47c4f..c47701efcc 100644 --- a/internal/store/builder.go +++ b/internal/store/builder.go @@ -200,10 +200,16 @@ func (b *Builder) WithAllowAnnotations(annotations map[string][]string) { } // WithAllowLabels configures which labels can be returned for metrics -func (b *Builder) WithAllowLabels(labels map[string][]string) { +func (b *Builder) WithAllowLabels(labels map[string][]string) error { if len(labels) > 0 { + for label := range labels { + if !resourceExists(label) { + return fmt.Errorf("resource %s does not exist. Available resources: %s", label, strings.Join(availableResources(), ",")) + } + } b.allowLabelsList = labels } + return nil } // Build initializes and registers all enabled stores. diff --git a/pkg/app/server.go b/pkg/app/server.go index a4a20234c2..1cb05fe354 100644 --- a/pkg/app/server.go +++ b/pkg/app/server.go @@ -149,7 +149,9 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options, factories . storeBuilder.WithCustomResourceClients(customResourceClients) storeBuilder.WithSharding(opts.Shard, opts.TotalShards) storeBuilder.WithAllowAnnotations(opts.AnnotationsAllowList) - storeBuilder.WithAllowLabels(opts.LabelsAllowList) + if err := storeBuilder.WithAllowLabels(opts.LabelsAllowList); err != nil { + return fmt.Errorf("failed to set up labels allowlist: %v", err) + } ksmMetricsRegistry.MustRegister( collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}), diff --git a/pkg/builder/types/interfaces.go b/pkg/builder/types/interfaces.go index 21b657a24f..ea37e941df 100644 --- a/pkg/builder/types/interfaces.go +++ b/pkg/builder/types/interfaces.go @@ -44,7 +44,7 @@ type BuilderInterface interface { WithUsingAPIServerCache(u bool) WithFamilyGeneratorFilter(l generator.FamilyGeneratorFilter) WithAllowAnnotations(a map[string][]string) - WithAllowLabels(l map[string][]string) + WithAllowLabels(l map[string][]string) error WithGenerateStoresFunc(f BuildStoresFunc) WithGenerateCustomResourceStoresFunc(f BuildCustomResourceStoresFunc) DefaultGenerateStoresFunc() BuildStoresFunc From 633cbf49d0ecf607c716860b21e03c4afd596b8c Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Fri, 7 Oct 2022 23:48:21 +0530 Subject: [PATCH 03/70] Represent GVK information as labels Represent GVK information as labels in the metrics, instead of appending them to the metric name itself. This would allow users to aggregate varying GVKs of a CR under the same metric, making operations much more easier. --- docs/customresourcestate-metrics.md | 22 ++++++++++--------- pkg/customresourcestate/config.go | 15 ++++--------- pkg/customresourcestate/registry_factory.go | 7 ++++++ .../registry_factory_test.go | 2 +- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/docs/customresourcestate-metrics.md b/docs/customresourcestate-metrics.md index 963e5fc55b..2a339658dc 100644 --- a/docs/customresourcestate-metrics.md +++ b/docs/customresourcestate-metrics.md @@ -48,6 +48,8 @@ spec: - --resources=certificatesigningrequests,configmaps,cronjobs,daemonsets,deployments,endpoints,foos,horizontalpodautoscalers,ingresses,jobs,limitranges,mutatingwebhookconfigurations,namespaces,networkpolicies,nodes,persistentvolumeclaims,persistentvolumes,poddisruptionbudgets,pods,replicasets,replicationcontrollers,resourcequotas,secrets,services,statefulsets,storageclasses,validatingwebhookconfigurations,volumeattachments,verticalpodautoscalers ``` +NOTE: The `group`, `version`, and `kind` common labels are reserved, and will be overwritten by the values from the `groupVersionKind` field. + ### Examples The examples in this section will use the following custom resource: @@ -114,7 +116,7 @@ spec: Produces the metric: ```prometheus -kube_myteam_io_v1_Foo_uptime 43.21 +uptime{group="myteam.io", kind="Foo", version="v1"} 43.21 ``` #### Multiple Metrics/Kitchen Sink @@ -165,8 +167,8 @@ spec: Produces the following metrics: ```prometheus -kube_myteam_io_v1_Foo_active_count{active="1",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-a"} 1 -kube_myteam_io_v1_Foo_active_count{active="3",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-b"} 3 +active_count{group="myteam.io", kind="Foo", version="v1", active="1",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-a"} 1 +active_count{group="myteam.io", kind="Foo", version="v1", active="3",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-b"} 3 ``` ### Metric types @@ -201,7 +203,7 @@ spec: Produces the metric: ```prometheus -kube_myteam_io_v1_Foo_uptime 43.21 +uptime{group="myteam.io", kind="Foo", version="v1"} 43.21 ``` #### StateSet @@ -227,15 +229,15 @@ spec: list: [Pending, Bar, Baz] ``` -Metrics of type `SateSet` will generate a metric for each value defined in `list` for each resource. +Metrics of type `StateSet` will generate a metric for each value defined in `list` for each resource. The value will be 1, if the value matches the one in list. Produces the metric: ```prometheus -kube_myteam_io_v1_Foo_status_phase{phase="Pending"} 1 -kube_myteam_io_v1_Foo_status_phase{phase="Bar"} 0 -kube_myteam_io_v1_Foo_status_phase{phase="Baz"} 0 +status_phase{group="myteam.io", kind="Foo", version="v1", phase="Pending"} 1 +status_phase{group="myteam.io", kind="Foo", version="v1", phase="Bar"} 0 +status_phase{group="myteam.io", kind="Foo", version="v1", phase="Baz"} 0 ``` #### Info @@ -265,7 +267,7 @@ spec: Produces the metric: ```prometheus -kube_myteam_io_v1_Foo_version{version="v1.2.3"} 1 +version{group="myteam.io", kind="Foo", version="v1", version="v1.2.3"} 1 ``` ### Naming @@ -287,7 +289,7 @@ spec: Produces: ```prometheus -myteam_foos_uptime 43.21 +myteam_foos_uptime{group="myteam.io", kind="Foo", version="v1"} 43.21 ``` To omit namespace and/or subsystem altogether, set them to the empty string: diff --git a/pkg/customresourcestate/config.go b/pkg/customresourcestate/config.go index 76e7786763..00659e8b45 100644 --- a/pkg/customresourcestate/config.go +++ b/pkg/customresourcestate/config.go @@ -41,9 +41,8 @@ type MetricsSpec struct { // Resource configures a custom resource for metric generation. type Resource struct { // MetricNamePrefix defines a prefix for all metrics of the resource. - // Falls back to the GroupVersionKind string prefixed with "kube_", with invalid characters replaced by _ if nil. // If set to "", no prefix will be added. - // Example: If GroupVersionKind is "my-team.io/v1/MyResource", MetricNamePrefix will be "kube_my_team_io_v1_MyResource". + // Example: If set to "foo", MetricNamePrefix will be "foo_". MetricNamePrefix *string `yaml:"metricNamePrefix" json:"metricNamePrefix"` // GroupVersionKind of the custom resource to be monitored. @@ -63,17 +62,11 @@ type Resource struct { // GetMetricNamePrefix returns the prefix to use for metrics. func (r Resource) GetMetricNamePrefix() string { - if r.MetricNamePrefix == nil { - return strings.NewReplacer( - "/", "_", - ".", "_", - "-", "_", - ).Replace(fmt.Sprintf("kube_%s_%s_%s", r.GroupVersionKind.Group, r.GroupVersionKind.Version, r.GroupVersionKind.Kind)) - } - if *r.MetricNamePrefix == "" { + p := r.MetricNamePrefix + if p == nil { return "" } - return *r.MetricNamePrefix + return *p } // GetResourceName returns the lowercase, plural form of the resource Kind. This is ResourcePlural if it is set. diff --git a/pkg/customresourcestate/registry_factory.go b/pkg/customresourcestate/registry_factory.go index 8cfe716c76..5c78294bd9 100644 --- a/pkg/customresourcestate/registry_factory.go +++ b/pkg/customresourcestate/registry_factory.go @@ -34,6 +34,13 @@ import ( func compile(resource Resource) ([]compiledFamily, error) { var families []compiledFamily + // Explicitly add GVK labels to all CR metrics. + if resource.CommonLabels == nil { + resource.CommonLabels = map[string]string{} + } + resource.CommonLabels["group"] = resource.GroupVersionKind.Group + resource.CommonLabels["version"] = resource.GroupVersionKind.Version + resource.CommonLabels["kind"] = resource.GroupVersionKind.Kind for _, f := range resource.Metrics { family, err := compileFamily(f, resource) if err != nil { diff --git a/pkg/customresourcestate/registry_factory_test.go b/pkg/customresourcestate/registry_factory_test.go index b553fa4be5..db9dd723d4 100644 --- a/pkg/customresourcestate/registry_factory_test.go +++ b/pkg/customresourcestate/registry_factory_test.go @@ -324,7 +324,7 @@ func Test_fullName(t *testing.T) { resource: r(nil), f: count, }, - want: "kube_apps_v1_Deployment_count", + want: "count", }, { name: "no prefix", From 7f906e87b6860f8e2c727f9f4381b092250832bc Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Tue, 18 Oct 2022 21:16:56 +0530 Subject: [PATCH 04/70] fixup! Represent GVK information as labels --- docs/customresourcestate-metrics.md | 16 ++++++++-------- pkg/customresourcestate/config.go | 2 +- pkg/customresourcestate/registry_factory_test.go | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/customresourcestate-metrics.md b/docs/customresourcestate-metrics.md index 2a339658dc..b16ddf7a0e 100644 --- a/docs/customresourcestate-metrics.md +++ b/docs/customresourcestate-metrics.md @@ -116,7 +116,7 @@ spec: Produces the metric: ```prometheus -uptime{group="myteam.io", kind="Foo", version="v1"} 43.21 +kube_uptime{group="myteam.io", kind="Foo", version="v1"} 43.21 ``` #### Multiple Metrics/Kitchen Sink @@ -167,8 +167,8 @@ spec: Produces the following metrics: ```prometheus -active_count{group="myteam.io", kind="Foo", version="v1", active="1",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-a"} 1 -active_count{group="myteam.io", kind="Foo", version="v1", active="3",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-b"} 3 +kube_active_count{group="myteam.io", kind="Foo", version="v1", active="1",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-a"} 1 +kube_active_count{group="myteam.io", kind="Foo", version="v1", active="3",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-b"} 3 ``` ### Metric types @@ -203,7 +203,7 @@ spec: Produces the metric: ```prometheus -uptime{group="myteam.io", kind="Foo", version="v1"} 43.21 +kube_uptime{group="myteam.io", kind="Foo", version="v1"} 43.21 ``` #### StateSet @@ -235,9 +235,9 @@ The value will be 1, if the value matches the one in list. Produces the metric: ```prometheus -status_phase{group="myteam.io", kind="Foo", version="v1", phase="Pending"} 1 -status_phase{group="myteam.io", kind="Foo", version="v1", phase="Bar"} 0 -status_phase{group="myteam.io", kind="Foo", version="v1", phase="Baz"} 0 +kube_status_phase{group="myteam.io", kind="Foo", version="v1", phase="Pending"} 1 +kube_status_phase{group="myteam.io", kind="Foo", version="v1", phase="Bar"} 0 +kube_status_phase{group="myteam.io", kind="Foo", version="v1", phase="Baz"} 0 ``` #### Info @@ -267,7 +267,7 @@ spec: Produces the metric: ```prometheus -version{group="myteam.io", kind="Foo", version="v1", version="v1.2.3"} 1 +kube_version{group="myteam.io", kind="Foo", version="v1", version="v1.2.3"} 1 ``` ### Naming diff --git a/pkg/customresourcestate/config.go b/pkg/customresourcestate/config.go index 00659e8b45..19b2dbb073 100644 --- a/pkg/customresourcestate/config.go +++ b/pkg/customresourcestate/config.go @@ -64,7 +64,7 @@ type Resource struct { func (r Resource) GetMetricNamePrefix() string { p := r.MetricNamePrefix if p == nil { - return "" + return "kube" } return *p } diff --git a/pkg/customresourcestate/registry_factory_test.go b/pkg/customresourcestate/registry_factory_test.go index db9dd723d4..67434b2222 100644 --- a/pkg/customresourcestate/registry_factory_test.go +++ b/pkg/customresourcestate/registry_factory_test.go @@ -324,7 +324,7 @@ func Test_fullName(t *testing.T) { resource: r(nil), f: count, }, - want: "count", + want: "kube_count", }, { name: "no prefix", From 762f98bb700fab13b0684fc0dc8533a79a0c44f0 Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Tue, 18 Oct 2022 21:29:20 +0530 Subject: [PATCH 05/70] fixup! fixup! Represent GVK information as labels --- docs/customresourcestate-metrics.md | 21 ++++++++++++------- pkg/customresourcestate/config.go | 2 +- .../registry_factory_test.go | 2 +- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/docs/customresourcestate-metrics.md b/docs/customresourcestate-metrics.md index b16ddf7a0e..7baaa58231 100644 --- a/docs/customresourcestate-metrics.md +++ b/docs/customresourcestate-metrics.md @@ -116,7 +116,7 @@ spec: Produces the metric: ```prometheus -kube_uptime{group="myteam.io", kind="Foo", version="v1"} 43.21 +kube_crd_uptime{group="myteam.io", kind="Foo", version="v1"} 43.21 ``` #### Multiple Metrics/Kitchen Sink @@ -167,8 +167,8 @@ spec: Produces the following metrics: ```prometheus -kube_active_count{group="myteam.io", kind="Foo", version="v1", active="1",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-a"} 1 -kube_active_count{group="myteam.io", kind="Foo", version="v1", active="3",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-b"} 3 +kube_crd_active_count{group="myteam.io", kind="Foo", version="v1", active="1",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-a"} 1 +kube_crd_active_count{group="myteam.io", kind="Foo", version="v1", active="3",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-b"} 3 ``` ### Metric types @@ -203,7 +203,7 @@ spec: Produces the metric: ```prometheus -kube_uptime{group="myteam.io", kind="Foo", version="v1"} 43.21 +kube_crd_uptime{group="myteam.io", kind="Foo", version="v1"} 43.21 ``` #### StateSet @@ -235,9 +235,9 @@ The value will be 1, if the value matches the one in list. Produces the metric: ```prometheus -kube_status_phase{group="myteam.io", kind="Foo", version="v1", phase="Pending"} 1 -kube_status_phase{group="myteam.io", kind="Foo", version="v1", phase="Bar"} 0 -kube_status_phase{group="myteam.io", kind="Foo", version="v1", phase="Baz"} 0 +kube_crd_status_phase{group="myteam.io", kind="Foo", version="v1", phase="Pending"} 1 +kube_crd_status_phase{group="myteam.io", kind="Foo", version="v1", phase="Bar"} 0 +kube_crd_status_phase{group="myteam.io", kind="Foo", version="v1", phase="Baz"} 0 ``` #### Info @@ -267,7 +267,7 @@ spec: Produces the metric: ```prometheus -kube_version{group="myteam.io", kind="Foo", version="v1", version="v1.2.3"} 1 +kube_crd_version{group="myteam.io", kind="Foo", version="v1", version="v1.2.3"} 1 ``` ### Naming @@ -305,6 +305,11 @@ spec: ... ``` +Produces: +```prometheus +uptime{group="myteam.io", kind="Foo", version="v1"} 43.21 +``` + ### Logging If a metric path is registered but not found on a custom resource, an error will be logged. For some resources, diff --git a/pkg/customresourcestate/config.go b/pkg/customresourcestate/config.go index 19b2dbb073..288c1e90b3 100644 --- a/pkg/customresourcestate/config.go +++ b/pkg/customresourcestate/config.go @@ -64,7 +64,7 @@ type Resource struct { func (r Resource) GetMetricNamePrefix() string { p := r.MetricNamePrefix if p == nil { - return "kube" + return "kube_crd" } return *p } diff --git a/pkg/customresourcestate/registry_factory_test.go b/pkg/customresourcestate/registry_factory_test.go index 67434b2222..1c05cd55ce 100644 --- a/pkg/customresourcestate/registry_factory_test.go +++ b/pkg/customresourcestate/registry_factory_test.go @@ -324,7 +324,7 @@ func Test_fullName(t *testing.T) { resource: r(nil), f: count, }, - want: "kube_count", + want: "kube_crd_count", }, { name: "no prefix", From 6b7027ff41eff6aeba3ab3de644a0c2fa4ee567f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Mon, 17 Oct 2022 00:48:44 +0200 Subject: [PATCH 06/70] Harden and add gosec linter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remediate: G104: Errors unhandled. G109: Potential Integer overflow made by strconv.Atoi result conversion to int16/32 G112: Potential Slowloris Attack because ReadHeaderTimeout is not configured in the http.Server G304: Potential file inclusion via variable G601: Implicit memory aliasing in for loop. Signed-off-by: Manuel Rüger --- .golangci.yml | 5 ++++ internal/store/job.go | 3 +- internal/store/secret.go | 4 +-- main.go | 3 +- pkg/app/server.go | 10 +++++-- pkg/app/server_test.go | 36 +++++++++++++++++++----- pkg/builder/builder_test.go | 7 +++-- pkg/metrics_store/metrics_writer_test.go | 9 ++++-- pkg/metricshandler/metrics_handler.go | 7 +++-- pkg/options/options.go | 5 +++- tests/e2e/main_test.go | 3 +- 11 files changed, 70 insertions(+), 22 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index a0b8723e19..b10ab5c6f3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -8,6 +8,7 @@ linters: - gocyclo - gofmt - goimports + - gosec - gosimple - govet - ineffassign @@ -28,3 +29,7 @@ issues: - path: _test\.go linters: - promlinter + # TODO(mrueg) Improve error handling + - text: "G104:" + linters: + - gosec diff --git a/internal/store/job.go b/internal/store/job.go index cd878c7e08..391fd24b3b 100644 --- a/internal/store/job.go +++ b/internal/store/job.go @@ -212,7 +212,8 @@ func jobMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat } } - for _, condition := range j.Status.Conditions { + for _, c := range j.Status.Conditions { + condition := c if condition.Type == v1batch.JobFailed { reasonKnown := false for _, reason := range jobFailureReasons { diff --git a/internal/store/secret.go b/internal/store/secret.go index fee2a2c8a3..74bca4327f 100644 --- a/internal/store/secret.go +++ b/internal/store/secret.go @@ -33,9 +33,9 @@ import ( var ( descSecretAnnotationsName = "kube_secret_annotations" - descSecretAnnotationsHelp = "Kubernetes annotations converted to Prometheus labels." + descSecretAnnotationsHelp = "Kubernetes annotations converted to Prometheus labels." //nolint:gosec descSecretLabelsName = "kube_secret_labels" - descSecretLabelsHelp = "Kubernetes labels converted to Prometheus labels." + descSecretLabelsHelp = "Kubernetes labels converted to Prometheus labels." //nolint:gosec descSecretLabelsDefaultLabels = []string{"namespace", "secret"} ) diff --git a/main.go b/main.go index a0e6c97a45..4bf0d3fb1f 100644 --- a/main.go +++ b/main.go @@ -20,6 +20,7 @@ import ( "context" "fmt" "os" + "path/filepath" "strings" "github.com/prometheus/common/version" @@ -74,7 +75,7 @@ func resolveCustomResourceConfig(opts *options.Options) (customresourcestate.Con return yaml.NewDecoder(strings.NewReader(s)), true } if file := opts.CustomResourceConfigFile; file != "" { - f, err := os.Open(file) + f, err := os.Open(filepath.Clean(file)) if err != nil { klog.ErrorS(err, "Custom Resource State Metrics file could not be opened") klog.FlushAndExit(klog.ExitFlushTimeout, 1) diff --git a/pkg/app/server.go b/pkg/app/server.go index a4a20234c2..75d08617fd 100644 --- a/pkg/app/server.go +++ b/pkg/app/server.go @@ -178,11 +178,17 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options, factories . telemetryMux := buildTelemetryServer(ksmMetricsRegistry) telemetryListenAddress := net.JoinHostPort(opts.TelemetryHost, strconv.Itoa(opts.TelemetryPort)) - telemetryServer := http.Server{Handler: telemetryMux, Addr: telemetryListenAddress} + telemetryServer := http.Server{ + Handler: telemetryMux, + Addr: telemetryListenAddress, + ReadHeaderTimeout: 5 * time.Second} metricsMux := buildMetricsServer(m, durationVec) metricsServerListenAddress := net.JoinHostPort(opts.Host, strconv.Itoa(opts.Port)) - metricsServer := http.Server{Handler: metricsMux, Addr: metricsServerListenAddress} + metricsServer := http.Server{ + Handler: metricsMux, + Addr: metricsServerListenAddress, + ReadHeaderTimeout: 5 * time.Second} // Run Telemetry server { diff --git a/pkg/app/server_test.go b/pkg/app/server_test.go index cba7e27fe3..a2353a49af 100644 --- a/pkg/app/server_test.go +++ b/pkg/app/server_test.go @@ -73,7 +73,10 @@ func BenchmarkKubeStateMetrics(b *testing.B) { builder := store.NewBuilder() builder.WithMetrics(reg) - builder.WithEnabledResources(options.DefaultResources.AsSlice()) + err := builder.WithEnabledResources(options.DefaultResources.AsSlice()) + if err != nil { + b.Fatal(err) + } builder.WithKubeClient(kubeClient) builder.WithSharding(0, 1) builder.WithContext(ctx) @@ -118,7 +121,10 @@ func BenchmarkKubeStateMetrics(b *testing.B) { b.StopTimer() buf := bytes.Buffer{} - buf.ReadFrom(resp.Body) + _, err := buf.ReadFrom(resp.Body) + if err != nil { + b.Fatal(err) + } accumulatedContentLength += buf.Len() b.StartTimer() } @@ -144,7 +150,10 @@ func TestFullScrapeCycle(t *testing.T) { reg := prometheus.NewRegistry() builder := store.NewBuilder() builder.WithMetrics(reg) - builder.WithEnabledResources(options.DefaultResources.AsSlice()) + err = builder.WithEnabledResources(options.DefaultResources.AsSlice()) + if err != nil { + t.Fatal(err) + } builder.WithKubeClient(kubeClient) builder.WithNamespaces(options.DefaultNamespaces, "") builder.WithGenerateStoresFunc(builder.DefaultGenerateStoresFunc()) @@ -428,7 +437,10 @@ func TestShardingEquivalenceScrapeCycle(t *testing.T) { reg := prometheus.NewRegistry() unshardedBuilder := store.NewBuilder() unshardedBuilder.WithMetrics(reg) - unshardedBuilder.WithEnabledResources(options.DefaultResources.AsSlice()) + err = unshardedBuilder.WithEnabledResources(options.DefaultResources.AsSlice()) + if err != nil { + t.Fatal(err) + } unshardedBuilder.WithKubeClient(kubeClient) unshardedBuilder.WithNamespaces(options.DefaultNamespaces, "") unshardedBuilder.WithFamilyGeneratorFilter(l) @@ -441,7 +453,10 @@ func TestShardingEquivalenceScrapeCycle(t *testing.T) { regShard1 := prometheus.NewRegistry() shardedBuilder1 := store.NewBuilder() shardedBuilder1.WithMetrics(regShard1) - shardedBuilder1.WithEnabledResources(options.DefaultResources.AsSlice()) + err = shardedBuilder1.WithEnabledResources(options.DefaultResources.AsSlice()) + if err != nil { + t.Fatal(err) + } shardedBuilder1.WithKubeClient(kubeClient) shardedBuilder1.WithNamespaces(options.DefaultNamespaces, "") shardedBuilder1.WithFamilyGeneratorFilter(l) @@ -454,7 +469,10 @@ func TestShardingEquivalenceScrapeCycle(t *testing.T) { regShard2 := prometheus.NewRegistry() shardedBuilder2 := store.NewBuilder() shardedBuilder2.WithMetrics(regShard2) - shardedBuilder2.WithEnabledResources(options.DefaultResources.AsSlice()) + err = shardedBuilder2.WithEnabledResources(options.DefaultResources.AsSlice()) + if err != nil { + t.Fatal(err) + } shardedBuilder2.WithKubeClient(kubeClient) shardedBuilder2.WithNamespaces(options.DefaultNamespaces, "") shardedBuilder2.WithFamilyGeneratorFilter(l) @@ -591,7 +609,11 @@ func TestCustomResourceExtension(t *testing.T) { builder := store.NewBuilder() builder.WithCustomResourceStoreFactories(factories...) builder.WithMetrics(reg) - builder.WithEnabledResources(resources) + err := builder.WithEnabledResources(resources) + if err != nil { + t.Fatal(err) + } + builder.WithKubeClient(kubeClient) builder.WithCustomResourceClients(customResourceClients) builder.WithNamespaces(options.DefaultNamespaces, "") diff --git a/pkg/builder/builder_test.go b/pkg/builder/builder_test.go index 9b420d47d0..7189cb1c66 100644 --- a/pkg/builder/builder_test.go +++ b/pkg/builder/builder_test.go @@ -40,9 +40,12 @@ var ( func TestBuilderWithCustomStore(t *testing.T) { b := builder.NewBuilder() b.WithFamilyGeneratorFilter(generator.NewCompositeFamilyGeneratorFilter()) - b.WithEnabledResources([]string{"pods"}) - b.WithGenerateStoresFunc(customStore) + err := b.WithEnabledResources([]string{"pods"}) + if err != nil { + t.Fatal(err) + } + b.WithGenerateStoresFunc(customStore) var fStores []*fakeStore for _, stores := range b.BuildStores() { for _, store := range stores { diff --git a/pkg/metrics_store/metrics_writer_test.go b/pkg/metrics_store/metrics_writer_test.go index ff758a6894..1c3f66fa1a 100644 --- a/pkg/metrics_store/metrics_writer_test.go +++ b/pkg/metrics_store/metrics_writer_test.go @@ -76,7 +76,8 @@ func TestWriteAllWithSingleStore(t *testing.T) { }, }, } - for _, svc := range svcs { + for _, s := range svcs { + svc := s if err := store.Add(&svc); err != nil { t.Fatal(err) } @@ -160,7 +161,8 @@ func TestWriteAllWithMultipleStores(t *testing.T) { }, }, } - for _, svc := range svcs1 { + for _, s := range svcs1 { + svc := s if err := s1.Add(&svc); err != nil { t.Fatal(err) } @@ -183,7 +185,8 @@ func TestWriteAllWithMultipleStores(t *testing.T) { }, } s2 := metricsstore.NewMetricsStore([]string{"Info 1 about services", "Info 2 about services"}, genFunc) - for _, svc := range svcs2 { + for _, s := range svcs2 { + svc := s if err := s2.Add(&svc); err != nil { t.Fatal(err) } diff --git a/pkg/metricshandler/metrics_handler.go b/pkg/metricshandler/metrics_handler.go index d46afa2651..b1a88f051d 100644 --- a/pkg/metricshandler/metrics_handler.go +++ b/pkg/metricshandler/metrics_handler.go @@ -205,7 +205,10 @@ func (m *MetricsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // In case we gzipped the response, we have to close the writer. if closer, ok := writer.(io.Closer); ok { - closer.Close() + err := closer.Close() + if err != nil { + klog.ErrorS(err, "Failed to close the writer") + } } } @@ -226,7 +229,7 @@ func shardingSettingsFromStatefulSet(ss *appsv1.StatefulSet, podName string) (no func detectNominalFromPod(statefulSetName, podName string) (int32, error) { nominalString := strings.TrimPrefix(podName, statefulSetName+"-") - nominal, err := strconv.Atoi(nominalString) + nominal, err := strconv.ParseInt(nominalString, 10, 32) if err != nil { return 0, fmt.Errorf("failed to detect shard index for Pod %s of StatefulSet %s, parsed %s: %w", podName, statefulSetName, nominalString, err) } diff --git a/pkg/options/options.go b/pkg/options/options.go index f87b459c0c..3bd07e9ab8 100644 --- a/pkg/options/options.go +++ b/pkg/options/options.go @@ -79,7 +79,10 @@ func (o *Options) AddFlags() { klogFlags := flag.NewFlagSet("klog", flag.ExitOnError) klog.InitFlags(klogFlags) o.flags.AddGoFlagSet(klogFlags) - o.flags.Lookup("logtostderr").Value.Set("true") + err := o.flags.Lookup("logtostderr").Value.Set("true") + if err != nil { + klog.Error(err) + } o.flags.Lookup("logtostderr").DefValue = "true" o.flags.Lookup("logtostderr").NoOptDefVal = "true" diff --git a/tests/e2e/main_test.go b/tests/e2e/main_test.go index 130d34085d..d01fb99f26 100644 --- a/tests/e2e/main_test.go +++ b/tests/e2e/main_test.go @@ -24,6 +24,7 @@ import ( "log" "os" "path" + "path/filepath" "regexp" "sort" "strings" @@ -165,7 +166,7 @@ func getLabelsDocumentation() (map[string][]string, error) { } filePath := path.Join(docPath, file.Name()) - f, err := os.Open(filePath) + f, err := os.Open(filepath.Clean(filePath)) if err != nil { return nil, fmt.Errorf("cannot read file %s: %w", filePath, err) } From 470c4fa6fb72e38eeada7650d7a92c9b21ed95db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Thu, 20 Oct 2022 21:35:59 +0200 Subject: [PATCH 07/70] .github: Update actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Context: https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/ Signed-off-by: Manuel Rüger --- .github/workflows/ci.yml | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c10fdbea5d..ac03bea322 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,13 +29,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go 1.x - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: go-version: ${{ env.GO_VERSION }} id: go - name: Check out code into the Go module directory - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup environment run: | @@ -52,13 +52,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go 1.x - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: go-version: ${{ env.GO_VERSION }} id: go - name: Check out code into the Go module directory - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup environment run: | @@ -74,13 +74,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go 1.x - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: go-version: ${{ env.GO_VERSION }} id: go - name: Check out code into the Go module directory - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup environment run: | @@ -96,13 +96,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go 1.x - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: go-version: ${{ env.GO_VERSION }} id: go - name: Check out code into the Go module directory - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup environment run: | @@ -118,13 +118,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go 1.x - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: go-version: ${{ env.GO_VERSION }} id: go - name: Check out code into the Go module directory - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup environment run: | @@ -140,7 +140,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup promtool run: | @@ -155,13 +155,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go 1.x - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: go-version: ${{ env.GO_VERSION }} id: go - name: Check out code into the Go module directory - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup environment run: | @@ -177,13 +177,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go 1.x - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: go-version: ${{ env.GO_VERSION }} id: go - name: Check out code into the Go module directory - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup environment run: | @@ -199,13 +199,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go 1.x - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: go-version: ${{ env.GO_VERSION }} id: go - name: Check out code into the Go module directory - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup environment run: | From a13c1107ac4d7a34b60d59374dd965507f5f5b81 Mon Sep 17 00:00:00 2001 From: Han Kang Date: Thu, 20 Oct 2022 12:27:52 -0700 Subject: [PATCH 08/70] add myself to OWNERs --- OWNERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OWNERS b/OWNERS index 067494f09c..6cd4db4d1f 100644 --- a/OWNERS +++ b/OWNERS @@ -1,10 +1,12 @@ reviewers: - dgrisonnet - fpetkovski + - logicalhan - mrueg approvers: - dgrisonnet - fpetkovski + - logicalhan - mrueg emeritus_approvers: - LiliC From 4c6fff147875b033bb0c32e5724ffddbdc1c751e Mon Sep 17 00:00:00 2001 From: Pavel Timofeev Date: Tue, 25 Oct 2022 22:48:27 -0600 Subject: [PATCH 09/70] Fix typos --- docs/customresourcestate-metrics.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/customresourcestate-metrics.md b/docs/customresourcestate-metrics.md index 394c6dbc00..b733509ccd 100644 --- a/docs/customresourcestate-metrics.md +++ b/docs/customresourcestate-metrics.md @@ -151,7 +151,7 @@ spec: labelsFromPath: active: [active] # The actual field to use as metric value. Should be a number. - value: [ready] + valueFrom: [ready] commonLabels: custom_metric: "yes" labelsFromPath: @@ -168,8 +168,8 @@ spec: Produces the following metrics: ```prometheus -kube_crd_active_count{group="myteam.io", kind="Foo", version="v1", active="1",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-a"} 1 -kube_crd_active_count{group="myteam.io", kind="Foo", version="v1", active="3",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-b"} 3 +kube_crd_active_count{group="myteam.io", kind="Foo", version="v1", active="1",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-a"} 2 +kube_crd_active_count{group="myteam.io", kind="Foo", version="v1", active="3",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-b"} 4 ``` ### Metric types From 1ea0ba87a34f217e03680bbb9eb2a4de5a2dded8 Mon Sep 17 00:00:00 2001 From: Pavel Timofeev Date: Wed, 26 Oct 2022 13:53:02 -0600 Subject: [PATCH 10/70] One more typo fix --- docs/customresourcestate-metrics.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/customresourcestate-metrics.md b/docs/customresourcestate-metrics.md index b733509ccd..14345c007f 100644 --- a/docs/customresourcestate-metrics.md +++ b/docs/customresourcestate-metrics.md @@ -168,8 +168,8 @@ spec: Produces the following metrics: ```prometheus -kube_crd_active_count{group="myteam.io", kind="Foo", version="v1", active="1",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-a"} 2 -kube_crd_active_count{group="myteam.io", kind="Foo", version="v1", active="3",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-b"} 4 +kube_crd_ready_count{group="myteam.io", kind="Foo", version="v1", active="1",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-a"} 2 +kube_crd_ready_count{group="myteam.io", kind="Foo", version="v1", active="3",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-b"} 4 ``` ### Metric types From aba1302f28fd18783a80a1adb534079a8d8d124e Mon Sep 17 00:00:00 2001 From: Pavel Timofeev Date: Wed, 26 Oct 2022 13:56:41 -0600 Subject: [PATCH 11/70] Clarify valueFrom comment --- docs/customresourcestate-metrics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/customresourcestate-metrics.md b/docs/customresourcestate-metrics.md index 14345c007f..4e0f5e5e25 100644 --- a/docs/customresourcestate-metrics.md +++ b/docs/customresourcestate-metrics.md @@ -150,7 +150,7 @@ spec: # label values can be resolved specific to this path labelsFromPath: active: [active] - # The actual field to use as metric value. Should be a number. + # The actual field to use as metric value. Should be a number, boolean or RFC3339 timestamp string. valueFrom: [ready] commonLabels: custom_metric: "yes" From 3d8abf894b8b63c762ef1c2d78778d1a4422e0a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Wed, 2 Nov 2022 11:25:42 +0100 Subject: [PATCH 12/70] e2e: Test against k8s 1.25.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Rüger --- tests/e2e.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e.sh b/tests/e2e.sh index e286c6431a..83fa77a3cf 100755 --- a/tests/e2e.sh +++ b/tests/e2e.sh @@ -24,13 +24,13 @@ case $(uname -m) in esac NODE_IMAGE_NAME="docker.io/kindest/node" -KUBERNETES_VERSION=${KUBERNETES_VERSION:-"v1.24.0"} +KUBERNETES_VERSION=${KUBERNETES_VERSION:-"v1.25.0"} KUBE_STATE_METRICS_LOG_DIR=./log KUBE_STATE_METRICS_CURRENT_IMAGE_NAME="registry.k8s.io/kube-state-metrics/kube-state-metrics" 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.14.0 +KIND_VERSION=v0.17.0 SUDO=${SUDO:-} OS=$(uname -s | awk '{print tolower($0)}') From 2c734dca81d9ee22832ab0d82c9b0e29992b83f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Wed, 2 Nov 2022 11:25:29 +0100 Subject: [PATCH 13/70] Makefile: Build with go 1.19.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Rüger --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c33e9a177a..07546003d6 100644 --- a/Makefile +++ b/Makefile @@ -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.37.0 -GO_VERSION = 1.19.2 +PROMETHEUS_VERSION = 2.39.1 +GO_VERSION = 1.19.3 IMAGE = $(REGISTRY)/kube-state-metrics MULTI_ARCH_IMG = $(IMAGE)-$(ARCH) USER ?= $(shell id -u -n) From 81cd6ea2c327ab7183e2e974e1d50d517094938d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Wed, 2 Nov 2022 11:25:16 +0100 Subject: [PATCH 14/70] go.mod: Bump dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Rüger --- go.mod | 37 +++++------ go.sum | 194 +++++++++++---------------------------------------------- 2 files changed, 57 insertions(+), 174 deletions(-) diff --git a/go.mod b/go.mod index 8e45889a6b..aaed3cc3ef 100644 --- a/go.mod +++ b/go.mod @@ -4,28 +4,28 @@ require ( github.com/brancz/gojsontoyaml v0.1.0 github.com/campoy/embedmd v1.0.0 github.com/dgryski/go-jump v0.0.0-20211018200510-ba001c3ffce0 - github.com/gobuffalo/flect v0.2.5 - github.com/google/go-cmp v0.5.8 - github.com/google/go-jsonnet v0.18.0 + github.com/gobuffalo/flect v0.3.0 + github.com/google/go-cmp v0.5.9 + github.com/google/go-jsonnet v0.19.1 github.com/jsonnet-bundler/jsonnet-bundler v0.5.1 github.com/oklog/run v1.1.0 - github.com/prometheus/client_golang v1.13.0 - github.com/prometheus/client_model v0.2.0 + github.com/prometheus/client_golang v1.13.1 + github.com/prometheus/client_model v0.3.0 github.com/prometheus/common v0.37.0 github.com/prometheus/exporter-toolkit v0.7.1 github.com/robfig/cron/v3 v3.0.1 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.8.0 - golang.org/x/perf v0.0.0-20220722155240-3d85ee92886d + github.com/stretchr/testify v1.8.1 + golang.org/x/perf v0.0.0-20220920022801-e8d778a60d07 gopkg.in/yaml.v3 v3.0.1 - k8s.io/api v0.25.2 - k8s.io/apimachinery v0.25.2 + k8s.io/api v0.25.3 + k8s.io/apimachinery v0.25.3 k8s.io/autoscaler/vertical-pod-autoscaler v0.12.0 - k8s.io/client-go v0.25.2 - k8s.io/component-base v0.25.2 + k8s.io/client-go v0.25.3 + k8s.io/component-base v0.25.3 k8s.io/klog/v2 v2.80.1 - k8s.io/sample-controller v0.25.2 - k8s.io/utils v0.0.0-20220922133306-665eaaec4324 + k8s.io/sample-controller v0.25.3 + k8s.io/utils v0.0.0-20221101230645-61b03e2f6476 ) require ( @@ -59,6 +59,7 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/gofuzz v1.1.0 // indirect + github.com/google/safehtml v0.0.2 // indirect github.com/imdario/mergo v0.3.6 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect @@ -74,10 +75,10 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect - golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect - golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect - golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect - golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect + golang.org/x/crypto v0.0.0-20221012134737-56aed061732a // indirect + golang.org/x/net v0.0.0-20220909164309-bea034e7d591 // indirect + golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 // indirect + golang.org/x/sys v0.1.0 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect @@ -92,4 +93,4 @@ require ( sigs.k8s.io/yaml v1.3.0 // indirect ) -go 1.17 +go 1.18 diff --git a/go.sum b/go.sum index 08186905a8..9ac093fd91 100644 --- a/go.sum +++ b/go.sum @@ -46,7 +46,6 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A= @@ -66,7 +65,6 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190129172621-c8b1d7a94ddf/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= @@ -85,10 +83,6 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -102,7 +96,6 @@ github.com/brancz/gojsontoyaml v0.1.0/go.mod h1:+ycZY94+V11XZBUaDEsbLr3hPNS/ZPrD github.com/campoy/embedmd v1.0.0 h1:V4kI2qTJJLf4J29RzI/MAt2c3Bl4dQSYPuflzwFH2hY= github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= @@ -114,21 +107,14 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-jump v0.0.0-20211018200510-ba001c3ffce0 h1:0wH6nO9QEa02Qx8sIQGw6ieKdz+BXjpccSOo9vXNl4U= github.com/dgryski/go-jump v0.0.0-20211018200510-ba001c3ffce0/go.mod h1:4hKCXuwrJoYvHZxJ86+bRVTOMyJ0Ej+RqfSm8mHi6KA= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -138,19 +124,14 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= @@ -174,17 +155,12 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= @@ -193,9 +169,8 @@ github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/ github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/gobuffalo/flect v0.2.5 h1:H6vvsv2an0lalEaCDRThvtBfmg44W/QHXBCYUXf/6S4= -github.com/gobuffalo/flect v0.2.5/go.mod h1:1ZyCLIbg0YD7sDkzvFdPoOydPtD8y9JQnrOROolUcM8= +github.com/gobuffalo/flect v0.3.0 h1:erfPWM+K1rFNIQeRPdeEXxo8yFr/PO17lhRnS8FUrtk= +github.com/gobuffalo/flect v0.3.0/go.mod h1:5pf3aGnsvqvCj50AVni7mJJF8ICxGZ8HomberC3pXLE= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -207,7 +182,6 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -243,7 +217,6 @@ github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2 github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -258,10 +231,10 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-jsonnet v0.18.0 h1:/6pTy6g+Jh1a1I2UMoAODkqELFiVIdOxbNwv0DDzoOg= -github.com/google/go-jsonnet v0.18.0/go.mod h1:C3fTzyVJDslXdiTqw/bTFk7vSGyCtH3MGRbDfvEwGd0= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-jsonnet v0.19.1 h1:MORxkrG0elylUqh36R4AcSPX0oZQa9hvI3lroN+kDhs= +github.com/google/go-jsonnet v0.19.1/go.mod h1:5JVT33JVCoehdTj5Z2KJq1eIdt3Nb8PCmZ+W5D8U350= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -280,29 +253,25 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/safehtml v0.0.2 h1:ZOt2VXg4x24bW0m2jtzAOkhoXV0iM8vNKc0paByCZqM= +github.com/google/safehtml v0.0.2/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go v0.0.0-20161107002406-da06d194a00e/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= @@ -349,9 +318,6 @@ github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGw github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -359,33 +325,16 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU= -github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q= -github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= @@ -401,13 +350,14 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= +github.com/prometheus/client_golang v1.13.1 h1:3gMjIY2+/hzmqhtUC/aQNYldJA6DtH3CgQvwS+02K1c= +github.com/prometheus/client_golang v1.13.1/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= @@ -431,7 +381,6 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= @@ -440,33 +389,28 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -474,21 +418,7 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -498,8 +428,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38= -golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20221012134737-56aed061732a h1:NmSIgad6KjE6VvHciPZuNRTKxGhlPfD6OA87W/PLkqg= +golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -548,11 +478,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -576,7 +503,6 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -589,16 +515,13 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/oauth2 v0.0.0-20170207211851-4464e7848382/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -615,11 +538,11 @@ golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq6kgU7yl5ub2cQLSdrv1Dg= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/perf v0.0.0-20220722155240-3d85ee92886d h1:YurdHpXO0MGox7XtCYq5Xm2kYylGN90LEfw4en36WVM= -golang.org/x/perf v0.0.0-20220722155240-3d85ee92886d/go.mod h1:O34quEX6kI7y6XJXzRa1g18oSkBHYYQN9/OSig0x0QM= +golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 h1:lxqLZaMad/dJHMFZH0NiNpiEZI/nhgWhe4wgzpE+MuA= +golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/perf v0.0.0-20220920022801-e8d778a60d07 h1:LhnzFL4oipoFsDvxTy2IJRHgOlnGzB2dE5l7C4PN7bg= +golang.org/x/perf v0.0.0-20220920022801-e8d778a60d07/go.mod h1:UBKtEnL8aqnd+0JHqZ+2qoMDwtuy6cYhhKNoHLBiTQc= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -631,11 +554,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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= @@ -646,10 +566,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -674,7 +591,6 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -695,15 +611,11 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -735,13 +647,11 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -761,7 +671,6 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -773,7 +682,6 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= @@ -782,8 +690,6 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -888,7 +794,6 @@ google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEc google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/grpc v0.0.0-20170208002647-2a6bf6142e96/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -915,8 +820,6 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -931,7 +834,6 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= @@ -943,10 +845,8 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -959,11 +859,8 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -971,38 +868,24 @@ 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.25.0/go.mod h1:ttceV1GyV1i1rnmvzT3BST08N6nGt+dudGrquzVQWPk= -k8s.io/api v0.25.2 h1:v6G8RyFcwf0HR5jQGIAYlvtRNrxMJQG1xJzaSeVnIS8= -k8s.io/api v0.25.2/go.mod h1:qP1Rn4sCVFwx/xIhe+we2cwBLTXNcheRyYXwajonhy0= -k8s.io/apimachinery v0.25.0/go.mod h1:qMx9eAk0sZQGsXGu86fab8tZdffHbwUfsvzqKn4mfB0= -k8s.io/apimachinery v0.25.2 h1:WbxfAjCx+AeN8Ilp9joWnyJ6xu9OMeS/fsfjK/5zaQs= -k8s.io/apimachinery v0.25.2/go.mod h1:hqqA1X0bsgsxI6dXsJ4HnNTBOmJNxyPp8dw3u2fSHwA= +k8s.io/api v0.25.3 h1:Q1v5UFfYe87vi5H7NU0p4RXC26PPMT8KOpr1TLQbCMQ= +k8s.io/api v0.25.3/go.mod h1:o42gKscFrEVjHdQnyRenACrMtbuJsVdP+WVjqejfzmI= +k8s.io/apimachinery v0.25.3 h1:7o9ium4uyUOM76t6aunP0nZuex7gDf8VGwkR5RcJnQc= +k8s.io/apimachinery v0.25.3/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo= k8s.io/autoscaler/vertical-pod-autoscaler v0.12.0 h1:cy8LoXSl5GkTNJDTx3ZCS143f9Ai7gqnGkoUxPlGSmI= k8s.io/autoscaler/vertical-pod-autoscaler v0.12.0/go.mod h1:LraL5kR2xX7jb4VMCG6/tUH4I75uRHlnzC0VWQHcyWk= -k8s.io/client-go v0.25.0/go.mod h1:lxykvypVfKilxhTklov0wz1FoaUZ8X4EwbhS6rpRfN8= -k8s.io/client-go v0.25.2 h1:SUPp9p5CwM0yXGQrwYurw9LWz+YtMwhWd0GqOsSiefo= -k8s.io/client-go v0.25.2/go.mod h1:i7cNU7N+yGQmJkewcRD2+Vuj4iz7b30kI8OcL3horQ4= -k8s.io/code-generator v0.25.0/go.mod h1:B6jZgI3DvDFAualltPitbYMQ74NjaCFxum3YeKZZ+3w= -k8s.io/code-generator v0.25.2/go.mod h1:f61OcU2VqVQcjt/6TrU0sta1TA5hHkOO6ZZPwkL9Eys= -k8s.io/component-base v0.25.0/go.mod h1:F2Sumv9CnbBlqrpdf7rKZTmmd2meJq0HizeyY/yAFxk= -k8s.io/component-base v0.25.2 h1:Nve/ZyHLUBHz1rqwkjXm/Re6IniNa5k7KgzxZpTfSQY= -k8s.io/component-base v0.25.2/go.mod h1:90W21YMr+Yjg7MX+DohmZLzjsBtaxQDDwaX4YxDkl60= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/client-go v0.25.3 h1:oB4Dyl8d6UbfDHD8Bv8evKylzs3BXzzufLiO27xuPs0= +k8s.io/client-go v0.25.3/go.mod h1:t39LPczAIMwycjcXkVc+CB+PZV69jQuNx4um5ORDjQA= +k8s.io/component-base v0.25.3 h1:UrsxciGdrCY03ULT1h/S/gXFCOPnLhUVwSyx+hM/zq4= +k8s.io/component-base v0.25.3/go.mod h1:WYoS8L+IlTZgU7rhAl5Ctpw0WdMxDfCC5dkxcEFa/TI= k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA= k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= -k8s.io/metrics v0.25.0/go.mod h1:HZZrbhuRX+fsDcRc3u59o2FbrKhqD67IGnoFECNmovc= -k8s.io/sample-controller v0.25.2 h1:nNbg1HWuurEFNnPgQmup4zDza2FJ+TG6vxfPOnSMlEo= -k8s.io/sample-controller v0.25.2/go.mod h1:JYee8Sey/F0WrkhkUdB3vVMQYzzmMQTVRpcgg7Veddg= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220922133306-665eaaec4324 h1:i+xdFemcSNuJvIfBlaYuXgRondKxK4z4prVPKzEaelI= -k8s.io/utils v0.0.0-20220922133306-665eaaec4324/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/sample-controller v0.25.3 h1:6abaENCl89Kl+/4tW+SOq18HnZhEd7L4rf9H6VjUTCk= +k8s.io/sample-controller v0.25.3/go.mod h1:73CRRrRusGH3xNcC35ZlzGrZDpbvBzInWD53AaIwat4= +k8s.io/utils v0.0.0-20221101230645-61b03e2f6476 h1:L14f2LWkOxG2rYsuSA3ltQnnST1vMfek/GUk+VemxD4= +k8s.io/utils v0.0.0-20221101230645-61b03e2f6476/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= @@ -1012,6 +895,5 @@ sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h6 sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= From 38858e60023765817acfe07500b71e30d5a155f6 Mon Sep 17 00:00:00 2001 From: Han Kang Date: Thu, 3 Nov 2022 09:21:31 -0700 Subject: [PATCH 15/70] Update OWNERS --- OWNERS | 1 - 1 file changed, 1 deletion(-) diff --git a/OWNERS b/OWNERS index 6cd4db4d1f..c5ce828386 100644 --- a/OWNERS +++ b/OWNERS @@ -6,7 +6,6 @@ reviewers: approvers: - dgrisonnet - fpetkovski - - logicalhan - mrueg emeritus_approvers: - LiliC From 5d20fd34540fe66da7ee877316def4d85c92ba1c Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Thu, 3 Nov 2022 22:47:02 +0530 Subject: [PATCH 16/70] Recommend kube-scheduler alternatives Recommend metrics exposed by the kube-scheduler, in case of the ones below: * `kube_pod_container_resource_limits` * `kube_pod_container_resource_requests` Signed-off-by: Pranshu Srivastava --- docs/pod-metrics.md | 90 +++++++++++++++++++------------------- internal/store/pod.go | 4 +- internal/store/pod_test.go | 4 +- pkg/app/server_test.go | 4 +- 4 files changed, 51 insertions(+), 51 deletions(-) diff --git a/docs/pod-metrics.md b/docs/pod-metrics.md index fcea2027d6..627ae4f90c 100644 --- a/docs/pod-metrics.md +++ b/docs/pod-metrics.md @@ -1,54 +1,54 @@ # Pod Metrics -| Metric name| Metric type | Description | Unit (where applicable) | Labels/tags | Status | Opt-in | -| ---------- | ----------- | ----------- | ----------------------- | ----------- | ------ | ------ | -| kube_pod_annotations | Gauge | Kubernetes annotations converted to Prometheus labels | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`annotation_POD_ANNOTATION`=<POD_ANNOTATION>
`uid`=<pod-uid> | EXPERIMENTAL | - -| kube_pod_info | Gauge | Information about pod | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`host_ip`=<host-ip>
`pod_ip`=<pod-ip>
`node`=<node-name>
`created_by_kind`=<created_by_kind>
`created_by_name`=<created_by_name>
`uid`=<pod-uid>
`priority_class`=<priority_class>
`host_network`=<host_network>| STABLE | - | -| kube_pod_ips | Gauge | Pod IP addresses | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`ip`=<pod-ip-address>
`ip_family`=<4 OR 6>
`uid`=<pod-uid> | EXPERIMENTAL | - | -| kube_pod_start_time | Gauge | Start time in unix timestamp for a pod | seconds | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_completion_time | Gauge | Completion time in unix timestamp for a pod | seconds | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_owner | Gauge | Information about the Pod's owner | |`pod`=<pod-name>
`namespace`=<pod-namespace>
`owner_kind`=<owner kind>
`owner_name`=<owner name>
`owner_is_controller`=<whether owner is controller>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_labels | Gauge | Kubernetes labels converted to Prometheus labels | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`label_POD_LABEL`=<POD_LABEL>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_nodeselectors| Gauge | Describes the Pod nodeSelectors | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`nodeselector_NODE_SELECTOR`=<NODE_SELECTOR>
`uid`=<pod-uid> | EXPERIMENTAL | Opt-in | -| kube_pod_status_phase | Gauge | The pods current phase | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`phase`=<Pending\|Running\|Succeeded\|Failed\|Unknown>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_status_ready | Gauge | Describes whether the pod is ready to serve requests | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`condition`=<true\|false\|unknown>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_status_scheduled | Gauge | Describes the status of the scheduling process for the pod | |`pod`=<pod-name>
`namespace`=<pod-namespace>
`condition`=<true\|false\|unknown>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_container_info | Gauge | Information about a container in a pod | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`image`=<image-name>
`image_id`=<image-id>
`image_spec`=<image-spec>
`container_id`=<containerid>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_container_status_waiting | Gauge | Describes whether the container is currently in waiting state | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_container_status_waiting_reason | Gauge | Describes the reason the container is currently in waiting state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<container-waiting-reason>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_container_status_running | Gauge | Describes whether the container is currently in running state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_container_state_started | Gauge | Start time in unix timestamp for a pod container | seconds |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_container_status_terminated | Gauge | Describes whether the container is currently in terminated state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_container_status_terminated_reason | Gauge | Describes the reason the container is currently in terminated state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<container-terminated-reason>
`uid`=<pod-uid> | EXPERIMENTAL | - | -| kube_pod_container_status_last_terminated_reason | Gauge | Describes the last reason the container was in terminated state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<last-terminated-reason>
`uid`=<pod-uid> | EXPERIMENTAL | - | -| kube_pod_container_status_last_terminated_exitcode | Gauge | Describes the exit code for the last container in terminated state. | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | -| kube_pod_container_status_ready | Gauge | Describes whether the containers readiness check succeeded | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_container_status_restarts_total | Counter | The number of container restarts per container | | `container`=<container-name>
`namespace`=<pod-namespace>
`pod`=<pod-name>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_container_resource_requests | Gauge | The number of requested request resource by a container | `cpu`=<core>
`memory`=<bytes> |`resource`=<resource-name>
`unit`=<resource-unit>
`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`node`=< node-name>
`uid`=<pod-uid> | EXPERIMENTAL | - | -| kube_pod_container_resource_limits | Gauge | The number of requested limit resource by a container | `cpu`=<core>
`memory`=<bytes> |`resource`=<resource-name>
`unit`=<resource-unit>
`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`node`=< node-name>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| Metric name| Metric type | Description | Unit (where applicable) | Labels/tags | Status | Opt-in | +| ---------- | ----------- |-----------------------------------------------------------------------| ----------------------- | ----------- | ------ | ------ | +| kube_pod_annotations | Gauge | Kubernetes annotations converted to Prometheus labels | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`annotation_POD_ANNOTATION`=<POD_ANNOTATION>
`uid`=<pod-uid> | EXPERIMENTAL | - +| kube_pod_info | Gauge | Information about pod | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`host_ip`=<host-ip>
`pod_ip`=<pod-ip>
`node`=<node-name>
`created_by_kind`=<created_by_kind>
`created_by_name`=<created_by_name>
`uid`=<pod-uid>
`priority_class`=<priority_class>
`host_network`=<host_network>| STABLE | - | +| kube_pod_ips | Gauge | Pod IP addresses | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`ip`=<pod-ip-address>
`ip_family`=<4 OR 6>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_start_time | Gauge | Start time in unix timestamp for a pod | seconds | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_completion_time | Gauge | Completion time in unix timestamp for a pod | seconds | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_owner | Gauge | Information about the Pod's owner | |`pod`=<pod-name>
`namespace`=<pod-namespace>
`owner_kind`=<owner kind>
`owner_name`=<owner name>
`owner_is_controller`=<whether owner is controller>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_labels | Gauge | Kubernetes labels converted to Prometheus labels | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`label_POD_LABEL`=<POD_LABEL>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_nodeselectors| Gauge | Describes the Pod nodeSelectors | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`nodeselector_NODE_SELECTOR`=<NODE_SELECTOR>
`uid`=<pod-uid> | EXPERIMENTAL | Opt-in | +| kube_pod_status_phase | Gauge | The pods current phase | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`phase`=<Pending\|Running\|Succeeded\|Failed\|Unknown>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_status_ready | Gauge | Describes whether the pod is ready to serve requests | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`condition`=<true\|false\|unknown>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_status_scheduled | Gauge | Describes the status of the scheduling process for the pod | |`pod`=<pod-name>
`namespace`=<pod-namespace>
`condition`=<true\|false\|unknown>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_container_info | Gauge | Information about a container in a pod | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`image`=<image-name>
`image_id`=<image-id>
`image_spec`=<image-spec>
`container_id`=<containerid>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_container_status_waiting | Gauge | Describes whether the container is currently in waiting state | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_container_status_waiting_reason | Gauge | Describes the reason the container is currently in waiting state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<container-waiting-reason>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_container_status_running | Gauge | Describes whether the container is currently in running state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_container_state_started | Gauge | Start time in unix timestamp for a pod container | seconds |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_container_status_terminated | Gauge | Describes whether the container is currently in terminated state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_container_status_terminated_reason | Gauge | Describes the reason the container is currently in terminated state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<container-terminated-reason>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_container_status_last_terminated_reason | Gauge | Describes the last reason the container was in terminated state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<last-terminated-reason>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_container_status_last_terminated_exitcode | Gauge | Describes the exit code for the last container in terminated state. | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_container_status_ready | Gauge | Describes whether the containers readiness check succeeded | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_container_status_restarts_total | Counter | The number of container restarts per container | | `container`=<container-name>
`namespace`=<pod-namespace>
`pod`=<pod-name>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_container_resource_requests | Gauge | The number of requested request resource by a container. It is recommended to use the `kube_pod_resource_requests` metric exposed by kube-scheduler instead, as it is more precise. | `cpu`=<core>
`memory`=<bytes> |`resource`=<resource-name>
`unit`=<resource-unit>
`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`node`=< node-name>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_container_resource_limits | Gauge | The number of requested limit resource by a container. It is recommended to use the `kube_pod_resource_limits` metric exposed by kube-scheduler instead, as it is more precise. | `cpu`=<core>
`memory`=<bytes> |`resource`=<resource-name>
`unit`=<resource-unit>
`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`node`=< node-name>
`uid`=<pod-uid> | EXPERIMENTAL | - | | kube_pod_overhead_cpu_cores | Gauge | The pod overhead in regards to cpu cores associated with running a pod | core |`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | -| kube_pod_overhead_memory_bytes | Gauge | The pod overhead in regards to memory associated with running a pod | bytes |`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | -| kube_pod_runtimeclass_name_info | Gauge | The runtimeclass associated with the pod | |`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | -| kube_pod_created | Gauge | Unix creation timestamp | seconds |`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_deletion_timestamp | Gauge | Unix deletion timestamp | seconds |`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | -| kube_pod_restart_policy | Gauge | Describes the restart policy in use by this pod | |`pod`=<pod-name>
`namespace`=<pod-namespace>
`type`=<Always\|Never\|OnFailure>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_init_container_info | Gauge | Information about an init container in a pod | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`image`=<image-name>
`image_id`=<image-id>
`image_spec`=<image-spec>
`container_id`=<containerid>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_init_container_status_waiting | Gauge | Describes whether the init container is currently in waiting state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_overhead_memory_bytes | Gauge | The pod overhead in regards to memory associated with running a pod | bytes |`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_runtimeclass_name_info | Gauge | The runtimeclass associated with the pod | |`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_created | Gauge | Unix creation timestamp | seconds |`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_deletion_timestamp | Gauge | Unix deletion timestamp | seconds |`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_restart_policy | Gauge | Describes the restart policy in use by this pod | |`pod`=<pod-name>
`namespace`=<pod-namespace>
`type`=<Always\|Never\|OnFailure>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_init_container_info | Gauge | Information about an init container in a pod | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`image`=<image-name>
`image_id`=<image-id>
`image_spec`=<image-spec>
`container_id`=<containerid>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_init_container_status_waiting | Gauge | Describes whether the init container is currently in waiting state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | | kube_pod_init_container_status_waiting_reason | Gauge | Describes the reason the init container is currently in waiting state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<container-waiting-reason>
`uid`=<pod-uid> | EXPERIMENTAL | - | -| kube_pod_init_container_status_running | Gauge | Describes whether the init container is currently in running state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_init_container_status_running | Gauge | Describes whether the init container is currently in running state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | | kube_pod_init_container_status_terminated | Gauge | Describes whether the init container is currently in terminated state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | | kube_pod_init_container_status_terminated_reason | Gauge | Describes the reason the init container is currently in terminated state | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<container-terminated-reason>
`uid`=<pod-uid> | EXPERIMENTAL | - | -| kube_pod_init_container_status_last_terminated_reason | Gauge | Describes the last reason the init container was in terminated state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<last-terminated-reason>
`uid`=<pod-uid> | EXPERIMENTAL | - | -| kube_pod_init_container_status_ready | Gauge | Describes whether the init containers readiness check succeeded | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_init_container_status_restarts_total | Counter | The number of restarts for the init container | integer |`container`=<container-name>
`namespace`=<pod-namespace>
`pod`=<pod-name>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_init_container_resource_limits | Gauge | The number of CPU cores requested limit by an init container | `cpu`=<core>
`memory`=<bytes> |`resource`=<resource-name>
`unit`=<resource-unit>
`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`node`=< node-name>
`uid`=<pod-uid> | EXPERIMENTAL | - | -| kube_pod_init_container_resource_requests | Gauge | The number of CPU cores requested by an init container | `cpu`=<core>
`memory`=<bytes> |`resource`=<resource-name>
`unit`=<resource-unit>
`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`node`=< node-name>
`uid`=<pod-uid> | EXPERIMENTAL | - | -| kube_pod_spec_volumes_persistentvolumeclaims_info | Gauge | Information about persistentvolumeclaim volumes in a pod | |`pod`=<pod-name>
`namespace`=<pod-namespace>
`volume`=<volume-name>
`persistentvolumeclaim`=<persistentvolumeclaim-claimname>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_spec_volumes_persistentvolumeclaims_readonly | Gauge | Describes whether a persistentvolumeclaim is mounted read only | bool |`pod`=<pod-name>
`namespace`=<pod-namespace>
`volume`=<volume-name>
`persistentvolumeclaim`=<persistentvolumeclaim-claimname>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_status_reason | Gauge | The pod status reasons | |`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<Evicted\|NodeAffinity\|NodeLost\|Shutdown\|UnexpectedAdmissionError>
`uid`=<pod-uid> | EXPERIMENTAL | - | -| kube_pod_status_scheduled_time | Gauge | Unix timestamp when pod moved into scheduled status | seconds |`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_status_unschedulable | Gauge | Describes the unschedulable status for the pod | |`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | -| kube_pod_tolerations | Gauge | Information about the pod tolerations | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid>
`key`=<toleration-key>
`operator`=<toleration-operator>
`value`=<toleration-value>
`effect`=<toleration-effect> `toleration_seconds`=<toleration-seconds> | EXPERIMENTAL | - | +| kube_pod_init_container_status_last_terminated_reason | Gauge | Describes the last reason the init container was in terminated state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<last-terminated-reason>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_init_container_status_ready | Gauge | Describes whether the init containers readiness check succeeded | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_init_container_status_restarts_total | Counter | The number of restarts for the init container | integer |`container`=<container-name>
`namespace`=<pod-namespace>
`pod`=<pod-name>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_init_container_resource_limits | Gauge | The number of CPU cores requested limit by an init container | `cpu`=<core>
`memory`=<bytes> |`resource`=<resource-name>
`unit`=<resource-unit>
`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`node`=< node-name>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_init_container_resource_requests | Gauge | The number of CPU cores requested by an init container | `cpu`=<core>
`memory`=<bytes> |`resource`=<resource-name>
`unit`=<resource-unit>
`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`node`=< node-name>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_spec_volumes_persistentvolumeclaims_info | Gauge | Information about persistentvolumeclaim volumes in a pod | |`pod`=<pod-name>
`namespace`=<pod-namespace>
`volume`=<volume-name>
`persistentvolumeclaim`=<persistentvolumeclaim-claimname>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_spec_volumes_persistentvolumeclaims_readonly | Gauge | Describes whether a persistentvolumeclaim is mounted read only | bool |`pod`=<pod-name>
`namespace`=<pod-namespace>
`volume`=<volume-name>
`persistentvolumeclaim`=<persistentvolumeclaim-claimname>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_status_reason | Gauge | The pod status reasons | |`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<Evicted\|NodeAffinity\|NodeLost\|Shutdown\|UnexpectedAdmissionError>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_status_scheduled_time | Gauge | Unix timestamp when pod moved into scheduled status | seconds |`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_status_unschedulable | Gauge | Describes the unschedulable status for the pod | |`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_tolerations | Gauge | Information about the pod tolerations | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid>
`key`=<toleration-key>
`operator`=<toleration-operator>
`value`=<toleration-value>
`effect`=<toleration-effect> `toleration_seconds`=<toleration-seconds> | EXPERIMENTAL | - | ## Useful metrics queries diff --git a/internal/store/pod.go b/internal/store/pod.go index 3d09fc137c..2bbbde9f3b 100644 --- a/internal/store/pod.go +++ b/internal/store/pod.go @@ -160,7 +160,7 @@ func createPodContainerInfoFamilyGenerator() generator.FamilyGenerator { func createPodContainerResourceLimitsFamilyGenerator() generator.FamilyGenerator { return *generator.NewFamilyGenerator( "kube_pod_container_resource_limits", - "The number of requested limit resource by a container.", + "The number of requested limit resource by a container. It is recommended to use the kube_pod_resource_limits metric exposed by kube-scheduler instead, as it is more precise.", metric.Gauge, "", wrapPodFunc(func(p *v1.Pod) *metric.Family { @@ -223,7 +223,7 @@ func createPodContainerResourceLimitsFamilyGenerator() generator.FamilyGenerator func createPodContainerResourceRequestsFamilyGenerator() generator.FamilyGenerator { return *generator.NewFamilyGenerator( "kube_pod_container_resource_requests", - "The number of requested request resource by a container.", + "The number of requested request resource by a container. It is recommended to use the kube_pod_resource_requests metric exposed by kube-scheduler instead, as it is more precise.", metric.Gauge, "", wrapPodFunc(func(p *v1.Pod) *metric.Family { diff --git a/internal/store/pod_test.go b/internal/store/pod_test.go index e94ecc3190..2306191472 100644 --- a/internal/store/pod_test.go +++ b/internal/store/pod_test.go @@ -1613,8 +1613,8 @@ func TestPodStore(t *testing.T) { }, }, Want: ` - # HELP kube_pod_container_resource_limits The number of requested limit resource by a container. - # HELP kube_pod_container_resource_requests The number of requested request resource by a container. + # HELP kube_pod_container_resource_limits The number of requested limit resource by a container. It is recommended to use the kube_pod_resource_limits metric exposed by kube-scheduler instead, as it is more precise. + # HELP kube_pod_container_resource_requests The number of requested request resource by a container. It is recommended to use the kube_pod_resource_requests metric exposed by kube-scheduler instead, as it is more precise. # HELP kube_pod_init_container_resource_limits The number of requested limit resource by an init container. # HELP kube_pod_init_container_resource_requests The number of requested request resource by an init container. # HELP kube_pod_init_container_status_last_terminated_reason Describes the last reason the init container was in terminated state. diff --git a/pkg/app/server_test.go b/pkg/app/server_test.go index a2353a49af..afb861c21f 100644 --- a/pkg/app/server_test.go +++ b/pkg/app/server_test.go @@ -202,8 +202,8 @@ func TestFullScrapeCycle(t *testing.T) { expected := `# HELP kube_pod_annotations Kubernetes annotations converted to Prometheus labels. # HELP kube_pod_completion_time [STABLE] Completion time in unix timestamp for a pod. # HELP kube_pod_container_info [STABLE] Information about a container in a pod. -# HELP kube_pod_container_resource_limits The number of requested limit resource by a container. -# HELP kube_pod_container_resource_requests The number of requested request resource by a container. +# HELP kube_pod_container_resource_limits The number of requested limit resource by a container. It is recommended to use the kube_pod_resource_limits metric exposed by kube-scheduler instead, as it is more precise. +# HELP kube_pod_container_resource_requests The number of requested request resource by a container. It is recommended to use the kube_pod_resource_requests metric exposed by kube-scheduler instead, as it is more precise. # HELP kube_pod_container_state_started [STABLE] Start time in unix timestamp for a pod container. # HELP kube_pod_container_status_last_terminated_exitcode Describes the exit code for the last container in terminated state. # HELP kube_pod_container_status_last_terminated_reason Describes the last reason the container was in terminated state. From 6d2a555bbc9819c69fc30b9e4f34189d3e1af46a Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Thu, 3 Nov 2022 23:07:09 +0530 Subject: [PATCH 17/70] Allow `labelFromKey` field Allow `labelFromKey` field for the following types: * Gauge: Done. * Info: Done. * StateSet: N/A (redundant use case, see doc changes for more info). Signed-off-by: Pranshu Srivastava --- docs/customresourcestate-metrics.md | 1 + .../config_metrics_types.go | 2 + pkg/customresourcestate/registry_factory.go | 81 ++++++++++++------- .../registry_factory_test.go | 17 +++- 4 files changed, 67 insertions(+), 34 deletions(-) diff --git a/docs/customresourcestate-metrics.md b/docs/customresourcestate-metrics.md index 4e0f5e5e25..5296091ebc 100644 --- a/docs/customresourcestate-metrics.md +++ b/docs/customresourcestate-metrics.md @@ -146,6 +146,7 @@ spec: path: [status, sub] # if path targets an object, the object key will be used as label value + # This is not supported for StateSet type as all values will be truthy, which is redundant. labelFromKey: type # label values can be resolved specific to this path labelsFromPath: diff --git a/pkg/customresourcestate/config_metrics_types.go b/pkg/customresourcestate/config_metrics_types.go index 110c4f9934..6e8e9167cd 100644 --- a/pkg/customresourcestate/config_metrics_types.go +++ b/pkg/customresourcestate/config_metrics_types.go @@ -51,6 +51,8 @@ type MetricGauge struct { // Ref: https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#info type MetricInfo struct { MetricMeta `yaml:",inline" json:",inline"` + // LabelFromKey adds a label with the given name if Path is an object. The label value will be the object key. + LabelFromKey string `yaml:"labelFromKey" json:"labelFromKey"` } // MetricStateSet is a metric which represent a series of related boolean values, also called a bitset. diff --git a/pkg/customresourcestate/registry_factory.go b/pkg/customresourcestate/registry_factory.go index 5c78294bd9..3cc575504d 100644 --- a/pkg/customresourcestate/registry_factory.go +++ b/pkg/customresourcestate/registry_factory.go @@ -157,6 +157,7 @@ func newCompiledMetric(m Metric) (compiledMetric, error) { compiledCommon: *cc, ValueFrom: valueFromPath, NilIsZero: m.Gauge.NilIsZero, + labelFromKey: m.Gauge.LabelFromKey, }, nil case MetricTypeInfo: if m.Info == nil { @@ -168,6 +169,7 @@ func newCompiledMetric(m Metric) (compiledMetric, error) { } return &compiledInfo{ compiledCommon: *cc, + labelFromKey: m.Info.LabelFromKey, }, nil case MetricTypeStateSet: if m.StateSet == nil { @@ -195,23 +197,8 @@ func newCompiledMetric(m Metric) (compiledMetric, error) { type compiledGauge struct { compiledCommon ValueFrom valuePath - LabelFromKey string NilIsZero bool -} - -func newCompiledGauge(m *MetricGauge) (*compiledGauge, error) { - cc, err := compileCommon(m.MetricMeta) - if err != nil { - return nil, fmt.Errorf("compile common: %w", err) - } - valueFromPath, err := compilePath(m.ValueFrom) - if err != nil { - return nil, fmt.Errorf("compile path ValueFrom: %w", err) - } - return &compiledGauge{ - compiledCommon: *cc, - ValueFrom: valueFromPath, - }, nil + labelFromKey string } func (c *compiledGauge) Values(v interface{}) (result []eachValue, errs []error) { @@ -227,8 +214,8 @@ func (c *compiledGauge) Values(v interface{}) (result []eachValue, errs []error) onError(fmt.Errorf("[%s]: %w", key, err)) continue } - if key != "" && c.LabelFromKey != "" { - ev.Labels[c.LabelFromKey] = key + if key != "" && c.labelFromKey != "" { + ev.Labels[c.labelFromKey] = key } addPathLabels(it, c.LabelFromPath(), ev.Labels) result = append(result, *ev) @@ -257,22 +244,54 @@ func (c *compiledGauge) Values(v interface{}) (result []eachValue, errs []error) type compiledInfo struct { compiledCommon + labelFromKey string } func (c *compiledInfo) Values(v interface{}) (result []eachValue, errs []error) { - if vs, isArray := v.([]interface{}); isArray { - for _, obj := range vs { + onError := func(err ...error) { + errs = append(errs, fmt.Errorf("%s: %v", c.Path(), err)) + } + + switch iter := v.(type) { + case []interface{}: + for _, obj := range iter { ev, err := c.values(obj) if len(err) > 0 { - errs = append(errs, err...) + onError(err...) continue } result = append(result, ev...) } - return + default: + value, err := c.values(v) + if err != nil { + onError(err...) + break + } + // labelFromKey logic + if vv, ok := v.(map[string]interface{}); ok { + for key, val := range vv { + if key != "" && c.labelFromKey != "" { + n, err := toFloat64(val, false) + if err != nil { + onError(err) + continue + } + result = append(result, eachValue{ + Labels: map[string]string{ + c.labelFromKey: key, + }, + Value: n, + }) + } + } + } + if len(result) == 0 { + result = value + } } - return c.values(v) + return } func (c *compiledInfo) values(v interface{}) (result []eachValue, err []error) { @@ -355,7 +374,7 @@ func less(a, b map[string]string) bool { func (c compiledGauge) value(it interface{}) (*eachValue, error) { labels := make(map[string]string) - value, err := getNum(c.ValueFrom.Get(it), c.NilIsZero) + value, err := toFloat64(c.ValueFrom.Get(it), c.NilIsZero) if err != nil { return nil, fmt.Errorf("%s: %w", c.ValueFrom, err) } @@ -478,7 +497,7 @@ func compilePath(path []string) (out valuePath, _ error) { return nil, fmt.Errorf("invalid list lookup: %s", part) } key, val := eq[0], eq[1] - num, notNum := getNum(val, false) + num, notNum := toFloat64(val, false) boolVal, notBool := strconv.ParseBool(val) out = append(out, pathOp{ part: part, @@ -496,7 +515,7 @@ func compilePath(path []string) (out valuePath, _ error) { } if notNum == nil { - if i, err := getNum(candidate, false); err == nil && num == i { + if i, err := toFloat64(candidate, false); err == nil && num == i { return m } } @@ -522,13 +541,14 @@ func compilePath(path []string) (out valuePath, _ error) { } else if s, ok := m.([]interface{}); ok { i, err := strconv.Atoi(part) if err != nil { - return nil + return fmt.Errorf("invalid list index: %s", part) } if i < 0 { + // negative index i += len(s) } if !(0 <= i && i < len(s)) { - return nil + return fmt.Errorf("list index out of range: %s", part) } return s[i] } @@ -544,6 +564,7 @@ func famGen(f compiledFamily) generator.FamilyGenerator { errLog := klog.V(f.ErrorLogV) return generator.FamilyGenerator{ Name: f.Name, + // TODO(@rexagod): This should be dynamic. Type: metric.Gauge, Help: f.Help, GenerateFunc: func(obj interface{}) *metric.Family { @@ -585,8 +606,8 @@ func scrapeValuesFor(e compiledEach, obj map[string]interface{}) ([]eachValue, [ return result, errs } -// getNum converts the value to a float64 which is the value type for any metric. -func getNum(value interface{}, nilIsZero bool) (float64, error) { +// toFloat64 converts the value to a float64 which is the value type for any metric. +func toFloat64(value interface{}, nilIsZero bool) (float64, error) { var v float64 // same as bool==false but for bool pointers if value == nil { diff --git a/pkg/customresourcestate/registry_factory_test.go b/pkg/customresourcestate/registry_factory_test.go index 1c05cd55ce..df41129db4 100644 --- a/pkg/customresourcestate/registry_factory_test.go +++ b/pkg/customresourcestate/registry_factory_test.go @@ -155,7 +155,7 @@ func Test_values(t *testing.T) { compiledCommon: compiledCommon{ path: mustCompilePath(t, "status", "active"), }, - LabelFromKey: "type", + labelFromKey: "type", }, wantResult: []eachValue{ newEachValue(t, 1, "type", "type-a"), newEachValue(t, 3, "type", "type-b"), @@ -167,7 +167,7 @@ func Test_values(t *testing.T) { "active": mustCompilePath(t, "active"), }, }, - LabelFromKey: "type", + labelFromKey: "type", ValueFrom: mustCompilePath(t, "ready"), }, wantResult: []eachValue{ newEachValue(t, 2, "type", "type-a", "active", "1"), @@ -201,7 +201,7 @@ func Test_values(t *testing.T) { newEachValue(t, 0), }}, {name: "info", each: &compiledInfo{ - compiledCommon{ + compiledCommon: compiledCommon{ labelFromPath: map[string]valuePath{ "version": mustCompilePath(t, "spec", "version"), }, @@ -210,10 +210,19 @@ func Test_values(t *testing.T) { newEachValue(t, 1, "version", "v0.0.0"), }}, {name: "info nil path", each: &compiledInfo{ - compiledCommon{ + compiledCommon: compiledCommon{ path: mustCompilePath(t, "does", "not", "exist"), }, }, wantResult: nil}, + {name: "info label from key", each: &compiledInfo{ + compiledCommon: compiledCommon{ + path: mustCompilePath(t, "status", "active"), + }, + labelFromKey: "type", + }, wantResult: []eachValue{ + newEachValue(t, 1, "type", "type-a"), + newEachValue(t, 3, "type", "type-b"), + }}, {name: "stateset", each: &compiledStateSet{ compiledCommon: compiledCommon{ path: mustCompilePath(t, "status", "phase"), From a5242f4ddbf72e5ad60cf80d80e860ed0f082e39 Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Fri, 4 Nov 2022 17:49:00 +0530 Subject: [PATCH 18/70] Address vulns reported by the security checks As of this moment, there are 2 vulns in the codebase. * GO-2022-1095: os/exec@go1.19.2 * GO-2022-1095: syscall@go1.19.2 This commit aims to fix that. Signed-off-by: Pranshu Srivastava From 2c0c8d2e51b9bbb1e8255c092e1f9714d46d02aa Mon Sep 17 00:00:00 2001 From: Catherine Fang Date: Fri, 14 Oct 2022 08:15:33 -0400 Subject: [PATCH 19/70] Sharding per node --- docs/cli-arguments.md | 1 + internal/store/builder.go | 40 +++++++++++++++-- pkg/app/server.go | 2 + pkg/options/options.go | 2 + pkg/options/types.go | 30 +++++++++++++ pkg/options/types_test.go | 94 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 165 insertions(+), 4 deletions(-) diff --git a/docs/cli-arguments.md b/docs/cli-arguments.md index 7f7ee451ab..c38a2b591b 100644 --- a/docs/cli-arguments.md +++ b/docs/cli-arguments.md @@ -46,6 +46,7 @@ Usage of ./kube-state-metrics: --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. + --nodename string Set spec.nodeName=nodeName when watching resources. Only available for resources which support nodeName filter. --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true) --pod string Name of the pod that contains the kube-state-metrics container. When set, it is expected that --pod and --pod-namespace are both set. Most likely this should be passed via the downward API. This is used for auto-detecting sharding. If set, this has preference over statically configured sharding. This is experimental, it may be removed without notice. --pod-namespace string Name of the namespace of the pod specified by --pod. When set, it is expected that --pod and --pod-namespace are both set. Most likely this should be passed via the downward API. This is used for auto-detecting sharding. If set, this has preference over statically configured sharding. This is experimental, it may be removed without notice. diff --git a/internal/store/builder.go b/internal/store/builder.go index c47701efcc..92801378c2 100644 --- a/internal/store/builder.go +++ b/internal/store/builder.go @@ -63,6 +63,7 @@ type Builder struct { vpaClient vpaclientset.Interface namespaces options.NamespaceList namespaceFilter string + nodenameFilter string ctx context.Context enabledResources []string familyGeneratorFilter generator.FamilyGeneratorFilter @@ -112,6 +113,16 @@ func (b *Builder) WithNamespaces(n options.NamespaceList, nsFilter string) { b.namespaceFilter = nsFilter } +// WithNodename sets the nodename property of a Builder. +func (b *Builder) WithNodename(nodenameFilter string) { + b.nodenameFilter = nodenameFilter +} + +// MergeFieldSelector merges two fieldSelectors using AND operator. +func (b *Builder) MergeFieldSelector(s1 string, s2 string) (string, error) { + return options.MergeFieldSelector(s1, s2) +} + // WithSharding sets the shard and totalShards property of a Builder. func (b *Builder) WithSharding(shard int32, totalShards int) { b.shard = shard @@ -467,7 +478,13 @@ func (b *Builder) buildStores( familyHeaders, composedMetricGenFuncs, ) - listWatcher := listWatchFunc(b.kubeClient, v1.NamespaceAll, b.namespaceFilter) + merged, err := b.MergeFieldSelector(b.namespaceFilter, b.nodenameFilter) + if err != nil { + panic(fmt.Sprintf("Failed to merge fieldSelector %s and %s", b.namespaceFilter, b.nodenameFilter)) + } + klog.Infof("FieldSelector is used ", merged) + listWatcher := listWatchFunc(b.kubeClient, v1.NamespaceAll, merged) + b.startReflector(expectedType, store, listWatcher, useAPIServerCache) b.startReflector(expectedType, store, listWatcher, useAPIServerCache) return []cache.Store{store} } @@ -478,7 +495,12 @@ func (b *Builder) buildStores( familyHeaders, composedMetricGenFuncs, ) - listWatcher := listWatchFunc(b.kubeClient, ns, b.namespaceFilter) + merged, err := b.MergeFieldSelector(b.namespaceFilter, b.nodenameFilter) + if err != nil { + panic(fmt.Sprintf("Failed to merge fieldSelector %s and %s", b.namespaceFilter, b.nodenameFilter)) + } + klog.Infof("FieldSelector is used ", merged) + listWatcher := listWatchFunc(b.kubeClient, ns, merged) b.startReflector(expectedType, store, listWatcher, useAPIServerCache) stores = append(stores, store) } @@ -508,7 +530,12 @@ func (b *Builder) buildCustomResourceStores(resourceName string, familyHeaders, composedMetricGenFuncs, ) - listWatcher := listWatchFunc(customResourceClient, v1.NamespaceAll, b.namespaceFilter) + merged, err := b.MergeFieldSelector(b.namespaceFilter, b.nodenameFilter) + if err != nil { + panic(fmt.Sprintf("Failed to merge fieldSelector %s and %s", b.namespaceFilter, b.nodenameFilter)) + } + klog.Infof("FieldSelector is used ", merged) + listWatcher := listWatchFunc(customResourceClient, v1.NamespaceAll, merged) b.startReflector(expectedType, store, listWatcher, useAPIServerCache) return []cache.Store{store} } @@ -519,7 +546,12 @@ func (b *Builder) buildCustomResourceStores(resourceName string, familyHeaders, composedMetricGenFuncs, ) - listWatcher := listWatchFunc(customResourceClient, ns, b.namespaceFilter) + merged, err := b.MergeFieldSelector(b.namespaceFilter, b.nodenameFilter) + if err != nil { + panic(fmt.Sprintf("Failed to merge fieldSelector %s and %s", b.namespaceFilter, b.nodenameFilter)) + } + klog.Infof("FieldSelector is used ", merged) + listWatcher := listWatchFunc(customResourceClient, ns, merged) b.startReflector(expectedType, store, listWatcher, useAPIServerCache) stores = append(stores, store) } diff --git a/pkg/app/server.go b/pkg/app/server.go index 1dff1a0cd9..16937794da 100644 --- a/pkg/app/server.go +++ b/pkg/app/server.go @@ -108,6 +108,8 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options, factories . nsFieldSelector := namespaces.GetExcludeNSFieldSelector(opts.NamespacesDenylist) storeBuilder.WithNamespaces(namespaces, nsFieldSelector) + storeBuilder.WithNodename(opts.Nodename.GetNodenameFieldSelector()) + allowDenyList, err := allowdenylist.New(opts.MetricAllowlist, opts.MetricDenylist) if err != nil { return err diff --git a/pkg/options/options.go b/pkg/options/options.go index 3bd07e9ab8..b771381411 100644 --- a/pkg/options/options.go +++ b/pkg/options/options.go @@ -39,6 +39,7 @@ type Options struct { Resources ResourceSet Namespaces NamespaceList NamespacesDenylist NamespaceList + Nodename NodenameType Shard int32 TotalShards int Pod string @@ -103,6 +104,7 @@ func (o *Options) AddFlags() { o.flags.Var(&o.Resources, "resources", fmt.Sprintf("Comma-separated list of Resources to be enabled. Defaults to %q", &DefaultResources)) o.flags.Var(&o.Namespaces, "namespaces", fmt.Sprintf("Comma-separated list of namespaces to be enabled. Defaults to %q", &DefaultNamespaces)) o.flags.Var(&o.NamespacesDenylist, "namespaces-denylist", "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.") + o.flags.StringVar((*string)(&o.Nodename), "nodename", "", "Set spec.nodeName=nodeName when watching resources. Only available for resources which support nodeName filter.") o.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.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.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") diff --git a/pkg/options/types.go b/pkg/options/types.go index 4043f6d5b5..39b2ce93e5 100644 --- a/pkg/options/types.go +++ b/pkg/options/types.go @@ -104,6 +104,36 @@ func (r *ResourceSet) Type() string { return "string" } +// NodenameType represents a nodeName to query from. +type NodenameType string + +// GetNodenameFieldSelector returns a nodename field selector. +func (n *NodenameType) GetNodenameFieldSelector() string { + if string(*n) != "" { + return fields.OneTermEqualSelector("spec.nodeName", string(*n)).String() + } + return fields.Nothing().String() +} + +// MergeFieldSelector returns AND of two field selectors. +func MergeFieldSelector(s1 string, s2 string) (string, error) { + selector1, err := fields.ParseSelector(s1) + if err != nil { + return fields.Nothing().String(), err + } + selector2, err := fields.ParseSelector(s2) + if err != nil { + return fields.Nothing().String(), err + } + if selector1.Empty() { + return selector2.String(), nil + } + if selector2.Empty() { + return selector1.String(), nil + } + return fields.AndSelectors(selector1, selector2).String(), nil +} + // NamespaceList represents a list of namespaces to query from. type NamespaceList []string diff --git a/pkg/options/types_test.go b/pkg/options/types_test.go index fb75abd7dd..fb4a88bac3 100644 --- a/pkg/options/types_test.go +++ b/pkg/options/types_test.go @@ -155,6 +155,100 @@ func TestNamespaceList_ExcludeNamespacesFieldSelector(t *testing.T) { } } +func TestNodenameFieldSelector(t *testing.T) { + tests := []struct { + Desc string + Nodename NodenameType + Wanted string + }{ + { + Desc: "empty node name", + Nodename: "", + Wanted: "", + }, + { + Desc: "with node name", + Nodename: "k8s-node-1", + Wanted: "spec.nodeName=k8s-node-1", + }, + } + + for _, test := range tests { + node := test.Nodename + actual := node.GetNodenameFieldSelector() + if !reflect.DeepEqual(actual, test.Wanted) { + t.Errorf("Test error for Desc: %s. Want: %+v. Got: %+v.", test.Desc, test.Wanted, actual) + } + } +} + +func TestMergeFieldSelector(t *testing.T) { + tests := []struct { + Desc string + Namespaces NamespaceList + DeniedNamespaces NamespaceList + Nodename NodenameType + Wanted string + }{ + { + Desc: "empty DeniedNamespaces", + Namespaces: NamespaceList{"default", "kube-system"}, + DeniedNamespaces: NamespaceList{}, + Nodename: "", + Wanted: "", + }, + { + Desc: "all DeniedNamespaces", + Namespaces: DefaultNamespaces, + DeniedNamespaces: NamespaceList{"some-system"}, + Nodename: "", + Wanted: "metadata.namespace!=some-system", + }, + { + Desc: "general case", + Namespaces: DefaultNamespaces, + DeniedNamespaces: NamespaceList{"case1-system", "case2-system"}, + Nodename: "", + Wanted: "metadata.namespace!=case1-system,metadata.namespace!=case2-system", + }, + { + Desc: "empty DeniedNamespaces", + Namespaces: NamespaceList{"default", "kube-system"}, + DeniedNamespaces: NamespaceList{}, + Nodename: "k8s-node-1", + Wanted: "spec.nodeName=k8s-node-1", + }, + { + Desc: "all DeniedNamespaces", + Namespaces: DefaultNamespaces, + DeniedNamespaces: NamespaceList{"some-system"}, + Nodename: "k8s-node-1", + Wanted: "metadata.namespace!=some-system,spec.nodeName=k8s-node-1", + }, + { + Desc: "general case", + Namespaces: DefaultNamespaces, + DeniedNamespaces: NamespaceList{"case1-system", "case2-system"}, + Nodename: "k8s-node-1", + Wanted: "metadata.namespace!=case1-system,metadata.namespace!=case2-system,spec.nodeName=k8s-node-1", + }, + } + + for _, test := range tests { + ns := test.Namespaces + deniedNS := test.DeniedNamespaces + selector1 := ns.GetExcludeNSFieldSelector(deniedNS) + selector2 := test.Nodename.GetNodenameFieldSelector() + actual, err := MergeFieldSelector(selector1, selector2) + if err != nil { + t.Errorf("Test error for Desc: %s. Can't merge field selector %v.", test.Desc, err) + } + if !reflect.DeepEqual(actual, test.Wanted) { + t.Errorf("Test error for Desc: %s. Want: %+v. Got: %+v.", test.Desc, test.Wanted, actual) + } + } +} + func TestMetricSetSet(t *testing.T) { tests := []struct { Desc string From 3b50fbcd16ffa0056b43af8485477e8fac267a6c Mon Sep 17 00:00:00 2001 From: Catherine Fang Date: Mon, 24 Oct 2022 22:39:17 -0400 Subject: [PATCH 20/70] Validate options --- main.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/main.go b/main.go index 4bf0d3fb1f..a191fc3f37 100644 --- a/main.go +++ b/main.go @@ -34,6 +34,19 @@ import ( "k8s.io/kube-state-metrics/v2/pkg/options" ) +func validate(opts *options.Options) error { + shardableResource := "pods" + if opts.Nodename == "" { + return nil + } + for _, x := range opts.Resources.AsSlice() { + if x != shardableResource { + return fmt.Errorf("Resource %s can't be sharding by field selector nodeName", x) + } + } + return nil +} + func main() { opts := options.NewOptions() opts.AddFlags() @@ -53,6 +66,11 @@ func main() { os.Exit(0) } + if err := validate(opts); err != nil { + klog.ErrorS(err, "Validating options error") + klog.FlushAndExit(klog.ExitFlushTimeout, 1) + } + var factories []customresource.RegistryFactory if config, set := resolveCustomResourceConfig(opts); set { crf, err := customresourcestate.FromConfig(config) From 87a7793c7f37412077246dbdda793070712cf2af Mon Sep 17 00:00:00 2001 From: Catherine Fang Date: Wed, 26 Oct 2022 14:42:37 -0400 Subject: [PATCH 21/70] Clean --- docs/cli-arguments.md | 2 +- internal/store/builder.go | 25 ++++++++++++------------- main.go | 2 +- pkg/app/server.go | 3 +-- pkg/options/options.go | 4 ++-- pkg/options/types.go | 8 ++++---- pkg/options/types_test.go | 28 ++++++++++++++-------------- 7 files changed, 35 insertions(+), 37 deletions(-) diff --git a/docs/cli-arguments.md b/docs/cli-arguments.md index c38a2b591b..adbe0954ca 100644 --- a/docs/cli-arguments.md +++ b/docs/cli-arguments.md @@ -46,7 +46,7 @@ Usage of ./kube-state-metrics: --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. - --nodename string Set spec.nodeName=nodeName when watching resources. Only available for resources which support nodeName filter. + --nodename string Set spec.nodeName=nodename when watching resources. Only available for resources which support nodeName filter. --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true) --pod string Name of the pod that contains the kube-state-metrics container. When set, it is expected that --pod and --pod-namespace are both set. Most likely this should be passed via the downward API. This is used for auto-detecting sharding. If set, this has preference over statically configured sharding. This is experimental, it may be removed without notice. --pod-namespace string Name of the namespace of the pod specified by --pod. When set, it is expected that --pod and --pod-namespace are both set. Most likely this should be passed via the downward API. This is used for auto-detecting sharding. If set, this has preference over statically configured sharding. This is experimental, it may be removed without notice. diff --git a/internal/store/builder.go b/internal/store/builder.go index 92801378c2..dec2ec502b 100644 --- a/internal/store/builder.go +++ b/internal/store/builder.go @@ -63,7 +63,7 @@ type Builder struct { vpaClient vpaclientset.Interface namespaces options.NamespaceList namespaceFilter string - nodenameFilter string + nodeNameFilter string ctx context.Context enabledResources []string familyGeneratorFilter generator.FamilyGeneratorFilter @@ -113,9 +113,9 @@ func (b *Builder) WithNamespaces(n options.NamespaceList, nsFilter string) { b.namespaceFilter = nsFilter } -// WithNodename sets the nodename property of a Builder. -func (b *Builder) WithNodename(nodenameFilter string) { - b.nodenameFilter = nodenameFilter +// WithNodeName sets the nodename property of a Builder. +func (b *Builder) WithNodeName(nodeNameFilter string) { + b.nodeNameFilter = nodeNameFilter } // MergeFieldSelector merges two fieldSelectors using AND operator. @@ -478,14 +478,13 @@ func (b *Builder) buildStores( familyHeaders, composedMetricGenFuncs, ) - merged, err := b.MergeFieldSelector(b.namespaceFilter, b.nodenameFilter) + merged, err := b.MergeFieldSelector(b.namespaceFilter, b.nodeNameFilter) if err != nil { - panic(fmt.Sprintf("Failed to merge fieldSelector %s and %s", b.namespaceFilter, b.nodenameFilter)) + panic(fmt.Sprintf("Failed to merge fieldSelector %s and %s", b.namespaceFilter, b.nodeNameFilter)) } klog.Infof("FieldSelector is used ", merged) listWatcher := listWatchFunc(b.kubeClient, v1.NamespaceAll, merged) b.startReflector(expectedType, store, listWatcher, useAPIServerCache) - b.startReflector(expectedType, store, listWatcher, useAPIServerCache) return []cache.Store{store} } @@ -495,9 +494,9 @@ func (b *Builder) buildStores( familyHeaders, composedMetricGenFuncs, ) - merged, err := b.MergeFieldSelector(b.namespaceFilter, b.nodenameFilter) + merged, err := b.MergeFieldSelector(b.namespaceFilter, b.nodeNameFilter) if err != nil { - panic(fmt.Sprintf("Failed to merge fieldSelector %s and %s", b.namespaceFilter, b.nodenameFilter)) + panic(fmt.Sprintf("Failed to merge fieldSelector %s and %s", b.namespaceFilter, b.nodeNameFilter)) } klog.Infof("FieldSelector is used ", merged) listWatcher := listWatchFunc(b.kubeClient, ns, merged) @@ -530,9 +529,9 @@ func (b *Builder) buildCustomResourceStores(resourceName string, familyHeaders, composedMetricGenFuncs, ) - merged, err := b.MergeFieldSelector(b.namespaceFilter, b.nodenameFilter) + merged, err := b.MergeFieldSelector(b.namespaceFilter, b.nodeNameFilter) if err != nil { - panic(fmt.Sprintf("Failed to merge fieldSelector %s and %s", b.namespaceFilter, b.nodenameFilter)) + panic(fmt.Sprintf("Failed to merge fieldSelector %s and %s", b.namespaceFilter, b.nodeNameFilter)) } klog.Infof("FieldSelector is used ", merged) listWatcher := listWatchFunc(customResourceClient, v1.NamespaceAll, merged) @@ -546,9 +545,9 @@ func (b *Builder) buildCustomResourceStores(resourceName string, familyHeaders, composedMetricGenFuncs, ) - merged, err := b.MergeFieldSelector(b.namespaceFilter, b.nodenameFilter) + merged, err := b.MergeFieldSelector(b.namespaceFilter, b.nodeNameFilter) if err != nil { - panic(fmt.Sprintf("Failed to merge fieldSelector %s and %s", b.namespaceFilter, b.nodenameFilter)) + panic(fmt.Sprintf("Failed to merge fieldSelector %s and %s", b.namespaceFilter, b.nodeNameFilter)) } klog.Infof("FieldSelector is used ", merged) listWatcher := listWatchFunc(customResourceClient, ns, merged) diff --git a/main.go b/main.go index a191fc3f37..4afdd2c674 100644 --- a/main.go +++ b/main.go @@ -36,7 +36,7 @@ import ( func validate(opts *options.Options) error { shardableResource := "pods" - if opts.Nodename == "" { + if opts.NodeName == "" { return nil } for _, x := range opts.Resources.AsSlice() { diff --git a/pkg/app/server.go b/pkg/app/server.go index 16937794da..e6424282f5 100644 --- a/pkg/app/server.go +++ b/pkg/app/server.go @@ -107,8 +107,7 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options, factories . namespaces := opts.Namespaces.GetNamespaces() nsFieldSelector := namespaces.GetExcludeNSFieldSelector(opts.NamespacesDenylist) storeBuilder.WithNamespaces(namespaces, nsFieldSelector) - - storeBuilder.WithNodename(opts.Nodename.GetNodenameFieldSelector()) + storeBuilder.WithNodeName(opts.NodeName.GetNodeNameFieldSelector()) allowDenyList, err := allowdenylist.New(opts.MetricAllowlist, opts.MetricDenylist) if err != nil { diff --git a/pkg/options/options.go b/pkg/options/options.go index b771381411..845c576225 100644 --- a/pkg/options/options.go +++ b/pkg/options/options.go @@ -39,7 +39,7 @@ type Options struct { Resources ResourceSet Namespaces NamespaceList NamespacesDenylist NamespaceList - Nodename NodenameType + NodeName NodeNameType Shard int32 TotalShards int Pod string @@ -104,7 +104,7 @@ func (o *Options) AddFlags() { o.flags.Var(&o.Resources, "resources", fmt.Sprintf("Comma-separated list of Resources to be enabled. Defaults to %q", &DefaultResources)) o.flags.Var(&o.Namespaces, "namespaces", fmt.Sprintf("Comma-separated list of namespaces to be enabled. Defaults to %q", &DefaultNamespaces)) o.flags.Var(&o.NamespacesDenylist, "namespaces-denylist", "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.") - o.flags.StringVar((*string)(&o.Nodename), "nodename", "", "Set spec.nodeName=nodeName when watching resources. Only available for resources which support nodeName filter.") + o.flags.StringVar((*string)(&o.NodeName), "nodename", "", "Set spec.nodeName=nodename when watching resources. Only available for resources which support nodeName filter.") o.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.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.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") diff --git a/pkg/options/types.go b/pkg/options/types.go index 39b2ce93e5..8ace382472 100644 --- a/pkg/options/types.go +++ b/pkg/options/types.go @@ -104,11 +104,11 @@ func (r *ResourceSet) Type() string { return "string" } -// NodenameType represents a nodeName to query from. -type NodenameType string +// NodeNameType represents a nodeName to query from. +type NodeNameType string -// GetNodenameFieldSelector returns a nodename field selector. -func (n *NodenameType) GetNodenameFieldSelector() string { +// GetNodeNameFieldSelector returns a nodename field selector. +func (n *NodeNameType) GetNodeNameFieldSelector() string { if string(*n) != "" { return fields.OneTermEqualSelector("spec.nodeName", string(*n)).String() } diff --git a/pkg/options/types_test.go b/pkg/options/types_test.go index fb4a88bac3..adaa802624 100644 --- a/pkg/options/types_test.go +++ b/pkg/options/types_test.go @@ -155,27 +155,27 @@ func TestNamespaceList_ExcludeNamespacesFieldSelector(t *testing.T) { } } -func TestNodenameFieldSelector(t *testing.T) { +func TestNodeNameFieldSelector(t *testing.T) { tests := []struct { Desc string - Nodename NodenameType + NodeName NodeNameType Wanted string }{ { Desc: "empty node name", - Nodename: "", + NodeName: "", Wanted: "", }, { Desc: "with node name", - Nodename: "k8s-node-1", + NodeName: "k8s-node-1", Wanted: "spec.nodeName=k8s-node-1", }, } for _, test := range tests { - node := test.Nodename - actual := node.GetNodenameFieldSelector() + node := test.NodeName + actual := node.GetNodeNameFieldSelector() if !reflect.DeepEqual(actual, test.Wanted) { t.Errorf("Test error for Desc: %s. Want: %+v. Got: %+v.", test.Desc, test.Wanted, actual) } @@ -187,49 +187,49 @@ func TestMergeFieldSelector(t *testing.T) { Desc string Namespaces NamespaceList DeniedNamespaces NamespaceList - Nodename NodenameType + NodeName NodeNameType Wanted string }{ { Desc: "empty DeniedNamespaces", Namespaces: NamespaceList{"default", "kube-system"}, DeniedNamespaces: NamespaceList{}, - Nodename: "", + NodeName: "", Wanted: "", }, { Desc: "all DeniedNamespaces", Namespaces: DefaultNamespaces, DeniedNamespaces: NamespaceList{"some-system"}, - Nodename: "", + NodeName: "", Wanted: "metadata.namespace!=some-system", }, { Desc: "general case", Namespaces: DefaultNamespaces, DeniedNamespaces: NamespaceList{"case1-system", "case2-system"}, - Nodename: "", + NodeName: "", Wanted: "metadata.namespace!=case1-system,metadata.namespace!=case2-system", }, { Desc: "empty DeniedNamespaces", Namespaces: NamespaceList{"default", "kube-system"}, DeniedNamespaces: NamespaceList{}, - Nodename: "k8s-node-1", + NodeName: "k8s-node-1", Wanted: "spec.nodeName=k8s-node-1", }, { Desc: "all DeniedNamespaces", Namespaces: DefaultNamespaces, DeniedNamespaces: NamespaceList{"some-system"}, - Nodename: "k8s-node-1", + NodeName: "k8s-node-1", Wanted: "metadata.namespace!=some-system,spec.nodeName=k8s-node-1", }, { Desc: "general case", Namespaces: DefaultNamespaces, DeniedNamespaces: NamespaceList{"case1-system", "case2-system"}, - Nodename: "k8s-node-1", + NodeName: "k8s-node-1", Wanted: "metadata.namespace!=case1-system,metadata.namespace!=case2-system,spec.nodeName=k8s-node-1", }, } @@ -238,7 +238,7 @@ func TestMergeFieldSelector(t *testing.T) { ns := test.Namespaces deniedNS := test.DeniedNamespaces selector1 := ns.GetExcludeNSFieldSelector(deniedNS) - selector2 := test.Nodename.GetNodenameFieldSelector() + selector2 := test.NodeName.GetNodeNameFieldSelector() actual, err := MergeFieldSelector(selector1, selector2) if err != nil { t.Errorf("Test error for Desc: %s. Can't merge field selector %v.", test.Desc, err) From d523f8e0e45541357153c551053da8fb735a568f Mon Sep 17 00:00:00 2001 From: Catherine Fang Date: Wed, 26 Oct 2022 15:30:54 -0400 Subject: [PATCH 22/70] Move merging fieldselectors into app/server.go and replace namespaceFitler with fieldSelectorFilter --- internal/store/builder.go | 62 +++++++++++++++------------------ pkg/app/server.go | 9 +++-- pkg/app/server_test.go | 12 +++---- pkg/builder/builder.go | 4 +-- pkg/builder/types/interfaces.go | 3 +- pkg/options/types.go | 9 +++-- 6 files changed, 53 insertions(+), 46 deletions(-) diff --git a/internal/store/builder.go b/internal/store/builder.go index dec2ec502b..034c8208bd 100644 --- a/internal/store/builder.go +++ b/internal/store/builder.go @@ -62,8 +62,7 @@ type Builder struct { customResourceClients map[string]interface{} vpaClient vpaclientset.Interface namespaces options.NamespaceList - namespaceFilter string - nodeNameFilter string + fieldSelectorFilter string ctx context.Context enabledResources []string familyGeneratorFilter generator.FamilyGeneratorFilter @@ -107,20 +106,27 @@ func (b *Builder) WithEnabledResources(r []string) error { return nil } -// WithNamespaces sets the namespaces property of a Builder. -func (b *Builder) WithNamespaces(n options.NamespaceList, nsFilter string) { - b.namespaces = n - b.namespaceFilter = nsFilter +// WithFieldSelectorFilter sets the fieldSelector property of a Builder. +func (b *Builder) WithFieldSelectorFilter(fieldSelectorFilter string) { + b.fieldSelectorFilter = fieldSelectorFilter } -// WithNodeName sets the nodename property of a Builder. -func (b *Builder) WithNodeName(nodeNameFilter string) { - b.nodeNameFilter = nodeNameFilter +// WithNamespaces sets the namespaces property of a Builder. +func (b *Builder) WithNamespaces(n options.NamespaceList) { + b.namespaces = n } -// MergeFieldSelector merges two fieldSelectors using AND operator. -func (b *Builder) MergeFieldSelector(s1 string, s2 string) (string, error) { - return options.MergeFieldSelector(s1, s2) +// MergeFieldSelector merges multiple fieldSelectors using AND operator. +func (b *Builder) MergeFieldSelector(selectors []string) (string, error) { + var err error + merged := options.EmptyFieldSelector() + for _, s := range selectors { + merged, err = options.MergeFieldSelector(merged, s) + if err != nil { + return "", err + } + } + return merged, nil } // WithSharding sets the shard and totalShards property of a Builder. @@ -478,12 +484,10 @@ func (b *Builder) buildStores( familyHeaders, composedMetricGenFuncs, ) - merged, err := b.MergeFieldSelector(b.namespaceFilter, b.nodeNameFilter) - if err != nil { - panic(fmt.Sprintf("Failed to merge fieldSelector %s and %s", b.namespaceFilter, b.nodeNameFilter)) + if b.fieldSelectorFilter != "" { + klog.Infof("FieldSelector is used ", b.fieldSelectorFilter) } - klog.Infof("FieldSelector is used ", merged) - listWatcher := listWatchFunc(b.kubeClient, v1.NamespaceAll, merged) + listWatcher := listWatchFunc(b.kubeClient, v1.NamespaceAll, b.fieldSelectorFilter) b.startReflector(expectedType, store, listWatcher, useAPIServerCache) return []cache.Store{store} } @@ -494,12 +498,10 @@ func (b *Builder) buildStores( familyHeaders, composedMetricGenFuncs, ) - merged, err := b.MergeFieldSelector(b.namespaceFilter, b.nodeNameFilter) - if err != nil { - panic(fmt.Sprintf("Failed to merge fieldSelector %s and %s", b.namespaceFilter, b.nodeNameFilter)) + if b.fieldSelectorFilter != "" { + klog.Infof("FieldSelector is used ", b.fieldSelectorFilter) } - klog.Infof("FieldSelector is used ", merged) - listWatcher := listWatchFunc(b.kubeClient, ns, merged) + listWatcher := listWatchFunc(b.kubeClient, ns, b.fieldSelectorFilter) b.startReflector(expectedType, store, listWatcher, useAPIServerCache) stores = append(stores, store) } @@ -529,12 +531,10 @@ func (b *Builder) buildCustomResourceStores(resourceName string, familyHeaders, composedMetricGenFuncs, ) - merged, err := b.MergeFieldSelector(b.namespaceFilter, b.nodeNameFilter) - if err != nil { - panic(fmt.Sprintf("Failed to merge fieldSelector %s and %s", b.namespaceFilter, b.nodeNameFilter)) + if b.fieldSelectorFilter != "" { + klog.Infof("FieldSelector is used ", b.fieldSelectorFilter) } - klog.Infof("FieldSelector is used ", merged) - listWatcher := listWatchFunc(customResourceClient, v1.NamespaceAll, merged) + listWatcher := listWatchFunc(customResourceClient, v1.NamespaceAll, b.fieldSelectorFilter) b.startReflector(expectedType, store, listWatcher, useAPIServerCache) return []cache.Store{store} } @@ -545,12 +545,8 @@ func (b *Builder) buildCustomResourceStores(resourceName string, familyHeaders, composedMetricGenFuncs, ) - merged, err := b.MergeFieldSelector(b.namespaceFilter, b.nodeNameFilter) - if err != nil { - panic(fmt.Sprintf("Failed to merge fieldSelector %s and %s", b.namespaceFilter, b.nodeNameFilter)) - } - klog.Infof("FieldSelector is used ", merged) - listWatcher := listWatchFunc(customResourceClient, ns, merged) + klog.Infof("FieldSelector is used ", b.fieldSelectorFilter) + listWatcher := listWatchFunc(customResourceClient, ns, b.fieldSelectorFilter) b.startReflector(expectedType, store, listWatcher, useAPIServerCache) stores = append(stores, store) } diff --git a/pkg/app/server.go b/pkg/app/server.go index e6424282f5..d9b2d8a659 100644 --- a/pkg/app/server.go +++ b/pkg/app/server.go @@ -106,8 +106,13 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options, factories . namespaces := opts.Namespaces.GetNamespaces() nsFieldSelector := namespaces.GetExcludeNSFieldSelector(opts.NamespacesDenylist) - storeBuilder.WithNamespaces(namespaces, nsFieldSelector) - storeBuilder.WithNodeName(opts.NodeName.GetNodeNameFieldSelector()) + nodeNameFieldSelector := opts.NodeName.GetNodeNameFieldSelector() + merged, err := storeBuilder.MergeFieldSelector([]string{nsFieldSelector, nodeNameFieldSelector}) + if err != nil { + return err + } + storeBuilder.WithNamespaces(namespaces) + storeBuilder.WithFieldSelectorFilter(merged) allowDenyList, err := allowdenylist.New(opts.MetricAllowlist, opts.MetricDenylist) if err != nil { diff --git a/pkg/app/server_test.go b/pkg/app/server_test.go index afb861c21f..7627f302a6 100644 --- a/pkg/app/server_test.go +++ b/pkg/app/server_test.go @@ -80,7 +80,7 @@ func BenchmarkKubeStateMetrics(b *testing.B) { builder.WithKubeClient(kubeClient) builder.WithSharding(0, 1) builder.WithContext(ctx) - builder.WithNamespaces(options.DefaultNamespaces, "") + builder.WithNamespaces(options.DefaultNamespaces) builder.WithGenerateStoresFunc(builder.DefaultGenerateStoresFunc()) allowDenyListFilter, err := allowdenylist.New(map[string]struct{}{}, map[string]struct{}{}) @@ -155,7 +155,7 @@ func TestFullScrapeCycle(t *testing.T) { t.Fatal(err) } builder.WithKubeClient(kubeClient) - builder.WithNamespaces(options.DefaultNamespaces, "") + builder.WithNamespaces(options.DefaultNamespaces) builder.WithGenerateStoresFunc(builder.DefaultGenerateStoresFunc()) l, err := allowdenylist.New(map[string]struct{}{}, map[string]struct{}{}) @@ -442,7 +442,7 @@ func TestShardingEquivalenceScrapeCycle(t *testing.T) { t.Fatal(err) } unshardedBuilder.WithKubeClient(kubeClient) - unshardedBuilder.WithNamespaces(options.DefaultNamespaces, "") + unshardedBuilder.WithNamespaces(options.DefaultNamespaces) unshardedBuilder.WithFamilyGeneratorFilter(l) unshardedBuilder.WithAllowLabels(map[string][]string{}) unshardedBuilder.WithGenerateStoresFunc(unshardedBuilder.DefaultGenerateStoresFunc()) @@ -458,7 +458,7 @@ func TestShardingEquivalenceScrapeCycle(t *testing.T) { t.Fatal(err) } shardedBuilder1.WithKubeClient(kubeClient) - shardedBuilder1.WithNamespaces(options.DefaultNamespaces, "") + shardedBuilder1.WithNamespaces(options.DefaultNamespaces) shardedBuilder1.WithFamilyGeneratorFilter(l) shardedBuilder1.WithAllowLabels(map[string][]string{}) shardedBuilder1.WithGenerateStoresFunc(shardedBuilder1.DefaultGenerateStoresFunc()) @@ -474,7 +474,7 @@ func TestShardingEquivalenceScrapeCycle(t *testing.T) { t.Fatal(err) } shardedBuilder2.WithKubeClient(kubeClient) - shardedBuilder2.WithNamespaces(options.DefaultNamespaces, "") + shardedBuilder2.WithNamespaces(options.DefaultNamespaces) shardedBuilder2.WithFamilyGeneratorFilter(l) shardedBuilder2.WithAllowLabels(map[string][]string{}) shardedBuilder2.WithGenerateStoresFunc(shardedBuilder2.DefaultGenerateStoresFunc()) @@ -616,7 +616,7 @@ func TestCustomResourceExtension(t *testing.T) { builder.WithKubeClient(kubeClient) builder.WithCustomResourceClients(customResourceClients) - builder.WithNamespaces(options.DefaultNamespaces, "") + builder.WithNamespaces(options.DefaultNamespaces) builder.WithGenerateStoresFunc(builder.DefaultGenerateStoresFunc()) builder.WithGenerateCustomResourceStoresFunc(builder.DefaultGenerateCustomResourceStoresFunc()) diff --git a/pkg/builder/builder.go b/pkg/builder/builder.go index 1e2763c455..f17663336c 100644 --- a/pkg/builder/builder.go +++ b/pkg/builder/builder.go @@ -58,8 +58,8 @@ func (b *Builder) WithEnabledResources(c []string) error { } // WithNamespaces sets the namespaces property of a Builder. -func (b *Builder) WithNamespaces(n options.NamespaceList, nsFilter string) { - b.internal.WithNamespaces(n, nsFilter) +func (b *Builder) WithNamespaces(n options.NamespaceList) { + b.internal.WithNamespaces(n) } // WithSharding sets the shard and totalShards property of a Builder. diff --git a/pkg/builder/types/interfaces.go b/pkg/builder/types/interfaces.go index ea37e941df..e52168235f 100644 --- a/pkg/builder/types/interfaces.go +++ b/pkg/builder/types/interfaces.go @@ -35,7 +35,8 @@ import ( type BuilderInterface interface { WithMetrics(r prometheus.Registerer) WithEnabledResources(c []string) error - WithNamespaces(n options.NamespaceList, nsFilter string) + WithNamespaces(n options.NamespaceList) + WithFieldSelectorFilter(fieldSelectors string) WithSharding(shard int32, totalShards int) WithContext(ctx context.Context) WithKubeClient(c clientset.Interface) diff --git a/pkg/options/types.go b/pkg/options/types.go index 8ace382472..92d188709b 100644 --- a/pkg/options/types.go +++ b/pkg/options/types.go @@ -115,15 +115,20 @@ func (n *NodeNameType) GetNodeNameFieldSelector() string { return fields.Nothing().String() } +// EmptyFieldSelector returns an empty field selector. +func EmptyFieldSelector() string { + return fields.Nothing().String() +} + // MergeFieldSelector returns AND of two field selectors. func MergeFieldSelector(s1 string, s2 string) (string, error) { selector1, err := fields.ParseSelector(s1) if err != nil { - return fields.Nothing().String(), err + return EmptyFieldSelector(), err } selector2, err := fields.ParseSelector(s2) if err != nil { - return fields.Nothing().String(), err + return EmptyFieldSelector(), err } if selector1.Empty() { return selector2.String(), nil From f9d29ba76146108356ba707a28331e062437f818 Mon Sep 17 00:00:00 2001 From: Catherine Fang Date: Thu, 27 Oct 2022 11:35:22 -0400 Subject: [PATCH 23/70] Refactoring --- docs/cli-arguments.md | 2 +- internal/store/builder.go | 31 ++++++++++++------------------- main.go | 15 +-------------- pkg/app/server.go | 2 +- pkg/options/options.go | 16 +++++++++++++++- pkg/options/types.go | 17 +++++++++++++++-- pkg/options/types_test.go | 4 ++-- 7 files changed, 47 insertions(+), 40 deletions(-) diff --git a/docs/cli-arguments.md b/docs/cli-arguments.md index adbe0954ca..ab4a54d13f 100644 --- a/docs/cli-arguments.md +++ b/docs/cli-arguments.md @@ -46,7 +46,7 @@ Usage of ./kube-state-metrics: --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. - --nodename string Set spec.nodeName=nodename when watching resources. Only available for resources which support nodeName filter. + --nodename string Name of the node that contains the kube-state-metrics pod, only available for resources (pod metrics) that support spec.nodeName fieldSelector. Each kube-state-metrics pod will only exposes metrics related to this node. --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true) --pod string Name of the pod that contains the kube-state-metrics container. When set, it is expected that --pod and --pod-namespace are both set. Most likely this should be passed via the downward API. This is used for auto-detecting sharding. If set, this has preference over statically configured sharding. This is experimental, it may be removed without notice. --pod-namespace string Name of the namespace of the pod specified by --pod. When set, it is expected that --pod and --pod-namespace are both set. Most likely this should be passed via the downward API. This is used for auto-detecting sharding. If set, this has preference over statically configured sharding. This is experimental, it may be removed without notice. diff --git a/internal/store/builder.go b/internal/store/builder.go index 034c8208bd..8dfb85342a 100644 --- a/internal/store/builder.go +++ b/internal/store/builder.go @@ -58,10 +58,11 @@ var _ ksmtypes.BuilderInterface = &Builder{} // Builder helps to build store. It follows the builder pattern // (https://en.wikipedia.org/wiki/Builder_pattern). type Builder struct { - kubeClient clientset.Interface - customResourceClients map[string]interface{} - vpaClient vpaclientset.Interface - namespaces options.NamespaceList + kubeClient clientset.Interface + customResourceClients map[string]interface{} + vpaClient vpaclientset.Interface + namespaces options.NamespaceList + // namespaceFilter is inside fieldSelectorFilter fieldSelectorFilter string ctx context.Context enabledResources []string @@ -116,17 +117,9 @@ func (b *Builder) WithNamespaces(n options.NamespaceList) { b.namespaces = n } -// MergeFieldSelector merges multiple fieldSelectors using AND operator. -func (b *Builder) MergeFieldSelector(selectors []string) (string, error) { - var err error - merged := options.EmptyFieldSelector() - for _, s := range selectors { - merged, err = options.MergeFieldSelector(merged, s) - if err != nil { - return "", err - } - } - return merged, nil +// MergeFieldSelectors merges multiple fieldSelectors using AND operator. +func (b *Builder) MergeFieldSelectors(selectors []string) (string, error) { + return options.MergeFieldSelectors(selectors) } // WithSharding sets the shard and totalShards property of a Builder. @@ -485,7 +478,7 @@ func (b *Builder) buildStores( composedMetricGenFuncs, ) if b.fieldSelectorFilter != "" { - klog.Infof("FieldSelector is used ", b.fieldSelectorFilter) + klog.Infof("FieldSelector is used %s", b.fieldSelectorFilter) } listWatcher := listWatchFunc(b.kubeClient, v1.NamespaceAll, b.fieldSelectorFilter) b.startReflector(expectedType, store, listWatcher, useAPIServerCache) @@ -499,7 +492,7 @@ func (b *Builder) buildStores( composedMetricGenFuncs, ) if b.fieldSelectorFilter != "" { - klog.Infof("FieldSelector is used ", b.fieldSelectorFilter) + klog.Infof("FieldSelector is used %s", b.fieldSelectorFilter) } listWatcher := listWatchFunc(b.kubeClient, ns, b.fieldSelectorFilter) b.startReflector(expectedType, store, listWatcher, useAPIServerCache) @@ -532,7 +525,7 @@ func (b *Builder) buildCustomResourceStores(resourceName string, composedMetricGenFuncs, ) if b.fieldSelectorFilter != "" { - klog.Infof("FieldSelector is used ", b.fieldSelectorFilter) + klog.Infof("FieldSelector is used %s", b.fieldSelectorFilter) } listWatcher := listWatchFunc(customResourceClient, v1.NamespaceAll, b.fieldSelectorFilter) b.startReflector(expectedType, store, listWatcher, useAPIServerCache) @@ -545,7 +538,7 @@ func (b *Builder) buildCustomResourceStores(resourceName string, familyHeaders, composedMetricGenFuncs, ) - klog.Infof("FieldSelector is used ", b.fieldSelectorFilter) + klog.Infof("FieldSelector is used %s", b.fieldSelectorFilter) listWatcher := listWatchFunc(customResourceClient, ns, b.fieldSelectorFilter) b.startReflector(expectedType, store, listWatcher, useAPIServerCache) stores = append(stores, store) diff --git a/main.go b/main.go index 4afdd2c674..72c8f090b5 100644 --- a/main.go +++ b/main.go @@ -34,19 +34,6 @@ import ( "k8s.io/kube-state-metrics/v2/pkg/options" ) -func validate(opts *options.Options) error { - shardableResource := "pods" - if opts.NodeName == "" { - return nil - } - for _, x := range opts.Resources.AsSlice() { - if x != shardableResource { - return fmt.Errorf("Resource %s can't be sharding by field selector nodeName", x) - } - } - return nil -} - func main() { opts := options.NewOptions() opts.AddFlags() @@ -66,7 +53,7 @@ func main() { os.Exit(0) } - if err := validate(opts); err != nil { + if err := opts.Validate(); err != nil { klog.ErrorS(err, "Validating options error") klog.FlushAndExit(klog.ExitFlushTimeout, 1) } diff --git a/pkg/app/server.go b/pkg/app/server.go index d9b2d8a659..dbdf835409 100644 --- a/pkg/app/server.go +++ b/pkg/app/server.go @@ -107,7 +107,7 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options, factories . namespaces := opts.Namespaces.GetNamespaces() nsFieldSelector := namespaces.GetExcludeNSFieldSelector(opts.NamespacesDenylist) nodeNameFieldSelector := opts.NodeName.GetNodeNameFieldSelector() - merged, err := storeBuilder.MergeFieldSelector([]string{nsFieldSelector, nodeNameFieldSelector}) + merged, err := storeBuilder.MergeFieldSelectors([]string{nsFieldSelector, nodeNameFieldSelector}) if err != nil { return err } diff --git a/pkg/options/options.go b/pkg/options/options.go index 845c576225..bdcede80c4 100644 --- a/pkg/options/options.go +++ b/pkg/options/options.go @@ -104,7 +104,7 @@ func (o *Options) AddFlags() { o.flags.Var(&o.Resources, "resources", fmt.Sprintf("Comma-separated list of Resources to be enabled. Defaults to %q", &DefaultResources)) o.flags.Var(&o.Namespaces, "namespaces", fmt.Sprintf("Comma-separated list of namespaces to be enabled. Defaults to %q", &DefaultNamespaces)) o.flags.Var(&o.NamespacesDenylist, "namespaces-denylist", "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.") - o.flags.StringVar((*string)(&o.NodeName), "nodename", "", "Set spec.nodeName=nodename when watching resources. Only available for resources which support nodeName filter.") + o.flags.StringVar((*string)(&o.NodeName), "nodename", "", "Name of the node that contains the kube-state-metrics pod, only available for resources (pod metrics) that support spec.nodeName fieldSelector. Each kube-state-metrics pod will only exposes metrics related to this node.") o.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.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.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") @@ -134,3 +134,17 @@ func (o *Options) Parse() error { func (o *Options) Usage() { o.flags.Usage() } + +// Validate validates arguments +func (o *Options) Validate() error { + shardableResource := "pods" + if o.NodeName == "" { + return nil + } + for _, x := range o.Resources.AsSlice() { + if x != shardableResource { + return fmt.Errorf("Resource %s can't be sharding by field selector spec.nodeName", x) + } + } + return nil +} diff --git a/pkg/options/types.go b/pkg/options/types.go index 92d188709b..5759a7741b 100644 --- a/pkg/options/types.go +++ b/pkg/options/types.go @@ -120,8 +120,21 @@ func EmptyFieldSelector() string { return fields.Nothing().String() } -// MergeFieldSelector returns AND of two field selectors. -func MergeFieldSelector(s1 string, s2 string) (string, error) { +// MergeFieldSelectors returns AND of a list of field selectors. +func MergeFieldSelectors(selectors []string) (string, error) { + var err error + merged := EmptyFieldSelector() + for _, s := range selectors { + merged, err = MergeTwoFieldSelectors(merged, s) + if err != nil { + return "", err + } + } + return merged, nil +} + +// MergeTwoFieldSelectors returns AND of two field selectors. +func MergeTwoFieldSelectors(s1 string, s2 string) (string, error) { selector1, err := fields.ParseSelector(s1) if err != nil { return EmptyFieldSelector(), err diff --git a/pkg/options/types_test.go b/pkg/options/types_test.go index adaa802624..8572423978 100644 --- a/pkg/options/types_test.go +++ b/pkg/options/types_test.go @@ -182,7 +182,7 @@ func TestNodeNameFieldSelector(t *testing.T) { } } -func TestMergeFieldSelector(t *testing.T) { +func TestMergeFieldSelectors(t *testing.T) { tests := []struct { Desc string Namespaces NamespaceList @@ -239,7 +239,7 @@ func TestMergeFieldSelector(t *testing.T) { deniedNS := test.DeniedNamespaces selector1 := ns.GetExcludeNSFieldSelector(deniedNS) selector2 := test.NodeName.GetNodeNameFieldSelector() - actual, err := MergeFieldSelector(selector1, selector2) + actual, err := MergeFieldSelectors([]string{selector1, selector2}) if err != nil { t.Errorf("Test error for Desc: %s. Can't merge field selector %v.", test.Desc, err) } From 2f1da3af9b6925bc8f13c823a3365a3167a51391 Mon Sep 17 00:00:00 2001 From: Catherine Fang Date: Mon, 31 Oct 2022 22:22:13 -0400 Subject: [PATCH 24/70] Provide scaling example --- README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/README.md b/README.md index 096c11840c..e75e31059b 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ are deleted they are no longer visible on the `/metrics` endpoint. - [Resource recommendation](#resource-recommendation) - [Horizontal sharding](#horizontal-sharding) - [Automated sharding](#automated-sharding) + - [Daemonset sharding for pod metrics](#daemonset-sharding-pod-metrics) - [Setup](#setup) - [Building the Docker container](#building-the-docker-container) - [Usage](#usage) @@ -235,6 +236,31 @@ This way of deploying shards is useful when you want to manage KSM shards throug The downside of using an auto-sharded setup comes from the rollout strategy supported by `StatefulSet`s. When managed by a `StatefulSet`, pods are replaced one at a time with each pod first getting terminated and then recreated. Besides such rollouts being slower, they will also lead to short downtime for each shard. If a Prometheus scrape happens during a rollout, it can miss some of the metrics exported by kube-state-metrics. +### Daemonset sharding for pod metrics + +For pod metrics, they can be sharded per node with the following flag: +* `--nodename` + +Each kube-state-metrics pod uses FieldSelector (spec.nodeName) to watch/list pod metrics only on the same node. + +A daemonset kube-state-metrics example: +``` +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: kube-state-metrics +spec: + template: + spec: + containers: + - name: kube-state-metrics + args: + - --resources=pods + - --nodename=$(NODE_NAME) +``` + +For other metrics, they can sharded via [Horizontal sharding](#horizontal-sharding). + ### Setup Install this project to your `$GOPATH` using `go get`: From 1736469dd4e771b8b63c7b70d1dc727b5ecf1395 Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Fri, 4 Nov 2022 17:04:32 +0530 Subject: [PATCH 25/70] Add `govulncheck` cron Add `govulncheck` cron configuration. Signed-off-by: Pranshu Srivastava --- .github/workflows/cron.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/cron.yml diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml new file mode 100644 index 0000000000..2af5820abf --- /dev/null +++ b/.github/workflows/cron.yml @@ -0,0 +1,26 @@ +name: cron + +on: + schedule: + # Run every Monday + - cron: '0 0 * * 1' + +env: + GO_VERSION: "^1.19" + +jobs: + ci-security-checks: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + name: Checkout code + - name: Set up Go 1.x + uses: actions/setup-go@v3 + with: + go-version: ${{ env.GO_VERSION }} + - name: Install govulncheck binary + run: | + go install golang.org/x/vuln/cmd/govulncheck@latest + - name: Run security checks + run: | + govulncheck -v ./... From 813496de4faad369ac9e3100c663102e3da3041e Mon Sep 17 00:00:00 2001 From: CatherineF-dev Date: Wed, 2 Nov 2022 08:51:59 -0400 Subject: [PATCH 26/70] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Manuel Rüger --- README.md | 15 ++++++++++----- pkg/options/types.go | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e75e31059b..9207c4d3f7 100644 --- a/README.md +++ b/README.md @@ -247,19 +247,24 @@ A daemonset kube-state-metrics example: ``` apiVersion: apps/v1 kind: DaemonSet -metadata: - name: kube-state-metrics spec: template: spec: containers: - - name: kube-state-metrics + - image: registry.k8s.io/kube-state-metrics/kube-state-metrics:IMAGE_TAG + name: kube-state-metrics args: - - --resources=pods + - --resource=pods - --nodename=$(NODE_NAME) + env: + - name: NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName ``` -For other metrics, they can sharded via [Horizontal sharding](#horizontal-sharding). +Other metrics can be sharded via [Horizontal sharding](#horizontal-sharding). ### Setup diff --git a/pkg/options/types.go b/pkg/options/types.go index 5759a7741b..4e4cd318f3 100644 --- a/pkg/options/types.go +++ b/pkg/options/types.go @@ -112,7 +112,7 @@ func (n *NodeNameType) GetNodeNameFieldSelector() string { if string(*n) != "" { return fields.OneTermEqualSelector("spec.nodeName", string(*n)).String() } - return fields.Nothing().String() + return EmptyFieldSelector() } // EmptyFieldSelector returns an empty field selector. From 43c60732346254bb90ffb5d325024fdac213643b Mon Sep 17 00:00:00 2001 From: Catherine Fang Date: Fri, 4 Nov 2022 13:43:12 -0400 Subject: [PATCH 27/70] Refactoring --- README.md | 4 ++-- docs/cli-arguments.md | 2 +- pkg/app/server.go | 4 ++-- pkg/options/options.go | 9 +++++---- pkg/options/types.go | 8 ++++---- pkg/options/types_test.go | 40 +++++++++++++++++++-------------------- 6 files changed, 34 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 9207c4d3f7..f4991cff27 100644 --- a/README.md +++ b/README.md @@ -239,7 +239,7 @@ The downside of using an auto-sharded setup comes from the rollout strategy supp ### Daemonset sharding for pod metrics For pod metrics, they can be sharded per node with the following flag: -* `--nodename` +* `--node` Each kube-state-metrics pod uses FieldSelector (spec.nodeName) to watch/list pod metrics only on the same node. @@ -255,7 +255,7 @@ spec: name: kube-state-metrics args: - --resource=pods - - --nodename=$(NODE_NAME) + - --node=$(NODE_NAME) env: - name: NODE_NAME valueFrom: diff --git a/docs/cli-arguments.md b/docs/cli-arguments.md index ab4a54d13f..ab31056704 100644 --- a/docs/cli-arguments.md +++ b/docs/cli-arguments.md @@ -46,7 +46,7 @@ Usage of ./kube-state-metrics: --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. - --nodename string Name of the node that contains the kube-state-metrics pod, only available for resources (pod metrics) that support spec.nodeName fieldSelector. Each kube-state-metrics pod will only exposes metrics related to this node. + --node string 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. --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true) --pod string Name of the pod that contains the kube-state-metrics container. When set, it is expected that --pod and --pod-namespace are both set. Most likely this should be passed via the downward API. This is used for auto-detecting sharding. If set, this has preference over statically configured sharding. This is experimental, it may be removed without notice. --pod-namespace string Name of the namespace of the pod specified by --pod. When set, it is expected that --pod and --pod-namespace are both set. Most likely this should be passed via the downward API. This is used for auto-detecting sharding. If set, this has preference over statically configured sharding. This is experimental, it may be removed without notice. diff --git a/pkg/app/server.go b/pkg/app/server.go index dbdf835409..665c7813f6 100644 --- a/pkg/app/server.go +++ b/pkg/app/server.go @@ -106,8 +106,8 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options, factories . namespaces := opts.Namespaces.GetNamespaces() nsFieldSelector := namespaces.GetExcludeNSFieldSelector(opts.NamespacesDenylist) - nodeNameFieldSelector := opts.NodeName.GetNodeNameFieldSelector() - merged, err := storeBuilder.MergeFieldSelectors([]string{nsFieldSelector, nodeNameFieldSelector}) + nodeFieldSelector := opts.Node.GetNodeFieldSelector() + merged, err := storeBuilder.MergeFieldSelectors([]string{nsFieldSelector, nodeFieldSelector}) if err != nil { return err } diff --git a/pkg/options/options.go b/pkg/options/options.go index bdcede80c4..763cfd6d67 100644 --- a/pkg/options/options.go +++ b/pkg/options/options.go @@ -39,7 +39,7 @@ type Options struct { Resources ResourceSet Namespaces NamespaceList NamespacesDenylist NamespaceList - NodeName NodeNameType + Node NodeType Shard int32 TotalShards int Pod string @@ -104,7 +104,6 @@ func (o *Options) AddFlags() { o.flags.Var(&o.Resources, "resources", fmt.Sprintf("Comma-separated list of Resources to be enabled. Defaults to %q", &DefaultResources)) o.flags.Var(&o.Namespaces, "namespaces", fmt.Sprintf("Comma-separated list of namespaces to be enabled. Defaults to %q", &DefaultNamespaces)) o.flags.Var(&o.NamespacesDenylist, "namespaces-denylist", "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.") - o.flags.StringVar((*string)(&o.NodeName), "nodename", "", "Name of the node that contains the kube-state-metrics pod, only available for resources (pod metrics) that support spec.nodeName fieldSelector. Each kube-state-metrics pod will only exposes metrics related to this node.") o.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.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.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") @@ -113,6 +112,8 @@ func (o *Options) AddFlags() { o.flags.Int32Var(&o.Shard, "shard", int32(0), "The instances shard nominal (zero indexed) within the total number of shards. (default 0)") o.flags.IntVar(&o.TotalShards, "total-shards", 1, "The total number of shards. Sharding is disabled when total shards is set to 1.") + o.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.") + autoshardingNotice := "When set, it is expected that --pod and --pod-namespace are both set. Most likely this should be passed via the downward API. This is used for auto-detecting sharding. If set, this has preference over statically configured sharding. This is experimental, it may be removed without notice." o.flags.StringVar(&o.Pod, "pod", "", "Name of the pod that contains the kube-state-metrics container. "+autoshardingNotice) @@ -138,12 +139,12 @@ func (o *Options) Usage() { // Validate validates arguments func (o *Options) Validate() error { shardableResource := "pods" - if o.NodeName == "" { + if o.Node == "" { return nil } for _, x := range o.Resources.AsSlice() { if x != shardableResource { - return fmt.Errorf("Resource %s can't be sharding by field selector spec.nodeName", x) + return fmt.Errorf("Resource %s can't be sharded by field selector spec.nodeName", x) } } return nil diff --git a/pkg/options/types.go b/pkg/options/types.go index 4e4cd318f3..ac0c11275e 100644 --- a/pkg/options/types.go +++ b/pkg/options/types.go @@ -104,11 +104,11 @@ func (r *ResourceSet) Type() string { return "string" } -// NodeNameType represents a nodeName to query from. -type NodeNameType string +// NodeType represents a nodeName to query from. +type NodeType string -// GetNodeNameFieldSelector returns a nodename field selector. -func (n *NodeNameType) GetNodeNameFieldSelector() string { +// GetNodeFieldSelector returns a nodename field selector. +func (n *NodeType) GetNodeFieldSelector() string { if string(*n) != "" { return fields.OneTermEqualSelector("spec.nodeName", string(*n)).String() } diff --git a/pkg/options/types_test.go b/pkg/options/types_test.go index 8572423978..48908b46f7 100644 --- a/pkg/options/types_test.go +++ b/pkg/options/types_test.go @@ -155,27 +155,27 @@ func TestNamespaceList_ExcludeNamespacesFieldSelector(t *testing.T) { } } -func TestNodeNameFieldSelector(t *testing.T) { +func TestNodeFieldSelector(t *testing.T) { tests := []struct { - Desc string - NodeName NodeNameType - Wanted string + Desc string + Node NodeType + Wanted string }{ { - Desc: "empty node name", - NodeName: "", - Wanted: "", + Desc: "empty node name", + Node: "", + Wanted: "", }, { - Desc: "with node name", - NodeName: "k8s-node-1", - Wanted: "spec.nodeName=k8s-node-1", + Desc: "with node name", + Node: "k8s-node-1", + Wanted: "spec.nodeName=k8s-node-1", }, } for _, test := range tests { - node := test.NodeName - actual := node.GetNodeNameFieldSelector() + node := test.Node + actual := node.GetNodeFieldSelector() if !reflect.DeepEqual(actual, test.Wanted) { t.Errorf("Test error for Desc: %s. Want: %+v. Got: %+v.", test.Desc, test.Wanted, actual) } @@ -187,49 +187,49 @@ func TestMergeFieldSelectors(t *testing.T) { Desc string Namespaces NamespaceList DeniedNamespaces NamespaceList - NodeName NodeNameType + Node NodeType Wanted string }{ { Desc: "empty DeniedNamespaces", Namespaces: NamespaceList{"default", "kube-system"}, DeniedNamespaces: NamespaceList{}, - NodeName: "", + Node: "", Wanted: "", }, { Desc: "all DeniedNamespaces", Namespaces: DefaultNamespaces, DeniedNamespaces: NamespaceList{"some-system"}, - NodeName: "", + Node: "", Wanted: "metadata.namespace!=some-system", }, { Desc: "general case", Namespaces: DefaultNamespaces, DeniedNamespaces: NamespaceList{"case1-system", "case2-system"}, - NodeName: "", + Node: "", Wanted: "metadata.namespace!=case1-system,metadata.namespace!=case2-system", }, { Desc: "empty DeniedNamespaces", Namespaces: NamespaceList{"default", "kube-system"}, DeniedNamespaces: NamespaceList{}, - NodeName: "k8s-node-1", + Node: "k8s-node-1", Wanted: "spec.nodeName=k8s-node-1", }, { Desc: "all DeniedNamespaces", Namespaces: DefaultNamespaces, DeniedNamespaces: NamespaceList{"some-system"}, - NodeName: "k8s-node-1", + Node: "k8s-node-1", Wanted: "metadata.namespace!=some-system,spec.nodeName=k8s-node-1", }, { Desc: "general case", Namespaces: DefaultNamespaces, DeniedNamespaces: NamespaceList{"case1-system", "case2-system"}, - NodeName: "k8s-node-1", + Node: "k8s-node-1", Wanted: "metadata.namespace!=case1-system,metadata.namespace!=case2-system,spec.nodeName=k8s-node-1", }, } @@ -238,7 +238,7 @@ func TestMergeFieldSelectors(t *testing.T) { ns := test.Namespaces deniedNS := test.DeniedNamespaces selector1 := ns.GetExcludeNSFieldSelector(deniedNS) - selector2 := test.NodeName.GetNodeNameFieldSelector() + selector2 := test.Node.GetNodeFieldSelector() actual, err := MergeFieldSelectors([]string{selector1, selector2}) if err != nil { t.Errorf("Test error for Desc: %s. Can't merge field selector %v.", test.Desc, err) From 53af11625c14c3e483ebc80278a863d7e8076bd0 Mon Sep 17 00:00:00 2001 From: Mario Constanti Date: Tue, 23 Aug 2022 09:36:34 +0200 Subject: [PATCH 28/70] introduce custom-resources-only flag ... ... to only monitor all known custom-resource configurations instead of listing each of them explicitly Signed-off-by: Mario Constanti --- docs/cli-arguments.md | 1 + pkg/app/server.go | 11 +++++++++-- pkg/options/options.go | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/cli-arguments.md b/docs/cli-arguments.md index 7f7ee451ab..4150ae9ec4 100644 --- a/docs/cli-arguments.md +++ b/docs/cli-arguments.md @@ -30,6 +30,7 @@ Usage of ./kube-state-metrics: --apiserver string The URL of the apiserver to use as a master --custom-resource-state-config string Inline Custom Resource State Metrics config YAML (experimental) --custom-resource-state-config-file string Path to a Custom Resource State Metrics config file (experimental) + --custom-resource-state-only Only provide Custom Resource State metrics (experimental) --enable-gzip-encoding Gzip responses when requested by clients via 'Accept-Encoding: gzip' header. -h, --help Print Help text --host string Host to expose metrics on. (default "::") diff --git a/pkg/app/server.go b/pkg/app/server.go index 1dff1a0cd9..745349a1eb 100644 --- a/pkg/app/server.go +++ b/pkg/app/server.go @@ -88,14 +88,21 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options, factories . storeBuilder.WithMetrics(ksmMetricsRegistry) var resources []string - if len(opts.Resources) == 0 { + switch { + case len(opts.Resources) == 0 && !opts.CustomResourcesOnly: klog.InfoS("Used default resources") resources = options.DefaultResources.AsSlice() // enable custom resource for _, factory := range factories { resources = append(resources, factory.Name()) } - } else { + case opts.CustomResourcesOnly: + // enable custom resource only + for _, factory := range factories { + resources = append(resources, factory.Name()) + } + klog.InfoS("Used CRD resources only", "resources", resources) + default: klog.InfoS("Used resources", "resources", opts.Resources.String()) resources = opts.Resources.AsSlice() } diff --git a/pkg/options/options.go b/pkg/options/options.go index 3bd07e9ab8..6476d10102 100644 --- a/pkg/options/options.go +++ b/pkg/options/options.go @@ -56,6 +56,7 @@ type Options struct { CustomResourceConfig string CustomResourceConfigFile string + CustomResourcesOnly bool flags *pflag.FlagSet } @@ -120,6 +121,7 @@ func (o *Options) AddFlags() { o.flags.StringVar(&o.CustomResourceConfig, "custom-resource-state-config", "", "Inline Custom Resource State Metrics config YAML (experimental)") o.flags.StringVar(&o.CustomResourceConfigFile, "custom-resource-state-config-file", "", "Path to a Custom Resource State Metrics config file (experimental)") + o.flags.BoolVar(&o.CustomResourcesOnly, "custom-resource-state-only", false, "Only provide Custom Resource State metrics (experimental)") } // Parse parses the flag definitions from the argument list. From d982bbc9c910ae60bab59866f3112017d6845434 Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Fri, 2 Sep 2022 03:52:21 +0530 Subject: [PATCH 29/70] Support filtering label allowlist by "*" Support filtering label allowlist by "*", which will expand to the enabled resources, while infering their values based on its value(s). Signed-off-by: Pranshu Srivastava --- docs/cli-arguments.md | 2 +- internal/store/builder.go | 10 ++- internal/store/builder_test.go | 115 +++++++++++++++++++++++++++++++++ pkg/options/options.go | 2 +- pkg/options/types_test.go | 9 +++ 5 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 internal/store/builder_test.go diff --git a/docs/cli-arguments.md b/docs/cli-arguments.md index 7f7ee451ab..d533021bd2 100644 --- a/docs/cli-arguments.md +++ b/docs/cli-arguments.md @@ -42,7 +42,7 @@ Usage of ./kube-state-metrics: --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-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=[*]'). + --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-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. diff --git a/internal/store/builder.go b/internal/store/builder.go index c47701efcc..373c58ff58 100644 --- a/internal/store/builder.go +++ b/internal/store/builder.go @@ -203,11 +203,19 @@ func (b *Builder) WithAllowAnnotations(annotations map[string][]string) { func (b *Builder) WithAllowLabels(labels map[string][]string) error { if len(labels) > 0 { for label := range labels { - if !resourceExists(label) { + if !resourceExists(label) && label != "*" { return fmt.Errorf("resource %s does not exist. Available resources: %s", label, strings.Join(availableResources(), ",")) } } b.allowLabelsList = labels + // "*" takes precedence over other specifications + if allowedLabels, ok := labels["*"]; ok { + m := make(map[string][]string) + for _, resource := range b.enabledResources { + m[resource] = allowedLabels + } + b.allowLabelsList = m + } } return nil } diff --git a/internal/store/builder_test.go b/internal/store/builder_test.go new file mode 100644 index 0000000000..758781d6f7 --- /dev/null +++ b/internal/store/builder_test.go @@ -0,0 +1,115 @@ +/* +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 ( + "reflect" + "testing" + + "k8s.io/kube-state-metrics/v2/pkg/options" +) + +type LabelsAllowList options.LabelsAllowList + +type expectedError struct { + expectedResourceError bool + expectedLabelError bool + expectedNotEqual bool +} + +func TestWithAllowLabels(t *testing.T) { + tests := []struct { + Desc string + LabelsAllowlist map[string][]string + EnabledResources []string + Wanted LabelsAllowList + err expectedError + }{ + { + Desc: "wildcard key-value as the only element", + LabelsAllowlist: map[string][]string{"*": {"*"}}, + EnabledResources: []string{"cronjobs", "pods", "deployments"}, + Wanted: LabelsAllowList(map[string][]string{ + "deployments": {"*"}, + "pods": {"*"}, + "cronjobs": {"*"}, + }), + }, + { + Desc: "wildcard key-value as not the only element", + LabelsAllowlist: map[string][]string{"*": {"*"}, "pods": {"*"}, "cronjobs": {"*"}}, + EnabledResources: []string{"cronjobs", "pods", "deployments"}, + Wanted: LabelsAllowList(map[string][]string{ + "deployments": {"*"}, + "pods": {"*"}, + "cronjobs": {"*"}, + }), + }, + { + Desc: "wildcard key-value as not the only element, with resource mismatch", + LabelsAllowlist: map[string][]string{"*": {"*"}, "pods": {"*"}, "cronjobs": {"*"}, "configmaps": {"*"}}, + EnabledResources: []string{"cronjobs", "pods", "deployments"}, + Wanted: LabelsAllowList{}, + err: expectedError{ + expectedNotEqual: true, + }, + }, + { + Desc: "wildcard key-value as not the only element, with other mutually-exclusive keys", + LabelsAllowlist: map[string][]string{"*": {"*"}, "foo": {"*"}, "bar": {"*"}, "cronjobs": {"*"}}, + EnabledResources: []string{"cronjobs", "pods", "deployments"}, + Wanted: LabelsAllowList(nil), + err: expectedError{ + expectedLabelError: true, + }, + }, + { + Desc: "wildcard key-value as not the only element, with other resources that do not exist", + LabelsAllowlist: map[string][]string{"*": {"*"}, "cronjobs": {"*"}}, + EnabledResources: []string{"cronjobs", "pods", "deployments", "foo", "bar"}, + Wanted: LabelsAllowList{}, + err: expectedError{ + expectedResourceError: true, + }, + }, + } + + for _, test := range tests { + b := NewBuilder() + + // Set the enabled resources. + err := b.WithEnabledResources(test.EnabledResources) + if err != nil && !test.err.expectedResourceError { + t.Log("Did not expect error while setting resources (--resources).") + t.Errorf("Test error for Desc: %s. Got Error: %v", test.Desc, err) + } + + // Resolve the allow list. + err = b.WithAllowLabels(test.LabelsAllowlist) + if err != nil && !test.err.expectedLabelError { + t.Log("Did not expect error while parsing allow list labels (--metric-labels-allowlist).") + t.Errorf("Test error for Desc: %s. Got Error: %v", test.Desc, err) + } + resolvedAllowLabels := LabelsAllowList(b.allowLabelsList) + + // Evaluate. + if !reflect.DeepEqual(resolvedAllowLabels, test.Wanted) && !test.err.expectedNotEqual { + t.Log("Expected maps to be equal.") + t.Errorf("Test error for Desc: %s\n Want: \n%+v\n Got: \n%#+v", test.Desc, test.Wanted, resolvedAllowLabels) + } + } +} diff --git a/pkg/options/options.go b/pkg/options/options.go index 3bd07e9ab8..c0097c1f77 100644 --- a/pkg/options/options.go +++ b/pkg/options/options.go @@ -107,7 +107,7 @@ func (o *Options) AddFlags() { o.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.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") o.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.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=[*]').") + o.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.flags.Int32Var(&o.Shard, "shard", int32(0), "The instances shard nominal (zero indexed) within the total number of shards. (default 0)") o.flags.IntVar(&o.TotalShards, "total-shards", 1, "The total number of shards. Sharding is disabled when total shards is set to 1.") diff --git a/pkg/options/types_test.go b/pkg/options/types_test.go index fb75abd7dd..85e0e328b7 100644 --- a/pkg/options/types_test.go +++ b/pkg/options/types_test.go @@ -279,6 +279,15 @@ func TestLabelsAllowListSet(t *testing.T) { "bar", "*"}}), }, + { + Desc: "with key as wildcard", + Value: "*=[*]", + Wanted: LabelsAllowList(map[string][]string{ + "*": { + "*", + }, + }), + }, } for _, test := range tests { From b6c5667fe6e69671929958796afd71f91cfdc430 Mon Sep 17 00:00:00 2001 From: Matthew Cary Date: Wed, 2 Nov 2022 15:21:05 -0700 Subject: [PATCH 30/70] Add retention policy metrics for KEP-1847 --- docs/statefulset-metrics.md | 1 + internal/store/statefulset.go | 27 ++++++++ internal/store/statefulset_test.go | 99 +++++++++++++++++++++++++++--- 3 files changed, 119 insertions(+), 8 deletions(-) diff --git a/docs/statefulset-metrics.md b/docs/statefulset-metrics.md index fae40311c3..00850ff954 100644 --- a/docs/statefulset-metrics.md +++ b/docs/statefulset-metrics.md @@ -11,6 +11,7 @@ | kube_statefulset_status_observed_generation | Gauge | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | STABLE | | kube_statefulset_replicas | Gauge | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | STABLE | | kube_statefulset_metadata_generation | Gauge | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | STABLE | +| kube_statefulset_persistentvolumeclaim_retention_policy | Gauge | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace>
`when_deleted`=<statefulset-when-deleted-pvc-policy>
`when_scaled`=<statefulset-when-scaled-pvc-policy> | ALPHA | | kube_statefulset_created | Gauge | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | STABLE | | kube_statefulset_labels | Gauge | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace>
`label_STATEFULSET_LABEL`=<STATEFULSET_LABEL> | STABLE | | kube_statefulset_status_current_revision | Gauge | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace>
`revision`=<statefulset-current-revision> | STABLE | diff --git a/internal/store/statefulset.go b/internal/store/statefulset.go index af6020772e..5be7c1f97e 100644 --- a/internal/store/statefulset.go +++ b/internal/store/statefulset.go @@ -193,6 +193,32 @@ func statefulSetMetricFamilies(allowAnnotationsList, allowLabelsList []string) [ } }), ), + *generator.NewFamilyGeneratorWithStability( + "kube_statefulset_persistentvolumeclaim_retention_policy", + "Count of retention policy for StatefulSet template PVCs", + metric.Gauge, + basemetrics.ALPHA, + "", + wrapStatefulSetFunc(func(s *v1.StatefulSet) *metric.Family { + deletedPolicyLabel := "" + scaledPolicyLabel := "" + if policy := s.Spec.PersistentVolumeClaimRetentionPolicy; policy != nil { + deletedPolicyLabel = string(policy.WhenDeleted) + scaledPolicyLabel = string(policy.WhenScaled) + } + ms := []*metric.Metric{} + if deletedPolicyLabel != "" || scaledPolicyLabel != "" { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{"when_deleted", "when_scaled"}, + LabelValues: []string{deletedPolicyLabel, scaledPolicyLabel}, + Value: 1, + }) + } + return &metric.Family{ + Metrics: ms, + } + }), + ), *generator.NewFamilyGenerator( descStatefulSetAnnotationsName, descStatefulSetAnnotationsHelp, @@ -268,6 +294,7 @@ func statefulSetMetricFamilies(allowAnnotationsList, allowLabelsList []string) [ ), } } + func wrapStatefulSetFunc(f func(*v1.StatefulSet) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { statefulSet := obj.(*v1.StatefulSet) diff --git a/internal/store/statefulset_test.go b/internal/store/statefulset_test.go index a6c63ee519..e48a96d961 100644 --- a/internal/store/statefulset_test.go +++ b/internal/store/statefulset_test.go @@ -63,6 +63,7 @@ func TestStatefulSetStore(t *testing.T) { # HELP kube_statefulset_created [STABLE] Unix creation timestamp # HELP kube_statefulset_labels [STABLE] Kubernetes labels converted to Prometheus labels. # HELP kube_statefulset_metadata_generation [STABLE] Sequence number representing a specific generation of the desired state for the StatefulSet. + # HELP kube_statefulset_persistentvolumeclaim_retention_policy Count of retention policy for StatefulSet template PVCs # HELP kube_statefulset_replicas [STABLE] Number of desired pods for a StatefulSet. # HELP kube_statefulset_status_current_revision [STABLE] Indicates the version of the StatefulSet used to generate Pods in the sequence [0,currentReplicas). # HELP kube_statefulset_status_observed_generation [STABLE] The generation observed by the StatefulSet controller. @@ -75,6 +76,7 @@ func TestStatefulSetStore(t *testing.T) { # TYPE kube_statefulset_created gauge # TYPE kube_statefulset_labels gauge # TYPE kube_statefulset_metadata_generation gauge + # TYPE kube_statefulset_persistentvolumeclaim_retention_policy gauge # TYPE kube_statefulset_replicas gauge # TYPE kube_statefulset_status_current_revision gauge # TYPE kube_statefulset_status_observed_generation gauge @@ -110,6 +112,7 @@ func TestStatefulSetStore(t *testing.T) { "kube_statefulset_status_replicas_updated", "kube_statefulset_status_update_revision", "kube_statefulset_status_current_revision", + "kube_statefulset_persistentvolumeclaim_retention_policy", }, }, { @@ -140,6 +143,7 @@ func TestStatefulSetStore(t *testing.T) { Want: ` # HELP kube_statefulset_labels [STABLE] Kubernetes labels converted to Prometheus labels. # HELP kube_statefulset_metadata_generation [STABLE] Sequence number representing a specific generation of the desired state for the StatefulSet. + # HELP kube_statefulset_persistentvolumeclaim_retention_policy Count of retention policy for StatefulSet template PVCs # HELP kube_statefulset_replicas [STABLE] Number of desired pods for a StatefulSet. # HELP kube_statefulset_status_current_revision [STABLE] Indicates the version of the StatefulSet used to generate Pods in the sequence [0,currentReplicas). # HELP kube_statefulset_status_observed_generation [STABLE] The generation observed by the StatefulSet controller. @@ -151,6 +155,7 @@ func TestStatefulSetStore(t *testing.T) { # HELP kube_statefulset_status_update_revision [STABLE] Indicates the version of the StatefulSet used to generate Pods in the sequence [replicas-updatedReplicas,replicas) # TYPE kube_statefulset_labels gauge # TYPE kube_statefulset_metadata_generation gauge + # TYPE kube_statefulset_persistentvolumeclaim_retention_policy gauge # TYPE kube_statefulset_replicas gauge # TYPE kube_statefulset_status_current_revision gauge # TYPE kube_statefulset_status_observed_generation gauge @@ -161,14 +166,14 @@ func TestStatefulSetStore(t *testing.T) { # TYPE kube_statefulset_status_replicas_updated gauge # TYPE kube_statefulset_status_update_revision gauge kube_statefulset_status_update_revision{namespace="ns2",revision="ur2",statefulset="statefulset2"} 1 - kube_statefulset_status_replicas{namespace="ns2",statefulset="statefulset2"} 5 + kube_statefulset_status_replicas{namespace="ns2",statefulset="statefulset2"} 5 kube_statefulset_status_replicas_available{namespace="ns2",statefulset="statefulset2"} 4 kube_statefulset_status_replicas_current{namespace="ns2",statefulset="statefulset2"} 2 kube_statefulset_status_replicas_ready{namespace="ns2",statefulset="statefulset2"} 5 kube_statefulset_status_replicas_updated{namespace="ns2",statefulset="statefulset2"} 3 - 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_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 `, @@ -184,6 +189,7 @@ func TestStatefulSetStore(t *testing.T) { "kube_statefulset_status_replicas_updated", "kube_statefulset_status_update_revision", "kube_statefulset_status_current_revision", + "kube_statefulset_persistentvolumeclaim_retention_policy", }, }, { @@ -210,6 +216,7 @@ func TestStatefulSetStore(t *testing.T) { Want: ` # HELP kube_statefulset_labels [STABLE] Kubernetes labels converted to Prometheus labels. # HELP kube_statefulset_metadata_generation [STABLE] Sequence number representing a specific generation of the desired state for the StatefulSet. + # HELP kube_statefulset_persistentvolumeclaim_retention_policy Count of retention policy for StatefulSet template PVCs # HELP kube_statefulset_replicas [STABLE] Number of desired pods for a StatefulSet. # HELP kube_statefulset_status_current_revision [STABLE] Indicates the version of the StatefulSet used to generate Pods in the sequence [0,currentReplicas). # HELP kube_statefulset_status_replicas [STABLE] The number of replicas per StatefulSet. @@ -220,6 +227,7 @@ func TestStatefulSetStore(t *testing.T) { # HELP kube_statefulset_status_update_revision [STABLE] Indicates the version of the StatefulSet used to generate Pods in the sequence [replicas-updatedReplicas,replicas) # TYPE kube_statefulset_labels gauge # TYPE kube_statefulset_metadata_generation gauge + # TYPE kube_statefulset_persistentvolumeclaim_retention_policy gauge # TYPE kube_statefulset_replicas gauge # TYPE kube_statefulset_status_current_revision gauge # TYPE kube_statefulset_status_replicas gauge @@ -229,13 +237,13 @@ func TestStatefulSetStore(t *testing.T) { # TYPE kube_statefulset_status_replicas_updated gauge # TYPE kube_statefulset_status_update_revision gauge kube_statefulset_status_update_revision{namespace="ns3",revision="ur3",statefulset="statefulset3"} 1 - kube_statefulset_status_replicas{namespace="ns3",statefulset="statefulset3"} 7 + kube_statefulset_status_replicas{namespace="ns3",statefulset="statefulset3"} 7 kube_statefulset_status_replicas_available{namespace="ns3",statefulset="statefulset3"} 0 kube_statefulset_status_replicas_current{namespace="ns3",statefulset="statefulset3"} 0 kube_statefulset_status_replicas_ready{namespace="ns3",statefulset="statefulset3"} 0 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_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 `, @@ -250,6 +258,81 @@ func TestStatefulSetStore(t *testing.T) { "kube_statefulset_status_replicas_updated", "kube_statefulset_status_update_revision", "kube_statefulset_status_current_revision", + "kube_statefulset_persistentvolumeclaim_retention_policy", + }, + }, + { + Obj: &v1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "statefulset4", + Namespace: "ns4", + Labels: map[string]string{ + "app": "example4", + }, + Generation: 1, + }, + Spec: v1.StatefulSetSpec{ + Replicas: &statefulSet1Replicas, + ServiceName: "statefulset4service", + PersistentVolumeClaimRetentionPolicy: &v1.StatefulSetPersistentVolumeClaimRetentionPolicy{ + WhenDeleted: v1.RetainPersistentVolumeClaimRetentionPolicyType, + WhenScaled: v1.DeletePersistentVolumeClaimRetentionPolicyType, + }, + }, + Status: v1.StatefulSetStatus{ + ObservedGeneration: 0, + Replicas: 7, + UpdateRevision: "ur3", + CurrentRevision: "cr3", + }, + }, + Want: ` + # HELP kube_statefulset_labels [STABLE] Kubernetes labels converted to Prometheus labels. + # HELP kube_statefulset_metadata_generation [STABLE] Sequence number representing a specific generation of the desired state for the StatefulSet. + # HELP kube_statefulset_persistentvolumeclaim_retention_policy Count of retention policy for StatefulSet template PVCs + # HELP kube_statefulset_replicas [STABLE] Number of desired pods for a StatefulSet. + # HELP kube_statefulset_status_current_revision [STABLE] Indicates the version of the StatefulSet used to generate Pods in the sequence [0,currentReplicas). + # HELP kube_statefulset_status_replicas [STABLE] The number of replicas per StatefulSet. + # HELP kube_statefulset_status_replicas_available The number of available replicas per StatefulSet. + # HELP kube_statefulset_status_replicas_current [STABLE] The number of current replicas per StatefulSet. + # HELP kube_statefulset_status_replicas_ready [STABLE] The number of ready replicas per StatefulSet. + # HELP kube_statefulset_status_replicas_updated [STABLE] The number of updated replicas per StatefulSet. + # HELP kube_statefulset_status_update_revision [STABLE] Indicates the version of the StatefulSet used to generate Pods in the sequence [replicas-updatedReplicas,replicas) + # TYPE kube_statefulset_labels gauge + # TYPE kube_statefulset_metadata_generation gauge + # TYPE kube_statefulset_persistentvolumeclaim_retention_policy gauge + # TYPE kube_statefulset_replicas gauge + # TYPE kube_statefulset_status_current_revision gauge + # TYPE kube_statefulset_status_replicas gauge + # TYPE kube_statefulset_status_replicas_available gauge + # TYPE kube_statefulset_status_replicas_current gauge + # TYPE kube_statefulset_status_replicas_ready gauge + # TYPE kube_statefulset_status_replicas_updated gauge + # TYPE kube_statefulset_status_update_revision gauge + kube_statefulset_status_update_revision{namespace="ns4",revision="ur3",statefulset="statefulset4"} 1 + kube_statefulset_status_replicas{namespace="ns4",statefulset="statefulset4"} 7 + kube_statefulset_status_replicas_available{namespace="ns4",statefulset="statefulset4"} 0 + kube_statefulset_status_replicas_current{namespace="ns4",statefulset="statefulset4"} 0 + kube_statefulset_status_replicas_ready{namespace="ns4",statefulset="statefulset4"} 0 + kube_statefulset_status_replicas_updated{namespace="ns4",statefulset="statefulset4"} 0 + 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{ + "kube_statefulset_labels", + "kube_statefulset_metadata_generation", + "kube_statefulset_replicas", + "kube_statefulset_status_replicas", + "kube_statefulset_status_replicas_available", + "kube_statefulset_status_replicas_current", + "kube_statefulset_status_replicas_ready", + "kube_statefulset_status_replicas_updated", + "kube_statefulset_status_update_revision", + "kube_statefulset_status_current_revision", + "kube_statefulset_persistentvolumeclaim_retention_policy", }, }, } @@ -257,7 +340,7 @@ func TestStatefulSetStore(t *testing.T) { c.Func = generator.ComposeMetricGenFuncs(statefulSetMetricFamilies(nil, nil)) c.Headers = generator.ExtractMetricFamilyHeaders(statefulSetMetricFamilies(nil, nil)) if err := c.run(); err != nil { - t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) + t.Errorf("unexpected collecting result for statefulset%d run:\n%s", i+1, err) } } } From 83d68c57fdfa935ee5200c30021d5661893f4a56 Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Wed, 9 Nov 2022 03:34:59 +0530 Subject: [PATCH 31/70] fixup! Allow `labelFromKey` field --- pkg/customresourcestate/registry_factory.go | 30 ++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/pkg/customresourcestate/registry_factory.go b/pkg/customresourcestate/registry_factory.go index 3cc575504d..4a8996f69f 100644 --- a/pkg/customresourcestate/registry_factory.go +++ b/pkg/customresourcestate/registry_factory.go @@ -262,33 +262,33 @@ func (c *compiledInfo) Values(v interface{}) (result []eachValue, errs []error) } result = append(result, ev...) } - default: + case map[string]interface{}: value, err := c.values(v) if err != nil { onError(err...) break } // labelFromKey logic - if vv, ok := v.(map[string]interface{}); ok { - for key, val := range vv { - if key != "" && c.labelFromKey != "" { - n, err := toFloat64(val, false) - if err != nil { - onError(err) - continue - } - result = append(result, eachValue{ - Labels: map[string]string{ - c.labelFromKey: key, - }, - Value: n, - }) + for key, val := range iter { + if key != "" && c.labelFromKey != "" { + n, err := toFloat64(val, false) + if err != nil { + onError(err) + continue } + result = append(result, eachValue{ + Labels: map[string]string{ + c.labelFromKey: key, + }, + Value: n, + }) } } if len(result) == 0 { result = value } + default: + result, errs = c.values(v) } return From a1716fa39dbfc5ebf5941764f8814067a1240722 Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Wed, 9 Nov 2022 12:27:18 +0530 Subject: [PATCH 32/70] fixup! fixup! Allow `labelFromKey` field --- pkg/customresourcestate/registry_factory.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/pkg/customresourcestate/registry_factory.go b/pkg/customresourcestate/registry_factory.go index 4a8996f69f..8782f43194 100644 --- a/pkg/customresourcestate/registry_factory.go +++ b/pkg/customresourcestate/registry_factory.go @@ -269,18 +269,13 @@ func (c *compiledInfo) Values(v interface{}) (result []eachValue, errs []error) break } // labelFromKey logic - for key, val := range iter { + for key := range iter { if key != "" && c.labelFromKey != "" { - n, err := toFloat64(val, false) - if err != nil { - onError(err) - continue - } result = append(result, eachValue{ Labels: map[string]string{ c.labelFromKey: key, }, - Value: n, + Value: 1, }) } } From b9f0d8ddf955936406566e401a3d7c9c6c8287dd Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Wed, 9 Nov 2022 16:49:28 +0530 Subject: [PATCH 33/70] fixup! fixup! fixup! Allow `labelFromKey` field --- pkg/customresourcestate/registry_factory.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/customresourcestate/registry_factory.go b/pkg/customresourcestate/registry_factory.go index 8782f43194..608446cdac 100644 --- a/pkg/customresourcestate/registry_factory.go +++ b/pkg/customresourcestate/registry_factory.go @@ -268,6 +268,12 @@ func (c *compiledInfo) Values(v interface{}) (result []eachValue, errs []error) onError(err...) break } + for _, ev := range value { + if _, ok := ev.Labels[c.labelFromKey]; ok { + onError(fmt.Errorf("labelFromKey (%s) generated labels conflict with labelsFromPath, consider renaming it", c.labelFromKey)) + continue + } + } // labelFromKey logic for key := range iter { if key != "" && c.labelFromKey != "" { From 2279fb269515cfd51dbf0fb467007ece2e8da5a1 Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Thu, 15 Sep 2022 11:43:51 +0530 Subject: [PATCH 34/70] Deprecate VPA Deprecate VPA metrics in v2.9.0. Signed-off-by: Pranshu Srivastava --- docs/verticalpodautoscaler-metrics.md | 59 ++++++++++++++++---- internal/store/verticalpodautoscaler.go | 18 +++--- internal/store/verticalpodautoscaler_test.go | 16 +++--- 3 files changed, 65 insertions(+), 28 deletions(-) diff --git a/docs/verticalpodautoscaler-metrics.md b/docs/verticalpodautoscaler-metrics.md index 3077c2395c..49d380de99 100644 --- a/docs/verticalpodautoscaler-metrics.md +++ b/docs/verticalpodautoscaler-metrics.md @@ -1,16 +1,53 @@ # Vertical Pod Autoscaler Metrics -| Metric name | Metric type | Labels/tags | Status | -| -------------------------------- | ----------- | ------------------------------------------------------------- | ------ | -| kube_verticalpodautoscaler_annotations | Gauge | `annotation_app`=<foo>
`namespace`=<namespace>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`verticalpodautoscaler`=<vertical pod autoscaler name> | EXPERIMENTAL | -| kube_verticalpodautoscaler_spec_resourcepolicy_container_policies_minallowed | Gauge | `container`=<container name>
`namespace`=<namespace>
`resource`=<cpu memory>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`unit`=<core byte>
`verticalpodautoscaler`=<vertical pod autoscaler name> | EXPERIMENTAL | -| kube_verticalpodautoscaler_spec_resourcepolicy_container_policies_maxallowed | Gauge | `container`=<container name>
`namespace`=<namespace>
`resource`=<cpu memory>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`unit`=<core byte>
`verticalpodautoscaler`=<vertical pod autoscaler name> | EXPERIMENTAL | -| kube_verticalpodautoscaler_status_recommendation_containerrecommendations_lowerbound | Gauge | `container`=<container name>
`namespace`=<namespace>
`resource`=<cpu memory>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`unit`=<core byte>
`verticalpodautoscaler`=<vertical pod autoscaler name> | EXPERIMENTAL | -| kube_verticalpodautoscaler_status_recommendation_containerrecommendations_target | Gauge | `container`=<container name>
`namespace`=<namespace>
`resource`=<cpu memory>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`unit`=<core byte>
`verticalpodautoscaler`=<vertical pod autoscaler name> | EXPERIMENTAL | -| kube_verticalpodautoscaler_status_recommendation_containerrecommendations_uncappedtarget | Gauge | `container`=<container name>
`namespace`=<namespace>
`resource`=<cpu memory>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`unit`=<core byte>
`verticalpodautoscaler`=<vertical pod autoscaler name> | EXPERIMENTAL | -| kube_verticalpodautoscaler_status_recommendation_containerrecommendations_upperbound | Gauge | `container`=<container name>
`namespace`=<namespace>
`resource`=<cpu memory>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`unit`=<core byte>
`verticalpodautoscaler`=<vertical pod autoscaler name> | EXPERIMENTAL | -| kube_verticalpodautoscaler_labels | Gauge | `label_app`=<foo>
`namespace`=<namespace>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`verticalpodautoscaler`=<vertical pod autoscaler name> | EXPERIMENTAL | -| kube_verticalpodautoscaler_spec_updatepolicy_updatemode | Gauge | `namespace`=<namespace>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`update_mode`=<foo>
`verticalpodautoscaler`=<vertical pod autoscaler name> | EXPERIMENTAL | +## DEPRECATION NOTICE + +From v2.9.0 onwards, `vericalpodautoscalers` will be removed from the list of default resources. This means that specifying that in the `--resource` flag will **not** generate metrics for the same. In order to generate `verticalpodautoscalers` metrics, you will have to explicitly specify it in `--custom-resource-state-config*` (either the inline yaml, or the configuration file), like so: +```yaml +# Using --resource=verticalpodautoscalers, we get the following output: +# HELP kube_verticalpodautoscaler_annotations (Deprecated since v2.9.0) Kubernetes annotations converted to Prometheus labels. +# TYPE kube_verticalpodautoscaler_annotations gauge +# kube_verticalpodautoscaler_annotations{namespace="default",verticalpodautoscaler="hamster-vpa",target_api_version="apps/v1",target_kind="Deployment",target_name="hamster"} 1 +# A similar result can be achieved by specifying the following in --custom-resource-state-config: +kind: CustomResourceStateMetrics +spec: + resources: + - groupVersionKind: + group: autoscaling.k8s.io + kind: "VerticalPodAutoscaler" + version: "v1" + labelsFromPath: + verticalpodautoscaler: [metadata, name] + namespace: [metadata, namespace] + target_api_version: [apiVersion] + target_kind: [spec, targetRef, kind] + target_name: [spec, targetRef, name] + metrics: + - name: "annotations" + help: "Kubernetes annotations converted to Prometheus labels." + each: + type: Gauge + gauge: + path: [metadata, annotations] +# This will output the following metric: +# HELP kube_crd_autoscaling_k8s_io_v1_VerticalPodAutoscaler_annotations Kubernetes annotations converted to Prometheus labels. +# TYPE kube_crd_autoscaling_k8s_io_v1_VerticalPodAutoscaler_annotations gauge +# kube_crd_autoscaling_k8s_io_v1_VerticalPodAutoscaler_annotations{namespace="default",target_api_version="autoscaling.k8s.io/v1",target_kind="Deployment",target_name="hamster",verticalpodautoscaler="hamster-vpa"} 123 +``` +PS. The above configuration was tested on [this](https://github.com/kubernetes/autoscaler/blob/master/vertical-pod-autoscaler/examples/hamster.yaml) VPA configuration, with an added annotation (`foo: 123`). +*** + +| Metric name | Metric type | Labels/tags | Status | +| -------------------------------- | ----------- | ------------------------------------------------------------- | ------ | +| kube_verticalpodautoscaler_annotations | Gauge | `annotation_app`=<foo>
`namespace`=<namespace>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`verticalpodautoscaler`=<vertical pod autoscaler name> | DEPRECATED | +| kube_verticalpodautoscaler_spec_resourcepolicy_container_policies_minallowed | Gauge | `container`=<container name>
`namespace`=<namespace>
`resource`=<cpu memory>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`unit`=<core byte>
`verticalpodautoscaler`=<vertical pod autoscaler name> | DEPRECATED | +| kube_verticalpodautoscaler_spec_resourcepolicy_container_policies_maxallowed | Gauge | `container`=<container name>
`namespace`=<namespace>
`resource`=<cpu memory>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`unit`=<core byte>
`verticalpodautoscaler`=<vertical pod autoscaler name> | DEPRECATED | +| kube_verticalpodautoscaler_status_recommendation_containerrecommendations_lowerbound | Gauge | `container`=<container name>
`namespace`=<namespace>
`resource`=<cpu memory>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`unit`=<core byte>
`verticalpodautoscaler`=<vertical pod autoscaler name> | DEPRECATED | +| kube_verticalpodautoscaler_status_recommendation_containerrecommendations_target | Gauge | `container`=<container name>
`namespace`=<namespace>
`resource`=<cpu memory>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`unit`=<core byte>
`verticalpodautoscaler`=<vertical pod autoscaler name> | DEPRECATED | +| kube_verticalpodautoscaler_status_recommendation_containerrecommendations_uncappedtarget | Gauge | `container`=<container name>
`namespace`=<namespace>
`resource`=<cpu memory>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`unit`=<core byte>
`verticalpodautoscaler`=<vertical pod autoscaler name> | DEPRECATED | +| kube_verticalpodautoscaler_status_recommendation_containerrecommendations_upperbound | Gauge | `container`=<container name>
`namespace`=<namespace>
`resource`=<cpu memory>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`unit`=<core byte>
`verticalpodautoscaler`=<vertical pod autoscaler name> | DEPRECATED | +| kube_verticalpodautoscaler_labels | Gauge | `label_app`=<foo>
`namespace`=<namespace>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`verticalpodautoscaler`=<vertical pod autoscaler name> | DEPRECATED | +| kube_verticalpodautoscaler_spec_updatepolicy_updatemode | Gauge | `namespace`=<namespace>
`target_api_version`=<api version>
`target_kind`=<target kind>
`target_name`=<target name>
`update_mode`=<foo>
`verticalpodautoscaler`=<vertical pod autoscaler name> | DEPRECATED | ## Configuration diff --git a/internal/store/verticalpodautoscaler.go b/internal/store/verticalpodautoscaler.go index b3841faf08..ed0fe7f46e 100644 --- a/internal/store/verticalpodautoscaler.go +++ b/internal/store/verticalpodautoscaler.go @@ -48,7 +48,7 @@ func vpaMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat descVerticalPodAutoscalerAnnotationsName, descVerticalPodAutoscalerAnnotationsHelp, metric.Gauge, - "", + "v2.9.0", wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", a.Annotations, allowAnnotationsList) return &metric.Family{ @@ -66,7 +66,7 @@ func vpaMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat descVerticalPodAutoscalerLabelsName, descVerticalPodAutoscalerLabelsHelp, metric.Gauge, - "", + "v2.9.0", wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { labelKeys, labelValues := createPrometheusLabelKeysValues("label", a.Labels, allowLabelsList) return &metric.Family{ @@ -84,7 +84,7 @@ func vpaMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat "kube_verticalpodautoscaler_spec_updatepolicy_updatemode", "Update mode of the VerticalPodAutoscaler.", metric.Gauge, - "", + "v2.9.0", wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { ms := []*metric.Metric{} @@ -122,7 +122,7 @@ func vpaMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat "kube_verticalpodautoscaler_spec_resourcepolicy_container_policies_minallowed", "Minimum resources the VerticalPodAutoscaler can set for containers matching the name.", metric.Gauge, - "", + "v2.9.0", wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { ms := []*metric.Metric{} if a.Spec.ResourcePolicy == nil || a.Spec.ResourcePolicy.ContainerPolicies == nil { @@ -144,7 +144,7 @@ func vpaMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat "kube_verticalpodautoscaler_spec_resourcepolicy_container_policies_maxallowed", "Maximum resources the VerticalPodAutoscaler can set for containers matching the name.", metric.Gauge, - "", + "v2.9.0", wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { ms := []*metric.Metric{} if a.Spec.ResourcePolicy == nil || a.Spec.ResourcePolicy.ContainerPolicies == nil { @@ -165,7 +165,7 @@ func vpaMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat "kube_verticalpodautoscaler_status_recommendation_containerrecommendations_lowerbound", "Minimum resources the container can use before the VerticalPodAutoscaler updater evicts it.", metric.Gauge, - "", + "v2.9.0", wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { ms := []*metric.Metric{} if a.Status.Recommendation == nil || a.Status.Recommendation.ContainerRecommendations == nil { @@ -186,7 +186,7 @@ func vpaMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat "kube_verticalpodautoscaler_status_recommendation_containerrecommendations_upperbound", "Maximum resources the container can use before the VerticalPodAutoscaler updater evicts it.", metric.Gauge, - "", + "v2.9.0", wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { ms := []*metric.Metric{} if a.Status.Recommendation == nil || a.Status.Recommendation.ContainerRecommendations == nil { @@ -207,7 +207,7 @@ func vpaMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat "kube_verticalpodautoscaler_status_recommendation_containerrecommendations_target", "Target resources the VerticalPodAutoscaler recommends for the container.", metric.Gauge, - "", + "v2.9.0", wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { ms := []*metric.Metric{} if a.Status.Recommendation == nil || a.Status.Recommendation.ContainerRecommendations == nil { @@ -227,7 +227,7 @@ func vpaMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat "kube_verticalpodautoscaler_status_recommendation_containerrecommendations_uncappedtarget", "Target resources the VerticalPodAutoscaler recommends for the container ignoring bounds.", metric.Gauge, - "", + "v2.9.0", wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { ms := []*metric.Metric{} if a.Status.Recommendation == nil || a.Status.Recommendation.ContainerRecommendations == nil { diff --git a/internal/store/verticalpodautoscaler_test.go b/internal/store/verticalpodautoscaler_test.go index 82aa7eb5ae..4c107b3c6c 100644 --- a/internal/store/verticalpodautoscaler_test.go +++ b/internal/store/verticalpodautoscaler_test.go @@ -30,14 +30,14 @@ import ( func TestVPAStore(t *testing.T) { const metadata = ` - # HELP kube_verticalpodautoscaler_labels Kubernetes labels converted to Prometheus labels. - # HELP kube_verticalpodautoscaler_spec_resourcepolicy_container_policies_maxallowed Maximum resources the VerticalPodAutoscaler can set for containers matching the name. - # HELP kube_verticalpodautoscaler_spec_resourcepolicy_container_policies_minallowed Minimum resources the VerticalPodAutoscaler can set for containers matching the name. - # HELP kube_verticalpodautoscaler_spec_updatepolicy_updatemode Update mode of the VerticalPodAutoscaler. - # HELP kube_verticalpodautoscaler_status_recommendation_containerrecommendations_lowerbound Minimum resources the container can use before the VerticalPodAutoscaler updater evicts it. - # HELP kube_verticalpodautoscaler_status_recommendation_containerrecommendations_target Target resources the VerticalPodAutoscaler recommends for the container. - # HELP kube_verticalpodautoscaler_status_recommendation_containerrecommendations_uncappedtarget Target resources the VerticalPodAutoscaler recommends for the container ignoring bounds. - # HELP kube_verticalpodautoscaler_status_recommendation_containerrecommendations_upperbound Maximum resources the container can use before the VerticalPodAutoscaler updater evicts it. + # HELP kube_verticalpodautoscaler_labels (Deprecated since v2.9.0) Kubernetes labels converted to Prometheus labels. + # HELP kube_verticalpodautoscaler_spec_resourcepolicy_container_policies_maxallowed (Deprecated since v2.9.0) Maximum resources the VerticalPodAutoscaler can set for containers matching the name. + # HELP kube_verticalpodautoscaler_spec_resourcepolicy_container_policies_minallowed (Deprecated since v2.9.0) Minimum resources the VerticalPodAutoscaler can set for containers matching the name. + # HELP kube_verticalpodautoscaler_spec_updatepolicy_updatemode (Deprecated since v2.9.0) Update mode of the VerticalPodAutoscaler. + # HELP kube_verticalpodautoscaler_status_recommendation_containerrecommendations_lowerbound (Deprecated since v2.9.0) Minimum resources the container can use before the VerticalPodAutoscaler updater evicts it. + # HELP kube_verticalpodautoscaler_status_recommendation_containerrecommendations_target (Deprecated since v2.9.0) Target resources the VerticalPodAutoscaler recommends for the container. + # HELP kube_verticalpodautoscaler_status_recommendation_containerrecommendations_uncappedtarget (Deprecated since v2.9.0) Target resources the VerticalPodAutoscaler recommends for the container ignoring bounds. + # HELP kube_verticalpodautoscaler_status_recommendation_containerrecommendations_upperbound (Deprecated since v2.9.0) Maximum resources the container can use before the VerticalPodAutoscaler updater evicts it. # TYPE kube_verticalpodautoscaler_labels gauge # TYPE kube_verticalpodautoscaler_spec_resourcepolicy_container_policies_maxallowed gauge # TYPE kube_verticalpodautoscaler_spec_resourcepolicy_container_policies_minallowed gauge From 30725023436018e609faddd5b1969379a4c46fb9 Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Thu, 10 Nov 2022 03:10:58 +0530 Subject: [PATCH 35/70] fixup! fixup! fixup! fixup! Allow `labelFromKey` field --- pkg/customresourcestate/registry_factory.go | 12 ++++++++---- pkg/customresourcestate/registry_factory_test.go | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/pkg/customresourcestate/registry_factory.go b/pkg/customresourcestate/registry_factory.go index 608446cdac..2c9ae80297 100644 --- a/pkg/customresourcestate/registry_factory.go +++ b/pkg/customresourcestate/registry_factory.go @@ -214,6 +214,10 @@ func (c *compiledGauge) Values(v interface{}) (result []eachValue, errs []error) onError(fmt.Errorf("[%s]: %w", key, err)) continue } + if _, ok := ev.Labels[c.labelFromKey]; ok { + onError(fmt.Errorf("labelFromKey (%s) generated labels conflict with labelsFromPath, consider renaming it", c.labelFromKey)) + continue + } if key != "" && c.labelFromKey != "" { ev.Labels[c.labelFromKey] = key } @@ -285,9 +289,7 @@ func (c *compiledInfo) Values(v interface{}) (result []eachValue, errs []error) }) } } - if len(result) == 0 { - result = value - } + result = append(result, value...) default: result, errs = c.values(v) } @@ -301,7 +303,9 @@ func (c *compiledInfo) values(v interface{}) (result []eachValue, err []error) { } value := eachValue{Value: 1, Labels: map[string]string{}} addPathLabels(v, c.labelFromPath, value.Labels) - result = append(result, value) + if len(value.Labels) != 0 { + result = append(result, value) + } return } diff --git a/pkg/customresourcestate/registry_factory_test.go b/pkg/customresourcestate/registry_factory_test.go index df41129db4..e4da7d997c 100644 --- a/pkg/customresourcestate/registry_factory_test.go +++ b/pkg/customresourcestate/registry_factory_test.go @@ -221,7 +221,7 @@ func Test_values(t *testing.T) { labelFromKey: "type", }, wantResult: []eachValue{ newEachValue(t, 1, "type", "type-a"), - newEachValue(t, 3, "type", "type-b"), + newEachValue(t, 1, "type", "type-b"), }}, {name: "stateset", each: &compiledStateSet{ compiledCommon: compiledCommon{ From d39f1b138b01cf26abf3bef4778c908c86ef1863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Thu, 10 Nov 2022 08:00:49 +0100 Subject: [PATCH 36/70] go.mod: Bump exporter-toolkit to 0.8.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Rüger --- go.mod | 4 +++- go.sum | 11 +++++++---- pkg/app/server.go | 17 +++++++++++++---- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index aaed3cc3ef..f55caf3121 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/prometheus/client_golang v1.13.1 github.com/prometheus/client_model v0.3.0 github.com/prometheus/common v0.37.0 - github.com/prometheus/exporter-toolkit v0.7.1 + github.com/prometheus/exporter-toolkit v0.8.1 github.com/robfig/cron/v3 v3.0.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.1 @@ -43,6 +43,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/coreos/go-systemd/v22 v22.4.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.8.0 // indirect github.com/evanphx/json-patch v4.12.0+incompatible // indirect @@ -78,6 +79,7 @@ require ( golang.org/x/crypto v0.0.0-20221012134737-56aed061732a // indirect golang.org/x/net v0.0.0-20220909164309-bea034e7d591 // indirect golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 // indirect + golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.1.0 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect diff --git a/go.sum b/go.sum index 9ac093fd91..34191be8ac 100644 --- a/go.sum +++ b/go.sum @@ -108,6 +108,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/coreos/go-systemd/v22 v22.4.0 h1:y9YHcjnjynCd/DVbg5j9L/33jQM3MxJlbj/zWskzfGU= +github.com/coreos/go-systemd/v22 v22.4.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -171,6 +173,7 @@ github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobuffalo/flect v0.3.0 h1:erfPWM+K1rFNIQeRPdeEXxo8yFr/PO17lhRnS8FUrtk= github.com/gobuffalo/flect v0.3.0/go.mod h1:5pf3aGnsvqvCj50AVni7mJJF8ICxGZ8HomberC3pXLE= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -361,12 +364,11 @@ github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3d github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/exporter-toolkit v0.7.1 h1:c6RXaK8xBVercEeUQ4tRNL8UGWzDHfvj9dseo1FcK1Y= -github.com/prometheus/exporter-toolkit v0.7.1/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g= +github.com/prometheus/exporter-toolkit v0.8.1 h1:TpKt8z55q1zF30BYaZKqh+bODY0WtByHDOhDA2M9pEs= +github.com/prometheus/exporter-toolkit v0.8.1/go.mod h1:00shzmJL7KxcsabLWcONwpyNEuWhREOnFqZW7vadFS0= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= @@ -425,7 +427,6 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20221012134737-56aed061732a h1:NmSIgad6KjE6VvHciPZuNRTKxGhlPfD6OA87W/PLkqg= @@ -554,6 +555,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/pkg/app/server.go b/pkg/app/server.go index a8022df7e0..94b20a6ce4 100644 --- a/pkg/app/server.go +++ b/pkg/app/server.go @@ -195,21 +195,30 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options, factories . telemetryListenAddress := net.JoinHostPort(opts.TelemetryHost, strconv.Itoa(opts.TelemetryPort)) telemetryServer := http.Server{ Handler: telemetryMux, - Addr: telemetryListenAddress, ReadHeaderTimeout: 5 * time.Second} + telemetryFlags := web.FlagConfig{ + WebListenAddresses: &[]string{telemetryListenAddress}, + WebSystemdSocket: new(bool), + WebConfigFile: &tlsConfig, + } metricsMux := buildMetricsServer(m, durationVec) metricsServerListenAddress := net.JoinHostPort(opts.Host, strconv.Itoa(opts.Port)) metricsServer := http.Server{ Handler: metricsMux, - Addr: metricsServerListenAddress, ReadHeaderTimeout: 5 * time.Second} + metricsFlags := web.FlagConfig{ + WebListenAddresses: &[]string{metricsServerListenAddress}, + WebSystemdSocket: new(bool), + WebConfigFile: &tlsConfig, + } + // Run Telemetry server { g.Add(func() error { klog.InfoS("Started kube-state-metrics self metrics server", "telemetryAddress", telemetryListenAddress) - return web.ListenAndServe(&telemetryServer, tlsConfig, promLogger) + return web.ListenAndServe(&telemetryServer, &telemetryFlags, promLogger) }, func(error) { ctxShutDown, cancel := context.WithTimeout(ctx, 3*time.Second) defer cancel() @@ -220,7 +229,7 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options, factories . { g.Add(func() error { klog.InfoS("Started metrics server", "metricsServerAddress", metricsServerListenAddress) - return web.ListenAndServe(&metricsServer, tlsConfig, promLogger) + return web.ListenAndServe(&metricsServer, &metricsFlags, promLogger) }, func(error) { ctxShutDown, cancel := context.WithTimeout(ctx, 3*time.Second) defer cancel() From b926fd968efef99115b634f8e80e81df14400063 Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Thu, 15 Sep 2022 02:54:58 +0530 Subject: [PATCH 37/70] Incorporate Cobra s/pflags/cobra/g: * Use spf13/cobra to handle all flags and sub-commands. * Remove all spf13/pflag usage, and fallback to the in-build flag package if, and when needed. * Add completion support. Signed-off-by: Pranshu Srivastava --- docs/cli-arguments.md | 15 +++- go.mod | 4 +- go.sum | 6 ++ main.go | 25 +++--- pkg/options/autoload.go | 143 ++++++++++++++++++++++++++++++++++ pkg/options/options.go | 115 +++++++++++++++------------ pkg/options/options_test.go | 58 ++++++-------- scripts/generate-help-text.sh | 2 +- 8 files changed, 265 insertions(+), 103 deletions(-) create mode 100644 pkg/options/autoload.go diff --git a/docs/cli-arguments.md b/docs/cli-arguments.md index beb5582d92..bb81133d5d 100644 --- a/docs/cli-arguments.md +++ b/docs/cli-arguments.md @@ -24,7 +24,18 @@ spec: [embedmd]:# (../help.txt) ```txt $ kube-state-metrics -h -Usage of ./kube-state-metrics: +kube-state-metrics is a simple service that listens to the Kubernetes API server and generates metrics about the state of the objects. + +Usage: + kube-state-metrics [flags] + kube-state-metrics [command] + +Available Commands: + completion Generate completion script for kube-state-metrics. + help Help about any command + version Print version information. + +Flags: --add_dir_header If true, adds the file directory to the header of the log messages --alsologtostderr log to standard error as well as files (no effect when -logtostderr=true) --apiserver string The URL of the apiserver to use as a master @@ -65,4 +76,6 @@ Usage of ./kube-state-metrics: -v, --v Level number for the log level verbosity --version kube-state-metrics build version information --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging + +Use "kube-state-metrics [command] --help" for more information about a command. ``` diff --git a/go.mod b/go.mod index f55caf3121..72d9598ab9 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/prometheus/common v0.37.0 github.com/prometheus/exporter-toolkit v0.8.1 github.com/robfig/cron/v3 v3.0.1 - github.com/spf13/pflag v1.0.5 + github.com/spf13/cobra v1.6.1 github.com/stretchr/testify v1.8.1 golang.org/x/perf v0.0.0-20220920022801-e8d778a60d07 gopkg.in/yaml.v3 v3.0.1 @@ -62,6 +62,7 @@ require ( github.com/google/gofuzz v1.1.0 // indirect github.com/google/safehtml v0.0.2 // indirect github.com/imdario/mergo v0.3.6 // indirect + github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -76,6 +77,7 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect golang.org/x/crypto v0.0.0-20221012134737-56aed061732a // indirect golang.org/x/net v0.0.0-20220909164309-bea034e7d591 // indirect golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 // indirect diff --git a/go.sum b/go.sum index 34191be8ac..7ff8d1cf2f 100644 --- a/go.sum +++ b/go.sum @@ -110,6 +110,7 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-systemd/v22 v22.4.0 h1:y9YHcjnjynCd/DVbg5j9L/33jQM3MxJlbj/zWskzfGU= github.com/coreos/go-systemd/v22 v22.4.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -275,6 +276,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= @@ -383,6 +386,7 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= @@ -391,6 +395,8 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= diff --git a/main.go b/main.go index 72c8f090b5..fdd5bcd582 100644 --- a/main.go +++ b/main.go @@ -18,46 +18,41 @@ package main import ( "context" - "fmt" "os" "path/filepath" "strings" - "github.com/prometheus/common/version" + "github.com/spf13/cobra" "gopkg.in/yaml.v3" "k8s.io/klog/v2" + "k8s.io/kube-state-metrics/v2/pkg/app" "k8s.io/kube-state-metrics/v2/pkg/customresource" "k8s.io/kube-state-metrics/v2/pkg/customresourcestate" - "k8s.io/kube-state-metrics/v2/pkg/app" "k8s.io/kube-state-metrics/v2/pkg/options" ) func main() { opts := options.NewOptions() - opts.AddFlags() + cmd := options.InitCommand + cmd.Run = func(cmd *cobra.Command, args []string) { + RunKubeStateMetricsWrapper(opts) + } + opts.AddFlags(cmd) if err := opts.Parse(); err != nil { - klog.ErrorS(err, "Parsing flag definitions error") klog.FlushAndExit(klog.ExitFlushTimeout, 1) } - if opts.Version { - fmt.Printf("%s\n", version.Print("kube-state-metrics")) - os.Exit(0) - } - - if opts.Help { - opts.Usage() - os.Exit(0) - } - if err := opts.Validate(); err != nil { klog.ErrorS(err, "Validating options error") klog.FlushAndExit(klog.ExitFlushTimeout, 1) } +} +// RunKubeStateMetricsWrapper is a wrapper around KSM, delegated to the root command. +func RunKubeStateMetricsWrapper(opts *options.Options) { var factories []customresource.RegistryFactory if config, set := resolveCustomResourceConfig(opts); set { crf, err := customresourcestate.FromConfig(config) diff --git a/pkg/options/autoload.go b/pkg/options/autoload.go new file mode 100644 index 0000000000..5d51a3d3af --- /dev/null +++ b/pkg/options/autoload.go @@ -0,0 +1,143 @@ +/* +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 options + +import ( + "os" + + "github.com/spf13/cobra" + "k8s.io/klog/v2" +) + +const autoloadZsh = `Generate the autocompletion script for the zsh shell. + +If shell completion is not already enabled in your environment you will need +to enable it. You can execute the following once: + + echo "autoload -U compinit; compinit" >> ~/.zshrc + +To load completions in your current shell session: + + source <(kube-state-metrics completion zsh); compdef _kube-state-metrics kube-state-metrics + +To load completions for every new session, execute once: + +#### Linux: + + kube-state-metrics completion zsh > "${fpath[1]}/_kube-state-metrics" + +#### macOS: + + kube-state-metrics completion zsh > $(brew --prefix)/share/zsh/site-functions/_kube-state-metrics + +You will need to start a new shell for this setup to take effect. + +Usage: + kube-state-metrics completion zsh [flags] + +Flags: + --no-descriptions disable completion descriptions +` +const autoloadBash = `Generate the autocompletion script for the bash shell. + +This script depends on the 'bash-completion' package. +If it is not installed already, you can install it via your OS's package manager. + +To load completions in your current shell session: + + source <(kube-state-metrics completion bash) + +To load completions for every new session, execute once: + +#### Linux: + + kube-state-metrics completion bash > /etc/bash_completion.d/kube-state-metrics + +#### macOS: + + kube-state-metrics completion bash > $(brew --prefix)/etc/bash_completion.d/kube-state-metrics + +You will need to start a new shell for this setup to take effect. + +Usage: + kube-state-metrics completion bash + +Flags: + --no-descriptions disable completion descriptions +` + +const autoloadFish = `Generate the autocompletion script for the fish shell. + +To load completions in your current shell session: + + kube-state-metrics completion fish | source + +To load completions for every new session, execute once: + + kube-state-metrics completion fish > ~/.config/fish/completions/kube-state-metrics.fish + +You will need to start a new shell for this setup to take effect. + +Usage: + kube-state-metrics completion fish [flags] + +Flags: + --no-descriptions disable completion descriptions +` + +// FetchLoadInstructions returns instructions for enabling autocompletion for a particular shell. +func FetchLoadInstructions(shell string) string { + switch shell { + case "zsh": + return autoloadZsh + case "bash": + return autoloadBash + case "fish": + return autoloadFish + default: + return "" + } +} + +var completionCommand = &cobra.Command{ + Use: "completion [bash|zsh|fish]", + Short: "Generate completion script for kube-state-metrics.", + DisableFlagsInUseLine: true, + Aliases: []string{"comp", "c"}, + ValidArgs: []string{"bash", "zsh", "fish"}, + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + switch args[0] { + case "bash": + _ = cmd.Root().GenBashCompletion(os.Stdout) + case "zsh": + _ = cmd.Root().GenZshCompletion(os.Stdout) + case "fish": + _ = cmd.Root().GenFishCompletion(os.Stdout, true) + } + klog.FlushAndExit(klog.ExitFlushTimeout, 0) + }, + Example: "kube-state-metrics completion bash > /tmp/kube-state-metrics.bash && source /tmp/kube-state-metrics.bash # for shells compatible with bash", +} + +// InitCommand defines the root command that others will latch onto. +var InitCommand = &cobra.Command{ + Use: "kube-state-metrics", + Short: "Add-on agent to generate and expose cluster-level metrics.", + Long: "kube-state-metrics is a simple service that listens to the Kubernetes API server and generates metrics about the state of the objects.", + Args: cobra.NoArgs, +} diff --git a/pkg/options/options.go b/pkg/options/options.go index 6991930147..2b3ce45528 100644 --- a/pkg/options/options.go +++ b/pkg/options/options.go @@ -20,10 +20,11 @@ import ( "flag" "fmt" "os" + "strings" + "github.com/prometheus/common/version" + "github.com/spf13/cobra" "k8s.io/klog/v2" - - "github.com/spf13/pflag" ) // Options are the configurable parameters for kube-state-metrics. @@ -59,7 +60,7 @@ type Options struct { CustomResourceConfigFile string CustomResourcesOnly bool - flags *pflag.FlagSet + cmd *cobra.Command } // NewOptions returns a new instance of `Options`. @@ -75,67 +76,83 @@ func NewOptions() *Options { } // AddFlags populated the Options struct from the command line arguments passed. -func (o *Options) AddFlags() { - o.flags = pflag.NewFlagSet("", pflag.ExitOnError) - // add klog flags - klogFlags := flag.NewFlagSet("klog", flag.ExitOnError) - klog.InitFlags(klogFlags) - o.flags.AddGoFlagSet(klogFlags) - err := o.flags.Lookup("logtostderr").Value.Set("true") - if err != nil { - klog.Error(err) +func (o *Options) AddFlags(cmd *cobra.Command) { + o.cmd = cmd + + completionCommand.SetHelpFunc(func(cmd *cobra.Command, args []string) { + if shellPath, ok := os.LookupEnv("SHELL"); ok { + shell := shellPath[strings.LastIndex(shellPath, "/")+1:] + fmt.Println(FetchLoadInstructions(shell)) + } else { + fmt.Println("SHELL environment variable not set, falling back to bash") + fmt.Println(FetchLoadInstructions("bash")) + } + klog.FlushAndExit(klog.ExitFlushTimeout, 0) + }) + + versionCommand := &cobra.Command{ + Use: "version", + Short: "Print version information.", + Run: func(cmd *cobra.Command, args []string) { + fmt.Printf("%s\n", version.Print("kube-state-metrics")) + klog.FlushAndExit(klog.ExitFlushTimeout, 0) + }, } - o.flags.Lookup("logtostderr").DefValue = "true" - o.flags.Lookup("logtostderr").NoOptDefVal = "true" - o.flags.Usage = func() { - fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) - o.flags.PrintDefaults() + cmd.AddCommand(completionCommand, versionCommand) + + o.cmd.Flags().Usage = func() { + _, _ = fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) + o.cmd.Flags().PrintDefaults() } - o.flags.BoolVarP(&o.UseAPIServerCache, "use-apiserver-cache", "", false, "Sets resourceVersion=0 for ListWatch requests, using cached resources from the apiserver instead of an etcd quorum read.") - o.flags.StringVar(&o.Apiserver, "apiserver", "", `The URL of the apiserver to use as a master`) - o.flags.StringVar(&o.Kubeconfig, "kubeconfig", "", "Absolute path to the kubeconfig file") - o.flags.StringVar(&o.TLSConfig, "tls-config", "", "Path to the TLS configuration file") - o.flags.BoolVarP(&o.Help, "help", "h", false, "Print Help text") - o.flags.IntVar(&o.Port, "port", 8080, `Port to expose metrics on.`) - o.flags.StringVar(&o.Host, "host", "::", `Host to expose metrics on.`) - o.flags.IntVar(&o.TelemetryPort, "telemetry-port", 8081, `Port to expose kube-state-metrics self metrics on.`) - o.flags.StringVar(&o.TelemetryHost, "telemetry-host", "::", `Host to expose kube-state-metrics self metrics on.`) - o.flags.Var(&o.Resources, "resources", fmt.Sprintf("Comma-separated list of Resources to be enabled. Defaults to %q", &DefaultResources)) - o.flags.Var(&o.Namespaces, "namespaces", fmt.Sprintf("Comma-separated list of namespaces to be enabled. Defaults to %q", &DefaultNamespaces)) - o.flags.Var(&o.NamespacesDenylist, "namespaces-denylist", "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.") - o.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.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.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") - o.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.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.flags.Int32Var(&o.Shard, "shard", int32(0), "The instances shard nominal (zero indexed) within the total number of shards. (default 0)") - o.flags.IntVar(&o.TotalShards, "total-shards", 1, "The total number of shards. Sharding is disabled when total shards is set to 1.") - - o.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.") + klogFlags := flag.NewFlagSet("klog", flag.ExitOnError) + klog.InitFlags(klogFlags) + o.cmd.Flags().AddGoFlagSet(klogFlags) + _ = o.cmd.Flags().Lookup("logtostderr").Value.Set("true") + o.cmd.Flags().Lookup("logtostderr").DefValue = "true" + o.cmd.Flags().Lookup("logtostderr").NoOptDefVal = "true" autoshardingNotice := "When set, it is expected that --pod and --pod-namespace are both set. Most likely this should be passed via the downward API. This is used for auto-detecting sharding. If set, this has preference over statically configured sharding. This is experimental, it may be removed without notice." - o.flags.StringVar(&o.Pod, "pod", "", "Name of the pod that contains the kube-state-metrics container. "+autoshardingNotice) - o.flags.StringVar(&o.Namespace, "pod-namespace", "", "Name of the namespace of the pod specified by --pod. "+autoshardingNotice) - o.flags.BoolVarP(&o.Version, "version", "", false, "kube-state-metrics build version information") - o.flags.BoolVar(&o.EnableGZIPEncoding, "enable-gzip-encoding", false, "Gzip responses when requested by clients via 'Accept-Encoding: gzip' header.") - - o.flags.StringVar(&o.CustomResourceConfig, "custom-resource-state-config", "", "Inline Custom Resource State Metrics config YAML (experimental)") - o.flags.StringVar(&o.CustomResourceConfigFile, "custom-resource-state-config-file", "", "Path to a Custom Resource State Metrics config file (experimental)") - o.flags.BoolVar(&o.CustomResourcesOnly, "custom-resource-state-only", false, "Only provide Custom Resource State metrics (experimental)") + o.cmd.Flags().BoolVar(&o.CustomResourcesOnly, "custom-resource-state-only", false, "Only provide Custom Resource State metrics (experimental)") + o.cmd.Flags().BoolVar(&o.EnableGZIPEncoding, "enable-gzip-encoding", false, "Gzip responses when requested by clients via 'Accept-Encoding: gzip' header.") + o.cmd.Flags().BoolVarP(&o.Help, "help", "h", false, "Print Help text") + o.cmd.Flags().BoolVarP(&o.UseAPIServerCache, "use-apiserver-cache", "", false, "Sets resourceVersion=0 for ListWatch requests, using cached resources from the apiserver instead of an etcd quorum read.") + o.cmd.Flags().BoolVarP(&o.Version, "version", "", false, "kube-state-metrics build version information") + o.cmd.Flags().Int32Var(&o.Shard, "shard", int32(0), "The instances shard nominal (zero indexed) within the total number of shards. (default 0)") + o.cmd.Flags().IntVar(&o.Port, "port", 8080, `Port to expose metrics on.`) + o.cmd.Flags().IntVar(&o.TelemetryPort, "telemetry-port", 8081, `Port to expose kube-state-metrics self metrics on.`) + o.cmd.Flags().IntVar(&o.TotalShards, "total-shards", 1, "The total number of shards. Sharding is disabled when total shards is set to 1.") + o.cmd.Flags().StringVar(&o.Apiserver, "apiserver", "", `The URL of the apiserver to use as a master`) + o.cmd.Flags().StringVar(&o.CustomResourceConfig, "custom-resource-state-config", "", "Inline Custom Resource State Metrics config YAML (experimental)") + o.cmd.Flags().StringVar(&o.CustomResourceConfigFile, "custom-resource-state-config-file", "", "Path to a Custom Resource State Metrics config file (experimental)") + o.cmd.Flags().StringVar(&o.Host, "host", "::", `Host to expose metrics on.`) + o.cmd.Flags().StringVar(&o.Kubeconfig, "kubeconfig", "", "Absolute path to the kubeconfig file") + o.cmd.Flags().StringVar(&o.Namespace, "pod-namespace", "", "Name of the namespace of the pod specified by --pod. "+autoshardingNotice) + o.cmd.Flags().StringVar(&o.Pod, "pod", "", "Name of the pod that contains the kube-state-metrics container. "+autoshardingNotice) + o.cmd.Flags().StringVar(&o.TLSConfig, "tls-config", "", "Path to the TLS configuration file") + o.cmd.Flags().StringVar(&o.TelemetryHost, "telemetry-host", "::", `Host to expose kube-state-metrics self metrics on.`) + 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.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") + o.cmd.Flags().Var(&o.Namespaces, "namespaces", fmt.Sprintf("Comma-separated list of namespaces to be enabled. Defaults to %q", &DefaultNamespaces)) + o.cmd.Flags().Var(&o.NamespacesDenylist, "namespaces-denylist", "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.") + o.cmd.Flags().Var(&o.Resources, "resources", fmt.Sprintf("Comma-separated list of Resources to be enabled. Defaults to %q", &DefaultResources)) } // Parse parses the flag definitions from the argument list. func (o *Options) Parse() error { - err := o.flags.Parse(os.Args) + err := o.cmd.Execute() return err } // Usage is the function called when an error occurs while parsing flags. func (o *Options) Usage() { - o.flags.Usage() + _ = o.cmd.Flags().FlagUsages() } // Validate validates arguments @@ -146,7 +163,7 @@ func (o *Options) Validate() error { } for _, x := range o.Resources.AsSlice() { if x != shardableResource { - return fmt.Errorf("Resource %s can't be sharded by field selector spec.nodeName", x) + return fmt.Errorf("resource %s can't be sharded by field selector spec.nodeName", x) } } return nil diff --git a/pkg/options/options_test.go b/pkg/options/options_test.go index 1a6f5c7304..beb5d79191 100644 --- a/pkg/options/options_test.go +++ b/pkg/options/options_test.go @@ -18,58 +18,44 @@ package options import ( "os" - "sync" "testing" - - "github.com/spf13/pflag" ) func TestOptionsParse(t *testing.T) { tests := []struct { - Desc string - Args []string - RecoverInvoked bool + Desc string + Args []string + ExpectsError bool }{ { - Desc: "resources command line argument", - Args: []string{"./kube-state-metrics", "--resources=configmaps,pods"}, - RecoverInvoked: false, + Desc: "resources command line argument", + Args: []string{"./kube-state-metrics", "--resources=configmaps,pods"}, + ExpectsError: false, + }, + { + Desc: "namespaces command line argument", + Args: []string{"./kube-state-metrics", "--namespaces=default,kube-system"}, + ExpectsError: false, }, { - Desc: "namespaces command line argument", - Args: []string{"./kube-state-metrics", "--namespaces=default,kube-system"}, - RecoverInvoked: false, + Desc: "foo command line argument", + Args: []string{"./kube-state-metrics", "--foo=bar,baz"}, + ExpectsError: true, }, } - for _, test := range tests { - var wg sync.WaitGroup - - opts := NewOptions() - opts.AddFlags() + opts := NewOptions() + opts.AddFlags(InitCommand) - flags := pflag.NewFlagSet("options_test", pflag.PanicOnError) - flags.AddFlagSet(opts.flags) - - opts.flags = flags + for _, test := range tests { os.Args = test.Args - wg.Add(1) - go func() { - defer wg.Done() - defer func() { - if err := recover(); err != nil { - test.RecoverInvoked = true - } - }() - - opts.Parse() - }() - - wg.Wait() - if test.RecoverInvoked { - t.Errorf("Test error for Desc: %s. Test panic", test.Desc) + err := opts.Parse() + if err != nil { + if !test.ExpectsError { + t.Errorf("Error for test with description: %s: %v", test.Desc, err.Error()) + } } } } diff --git a/scripts/generate-help-text.sh b/scripts/generate-help-text.sh index 8d58828a1c..00393eac81 100755 --- a/scripts/generate-help-text.sh +++ b/scripts/generate-help-text.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash echo "$ kube-state-metrics -h" > help.txt -./kube-state-metrics -h 2>> help.txt +./kube-state-metrics -h >> help.txt exit 0 From 837f7473e10b36f35eefe93a1ae234274db11fe0 Mon Sep 17 00:00:00 2001 From: Akshit Tyagi <37214399+exitflynn@users.noreply.github.com> Date: Mon, 14 Nov 2022 14:47:38 +0000 Subject: [PATCH 38/70] update kube_node_status_{capacity/allocatable} doc to clarify difference --- docs/node-metrics.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/node-metrics.md b/docs/node-metrics.md index cc817caaa6..f5a31e0a01 100644 --- a/docs/node-metrics.md +++ b/docs/node-metrics.md @@ -8,7 +8,7 @@ | kube_node_role | Gauge | The role of a cluster node | | `node`=<node-address>
`role`=<NODE_ROLE> | EXPERIMENTAL | | kube_node_spec_unschedulable | Gauge | Whether a node can schedule new pods | | `node`=<node-address>| STABLE | | kube_node_spec_taint | Gauge | The taint of a cluster node. | |`node`=<node-address>
`key`=<taint-key>
`value=`<taint-value>
`effect=`<taint-effect> | STABLE | -| kube_node_status_capacity | Gauge | The capacity for different resources of a node | `cpu`=<core>
`ephemeral_storage`=<byte>
`pods`=<integer>
`attachable_volumes_*`=<byte>
`hugepages_*`=<byte>
`memory`=<byte> |`node`=<node-address>
`resource`=<resource-name>
`unit`=<resource-unit>| STABLE | -| kube_node_status_allocatable | Gauge | The allocatable for different resources of a node that are available for scheduling | `cpu`=<core>
`ephemeral_storage`=<byte>
`pods`=<integer>
`attachable_volumes_*`=<byte>
`hugepages_*`=<byte>
`memory`=<byte> |`node`=<node-address>
`resource`=<resource-name>
`unit`=<resource-unit>| STABLE | +| kube_node_status_capacity | Gauge | The total amount of resources available for a node | `cpu`=<core>
`ephemeral_storage`=<byte>
`pods`=<integer>
`attachable_volumes_*`=<byte>
`hugepages_*`=<byte>
`memory`=<byte> |`node`=<node-address>
`resource`=<resource-name>
`unit`=<resource-unit>| STABLE | +| kube_node_status_allocatable | Gauge | The amount of resources allocatable for pods (after reserving some for system daemons) | `cpu`=<core>
`ephemeral_storage`=<byte>
`pods`=<integer>
`attachable_volumes_*`=<byte>
`hugepages_*`=<byte>
`memory`=<byte> |`node`=<node-address>
`resource`=<resource-name>
`unit`=<resource-unit>| STABLE | | kube_node_status_condition | Gauge | The condition of a cluster node | |`node`=<node-address>
`condition`=<node-condition>
`status`=<true\|false\|unknown> | STABLE | | kube_node_created | Gauge | Unix creation timestamp | seconds |`node`=<node-address>| STABLE | From ed551af5b5379e12d6db601d6946eb117d551ad8 Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Sun, 13 Nov 2022 00:10:14 +0530 Subject: [PATCH 39/70] Add node deletionTimestamp metric Adds deletionTimestamp metric, for nodes. Signed-off-by: Pranshu Srivastava --- docs/node-metrics.md | 1 + internal/store/node.go | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/docs/node-metrics.md b/docs/node-metrics.md index cc817caaa6..2ff3f1eab5 100644 --- a/docs/node-metrics.md +++ b/docs/node-metrics.md @@ -12,3 +12,4 @@ | kube_node_status_allocatable | Gauge | The allocatable for different resources of a node that are available for scheduling | `cpu`=<core>
`ephemeral_storage`=<byte>
`pods`=<integer>
`attachable_volumes_*`=<byte>
`hugepages_*`=<byte>
`memory`=<byte> |`node`=<node-address>
`resource`=<resource-name>
`unit`=<resource-unit>| STABLE | | kube_node_status_condition | Gauge | The condition of a cluster node | |`node`=<node-address>
`condition`=<node-condition>
`status`=<true\|false\|unknown> | STABLE | | kube_node_created | Gauge | Unix creation timestamp | seconds |`node`=<node-address>| STABLE | +| kube_node_deletion_timestamp | Gauge | Unix creation timestamp | seconds |`node`=<node-address>| STABLE | diff --git a/internal/store/node.go b/internal/store/node.go index 09ec39140c..51827c8765 100644 --- a/internal/store/node.go +++ b/internal/store/node.go @@ -44,9 +44,10 @@ var ( func nodeMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generator.FamilyGenerator { return []generator.FamilyGenerator{ + createNodeAnnotationsGenerator(allowAnnotationsList), createNodeCreatedFamilyGenerator(), + createNodeDeletionTimestampFamilyGenerator(), createNodeInfoFamilyGenerator(), - createNodeAnnotationsGenerator(allowAnnotationsList), createNodeLabelsGenerator(allowLabelsList), createNodeRoleFamilyGenerator(), createNodeSpecTaintFamilyGenerator(), @@ -57,6 +58,29 @@ func nodeMetricFamilies(allowAnnotationsList, allowLabelsList []string) []genera } } +func createNodeDeletionTimestampFamilyGenerator() generator.FamilyGenerator { + return *generator.NewFamilyGeneratorWithStability( + "kube_node_deletion_timestamp", + "Unix deletion timestamp", + metric.Gauge, + basemetrics.ALPHA, + "", + wrapNodeFunc(func(n *v1.Node) *metric.Family { + var ms []*metric.Metric + + if n.DeletionTimestamp != nil && !n.DeletionTimestamp.IsZero() { + ms = append(ms, &metric.Metric{ + Value: float64(n.DeletionTimestamp.Unix()), + }) + } + + return &metric.Family{ + Metrics: ms, + } + }), + ) +} + func createNodeCreatedFamilyGenerator() generator.FamilyGenerator { return *generator.NewFamilyGeneratorWithStability( "kube_node_created", From 5888a7eb3747220f650b39a849573aca42a52e39 Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Mon, 7 Nov 2022 02:38:35 +0530 Subject: [PATCH 40/70] Add --config flag --config flag defines the path to the kube-state-metrics options config file. --- pkg/options/options.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/options/options.go b/pkg/options/options.go index 2b3ce45528..93f3941286 100644 --- a/pkg/options/options.go +++ b/pkg/options/options.go @@ -45,8 +45,8 @@ type Options struct { TotalShards int Pod string Namespace string - MetricDenylist MetricSet - MetricAllowlist MetricSet + MetricDenylist MetricSet `yaml:"metric_denylist"` + MetricAllowlist MetricSet `yaml:"metric_allowlist"` MetricOptInList MetricSet Version bool AnnotationsAllowList LabelsAllowList @@ -60,6 +60,8 @@ type Options struct { CustomResourceConfigFile string CustomResourcesOnly bool + optsConfigFile string + cmd *cobra.Command } @@ -133,6 +135,7 @@ func (o *Options) AddFlags(cmd *cobra.Command) { o.cmd.Flags().StringVar(&o.Pod, "pod", "", "Name of the pod that contains the kube-state-metrics container. "+autoshardingNotice) o.cmd.Flags().StringVar(&o.TLSConfig, "tls-config", "", "Path to the TLS configuration file") o.cmd.Flags().StringVar(&o.TelemetryHost, "telemetry-host", "::", `Host to expose kube-state-metrics self metrics on.`) + o.cmd.Flags().StringVar(&o.optsConfigFile, "options-config-file", "", "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=[*]'.") From 9860f46776d268d3050539de44f0361611b9cac8 Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Mon, 7 Nov 2022 02:40:08 +0530 Subject: [PATCH 41/70] Implement hot-reloading based on config changes Reload KSM on-the-fly when a change is detected in the configuration. Meta changes (will squash) --- docs/cli-arguments.md | 1 + go.mod | 14 ++++- go.sum | 133 ++++++++++++++++++++++++++++++++++++++++- main.go | 39 ++++++++++-- pkg/app/server.go | 32 ++++++++++ pkg/options/options.go | 64 ++++++++++---------- 6 files changed, 245 insertions(+), 38 deletions(-) diff --git a/docs/cli-arguments.md b/docs/cli-arguments.md index bb81133d5d..67190c66b5 100644 --- a/docs/cli-arguments.md +++ b/docs/cli-arguments.md @@ -39,6 +39,7 @@ Flags: --add_dir_header If true, adds the file directory to the header of the log messages --alsologtostderr log to standard error as well as files (no effect when -logtostderr=true) --apiserver string The URL of the apiserver to use as a master + --config string Path to the kube-state-metrics options config file --custom-resource-state-config string Inline Custom Resource State Metrics config YAML (experimental) --custom-resource-state-config-file string Path to a Custom Resource State Metrics config file (experimental) --custom-resource-state-only Only provide Custom Resource State metrics (experimental) diff --git a/go.mod b/go.mod index 72d9598ab9..ac82fa58bb 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ require ( github.com/brancz/gojsontoyaml v0.1.0 github.com/campoy/embedmd v1.0.0 github.com/dgryski/go-jump v0.0.0-20211018200510-ba001c3ffce0 + github.com/fsnotify/fsnotify v1.5.4 github.com/gobuffalo/flect v0.3.0 github.com/google/go-cmp v0.5.9 github.com/google/go-jsonnet v0.19.1 @@ -15,6 +16,7 @@ require ( github.com/prometheus/exporter-toolkit v0.8.1 github.com/robfig/cron/v3 v3.0.1 github.com/spf13/cobra v1.6.1 + github.com/spf13/viper v1.13.0 github.com/stretchr/testify v1.8.1 golang.org/x/perf v0.0.0-20220920022801-e8d778a60d07 gopkg.in/yaml.v3 v3.0.1 @@ -29,7 +31,7 @@ require ( ) require ( - cloud.google.com/go v0.97.0 // indirect + cloud.google.com/go/compute v1.7.0 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest v0.11.27 // indirect github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect @@ -61,23 +63,32 @@ require ( github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/gofuzz v1.1.0 // indirect github.com/google/safehtml v0.0.2 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect github.com/imdario/mergo v0.3.6 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/magiconair/properties v1.8.6 // indirect github.com/mailru/easyjson v0.7.6 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect + github.com/spf13/afero v1.8.2 // indirect + github.com/spf13/cast v1.5.0 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.4.1 // indirect golang.org/x/crypto v0.0.0-20221012134737-56aed061732a // indirect golang.org/x/net v0.0.0-20220909164309-bea034e7d591 // indirect golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 // indirect @@ -90,6 +101,7 @@ require ( google.golang.org/protobuf v1.28.1 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect diff --git a/go.sum b/go.sum index 7ff8d1cf2f..83da795055 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,7 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -16,6 +17,7 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= @@ -25,16 +27,26 @@ cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWc cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0 h1:3DXvAyifywvq64LfkKaMOmkWPS1CikIQdMe2lY9vxU8= cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= +cloud.google.com/go/compute v1.7.0 h1:v/k9Eueb8aAJ0vZuxKMrgm6kPhCLZU9HxFU+AFDs9Uk= +cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -44,6 +56,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= @@ -107,7 +121,12 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-systemd/v22 v22.4.0 h1:y9YHcjnjynCd/DVbg5j9L/33jQM3MxJlbj/zWskzfGU= github.com/coreos/go-systemd/v22 v22.4.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -127,6 +146,8 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -135,6 +156,9 @@ github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= @@ -235,6 +259,8 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-jsonnet v0.19.1 h1:MORxkrG0elylUqh36R4AcSPX0oZQa9hvI3lroN+kDhs= @@ -255,6 +281,7 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= @@ -265,13 +292,22 @@ github.com/google/safehtml v0.0.2 h1:ZOt2VXg4x24bW0m2jtzAOkhoXV0iM8vNKc0paByCZqM github.com/google/safehtml v0.0.2/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/gax-go v0.0.0-20161107002406-da06d194a00e/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= @@ -299,6 +335,7 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -309,6 +346,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= @@ -324,6 +363,8 @@ github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGw github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -341,6 +382,10 @@ github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU= github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= +github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= @@ -349,6 +394,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -395,10 +441,18 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= +github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= +github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU= +github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -409,11 +463,14 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= +github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -433,7 +490,9 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20221012134737-56aed061732a h1:NmSIgad6KjE6VvHciPZuNRTKxGhlPfD6OA87W/PLkqg= golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -518,6 +577,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= @@ -527,6 +587,10 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI= golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/oauth2 v0.0.0-20170207211851-4464e7848382/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -545,7 +609,11 @@ golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 h1:lxqLZaMad/dJHMFZH0NiNpiEZI/nhgWhe4wgzpE+MuA= golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/perf v0.0.0-20220920022801-e8d778a60d07 h1:LhnzFL4oipoFsDvxTy2IJRHgOlnGzB2dE5l7C4PN7bg= @@ -561,6 +629,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -603,12 +672,14 @@ golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -620,8 +691,19 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -693,6 +775,7 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= @@ -703,6 +786,9 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= @@ -738,7 +824,18 @@ google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNe google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -783,10 +880,13 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= @@ -802,7 +902,29 @@ google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEc google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= google.golang.org/grpc v0.0.0-20170208002647-2a6bf6142e96/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -829,6 +951,12 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -843,6 +971,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= @@ -856,6 +985,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go index fdd5bcd582..fff30ed1b5 100644 --- a/main.go +++ b/main.go @@ -18,18 +18,21 @@ package main import ( "context" + "errors" "os" "path/filepath" "strings" + "time" + "github.com/fsnotify/fsnotify" "github.com/spf13/cobra" + "github.com/spf13/viper" "gopkg.in/yaml.v3" "k8s.io/klog/v2" "k8s.io/kube-state-metrics/v2/pkg/app" "k8s.io/kube-state-metrics/v2/pkg/customresource" "k8s.io/kube-state-metrics/v2/pkg/customresourcestate" - "k8s.io/kube-state-metrics/v2/pkg/options" ) @@ -63,11 +66,37 @@ func RunKubeStateMetricsWrapper(opts *options.Options) { factories = append(factories, crf...) } - ctx := context.Background() - if err := app.RunKubeStateMetrics(ctx, opts, factories...); err != nil { - klog.ErrorS(err, "Failed to run kube-state-metrics") - klog.FlushAndExit(klog.ExitFlushTimeout, 1) + KSMRunOrDie := func(ctx context.Context) { + if err := app.RunKubeStateMetricsWrapper(ctx, opts, factories...); err != nil { + klog.ErrorS(err, "Failed to run kube-state-metrics") + klog.FlushAndExit(klog.ExitFlushTimeout, 1) + } + } + ctx, cancel := context.WithCancel(context.Background()) + if file := options.GetOptsConfigFile(*opts); file != "" { + viper.SetConfigType("yaml") + viper.SetConfigFile(file) + if err := viper.ReadInConfig(); err != nil { + if errors.Is(err, viper.ConfigFileNotFoundError{}) { + klog.ErrorS(err, "Options configuration file not found", "file", file) + } else { + klog.ErrorS(err, "Error reading options configuration file", "file", file) + } + klog.FlushAndExit(klog.ExitFlushTimeout, 1) + } + viper.OnConfigChange(func(e fsnotify.Event) { + klog.Infof("Changes detected: %s\n", e.Name) + cancel() + // Wait for the ports to be released. + <-time.After(3 * time.Second) + ctx, cancel = context.WithCancel(context.Background()) + go KSMRunOrDie(ctx) + }) + viper.WatchConfig() } + klog.Infoln("Starting kube-state-metrics") + KSMRunOrDie(ctx) + select {} } func resolveCustomResourceConfig(opts *options.Options) (customresourcestate.ConfigDecoder, bool) { diff --git a/pkg/app/server.go b/pkg/app/server.go index 94b20a6ce4..29c8002d99 100644 --- a/pkg/app/server.go +++ b/pkg/app/server.go @@ -22,9 +22,13 @@ import ( "net" "net/http" "net/http/pprof" + "os" + "path/filepath" "strconv" "time" + "gopkg.in/yaml.v3" + "github.com/oklog/run" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/collectors" @@ -66,6 +70,16 @@ func (pl promLogger) Log(v ...interface{}) error { return nil } +// RunKubeStateMetricsWrapper runs KSM with context cancellation. +func RunKubeStateMetricsWrapper(ctx context.Context, opts *options.Options, factories ...customresource.RegistryFactory) error { + err := RunKubeStateMetrics(ctx, opts, factories...) + if ctx.Err() == context.Canceled { + klog.Infoln("Restarting: kube-state-metrics, metrics will be reset") + return nil + } + return err +} + // RunKubeStateMetrics will build and run the kube-state-metrics. // Any out-of-tree custom resource metrics could be registered by newing a registry factory // which implements customresource.RegistryFactory and pass all factories into this function. @@ -87,6 +101,24 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options, factories . ) storeBuilder.WithMetrics(ksmMetricsRegistry) + got := options.GetOptsConfigFile(*opts) + if got != "" { + optsConfigFile, err := os.ReadFile(filepath.Clean(got)) + if err != nil { + return fmt.Errorf("failed to read opts config file: %v", err) + } + // NOTE: Config value will override default values of intersecting options. + err = yaml.Unmarshal(optsConfigFile, opts) + if err != nil { + // DO NOT end the process. + // We want to allow the user to still be able to fix the misconfigured config (redeploy or edit the configmaps) and reload KSM automatically once that's done. + klog.Warningf("failed to unmarshal opts config file: %v", err) + // Wait for the next reload. + klog.Infof("misconfigured config detected, KSM will automatically reload on next write to the config") + klog.Infof("waiting for config to be fixed") + <-ctx.Done() + } + } var resources []string switch { case len(opts.Resources) == 0 && !opts.CustomResourcesOnly: diff --git a/pkg/options/options.go b/pkg/options/options.go index 93f3941286..97e91c6b89 100644 --- a/pkg/options/options.go +++ b/pkg/options/options.go @@ -29,42 +29,44 @@ import ( // Options are the configurable parameters for kube-state-metrics. type Options struct { - Apiserver string - Kubeconfig string - Help bool - Port int - Host string - TelemetryPort int - TelemetryHost string - TLSConfig string - Resources ResourceSet - Namespaces NamespaceList - NamespacesDenylist NamespaceList - Node NodeType - Shard int32 - TotalShards int - Pod string - Namespace string - MetricDenylist MetricSet `yaml:"metric_denylist"` - MetricAllowlist MetricSet `yaml:"metric_allowlist"` - MetricOptInList MetricSet - Version bool - AnnotationsAllowList LabelsAllowList - LabelsAllowList LabelsAllowList - - EnableGZIPEncoding bool - - UseAPIServerCache bool - - CustomResourceConfig string - CustomResourceConfigFile string - CustomResourcesOnly bool + AnnotationsAllowList LabelsAllowList `yaml:"annotations_allow_list"` + Apiserver string `yaml:"apiserver"` + CustomResourceConfig string `yaml:"custom_resource_config"` + CustomResourceConfigFile string `yaml:"custom_resource_config_file"` + CustomResourcesOnly bool `yaml:"custom_resources_only"` + EnableGZIPEncoding bool `yaml:"enable_gzip_encoding"` + Help bool `yaml:"help"` + Host string `yaml:"host"` + Kubeconfig string `yaml:"kubeconfig"` + LabelsAllowList LabelsAllowList `yaml:"labels_allow_list"` + MetricAllowlist MetricSet `yaml:"metric_allowlist"` + MetricDenylist MetricSet `yaml:"metric_denylist"` + MetricOptInList MetricSet `yaml:"metric_opt_in_list"` + Namespace string `yaml:"namespace"` + Namespaces NamespaceList `yaml:"namespaces"` + NamespacesDenylist NamespaceList `yaml:"namespaces_denylist"` + Node NodeType `yaml:"node"` + Pod string `yaml:"pod"` + Port int `yaml:"port"` + Resources ResourceSet `yaml:"resources"` + Shard int32 `yaml:"shard"` + TLSConfig string `yaml:"tls_config"` + TelemetryHost string `yaml:"telemetry_host"` + TelemetryPort int `yaml:"telemetry_port"` + TotalShards int `yaml:"total_shards"` + UseAPIServerCache bool `yaml:"use_api_server_cache"` + Version bool `yaml:"version"` optsConfigFile string cmd *cobra.Command } +// GetOptsConfigFile is the getter for --options-config-file value. +func GetOptsConfigFile(opt Options) string { + return opt.optsConfigFile +} + // NewOptions returns a new instance of `Options`. func NewOptions() *Options { return &Options{ @@ -135,7 +137,7 @@ func (o *Options) AddFlags(cmd *cobra.Command) { o.cmd.Flags().StringVar(&o.Pod, "pod", "", "Name of the pod that contains the kube-state-metrics container. "+autoshardingNotice) o.cmd.Flags().StringVar(&o.TLSConfig, "tls-config", "", "Path to the TLS configuration file") o.cmd.Flags().StringVar(&o.TelemetryHost, "telemetry-host", "::", `Host to expose kube-state-metrics self metrics on.`) - o.cmd.Flags().StringVar(&o.optsConfigFile, "options-config-file", "", "Path to the kube-state-metrics options config file") + o.cmd.Flags().StringVar(&o.optsConfigFile, "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=[*]'.") From f8360a890329d222990098a3d436dc2af556ee10 Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Wed, 16 Nov 2022 19:06:22 +0530 Subject: [PATCH 42/70] Add end-to-end testing to verify hot-reloading Add end-to-end testing to verify hot-reloading for event-based changes stemming from the config file. Also, * sent in a doc fix that was missed earlier: https://github.com/kubernetes/kube-state-metrics/pull/1890/files#diff-380eca5a922c0ddbf67f04daefc6823e7ef0e197434d3a826d39c7063cdfa6d6R15, * updated fsnotify and viper dependencies (v1.6.0 and v1.14.0 respectively). Signed-off-by: Pranshu Srivastava --- docs/node-metrics.md | 2 +- go.mod | 17 +-- go.sum | 230 +++-------------------------------- internal/wrapper.go | 96 +++++++++++++++ main.go | 76 +----------- pkg/options/options.go | 6 +- pkg/options/options_test.go | 14 ++- tests/e2e.sh | 3 +- tests/e2e/hot-reload_test.go | 116 ++++++++++++++++++ 9 files changed, 257 insertions(+), 303 deletions(-) create mode 100644 internal/wrapper.go create mode 100644 tests/e2e/hot-reload_test.go diff --git a/docs/node-metrics.md b/docs/node-metrics.md index 2ff3f1eab5..e9f1a336bf 100644 --- a/docs/node-metrics.md +++ b/docs/node-metrics.md @@ -12,4 +12,4 @@ | kube_node_status_allocatable | Gauge | The allocatable for different resources of a node that are available for scheduling | `cpu`=<core>
`ephemeral_storage`=<byte>
`pods`=<integer>
`attachable_volumes_*`=<byte>
`hugepages_*`=<byte>
`memory`=<byte> |`node`=<node-address>
`resource`=<resource-name>
`unit`=<resource-unit>| STABLE | | kube_node_status_condition | Gauge | The condition of a cluster node | |`node`=<node-address>
`condition`=<node-condition>
`status`=<true\|false\|unknown> | STABLE | | kube_node_created | Gauge | Unix creation timestamp | seconds |`node`=<node-address>| STABLE | -| kube_node_deletion_timestamp | Gauge | Unix creation timestamp | seconds |`node`=<node-address>| STABLE | +| kube_node_deletion_timestamp | Gauge | Unix creation timestamp | seconds |`node`=<node-address>| EXPERIMENTAL | diff --git a/go.mod b/go.mod index ac82fa58bb..e81a8fb889 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ require ( github.com/brancz/gojsontoyaml v0.1.0 github.com/campoy/embedmd v1.0.0 github.com/dgryski/go-jump v0.0.0-20211018200510-ba001c3ffce0 - github.com/fsnotify/fsnotify v1.5.4 + github.com/fsnotify/fsnotify v1.6.0 github.com/gobuffalo/flect v0.3.0 github.com/google/go-cmp v0.5.9 github.com/google/go-jsonnet v0.19.1 @@ -16,7 +16,7 @@ require ( github.com/prometheus/exporter-toolkit v0.8.1 github.com/robfig/cron/v3 v3.0.1 github.com/spf13/cobra v1.6.1 - github.com/spf13/viper v1.13.0 + github.com/spf13/viper v1.14.0 github.com/stretchr/testify v1.8.1 golang.org/x/perf v0.0.0-20220920022801-e8d778a60d07 gopkg.in/yaml.v3 v3.0.1 @@ -31,7 +31,8 @@ require ( ) require ( - cloud.google.com/go/compute v1.7.0 // indirect + cloud.google.com/go/compute v1.12.1 // indirect + cloud.google.com/go/compute/metadata v0.2.1 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest v0.11.27 // indirect github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect @@ -84,19 +85,19 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect - github.com/spf13/afero v1.8.2 // indirect + github.com/spf13/afero v1.9.2 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.4.1 // indirect golang.org/x/crypto v0.0.0-20221012134737-56aed061732a // indirect - golang.org/x/net v0.0.0-20220909164309-bea034e7d591 // indirect - golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 // indirect + golang.org/x/net v0.0.0-20221014081412-f15817d10f9b // indirect + golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.1.0 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect - golang.org/x/text v0.3.7 // indirect - golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect + golang.org/x/text v0.4.0 // indirect + golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect diff --git a/go.sum b/go.sum index 83da795055..fbec7954b7 100644 --- a/go.sum +++ b/go.sum @@ -18,35 +18,18 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/compute v1.7.0 h1:v/k9Eueb8aAJ0vZuxKMrgm6kPhCLZU9HxFU+AFDs9Uk= -cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= +cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0= +cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48= +cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -57,7 +40,6 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= @@ -79,7 +61,6 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190129172621-c8b1d7a94ddf/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= @@ -96,7 +77,6 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -110,7 +90,6 @@ github.com/brancz/gojsontoyaml v0.1.0/go.mod h1:+ycZY94+V11XZBUaDEsbLr3hPNS/ZPrD github.com/campoy/embedmd v1.0.0 h1:V4kI2qTJJLf4J29RzI/MAt2c3Bl4dQSYPuflzwFH2hY= github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -121,12 +100,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-systemd/v22 v22.4.0 h1:y9YHcjnjynCd/DVbg5j9L/33jQM3MxJlbj/zWskzfGU= github.com/coreos/go-systemd/v22 v22.4.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -144,10 +117,6 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -157,8 +126,8 @@ github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYF github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= @@ -217,8 +186,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -234,10 +201,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc= github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg= github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks= @@ -255,12 +220,8 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-jsonnet v0.19.1 h1:MORxkrG0elylUqh36R4AcSPX0oZQa9hvI3lroN+kDhs= @@ -271,7 +232,6 @@ github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -282,28 +242,15 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/safehtml v0.0.2 h1:ZOt2VXg4x24bW0m2jtzAOkhoXV0iM8vNKc0paByCZqM= github.com/google/safehtml v0.0.2/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/gax-go v0.0.0-20161107002406-da06d194a00e/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -427,7 +374,6 @@ github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5 github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= @@ -440,9 +386,8 @@ github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNX github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= -github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= +github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= @@ -451,8 +396,8 @@ github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmq github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU= -github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw= +github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU= +github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -475,15 +420,12 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -532,7 +474,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -543,7 +484,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -575,24 +515,15 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b h1:tvrvnPFcdzp294diPnrdZZZ8XUt2Tyj7svb7X52iDuU= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/oauth2 v0.0.0-20170207211851-4464e7848382/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -603,19 +534,10 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 h1:lxqLZaMad/dJHMFZH0NiNpiEZI/nhgWhe4wgzpE+MuA= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/perf v0.0.0-20220920022801-e8d778a60d07 h1:LhnzFL4oipoFsDvxTy2IJRHgOlnGzB2dE5l7C4PN7bg= golang.org/x/perf v0.0.0-20220920022801-e8d778a60d07/go.mod h1:UBKtEnL8aqnd+0JHqZ+2qoMDwtuy6cYhhKNoHLBiTQc= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -628,8 +550,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -671,40 +591,18 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -718,13 +616,14 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= +golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -777,18 +676,10 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= @@ -816,26 +707,6 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= -google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -867,7 +738,6 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= @@ -881,50 +751,7 @@ google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= google.golang.org/grpc v0.0.0-20170208002647-2a6bf6142e96/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -939,25 +766,9 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -970,8 +781,6 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= @@ -989,7 +798,6 @@ gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/internal/wrapper.go b/internal/wrapper.go new file mode 100644 index 0000000000..e40975cc4b --- /dev/null +++ b/internal/wrapper.go @@ -0,0 +1,96 @@ +/* +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 internal + +import ( + "context" + "errors" + "os" + "path/filepath" + "strings" + "time" + + "github.com/fsnotify/fsnotify" + "github.com/spf13/viper" + "gopkg.in/yaml.v3" + "k8s.io/klog/v2" + + "k8s.io/kube-state-metrics/v2/pkg/app" + "k8s.io/kube-state-metrics/v2/pkg/customresource" + "k8s.io/kube-state-metrics/v2/pkg/customresourcestate" + "k8s.io/kube-state-metrics/v2/pkg/options" +) + +// RunKubeStateMetricsWrapper is a wrapper around KSM, delegated to the root command. +func RunKubeStateMetricsWrapper(opts *options.Options) { + var factories []customresource.RegistryFactory + if config, set := resolveCustomResourceConfig(opts); set { + crf, err := customresourcestate.FromConfig(config) + if err != nil { + klog.ErrorS(err, "Parsing from Custom Resource State Metrics file failed") + klog.FlushAndExit(klog.ExitFlushTimeout, 1) + } + factories = append(factories, crf...) + } + + KSMRunOrDie := func(ctx context.Context) { + if err := app.RunKubeStateMetricsWrapper(ctx, opts, factories...); err != nil { + klog.ErrorS(err, "Failed to run kube-state-metrics") + klog.FlushAndExit(klog.ExitFlushTimeout, 1) + } + } + ctx, cancel := context.WithCancel(context.Background()) + if file := options.GetOptsConfigFile(*opts); file != "" { + viper.SetConfigType("yaml") + viper.SetConfigFile(file) + if err := viper.ReadInConfig(); err != nil { + if errors.Is(err, viper.ConfigFileNotFoundError{}) { + klog.ErrorS(err, "Options configuration file not found", "file", file) + } else { + klog.ErrorS(err, "Error reading options configuration file", "file", file) + } + klog.FlushAndExit(klog.ExitFlushTimeout, 1) + } + viper.OnConfigChange(func(e fsnotify.Event) { + klog.Infof("Changes detected: %s\n", e.Name) + cancel() + // Wait for the ports to be released. + <-time.After(3 * time.Second) + ctx, cancel = context.WithCancel(context.Background()) + go KSMRunOrDie(ctx) + }) + viper.WatchConfig() + } + klog.Infoln("Starting kube-state-metrics") + KSMRunOrDie(ctx) + select {} +} + +func resolveCustomResourceConfig(opts *options.Options) (customresourcestate.ConfigDecoder, bool) { + if s := opts.CustomResourceConfig; s != "" { + return yaml.NewDecoder(strings.NewReader(s)), true + } + if file := opts.CustomResourceConfigFile; file != "" { + f, err := os.Open(filepath.Clean(file)) + if err != nil { + klog.ErrorS(err, "Custom Resource State Metrics file could not be opened") + klog.FlushAndExit(klog.ExitFlushTimeout, 1) + } + return yaml.NewDecoder(f), true + } + return nil, false +} diff --git a/main.go b/main.go index fff30ed1b5..04fdad5a68 100644 --- a/main.go +++ b/main.go @@ -17,22 +17,10 @@ limitations under the License. package main import ( - "context" - "errors" - "os" - "path/filepath" - "strings" - "time" - - "github.com/fsnotify/fsnotify" "github.com/spf13/cobra" - "github.com/spf13/viper" - "gopkg.in/yaml.v3" "k8s.io/klog/v2" - "k8s.io/kube-state-metrics/v2/pkg/app" - "k8s.io/kube-state-metrics/v2/pkg/customresource" - "k8s.io/kube-state-metrics/v2/pkg/customresourcestate" + "k8s.io/kube-state-metrics/v2/internal" "k8s.io/kube-state-metrics/v2/pkg/options" ) @@ -40,7 +28,7 @@ func main() { opts := options.NewOptions() cmd := options.InitCommand cmd.Run = func(cmd *cobra.Command, args []string) { - RunKubeStateMetricsWrapper(opts) + internal.RunKubeStateMetricsWrapper(opts) } opts.AddFlags(cmd) @@ -53,63 +41,3 @@ func main() { klog.FlushAndExit(klog.ExitFlushTimeout, 1) } } - -// RunKubeStateMetricsWrapper is a wrapper around KSM, delegated to the root command. -func RunKubeStateMetricsWrapper(opts *options.Options) { - var factories []customresource.RegistryFactory - if config, set := resolveCustomResourceConfig(opts); set { - crf, err := customresourcestate.FromConfig(config) - if err != nil { - klog.ErrorS(err, "Parsing from Custom Resource State Metrics file failed") - klog.FlushAndExit(klog.ExitFlushTimeout, 1) - } - factories = append(factories, crf...) - } - - KSMRunOrDie := func(ctx context.Context) { - if err := app.RunKubeStateMetricsWrapper(ctx, opts, factories...); err != nil { - klog.ErrorS(err, "Failed to run kube-state-metrics") - klog.FlushAndExit(klog.ExitFlushTimeout, 1) - } - } - ctx, cancel := context.WithCancel(context.Background()) - if file := options.GetOptsConfigFile(*opts); file != "" { - viper.SetConfigType("yaml") - viper.SetConfigFile(file) - if err := viper.ReadInConfig(); err != nil { - if errors.Is(err, viper.ConfigFileNotFoundError{}) { - klog.ErrorS(err, "Options configuration file not found", "file", file) - } else { - klog.ErrorS(err, "Error reading options configuration file", "file", file) - } - klog.FlushAndExit(klog.ExitFlushTimeout, 1) - } - viper.OnConfigChange(func(e fsnotify.Event) { - klog.Infof("Changes detected: %s\n", e.Name) - cancel() - // Wait for the ports to be released. - <-time.After(3 * time.Second) - ctx, cancel = context.WithCancel(context.Background()) - go KSMRunOrDie(ctx) - }) - viper.WatchConfig() - } - klog.Infoln("Starting kube-state-metrics") - KSMRunOrDie(ctx) - select {} -} - -func resolveCustomResourceConfig(opts *options.Options) (customresourcestate.ConfigDecoder, bool) { - if s := opts.CustomResourceConfig; s != "" { - return yaml.NewDecoder(strings.NewReader(s)), true - } - if file := opts.CustomResourceConfigFile; file != "" { - f, err := os.Open(filepath.Clean(file)) - if err != nil { - klog.ErrorS(err, "Custom Resource State Metrics file could not be opened") - klog.FlushAndExit(klog.ExitFlushTimeout, 1) - } - return yaml.NewDecoder(f), true - } - return nil, false -} diff --git a/pkg/options/options.go b/pkg/options/options.go index 97e91c6b89..95b726048a 100644 --- a/pkg/options/options.go +++ b/pkg/options/options.go @@ -57,14 +57,14 @@ type Options struct { UseAPIServerCache bool `yaml:"use_api_server_cache"` Version bool `yaml:"version"` - optsConfigFile string + Config string cmd *cobra.Command } // GetOptsConfigFile is the getter for --options-config-file value. func GetOptsConfigFile(opt Options) string { - return opt.optsConfigFile + return opt.Config } // NewOptions returns a new instance of `Options`. @@ -137,7 +137,7 @@ func (o *Options) AddFlags(cmd *cobra.Command) { o.cmd.Flags().StringVar(&o.Pod, "pod", "", "Name of the pod that contains the kube-state-metrics container. "+autoshardingNotice) o.cmd.Flags().StringVar(&o.TLSConfig, "tls-config", "", "Path to the TLS configuration file") o.cmd.Flags().StringVar(&o.TelemetryHost, "telemetry-host", "::", `Host to expose kube-state-metrics self metrics on.`) - o.cmd.Flags().StringVar(&o.optsConfigFile, "config", "", "Path to the kube-state-metrics options config file") + 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=[*]'.") diff --git a/pkg/options/options_test.go b/pkg/options/options_test.go index beb5d79191..0e17c0c5a8 100644 --- a/pkg/options/options_test.go +++ b/pkg/options/options_test.go @@ -48,14 +48,18 @@ func TestOptionsParse(t *testing.T) { opts.AddFlags(InitCommand) for _, test := range tests { + t.Run(test.Desc, func(t *testing.T) { + os.Args = test.Args - os.Args = test.Args + err := opts.Parse() - err := opts.Parse() - if err != nil { - if !test.ExpectsError { + if !test.ExpectsError && err != nil { t.Errorf("Error for test with description: %s: %v", test.Desc, err.Error()) } - } + + if test.ExpectsError && err == nil { + t.Errorf("Expected error for test with description: %s", test.Desc) + } + }) } } diff --git a/tests/e2e.sh b/tests/e2e.sh index 83fa77a3cf..6381b7d8db 100755 --- a/tests/e2e.sh +++ b/tests/e2e.sh @@ -155,7 +155,8 @@ echo "kube-state-metrics is up and running" echo "start e2e test for kube-state-metrics" KSM_HTTP_METRICS_URL='http://localhost:8001/api/v1/namespaces/kube-system/services/kube-state-metrics:http-metrics/proxy' KSM_TELEMETRY_URL='http://localhost:8001/api/v1/namespaces/kube-system/services/kube-state-metrics:telemetry/proxy' -go test -v ./tests/e2e/ --ksm-http-metrics-url=${KSM_HTTP_METRICS_URL} --ksm-telemetry-url=${KSM_TELEMETRY_URL} +go test -v ./tests/e2e/main_test.go --ksm-http-metrics-url=${KSM_HTTP_METRICS_URL} --ksm-telemetry-url=${KSM_TELEMETRY_URL} +go test -v ./tests/e2e/hot-reload_test.go mkdir -p ${KUBE_STATE_METRICS_LOG_DIR} diff --git a/tests/e2e/hot-reload_test.go b/tests/e2e/hot-reload_test.go new file mode 100644 index 0000000000..c5d099b58d --- /dev/null +++ b/tests/e2e/hot-reload_test.go @@ -0,0 +1,116 @@ +/* +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 e2e + +import ( + "net" + "os" + "testing" + "time" + + "k8s.io/apimachinery/pkg/util/wait" + + "k8s.io/kube-state-metrics/v2/internal" + "k8s.io/kube-state-metrics/v2/pkg/options" +) + +func TestConfigHotReload(t *testing.T) { + + // Initialise options. + opts := options.NewOptions() + cmd := options.InitCommand + opts.AddFlags(cmd) + + // Create testdata. + f, err := os.CreateTemp("", "config") + if err != nil { + t.Fatal(err) + } + + // Delete artefacts. + defer func() { + err := os.Remove(opts.Config) + if err != nil { + t.Fatalf("failed to remove config file: %v", err) + } + }() + + // Populate options. + opts.Config = f.Name() + + // Assume $HOME is always defined. + opts.Kubeconfig = os.Getenv("HOME") + "/.kube/config" + + // Run general validation on options. + if err := opts.Parse(); err != nil { + t.Fatalf("failed to parse options: %v", err) + } + + // Make the process asynchronous. + go internal.RunKubeStateMetricsWrapper(opts) + + // Wait for port 8080 to come up. + err = wait.PollImmediate(1*time.Second, 20*time.Second, func() (bool, error) { + conn, err := net.Dial("tcp", "localhost:8080") + if err != nil { + return false, nil + } + err = conn.Close() + if err != nil { + return false, err + } + return true, nil + }) + if err != nil { + t.Fatalf("failed to wait for port 8080 to come up for the first time: %v", err) + } + + // Modify config to trigger hot reload. + config := `foo: "bar"` + err = os.WriteFile(opts.Config, []byte(config), 0600 /* rw------- */) + if err != nil { + t.Fatalf("failed to write config file: %v", err) + } + + // Wait for port 8080 to come up. + ch := make(chan bool, 1) + err = wait.PollImmediate(1*time.Second, 20*time.Second, func() (bool, error) { + conn, err := net.Dial("tcp", "localhost:8080") + if err != nil { + return false, nil + } + err = conn.Close() + if err != nil { + return false, err + } + return true, nil + }) + if err != nil { + t.Fatalf("failed to wait for port 8080 to come up after restarting the process: %v", err) + } + + // Indicate that the test has passed. + ch <- true + + // Wait for process to exit. + select { + case <-ch: + t.Log("test passed successfully") + case <-time.After(20 * time.Second): + t.Fatal("timed out waiting for test to pass, check the logs for more info") + } +} From cc0fd00cf7e468c9ec14849063c920d0f055d77a Mon Sep 17 00:00:00 2001 From: Damien Grisonnet Date: Tue, 22 Nov 2022 11:30:48 +0100 Subject: [PATCH 43/70] Add rexagod as reviewer Signed-off-by: Damien Grisonnet --- OWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/OWNERS b/OWNERS index c5ce828386..0e0b1930f4 100644 --- a/OWNERS +++ b/OWNERS @@ -3,6 +3,7 @@ reviewers: - fpetkovski - logicalhan - mrueg + - rexagod approvers: - dgrisonnet - fpetkovski From 4abefe268a2b6abb1e01eb2916ac19897a3b9fd1 Mon Sep 17 00:00:00 2001 From: Kaito Ii Date: Sun, 20 Nov 2022 22:22:27 +0900 Subject: [PATCH 44/70] add ingress class metrics --- docs/README.md | 1 + docs/ingressclass-metrics.md | 8 ++ examples/autosharding/cluster-role.yaml | 1 + examples/standard/cluster-role.yaml | 1 + internal/store/builder.go | 5 + internal/store/ingressclass.go | 134 ++++++++++++++++++ internal/store/ingressclass_test.go | 105 ++++++++++++++ .../kube-state-metrics.libsonnet | 1 + tests/manifests/ingress.yaml | 2 +- tests/manifests/ingressclass.yaml | 8 ++ 10 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 docs/ingressclass-metrics.md create mode 100644 internal/store/ingressclass.go create mode 100644 internal/store/ingressclass_test.go create mode 100644 tests/manifests/ingressclass.yaml diff --git a/docs/README.md b/docs/README.md index 617c28f39e..6e5e48e074 100644 --- a/docs/README.md +++ b/docs/README.md @@ -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) diff --git a/docs/ingressclass-metrics.md b/docs/ingressclass-metrics.md new file mode 100644 index 0000000000..1be511d350 --- /dev/null +++ b/docs/ingressclass-metrics.md @@ -0,0 +1,8 @@ +# IngressClass Metrics + +| Metric name| Metric type | Labels/tags | Status | +| ---------- | ----------- | ----------- | ----------- | +| kube_ingressclass_annotations | Gauge | `ingressclass`=<ingressclass-name>
`annotation_INGRESSCLASS_ANNOTATION`=<INGRESSCLASS_ANNOTATION> | EXPERIMENTAL | +| kube_ingressclass_info | Gauge | `ingressclass`=<ingressclass-name>
`controller`=<ingress-controller-name>
| STABLE | +| kube_ingressclass_labels | Gauge | `ingressclass`=<ingressclass-name>
`label_INGRESSCLASS_LABEL`=<INGRESSCLASS_LABEL> | STABLE | +| kube_ingressclass_created | Gauge | `ingressclass`=<ingressclass-name> | STABLE | diff --git a/examples/autosharding/cluster-role.yaml b/examples/autosharding/cluster-role.yaml index 2a54e60129..235ed7f570 100644 --- a/examples/autosharding/cluster-role.yaml +++ b/examples/autosharding/cluster-role.yaml @@ -97,6 +97,7 @@ rules: - networking.k8s.io resources: - networkpolicies + - ingressclasses - ingresses verbs: - list diff --git a/examples/standard/cluster-role.yaml b/examples/standard/cluster-role.yaml index 2a54e60129..235ed7f570 100644 --- a/examples/standard/cluster-role.yaml +++ b/examples/standard/cluster-role.yaml @@ -97,6 +97,7 @@ rules: - networking.k8s.io resources: - networkpolicies + - ingressclasses - ingresses verbs: - list diff --git a/internal/store/builder.go b/internal/store/builder.go index 11dbca14ba..35786cdaf5 100644 --- a/internal/store/builder.go +++ b/internal/store/builder.go @@ -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() }, @@ -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["ingressclass"], b.allowLabelsList["ingressclass"]), &networkingv1.IngressClass{}, createIngressClassListWatch, b.useAPIServerCache) +} + func (b *Builder) buildStores( metricFamilies []generator.FamilyGenerator, expectedType interface{}, diff --git a/internal/store/ingressclass.go b/internal/store/ingressclass.go new file mode 100644 index 0000000000..f86a3180d3 --- /dev/null +++ b/internal/store/ingressclass.go @@ -0,0 +1,134 @@ +/* +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" + + "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.NewFamilyGenerator( + "kube_ingressclass_info", + "Information about ingressclass.", + metric.Gauge, + "", + 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.NewFamilyGenerator( + "kube_ingressclass_created", + "Unix creation timestamp", + metric.Gauge, + "", + 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.NewFamilyGenerator( + descIngressClassAnnotationsName, + descIngressClassAnnotationsHelp, + metric.Gauge, + "", + 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.NewFamilyGenerator( + descIngressClassLabelsName, + descIngressClassLabelsHelp, + metric.Gauge, + "", + 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) + }, + } +} diff --git a/internal/store/ingressclass_test.go b/internal/store/ingressclass_test.go new file mode 100644 index 0000000000..50312d0ca3 --- /dev/null +++ b/internal/store/ingressclass_test.go @@ -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) + } + } +} diff --git a/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet b/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet index 44ff393ebc..2275c7b584 100644 --- a/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet +++ b/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet @@ -134,6 +134,7 @@ apiGroups: ['networking.k8s.io'], resources: [ 'networkpolicies', + 'ingressclasses', 'ingresses', ], verbs: ['list', 'watch'], diff --git a/tests/manifests/ingress.yaml b/tests/manifests/ingress.yaml index 05428277e1..7e35f7e343 100644 --- a/tests/manifests/ingress.yaml +++ b/tests/manifests/ingress.yaml @@ -1,4 +1,4 @@ -apiVersion: networking.k8s.io/v1 +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress diff --git a/tests/manifests/ingressclass.yaml b/tests/manifests/ingressclass.yaml new file mode 100644 index 0000000000..95a5aa1278 --- /dev/null +++ b/tests/manifests/ingressclass.yaml @@ -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 From 278426995e0515a25bb72409a2dd9460d7a5a31a Mon Sep 17 00:00:00 2001 From: Kaito Ii Date: Thu, 24 Nov 2022 00:07:56 +0900 Subject: [PATCH 45/70] add ingress classs as nondefault resource --- tests/e2e/main_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/e2e/main_test.go b/tests/e2e/main_test.go index d01fb99f26..4f9d08e86e 100644 --- a/tests/e2e/main_test.go +++ b/tests/e2e/main_test.go @@ -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, From 07af191fe54d216743ec330cf11ccd0d0d4caeab Mon Sep 17 00:00:00 2001 From: Kaito Ii Date: Thu, 24 Nov 2022 00:54:58 +0900 Subject: [PATCH 46/70] add stability experimental --- docs/ingressclass-metrics.md | 6 +++--- internal/store/ingressclass.go | 13 +++++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/docs/ingressclass-metrics.md b/docs/ingressclass-metrics.md index 1be511d350..f9fade6171 100644 --- a/docs/ingressclass-metrics.md +++ b/docs/ingressclass-metrics.md @@ -3,6 +3,6 @@ | Metric name| Metric type | Labels/tags | Status | | ---------- | ----------- | ----------- | ----------- | | kube_ingressclass_annotations | Gauge | `ingressclass`=<ingressclass-name>
`annotation_INGRESSCLASS_ANNOTATION`=<INGRESSCLASS_ANNOTATION> | EXPERIMENTAL | -| kube_ingressclass_info | Gauge | `ingressclass`=<ingressclass-name>
`controller`=<ingress-controller-name>
| STABLE | -| kube_ingressclass_labels | Gauge | `ingressclass`=<ingressclass-name>
`label_INGRESSCLASS_LABEL`=<INGRESSCLASS_LABEL> | STABLE | -| kube_ingressclass_created | Gauge | `ingressclass`=<ingressclass-name> | STABLE | +| kube_ingressclass_info | Gauge | `ingressclass`=<ingressclass-name>
`controller`=<ingress-controller-name>
| EXPERIMENTAL | +| kube_ingressclass_labels | Gauge | `ingressclass`=<ingressclass-name>
`label_INGRESSCLASS_LABEL`=<INGRESSCLASS_LABEL> | EXPERIMENTAL| +| kube_ingressclass_created | Gauge | `ingressclass`=<ingressclass-name> | EXPERIMENTAL| diff --git a/internal/store/ingressclass.go b/internal/store/ingressclass.go index f86a3180d3..9a433c3c22 100644 --- a/internal/store/ingressclass.go +++ b/internal/store/ingressclass.go @@ -16,6 +16,7 @@ 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" @@ -37,10 +38,11 @@ var ( func ingressClassMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generator.FamilyGenerator { return []generator.FamilyGenerator{ - *generator.NewFamilyGenerator( + *generator.NewFamilyGeneratorWithStability( "kube_ingressclass_info", "Information about ingressclass.", metric.Gauge, + basemetrics.ALPHA, "", wrapIngressClassFunc(func(s *networkingv1.IngressClass) *metric.Family { @@ -52,10 +54,11 @@ func ingressClassMetricFamilies(allowAnnotationsList, allowLabelsList []string) return &metric.Family{Metrics: []*metric.Metric{&m}} }), ), - *generator.NewFamilyGenerator( + *generator.NewFamilyGeneratorWithStability( "kube_ingressclass_created", "Unix creation timestamp", metric.Gauge, + basemetrics.ALPHA, "", wrapIngressClassFunc(func(s *networkingv1.IngressClass) *metric.Family { ms := []*metric.Metric{} @@ -69,10 +72,11 @@ func ingressClassMetricFamilies(allowAnnotationsList, allowLabelsList []string) } }), ), - *generator.NewFamilyGenerator( + *generator.NewFamilyGeneratorWithStability( descIngressClassAnnotationsName, descIngressClassAnnotationsHelp, metric.Gauge, + basemetrics.ALPHA, "", wrapIngressClassFunc(func(s *networkingv1.IngressClass) *metric.Family { annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", s.Annotations, allowAnnotationsList) @@ -87,10 +91,11 @@ func ingressClassMetricFamilies(allowAnnotationsList, allowLabelsList []string) } }), ), - *generator.NewFamilyGenerator( + *generator.NewFamilyGeneratorWithStability( descIngressClassLabelsName, descIngressClassLabelsHelp, metric.Gauge, + basemetrics.ALPHA, "", wrapIngressClassFunc(func(s *networkingv1.IngressClass) *metric.Family { labelKeys, labelValues := createPrometheusLabelKeysValues("label", s.Labels, allowLabelsList) From 8f27e707603a41f983f794956f6b163e6f263acb Mon Sep 17 00:00:00 2001 From: JoaoBraveCoding Date: Mon, 21 Nov 2022 14:59:49 +0000 Subject: [PATCH 47/70] autoscaling/v2beta2 HorizontalPodAutoscaler is deprecated in v1.23+ Issue: https://github.com/kubernetes/kube-state-metrics/issues/1711 Problem: kube-state-metrics supports up to (latest k8s release - 3) k8s version. Since v1.25 has been release we can update it to start using autoscaler/v2. Solution: update packages to start using autoscaler/v2 Signed-off-by: JoaoBraveCoding --- internal/store/builder.go | 2 +- internal/store/horizontalpodautoscaler.go | 6 +++--- internal/store/horizontalpodautoscaler_test.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/store/builder.go b/internal/store/builder.go index 11dbca14ba..adb4e73a03 100644 --- a/internal/store/builder.go +++ b/internal/store/builder.go @@ -27,7 +27,7 @@ import ( "github.com/prometheus/client_golang/prometheus" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" appsv1 "k8s.io/api/apps/v1" - autoscaling "k8s.io/api/autoscaling/v2beta2" + autoscaling "k8s.io/api/autoscaling/v2" batchv1 "k8s.io/api/batch/v1" certv1 "k8s.io/api/certificates/v1" coordinationv1 "k8s.io/api/coordination/v1" diff --git a/internal/store/horizontalpodautoscaler.go b/internal/store/horizontalpodautoscaler.go index 3f9ba17595..57300f1641 100644 --- a/internal/store/horizontalpodautoscaler.go +++ b/internal/store/horizontalpodautoscaler.go @@ -19,7 +19,7 @@ package store import ( "context" - autoscaling "k8s.io/api/autoscaling/v2beta2" + autoscaling "k8s.io/api/autoscaling/v2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" @@ -351,11 +351,11 @@ func createHPAListWatch(kubeClient clientset.Interface, ns string, fieldSelector return &cache.ListWatch{ ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { opts.FieldSelector = fieldSelector - return kubeClient.AutoscalingV2beta2().HorizontalPodAutoscalers(ns).List(context.TODO(), opts) + return kubeClient.AutoscalingV2().HorizontalPodAutoscalers(ns).List(context.TODO(), opts) }, WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { opts.FieldSelector = fieldSelector - return kubeClient.AutoscalingV2beta2().HorizontalPodAutoscalers(ns).Watch(context.TODO(), opts) + return kubeClient.AutoscalingV2().HorizontalPodAutoscalers(ns).Watch(context.TODO(), opts) }, } } diff --git a/internal/store/horizontalpodautoscaler_test.go b/internal/store/horizontalpodautoscaler_test.go index 9f462fc4dc..85c7f51b2b 100644 --- a/internal/store/horizontalpodautoscaler_test.go +++ b/internal/store/horizontalpodautoscaler_test.go @@ -19,7 +19,7 @@ package store import ( "testing" - autoscaling "k8s.io/api/autoscaling/v2beta2" + autoscaling "k8s.io/api/autoscaling/v2" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" From 991857ccb530e93fe2dd97d6874afa5b56f4abd3 Mon Sep 17 00:00:00 2001 From: Kaito Ii Date: Thu, 24 Nov 2022 22:29:01 +0900 Subject: [PATCH 48/70] Update internal/store/builder.go Co-authored-by: Damien Grisonnet --- internal/store/builder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/store/builder.go b/internal/store/builder.go index 35786cdaf5..31d6b30d11 100644 --- a/internal/store/builder.go +++ b/internal/store/builder.go @@ -472,7 +472,7 @@ func (b *Builder) buildRoleBindingStores() []cache.Store { } func (b *Builder) buildIngressClassStores() []cache.Store { - return b.buildStoresFunc(ingressClassMetricFamilies(b.allowAnnotationsList["ingressclass"], b.allowLabelsList["ingressclass"]), &networkingv1.IngressClass{}, createIngressClassListWatch, b.useAPIServerCache) + return b.buildStoresFunc(ingressClassMetricFamilies(b.allowAnnotationsList["ingressclasses"], b.allowLabelsList["ingressclasses"]), &networkingv1.IngressClass{}, createIngressClassListWatch, b.useAPIServerCache) } func (b *Builder) buildStores( From df2d8f1c0e629fa7a6925780b4b43970159f8625 Mon Sep 17 00:00:00 2001 From: Kaito Ii Date: Thu, 24 Nov 2022 22:50:14 +0900 Subject: [PATCH 49/70] fix linter error --- internal/store/ingressclass.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/store/ingressclass.go b/internal/store/ingressclass.go index 9a433c3c22..3e67881ef0 100644 --- a/internal/store/ingressclass.go +++ b/internal/store/ingressclass.go @@ -17,6 +17,7 @@ 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" From 820741d4d48fe7ac325120bedb3fc5272dc75cac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Mon, 21 Nov 2022 15:10:12 +0100 Subject: [PATCH 50/70] go.mod: Update dependencies --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index e81a8fb889..a9a00e4cc6 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/google/go-jsonnet v0.19.1 github.com/jsonnet-bundler/jsonnet-bundler v0.5.1 github.com/oklog/run v1.1.0 - github.com/prometheus/client_golang v1.13.1 + github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.3.0 github.com/prometheus/common v0.37.0 github.com/prometheus/exporter-toolkit v0.8.1 @@ -20,13 +20,13 @@ require ( github.com/stretchr/testify v1.8.1 golang.org/x/perf v0.0.0-20220920022801-e8d778a60d07 gopkg.in/yaml.v3 v3.0.1 - k8s.io/api v0.25.3 - k8s.io/apimachinery v0.25.3 + k8s.io/api v0.25.4 + k8s.io/apimachinery v0.25.4 k8s.io/autoscaler/vertical-pod-autoscaler v0.12.0 - k8s.io/client-go v0.25.3 - k8s.io/component-base v0.25.3 + k8s.io/client-go v0.25.4 + k8s.io/component-base v0.25.4 k8s.io/klog/v2 v2.80.1 - k8s.io/sample-controller v0.25.3 + k8s.io/sample-controller v0.25.4 k8s.io/utils v0.0.0-20221101230645-61b03e2f6476 ) diff --git a/go.sum b/go.sum index fbec7954b7..7152424ed6 100644 --- a/go.sum +++ b/go.sum @@ -349,8 +349,8 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.1 h1:3gMjIY2+/hzmqhtUC/aQNYldJA6DtH3CgQvwS+02K1c= -github.com/prometheus/client_golang v1.13.1/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -816,22 +816,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.25.3 h1:Q1v5UFfYe87vi5H7NU0p4RXC26PPMT8KOpr1TLQbCMQ= -k8s.io/api v0.25.3/go.mod h1:o42gKscFrEVjHdQnyRenACrMtbuJsVdP+WVjqejfzmI= -k8s.io/apimachinery v0.25.3 h1:7o9ium4uyUOM76t6aunP0nZuex7gDf8VGwkR5RcJnQc= -k8s.io/apimachinery v0.25.3/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo= +k8s.io/api v0.25.4 h1:3YO8J4RtmG7elEgaWMb4HgmpS2CfY1QlaOz9nwB+ZSs= +k8s.io/api v0.25.4/go.mod h1:IG2+RzyPQLllQxnhzD8KQNEu4c4YvyDTpSMztf4A0OQ= +k8s.io/apimachinery v0.25.4 h1:CtXsuaitMESSu339tfhVXhQrPET+EiWnIY1rcurKnAc= +k8s.io/apimachinery v0.25.4/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo= k8s.io/autoscaler/vertical-pod-autoscaler v0.12.0 h1:cy8LoXSl5GkTNJDTx3ZCS143f9Ai7gqnGkoUxPlGSmI= k8s.io/autoscaler/vertical-pod-autoscaler v0.12.0/go.mod h1:LraL5kR2xX7jb4VMCG6/tUH4I75uRHlnzC0VWQHcyWk= -k8s.io/client-go v0.25.3 h1:oB4Dyl8d6UbfDHD8Bv8evKylzs3BXzzufLiO27xuPs0= -k8s.io/client-go v0.25.3/go.mod h1:t39LPczAIMwycjcXkVc+CB+PZV69jQuNx4um5ORDjQA= -k8s.io/component-base v0.25.3 h1:UrsxciGdrCY03ULT1h/S/gXFCOPnLhUVwSyx+hM/zq4= -k8s.io/component-base v0.25.3/go.mod h1:WYoS8L+IlTZgU7rhAl5Ctpw0WdMxDfCC5dkxcEFa/TI= +k8s.io/client-go v0.25.4 h1:3RNRDffAkNU56M/a7gUfXaEzdhZlYhoW8dgViGy5fn8= +k8s.io/client-go v0.25.4/go.mod h1:8trHCAC83XKY0wsBIpbirZU4NTUpbuhc2JnI7OruGZw= +k8s.io/component-base v0.25.4 h1:n1bjg9Yt+G1C0WnIDJmg2fo6wbEU1UGMRiQSjmj7hNQ= +k8s.io/component-base v0.25.4/go.mod h1:nnZJU8OP13PJEm6/p5V2ztgX2oyteIaAGKGMYb2L2cY= k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA= k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= -k8s.io/sample-controller v0.25.3 h1:6abaENCl89Kl+/4tW+SOq18HnZhEd7L4rf9H6VjUTCk= -k8s.io/sample-controller v0.25.3/go.mod h1:73CRRrRusGH3xNcC35ZlzGrZDpbvBzInWD53AaIwat4= +k8s.io/sample-controller v0.25.4 h1:DWOuUMa3qHAP/734F75hSyMtGQrojodwGuEdrirzw9A= +k8s.io/sample-controller v0.25.4/go.mod h1:uaKn9T3EHfpgJA2uuDadTpr/zyZywWsIibNgAzByF8U= k8s.io/utils v0.0.0-20221101230645-61b03e2f6476 h1:L14f2LWkOxG2rYsuSA3ltQnnST1vMfek/GUk+VemxD4= k8s.io/utils v0.0.0-20221101230645-61b03e2f6476/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= From 095bf79b11de218535e7f4b4fadb294cae60e498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Mon, 14 Nov 2022 23:00:50 +0100 Subject: [PATCH 51/70] *: Cut v2.7.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Rüger --- CHANGELOG.md | 33 +++++++++++++++++++ README.md | 3 +- VERSION | 2 +- .../autosharding/cluster-role-binding.yaml | 2 +- examples/autosharding/cluster-role.yaml | 2 +- examples/autosharding/role-binding.yaml | 2 +- examples/autosharding/role.yaml | 2 +- examples/autosharding/service-account.yaml | 2 +- examples/autosharding/service.yaml | 2 +- examples/autosharding/statefulset.yaml | 6 ++-- examples/standard/cluster-role-binding.yaml | 2 +- examples/standard/cluster-role.yaml | 2 +- examples/standard/deployment.yaml | 6 ++-- examples/standard/service-account.yaml | 2 +- examples/standard/service.yaml | 2 +- 15 files changed, 52 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e773ba66c2..c9ea168675 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,36 @@ +## v2.7.0 / 2022-11-25 + +Note: Experimental VerticalPodAutoscaler metrics are considered deprecated in this release and will be removed in v2.9.0. +Please use CustomResourceStateMetrics to gather metrics from VPA resources. See: #1718 + +Note: Experimental CustomResourceState changed their naming convention for better usability. +The name of the CRD used to be interpolated into the name of the metric which made it impossible to aggregate a CRD across different versions. +This was changed to have the GVK information represented as labels: +kube_myteam_io_v1_Foo_uptime -> kube_crd_uptime{group="myteam.io", kind="Foo", version="v1"} +See: #1847 + +* [CHANGE] Deprecate VerticalPodAutoscaler metrics #1835 @rexagod +* [CHANGE] Recommend kube-scheduler metrics for container resource limits and requests #1849 @rexagod +* [FEATURE] Add experimental kube_pod_container_status_last_terminated_exitcode metric #1752 @ssabo +* [FEATURE] Introduce custom-resources-only flag #1813 @bavarianbidi +* [FEATURE] Allow allowlist filtering by wildcard key #1823 @rexagod +* [FEATURE] Add ContainerResourceSourceType to hpa spec and target metrics #1831 @whitebear009 +* [FEATURE] Represent group, version and kind of a resource as labels #1850 @rexagod +* [FEATURE] Sharding metrics per node via fieldSelector #1864 @CatherineF-dev +* [FEATURE] Add experimental StatefulSet retention policy metrics #1876 @mattcary +* [FEATURE] Allow labelFromKey field for all applicable metric types #1880 @rexagod +* [FEATURE] Introduce Viper, allow hot-reload on config change #1827 @rexagod +* [FEATURE] Introduce Cobra, allow configuration via environment variables #1834 @rexagod +* [FEATURE] Add experimental kube_node_deletion_timestamp metric #1890 @rexagod +* [FEATURE] Support autoscaling/v2 resources for HorizontalPodAutoscaler #1906 @JoaoBraveCoding +* [FEATURE] Add IngressClass metrics #1905 @kaitoii11 +* [ENHANCEMENT] Import Kubernetes metrics stability framework #1844 @CatherineF-dev +* [ENHANCEMENT] Promote kube_pod_container_status_waiting_reason and kube_deployment_status_replicas_ready to stable #1821 @CatherineF-dev +* [ENHANCEMENT] Build with Kubernetes 1.25 and go 1.19 #1819 @mrueg +* [BUGFIX] Handle singular labels in allowlist #1826 @rexagod +* [BUGFIX] Do not expose ingress path metric when service is nil #1841 @evir35 +* [BUGFIX] Allow lease metrics to be exported across all namespaces #1845 @lantingchiang + ## v2.6.0 / 2022-08-26 * [FEATURE] Add local storage labels to kube_persistentvolume_info #1814 @nabokihms * [FEATURE] Add support for StateSet and Info metrics for Custom-Resource State #1777 @chrischdi diff --git a/README.md b/README.md index f4991cff27..2eaf634f6e 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,7 @@ Generally, it is recommended to use the latest release of kube-state-metrics. If | **v2.4.2** | v1.23 | | **v2.5.0** | v1.24 | | **v2.6.0** | v1.24 | +| **v2.7.0** | v1.25 | | **master** | v1.25 | @@ -88,7 +89,7 @@ release. #### Container Image The latest container image can be found at: -* `registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.6.0` (arch: `amd64`, `arm`, `arm64`, `ppc64le` and `s390x`) +* `registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.7.0` (arch: `amd64`, `arm`, `arm64`, `ppc64le` and `s390x`) ### Metrics Documentation diff --git a/VERSION b/VERSION index e70b4523ae..24ba9a38de 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.6.0 +2.7.0 diff --git a/examples/autosharding/cluster-role-binding.yaml b/examples/autosharding/cluster-role-binding.yaml index d9e76e28fd..72764789f8 100644 --- a/examples/autosharding/cluster-role-binding.yaml +++ b/examples/autosharding/cluster-role-binding.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.6.0 + app.kubernetes.io/version: 2.7.0 name: kube-state-metrics roleRef: apiGroup: rbac.authorization.k8s.io diff --git a/examples/autosharding/cluster-role.yaml b/examples/autosharding/cluster-role.yaml index 235ed7f570..ac5436f7f1 100644 --- a/examples/autosharding/cluster-role.yaml +++ b/examples/autosharding/cluster-role.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.6.0 + app.kubernetes.io/version: 2.7.0 name: kube-state-metrics rules: - apiGroups: diff --git a/examples/autosharding/role-binding.yaml b/examples/autosharding/role-binding.yaml index a64631035d..1cb7521df6 100644 --- a/examples/autosharding/role-binding.yaml +++ b/examples/autosharding/role-binding.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.6.0 + app.kubernetes.io/version: 2.7.0 name: kube-state-metrics namespace: kube-system roleRef: diff --git a/examples/autosharding/role.yaml b/examples/autosharding/role.yaml index 940cc16b90..9bca941ad2 100644 --- a/examples/autosharding/role.yaml +++ b/examples/autosharding/role.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.6.0 + app.kubernetes.io/version: 2.7.0 name: kube-state-metrics namespace: kube-system rules: diff --git a/examples/autosharding/service-account.yaml b/examples/autosharding/service-account.yaml index 23501a2eb4..8d6dc8e84d 100644 --- a/examples/autosharding/service-account.yaml +++ b/examples/autosharding/service-account.yaml @@ -5,6 +5,6 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.6.0 + app.kubernetes.io/version: 2.7.0 name: kube-state-metrics namespace: kube-system diff --git a/examples/autosharding/service.yaml b/examples/autosharding/service.yaml index c81f81ea3d..2c41087009 100644 --- a/examples/autosharding/service.yaml +++ b/examples/autosharding/service.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.6.0 + app.kubernetes.io/version: 2.7.0 name: kube-state-metrics namespace: kube-system spec: diff --git a/examples/autosharding/statefulset.yaml b/examples/autosharding/statefulset.yaml index 4190b81477..605d4e541d 100644 --- a/examples/autosharding/statefulset.yaml +++ b/examples/autosharding/statefulset.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.6.0 + app.kubernetes.io/version: 2.7.0 name: kube-state-metrics namespace: kube-system spec: @@ -18,7 +18,7 @@ spec: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.6.0 + app.kubernetes.io/version: 2.7.0 spec: automountServiceAccountToken: true containers: @@ -34,7 +34,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.6.0 + image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.7.0 livenessProbe: httpGet: path: /healthz diff --git a/examples/standard/cluster-role-binding.yaml b/examples/standard/cluster-role-binding.yaml index d9e76e28fd..72764789f8 100644 --- a/examples/standard/cluster-role-binding.yaml +++ b/examples/standard/cluster-role-binding.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.6.0 + app.kubernetes.io/version: 2.7.0 name: kube-state-metrics roleRef: apiGroup: rbac.authorization.k8s.io diff --git a/examples/standard/cluster-role.yaml b/examples/standard/cluster-role.yaml index 235ed7f570..ac5436f7f1 100644 --- a/examples/standard/cluster-role.yaml +++ b/examples/standard/cluster-role.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.6.0 + app.kubernetes.io/version: 2.7.0 name: kube-state-metrics rules: - apiGroups: diff --git a/examples/standard/deployment.yaml b/examples/standard/deployment.yaml index a059056979..bcb18be1df 100644 --- a/examples/standard/deployment.yaml +++ b/examples/standard/deployment.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.6.0 + app.kubernetes.io/version: 2.7.0 name: kube-state-metrics namespace: kube-system spec: @@ -17,11 +17,11 @@ spec: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.6.0 + app.kubernetes.io/version: 2.7.0 spec: automountServiceAccountToken: true containers: - - image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.6.0 + - image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.7.0 livenessProbe: httpGet: path: /healthz diff --git a/examples/standard/service-account.yaml b/examples/standard/service-account.yaml index 23501a2eb4..8d6dc8e84d 100644 --- a/examples/standard/service-account.yaml +++ b/examples/standard/service-account.yaml @@ -5,6 +5,6 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.6.0 + app.kubernetes.io/version: 2.7.0 name: kube-state-metrics namespace: kube-system diff --git a/examples/standard/service.yaml b/examples/standard/service.yaml index c81f81ea3d..2c41087009 100644 --- a/examples/standard/service.yaml +++ b/examples/standard/service.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.6.0 + app.kubernetes.io/version: 2.7.0 name: kube-state-metrics namespace: kube-system spec: From b4b8c23b972423e10d6037d52a649ff21b9d023c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Fri, 25 Nov 2022 01:37:57 +0100 Subject: [PATCH 52/70] Add Metrics for EndpointSlices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements https://pkg.go.dev/k8s.io/api/discovery/v1#EndpointSlice This resourcetype is disabled by default as they are very verbose and have a high cardinality. Metrics from endpointslices can be used to identify if specific pods are part of an endpoint and thus discoverable through a service. Signed-off-by: Manuel Rüger --- docs/README.md | 1 + docs/endpointslice-metrics.md | 10 + examples/autosharding/cluster-role.yaml | 7 + examples/standard/cluster-role.yaml | 7 + internal/store/builder.go | 6 + internal/store/endpointslice.go | 234 ++++++++++++++++++ internal/store/endpointslice_test.go | 161 ++++++++++++ .../kube-state-metrics.libsonnet | 7 + tests/e2e/main_test.go | 1 + tests/manifests/endpointslice.yaml | 13 + 10 files changed, 447 insertions(+) create mode 100644 docs/endpointslice-metrics.md create mode 100644 internal/store/endpointslice.go create mode 100644 internal/store/endpointslice_test.go create mode 100644 tests/manifests/endpointslice.yaml diff --git a/docs/README.md b/docs/README.md index 6e5e48e074..a6f6840f30 100644 --- a/docs/README.md +++ b/docs/README.md @@ -65,6 +65,7 @@ See each file for specific documentation about the exposed metrics: - [ClusterRole Metrics](clusterrole-metrics.md) - [ClusterRoleBinding Metrics](clusterrolebinding-metrics.md) +- [EndpointSlice Metrics](endpointslice-metrics.md) - [IngressClass Metrics](ingressclass-metrics.md) - [Role Metrics](role-metrics.md) - [RoleBinding Metrics](rolebinding-metrics.md) diff --git a/docs/endpointslice-metrics.md b/docs/endpointslice-metrics.md new file mode 100644 index 0000000000..f2327a5265 --- /dev/null +++ b/docs/endpointslice-metrics.md @@ -0,0 +1,10 @@ +# Endpoint Metrics + +| Metric name| Metric type | Labels/tags | Status | +| ---------- | ----------- | ----------- | ----------- | +| kube_endpointslice_annotations | Gauge | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace>
`annotation_ENDPOINTSLICE_ANNOTATION`=<ENDPOINTSLICE_ANNOTATION> | EXPERIMENTAL | +| kube_endpointslice_info | Gauge | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace> | EXPERIMENTAL | +| kube_endpointslice_ports | Gauge | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace>
`port_name`=<endpointslice-port-name>
`port_protocol`=<endpointslice-port-protocol>
`port_number`=<endpointslice-port-number> | EXPERIMENTAL | +| kube_endpointslice_endpoints | Gauge | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace>
`ready`=<endpointslice-ready>
`serving`=<endpointslice-serving>
`terminating`=<endpointslice-terminating>
`hostname`=<endpointslice-hostname>
`targetref_kind`=<endpointslice-targetref-kind>
`targetref_name`=<endpointslice-targetref-name>
`targetref_namespace`=<endpointslice-targetref-namespace>
`nodename`=<endpointslice-nodename>
`endpoint_zone`=<endpointslice-zone> | EXPERIMENTAL | +| kube_endpointslice_labels | Gauge | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace>
`label_ENDPOINTSLICE_LABEL`=<ENDPOINTSLICE_LABEL> | EXPERIMENTAL | +| kube_endpointslice_created | Gauge | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace> | EXPERIMENTAL | diff --git a/examples/autosharding/cluster-role.yaml b/examples/autosharding/cluster-role.yaml index ac5436f7f1..e20db08235 100644 --- a/examples/autosharding/cluster-role.yaml +++ b/examples/autosharding/cluster-role.yaml @@ -77,6 +77,13 @@ rules: verbs: - list - watch +- apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch - apiGroups: - storage.k8s.io resources: diff --git a/examples/standard/cluster-role.yaml b/examples/standard/cluster-role.yaml index ac5436f7f1..e20db08235 100644 --- a/examples/standard/cluster-role.yaml +++ b/examples/standard/cluster-role.yaml @@ -77,6 +77,13 @@ rules: verbs: - list - watch +- apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - list + - watch - apiGroups: - storage.k8s.io resources: diff --git a/internal/store/builder.go b/internal/store/builder.go index df00ed496d..9f58933e6f 100644 --- a/internal/store/builder.go +++ b/internal/store/builder.go @@ -32,6 +32,7 @@ import ( certv1 "k8s.io/api/certificates/v1" coordinationv1 "k8s.io/api/coordination/v1" v1 "k8s.io/api/core/v1" + discoveryv1 "k8s.io/api/discovery/v1" networkingv1 "k8s.io/api/networking/v1" policyv1 "k8s.io/api/policy/v1" rbacv1 "k8s.io/api/rbac/v1" @@ -293,6 +294,7 @@ var availableStores = map[string]func(f *Builder) []cache.Store{ "daemonsets": func(b *Builder) []cache.Store { return b.buildDaemonSetStores() }, "deployments": func(b *Builder) []cache.Store { return b.buildDeploymentStores() }, "endpoints": func(b *Builder) []cache.Store { return b.buildEndpointsStores() }, + "endpointslices": func(b *Builder) []cache.Store { return b.buildEndpointSlicesStores() }, "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() }, @@ -355,6 +357,10 @@ func (b *Builder) buildEndpointsStores() []cache.Store { return b.buildStoresFunc(endpointMetricFamilies(b.allowAnnotationsList["endpoints"], b.allowLabelsList["endpoints"]), &v1.Endpoints{}, createEndpointsListWatch, b.useAPIServerCache) } +func (b *Builder) buildEndpointSlicesStores() []cache.Store { + return b.buildStoresFunc(endpointSliceMetricFamilies(b.allowAnnotationsList["endpointslices"], b.allowLabelsList["endpointslices"]), &discoveryv1.EndpointSlice{}, createEndpointSliceListWatch, b.useAPIServerCache) +} + func (b *Builder) buildHPAStores() []cache.Store { return b.buildStoresFunc(hpaMetricFamilies(b.allowAnnotationsList["horizontalpodautoscalers"], b.allowLabelsList["horizontalpodautoscalers"]), &autoscaling.HorizontalPodAutoscaler{}, createHPAListWatch, b.useAPIServerCache) } diff --git a/internal/store/endpointslice.go b/internal/store/endpointslice.go new file mode 100644 index 0000000000..0b01284468 --- /dev/null +++ b/internal/store/endpointslice.go @@ -0,0 +1,234 @@ +/* +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" + "strconv" + + basemetrics "k8s.io/component-base/metrics" + + "k8s.io/kube-state-metrics/v2/pkg/metric" + generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" + + discoveryv1 "k8s.io/api/discovery/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 ( + descEndpointSliceAnnotationsName = "kube_endpointslice_annotations" + descEndpointSliceAnnotationsHelp = "Kubernetes annotations converted to Prometheus labels." + descEndpointSliceLabelsName = "kube_endpointslice_labels" + descEndpointSliceLabelsHelp = "Kubernetes labels converted to Prometheus labels." + descEndpointSliceLabelsDefaultLabels = []string{"endpointslice"} +) + +func endpointSliceMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generator.FamilyGenerator { + return []generator.FamilyGenerator{ + *generator.NewFamilyGeneratorWithStability( + "kube_endpointslice_info", + "Information about endpointslice.", + metric.Gauge, + basemetrics.ALPHA, + "", + wrapEndpointSliceFunc(func(s *discoveryv1.EndpointSlice) *metric.Family { + + m := metric.Metric{ + LabelKeys: []string{"addresstype"}, + LabelValues: []string{string(s.AddressType)}, + Value: 1, + } + return &metric.Family{Metrics: []*metric.Metric{&m}} + }), + ), + *generator.NewFamilyGeneratorWithStability( + "kube_endpointslice_created", + "Unix creation timestamp", + metric.Gauge, + basemetrics.ALPHA, + "", + wrapEndpointSliceFunc(func(s *discoveryv1.EndpointSlice) *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( + "kube_endpointslice_endpoints", + "Endpoints attached to the endpointslice.", + metric.Gauge, + basemetrics.ALPHA, + "", + wrapEndpointSliceFunc(func(e *discoveryv1.EndpointSlice) *metric.Family { + m := []*metric.Metric{} + for _, ep := range e.Endpoints { + var ( + labelKeys, + labelValues []string + ) + + if ep.Conditions.Ready != nil { + labelKeys = append(labelKeys, "ready") + labelValues = append(labelValues, strconv.FormatBool(*ep.Conditions.Ready)) + } + if ep.Conditions.Serving != nil { + labelKeys = append(labelKeys, "serving") + labelValues = append(labelValues, strconv.FormatBool(*ep.Conditions.Serving)) + } + if ep.Conditions.Terminating != nil { + labelKeys = append(labelKeys, "terminating") + labelValues = append(labelValues, strconv.FormatBool(*ep.Conditions.Terminating)) + } + + if ep.Hostname != nil { + labelKeys = append(labelKeys, "hostname") + labelValues = append(labelValues, *ep.Hostname) + } + + if ep.TargetRef != nil { + if ep.TargetRef.Kind != "" { + labelKeys = append(labelKeys, "targetref_kind") + labelValues = append(labelValues, ep.TargetRef.Kind) + } + if ep.TargetRef.Name != "" { + labelKeys = append(labelKeys, "targetref_name") + labelValues = append(labelValues, ep.TargetRef.Name) + } + if ep.TargetRef.Namespace != "" { + labelKeys = append(labelKeys, "targetref_namespace") + labelValues = append(labelValues, ep.TargetRef.Namespace) + } + } + + if ep.NodeName != nil { + labelKeys = append(labelKeys, "endpoint_nodename") + labelValues = append(labelValues, *ep.NodeName) + } + + if ep.Zone != nil { + labelKeys = append(labelKeys, "endpoint_zone") + labelValues = append(labelValues, *ep.Zone) + } + labelKeys = append(labelKeys, "address") + for _, address := range ep.Addresses { + newlabelValues := make([]string, len(labelValues)) + copy(newlabelValues, labelValues) + m = append(m, &metric.Metric{ + LabelKeys: labelKeys, + LabelValues: append(newlabelValues, address), + Value: 1, + }) + } + } + return &metric.Family{ + Metrics: m, + } + }), + ), + + *generator.NewFamilyGeneratorWithStability( + "kube_endpointslice_ports", + "Ports attached to the endpointslice.", + metric.Gauge, + basemetrics.ALPHA, + "", + wrapEndpointSliceFunc(func(e *discoveryv1.EndpointSlice) *metric.Family { + m := []*metric.Metric{} + for _, port := range e.Ports { + m = append(m, &metric.Metric{ + LabelValues: []string{*port.Name, string(*port.Protocol), strconv.FormatInt(int64(*port.Port), 10)}, + LabelKeys: []string{"port_name", "port_protocol", "port_number"}, + Value: 1, + }) + } + return &metric.Family{ + Metrics: m, + } + }), + ), + *generator.NewFamilyGeneratorWithStability( + descEndpointSliceAnnotationsName, + descEndpointSliceAnnotationsHelp, + metric.Gauge, + basemetrics.ALPHA, + "", + wrapEndpointSliceFunc(func(s *discoveryv1.EndpointSlice) *metric.Family { + annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", s.Annotations, allowAnnotationsList) + return &metric.Family{ + Metrics: []*metric.Metric{ + { + LabelKeys: annotationKeys, + LabelValues: annotationValues, + Value: 1, + }, + }, + } + }), + ), + *generator.NewFamilyGeneratorWithStability( + descEndpointSliceLabelsName, + descEndpointSliceLabelsHelp, + metric.Gauge, + basemetrics.ALPHA, + "", + wrapEndpointSliceFunc(func(s *discoveryv1.EndpointSlice) *metric.Family { + labelKeys, labelValues := createPrometheusLabelKeysValues("label", s.Labels, allowLabelsList) + return &metric.Family{ + Metrics: []*metric.Metric{ + { + LabelKeys: labelKeys, + LabelValues: labelValues, + Value: 1, + }, + }, + } + }), + ), + } +} + +func wrapEndpointSliceFunc(f func(*discoveryv1.EndpointSlice) *metric.Family) func(interface{}) *metric.Family { + return func(obj interface{}) *metric.Family { + endpointSlice := obj.(*discoveryv1.EndpointSlice) + + metricFamily := f(endpointSlice) + + for _, m := range metricFamily.Metrics { + m.LabelKeys, m.LabelValues = mergeKeyValues(descEndpointSliceLabelsDefaultLabels, []string{endpointSlice.Name}, m.LabelKeys, m.LabelValues) + } + + return metricFamily + } +} + +func createEndpointSliceListWatch(kubeClient clientset.Interface, ns string, fieldSelector string) cache.ListerWatcher { + return &cache.ListWatch{ + ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { + return kubeClient.DiscoveryV1().EndpointSlices(ns).List(context.TODO(), opts) + }, + WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { + return kubeClient.DiscoveryV1().EndpointSlices(ns).Watch(context.TODO(), opts) + }, + } +} diff --git a/internal/store/endpointslice_test.go b/internal/store/endpointslice_test.go new file mode 100644 index 0000000000..cca8638cd9 --- /dev/null +++ b/internal/store/endpointslice_test.go @@ -0,0 +1,161 @@ +/* +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" + + corev1 "k8s.io/api/core/v1" + discoveryv1 "k8s.io/api/discovery/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" +) + +func TestEndpointSliceStore(t *testing.T) { + startTime := 1501569018 + metav1StartTime := metav1.Unix(int64(startTime), 0) + portname := "http" + portnumber := int32(80) + portprotocol := corev1.Protocol("TCP") + nodename := "node" + hostname := "host" + zone := "west" + ready := true + terminating := false + addresses := []string{"10.0.0.1", "192.168.1.10"} + + cases := []generateMetricsTestCase{ + { + Obj: &discoveryv1.EndpointSlice{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test_endpointslice-info", + }, + AddressType: "IPv4", + }, + Want: ` + # HELP kube_endpointslice_info Information about endpointslice. + # TYPE kube_endpointslice_info gauge + kube_endpointslice_info{endpointslice="test_endpointslice-info",addresstype="IPv4"} 1 + `, + MetricNames: []string{ + "kube_endpointslice_info", + }, + }, + { + Obj: &discoveryv1.EndpointSlice{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test_kube_endpointslice-created", + CreationTimestamp: metav1StartTime, + }, + AddressType: "IPv4", + }, + Want: ` + # HELP kube_endpointslice_created Unix creation timestamp + # TYPE kube_endpointslice_created gauge + kube_endpointslice_created{endpointslice="test_kube_endpointslice-created"} 1.501569018e+09 + `, + MetricNames: []string{ + "kube_endpointslice_created", + }, + }, + { + Obj: &discoveryv1.EndpointSlice{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test_endpointslice-ports", + }, + AddressType: "IPv4", + Ports: []discoveryv1.EndpointPort{ + {Name: &portname, + Port: &portnumber, + Protocol: &portprotocol, + }, + }, + }, + Want: ` + # HELP kube_endpointslice_ports Ports attached to the endpointslice. + # TYPE kube_endpointslice_ports gauge + kube_endpointslice_ports{endpointslice="test_endpointslice-ports",port_name="http",port_protocol="TCP",port_number="80"} 1 + `, + MetricNames: []string{ + "kube_endpointslice_ports", + }, + }, + { + Obj: &discoveryv1.EndpointSlice{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test_endpointslice-endpoints", + }, + AddressType: "IPv4", + Endpoints: []discoveryv1.Endpoint{ + { + NodeName: &nodename, + Conditions: discoveryv1.EndpointConditions{ + Ready: &ready, + Terminating: &terminating, + }, + Hostname: &hostname, + Zone: &zone, + Addresses: addresses, + }, + }, + }, + Want: ` + # HELP kube_endpointslice_endpoints Endpoints attached to the endpointslice. + # TYPE kube_endpointslice_endpoints gauge + kube_endpointslice_endpoints{address="10.0.0.1",endpoint_nodename="node",endpoint_zone="west",endpointslice="test_endpointslice-endpoints",hostname="host",ready="true",terminating="false"} 1 + kube_endpointslice_endpoints{address="192.168.1.10",endpoint_nodename="node",endpoint_zone="west",endpointslice="test_endpointslice-endpoints",hostname="host",ready="true",terminating="false"} 1 + `, + + MetricNames: []string{ + "kube_endpointslice_endpoints", + }, + }, + { + AllowAnnotationsList: []string{ + "foo", + }, + Obj: &discoveryv1.EndpointSlice{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test_endpointslice-labels", + Annotations: map[string]string{ + "foo": "baz", + }, + Labels: map[string]string{ + "foo": "bar", + }, + }, + AddressType: "IPv4", + }, + Want: ` + # HELP kube_endpointslice_annotations Kubernetes annotations converted to Prometheus labels. + # HELP kube_endpointslice_labels Kubernetes labels converted to Prometheus labels. + # 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", + }, + }, + } + for i, c := range cases { + c.Func = generator.ComposeMetricGenFuncs(endpointSliceMetricFamilies(c.AllowAnnotationsList, nil)) + c.Headers = generator.ExtractMetricFamilyHeaders(endpointSliceMetricFamilies(c.AllowAnnotationsList, nil)) + if err := c.run(); err != nil { + t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) + } + } +} diff --git a/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet b/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet index 2275c7b584..d562d02c3b 100644 --- a/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet +++ b/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet @@ -114,6 +114,13 @@ ], verbs: ['list', 'watch'], }, + { + apiGroups: ['discovery.k8s.io'], + resources: [ + 'endpointslices', + ], + verbs: ['list', 'watch'], + }, { apiGroups: ['storage.k8s.io'], resources: [ diff --git a/tests/e2e/main_test.go b/tests/e2e/main_test.go index 4f9d08e86e..d0880a3261 100644 --- a/tests/e2e/main_test.go +++ b/tests/e2e/main_test.go @@ -256,6 +256,7 @@ func TestDefaultCollectorMetricsAvailable(t *testing.T) { nonDefaultResources := map[string]bool{ "clusterrole": true, "clusterrolebinding": true, + "endpointslice": true, "ingressclass": true, "role": true, "rolebinding": true, diff --git a/tests/manifests/endpointslice.yaml b/tests/manifests/endpointslice.yaml new file mode 100644 index 0000000000..078e67f2bb --- /dev/null +++ b/tests/manifests/endpointslice.yaml @@ -0,0 +1,13 @@ +apiVersion: discovery.k8s.io/v1 +kind: EndpointSlice +metadata: + name: example-endpointslice + namespace: default +addressType: IPv4 +endpoints: +- addresses: + - 10.0.0.2 + conditions: + ready: true + serving: true + terminating: false From af833dd387cb0e6115722cfe02608447af92a26c Mon Sep 17 00:00:00 2001 From: Damien Grisonnet Date: Tue, 29 Nov 2022 14:47:17 +0100 Subject: [PATCH 53/70] Add CatherineF-dev as reviewer Signed-off-by: Damien Grisonnet --- OWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/OWNERS b/OWNERS index 0e0b1930f4..11dcc5a67c 100644 --- a/OWNERS +++ b/OWNERS @@ -1,4 +1,5 @@ reviewers: + - CatherineF-dev - dgrisonnet - fpetkovski - logicalhan From 8b1016485ac08f3417349c5c99fac1e7be60038b Mon Sep 17 00:00:00 2001 From: Simon Pasquier Date: Wed, 30 Nov 2022 15:55:48 +0100 Subject: [PATCH 54/70] Update github.com/prometheus/exporter-toolkit The latest version (v0.8.2) fixes CVE-2022-46146. Signed-off-by: Simon Pasquier --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a9a00e4cc6..c268e182d7 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.3.0 github.com/prometheus/common v0.37.0 - github.com/prometheus/exporter-toolkit v0.8.1 + github.com/prometheus/exporter-toolkit v0.8.2 github.com/robfig/cron/v3 v3.0.1 github.com/spf13/cobra v1.6.1 github.com/spf13/viper v1.14.0 diff --git a/go.sum b/go.sum index 7152424ed6..220caf7a9d 100644 --- a/go.sum +++ b/go.sum @@ -363,8 +363,8 @@ github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9 github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/exporter-toolkit v0.8.1 h1:TpKt8z55q1zF30BYaZKqh+bODY0WtByHDOhDA2M9pEs= -github.com/prometheus/exporter-toolkit v0.8.1/go.mod h1:00shzmJL7KxcsabLWcONwpyNEuWhREOnFqZW7vadFS0= +github.com/prometheus/exporter-toolkit v0.8.2 h1:sbJAfBXQFkG6sUkbwBun8MNdzW9+wd5YfPYofbmj0YM= +github.com/prometheus/exporter-toolkit v0.8.2/go.mod h1:00shzmJL7KxcsabLWcONwpyNEuWhREOnFqZW7vadFS0= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= From ee891760b8a9fbd53666094f08c74b8be20082f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Tue, 29 Nov 2022 19:59:18 +0100 Subject: [PATCH 55/70] Add metrics for config file changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This uses code pieces from prometheus/alertmanager in https://github.com/prometheus/alertmanager/blob/main/config/coordinator.go#LL56C26-L56C26 licensed under Apache-2.0. kube_state_metrics_config_hash{type="config", filename="config.yml"} 4.0061079457904e+13 kube_state_metrics_config_last_reload_success_timestamp_seconds{type="config", filename="config.yml"} 1.6697483049487052e+09 kube_state_metrics_config_last_reload_successful{type="config", filename="config.yml"} 1 Signed-off-by: Manuel Rüger --- README.md | 8 ++++++++ internal/wrapper.go | 2 +- pkg/app/server.go | 41 ++++++++++++++++++++++++++++++++++++++--- pkg/options/options.go | 4 ++-- 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 2eaf634f6e..73e679666e 100644 --- a/README.md +++ b/README.md @@ -165,6 +165,14 @@ please check the blog post [here](https://www.robustperception.io/exposing-the-s Sharding metrics expose `--shard` and `--total-shards` flags and can be used to validate run-time configuration, see [`/examples/prometheus-alerting-rules`](./examples/prometheus-alerting-rules). +kube-state-metrics also exposes metrics about it config file: + +``` +kube_state_metrics_config_hash{type="config", filename="config.yml"} 4.0061079457904e+13 +kube_state_metrics_config_last_reload_success_timestamp_seconds{type="config", filename="config.yml"} 1.6697483049487052e+09 +kube_state_metrics_config_last_reload_successful{type="config", filename="config.yml"} 1 +``` + ### Scaling kube-state-metrics #### Resource recommendation diff --git a/internal/wrapper.go b/internal/wrapper.go index e40975cc4b..65db430363 100644 --- a/internal/wrapper.go +++ b/internal/wrapper.go @@ -54,7 +54,7 @@ func RunKubeStateMetricsWrapper(opts *options.Options) { } } ctx, cancel := context.WithCancel(context.Background()) - if file := options.GetOptsConfigFile(*opts); file != "" { + if file := options.GetConfigFile(*opts); file != "" { viper.SetConfigType("yaml") viper.SetConfigFile(file) if err := viper.ReadInConfig(); err != nil { diff --git a/pkg/app/server.go b/pkg/app/server.go index 29c8002d99..e9dc75e0ec 100644 --- a/pkg/app/server.go +++ b/pkg/app/server.go @@ -18,6 +18,8 @@ package app import ( "context" + "crypto/md5" //nolint:gosec + "encoding/binary" "fmt" "net" "net/http" @@ -99,16 +101,32 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options, factories . ConstLabels: prometheus.Labels{"handler": "metrics"}, }, []string{"method"}, ) + configHash := promauto.With(ksmMetricsRegistry).NewGaugeVec( + prometheus.GaugeOpts{ + Name: "kube_state_metrics_config_hash", + Help: "Hash of the currently loaded configuration.", + }, []string{"type", "filename"}) + configSuccess := promauto.With(ksmMetricsRegistry).NewGaugeVec( + prometheus.GaugeOpts{ + Name: "kube_state_metrics_last_config_reload_successful", + Help: "Whether the last configuration reload attempt was successful.", + }, []string{"type", "filename"}) + configSuccessTime := promauto.With(ksmMetricsRegistry).NewGaugeVec( + prometheus.GaugeOpts{ + Name: "kube_state_metrics_last_config_reload_success_timestamp_seconds", + Help: "Timestamp of the last successful configuration reload.", + }, []string{"type", "filename"}) + storeBuilder.WithMetrics(ksmMetricsRegistry) - got := options.GetOptsConfigFile(*opts) + got := options.GetConfigFile(*opts) if got != "" { - optsConfigFile, err := os.ReadFile(filepath.Clean(got)) + configFile, err := os.ReadFile(filepath.Clean(got)) if err != nil { return fmt.Errorf("failed to read opts config file: %v", err) } // NOTE: Config value will override default values of intersecting options. - err = yaml.Unmarshal(optsConfigFile, opts) + err = yaml.Unmarshal(configFile, opts) if err != nil { // DO NOT end the process. // We want to allow the user to still be able to fix the misconfigured config (redeploy or edit the configmaps) and reload KSM automatically once that's done. @@ -116,7 +134,13 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options, factories . // Wait for the next reload. klog.Infof("misconfigured config detected, KSM will automatically reload on next write to the config") klog.Infof("waiting for config to be fixed") + configSuccess.WithLabelValues("config", filepath.Clean(got)).Set(0) <-ctx.Done() + } else { + configSuccess.WithLabelValues("config", filepath.Clean(got)).Set(1) + configSuccessTime.WithLabelValues("config", filepath.Clean(got)).SetToCurrentTime() + hash := md5HashAsMetricValue(configFile) + configHash.WithLabelValues("config", filepath.Clean(got)).Set(hash) } } var resources []string @@ -371,3 +395,14 @@ func buildMetricsServer(m *metricshandler.MetricsHandler, durationObserver prome }) return mux } + +// md5HashAsMetricValue creates an md5 hash and returns the most significant bytes that fit into a float64 +// Taken from https://github.com/prometheus/alertmanager/blob/6ef6e6868dbeb7984d2d577dd4bf75c65bf1904f/config/coordinator.go#L149 +func md5HashAsMetricValue(data []byte) float64 { + sum := md5.Sum(data) //nolint:gosec + // We only want 48 bits as a float64 only has a 53 bit mantissa. + smallSum := sum[0:6] + bytes := make([]byte, 8) + copy(bytes, smallSum) + return float64(binary.LittleEndian.Uint64(bytes)) +} diff --git a/pkg/options/options.go b/pkg/options/options.go index 95b726048a..bb26ef21ff 100644 --- a/pkg/options/options.go +++ b/pkg/options/options.go @@ -62,8 +62,8 @@ type Options struct { cmd *cobra.Command } -// GetOptsConfigFile is the getter for --options-config-file value. -func GetOptsConfigFile(opt Options) string { +// GetConfigFile is the getter for --config value. +func GetConfigFile(opt Options) string { return opt.Config } From 2c3ea01cb2c2ca3fa6ea9958d899f497ef14f5c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Kubica?= Date: Sat, 3 Dec 2022 15:17:02 +0100 Subject: [PATCH 56/70] Replace "" with empty string for "owner_kind", "owner_name" and "owner_is_controller" dimensions. Returning empty string instead of "" value for "owner_kind", "owner_name" and "owner_is_controller" dimensions when no metadata.ownerReferences exists in Kubernetes resoures. --- internal/store/job.go | 2 +- internal/store/job_test.go | 6 +++--- internal/store/lease.go | 2 +- internal/store/pod.go | 6 +++--- internal/store/pod_test.go | 4 ++-- internal/store/replicaset.go | 2 +- internal/store/replicaset_test.go | 2 +- internal/store/replicationcontroller.go | 2 +- internal/store/replicationcontroller_test.go | 2 +- pkg/app/server_test.go | 4 ++-- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/internal/store/job.go b/internal/store/job.go index 391fd24b3b..fc7bd969c3 100644 --- a/internal/store/job.go +++ b/internal/store/job.go @@ -364,7 +364,7 @@ func jobMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat Metrics: []*metric.Metric{ { LabelKeys: labelKeys, - LabelValues: []string{"", "", ""}, + LabelValues: []string{"", "", ""}, Value: 1, }, }, diff --git a/internal/store/job_test.go b/internal/store/job_test.go index 3cb2b13174..2394c09091 100644 --- a/internal/store/job_test.go +++ b/internal/store/job_test.go @@ -154,7 +154,7 @@ 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_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 @@ -198,7 +198,7 @@ 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_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 @@ -243,7 +243,7 @@ func TestJobStore(t *testing.T) { }, }, Want: metadata + ` - kube_job_owner{job_name="SuccessfulJob2NoActiveDeadlineSeconds",namespace="ns1",owner_is_controller="",owner_kind="",owner_name=""} 1 + kube_job_owner{job_name="SuccessfulJob2NoActiveDeadlineSeconds",namespace="ns1",owner_is_controller="",owner_kind="",owner_name=""} 1 kube_job_complete{condition="false",job_name="SuccessfulJob2NoActiveDeadlineSeconds",namespace="ns1"} 0 kube_job_complete{condition="true",job_name="SuccessfulJob2NoActiveDeadlineSeconds",namespace="ns1"} 1 diff --git a/internal/store/lease.go b/internal/store/lease.go index af0cc3db09..5ac49c22ef 100644 --- a/internal/store/lease.go +++ b/internal/store/lease.go @@ -53,7 +53,7 @@ var ( Metrics: []*metric.Metric{ { LabelKeys: labelKeys, - LabelValues: []string{"", "", l.Namespace, holder}, + LabelValues: []string{"", "", l.Namespace, holder}, Value: 1, }, }, diff --git a/internal/store/pod.go b/internal/store/pod.go index 2bbbde9f3b..f9bfdd21f2 100644 --- a/internal/store/pod.go +++ b/internal/store/pod.go @@ -597,8 +597,8 @@ func createPodInfoFamilyGenerator() generator.FamilyGenerator { "", wrapPodFunc(func(p *v1.Pod) *metric.Family { createdBy := metav1.GetControllerOf(p) - createdByKind := "" - createdByName := "" + createdByKind := "" + createdByName := "" if createdBy != nil { if createdBy.Kind != "" { createdByKind = createdBy.Kind @@ -1118,7 +1118,7 @@ func createPodOwnerFamilyGenerator() generator.FamilyGenerator { Metrics: []*metric.Metric{ { LabelKeys: labelKeys, - LabelValues: []string{"", "", ""}, + LabelValues: []string{"", "", ""}, Value: 1, }, }, diff --git a/internal/store/pod_test.go b/internal/store/pod_test.go index 2306191472..fb118f2d1c 100644 --- a/internal/store/pod_test.go +++ b/internal/store/pod_test.go @@ -1032,11 +1032,11 @@ func TestPodStore(t *testing.T) { # TYPE kube_pod_owner gauge # TYPE kube_pod_start_time gauge kube_pod_created{namespace="ns1",pod="pod1",uid="abc-123-xxx"} 1.5e+09 - kube_pod_info{created_by_kind="",created_by_name="",host_ip="1.1.1.1",namespace="ns1",node="node1",pod="pod1",pod_ip="1.2.3.4",uid="abc-123-xxx",priority_class="system-node-critical",host_network="true"} 1 + kube_pod_info{created_by_kind="",created_by_name="",host_ip="1.1.1.1",namespace="ns1",node="node1",pod="pod1",pod_ip="1.2.3.4",uid="abc-123-xxx",priority_class="system-node-critical",host_network="true"} 1 kube_pod_ips{namespace="ns1",pod="pod1",uid="abc-123-xxx",ip="1.2.3.4",ip_family="4"} 1 kube_pod_ips{namespace="ns1",pod="pod1",uid="abc-123-xxx",ip="fc00:1234:5678:90ab:cdef:cafe:f00d:d00d",ip_family="6"} 1 kube_pod_start_time{namespace="ns1",pod="pod1",uid="abc-123-xxx"} 1.501569018e+09 - kube_pod_owner{namespace="ns1",owner_is_controller="",owner_kind="",owner_name="",pod="pod1",uid="abc-123-xxx"} 1 + kube_pod_owner{namespace="ns1",owner_is_controller="",owner_kind="",owner_name="",pod="pod1",uid="abc-123-xxx"} 1 `, MetricNames: []string{"kube_pod_created", "kube_pod_info", "kube_pod_ips", "kube_pod_start_time", "kube_pod_completion_time", "kube_pod_owner"}, }, diff --git a/internal/store/replicaset.go b/internal/store/replicaset.go index 7ea4cff730..21c9a73626 100644 --- a/internal/store/replicaset.go +++ b/internal/store/replicaset.go @@ -178,7 +178,7 @@ func replicaSetMetricFamilies(allowAnnotationsList, allowLabelsList []string) [] Metrics: []*metric.Metric{ { LabelKeys: []string{"owner_kind", "owner_name", "owner_is_controller"}, - LabelValues: []string{"", "", ""}, + LabelValues: []string{"", "", ""}, Value: 1, }, }, diff --git a/internal/store/replicaset_test.go b/internal/store/replicaset_test.go index f25d51e275..80d7fabd7f 100644 --- a/internal/store/replicaset_test.go +++ b/internal/store/replicaset_test.go @@ -129,7 +129,7 @@ func TestReplicaSetStore(t *testing.T) { kube_replicaset_status_fully_labeled_replicas{namespace="ns2",replicaset="rs2"} 5 kube_replicaset_status_ready_replicas{namespace="ns2",replicaset="rs2"} 0 kube_replicaset_spec_replicas{namespace="ns2",replicaset="rs2"} 0 - kube_replicaset_owner{namespace="ns2",owner_is_controller="",owner_kind="",owner_name="",replicaset="rs2"} 1 + kube_replicaset_owner{namespace="ns2",owner_is_controller="",owner_kind="",owner_name="",replicaset="rs2"} 1 `, }, } diff --git a/internal/store/replicationcontroller.go b/internal/store/replicationcontroller.go index f5da7f5bdb..ffc0cc1208 100644 --- a/internal/store/replicationcontroller.go +++ b/internal/store/replicationcontroller.go @@ -185,7 +185,7 @@ var ( if len(owners) == 0 { ms = append(ms, &metric.Metric{ LabelKeys: labelKeys, - LabelValues: []string{"", "", ""}, + LabelValues: []string{"", "", ""}, Value: 1, }) } else { diff --git a/internal/store/replicationcontroller_test.go b/internal/store/replicationcontroller_test.go index f125d294c3..aea8bb1bb5 100644 --- a/internal/store/replicationcontroller_test.go +++ b/internal/store/replicationcontroller_test.go @@ -116,7 +116,7 @@ func TestReplicationControllerStore(t *testing.T) { }, Want: metadata + ` kube_replicationcontroller_metadata_generation{namespace="ns2",replicationcontroller="rc2"} 14 - kube_replicationcontroller_owner{namespace="ns2",owner_is_controller="",owner_kind="",owner_name="",replicationcontroller="rc2"} 1 + kube_replicationcontroller_owner{namespace="ns2",owner_is_controller="",owner_kind="",owner_name="",replicationcontroller="rc2"} 1 kube_replicationcontroller_status_replicas{namespace="ns2",replicationcontroller="rc2"} 0 kube_replicationcontroller_status_observed_generation{namespace="ns2",replicationcontroller="rc2"} 5 kube_replicationcontroller_status_fully_labeled_replicas{namespace="ns2",replicationcontroller="rc2"} 5 diff --git a/pkg/app/server_test.go b/pkg/app/server_test.go index 7627f302a6..659b84bf24 100644 --- a/pkg/app/server_test.go +++ b/pkg/app/server_test.go @@ -322,9 +322,9 @@ kube_pod_container_status_waiting_reason{namespace="default",pod="pod0",uid="abc kube_pod_container_status_waiting{namespace="default",pod="pod0",uid="abc-0",container="pod1_con1"} 1 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_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_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_status_phase{namespace="default",pod="pod0",uid="abc-0",phase="Failed"} 0 kube_pod_status_phase{namespace="default",pod="pod0",uid="abc-0",phase="Pending"} 0 From 0553bf45a9ef380a2b6c90f85aacde57b10f986e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Kubica?= Date: Sat, 3 Dec 2022 15:20:08 +0100 Subject: [PATCH 57/70] Replace special string "" with empty string for "storageclass" dimension. Returning empty string instead of special string "" for "storageclass" dimensions of "kube_persistentvolumeclaim_info" metric. --- docs/persistentvolumeclaim-metrics.md | 2 +- internal/store/persistentvolumeclaim.go | 4 ++-- internal/store/persistentvolumeclaim_test.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/persistentvolumeclaim-metrics.md b/docs/persistentvolumeclaim-metrics.md index 6294d6a3fe..2c92bc8247 100644 --- a/docs/persistentvolumeclaim-metrics.md +++ b/docs/persistentvolumeclaim-metrics.md @@ -13,4 +13,4 @@ Note: -- A special `` string will be used if PVC has no storage class. +- An empty string will be used if PVC has no storage class. diff --git a/internal/store/persistentvolumeclaim.go b/internal/store/persistentvolumeclaim.go index b048faa674..05159bff6e 100644 --- a/internal/store/persistentvolumeclaim.go +++ b/internal/store/persistentvolumeclaim.go @@ -270,6 +270,6 @@ func getPersistentVolumeClaimClass(claim *v1.PersistentVolumeClaim) string { return *claim.Spec.StorageClassName } - // Special non-empty string to indicate absence of storage class. - return "" + // An empty string indicate absence of storage class. + return "" } diff --git a/internal/store/persistentvolumeclaim_test.go b/internal/store/persistentvolumeclaim_test.go index 4902dfe217..39c5c6d824 100644 --- a/internal/store/persistentvolumeclaim_test.go +++ b/internal/store/persistentvolumeclaim_test.go @@ -257,7 +257,7 @@ func TestPersistentVolumeClaimStore(t *testing.T) { # TYPE kube_persistentvolumeclaim_status_phase gauge # TYPE kube_persistentvolumeclaim_status_condition gauge kube_persistentvolumeclaim_created{namespace="",persistentvolumeclaim="mongo-data"} 1.5e+09 - kube_persistentvolumeclaim_info{namespace="",persistentvolumeclaim="mongo-data",storageclass="",volumename=""} 1 + kube_persistentvolumeclaim_info{namespace="",persistentvolumeclaim="mongo-data",storageclass="",volumename=""} 1 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 From 98583875f5ccdf0149b16dd9d98cf32b1de8ea42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Kubica?= <49437476+pawcykca@users.noreply.github.com> Date: Mon, 5 Dec 2022 10:15:27 +0100 Subject: [PATCH 58/70] Update internal/store/persistentvolumeclaim.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Manuel Rüger --- internal/store/persistentvolumeclaim.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/store/persistentvolumeclaim.go b/internal/store/persistentvolumeclaim.go index 05159bff6e..9c9179788e 100644 --- a/internal/store/persistentvolumeclaim.go +++ b/internal/store/persistentvolumeclaim.go @@ -270,6 +270,6 @@ func getPersistentVolumeClaimClass(claim *v1.PersistentVolumeClaim) string { return *claim.Spec.StorageClassName } - // An empty string indicate absence of storage class. + // An empty string indicates the absence of storage class. return "" } From e355c48da1708bff67c809e3e9354b2dd4fb2145 Mon Sep 17 00:00:00 2001 From: Damien Grisonnet Date: Fri, 2 Dec 2022 19:33:42 +0100 Subject: [PATCH 59/70] Remove duplicated MetricsWriter implementation Simplify the implementation of the MetricsWriter to avoid code duplication between single and multi stores scenarios. Signed-off-by: Damien Grisonnet --- internal/store/builder.go | 10 +++------- pkg/builder/builder.go | 5 ++--- pkg/builder/types/interfaces.go | 2 +- pkg/metrics_store/metrics_store.go | 16 ---------------- pkg/metrics_store/metrics_store_test.go | 3 ++- pkg/metrics_store/metrics_writer.go | 21 +++++++++------------ pkg/metrics_store/metrics_writer_test.go | 4 ++-- pkg/metricshandler/metrics_handler.go | 2 +- tests/lib/lib_test.go | 3 ++- 9 files changed, 22 insertions(+), 44 deletions(-) diff --git a/internal/store/builder.go b/internal/store/builder.go index df00ed496d..7ecc93c9fa 100644 --- a/internal/store/builder.go +++ b/internal/store/builder.go @@ -233,12 +233,12 @@ func (b *Builder) WithAllowLabels(labels map[string][]string) error { // Build initializes and registers all enabled stores. // It returns metrics writers which can be used to write out // metrics from the stores. -func (b *Builder) Build() []metricsstore.MetricsWriter { +func (b *Builder) Build() metricsstore.MetricsWriterList { if b.familyGeneratorFilter == nil { panic("familyGeneratorFilter should not be nil") } - var metricsWriters []metricsstore.MetricsWriter + var metricsWriters metricsstore.MetricsWriterList var activeStoreNames []string for _, c := range b.enabledResources { @@ -246,11 +246,7 @@ func (b *Builder) Build() []metricsstore.MetricsWriter { if ok { stores := cacheStoresToMetricStores(constructor(b)) activeStoreNames = append(activeStoreNames, c) - if len(stores) == 1 { - metricsWriters = append(metricsWriters, stores[0]) - } else { - metricsWriters = append(metricsWriters, metricsstore.NewMultiStoreMetricsWriter(stores)) - } + metricsWriters = append(metricsWriters, metricsstore.NewMetricsWriter(stores...)) } } diff --git a/pkg/builder/builder.go b/pkg/builder/builder.go index f17663336c..ba1f10bac1 100644 --- a/pkg/builder/builder.go +++ b/pkg/builder/builder.go @@ -19,8 +19,6 @@ package builder import ( "context" - generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" - "github.com/prometheus/client_golang/prometheus" vpaclientset "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/client/clientset/versioned" clientset "k8s.io/client-go/kubernetes" @@ -29,6 +27,7 @@ import ( internalstore "k8s.io/kube-state-metrics/v2/internal/store" ksmtypes "k8s.io/kube-state-metrics/v2/pkg/builder/types" "k8s.io/kube-state-metrics/v2/pkg/customresource" + generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" metricsstore "k8s.io/kube-state-metrics/v2/pkg/metrics_store" "k8s.io/kube-state-metrics/v2/pkg/options" ) @@ -135,7 +134,7 @@ func (b *Builder) WithCustomResourceStoreFactories(fs ...customresource.Registry // Build initializes and registers all enabled stores. // Returns metric writers. -func (b *Builder) Build() []metricsstore.MetricsWriter { +func (b *Builder) Build() metricsstore.MetricsWriterList { return b.internal.Build() } diff --git a/pkg/builder/types/interfaces.go b/pkg/builder/types/interfaces.go index e52168235f..c8ddf40c05 100644 --- a/pkg/builder/types/interfaces.go +++ b/pkg/builder/types/interfaces.go @@ -51,7 +51,7 @@ type BuilderInterface interface { DefaultGenerateStoresFunc() BuildStoresFunc DefaultGenerateCustomResourceStoresFunc() BuildCustomResourceStoresFunc WithCustomResourceStoreFactories(fs ...customresource.RegistryFactory) - Build() []metricsstore.MetricsWriter + Build() metricsstore.MetricsWriterList BuildStores() [][]cache.Store } diff --git a/pkg/metrics_store/metrics_store.go b/pkg/metrics_store/metrics_store.go index 885dfaf7f2..80d7149781 100644 --- a/pkg/metrics_store/metrics_store.go +++ b/pkg/metrics_store/metrics_store.go @@ -17,7 +17,6 @@ limitations under the License. package metricsstore import ( - "io" "sync" "k8s.io/apimachinery/pkg/api/meta" @@ -144,18 +143,3 @@ func (s *MetricsStore) Replace(list []interface{}, _ string) error { func (s *MetricsStore) Resync() error { return nil } - -// WriteAll writes all metrics of the store into the given writer, zipped with the -// help text of each metric family. -func (s *MetricsStore) WriteAll(w io.Writer) { - s.mutex.RLock() - defer s.mutex.RUnlock() - - for i, help := range s.headers { - w.Write([]byte(help)) - w.Write([]byte{'\n'}) - for _, metricFamilies := range s.metrics { - w.Write(metricFamilies[i]) - } - } -} diff --git a/pkg/metrics_store/metrics_store_test.go b/pkg/metrics_store/metrics_store_test.go index bbd145c981..e965525d21 100644 --- a/pkg/metrics_store/metrics_store_test.go +++ b/pkg/metrics_store/metrics_store_test.go @@ -81,7 +81,8 @@ func TestObjectsSameNameDifferentNamespaces(t *testing.T) { } w := strings.Builder{} - ms.WriteAll(&w) + mw := NewMetricsWriter(ms) + mw.WriteAll(&w) m := w.String() for _, id := range serviceIDS { diff --git a/pkg/metrics_store/metrics_writer.go b/pkg/metrics_store/metrics_writer.go index 5d0362ae15..aa82f0fdd7 100644 --- a/pkg/metrics_store/metrics_writer.go +++ b/pkg/metrics_store/metrics_writer.go @@ -18,26 +18,23 @@ package metricsstore import "io" -// MetricsWriter is the interface that wraps the WriteAll method. -// WriteAll writes out bytes to the underlying writer. -type MetricsWriter interface { - WriteAll(w io.Writer) -} +// MetricsWriterList represent a list of MetricsWriter +type MetricsWriterList []*MetricsWriter -// MultiStoreMetricsWriter is a struct that holds multiple MetricsStore(s) and +// MetricsWriter is a struct that holds multiple MetricsStore(s) and // implements the MetricsWriter interface. // It should be used with stores which have the same metric headers. // -// MultiStoreMetricsWriter writes out metrics from the underlying stores so that +// MetricsWriter writes out metrics from the underlying stores so that // metrics with the same name coming from different stores end up grouped together. // It also ensures that the metric headers are only written out once. -type MultiStoreMetricsWriter struct { +type MetricsWriter struct { stores []*MetricsStore } -// NewMultiStoreMetricsWriter creates a new MultiStoreMetricsWriter. -func NewMultiStoreMetricsWriter(stores []*MetricsStore) MetricsWriter { - return &MultiStoreMetricsWriter{ +// NewMetricsWriter creates a new MetricsWriter. +func NewMetricsWriter(stores ...*MetricsStore) *MetricsWriter { + return &MetricsWriter{ stores: stores, } } @@ -46,7 +43,7 @@ func NewMultiStoreMetricsWriter(stores []*MetricsStore) MetricsWriter { // // WriteAll writes metrics so that the ones with the same name // are grouped together when written out. -func (m MultiStoreMetricsWriter) WriteAll(w io.Writer) { +func (m MetricsWriter) WriteAll(w io.Writer) { if len(m.stores) == 0 { return } diff --git a/pkg/metrics_store/metrics_writer_test.go b/pkg/metrics_store/metrics_writer_test.go index 1c3f66fa1a..b03b30f510 100644 --- a/pkg/metrics_store/metrics_writer_test.go +++ b/pkg/metrics_store/metrics_writer_test.go @@ -83,7 +83,7 @@ func TestWriteAllWithSingleStore(t *testing.T) { } } - multiNsWriter := metricsstore.NewMultiStoreMetricsWriter([]*metricsstore.MetricsStore{store}) + multiNsWriter := metricsstore.NewMetricsWriter(store) w := strings.Builder{} multiNsWriter.WriteAll(&w) result := w.String() @@ -192,7 +192,7 @@ func TestWriteAllWithMultipleStores(t *testing.T) { } } - multiNsWriter := metricsstore.NewMultiStoreMetricsWriter([]*metricsstore.MetricsStore{s1, s2}) + multiNsWriter := metricsstore.NewMetricsWriter(s1, s2) w := strings.Builder{} multiNsWriter.WriteAll(&w) result := w.String() diff --git a/pkg/metricshandler/metrics_handler.go b/pkg/metricshandler/metrics_handler.go index b1a88f051d..32a0cda459 100644 --- a/pkg/metricshandler/metrics_handler.go +++ b/pkg/metricshandler/metrics_handler.go @@ -51,7 +51,7 @@ type MetricsHandler struct { // mtx protects metricsWriters, curShard, and curTotalShards mtx *sync.RWMutex - metricsWriters []metricsstore.MetricsWriter + metricsWriters metricsstore.MetricsWriterList curShard int32 curTotalShards int } diff --git a/tests/lib/lib_test.go b/tests/lib/lib_test.go index b948a35c46..3588b81b0f 100644 --- a/tests/lib/lib_test.go +++ b/tests/lib/lib_test.go @@ -55,7 +55,8 @@ func TestAsLibrary(t *testing.T) { time.Sleep(time.Second) w := strings.Builder{} - c.WriteAll(&w) + mw := metricsstore.NewMetricsWriter(c) + mw.WriteAll(&w) m := w.String() if !strings.Contains(m, service.ObjectMeta.Name) { From fa89bc91abce5f5418d3fb401b8c925fb13e7faa Mon Sep 17 00:00:00 2001 From: Damien Grisonnet Date: Tue, 6 Dec 2022 19:14:45 +0100 Subject: [PATCH 60/70] pkg/metrics_store: add error handling to WriteAll Signed-off-by: Damien Grisonnet --- pkg/metrics_store/metrics_store_test.go | 5 ++++- pkg/metrics_store/metrics_writer.go | 22 ++++++++++++++++------ pkg/metrics_store/metrics_writer_test.go | 10 ++++++++-- pkg/metricshandler/metrics_handler.go | 5 ++++- tests/lib/lib_test.go | 5 ++++- 5 files changed, 36 insertions(+), 11 deletions(-) diff --git a/pkg/metrics_store/metrics_store_test.go b/pkg/metrics_store/metrics_store_test.go index e965525d21..b32e1bcb38 100644 --- a/pkg/metrics_store/metrics_store_test.go +++ b/pkg/metrics_store/metrics_store_test.go @@ -82,7 +82,10 @@ func TestObjectsSameNameDifferentNamespaces(t *testing.T) { w := strings.Builder{} mw := NewMetricsWriter(ms) - mw.WriteAll(&w) + err := mw.WriteAll(&w) + if err != nil { + t.Fatalf("failed to write metrics: %v", err) + } m := w.String() for _, id := range serviceIDS { diff --git a/pkg/metrics_store/metrics_writer.go b/pkg/metrics_store/metrics_writer.go index aa82f0fdd7..7cc92c298b 100644 --- a/pkg/metrics_store/metrics_writer.go +++ b/pkg/metrics_store/metrics_writer.go @@ -16,7 +16,10 @@ limitations under the License. package metricsstore -import "io" +import ( + "fmt" + "io" +) // MetricsWriterList represent a list of MetricsWriter type MetricsWriterList []*MetricsWriter @@ -43,9 +46,9 @@ func NewMetricsWriter(stores ...*MetricsStore) *MetricsWriter { // // WriteAll writes metrics so that the ones with the same name // are grouped together when written out. -func (m MetricsWriter) WriteAll(w io.Writer) { +func (m MetricsWriter) WriteAll(w io.Writer) error { if len(m.stores) == 0 { - return + return nil } for _, s := range m.stores { @@ -56,12 +59,19 @@ func (m MetricsWriter) WriteAll(w io.Writer) { } for i, help := range m.stores[0].headers { - w.Write([]byte(help)) - w.Write([]byte{'\n'}) + _, err := w.Write([]byte(help + "\n")) + if err != nil { + return fmt.Errorf("failed to write help text: %v", err) + } + for _, s := range m.stores { for _, metricFamilies := range s.metrics { - w.Write(metricFamilies[i]) + _, err := w.Write(metricFamilies[i]) + if err != nil { + return fmt.Errorf("failed to write metrics family: %v", err) + } } } } + return nil } diff --git a/pkg/metrics_store/metrics_writer_test.go b/pkg/metrics_store/metrics_writer_test.go index b03b30f510..b13c160555 100644 --- a/pkg/metrics_store/metrics_writer_test.go +++ b/pkg/metrics_store/metrics_writer_test.go @@ -85,7 +85,10 @@ func TestWriteAllWithSingleStore(t *testing.T) { multiNsWriter := metricsstore.NewMetricsWriter(store) w := strings.Builder{} - multiNsWriter.WriteAll(&w) + err := multiNsWriter.WriteAll(&w) + if err != nil { + t.Fatalf("failed to write metrics: %v", err) + } result := w.String() resultLines := strings.Split(strings.TrimRight(result, "\n"), "\n") @@ -194,7 +197,10 @@ func TestWriteAllWithMultipleStores(t *testing.T) { multiNsWriter := metricsstore.NewMetricsWriter(s1, s2) w := strings.Builder{} - multiNsWriter.WriteAll(&w) + err := multiNsWriter.WriteAll(&w) + if err != nil { + t.Fatalf("failed to write metrics: %v", err) + } result := w.String() resultLines := strings.Split(strings.TrimRight(result, "\n"), "\n") diff --git a/pkg/metricshandler/metrics_handler.go b/pkg/metricshandler/metrics_handler.go index 32a0cda459..a6a245dfe2 100644 --- a/pkg/metricshandler/metrics_handler.go +++ b/pkg/metricshandler/metrics_handler.go @@ -200,7 +200,10 @@ func (m *MetricsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } for _, w := range m.metricsWriters { - w.WriteAll(writer) + err := w.WriteAll(writer) + if err != nil { + klog.ErrorS(err, "Failed to write metrics") + } } // In case we gzipped the response, we have to close the writer. diff --git a/tests/lib/lib_test.go b/tests/lib/lib_test.go index 3588b81b0f..ba96edf00e 100644 --- a/tests/lib/lib_test.go +++ b/tests/lib/lib_test.go @@ -56,7 +56,10 @@ func TestAsLibrary(t *testing.T) { w := strings.Builder{} mw := metricsstore.NewMetricsWriter(c) - mw.WriteAll(&w) + err = mw.WriteAll(&w) + if err != nil { + t.Fatalf("failed to write metrics: %v", err) + } m := w.String() if !strings.Contains(m, service.ObjectMeta.Name) { From eb3bdbcb58058e28fb4ac6a0597fe0fc898b2bf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Wed, 7 Dec 2022 23:16:34 +0100 Subject: [PATCH 61/70] Add metrics for CustomResourceConfig file --- README.md | 11 +++++++---- pkg/app/server.go | 13 +++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 73e679666e..589e344435 100644 --- a/README.md +++ b/README.md @@ -165,12 +165,15 @@ please check the blog post [here](https://www.robustperception.io/exposing-the-s Sharding metrics expose `--shard` and `--total-shards` flags and can be used to validate run-time configuration, see [`/examples/prometheus-alerting-rules`](./examples/prometheus-alerting-rules). -kube-state-metrics also exposes metrics about it config file: +kube-state-metrics also exposes metrics about it config file and the Custom Resource State config file: ``` -kube_state_metrics_config_hash{type="config", filename="config.yml"} 4.0061079457904e+13 -kube_state_metrics_config_last_reload_success_timestamp_seconds{type="config", filename="config.yml"} 1.6697483049487052e+09 -kube_state_metrics_config_last_reload_successful{type="config", filename="config.yml"} 1 +kube_state_metrics_config_hash{filename="crs.yml",type="customresourceconfig"} 2.38272279311849e+14 +kube_state_metrics_config_hash{filename="config.yml",type="config"} 2.65285922340846e+14 +kube_state_metrics_last_config_reload_success_timestamp_seconds{filename="crs.yml",type="customresourceconfig"} 1.6704882592037103e+09 +kube_state_metrics_last_config_reload_success_timestamp_seconds{filename="config.yml",type="config"} 1.6704882592035313e+09 +kube_state_metrics_last_config_reload_successful{filename="crs.yml",type="customresourceconfig"} 1 +kube_state_metrics_last_config_reload_successful{filename="config.yml",type="config"} 1 ``` ### Scaling kube-state-metrics diff --git a/pkg/app/server.go b/pkg/app/server.go index e9dc75e0ec..67c235e0c6 100644 --- a/pkg/app/server.go +++ b/pkg/app/server.go @@ -143,6 +143,19 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options, factories . configHash.WithLabelValues("config", filepath.Clean(got)).Set(hash) } } + + if opts.CustomResourceConfigFile != "" { + crcFile, err := os.ReadFile(filepath.Clean(opts.CustomResourceConfigFile)) + if err != nil { + return fmt.Errorf("failed to read custom resource config file: %v", err) + } + configSuccess.WithLabelValues("customresourceconfig", filepath.Clean(opts.CustomResourceConfigFile)).Set(1) + configSuccessTime.WithLabelValues("customresourceconfig", filepath.Clean(opts.CustomResourceConfigFile)).SetToCurrentTime() + hash := md5HashAsMetricValue(crcFile) + configHash.WithLabelValues("customresourceconfig", filepath.Clean(opts.CustomResourceConfigFile)).Set(hash) + + } + var resources []string switch { case len(opts.Resources) == 0 && !opts.CustomResourcesOnly: From 2849d59668c75cc5fc905fc4892f7f606012685e Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Mon, 5 Dec 2022 12:31:41 +0530 Subject: [PATCH 62/70] docs: add status badge for the periodic cronjob Additionally, rename it to a more fitting name. --- .github/workflows/{cron.yml => govulncheck.yml} | 2 +- README.md | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) rename .github/workflows/{cron.yml => govulncheck.yml} (96%) diff --git a/.github/workflows/cron.yml b/.github/workflows/govulncheck.yml similarity index 96% rename from .github/workflows/cron.yml rename to .github/workflows/govulncheck.yml index 2af5820abf..2326a220e9 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/govulncheck.yml @@ -1,4 +1,4 @@ -name: cron +name: govulncheck on: schedule: diff --git a/README.md b/README.md index 2eaf634f6e..f68a0df8c4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # Overview [![Build Status](https://github.com/kubernetes/kube-state-metrics/workflows/continuous-integration/badge.svg)](https://github.com/kubernetes/kube-state-metrics/actions) -[![Go Report Card](https://goreportcard.com/badge/github.com/kubernetes/kube-state-metrics)](https://goreportcard.com/report/github.com/kubernetes/kube-state-metrics) [![GoDoc](https://godoc.org/github.com/kubernetes/kube-state-metrics?status.svg)](https://godoc.org/github.com/kubernetes/kube-state-metrics) +[![Go Report Card](https://goreportcard.com/badge/github.com/kubernetes/kube-state-metrics)](https://goreportcard.com/report/github.com/kubernetes/kube-state-metrics) +[![Go Reference](https://pkg.go.dev/badge/github.com/kubernetes/kube-state-metrics.svg)](https://pkg.go.dev/github.com/kubernetes/kube-state-metrics) +[![govulncheck](https://github.com/kubernetes/kube-state-metrics/actions/workflows/govulncheck.yml/badge.svg)](https://github.com/kubernetes/kube-state-metrics/actions/workflows/govulncheck.yml) kube-state-metrics (KSM) is a simple service that listens to the Kubernetes API server and generates metrics about the state of the objects. (See examples in From 01062d51864773fd6216f2da54cc9c38029212d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Sun, 11 Dec 2022 19:13:31 +0100 Subject: [PATCH 63/70] Rename references from master to main branch --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/workflows/ci.yml | 4 ++-- Makefile | 2 +- README.md | 4 ++-- RELEASE.md | 6 +++--- docs/developer/guide.md | 18 +++++++++--------- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index bd31c20df2..79d1ddae87 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -9,7 +9,7 @@ assignees: '' **What happened**: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ac03bea322..3e2c07ac1c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,14 +3,14 @@ name: continuous-integration on: push: branches: - - master + - main - release* tags: - v1.* - v2.* pull_request: branches: - - master + - main - release* permissions: diff --git a/Makefile b/Makefile index 07546003d6..a8d0e91481 100644 --- a/Makefile +++ b/Makefile @@ -78,7 +78,7 @@ shellcheck: # the two. test-benchmark-compare: @git fetch - ./tests/compare_benchmarks.sh master + ./tests/compare_benchmarks.sh main ./tests/compare_benchmarks.sh ${LATEST_RELEASE_BRANCH} all: all-container diff --git a/README.md b/README.md index 589e344435..ab4edb1f10 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ Generally, it is recommended to use the latest release of kube-state-metrics. If | **v2.5.0** | v1.24 | | **v2.6.0** | v1.24 | | **v2.7.0** | v1.25 | -| **master** | v1.25 | +| **main** | v1.25 | #### Resource group version compatibility @@ -155,7 +155,7 @@ http_request_duration_seconds_count{handler="metrics",method="get"} 30 kube-state-metrics also exposes build and configuration metrics: ``` -kube_state_metrics_build_info{branch="master",goversion="go1.15.3",revision="6c9d775d",version="v2.0.0-beta"} 1 +kube_state_metrics_build_info{branch="main",goversion="go1.15.3",revision="6c9d775d",version="v2.0.0-beta"} 1 kube_state_metrics_shard_ordinal{shard_ordinal="0"} 0 kube_state_metrics_total_shards 1 ``` diff --git a/RELEASE.md b/RELEASE.md index e2ab973030..072da51edf 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -6,9 +6,9 @@ We use [Semantic Versioning](http://semver.org/). We maintain a separate branch for each minor release, named `release-.`, e.g. `release-1.1`, `release-2.0`. -The usual flow is to merge new features and changes into the master branch and to merge bug fixes into the latest release branch. Bug fixes are then merged into master from the latest release branch. The master branch should always contain all commits from the latest release branch. +The usual flow is to merge new features and changes into the main branch and to merge bug fixes into the latest release branch. Bug fixes are then merged into main from the latest release branch. The main branch should always contain all commits from the latest release branch. -If a bug fix got accidentally merged into master, cherry-pick commits have to be created in the latest release branch, which then have to be merged back into master. Try to avoid that situation. +If a bug fix got accidentally merged into main, cherry-pick commits have to be created in the latest release branch, which then have to be merged back into main. Try to avoid that situation. Maintaining the release branches for older minor releases happens on a best effort basis. @@ -34,7 +34,7 @@ Maintaining the release branches for older minor releases happens on a best effo * Create a new **pre-release** on github * New images are automatically built and pushed to `gcr.io/k8s-staging-kube-state-metrics/kube-state-metrics` * Promote image by sending a PR to [kubernetes/k8s.io](https://github.com/kubernetes/k8s.io) repository. Follow the [example PR](https://github.com/kubernetes/k8s.io/pull/3798). Use [kpromo pr](https://github.com/kubernetes-sigs/promo-tools/blob/main/docs/promotion-pull-requests.md) to update the manifest files in this repository, e.g. `kpromo pr --fork=$YOURNAME -i --project=kube-state-metrics -t=v2.5.0` -* Create a PR to merge the changes of this release back into the master branch. +* Create a PR to merge the changes of this release back into the main branch. * Once the PR to promote the image is merged, mark the pre-release as a regular release. ## Stable release diff --git a/docs/developer/guide.md b/docs/developer/guide.md index b515564e40..6600d19a4a 100644 --- a/docs/developer/guide.md +++ b/docs/developer/guide.md @@ -11,12 +11,12 @@ Any contribution to improving this documentation will be appreciated. The following steps are needed to introduce a new resource and its respective resource metrics. -- Reference your new resource(s) to the [docs/README.md](https://github.com/kubernetes/kube-state-metrics/blob/master/docs/README.md#exposed-metrics). -- Reference your new resource(s) in the [docs/cli-arguments.md](https://github.com/kubernetes/kube-state-metrics/blob/master/docs/cli-arguments.md#available-options) as part of the `--resources` flag. -- Create a new `.md` in the [docs](https://github.com/kubernetes/kube-state-metrics/tree/master/docs) directory to provide documentation on the resource(s) and metrics you implemented. Follow the formatting of all other resources. -- Add the resource(s) you are representing to the [jsonnet/kube-state-metrics/kube-state-metrics.libsonnet](https://github.com/kubernetes/kube-state-metrics/blob/master/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet) under the appropriate `apiGroup` using the `verbs`: `list` and `watch`. -- Run `make examples/standard`, this should re-generate [examples/standard/cluster-role.yaml](https://github.com/kubernetes/kube-state-metrics/blob/master/examples/standard/cluster-role.yaml) with the resource(s) added to [jsonnet/kube-state-metrics/kube-state-metrics.libsonnet](https://github.com/kubernetes/kube-state-metrics/blob/master/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet). -- Reference and add build functions for the new resource(s) in [internal/store/builder.go](https://github.com/kubernetes/kube-state-metrics/blob/master/internal/store/builder.go). -- Reference the new resource in [pkg/options/resource.go](https://github.com/kubernetes/kube-state-metrics/blob/master/pkg/options/resource.go). -- Add a sample Kubernetes manifest to be used by tests in the [tests/manifests/](https://github.com/kubernetes/kube-state-metrics/tree/master/tests/manifests) directory. -- Lastly, and most importantly, actually implement your new resource(s) and its test binary in [internal/store](https://github.com/kubernetes/kube-state-metrics/tree/master/internal/store). Follow the formatting and structure of other resources. +- Reference your new resource(s) to the [docs/README.md](https://github.com/kubernetes/kube-state-metrics/blob/main/docs/README.md#exposed-metrics). +- Reference your new resource(s) in the [docs/cli-arguments.md](https://github.com/kubernetes/kube-state-metrics/blob/main/docs/cli-arguments.md#available-options) as part of the `--resources` flag. +- Create a new `.md` in the [docs](https://github.com/kubernetes/kube-state-metrics/tree/main/docs) directory to provide documentation on the resource(s) and metrics you implemented. Follow the formatting of all other resources. +- Add the resource(s) you are representing to the [jsonnet/kube-state-metrics/kube-state-metrics.libsonnet](https://github.com/kubernetes/kube-state-metrics/blob/main/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet) under the appropriate `apiGroup` using the `verbs`: `list` and `watch`. +- Run `make examples/standard`, this should re-generate [examples/standard/cluster-role.yaml](https://github.com/kubernetes/kube-state-metrics/blob/main/examples/standard/cluster-role.yaml) with the resource(s) added to [jsonnet/kube-state-metrics/kube-state-metrics.libsonnet](https://github.com/kubernetes/kube-state-metrics/blob/main/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet). +- Reference and add build functions for the new resource(s) in [internal/store/builder.go](https://github.com/kubernetes/kube-state-metrics/blob/main/internal/store/builder.go). +- Reference the new resource in [pkg/options/resource.go](https://github.com/kubernetes/kube-state-metrics/blob/main/pkg/options/resource.go). +- Add a sample Kubernetes manifest to be used by tests in the [tests/manifests/](https://github.com/kubernetes/kube-state-metrics/tree/main/tests/manifests) directory. +- Lastly, and most importantly, actually implement your new resource(s) and its test binary in [internal/store](https://github.com/kubernetes/kube-state-metrics/tree/main/internal/store). Follow the formatting and structure of other resources. From 28052175ab447fee5308294b18080941f4a13eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Mon, 12 Dec 2022 23:48:05 +0100 Subject: [PATCH 64/70] Makefile: Bump to go 1.19.4 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a8d0e91481..a63b0e6ec3 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ OS ?= $(shell uname -s | tr A-Z a-z) ALL_ARCH = amd64 arm arm64 ppc64le s390x PKG = github.com/prometheus/common PROMETHEUS_VERSION = 2.39.1 -GO_VERSION = 1.19.3 +GO_VERSION = 1.19.4 IMAGE = $(REGISTRY)/kube-state-metrics MULTI_ARCH_IMG = $(IMAGE)-$(ARCH) USER ?= $(shell id -u -n) From 97b7e41f9475967a89eab887ce9954e323959e56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Mon, 12 Dec 2022 23:48:43 +0100 Subject: [PATCH 65/70] Makefile: Bump to prometheus 2.40.6 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a63b0e6ec3..665044e578 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ 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.39.1 +PROMETHEUS_VERSION = 2.40.6 GO_VERSION = 1.19.4 IMAGE = $(REGISTRY)/kube-state-metrics MULTI_ARCH_IMG = $(IMAGE)-$(ARCH) From 89403d239a47b75625d5939c8f26c73f4dc34245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Mon, 12 Dec 2022 23:46:36 +0100 Subject: [PATCH 66/70] go.mod: Bump to kubernetes 1.26.0 --- README.md | 3 +- go.mod | 41 +++++-------- go.sum | 167 ++++++++++----------------------------------------- tests/e2e.sh | 2 +- 4 files changed, 49 insertions(+), 164 deletions(-) diff --git a/README.md b/README.md index f58021ae94..c4bce76cca 100644 --- a/README.md +++ b/README.md @@ -74,12 +74,11 @@ Generally, it is recommended to use the latest release of kube-state-metrics. If | kube-state-metrics | Kubernetes client-go Version | |--------------------|:----------------------------:| -| **v2.3.0** | v1.23 | | **v2.4.2** | v1.23 | | **v2.5.0** | v1.24 | | **v2.6.0** | v1.24 | | **v2.7.0** | v1.25 | -| **main** | v1.25 | +| **main** | v1.26 | #### Resource group version compatibility diff --git a/go.mod b/go.mod index c268e182d7..6caf039c6a 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/oklog/run v1.1.0 github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.3.0 - github.com/prometheus/common v0.37.0 + github.com/prometheus/common v0.38.0 github.com/prometheus/exporter-toolkit v0.8.2 github.com/robfig/cron/v3 v3.0.1 github.com/spf13/cobra v1.6.1 @@ -20,27 +20,17 @@ require ( github.com/stretchr/testify v1.8.1 golang.org/x/perf v0.0.0-20220920022801-e8d778a60d07 gopkg.in/yaml.v3 v3.0.1 - k8s.io/api v0.25.4 - k8s.io/apimachinery v0.25.4 + k8s.io/api v0.26.0 + k8s.io/apimachinery v0.26.0 k8s.io/autoscaler/vertical-pod-autoscaler v0.12.0 - k8s.io/client-go v0.25.4 - k8s.io/component-base v0.25.4 + k8s.io/client-go v0.26.0 + k8s.io/component-base v0.26.0 k8s.io/klog/v2 v2.80.1 - k8s.io/sample-controller v0.25.4 - k8s.io/utils v0.0.0-20221101230645-61b03e2f6476 + k8s.io/sample-controller v0.26.0 + k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 ) require ( - cloud.google.com/go/compute v1.12.1 // indirect - cloud.google.com/go/compute/metadata v0.2.1 // indirect - github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.27 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect - github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect - github.com/Azure/go-autorest/logger v0.2.1 // indirect - github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/PuerkitoBio/purell v1.1.1 // indirect - github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -48,7 +38,7 @@ require ( github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/coreos/go-systemd/v22 v22.4.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/emicklei/go-restful/v3 v3.8.0 // indirect + github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/evanphx/json-patch v4.12.0+incompatible // indirect github.com/fatih/color v1.13.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect @@ -56,10 +46,9 @@ require ( github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect github.com/go-openapi/swag v0.19.14 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.2.0 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/gofuzz v1.1.0 // indirect @@ -74,7 +63,7 @@ require ( github.com/mailru/easyjson v0.7.6 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -91,12 +80,12 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.4.1 // indirect golang.org/x/crypto v0.0.0-20221012134737-56aed061732a // indirect - golang.org/x/net v0.0.0-20221014081412-f15817d10f9b // indirect + golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 // indirect golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.1.0 // indirect - golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect - golang.org/x/text v0.4.0 // indirect + golang.org/x/sys v0.3.0 // indirect + golang.org/x/term v0.3.0 // indirect + golang.org/x/text v0.5.0 // indirect golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.1 // indirect @@ -104,7 +93,7 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect + k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect diff --git a/go.sum b/go.sum index 220caf7a9d..7f51f9095e 100644 --- a/go.sum +++ b/go.sum @@ -24,10 +24,6 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0= -cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= @@ -42,43 +38,17 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A= -github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U= -github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/adal v0.9.20 h1:gJ3E98kMpFB1MFqQCvA1yFab8vthOeD4VlFRQULxahg= -github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= -github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190129172621-c8b1d7a94ddf/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/aclements/go-gg v0.0.0-20170118225347-6dbb4e4fefb0/go.mod h1:55qNq4vcpkIuHowELi5C8e+1yUHtoLoOUR9QU5j7Tes= github.com/aclements/go-moremath v0.0.0-20210112150236-f10218a38794/go.mod h1:7e+I0LQFUI9AXWxOfsQROs9xPhoJtbsyWcjJqDd4KPY= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/ajstarks/svgo v0.0.0-20210923152817-c3b6e2f0c527/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= @@ -90,7 +60,6 @@ github.com/brancz/gojsontoyaml v0.1.0/go.mod h1:+ycZY94+V11XZBUaDEsbLr3hPNS/ZPrD github.com/campoy/embedmd v1.0.0 h1:V4kI2qTJJLf4J29RzI/MAt2c3Bl4dQSYPuflzwFH2hY= github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -110,8 +79,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/dgryski/go-jump v0.0.0-20211018200510-ba001c3ffce0 h1:0wH6nO9QEa02Qx8sIQGw6ieKdz+BXjpccSOo9vXNl4U= github.com/dgryski/go-jump v0.0.0-20211018200510-ba001c3ffce0/go.mod h1:4hKCXuwrJoYvHZxJ86+bRVTOMyJ0Ej+RqfSm8mHi6KA= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= -github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -138,17 +107,10 @@ github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmn github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -157,23 +119,18 @@ github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobuffalo/flect v0.3.0 h1:erfPWM+K1rFNIQeRPdeEXxo8yFr/PO17lhRnS8FUrtk= github.com/gobuffalo/flect v0.3.0/go.mod h1:5pf3aGnsvqvCj50AVni7mJJF8ICxGZ8HomberC3pXLE= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -265,25 +222,17 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jsonnet-bundler/jsonnet-bundler v0.5.1 h1:eUd6EA1Qzz73Q4NLNLOrNkMb96+6NTTERbX9lqaxVwk= github.com/jsonnet-bundler/jsonnet-bundler v0.5.1/go.mod h1:Qrdw/7mOFS2SKCOALKFfEH8gdvXJi8XZjw9g5ilpf4I= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -307,28 +256,24 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM= +github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= -github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU= -github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q= +github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs= +github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= @@ -337,39 +282,21 @@ github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2 github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/common v0.38.0 h1:VTQitp6mXTdUoCmDMugDVOJ1opi6ADftKfp/yeqTR/E= +github.com/prometheus/common v0.38.0/go.mod h1:MBXfmBQZrK5XpbCkjofnXs96LD2QQ7fEq4C0xjC/yec= github.com/prometheus/exporter-toolkit v0.8.2 h1:sbJAfBXQFkG6sUkbwBun8MNdzW9+wd5YfPYofbmj0YM= github.com/prometheus/exporter-toolkit v0.8.2/go.mod h1:00shzmJL7KxcsabLWcONwpyNEuWhREOnFqZW7vadFS0= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= @@ -383,9 +310,6 @@ github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfF github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= @@ -400,7 +324,6 @@ github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU= github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -426,16 +349,13 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20221012134737-56aed061732a h1:NmSIgad6KjE6VvHciPZuNRTKxGhlPfD6OA87W/PLkqg= golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -486,7 +406,6 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -494,11 +413,9 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -518,12 +435,8 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20221014081412-f15817d10f9b h1:tvrvnPFcdzp294diPnrdZZZ8XUt2Tyj7svb7X52iDuU= -golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 h1:Frnccbp+ok2GkUS2tC84yAq/U9Vg+0sIO7aRL3T4Xnc= +golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/oauth2 v0.0.0-20170207211851-4464e7848382/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -534,8 +447,6 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/perf v0.0.0-20220920022801-e8d778a60d07 h1:LhnzFL4oipoFsDvxTy2IJRHgOlnGzB2dE5l7C4PN7bg= @@ -553,12 +464,9 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -567,7 +475,6 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -581,8 +488,6 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -590,24 +495,20 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -616,9 +517,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -796,13 +696,10 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -816,24 +713,24 @@ 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.25.4 h1:3YO8J4RtmG7elEgaWMb4HgmpS2CfY1QlaOz9nwB+ZSs= -k8s.io/api v0.25.4/go.mod h1:IG2+RzyPQLllQxnhzD8KQNEu4c4YvyDTpSMztf4A0OQ= -k8s.io/apimachinery v0.25.4 h1:CtXsuaitMESSu339tfhVXhQrPET+EiWnIY1rcurKnAc= -k8s.io/apimachinery v0.25.4/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo= +k8s.io/api v0.26.0 h1:IpPlZnxBpV1xl7TGk/X6lFtpgjgntCg8PJ+qrPHAC7I= +k8s.io/api v0.26.0/go.mod h1:k6HDTaIFC8yn1i6pSClSqIwLABIcLV9l5Q4EcngKnQg= +k8s.io/apimachinery v0.26.0 h1:1feANjElT7MvPqp0JT6F3Ss6TWDwmcjLypwoPpEf7zg= +k8s.io/apimachinery v0.26.0/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= k8s.io/autoscaler/vertical-pod-autoscaler v0.12.0 h1:cy8LoXSl5GkTNJDTx3ZCS143f9Ai7gqnGkoUxPlGSmI= k8s.io/autoscaler/vertical-pod-autoscaler v0.12.0/go.mod h1:LraL5kR2xX7jb4VMCG6/tUH4I75uRHlnzC0VWQHcyWk= -k8s.io/client-go v0.25.4 h1:3RNRDffAkNU56M/a7gUfXaEzdhZlYhoW8dgViGy5fn8= -k8s.io/client-go v0.25.4/go.mod h1:8trHCAC83XKY0wsBIpbirZU4NTUpbuhc2JnI7OruGZw= -k8s.io/component-base v0.25.4 h1:n1bjg9Yt+G1C0WnIDJmg2fo6wbEU1UGMRiQSjmj7hNQ= -k8s.io/component-base v0.25.4/go.mod h1:nnZJU8OP13PJEm6/p5V2ztgX2oyteIaAGKGMYb2L2cY= +k8s.io/client-go v0.26.0 h1:lT1D3OfO+wIi9UFolCrifbjUUgu7CpLca0AD8ghRLI8= +k8s.io/client-go v0.26.0/go.mod h1:I2Sh57A79EQsDmn7F7ASpmru1cceh3ocVT9KlX2jEZg= +k8s.io/component-base v0.26.0 h1:0IkChOCohtDHttmKuz+EP3j3+qKmV55rM9gIFTXA7Vs= +k8s.io/component-base v0.26.0/go.mod h1:lqHwlfV1/haa14F/Z5Zizk5QmzaVf23nQzCwVOQpfC8= k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= -k8s.io/sample-controller v0.25.4 h1:DWOuUMa3qHAP/734F75hSyMtGQrojodwGuEdrirzw9A= -k8s.io/sample-controller v0.25.4/go.mod h1:uaKn9T3EHfpgJA2uuDadTpr/zyZywWsIibNgAzByF8U= -k8s.io/utils v0.0.0-20221101230645-61b03e2f6476 h1:L14f2LWkOxG2rYsuSA3ltQnnST1vMfek/GUk+VemxD4= -k8s.io/utils v0.0.0-20221101230645-61b03e2f6476/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= +k8s.io/sample-controller v0.26.0 h1:cOEpHfipQYZRiQAZDyJrGrBZLIi5q3y2jKBCxU1GU8E= +k8s.io/sample-controller v0.26.0/go.mod h1:t8CYIAljtF67tvO1tzBzfXUmEbnHf1dupDG/orwCsjY= +k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y= +k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= diff --git a/tests/e2e.sh b/tests/e2e.sh index 6381b7d8db..1dea5b283d 100755 --- a/tests/e2e.sh +++ b/tests/e2e.sh @@ -24,7 +24,7 @@ case $(uname -m) in esac NODE_IMAGE_NAME="docker.io/kindest/node" -KUBERNETES_VERSION=${KUBERNETES_VERSION:-"v1.25.0"} +KUBERNETES_VERSION=${KUBERNETES_VERSION:-"v1.26.0"} KUBE_STATE_METRICS_LOG_DIR=./log KUBE_STATE_METRICS_CURRENT_IMAGE_NAME="registry.k8s.io/kube-state-metrics/kube-state-metrics" KUBE_STATE_METRICS_IMAGE_NAME="registry.k8s.io/kube-state-metrics/kube-state-metrics-${ARCH}" From 0955db83999326550ceebc876063b2d66d7c2e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Tue, 13 Dec 2022 00:00:26 +0100 Subject: [PATCH 67/70] .github: Bump golangci-lint to 1.50.1 --- .github/workflows/ci.yml | 2 +- .golangci.yml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e2c07ac1c..b4aef6f89c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ env: E2E_SETUP_KUBECTL: yes SUDO: sudo GO_VERSION: "^1.19" - GOLANGCI_LINT_VERSION: "v1.48.0" + GOLANGCI_LINT_VERSION: "v1.50.1" jobs: ci-go-lint: diff --git a/.golangci.yml b/.golangci.yml index b10ab5c6f3..67ee2fb49a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -33,3 +33,6 @@ issues: - text: "G104:" linters: - gosec + - text: "package-comments:" + linters: + - revive From 02fd1a9c1898ec53eccdd66da003cee3b710e71d Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Sun, 11 Dec 2022 19:20:04 +0530 Subject: [PATCH 68/70] Make CRS metrics type dynamic All CRS metrics are hardcoded to "gauge" type, this patch addresses that. --- .../custom_resource_metrics_test.go | 76 +++++++++++++++++++ pkg/customresourcestate/registry_factory.go | 11 ++- pkg/metric/metric.go | 12 ++- 3 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 pkg/customresourcestate/custom_resource_metrics_test.go diff --git a/pkg/customresourcestate/custom_resource_metrics_test.go b/pkg/customresourcestate/custom_resource_metrics_test.go new file mode 100644 index 0000000000..9bd1a5c536 --- /dev/null +++ b/pkg/customresourcestate/custom_resource_metrics_test.go @@ -0,0 +1,76 @@ +/* +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 customresourcestate + +import ( + "testing" +) + +func TestNewCustomResourceMetrics(t *testing.T) { + tests := []struct { + r Resource + wantErr bool + name string + }{ + { + // https://github.com/kubernetes/kube-state-metrics/issues/1886 + name: "dynamic metric type (not just hardcoded to gauge)", + r: Resource{ + GroupVersionKind: GroupVersionKind{ + Group: "apps", + Version: "v1", + Kind: "Deployment", + }, + Labels: Labels{ + LabelsFromPath: map[string][]string{ + "name": {"metadata", "name"}, + }, + }, + Metrics: []Generator{ + { + Name: "test_metrics", + Help: "metrics for testing", + Each: Metric{ + Type: MetricTypeInfo, + Info: &MetricInfo{ + MetricMeta: MetricMeta{ + Path: []string{ + "metadata", + "annotations", + }, + }, + LabelFromKey: "test", + }, + }, + }, + }, + }, + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + v, err := NewCustomResourceMetrics(tt.r) + expectedError := v.(*customResourceMetrics).Families[0].Each.Type() != "info" + if (err != nil) != tt.wantErr || expectedError { + t.Errorf("NewCustomResourceMetrics() error = %v, wantErr %v", err, tt.wantErr) + return + } + }) + } +} diff --git a/pkg/customresourcestate/registry_factory.go b/pkg/customresourcestate/registry_factory.go index 2c9ae80297..e027cae8e7 100644 --- a/pkg/customresourcestate/registry_factory.go +++ b/pkg/customresourcestate/registry_factory.go @@ -118,6 +118,7 @@ type compiledEach compiledMetric type compiledCommon struct { labelFromPath map[string]valuePath path valuePath + t metric.Type } func (c compiledCommon) Path() valuePath { @@ -126,6 +127,9 @@ func (c compiledCommon) Path() valuePath { func (c compiledCommon) LabelFromPath() map[string]valuePath { return c.labelFromPath } +func (c compiledCommon) Type() metric.Type { + return c.t +} type eachValue struct { Labels map[string]string @@ -136,6 +140,7 @@ type compiledMetric interface { Values(v interface{}) (result []eachValue, err []error) Path() valuePath LabelFromPath() map[string]valuePath + Type() metric.Type } // newCompiledMetric returns a compiledMetric depending given the metric type. @@ -146,6 +151,7 @@ func newCompiledMetric(m Metric) (compiledMetric, error) { return nil, errors.New("expected each.gauge to not be nil") } cc, err := compileCommon(m.Gauge.MetricMeta) + cc.t = metric.Gauge if err != nil { return nil, fmt.Errorf("each.gauge: %w", err) } @@ -164,6 +170,7 @@ func newCompiledMetric(m Metric) (compiledMetric, error) { return nil, errors.New("expected each.info to not be nil") } cc, err := compileCommon(m.Info.MetricMeta) + cc.t = metric.Info if err != nil { return nil, fmt.Errorf("each.info: %w", err) } @@ -176,6 +183,7 @@ func newCompiledMetric(m Metric) (compiledMetric, error) { return nil, errors.New("expected each.stateSet to not be nil") } cc, err := compileCommon(m.StateSet.MetricMeta) + cc.t = metric.StateSet if err != nil { return nil, fmt.Errorf("each.stateSet: %w", err) } @@ -569,8 +577,7 @@ func famGen(f compiledFamily) generator.FamilyGenerator { errLog := klog.V(f.ErrorLogV) return generator.FamilyGenerator{ Name: f.Name, - // TODO(@rexagod): This should be dynamic. - Type: metric.Gauge, + Type: f.Each.Type(), Help: f.Help, GenerateFunc: func(obj interface{}) *metric.Family { return generate(obj.(*unstructured.Unstructured), f, errLog) diff --git a/pkg/metric/metric.go b/pkg/metric/metric.go index 96bf8c8063..007eb9fa87 100644 --- a/pkg/metric/metric.go +++ b/pkg/metric/metric.go @@ -38,13 +38,19 @@ var ( ) // Type represents the type of a metric e.g. a counter. See -// https://prometheus.io/docs/concepts/metric_types/. +// https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#metric-types. type Type string -// Gauge defines a Prometheus gauge. +// Gauge defines a OpenMetrics gauge. var Gauge Type = "gauge" -// Counter defines a Prometheus counter. +// Info defines an OpenMetrics info. +var Info Type = "info" + +// StateSet defines an OpenMetrics stateset. +var StateSet Type = "stateset" + +// Counter defines a OpenMetrics counter. var Counter Type = "counter" // Metric represents a single time series. From 62f3fc2983d1ee5f3a9fee83e089eac50a4f48bf Mon Sep 17 00:00:00 2001 From: Catherine Fang Date: Tue, 20 Dec 2022 10:02:26 -0500 Subject: [PATCH 69/70] Add develop doc on adding new metrics --- docs/developer/guide.md | 11 +++++++++++ docs/statefulset-metrics.md | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/developer/guide.md b/docs/developer/guide.md index 6600d19a4a..81be3e7e48 100644 --- a/docs/developer/guide.md +++ b/docs/developer/guide.md @@ -6,6 +6,7 @@ Any contribution to improving this documentation will be appreciated. ## Table of Contents - [Add New Kubernetes Resource Metric Collector](#add-new-kubernetes-resource-metric-collector) +- [Add New Metrics](#add-new-metrics) ### Add New Kubernetes Resource Metric Collector @@ -20,3 +21,13 @@ The following steps are needed to introduce a new resource and its respective re - Reference the new resource in [pkg/options/resource.go](https://github.com/kubernetes/kube-state-metrics/blob/main/pkg/options/resource.go). - Add a sample Kubernetes manifest to be used by tests in the [tests/manifests/](https://github.com/kubernetes/kube-state-metrics/tree/main/tests/manifests) directory. - Lastly, and most importantly, actually implement your new resource(s) and its test binary in [internal/store](https://github.com/kubernetes/kube-state-metrics/tree/main/internal/store). Follow the formatting and structure of other resources. + +### Add New Metrics + +- Make metrics experimental first when introducing them, [Example PR](https://github.com/kubernetes/kube-state-metrics/pull/1910). + +| Metric stability level | | +|------------------------|--------------------| +| EXPERIMENTAL | basemetrics.ALPHA | +| STABLE | basemetrics.STABLE | + diff --git a/docs/statefulset-metrics.md b/docs/statefulset-metrics.md index 00850ff954..e7d0aa567e 100644 --- a/docs/statefulset-metrics.md +++ b/docs/statefulset-metrics.md @@ -11,7 +11,7 @@ | kube_statefulset_status_observed_generation | Gauge | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | STABLE | | kube_statefulset_replicas | Gauge | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | STABLE | | kube_statefulset_metadata_generation | Gauge | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | STABLE | -| kube_statefulset_persistentvolumeclaim_retention_policy | Gauge | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace>
`when_deleted`=<statefulset-when-deleted-pvc-policy>
`when_scaled`=<statefulset-when-scaled-pvc-policy> | ALPHA | +| kube_statefulset_persistentvolumeclaim_retention_policy | Gauge | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace>
`when_deleted`=<statefulset-when-deleted-pvc-policy>
`when_scaled`=<statefulset-when-scaled-pvc-policy> | EXPERIMENTAL | | kube_statefulset_created | Gauge | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | STABLE | | kube_statefulset_labels | Gauge | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace>
`label_STATEFULSET_LABEL`=<STATEFULSET_LABEL> | STABLE | | kube_statefulset_status_current_revision | Gauge | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace>
`revision`=<statefulset-current-revision> | STABLE | From 022fce9d9b92d95a288610b887b4fba7d75dfe6b Mon Sep 17 00:00:00 2001 From: CatherineF-dev Date: Wed, 21 Dec 2022 09:34:40 -0500 Subject: [PATCH 70/70] Update docs/developer/guide.md Co-authored-by: Pranshu Srivastava --- docs/developer/guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer/guide.md b/docs/developer/guide.md index 81be3e7e48..eb5a72e51b 100644 --- a/docs/developer/guide.md +++ b/docs/developer/guide.md @@ -24,7 +24,7 @@ The following steps are needed to introduce a new resource and its respective re ### Add New Metrics -- Make metrics experimental first when introducing them, [Example PR](https://github.com/kubernetes/kube-state-metrics/pull/1910). +- Make metrics experimental first when introducing them, refer [#1910](https://github.com/kubernetes/kube-state-metrics/pull/1910) for more information. | Metric stability level | | |------------------------|--------------------|