mirror of
https://github.com/kubernetes-sigs/prometheus-adapter.git
synced 2026-04-06 17:57:51 +00:00
Moving it into its own type to better organize and separate concerns. Also makes unit testing easier.
94 lines
2.5 KiB
Go
94 lines
2.5 KiB
Go
package provider
|
|
|
|
import (
|
|
"fmt"
|
|
s "strings"
|
|
|
|
"k8s.io/apimachinery/pkg/labels"
|
|
"k8s.io/apimachinery/pkg/selection"
|
|
)
|
|
|
|
type ExternalMetricQueryBuilder interface {
|
|
BuildPrometheusQuery(namespace string, metricName string, metricSelector labels.Selector) string
|
|
}
|
|
|
|
type externalMetricQueryBuilder struct {
|
|
}
|
|
|
|
func NewExternalMetricQueryBuilder() ExternalMetricQueryBuilder {
|
|
return &externalMetricQueryBuilder{}
|
|
}
|
|
|
|
func (p *externalMetricQueryBuilder) BuildPrometheusQuery(namespace string, metricName string, metricSelector labels.Selector) string {
|
|
namespaceSelector := p.makeLabelFilter("namespace", "=", namespace)
|
|
otherSelectors := p.convertSelectors(metricSelector)
|
|
|
|
finalTargets := append([]string{namespaceSelector}, otherSelectors...)
|
|
joinedLabels := s.Join(finalTargets, ", ")
|
|
return fmt.Sprintf("%s{%s}", metricName, joinedLabels)
|
|
}
|
|
|
|
func (p *externalMetricQueryBuilder) makeLabelFilter(labelName string, operator string, targetValue string) string {
|
|
return fmt.Sprintf("%s%s\"%s\"", labelName, operator, targetValue)
|
|
}
|
|
|
|
func (p *externalMetricQueryBuilder) convertSelectors(metricSelector labels.Selector) []string {
|
|
requirements, _ := metricSelector.Requirements()
|
|
|
|
selectors := []string{}
|
|
for i := 0; i < len(requirements); i++ {
|
|
selector := p.convertRequirement(requirements[i])
|
|
|
|
selectors = append(selectors, selector)
|
|
}
|
|
|
|
return selectors
|
|
}
|
|
|
|
func (p *externalMetricQueryBuilder) convertRequirement(requirement labels.Requirement) string {
|
|
labelName := requirement.Key()
|
|
values := requirement.Values().List()
|
|
|
|
stringValues := values[0]
|
|
|
|
valueCount := len(values)
|
|
if valueCount > 1 {
|
|
stringValues = s.Join(values, "|")
|
|
}
|
|
|
|
operator := p.selectOperator(requirement.Operator(), valueCount)
|
|
|
|
return p.makeLabelFilter(labelName, operator, stringValues)
|
|
}
|
|
|
|
func (p *externalMetricQueryBuilder) selectOperator(operator selection.Operator, valueCount int) string {
|
|
if valueCount > 1 {
|
|
return p.selectRegexOperator(operator)
|
|
}
|
|
|
|
return p.selectSingleValueOperator(operator)
|
|
}
|
|
|
|
func (p *externalMetricQueryBuilder) selectRegexOperator(operator selection.Operator) string {
|
|
switch operator {
|
|
case selection.Equals:
|
|
return "=~"
|
|
case selection.NotEquals:
|
|
return "!~"
|
|
}
|
|
|
|
//TODO: Cover more cases, supply appropriate errors for any unhandled cases.
|
|
return "="
|
|
}
|
|
|
|
func (p *externalMetricQueryBuilder) selectSingleValueOperator(operator selection.Operator) string {
|
|
switch operator {
|
|
case selection.Equals:
|
|
return "="
|
|
case selection.NotEquals:
|
|
return "!="
|
|
}
|
|
|
|
//TODO: Cover more cases, supply appropriate errors for any unhandled cases.
|
|
return "="
|
|
}
|