mirror of
https://github.com/kubernetes-sigs/prometheus-adapter.git
synced 2026-04-06 01:38:10 +00:00
Re-implementing changes on top of the latest master.
This commit is contained in:
parent
7b606a79fc
commit
e9af0455ba
5 changed files with 181 additions and 16 deletions
15
Gopkg.lock
generated
15
Gopkg.lock
generated
|
|
@ -68,6 +68,19 @@
|
|||
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/directxman12/k8s-prometheus-adapter"
|
||||
packages = [
|
||||
"cmd/adapter/app",
|
||||
"cmd/config-gen/utils",
|
||||
"pkg/client",
|
||||
"pkg/client/metrics",
|
||||
"pkg/config",
|
||||
"pkg/custom-provider"
|
||||
]
|
||||
revision = "7b606a79fc2fdc4246e455e8f28503e0b4807a92"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/elazarl/go-bindata-assetfs"
|
||||
packages = ["."]
|
||||
|
|
@ -802,6 +815,6 @@
|
|||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "922da691d7be0fa3bde2ab628c629fea6718792cb234a2e5c661a193f0545d6f"
|
||||
inputs-digest = "66b8ba4b829725e88ff6ba39c022bdf9670bdffa53ef9f8094c84e0c1447d2db"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ func (o PrometheusAdapterServerOptions) RunCustomMetricsAdapterServer(stopCh <-c
|
|||
return fmt.Errorf("unable to construct naming scheme from metrics rules: %v", err)
|
||||
}
|
||||
|
||||
cmProvider, runner := cmprov.NewPrometheusProvider(dynamicMapper, dynamicClient, promClient, namers, o.MetricsRelistInterval)
|
||||
cmProvider, runner := cmprov.NewCustomPrometheusProvider(dynamicMapper, dynamicClient, promClient, namers, o.MetricsRelistInterval)
|
||||
runner.RunUntil(stopCh)
|
||||
|
||||
server, err := config.Complete().New("prometheus-custom-metrics-adapter", cmProvider, nil)
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ type Runnable interface {
|
|||
RunUntil(stopChan <-chan struct{})
|
||||
}
|
||||
|
||||
type prometheusProvider struct {
|
||||
type customPrometheusProvider struct {
|
||||
mapper apimeta.RESTMapper
|
||||
kubeClient dynamic.Interface
|
||||
promClient prom.Client
|
||||
|
|
@ -56,7 +56,7 @@ type prometheusProvider struct {
|
|||
SeriesRegistry
|
||||
}
|
||||
|
||||
func NewPrometheusProvider(mapper apimeta.RESTMapper, kubeClient dynamic.Interface, promClient prom.Client, namers []MetricNamer, updateInterval time.Duration) (provider.CustomMetricsProvider, Runnable) {
|
||||
func NewCustomPrometheusProvider(mapper apimeta.RESTMapper, kubeClient dynamic.Interface, promClient prom.Client, namers []MetricNamer, updateInterval time.Duration) (provider.CustomMetricsProvider, Runnable) {
|
||||
lister := &cachingMetricsLister{
|
||||
updateInterval: updateInterval,
|
||||
promClient: promClient,
|
||||
|
|
@ -67,7 +67,7 @@ func NewPrometheusProvider(mapper apimeta.RESTMapper, kubeClient dynamic.Interfa
|
|||
},
|
||||
}
|
||||
|
||||
return &prometheusProvider{
|
||||
return &customPrometheusProvider{
|
||||
mapper: mapper,
|
||||
kubeClient: kubeClient,
|
||||
promClient: promClient,
|
||||
|
|
@ -76,7 +76,7 @@ func NewPrometheusProvider(mapper apimeta.RESTMapper, kubeClient dynamic.Interfa
|
|||
}, lister
|
||||
}
|
||||
|
||||
func (p *prometheusProvider) metricFor(value pmodel.SampleValue, groupResource schema.GroupResource, namespace string, name string, metricName string) (*custom_metrics.MetricValue, error) {
|
||||
func (p *customPrometheusProvider) metricFor(value pmodel.SampleValue, groupResource schema.GroupResource, namespace string, name string, metricName string) (*custom_metrics.MetricValue, error) {
|
||||
kind, err := p.mapper.KindFor(groupResource.WithVersion(""))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -95,7 +95,7 @@ func (p *prometheusProvider) metricFor(value pmodel.SampleValue, groupResource s
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (p *prometheusProvider) metricsFor(valueSet pmodel.Vector, info provider.CustomMetricInfo, list runtime.Object) (*custom_metrics.MetricValueList, error) {
|
||||
func (p *customPrometheusProvider) metricsFor(valueSet pmodel.Vector, info provider.CustomMetricInfo, list runtime.Object) (*custom_metrics.MetricValueList, error) {
|
||||
if !apimeta.IsListType(list) {
|
||||
return nil, apierr.NewInternalError(fmt.Errorf("result of label selector list operation was not a list"))
|
||||
}
|
||||
|
|
@ -129,7 +129,7 @@ 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) {
|
||||
func (p *customPrometheusProvider) buildQuery(info provider.CustomMetricInfo, namespace string, names ...string) (pmodel.Vector, error) {
|
||||
query, found := p.QueryForMetric(info, namespace, names...)
|
||||
if !found {
|
||||
return nil, provider.NewMetricNotFoundError(info.GroupResource, info.Metric)
|
||||
|
|
@ -151,7 +151,7 @@ func (p *prometheusProvider) buildQuery(info provider.CustomMetricInfo, namespac
|
|||
return *queryResults.Vector, nil
|
||||
}
|
||||
|
||||
func (p *prometheusProvider) getSingle(info provider.CustomMetricInfo, namespace, name string) (*custom_metrics.MetricValue, error) {
|
||||
func (p *customPrometheusProvider) getSingle(info provider.CustomMetricInfo, namespace, name string) (*custom_metrics.MetricValue, error) {
|
||||
queryResults, err := p.buildQuery(info, namespace, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -179,7 +179,7 @@ func (p *prometheusProvider) getSingle(info provider.CustomMetricInfo, namespace
|
|||
return p.metricFor(resultValue, info.GroupResource, "", name, info.Metric)
|
||||
}
|
||||
|
||||
func (p *prometheusProvider) getMultiple(info provider.CustomMetricInfo, namespace string, selector labels.Selector) (*custom_metrics.MetricValueList, error) {
|
||||
func (p *customPrometheusProvider) getMultiple(info provider.CustomMetricInfo, namespace string, selector labels.Selector) (*custom_metrics.MetricValueList, error) {
|
||||
fullResources, err := p.mapper.ResourcesFor(info.GroupResource.WithVersion(""))
|
||||
if err == nil && len(fullResources) == 0 {
|
||||
err = fmt.Errorf("no fully versioned resources known for group-resource %v", info.GroupResource)
|
||||
|
|
@ -225,7 +225,7 @@ func (p *prometheusProvider) getMultiple(info provider.CustomMetricInfo, namespa
|
|||
return p.metricsFor(queryResults, info, matchingObjectsRaw)
|
||||
}
|
||||
|
||||
func (p *prometheusProvider) GetRootScopedMetricByName(groupResource schema.GroupResource, name string, metricName string) (*custom_metrics.MetricValue, error) {
|
||||
func (p *customPrometheusProvider) GetRootScopedMetricByName(groupResource schema.GroupResource, name string, metricName string) (*custom_metrics.MetricValue, error) {
|
||||
info := provider.CustomMetricInfo{
|
||||
GroupResource: groupResource,
|
||||
Metric: metricName,
|
||||
|
|
@ -235,7 +235,7 @@ func (p *prometheusProvider) GetRootScopedMetricByName(groupResource schema.Grou
|
|||
return p.getSingle(info, "", name)
|
||||
}
|
||||
|
||||
func (p *prometheusProvider) GetRootScopedMetricBySelector(groupResource schema.GroupResource, selector labels.Selector, metricName string) (*custom_metrics.MetricValueList, error) {
|
||||
func (p *customPrometheusProvider) GetRootScopedMetricBySelector(groupResource schema.GroupResource, selector labels.Selector, metricName string) (*custom_metrics.MetricValueList, error) {
|
||||
info := provider.CustomMetricInfo{
|
||||
GroupResource: groupResource,
|
||||
Metric: metricName,
|
||||
|
|
@ -244,7 +244,7 @@ func (p *prometheusProvider) GetRootScopedMetricBySelector(groupResource schema.
|
|||
return p.getMultiple(info, "", selector)
|
||||
}
|
||||
|
||||
func (p *prometheusProvider) GetNamespacedMetricByName(groupResource schema.GroupResource, namespace string, name string, metricName string) (*custom_metrics.MetricValue, error) {
|
||||
func (p *customPrometheusProvider) GetNamespacedMetricByName(groupResource schema.GroupResource, namespace string, name string, metricName string) (*custom_metrics.MetricValue, error) {
|
||||
info := provider.CustomMetricInfo{
|
||||
GroupResource: groupResource,
|
||||
Metric: metricName,
|
||||
|
|
@ -254,7 +254,7 @@ func (p *prometheusProvider) GetNamespacedMetricByName(groupResource schema.Grou
|
|||
return p.getSingle(info, namespace, name)
|
||||
}
|
||||
|
||||
func (p *prometheusProvider) GetNamespacedMetricBySelector(groupResource schema.GroupResource, namespace string, selector labels.Selector, metricName string) (*custom_metrics.MetricValueList, error) {
|
||||
func (p *customPrometheusProvider) GetNamespacedMetricBySelector(groupResource schema.GroupResource, namespace string, selector labels.Selector, metricName string) (*custom_metrics.MetricValueList, error) {
|
||||
info := provider.CustomMetricInfo{
|
||||
GroupResource: groupResource,
|
||||
Metric: metricName,
|
||||
|
|
@ -95,7 +95,7 @@ func setupPrometheusProvider(t *testing.T) (provider.CustomMetricsProvider, *fak
|
|||
namers, err := NamersFromConfig(cfg, restMapper())
|
||||
require.NoError(t, err)
|
||||
|
||||
prov, _ := NewPrometheusProvider(restMapper(), fakeKubeClient, fakeProm, namers, fakeProviderUpdateInterval)
|
||||
prov, _ := NewCustomPrometheusProvider(restMapper(), fakeKubeClient, fakeProm, namers, fakeProviderUpdateInterval)
|
||||
|
||||
containerSel := prom.MatchSeries("", prom.NameMatches("^container_.*"), prom.LabelNeq("container_name", "POD"), prom.LabelNeq("namespace", ""), prom.LabelNeq("pod_name", ""))
|
||||
namespacedSel := prom.MatchSeries("", prom.LabelNeq("namespace", ""), prom.NameNotMatches("^container_.*"))
|
||||
|
|
@ -141,7 +141,7 @@ func TestListAllMetrics(t *testing.T) {
|
|||
fakeProm.acceptibleInterval = pmodel.Interval{Start: startTime, End: 0}
|
||||
|
||||
// update the metrics (without actually calling RunUntil, so we can avoid timing issues)
|
||||
lister := prov.(*prometheusProvider).SeriesRegistry.(*cachingMetricsLister)
|
||||
lister := prov.(*customPrometheusProvider).SeriesRegistry.(*cachingMetricsLister)
|
||||
require.NoError(t, lister.updateMetrics())
|
||||
|
||||
// list/sort the metrics
|
||||
152
pkg/custom-provider/external_provider.go
Normal file
152
pkg/custom-provider/external_provider.go
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
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 provider
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
s "strings"
|
||||
"time"
|
||||
|
||||
"github.com/kubernetes-incubator/custom-metrics-apiserver/pkg/provider"
|
||||
apimeta "k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/selection"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/metrics/pkg/apis/external_metrics"
|
||||
|
||||
prom "github.com/directxman12/k8s-prometheus-adapter/pkg/client"
|
||||
)
|
||||
|
||||
type externalPrometheusProvider struct {
|
||||
mapper apimeta.RESTMapper
|
||||
kubeClient dynamic.Interface
|
||||
promClient prom.Client
|
||||
|
||||
SeriesRegistry
|
||||
}
|
||||
|
||||
func NewExternalPrometheusProvider(mapper apimeta.RESTMapper, kubeClient dynamic.Interface, promClient prom.Client, namers []MetricNamer, updateInterval time.Duration) (provider.ExternalMetricsProvider, Runnable) {
|
||||
lister := &cachingMetricsLister{
|
||||
updateInterval: updateInterval,
|
||||
promClient: promClient,
|
||||
namers: namers,
|
||||
|
||||
SeriesRegistry: &basicSeriesRegistry{
|
||||
mapper: mapper,
|
||||
},
|
||||
}
|
||||
|
||||
return &externalPrometheusProvider{
|
||||
mapper: mapper,
|
||||
kubeClient: kubeClient,
|
||||
promClient: promClient,
|
||||
|
||||
SeriesRegistry: lister,
|
||||
}, lister
|
||||
}
|
||||
|
||||
func (p *externalPrometheusProvider) GetExternalMetric(namespace string, metricName string, metricSelector labels.Selector) (*external_metrics.ExternalMetricValueList, error) {
|
||||
//TODO: Steps
|
||||
//1. Generate a Prometheus Query.
|
||||
// Something like my_metric{namespace="namespace" some_label="some_value"}
|
||||
//2. Send that query to Prometheus.
|
||||
//3. Adapt the results.
|
||||
//The query generation for external metrics is much more straightforward
|
||||
//than for custom metrics because no renaming is applied.
|
||||
//So we'll just start with some simple string operations and see how far that gets us.
|
||||
//Then I'll circle back and figure out how much code reuse I can get out of the original implementation.
|
||||
namespaceSelector := p.makeLabelFilter("namespace", "=", namespace)
|
||||
otherSelectors := p.convertSelectors(metricSelector)
|
||||
|
||||
finalTargets := append([]string{namespaceSelector}, otherSelectors...)
|
||||
|
||||
//TODO: Only here to stop compiler issues in this incomplete code.
|
||||
fmt.Printf("len=%d", len(finalTargets))
|
||||
|
||||
//TODO: Construct a real result.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *externalPrometheusProvider) makeLabelFilter(labelName string, operator string, targetValue string) string {
|
||||
return fmt.Sprintf("%s%s\"%s\"", labelName, operator, targetValue)
|
||||
}
|
||||
|
||||
func (p *externalPrometheusProvider) 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 *externalPrometheusProvider) 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 *externalPrometheusProvider) selectOperator(operator selection.Operator, valueCount int) string {
|
||||
if valueCount > 1 {
|
||||
return p.selectRegexOperator(operator)
|
||||
}
|
||||
|
||||
return p.selectSingleValueOperator(operator)
|
||||
}
|
||||
|
||||
func (p *externalPrometheusProvider) 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 *externalPrometheusProvider) 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 "="
|
||||
}
|
||||
|
||||
func (p *externalPrometheusProvider) ListAllExternalMetrics() []provider.ExternalMetricInfo {
|
||||
//TODO: Provide a real response.
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue