mirror of
https://github.com/kubernetes-sigs/prometheus-adapter.git
synced 2026-04-06 01:38:10 +00:00
Update metrics apiserver to support filtering by labels
This commit is contained in:
parent
03bc47e9fb
commit
d091fff18b
11 changed files with 331 additions and 187 deletions
|
|
@ -118,8 +118,8 @@ func (p *prometheusProvider) metricsFor(valueSet pmodel.Vector, info provider.Cu
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (p *prometheusProvider) buildQuery(info provider.CustomMetricInfo, namespace string, names ...string) (pmodel.Vector, error) {
|
||||
query, found := p.QueryForMetric(info, namespace, names...)
|
||||
func (p *prometheusProvider) buildQuery(info provider.CustomMetricInfo, namespace string, metricSelector labels.Selector, names ...string) (pmodel.Vector, error) {
|
||||
query, found := p.QueryForMetric(info, namespace, metricSelector, names...)
|
||||
if !found {
|
||||
return nil, provider.NewMetricNotFoundError(info.GroupResource, info.Metric)
|
||||
}
|
||||
|
|
@ -140,9 +140,9 @@ func (p *prometheusProvider) buildQuery(info provider.CustomMetricInfo, namespac
|
|||
return *queryResults.Vector, nil
|
||||
}
|
||||
|
||||
func (p *prometheusProvider) GetMetricByName(name types.NamespacedName, info provider.CustomMetricInfo) (*custom_metrics.MetricValue, error) {
|
||||
func (p *prometheusProvider) GetMetricByName(name types.NamespacedName, info provider.CustomMetricInfo, metricSelector labels.Selector) (*custom_metrics.MetricValue, error) {
|
||||
// construct a query
|
||||
queryResults, err := p.buildQuery(info, name.Namespace, name.Name)
|
||||
queryResults, err := p.buildQuery(info, name.Namespace, metricSelector, name.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -171,7 +171,7 @@ func (p *prometheusProvider) GetMetricByName(name types.NamespacedName, info pro
|
|||
return p.metricFor(resultValue, name, info)
|
||||
}
|
||||
|
||||
func (p *prometheusProvider) GetMetricBySelector(namespace string, selector labels.Selector, info provider.CustomMetricInfo) (*custom_metrics.MetricValueList, error) {
|
||||
func (p *prometheusProvider) GetMetricBySelector(namespace string, selector labels.Selector, info provider.CustomMetricInfo, metricSelector labels.Selector) (*custom_metrics.MetricValueList, error) {
|
||||
// fetch a list of relevant resource names
|
||||
resourceNames, err := helpers.ListObjectNames(p.mapper, p.kubeClient, namespace, selector, info)
|
||||
if err != nil {
|
||||
|
|
@ -181,7 +181,7 @@ func (p *prometheusProvider) GetMetricBySelector(namespace string, selector labe
|
|||
}
|
||||
|
||||
// construct the actual query
|
||||
queryResults, err := p.buildQuery(info, namespace, resourceNames...)
|
||||
queryResults, err := p.buildQuery(info, namespace, metricSelector, resourceNames...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import (
|
|||
|
||||
"github.com/kubernetes-incubator/custom-metrics-apiserver/pkg/provider"
|
||||
apimeta "k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
|
||||
prom "github.com/directxman12/k8s-prometheus-adapter/pkg/client"
|
||||
"github.com/directxman12/k8s-prometheus-adapter/pkg/naming"
|
||||
|
|
@ -51,7 +52,7 @@ type SeriesRegistry interface {
|
|||
ListAllMetrics() []provider.CustomMetricInfo
|
||||
// SeriesForMetric looks up the minimum required series information to make a query for the given metric
|
||||
// against the given resource (namespace may be empty for non-namespaced resources)
|
||||
QueryForMetric(info provider.CustomMetricInfo, namespace string, resourceNames ...string) (query prom.Selector, found bool)
|
||||
QueryForMetric(info provider.CustomMetricInfo, namespace string, metricSelector labels.Selector, resourceNames ...string) (query prom.Selector, found bool)
|
||||
// MatchValuesToNames matches result values to resource names for the given metric and value set
|
||||
MatchValuesToNames(metricInfo provider.CustomMetricInfo, values pmodel.Vector) (matchedValues map[string]pmodel.SampleValue, found bool)
|
||||
}
|
||||
|
|
@ -135,7 +136,7 @@ func (r *basicSeriesRegistry) ListAllMetrics() []provider.CustomMetricInfo {
|
|||
return r.metrics
|
||||
}
|
||||
|
||||
func (r *basicSeriesRegistry) QueryForMetric(metricInfo provider.CustomMetricInfo, namespace string, resourceNames ...string) (prom.Selector, bool) {
|
||||
func (r *basicSeriesRegistry) QueryForMetric(metricInfo provider.CustomMetricInfo, namespace string, metricSelector labels.Selector, resourceNames ...string) (prom.Selector, bool) {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
|
||||
|
|
@ -156,7 +157,7 @@ func (r *basicSeriesRegistry) QueryForMetric(metricInfo provider.CustomMetricInf
|
|||
return "", false
|
||||
}
|
||||
|
||||
query, err := info.namer.QueryForSeries(info.seriesName, metricInfo.GroupResource, namespace, resourceNames...)
|
||||
query, err := info.namer.QueryForSeries(info.seriesName, metricInfo.GroupResource, namespace, metricSelector, resourceNames...)
|
||||
if err != nil {
|
||||
klog.Errorf("unable to construct query for metric %s: %v", metricInfo.String(), err)
|
||||
return "", false
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ import (
|
|||
coreapi "k8s.io/api/core/v1"
|
||||
extapi "k8s.io/api/extensions/v1beta1"
|
||||
apimeta "k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/selection"
|
||||
|
||||
config "github.com/directxman12/k8s-prometheus-adapter/cmd/config-gen/utils"
|
||||
prom "github.com/directxman12/k8s-prometheus-adapter/pkg/client"
|
||||
|
|
@ -118,14 +120,23 @@ var seriesRegistryTestSeries = [][]prom.Series{
|
|||
}
|
||||
|
||||
type regTestCase struct {
|
||||
title string
|
||||
info provider.CustomMetricInfo
|
||||
namespace string
|
||||
resourceNames []string
|
||||
title string
|
||||
info provider.CustomMetricInfo
|
||||
namespace string
|
||||
resourceNames []string
|
||||
metricSelector labels.Selector
|
||||
|
||||
expectedQuery string
|
||||
}
|
||||
|
||||
func mustNewLabelRequirement(key string, op selection.Operator, vals []string) *labels.Requirement {
|
||||
req, err := labels.NewRequirement(key, op, vals)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return req
|
||||
}
|
||||
|
||||
var _ = Describe("Series Registry", func() {
|
||||
var (
|
||||
registry *basicSeriesRegistry
|
||||
|
|
@ -144,89 +155,110 @@ var _ = Describe("Series Registry", func() {
|
|||
testCases := []regTestCase{
|
||||
// container metrics
|
||||
{
|
||||
title: "container metrics gauge / multiple resource names",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "pods"}, true, "some_usage"},
|
||||
namespace: "somens",
|
||||
resourceNames: []string{"somepod1", "somepod2"},
|
||||
title: "container metrics gauge / multiple resource names",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "pods"}, true, "some_usage"},
|
||||
namespace: "somens",
|
||||
resourceNames: []string{"somepod1", "somepod2"},
|
||||
metricSelector: labels.Everything(),
|
||||
|
||||
expectedQuery: "sum(container_some_usage{namespace=\"somens\",pod_name=~\"somepod1|somepod2\",container_name!=\"POD\"}) by (pod_name)",
|
||||
},
|
||||
{
|
||||
title: "container metrics counter",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "pods"}, true, "some_count"},
|
||||
namespace: "somens",
|
||||
resourceNames: []string{"somepod1", "somepod2"},
|
||||
title: "container metrics counter",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "pods"}, true, "some_count"},
|
||||
namespace: "somens",
|
||||
resourceNames: []string{"somepod1", "somepod2"},
|
||||
metricSelector: labels.Everything(),
|
||||
|
||||
expectedQuery: "sum(rate(container_some_count_total{namespace=\"somens\",pod_name=~\"somepod1|somepod2\",container_name!=\"POD\"}[1m])) by (pod_name)",
|
||||
},
|
||||
{
|
||||
title: "container metrics seconds counter",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "pods"}, true, "some_time"},
|
||||
namespace: "somens",
|
||||
resourceNames: []string{"somepod1", "somepod2"},
|
||||
title: "container metrics seconds counter",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "pods"}, true, "some_time"},
|
||||
namespace: "somens",
|
||||
resourceNames: []string{"somepod1", "somepod2"},
|
||||
metricSelector: labels.Everything(),
|
||||
|
||||
expectedQuery: "sum(rate(container_some_time_seconds_total{namespace=\"somens\",pod_name=~\"somepod1|somepod2\",container_name!=\"POD\"}[1m])) by (pod_name)",
|
||||
},
|
||||
// namespaced metrics
|
||||
{
|
||||
title: "namespaced metrics counter / multidimensional (service)",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "service"}, true, "ingress_hits"},
|
||||
namespace: "somens",
|
||||
resourceNames: []string{"somesvc"},
|
||||
title: "namespaced metrics counter / multidimensional (service)",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "service"}, true, "ingress_hits"},
|
||||
namespace: "somens",
|
||||
resourceNames: []string{"somesvc"},
|
||||
metricSelector: labels.Everything(),
|
||||
|
||||
expectedQuery: "sum(rate(ingress_hits_total{kube_namespace=\"somens\",kube_service=\"somesvc\"}[1m])) by (kube_service)",
|
||||
},
|
||||
{
|
||||
title: "namespaced metrics counter / multidimensional (ingress)",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Group: "extensions", Resource: "ingress"}, true, "ingress_hits"},
|
||||
title: "namespaced metrics counter / multidimensional (service) / selection using labels",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "service"}, true, "ingress_hits"},
|
||||
namespace: "somens",
|
||||
resourceNames: []string{"someingress"},
|
||||
resourceNames: []string{"somesvc"},
|
||||
metricSelector: labels.NewSelector().Add(
|
||||
*mustNewLabelRequirement("param1", selection.Equals, []string{"value1"}),
|
||||
),
|
||||
expectedQuery: "sum(rate(ingress_hits_total{param1=\"value1\",kube_namespace=\"somens\",kube_service=\"somesvc\"}[1m])) by (kube_service)",
|
||||
},
|
||||
{
|
||||
title: "namespaced metrics counter / multidimensional (ingress)",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Group: "extensions", Resource: "ingress"}, true, "ingress_hits"},
|
||||
namespace: "somens",
|
||||
resourceNames: []string{"someingress"},
|
||||
metricSelector: labels.Everything(),
|
||||
|
||||
expectedQuery: "sum(rate(ingress_hits_total{kube_namespace=\"somens\",kube_ingress=\"someingress\"}[1m])) by (kube_ingress)",
|
||||
},
|
||||
{
|
||||
title: "namespaced metrics counter / multidimensional (pod)",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "pod"}, true, "ingress_hits"},
|
||||
namespace: "somens",
|
||||
resourceNames: []string{"somepod"},
|
||||
title: "namespaced metrics counter / multidimensional (pod)",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "pod"}, true, "ingress_hits"},
|
||||
namespace: "somens",
|
||||
resourceNames: []string{"somepod"},
|
||||
metricSelector: labels.Everything(),
|
||||
|
||||
expectedQuery: "sum(rate(ingress_hits_total{kube_namespace=\"somens\",kube_pod=\"somepod\"}[1m])) by (kube_pod)",
|
||||
},
|
||||
{
|
||||
title: "namespaced metrics gauge",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "service"}, true, "service_proxy_packets"},
|
||||
namespace: "somens",
|
||||
resourceNames: []string{"somesvc"},
|
||||
title: "namespaced metrics gauge",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "service"}, true, "service_proxy_packets"},
|
||||
namespace: "somens",
|
||||
resourceNames: []string{"somesvc"},
|
||||
metricSelector: labels.Everything(),
|
||||
|
||||
expectedQuery: "sum(service_proxy_packets{kube_namespace=\"somens\",kube_service=\"somesvc\"}) by (kube_service)",
|
||||
},
|
||||
{
|
||||
title: "namespaced metrics seconds counter",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Group: "extensions", Resource: "deployment"}, true, "work_queue_wait"},
|
||||
namespace: "somens",
|
||||
resourceNames: []string{"somedep"},
|
||||
title: "namespaced metrics seconds counter",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Group: "extensions", Resource: "deployment"}, true, "work_queue_wait"},
|
||||
namespace: "somens",
|
||||
resourceNames: []string{"somedep"},
|
||||
metricSelector: labels.Everything(),
|
||||
|
||||
expectedQuery: "sum(rate(work_queue_wait_seconds_total{kube_namespace=\"somens\",kube_deployment=\"somedep\"}[1m])) by (kube_deployment)",
|
||||
},
|
||||
// non-namespaced series
|
||||
{
|
||||
title: "root scoped metrics gauge",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "node"}, false, "node_gigawatts"},
|
||||
resourceNames: []string{"somenode"},
|
||||
title: "root scoped metrics gauge",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "node"}, false, "node_gigawatts"},
|
||||
resourceNames: []string{"somenode"},
|
||||
metricSelector: labels.Everything(),
|
||||
|
||||
expectedQuery: "sum(node_gigawatts{kube_node=\"somenode\"}) by (kube_node)",
|
||||
},
|
||||
{
|
||||
title: "root scoped metrics counter",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "persistentvolume"}, false, "volume_claims"},
|
||||
resourceNames: []string{"somepv"},
|
||||
title: "root scoped metrics counter",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "persistentvolume"}, false, "volume_claims"},
|
||||
resourceNames: []string{"somepv"},
|
||||
metricSelector: labels.Everything(),
|
||||
|
||||
expectedQuery: "sum(rate(volume_claims_total{kube_persistentvolume=\"somepv\"}[1m])) by (kube_persistentvolume)",
|
||||
},
|
||||
{
|
||||
title: "root scoped metrics seconds counter",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "node"}, false, "node_fan"},
|
||||
resourceNames: []string{"somenode"},
|
||||
title: "root scoped metrics seconds counter",
|
||||
info: provider.CustomMetricInfo{schema.GroupResource{Resource: "node"}, false, "node_fan"},
|
||||
resourceNames: []string{"somenode"},
|
||||
metricSelector: labels.Everything(),
|
||||
|
||||
expectedQuery: "sum(rate(node_fan_seconds_total{kube_node=\"somenode\"}[1m])) by (kube_node)",
|
||||
},
|
||||
|
|
@ -236,7 +268,7 @@ var _ = Describe("Series Registry", func() {
|
|||
tc := tc // copy to avoid iteration variable issues
|
||||
It(fmt.Sprintf("should build a query for %s", tc.title), func() {
|
||||
By(fmt.Sprintf("composing the query for the %s metric on %v in namespace %s", tc.info, tc.resourceNames, tc.namespace))
|
||||
outputQuery, found := registry.QueryForMetric(tc.info, tc.namespace, tc.resourceNames...)
|
||||
outputQuery, found := registry.QueryForMetric(tc.info, tc.namespace, tc.metricSelector, tc.resourceNames...)
|
||||
Expect(found).To(BeTrue(), "metric %s should be available", tc.info)
|
||||
|
||||
By("verifying that the query is as expected")
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ type MetricNamer interface {
|
|||
MetricNameForSeries(series prom.Series) (string, error)
|
||||
// QueryForSeries returns the query for a given series (not API metric name), with
|
||||
// the given namespace name (if relevant), resource, and resource names.
|
||||
QueryForSeries(series string, resource schema.GroupResource, namespace string, names ...string) (prom.Selector, error)
|
||||
QueryForSeries(series string, resource schema.GroupResource, namespace string, metricSelector labels.Selector, names ...string) (prom.Selector, error)
|
||||
// QueryForExternalSeries returns the query for a given series (not API metric name), with
|
||||
// the given namespace name (if relevant), resource, and resource names.
|
||||
QueryForExternalSeries(series string, namespace string, targetLabels labels.Selector) (prom.Selector, error)
|
||||
|
|
@ -126,8 +126,8 @@ SeriesLoop:
|
|||
return finalSeries
|
||||
}
|
||||
|
||||
func (n *metricNamer) QueryForSeries(series string, resource schema.GroupResource, namespace string, names ...string) (prom.Selector, error) {
|
||||
return n.metricsQuery.Build(series, resource, namespace, nil, names...)
|
||||
func (n *metricNamer) QueryForSeries(series string, resource schema.GroupResource, namespace string, metricSelector labels.Selector, names ...string) (prom.Selector, error) {
|
||||
return n.metricsQuery.Build(series, resource, namespace, nil, metricSelector, names...)
|
||||
}
|
||||
|
||||
func (n *metricNamer) QueryForExternalSeries(series string, namespace string, metricSelector labels.Selector) (prom.Selector, error) {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ type MetricsQuery interface {
|
|||
// is considered to be root-scoped. extraGroupBy may be used for cases
|
||||
// where we need to scope down more specifically than just the group-resource
|
||||
// (e.g. container metrics).
|
||||
Build(series string, groupRes schema.GroupResource, namespace string, extraGroupBy []string, resourceNames ...string) (prom.Selector, error)
|
||||
Build(series string, groupRes schema.GroupResource, namespace string, extraGroupBy []string, metricSelector labels.Selector, resourceNames ...string) (prom.Selector, error)
|
||||
BuildExternal(seriesName string, namespace string, groupBy string, groupBySlice []string, metricSelector labels.Selector) (prom.Selector, error)
|
||||
}
|
||||
|
||||
|
|
@ -85,17 +85,25 @@ type queryPart struct {
|
|||
operator selection.Operator
|
||||
}
|
||||
|
||||
func (q *metricsQuery) Build(series string, resource schema.GroupResource, namespace string, extraGroupBy []string, names ...string) (prom.Selector, error) {
|
||||
var exprs []string
|
||||
valuesByName := map[string]string{}
|
||||
func (q *metricsQuery) Build(series string, resource schema.GroupResource, namespace string, extraGroupBy []string, metricSelector labels.Selector, names ...string) (prom.Selector, error) {
|
||||
queryParts := q.createQueryPartsFromSelector(metricSelector)
|
||||
|
||||
if namespace != "" {
|
||||
namespaceLbl, err := q.resConverter.LabelForResource(NsGroupResource)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
exprs = append(exprs, prom.LabelEq(string(namespaceLbl), namespace))
|
||||
valuesByName[string(namespaceLbl)] = namespace
|
||||
|
||||
queryParts = append(queryParts, queryPart{
|
||||
labelName: string(namespaceLbl),
|
||||
values: []string{namespace},
|
||||
operator: selection.Equals,
|
||||
})
|
||||
}
|
||||
|
||||
exprs, valuesByName, err := q.processQueryParts(queryParts)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
resourceLbl, err := q.resConverter.LabelForResource(resource)
|
||||
|
|
|
|||
|
|
@ -83,23 +83,33 @@ func TestBuildSelector(t *testing.T) {
|
|||
return mq
|
||||
}
|
||||
|
||||
mustNewLabelRequirement := func(key string, op selection.Operator, vals []string) *labels.Requirement {
|
||||
req, err := labels.NewRequirement(key, op, vals)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return req
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
mq MetricsQuery
|
||||
|
||||
series string
|
||||
resource schema.GroupResource
|
||||
namespace string
|
||||
extraGroupBy []string
|
||||
names []string
|
||||
series string
|
||||
resource schema.GroupResource
|
||||
namespace string
|
||||
extraGroupBy []string
|
||||
metricSelector labels.Selector
|
||||
names []string
|
||||
|
||||
check checkFunc
|
||||
}{
|
||||
{
|
||||
name: "series",
|
||||
|
||||
mq: mustNewQuery(`series <<.Series>>`, false),
|
||||
series: "foo",
|
||||
mq: mustNewQuery(`series <<.Series>>`, false),
|
||||
metricSelector: labels.NewSelector(),
|
||||
series: "foo",
|
||||
|
||||
check: checks(
|
||||
hasError(nil),
|
||||
|
|
@ -110,9 +120,10 @@ func TestBuildSelector(t *testing.T) {
|
|||
{
|
||||
name: "multiple LabelMatchers values",
|
||||
|
||||
mq: mustNewQuery(`<<.LabelMatchers>>`, false),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
names: []string{"bar", "baz"},
|
||||
mq: mustNewQuery(`<<.LabelMatchers>>`, false),
|
||||
metricSelector: labels.NewSelector(),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
names: []string{"bar", "baz"},
|
||||
|
||||
check: checks(
|
||||
hasError(nil),
|
||||
|
|
@ -123,9 +134,10 @@ func TestBuildSelector(t *testing.T) {
|
|||
{
|
||||
name: "single LabelMatchers value",
|
||||
|
||||
mq: mustNewQuery(`<<.LabelMatchers>>`, false),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
names: []string{"bar"},
|
||||
mq: mustNewQuery(`<<.LabelMatchers>>`, false),
|
||||
metricSelector: labels.NewSelector(),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
names: []string{"bar"},
|
||||
|
||||
check: checks(
|
||||
hasError(nil),
|
||||
|
|
@ -134,12 +146,29 @@ func TestBuildSelector(t *testing.T) {
|
|||
},
|
||||
|
||||
{
|
||||
name: "single LabelValuesByName value",
|
||||
name: "LabelMatchers with additional metrics filter",
|
||||
|
||||
mq: mustNewQuery(`<<index .LabelValuesByName "resource">>`, false),
|
||||
mq: mustNewQuery(`<<.LabelMatchers>>`, false),
|
||||
metricSelector: labels.NewSelector().Add(
|
||||
*mustNewLabelRequirement("metric1", selection.Equals, []string{"value1"}),
|
||||
),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
names: []string{"bar"},
|
||||
|
||||
check: checks(
|
||||
hasError(nil),
|
||||
hasSelector(`metric1="value1",resource="bar"`),
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
name: "single LabelValuesByName value",
|
||||
|
||||
mq: mustNewQuery(`<<index .LabelValuesByName "resource">>`, false),
|
||||
metricSelector: labels.NewSelector(),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
names: []string{"bar"},
|
||||
|
||||
check: checks(
|
||||
hasError(nil),
|
||||
hasSelector("bar"),
|
||||
|
|
@ -149,9 +178,10 @@ func TestBuildSelector(t *testing.T) {
|
|||
{
|
||||
name: "multiple LabelValuesByName values",
|
||||
|
||||
mq: mustNewQuery(`<<index .LabelValuesByName "resource">>`, false),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
names: []string{"bar", "baz"},
|
||||
mq: mustNewQuery(`<<index .LabelValuesByName "resource">>`, false),
|
||||
metricSelector: labels.NewSelector(),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
names: []string{"bar", "baz"},
|
||||
|
||||
check: checks(
|
||||
hasError(nil),
|
||||
|
|
@ -162,10 +192,11 @@ func TestBuildSelector(t *testing.T) {
|
|||
{
|
||||
name: "multiple LabelValuesByName values with namespace",
|
||||
|
||||
mq: mustNewQuery(`<<index .LabelValuesByName "namespaces">> <<index .LabelValuesByName "resource">>`, true),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
namespace: "default",
|
||||
names: []string{"bar", "baz"},
|
||||
mq: mustNewQuery(`<<index .LabelValuesByName "namespaces">> <<index .LabelValuesByName "resource">>`, true),
|
||||
metricSelector: labels.NewSelector(),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
namespace: "default",
|
||||
names: []string{"bar", "baz"},
|
||||
|
||||
check: checks(
|
||||
hasError(nil),
|
||||
|
|
@ -176,8 +207,9 @@ func TestBuildSelector(t *testing.T) {
|
|||
{
|
||||
name: "single GroupBy value",
|
||||
|
||||
mq: mustNewQuery(`<<.GroupBy>>`, false),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
mq: mustNewQuery(`<<.GroupBy>>`, false),
|
||||
metricSelector: labels.NewSelector(),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
|
||||
check: checks(
|
||||
hasError(nil),
|
||||
|
|
@ -188,9 +220,10 @@ func TestBuildSelector(t *testing.T) {
|
|||
{
|
||||
name: "multiple GroupBy values",
|
||||
|
||||
mq: mustNewQuery(`<<.GroupBy>>`, false),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
extraGroupBy: []string{"extra", "groups"},
|
||||
mq: mustNewQuery(`<<.GroupBy>>`, false),
|
||||
metricSelector: labels.NewSelector(),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
extraGroupBy: []string{"extra", "groups"},
|
||||
|
||||
check: checks(
|
||||
hasError(nil),
|
||||
|
|
@ -201,8 +234,9 @@ func TestBuildSelector(t *testing.T) {
|
|||
{
|
||||
name: "single GroupBySlice value",
|
||||
|
||||
mq: mustNewQuery(`<<.GroupBySlice>>`, false),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
mq: mustNewQuery(`<<.GroupBySlice>>`, false),
|
||||
metricSelector: labels.NewSelector(),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
|
||||
check: checks(
|
||||
hasError(nil),
|
||||
|
|
@ -213,9 +247,10 @@ func TestBuildSelector(t *testing.T) {
|
|||
{
|
||||
name: "multiple GroupBySlice values",
|
||||
|
||||
mq: mustNewQuery(`<<.GroupBySlice>>`, false),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
extraGroupBy: []string{"extra", "groups"},
|
||||
mq: mustNewQuery(`<<.GroupBySlice>>`, false),
|
||||
metricSelector: labels.NewSelector(),
|
||||
resource: schema.GroupResource{Group: "group", Resource: "resource"},
|
||||
extraGroupBy: []string{"extra", "groups"},
|
||||
|
||||
check: checks(
|
||||
hasError(nil),
|
||||
|
|
@ -226,7 +261,7 @@ func TestBuildSelector(t *testing.T) {
|
|||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
selector, err := tc.mq.Build(tc.series, tc.resource, tc.namespace, tc.extraGroupBy, tc.names...)
|
||||
selector, err := tc.mq.Build(tc.series, tc.resource, tc.namespace, tc.extraGroupBy, tc.metricSelector, tc.names...)
|
||||
|
||||
if err := tc.check(selector, err); err != nil {
|
||||
t.Error(err)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import (
|
|||
corev1 "k8s.io/api/core/v1"
|
||||
apimeta "k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
apitypes "k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/klog"
|
||||
|
|
@ -347,10 +348,10 @@ func (p *resourceProvider) runQuery(now pmodel.Time, queryInfo resourceQuery, re
|
|||
|
||||
// build the query, which needs the special "container" group by if this is for pod metrics
|
||||
if resource == nodeResource {
|
||||
query, err = queryInfo.nodeQuery.Build("", resource, namespace, nil, names...)
|
||||
query, err = queryInfo.nodeQuery.Build("", resource, namespace, nil, labels.Everything(), names...)
|
||||
} else {
|
||||
extraGroupBy := []string{queryInfo.containerLabel}
|
||||
query, err = queryInfo.contQuery.Build("", resource, namespace, extraGroupBy, names...)
|
||||
query, err = queryInfo.contQuery.Build("", resource, namespace, extraGroupBy, labels.Everything(), names...)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to construct query: %v", err)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import (
|
|||
corev1 "k8s.io/api/core/v1"
|
||||
apimeta "k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/metrics/pkg/apis/metrics"
|
||||
|
|
@ -124,22 +125,22 @@ var _ = Describe("Resource Metrics Provider", func() {
|
|||
{Namespace: "other-ns", Name: "pod27"},
|
||||
}
|
||||
fakeProm.QueryResults = map[prom.Selector]prom.QueryResult{
|
||||
mustBuild(cpuQueries.contQuery.Build("", podResource, "some-ns", []string{cpuQueries.containerLabel}, "pod1", "pod3")): buildQueryRes("container_cpu_usage_seconds_total",
|
||||
mustBuild(cpuQueries.contQuery.Build("", podResource, "some-ns", []string{cpuQueries.containerLabel}, labels.Everything(), "pod1", "pod3")): buildQueryRes("container_cpu_usage_seconds_total",
|
||||
buildPodSample("some-ns", "pod1", "cont1", 1100.0, 10),
|
||||
buildPodSample("some-ns", "pod1", "cont2", 1110.0, 20),
|
||||
buildPodSample("some-ns", "pod3", "cont1", 1300.0, 10),
|
||||
buildPodSample("some-ns", "pod3", "cont2", 1310.0, 20),
|
||||
),
|
||||
mustBuild(cpuQueries.contQuery.Build("", podResource, "other-ns", []string{cpuQueries.containerLabel}, "pod27")): buildQueryRes("container_cpu_usage_seconds_total",
|
||||
mustBuild(cpuQueries.contQuery.Build("", podResource, "other-ns", []string{cpuQueries.containerLabel}, labels.Everything(), "pod27")): buildQueryRes("container_cpu_usage_seconds_total",
|
||||
buildPodSample("other-ns", "pod27", "cont1", 2200.0, 270),
|
||||
),
|
||||
mustBuild(memQueries.contQuery.Build("", podResource, "some-ns", []string{cpuQueries.containerLabel}, "pod1", "pod3")): buildQueryRes("container_memory_working_set_bytes",
|
||||
mustBuild(memQueries.contQuery.Build("", podResource, "some-ns", []string{cpuQueries.containerLabel}, labels.Everything(), "pod1", "pod3")): buildQueryRes("container_memory_working_set_bytes",
|
||||
buildPodSample("some-ns", "pod1", "cont1", 3100.0, 11),
|
||||
buildPodSample("some-ns", "pod1", "cont2", 3110.0, 21),
|
||||
buildPodSample("some-ns", "pod3", "cont1", 3300.0, 11),
|
||||
buildPodSample("some-ns", "pod3", "cont2", 3310.0, 21),
|
||||
),
|
||||
mustBuild(memQueries.contQuery.Build("", podResource, "other-ns", []string{cpuQueries.containerLabel}, "pod27")): buildQueryRes("container_memory_working_set_bytes",
|
||||
mustBuild(memQueries.contQuery.Build("", podResource, "other-ns", []string{cpuQueries.containerLabel}, labels.Everything(), "pod27")): buildQueryRes("container_memory_working_set_bytes",
|
||||
buildPodSample("other-ns", "pod27", "cont1", 4200.0, 271),
|
||||
),
|
||||
}
|
||||
|
|
@ -173,11 +174,11 @@ var _ = Describe("Resource Metrics Provider", func() {
|
|||
|
||||
It("should return nil metrics for missing pods, but still return partial results", func() {
|
||||
fakeProm.QueryResults = map[prom.Selector]prom.QueryResult{
|
||||
mustBuild(cpuQueries.contQuery.Build("", podResource, "some-ns", []string{cpuQueries.containerLabel}, "pod1", "pod-nonexistant")): buildQueryRes("container_cpu_usage_seconds_total",
|
||||
mustBuild(cpuQueries.contQuery.Build("", podResource, "some-ns", []string{cpuQueries.containerLabel}, labels.Everything(), "pod1", "pod-nonexistant")): buildQueryRes("container_cpu_usage_seconds_total",
|
||||
buildPodSample("some-ns", "pod1", "cont1", 1100.0, 10),
|
||||
buildPodSample("some-ns", "pod1", "cont2", 1110.0, 20),
|
||||
),
|
||||
mustBuild(memQueries.contQuery.Build("", podResource, "some-ns", []string{cpuQueries.containerLabel}, "pod1", "pod-nonexistant")): buildQueryRes("container_memory_working_set_bytes",
|
||||
mustBuild(memQueries.contQuery.Build("", podResource, "some-ns", []string{cpuQueries.containerLabel}, labels.Everything(), "pod1", "pod-nonexistant")): buildQueryRes("container_memory_working_set_bytes",
|
||||
buildPodSample("some-ns", "pod1", "cont1", 3100.0, 11),
|
||||
buildPodSample("some-ns", "pod1", "cont2", 3110.0, 21),
|
||||
),
|
||||
|
|
@ -205,11 +206,11 @@ var _ = Describe("Resource Metrics Provider", func() {
|
|||
|
||||
It("should be able to list metrics for nodes", func() {
|
||||
fakeProm.QueryResults = map[prom.Selector]prom.QueryResult{
|
||||
mustBuild(cpuQueries.nodeQuery.Build("", nodeResource, "", nil, "node1", "node2")): buildQueryRes("container_cpu_usage_seconds_total",
|
||||
mustBuild(cpuQueries.nodeQuery.Build("", nodeResource, "", nil, labels.Everything(), "node1", "node2")): buildQueryRes("container_cpu_usage_seconds_total",
|
||||
buildNodeSample("node1", 1100.0, 10),
|
||||
buildNodeSample("node2", 1200.0, 14),
|
||||
),
|
||||
mustBuild(memQueries.nodeQuery.Build("", nodeResource, "", nil, "node1", "node2")): buildQueryRes("container_memory_working_set_bytes",
|
||||
mustBuild(memQueries.nodeQuery.Build("", nodeResource, "", nil, labels.Everything(), "node1", "node2")): buildQueryRes("container_memory_working_set_bytes",
|
||||
buildNodeSample("node1", 2100.0, 11),
|
||||
buildNodeSample("node2", 2200.0, 12),
|
||||
),
|
||||
|
|
@ -233,11 +234,11 @@ var _ = Describe("Resource Metrics Provider", func() {
|
|||
|
||||
It("should return nil metrics for missing nodes, but still return partial results", func() {
|
||||
fakeProm.QueryResults = map[prom.Selector]prom.QueryResult{
|
||||
mustBuild(cpuQueries.nodeQuery.Build("", nodeResource, "", nil, "node1", "node2", "node3")): buildQueryRes("container_cpu_usage_seconds_total",
|
||||
mustBuild(cpuQueries.nodeQuery.Build("", nodeResource, "", nil, labels.Everything(), "node1", "node2", "node3")): buildQueryRes("container_cpu_usage_seconds_total",
|
||||
buildNodeSample("node1", 1100.0, 10),
|
||||
buildNodeSample("node2", 1200.0, 14),
|
||||
),
|
||||
mustBuild(memQueries.nodeQuery.Build("", nodeResource, "", nil, "node1", "node2", "node3")): buildQueryRes("container_memory_working_set_bytes",
|
||||
mustBuild(memQueries.nodeQuery.Build("", nodeResource, "", nil, labels.Everything(), "node1", "node2", "node3")): buildQueryRes("container_memory_working_set_bytes",
|
||||
buildNodeSample("node1", 2100.0, 11),
|
||||
buildNodeSample("node2", 2200.0, 12),
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue