Merge pull request #521 from dgrisonnet/bump-k8s-deps-1.24

Update dependencies
This commit is contained in:
Damien Grisonnet 2022-08-11 16:30:52 +02:00 committed by GitHub
commit 47ca16ef50
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 1098 additions and 953 deletions

View file

@ -7,7 +7,7 @@ VERSION=$(shell cat VERSION)
TAG_PREFIX=v TAG_PREFIX=v
TAG?=$(TAG_PREFIX)$(VERSION) TAG?=$(TAG_PREFIX)$(VERSION)
GO_VERSION?=1.16.4 GO_VERSION?=1.18.5
.PHONY: all .PHONY: all
all: prometheus-adapter all: prometheus-adapter

View file

@ -32,8 +32,8 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
openapinamer "k8s.io/apiserver/pkg/endpoints/openapi" openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
genericapiserver "k8s.io/apiserver/pkg/server" genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/client-go/informers" "k8s.io/client-go/metadata"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/metadata/metadatainformer"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/transport" "k8s.io/client-go/transport"
@ -238,15 +238,15 @@ func (cmd *PrometheusAdapter) addResourceMetricsAPI(promClient prom.Client, stop
return err return err
} }
client, err := kubernetes.NewForConfig(rest) client, err := metadata.NewForConfig(rest)
if err != nil { if err != nil {
return err return err
} }
podInformerFactory := informers.NewFilteredSharedInformerFactory(client, 0, corev1.NamespaceAll, func(options *metav1.ListOptions) { podInformerFactory := metadatainformer.NewFilteredSharedInformerFactory(client, 0, corev1.NamespaceAll, func(options *metav1.ListOptions) {
options.FieldSelector = "status.phase=Running" options.FieldSelector = "status.phase=Running"
}) })
podInformer := podInformerFactory.Core().V1().Pods() podInformer := podInformerFactory.ForResource(corev1.SchemeGroupVersion.WithResource("pods"))
informer, err := cmd.Informers() informer, err := cmd.Informers()
if err != nil { if err != nil {

121
go.mod
View file

@ -1,23 +1,110 @@
module sigs.k8s.io/prometheus-adapter module sigs.k8s.io/prometheus-adapter
go 1.16 go 1.18
require ( require (
github.com/onsi/ginkgo v1.16.4 github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.15.0 github.com/onsi/gomega v1.20.0
github.com/prometheus/client_golang v1.11.0 github.com/prometheus/client_golang v1.12.1
github.com/prometheus/common v0.26.0 github.com/prometheus/common v0.32.1
github.com/spf13/cobra v1.2.1 github.com/spf13/cobra v1.5.0
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.8.0
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.22.0 k8s.io/api v0.24.3
k8s.io/apimachinery v0.22.0 k8s.io/apimachinery v0.24.3
k8s.io/apiserver v0.22.0 k8s.io/apiserver v0.24.3
k8s.io/client-go v0.22.0 k8s.io/client-go v0.24.3
k8s.io/component-base v0.22.0 k8s.io/component-base v0.24.3
k8s.io/klog/v2 v2.9.0 k8s.io/klog/v2 v2.70.1
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e k8s.io/kube-openapi v0.0.0-20220413171646-5e7f5fdc6da6
k8s.io/metrics v0.22.0 k8s.io/metrics v0.24.3
sigs.k8s.io/custom-metrics-apiserver v1.22.0 sigs.k8s.io/custom-metrics-apiserver v1.24.0
sigs.k8s.io/metrics-server v0.5.0 sigs.k8s.io/metrics-server v0.6.1
)
require (
github.com/NYTimes/gziphandler v1.1.1 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
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-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful v2.16.0+incompatible // indirect
github.com/emicklei/go-restful-swagger12 v0.0.0-20201014110547-68ccff494617 // indirect
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
github.com/felixge/httpsnoop v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/go-logr/logr v1.2.0 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.6 // indirect
github.com/go-openapi/swag v0.19.15 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/gnostic v0.6.9 // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/google/uuid v1.1.2 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/imdario/mergo v0.3.5 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // 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/nxadm/tail v1.4.8 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/procfs v0.7.3 // indirect
github.com/spf13/pflag v1.0.5 // indirect
go.etcd.io/etcd/api/v3 v3.5.1 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.1 // indirect
go.etcd.io/etcd/client/v3 v3.5.1 // indirect
go.opentelemetry.io/contrib v0.20.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 // indirect
go.opentelemetry.io/otel v0.20.0 // indirect
go.opentelemetry.io/otel/exporters/otlp v0.20.0 // indirect
go.opentelemetry.io/otel/metric v0.20.0 // indirect
go.opentelemetry.io/otel/sdk v0.20.0 // indirect
go.opentelemetry.io/otel/sdk/export/metric v0.20.0 // indirect
go.opentelemetry.io/otel/sdk/metric v0.20.0 // indirect
go.opentelemetry.io/otel/trace v0.20.0 // indirect
go.opentelemetry.io/proto/otlp v0.7.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.19.0 // indirect
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // 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/tools v0.1.10 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 // indirect
google.golang.org/grpc v1.40.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/gengo v0.0.0-20211129171323-c02415ce4185 // indirect
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30 // indirect
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.2.0 // indirect
) )

452
go.sum

File diff suppressed because it is too large Load diff

View file

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
//go:build tools
// +build tools // +build tools
// Package tools tracks dependencies for tools that used in the build process. // Package tools tracks dependencies for tools that used in the build process.

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,4 @@
//go:build codegen
// +build codegen // +build codegen
/* /*

View file

@ -26,9 +26,9 @@ import (
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta" apimeta "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
apitypes "k8s.io/apimachinery/pkg/types"
"k8s.io/klog/v2" "k8s.io/klog/v2"
metrics "k8s.io/metrics/pkg/apis/metrics" metrics "k8s.io/metrics/pkg/apis/metrics"
@ -123,12 +123,11 @@ type nsQueryResults struct {
} }
// GetPodMetrics implements the api.MetricsProvider interface. // GetPodMetrics implements the api.MetricsProvider interface.
func (p *resourceProvider) GetPodMetrics(pods ...apitypes.NamespacedName) ([]api.TimeInfo, [][]metrics.ContainerMetrics, error) { func (p *resourceProvider) GetPodMetrics(pods ...*metav1.PartialObjectMetadata) ([]metrics.PodMetrics, error) {
resTimes := make([]api.TimeInfo, len(pods)) resMetrics := make([]metrics.PodMetrics, 0, len(pods))
resMetrics := make([][]metrics.ContainerMetrics, len(pods))
if len(pods) == 0 { if len(pods) == 0 {
return resTimes, resMetrics, nil return resMetrics, nil
} }
// TODO(directxman12): figure out how well this scales if we go to list 1000+ pods // TODO(directxman12): figure out how well this scales if we go to list 1000+ pods
@ -168,37 +167,40 @@ func (p *resourceProvider) GetPodMetrics(pods ...apitypes.NamespacedName) ([]api
// convert the unorganized per-container results into results grouped // convert the unorganized per-container results into results grouped
// together by namespace, pod, and container // together by namespace, pod, and container
for i, pod := range pods { for _, pod := range pods {
p.assignForPod(pod, resultsByNs, &resMetrics[i], &resTimes[i]) podMetric := p.assignForPod(pod, resultsByNs)
if podMetric != nil {
resMetrics = append(resMetrics, *podMetric)
}
} }
return resTimes, resMetrics, nil return resMetrics, nil
} }
// assignForPod takes the resource metrics for all containers in the given pod // assignForPod takes the resource metrics for all containers in the given pod
// from resultsByNs, and places them in MetricsProvider response format in resMetrics, // from resultsByNs, and places them in MetricsProvider response format in resMetrics,
// also recording the earliest time in resTime. It will return without operating if // also recording the earliest time in resTime. It will return without operating if
// any data is missing. // any data is missing.
func (p *resourceProvider) assignForPod(pod apitypes.NamespacedName, resultsByNs map[string]nsQueryResults, resMetrics *[]metrics.ContainerMetrics, resTime *api.TimeInfo) { func (p *resourceProvider) assignForPod(pod *metav1.PartialObjectMetadata, resultsByNs map[string]nsQueryResults) *metrics.PodMetrics {
// check to make sure everything is present // check to make sure everything is present
nsRes, nsResPresent := resultsByNs[pod.Namespace] nsRes, nsResPresent := resultsByNs[pod.Namespace]
if !nsResPresent { if !nsResPresent {
klog.Errorf("unable to fetch metrics for pods in namespace %q, skipping pod %s", pod.Namespace, pod.String()) klog.Errorf("unable to fetch metrics for pods in namespace %q, skipping pod %s", pod.Namespace, pod.String())
return return nil
} }
cpuRes, hasResult := nsRes.cpu[pod.Name] cpuRes, hasResult := nsRes.cpu[pod.Name]
if !hasResult { if !hasResult {
klog.Errorf("unable to fetch CPU metrics for pod %s, skipping", pod.String()) klog.Errorf("unable to fetch CPU metrics for pod %s, skipping", pod.String())
return return nil
} }
memRes, hasResult := nsRes.mem[pod.Name] memRes, hasResult := nsRes.mem[pod.Name]
if !hasResult { if !hasResult {
klog.Errorf("unable to fetch memory metrics for pod %s, skipping", pod.String()) klog.Errorf("unable to fetch memory metrics for pod %s, skipping", pod.String())
return return nil
} }
earliestTs := pmodel.Latest
containerMetrics := make(map[string]metrics.ContainerMetrics) containerMetrics := make(map[string]metrics.ContainerMetrics)
earliestTs := pmodel.Latest
// organize all the CPU results // organize all the CPU results
for _, cpu := range cpuRes { for _, cpu := range cpuRes {
@ -241,40 +243,50 @@ func (p *resourceProvider) assignForPod(pod apitypes.NamespacedName, resultsByNs
} }
} }
// store the time in the final format podMetric := &metrics.PodMetrics{
*resTime = api.TimeInfo{ ObjectMeta: metav1.ObjectMeta{
Timestamp: earliestTs.Time(), Name: pod.Name,
Window: p.window, Namespace: pod.Namespace,
Labels: pod.Labels,
CreationTimestamp: metav1.Now(),
},
// store the time in the final format
Timestamp: metav1.NewTime(earliestTs.Time()),
Window: metav1.Duration{Duration: p.window},
} }
// store the container metrics in the final format // store the container metrics in the final format
containerMetricsList := make([]metrics.ContainerMetrics, 0, len(containerMetrics)) podMetric.Containers = make([]metrics.ContainerMetrics, 0, len(containerMetrics))
for _, containerMetric := range containerMetrics { for _, containerMetric := range containerMetrics {
containerMetricsList = append(containerMetricsList, containerMetric) podMetric.Containers = append(podMetric.Containers, containerMetric)
} }
*resMetrics = containerMetricsList
return podMetric
} }
// GetNodeMetrics implements the api.MetricsProvider interface. // GetNodeMetrics implements the api.MetricsProvider interface.
func (p *resourceProvider) GetNodeMetrics(nodes ...string) ([]api.TimeInfo, []corev1.ResourceList, error) { func (p *resourceProvider) GetNodeMetrics(nodes ...*corev1.Node) ([]metrics.NodeMetrics, error) {
resTimes := make([]api.TimeInfo, len(nodes)) resMetrics := make([]metrics.NodeMetrics, 0, len(nodes))
resMetrics := make([]corev1.ResourceList, len(nodes))
if len(nodes) == 0 { if len(nodes) == 0 {
return resTimes, resMetrics, nil return resMetrics, nil
} }
now := pmodel.Now() now := pmodel.Now()
nodeNames := make([]string, 0, len(nodes))
for _, node := range nodes {
nodeNames = append(nodeNames, node.Name)
}
// run the actual query // run the actual query
qRes := p.queryBoth(now, nodeResource, "", nodes...) qRes := p.queryBoth(now, nodeResource, "", nodeNames...)
if qRes.err != nil { if qRes.err != nil {
klog.Errorf("failed querying node metrics: %v", qRes.err) klog.Errorf("failed querying node metrics: %v", qRes.err)
return resTimes, resMetrics, nil return resMetrics, nil
} }
// organize the results // organize the results
for i, nodeName := range nodes { for i, nodeName := range nodeNames {
// skip if any data is missing // skip if any data is missing
rawCPUs, gotResult := qRes.cpu[nodeName] rawCPUs, gotResult := qRes.cpu[nodeName]
if !gotResult { if !gotResult {
@ -290,28 +302,30 @@ func (p *resourceProvider) GetNodeMetrics(nodes ...string) ([]api.TimeInfo, []co
rawMem := rawMems[0] rawMem := rawMems[0]
rawCPU := rawCPUs[0] rawCPU := rawCPUs[0]
// store the results
resMetrics[i] = corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(int64(rawCPU.Value*1000.0), resource.DecimalSI),
corev1.ResourceMemory: *resource.NewMilliQuantity(int64(rawMem.Value*1000.0), resource.BinarySI),
}
// use the earliest timestamp available (in order to be conservative // use the earliest timestamp available (in order to be conservative
// when determining if metrics are tainted by startup) // when determining if metrics are tainted by startup)
if rawMem.Timestamp.Before(rawCPU.Timestamp) { ts := rawCPU.Timestamp.Time()
resTimes[i] = api.TimeInfo{ if ts.After(rawMem.Timestamp.Time()) {
Timestamp: rawMem.Timestamp.Time(), ts = rawMem.Timestamp.Time()
Window: p.window,
}
} else {
resTimes[i] = api.TimeInfo{
Timestamp: rawCPU.Timestamp.Time(),
Window: 1 * time.Minute,
}
} }
// store the results
resMetrics = append(resMetrics, metrics.NodeMetrics{
ObjectMeta: metav1.ObjectMeta{
Name: nodes[i].Name,
Labels: nodes[i].Labels,
CreationTimestamp: metav1.Now(),
},
Usage: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(int64(rawCPU.Value*1000.0), resource.DecimalSI),
corev1.ResourceMemory: *resource.NewMilliQuantity(int64(rawMem.Value*1000.0), resource.BinarySI),
},
Timestamp: metav1.NewTime(ts),
Window: metav1.Duration{Duration: p.window},
})
} }
return resTimes, resMetrics, nil return resMetrics, nil
} }
// queryBoth queries for both CPU and memory metrics on the given // queryBoth queries for both CPU and memory metrics on the given

View file

@ -23,9 +23,9 @@ import (
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta" apimeta "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/metrics/pkg/apis/metrics" "k8s.io/metrics/pkg/apis/metrics"
"sigs.k8s.io/metrics-server/pkg/api" "sigs.k8s.io/metrics-server/pkg/api"
@ -122,10 +122,10 @@ var _ = Describe("Resource Metrics Provider", func() {
}) })
It("should be able to list metrics pods across different namespaces", func() { It("should be able to list metrics pods across different namespaces", func() {
pods := []types.NamespacedName{ pods := []*metav1.PartialObjectMetadata{
{Namespace: "some-ns", Name: "pod1"}, {ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "pod1"}},
{Namespace: "some-ns", Name: "pod3"}, {ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "pod3"}},
{Namespace: "other-ns", Name: "pod27"}, {ObjectMeta: metav1.ObjectMeta{Namespace: "other-ns", Name: "pod27"}},
} }
fakeProm.QueryResults = map[prom.Selector]prom.QueryResult{ fakeProm.QueryResults = map[prom.Selector]prom.QueryResult{
mustBuild(cpuQueries.contQuery.Build("", podResource, "some-ns", []string{cpuQueries.containerLabel}, labels.Everything(), "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",
@ -149,28 +149,34 @@ var _ = Describe("Resource Metrics Provider", func() {
} }
By("querying for metrics for some pods") By("querying for metrics for some pods")
times, metricVals, err := prov.GetPodMetrics(pods...) podMetrics, err := prov.GetPodMetrics(pods...)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
By("verifying that metrics have been fetched for all the pods")
Expect(podMetrics).To(HaveLen(3))
By("verifying that the reported times for each are the earliest times for each pod") By("verifying that the reported times for each are the earliest times for each pod")
Expect(times).To(Equal([]api.TimeInfo{ Expect(podMetrics[0].Timestamp.Time).To(Equal(pmodel.Time(10).Time()))
{Timestamp: pmodel.Time(10).Time(), Window: 1 * time.Minute}, Expect(podMetrics[0].Window.Duration).To(Equal(time.Minute))
{Timestamp: pmodel.Time(10).Time(), Window: 1 * time.Minute},
{Timestamp: pmodel.Time(270).Time(), Window: 1 * time.Minute}, Expect(podMetrics[1].Timestamp.Time).To(Equal(pmodel.Time(10).Time()))
})) Expect(podMetrics[1].Window.Duration).To(Equal(time.Minute))
Expect(podMetrics[2].Timestamp.Time).To(Equal(pmodel.Time(270).Time()))
Expect(podMetrics[2].Window.Duration).To(Equal(time.Minute))
By("verifying that the right metrics were fetched") By("verifying that the right metrics were fetched")
Expect(metricVals).To(HaveLen(3)) Expect(podMetrics).To(HaveLen(3))
Expect(metricVals[0]).To(ConsistOf( Expect(podMetrics[0].Containers).To(ConsistOf(
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(1100.0, 3100.0)}, metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(1100.0, 3100.0)},
metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(1110.0, 3110.0)}, metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(1110.0, 3110.0)},
)) ))
Expect(metricVals[1]).To(ConsistOf( Expect(podMetrics[1].Containers).To(ConsistOf(
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(1300.0, 3300.0)}, metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(1300.0, 3300.0)},
metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(1310.0, 3310.0)}, metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(1310.0, 3310.0)},
)) ))
Expect(metricVals[2]).To(ConsistOf( Expect(podMetrics[2].Containers).To(ConsistOf(
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(2200.0, 4200.0)}, metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(2200.0, 4200.0)},
)) ))
}) })
@ -188,23 +194,22 @@ var _ = Describe("Resource Metrics Provider", func() {
} }
By("querying for metrics for some pods, one of which is missing") By("querying for metrics for some pods, one of which is missing")
times, metricVals, err := prov.GetPodMetrics( podMetrics, err := prov.GetPodMetrics(
types.NamespacedName{Namespace: "some-ns", Name: "pod1"}, &metav1.PartialObjectMetadata{ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "pod1"}},
types.NamespacedName{Namespace: "some-ns", Name: "pod-nonexistant"}, &metav1.PartialObjectMetadata{ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "pod-nonexistant"}},
) )
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
By("verifying that the missing pod had nil metrics") By("verifying that the missing pod had no metrics")
Expect(metricVals).To(HaveLen(2)) Expect(podMetrics).To(HaveLen(1))
Expect(metricVals[1]).To(BeNil())
By("verifying that the rest of time metrics and times are correct") By("verifying that the rest of time metrics and times are correct")
Expect(metricVals[0]).To(ConsistOf( Expect(podMetrics[0].Timestamp.Time).To(Equal(pmodel.Time(10).Time()))
Expect(podMetrics[0].Window.Duration).To(Equal(time.Minute))
Expect(podMetrics[0].Containers).To(ConsistOf(
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(1100.0, 3100.0)}, metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(1100.0, 3100.0)},
metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(1110.0, 3110.0)}, metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(1110.0, 3110.0)},
)) ))
Expect(times).To(HaveLen(2))
Expect(times[0]).To(Equal(api.TimeInfo{Timestamp: pmodel.Time(10).Time(), Window: 1 * time.Minute}))
}) })
It("should return metrics of value zero when pod metrics have NaN or negative values", func() { It("should return metrics of value zero when pod metrics have NaN or negative values", func() {
@ -224,25 +229,27 @@ var _ = Describe("Resource Metrics Provider", func() {
} }
By("querying for metrics for some pods") By("querying for metrics for some pods")
times, metricVals, err := prov.GetPodMetrics( podMetrics, err := prov.GetPodMetrics(
types.NamespacedName{Namespace: "some-ns", Name: "pod1"}, &metav1.PartialObjectMetadata{ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "pod1"}},
types.NamespacedName{Namespace: "some-ns", Name: "pod3"}, &metav1.PartialObjectMetadata{ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "pod3"}},
) )
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
By("verifying that metrics have been fetched for all the pods")
Expect(podMetrics).To(HaveLen(2))
By("verifying that the reported times for each are the earliest times for each pod") By("verifying that the reported times for each are the earliest times for each pod")
Expect(times).To(Equal([]api.TimeInfo{ Expect(podMetrics[0].Timestamp.Time).To(Equal(pmodel.Time(10).Time()))
{Timestamp: pmodel.Time(10).Time(), Window: 1 * time.Minute}, Expect(podMetrics[0].Window.Duration).To(Equal(time.Minute))
{Timestamp: pmodel.Time(10).Time(), Window: 1 * time.Minute}, Expect(podMetrics[1].Timestamp.Time).To(Equal(pmodel.Time(10).Time()))
})) Expect(podMetrics[1].Window.Duration).To(Equal(time.Minute))
By("verifying that NaN and negative values were replaced by zero") By("verifying that NaN and negative values were replaced by zero")
Expect(metricVals).To(HaveLen(2)) Expect(podMetrics[0].Containers).To(ConsistOf(
Expect(metricVals[0]).To(ConsistOf(
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(0, 3100.0)}, metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(0, 3100.0)},
metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(0, 0)}, metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(0, 0)},
)) ))
Expect(metricVals[1]).To(ConsistOf( Expect(podMetrics[1].Containers).To(ConsistOf(
metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(0, 0)}, metrics.ContainerMetrics{Name: "cont1", Usage: buildResList(0, 0)},
metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(1310.0, 0)}, metrics.ContainerMetrics{Name: "cont2", Usage: buildResList(1310.0, 0)},
)) ))
@ -260,20 +267,24 @@ var _ = Describe("Resource Metrics Provider", func() {
), ),
} }
By("querying for metrics for some nodes") By("querying for metrics for some nodes")
times, metricVals, err := prov.GetNodeMetrics("node1", "node2") nodeMetrics, err := prov.GetNodeMetrics(
&corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node1"}},
&corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node2"}},
)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
By("verifying that the reported times for each are the earliest times for each pod") By("verifying that metrics have been fetched for all the nodes")
Expect(times).To(Equal([]api.TimeInfo{ Expect(nodeMetrics).To(HaveLen(2))
{Timestamp: pmodel.Time(10).Time(), Window: 1 * time.Minute},
{Timestamp: pmodel.Time(12).Time(), Window: 1 * time.Minute}, By("verifying that the reported times for each are the earliest times for each node")
})) Expect(nodeMetrics[0].Timestamp.Time).To(Equal(pmodel.Time(10).Time()))
Expect(nodeMetrics[0].Window.Duration).To(Equal(time.Minute))
Expect(nodeMetrics[1].Timestamp.Time).To(Equal(pmodel.Time(12).Time()))
Expect(nodeMetrics[1].Window.Duration).To(Equal(time.Minute))
By("verifying that the right metrics were fetched") By("verifying that the right metrics were fetched")
Expect(metricVals).To(Equal([]corev1.ResourceList{ Expect(nodeMetrics[0].Usage).To(Equal(buildResList(1100.0, 2100.0)))
buildResList(1100.0, 2100.0), Expect(nodeMetrics[1].Usage).To(Equal(buildResList(1200.0, 2200.0)))
buildResList(1200.0, 2200.0),
}))
}) })
It("should return nil metrics for missing nodes, but still return partial results", func() { It("should return nil metrics for missing nodes, but still return partial results", func() {
@ -288,24 +299,23 @@ var _ = Describe("Resource Metrics Provider", func() {
), ),
} }
By("querying for metrics for some nodes, one of which is missing") By("querying for metrics for some nodes, one of which is missing")
times, metricVals, err := prov.GetNodeMetrics("node1", "node2", "node3") nodeMetrics, err := prov.GetNodeMetrics(
&corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node1"}},
&corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node2"}},
&corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node3"}},
)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
By("verifying that the missing pod had nil metrics") By("verifying that the missing pod had no metrics")
Expect(metricVals).To(HaveLen(3)) Expect(nodeMetrics).To(HaveLen(2))
Expect(metricVals[2]).To(BeNil())
By("verifying that the rest of time metrics and times are correct") By("verifying that the rest of time metrics and times are correct")
Expect(metricVals).To(Equal([]corev1.ResourceList{ Expect(nodeMetrics[0].Usage).To(Equal(buildResList(1100.0, 2100.0)))
buildResList(1100.0, 2100.0), Expect(nodeMetrics[0].Timestamp.Time).To(Equal(pmodel.Time(10).Time()))
buildResList(1200.0, 2200.0), Expect(nodeMetrics[0].Window.Duration).To(Equal(time.Minute))
nil, Expect(nodeMetrics[1].Usage).To(Equal(buildResList(1200.0, 2200.0)))
})) Expect(nodeMetrics[1].Timestamp.Time).To(Equal(pmodel.Time(12).Time()))
Expect(times).To(Equal([]api.TimeInfo{ Expect(nodeMetrics[1].Window.Duration).To(Equal(time.Minute))
{Timestamp: pmodel.Time(10).Time(), Window: 1 * time.Minute},
{Timestamp: pmodel.Time(12).Time(), Window: 1 * time.Minute},
{},
}))
}) })
It("should return metrics of value zero when node metrics have NaN or negative values", func() { It("should return metrics of value zero when node metrics have NaN or negative values", func() {
@ -320,19 +330,23 @@ var _ = Describe("Resource Metrics Provider", func() {
), ),
} }
By("querying for metrics for some nodes") By("querying for metrics for some nodes")
times, metricVals, err := prov.GetNodeMetrics("node1", "node2") nodeMetrics, err := prov.GetNodeMetrics(
&corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node1"}},
&corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node2"}},
)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
By("verifying that metrics have been fetched for all the nodes")
Expect(nodeMetrics).To(HaveLen(2))
By("verifying that the reported times for each are the earliest times for each pod") By("verifying that the reported times for each are the earliest times for each pod")
Expect(times).To(Equal([]api.TimeInfo{ Expect(nodeMetrics[0].Timestamp.Time).To(Equal(pmodel.Time(10).Time()))
{Timestamp: pmodel.Time(10).Time(), Window: 1 * time.Minute}, Expect(nodeMetrics[0].Window.Duration).To(Equal(time.Minute))
{Timestamp: pmodel.Time(12).Time(), Window: 1 * time.Minute}, Expect(nodeMetrics[1].Timestamp.Time).To(Equal(pmodel.Time(12).Time()))
})) Expect(nodeMetrics[1].Window.Duration).To(Equal(time.Minute))
By("verifying that NaN and negative values were replaced by zero") By("verifying that NaN and negative values were replaced by zero")
Expect(metricVals).To(Equal([]corev1.ResourceList{ Expect(nodeMetrics[0].Usage).To(Equal(buildResList(0, 2100.0)))
buildResList(0, 2100.0), Expect(nodeMetrics[1].Usage).To(Equal(buildResList(1200.0, 0)))
buildResList(1200.0, 0),
}))
}) })
}) })