Commit c7102ee5 authored by Mike Dame's avatar Mike Dame

Implement autoscaling/v2beta2 features in HPA controller

parent a79916fa
package(default_visibility = ["//visibility:public"]) load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library( go_library(
name = "go_default_library", name = "go_default_library",
...@@ -15,13 +9,14 @@ go_library( ...@@ -15,13 +9,14 @@ go_library(
"replica_calculator.go", "replica_calculator.go",
], ],
importpath = "k8s.io/kubernetes/pkg/controller/podautoscaler", importpath = "k8s.io/kubernetes/pkg/controller/podautoscaler",
visibility = ["//visibility:public"],
deps = [ deps = [
"//pkg/api/legacyscheme:go_default_library", "//pkg/api/legacyscheme:go_default_library",
"//pkg/api/v1/pod:go_default_library", "//pkg/api/v1/pod:go_default_library",
"//pkg/controller:go_default_library", "//pkg/controller:go_default_library",
"//pkg/controller/podautoscaler/metrics:go_default_library", "//pkg/controller/podautoscaler/metrics:go_default_library",
"//staging/src/k8s.io/api/autoscaling/v1:go_default_library", "//staging/src/k8s.io/api/autoscaling/v1:go_default_library",
"//staging/src/k8s.io/api/autoscaling/v2beta1:go_default_library", "//staging/src/k8s.io/api/autoscaling/v2beta2:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
...@@ -66,6 +61,7 @@ go_test( ...@@ -66,6 +61,7 @@ go_test(
"//pkg/controller/podautoscaler/metrics:go_default_library", "//pkg/controller/podautoscaler/metrics:go_default_library",
"//staging/src/k8s.io/api/autoscaling/v1:go_default_library", "//staging/src/k8s.io/api/autoscaling/v1:go_default_library",
"//staging/src/k8s.io/api/autoscaling/v2beta1:go_default_library", "//staging/src/k8s.io/api/autoscaling/v2beta1:go_default_library",
"//staging/src/k8s.io/api/autoscaling/v2beta2:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
...@@ -80,7 +76,7 @@ go_test( ...@@ -80,7 +76,7 @@ go_test(
"//staging/src/k8s.io/client-go/rest:go_default_library", "//staging/src/k8s.io/client-go/rest:go_default_library",
"//staging/src/k8s.io/client-go/scale/fake:go_default_library", "//staging/src/k8s.io/client-go/scale/fake:go_default_library",
"//staging/src/k8s.io/client-go/testing:go_default_library", "//staging/src/k8s.io/client-go/testing:go_default_library",
"//staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1:go_default_library", "//staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2:go_default_library",
"//staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1:go_default_library", "//staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1:go_default_library",
"//staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1:go_default_library", "//staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1:go_default_library",
"//staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1:go_default_library", "//staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1:go_default_library",
...@@ -107,4 +103,5 @@ filegroup( ...@@ -107,4 +103,5 @@ filegroup(
"//pkg/controller/podautoscaler/metrics:all-srcs", "//pkg/controller/podautoscaler/metrics:all-srcs",
], ],
tags = ["automanaged"], tags = ["automanaged"],
visibility = ["//visibility:public"],
) )
...@@ -210,7 +210,7 @@ func (tc *legacyReplicaCalcTestCase) runTest(t *testing.T) { ...@@ -210,7 +210,7 @@ func (tc *legacyReplicaCalcTestCase) runTest(t *testing.T) {
assert.True(t, tc.timestamp.Equal(outTimestamp), "timestamp should be as expected") assert.True(t, tc.timestamp.Equal(outTimestamp), "timestamp should be as expected")
} else { } else {
outReplicas, outUtilization, outTimestamp, err := replicaCalc.GetMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, selector) outReplicas, outUtilization, outTimestamp, err := replicaCalc.GetMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, selector, nil)
if tc.expectedError != nil { if tc.expectedError != nil {
require.Error(t, err, "there should be an error calculating the replica count") require.Error(t, err, "there should be an error calculating the replica count")
......
package(default_visibility = ["//visibility:public"]) load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library( go_library(
name = "go_default_library", name = "go_default_library",
...@@ -15,15 +9,16 @@ go_library( ...@@ -15,15 +9,16 @@ go_library(
"utilization.go", "utilization.go",
], ],
importpath = "k8s.io/kubernetes/pkg/controller/podautoscaler/metrics", importpath = "k8s.io/kubernetes/pkg/controller/podautoscaler/metrics",
visibility = ["//visibility:public"],
deps = [ deps = [
"//staging/src/k8s.io/api/autoscaling/v2beta1:go_default_library", "//staging/src/k8s.io/api/autoscaling/v2beta2:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
"//staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1:go_default_library", "//staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2:go_default_library",
"//staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1:go_default_library", "//staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1:go_default_library",
"//staging/src/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1:go_default_library", "//staging/src/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1:go_default_library",
"//staging/src/k8s.io/metrics/pkg/client/custom_metrics:go_default_library", "//staging/src/k8s.io/metrics/pkg/client/custom_metrics:go_default_library",
...@@ -44,7 +39,7 @@ go_test( ...@@ -44,7 +39,7 @@ go_test(
deps = [ deps = [
"//pkg/api/legacyscheme:go_default_library", "//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/extensions/install:go_default_library", "//pkg/apis/extensions/install:go_default_library",
"//staging/src/k8s.io/api/autoscaling/v2beta1:go_default_library", "//staging/src/k8s.io/api/autoscaling/v2beta2:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
...@@ -55,7 +50,7 @@ go_test( ...@@ -55,7 +50,7 @@ go_test(
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
"//staging/src/k8s.io/client-go/rest:go_default_library", "//staging/src/k8s.io/client-go/rest:go_default_library",
"//staging/src/k8s.io/client-go/testing:go_default_library", "//staging/src/k8s.io/client-go/testing:go_default_library",
"//staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1:go_default_library", "//staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2:go_default_library",
"//staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1:go_default_library", "//staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1:go_default_library",
"//staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1:go_default_library", "//staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1:go_default_library",
"//staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1:go_default_library", "//staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1:go_default_library",
...@@ -78,4 +73,5 @@ filegroup( ...@@ -78,4 +73,5 @@ filegroup(
name = "all-srcs", name = "all-srcs",
srcs = [":package-srcs"], srcs = [":package-srcs"],
tags = ["automanaged"], tags = ["automanaged"],
visibility = ["//visibility:public"],
) )
...@@ -19,7 +19,7 @@ package metrics ...@@ -19,7 +19,7 @@ package metrics
import ( import (
"time" "time"
autoscaling "k8s.io/api/autoscaling/v2beta1" autoscaling "k8s.io/api/autoscaling/v2beta2"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
) )
...@@ -37,11 +37,11 @@ type MetricsClient interface { ...@@ -37,11 +37,11 @@ type MetricsClient interface {
// GetRawMetric gets the given metric (and an associated oldest timestamp) // GetRawMetric gets the given metric (and an associated oldest timestamp)
// for all pods matching the specified selector in the given namespace // for all pods matching the specified selector in the given namespace
GetRawMetric(metricName string, namespace string, selector labels.Selector) (PodMetricsInfo, time.Time, error) GetRawMetric(metricName string, namespace string, selector labels.Selector, metricSelector labels.Selector) (PodMetricsInfo, time.Time, error)
// GetObjectMetric gets the given metric (and an associated timestamp) for the given // GetObjectMetric gets the given metric (and an associated timestamp) for the given
// object in the given namespace // object in the given namespace
GetObjectMetric(metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference) (int64, time.Time, error) GetObjectMetric(metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference, metricSelector labels.Selector) (int64, time.Time, error)
// GetExternalMetric gets all the values of a given external metric // GetExternalMetric gets all the values of a given external metric
// that match the specified selector. // that match the specified selector.
......
...@@ -26,7 +26,7 @@ import ( ...@@ -26,7 +26,7 @@ import (
heapster "k8s.io/heapster/metrics/api/v1/types" heapster "k8s.io/heapster/metrics/api/v1/types"
metricsapi "k8s.io/metrics/pkg/apis/metrics/v1alpha1" metricsapi "k8s.io/metrics/pkg/apis/metrics/v1alpha1"
autoscaling "k8s.io/api/autoscaling/v2beta1" autoscaling "k8s.io/api/autoscaling/v2beta2"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
...@@ -109,7 +109,7 @@ func (h *HeapsterMetricsClient) GetResourceMetric(resource v1.ResourceName, name ...@@ -109,7 +109,7 @@ func (h *HeapsterMetricsClient) GetResourceMetric(resource v1.ResourceName, name
return res, timestamp, nil return res, timestamp, nil
} }
func (h *HeapsterMetricsClient) GetRawMetric(metricName string, namespace string, selector labels.Selector) (PodMetricsInfo, time.Time, error) { func (h *HeapsterMetricsClient) GetRawMetric(metricName string, namespace string, selector labels.Selector, metricSelector labels.Selector) (PodMetricsInfo, time.Time, error) {
podList, err := h.podsGetter.Pods(namespace).List(metav1.ListOptions{LabelSelector: selector.String()}) podList, err := h.podsGetter.Pods(namespace).List(metav1.ListOptions{LabelSelector: selector.String()})
if err != nil { if err != nil {
return nil, time.Time{}, fmt.Errorf("failed to get pod list while fetching metrics: %v", err) return nil, time.Time{}, fmt.Errorf("failed to get pod list while fetching metrics: %v", err)
...@@ -173,7 +173,7 @@ func (h *HeapsterMetricsClient) GetRawMetric(metricName string, namespace string ...@@ -173,7 +173,7 @@ func (h *HeapsterMetricsClient) GetRawMetric(metricName string, namespace string
return res, *timestamp, nil return res, *timestamp, nil
} }
func (h *HeapsterMetricsClient) GetObjectMetric(metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference) (int64, time.Time, error) { func (h *HeapsterMetricsClient) GetObjectMetric(metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference, metricSelector labels.Selector) (int64, time.Time, error) {
return 0, time.Time{}, fmt.Errorf("object metrics are not yet supported") return 0, time.Time{}, fmt.Errorf("object metrics are not yet supported")
} }
......
...@@ -71,10 +71,11 @@ type testCase struct { ...@@ -71,10 +71,11 @@ type testCase struct {
reportedMetricsPoints [][]metricPoint reportedMetricsPoints [][]metricPoint
reportedPodMetrics [][]int64 reportedPodMetrics [][]int64
namespace string namespace string
selector labels.Selector selector labels.Selector
resourceName v1.ResourceName metricSelector labels.Selector
metricName string resourceName v1.ResourceName
metricName string
} }
func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset { func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
...@@ -211,7 +212,7 @@ func (tc *testCase) runTest(t *testing.T) { ...@@ -211,7 +212,7 @@ func (tc *testCase) runTest(t *testing.T) {
info, timestamp, err := metricsClient.GetResourceMetric(tc.resourceName, tc.namespace, tc.selector) info, timestamp, err := metricsClient.GetResourceMetric(tc.resourceName, tc.namespace, tc.selector)
tc.verifyResults(t, info, timestamp, err) tc.verifyResults(t, info, timestamp, err)
} else { } else {
info, timestamp, err := metricsClient.GetRawMetric(tc.metricName, tc.namespace, tc.selector) info, timestamp, err := metricsClient.GetRawMetric(tc.metricName, tc.namespace, tc.selector, tc.metricSelector)
tc.verifyResults(t, info, timestamp, err) tc.verifyResults(t, info, timestamp, err)
} }
} }
......
...@@ -22,12 +22,12 @@ import ( ...@@ -22,12 +22,12 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
autoscaling "k8s.io/api/autoscaling/v2beta1" autoscaling "k8s.io/api/autoscaling/v2beta2"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 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"
customapi "k8s.io/metrics/pkg/apis/custom_metrics/v1beta1" customapi "k8s.io/metrics/pkg/apis/custom_metrics/v1beta2"
resourceclient "k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1" resourceclient "k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1"
customclient "k8s.io/metrics/pkg/client/custom_metrics" customclient "k8s.io/metrics/pkg/client/custom_metrics"
externalclient "k8s.io/metrics/pkg/client/external_metrics" externalclient "k8s.io/metrics/pkg/client/external_metrics"
...@@ -101,8 +101,8 @@ type customMetricsClient struct { ...@@ -101,8 +101,8 @@ type customMetricsClient struct {
// GetRawMetric gets the given metric (and an associated oldest timestamp) // GetRawMetric gets the given metric (and an associated oldest timestamp)
// for all pods matching the specified selector in the given namespace // for all pods matching the specified selector in the given namespace
func (c *customMetricsClient) GetRawMetric(metricName string, namespace string, selector labels.Selector) (PodMetricsInfo, time.Time, error) { func (c *customMetricsClient) GetRawMetric(metricName string, namespace string, selector labels.Selector, metricSelector labels.Selector) (PodMetricsInfo, time.Time, error) {
metrics, err := c.client.NamespacedMetrics(namespace).GetForObjects(schema.GroupKind{Kind: "Pod"}, selector, metricName) metrics, err := c.client.NamespacedMetrics(namespace).GetForObjects(schema.GroupKind{Kind: "Pod"}, selector, metricName, metricSelector)
if err != nil { if err != nil {
return nil, time.Time{}, fmt.Errorf("unable to fetch metrics from custom metrics API: %v", err) return nil, time.Time{}, fmt.Errorf("unable to fetch metrics from custom metrics API: %v", err)
} }
...@@ -123,7 +123,7 @@ func (c *customMetricsClient) GetRawMetric(metricName string, namespace string, ...@@ -123,7 +123,7 @@ func (c *customMetricsClient) GetRawMetric(metricName string, namespace string,
// GetObjectMetric gets the given metric (and an associated timestamp) for the given // GetObjectMetric gets the given metric (and an associated timestamp) for the given
// object in the given namespace // object in the given namespace
func (c *customMetricsClient) GetObjectMetric(metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference) (int64, time.Time, error) { func (c *customMetricsClient) GetObjectMetric(metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference, metricSelector labels.Selector) (int64, time.Time, error) {
gvk := schema.FromAPIVersionAndKind(objectRef.APIVersion, objectRef.Kind) gvk := schema.FromAPIVersionAndKind(objectRef.APIVersion, objectRef.Kind)
var metricValue *customapi.MetricValue var metricValue *customapi.MetricValue
var err error var err error
...@@ -131,9 +131,9 @@ func (c *customMetricsClient) GetObjectMetric(metricName string, namespace strin ...@@ -131,9 +131,9 @@ func (c *customMetricsClient) GetObjectMetric(metricName string, namespace strin
// handle namespace separately // handle namespace separately
// NB: we ignore namespace name here, since CrossVersionObjectReference isn't // NB: we ignore namespace name here, since CrossVersionObjectReference isn't
// supposed to allow you to escape your namespace // supposed to allow you to escape your namespace
metricValue, err = c.client.RootScopedMetrics().GetForObject(gvk.GroupKind(), namespace, metricName) metricValue, err = c.client.RootScopedMetrics().GetForObject(gvk.GroupKind(), namespace, metricName, metricSelector)
} else { } else {
metricValue, err = c.client.NamespacedMetrics(namespace).GetForObject(gvk.GroupKind(), objectRef.Name, metricName) metricValue, err = c.client.NamespacedMetrics(namespace).GetForObject(gvk.GroupKind(), objectRef.Name, metricName, metricSelector)
} }
if err != nil { if err != nil {
......
...@@ -21,7 +21,7 @@ import ( ...@@ -21,7 +21,7 @@ import (
"testing" "testing"
"time" "time"
autoscalingapi "k8s.io/api/autoscaling/v2beta1" autoscalingapi "k8s.io/api/autoscaling/v2beta2"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta/testrestmapper" "k8s.io/apimachinery/pkg/api/meta/testrestmapper"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
...@@ -32,7 +32,7 @@ import ( ...@@ -32,7 +32,7 @@ import (
core "k8s.io/client-go/testing" core "k8s.io/client-go/testing"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
_ "k8s.io/kubernetes/pkg/apis/extensions/install" _ "k8s.io/kubernetes/pkg/apis/extensions/install"
cmapi "k8s.io/metrics/pkg/apis/custom_metrics/v1beta1" cmapi "k8s.io/metrics/pkg/apis/custom_metrics/v1beta2"
emapi "k8s.io/metrics/pkg/apis/external_metrics/v1beta1" emapi "k8s.io/metrics/pkg/apis/external_metrics/v1beta1"
metricsapi "k8s.io/metrics/pkg/apis/metrics/v1beta1" metricsapi "k8s.io/metrics/pkg/apis/metrics/v1beta1"
metricsfake "k8s.io/metrics/pkg/client/clientset/versioned/fake" metricsfake "k8s.io/metrics/pkg/client/clientset/versioned/fake"
...@@ -143,9 +143,11 @@ func (tc *restClientTestCase) prepareTestClient(t *testing.T) (*metricsfake.Clie ...@@ -143,9 +143,11 @@ func (tc *restClientTestCase) prepareTestClient(t *testing.T) (*metricsfake.Clie
APIVersion: "v1", APIVersion: "v1",
Name: fmt.Sprintf("%s-%d", podNamePrefix, i), Name: fmt.Sprintf("%s-%d", podNamePrefix, i),
}, },
Value: *resource.NewMilliQuantity(int64(metricPoint.level), resource.DecimalSI), Value: *resource.NewMilliQuantity(int64(metricPoint.level), resource.DecimalSI),
Timestamp: metav1.Time{Time: timestamp}, Timestamp: metav1.Time{Time: timestamp},
MetricName: tc.metricName, Metric: cmapi.MetricIdentifier{
Name: tc.metricName,
},
} }
metrics.Items = append(metrics.Items, metric) metrics.Items = append(metrics.Items, metric)
...@@ -176,9 +178,11 @@ func (tc *restClientTestCase) prepareTestClient(t *testing.T) (*metricsfake.Clie ...@@ -176,9 +178,11 @@ func (tc *restClientTestCase) prepareTestClient(t *testing.T) (*metricsfake.Clie
APIVersion: tc.singleObject.APIVersion, APIVersion: tc.singleObject.APIVersion,
Name: tc.singleObject.Name, Name: tc.singleObject.Name,
}, },
Timestamp: metav1.Time{Time: timestamp}, Timestamp: metav1.Time{Time: timestamp},
MetricName: tc.metricName, Metric: cmapi.MetricIdentifier{
Value: *resource.NewMilliQuantity(int64(metricPoint.level), resource.DecimalSI), Name: tc.metricName,
},
Value: *resource.NewMilliQuantity(int64(metricPoint.level), resource.DecimalSI),
}, },
}, },
} }
...@@ -227,10 +231,10 @@ func (tc *restClientTestCase) runTest(t *testing.T) { ...@@ -227,10 +231,10 @@ func (tc *restClientTestCase) runTest(t *testing.T) {
} }
tc.verifyResults(t, info, timestamp, err) tc.verifyResults(t, info, timestamp, err)
} else if tc.singleObject == nil { } else if tc.singleObject == nil {
info, timestamp, err := metricsClient.GetRawMetric(tc.metricName, tc.namespace, tc.selector) info, timestamp, err := metricsClient.GetRawMetric(tc.metricName, tc.namespace, tc.selector, tc.metricLabelSelector)
tc.verifyResults(t, info, timestamp, err) tc.verifyResults(t, info, timestamp, err)
} else { } else {
val, timestamp, err := metricsClient.GetObjectMetric(tc.metricName, tc.namespace, tc.singleObject) val, timestamp, err := metricsClient.GetObjectMetric(tc.metricName, tc.namespace, tc.singleObject, tc.metricLabelSelector)
info := PodMetricsInfo{tc.singleObject.Name: val} info := PodMetricsInfo{tc.singleObject.Name: val}
tc.verifyResults(t, info, timestamp, err) tc.verifyResults(t, info, timestamp, err)
} }
......
...@@ -22,7 +22,7 @@ import ( ...@@ -22,7 +22,7 @@ import (
"time" "time"
"github.com/golang/glog" "github.com/golang/glog"
autoscaling "k8s.io/api/autoscaling/v2beta1" autoscaling "k8s.io/api/autoscaling/v2beta2"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
...@@ -159,8 +159,8 @@ func (c *ReplicaCalculator) GetRawResourceReplicas(currentReplicas int32, target ...@@ -159,8 +159,8 @@ func (c *ReplicaCalculator) GetRawResourceReplicas(currentReplicas int32, target
// GetMetricReplicas calculates the desired replica count based on a target metric utilization // GetMetricReplicas calculates the desired replica count based on a target metric utilization
// (as a milli-value) for pods matching the given selector in the given namespace, and the // (as a milli-value) for pods matching the given selector in the given namespace, and the
// current replica count // current replica count
func (c *ReplicaCalculator) GetMetricReplicas(currentReplicas int32, targetUtilization int64, metricName string, namespace string, selector labels.Selector) (replicaCount int32, utilization int64, timestamp time.Time, err error) { func (c *ReplicaCalculator) GetMetricReplicas(currentReplicas int32, targetUtilization int64, metricName string, namespace string, selector labels.Selector, metricSelector labels.Selector) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
metrics, timestamp, err := c.metricsClient.GetRawMetric(metricName, namespace, selector) metrics, timestamp, err := c.metricsClient.GetRawMetric(metricName, namespace, selector, metricSelector)
if err != nil { if err != nil {
return 0, 0, time.Time{}, fmt.Errorf("unable to get metric %s: %v", metricName, err) return 0, 0, time.Time{}, fmt.Errorf("unable to get metric %s: %v", metricName, err)
} }
...@@ -238,8 +238,8 @@ func (c *ReplicaCalculator) calcPlainMetricReplicas(metrics metricsclient.PodMet ...@@ -238,8 +238,8 @@ func (c *ReplicaCalculator) calcPlainMetricReplicas(metrics metricsclient.PodMet
// GetObjectMetricReplicas calculates the desired replica count based on a target metric utilization (as a milli-value) // GetObjectMetricReplicas calculates the desired replica count based on a target metric utilization (as a milli-value)
// for the given object in the given namespace, and the current replica count. // for the given object in the given namespace, and the current replica count.
func (c *ReplicaCalculator) GetObjectMetricReplicas(currentReplicas int32, targetUtilization int64, metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference, selector labels.Selector) (replicaCount int32, utilization int64, timestamp time.Time, err error) { func (c *ReplicaCalculator) GetObjectMetricReplicas(currentReplicas int32, targetUtilization int64, metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference, selector labels.Selector, metricSelector labels.Selector) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
utilization, timestamp, err = c.metricsClient.GetObjectMetric(metricName, namespace, objectRef) utilization, timestamp, err = c.metricsClient.GetObjectMetric(metricName, namespace, objectRef, metricSelector)
if err != nil { if err != nil {
return 0, 0, time.Time{}, fmt.Errorf("unable to get metric %s: %v on %s %s/%s", metricName, objectRef.Kind, namespace, objectRef.Name, err) return 0, 0, time.Time{}, fmt.Errorf("unable to get metric %s: %v on %s %s/%s", metricName, objectRef.Kind, namespace, objectRef.Name, err)
} }
......
...@@ -22,20 +22,20 @@ import ( ...@@ -22,20 +22,20 @@ import (
"testing" "testing"
"time" "time"
autoscalingv2 "k8s.io/api/autoscaling/v2beta1" autoscalingv2 "k8s.io/api/autoscaling/v2beta2"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta/testrestmapper" "k8s.io/apimachinery/pkg/api/meta/testrestmapper"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/kubernetes/fake"
core "k8s.io/client-go/testing" core "k8s.io/client-go/testing"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/controller/podautoscaler/metrics"
metricsclient "k8s.io/kubernetes/pkg/controller/podautoscaler/metrics" metricsclient "k8s.io/kubernetes/pkg/controller/podautoscaler/metrics"
cmapi "k8s.io/metrics/pkg/apis/custom_metrics/v1beta1" cmapi "k8s.io/metrics/pkg/apis/custom_metrics/v1beta2"
emapi "k8s.io/metrics/pkg/apis/external_metrics/v1beta1" emapi "k8s.io/metrics/pkg/apis/external_metrics/v1beta1"
metricsapi "k8s.io/metrics/pkg/apis/metrics/v1beta1" metricsapi "k8s.io/metrics/pkg/apis/metrics/v1beta1"
metricsfake "k8s.io/metrics/pkg/client/clientset/versioned/fake" metricsfake "k8s.io/metrics/pkg/client/clientset/versioned/fake"
...@@ -86,8 +86,9 @@ type replicaCalcTestCase struct { ...@@ -86,8 +86,9 @@ type replicaCalcTestCase struct {
timestamp time.Time timestamp time.Time
resource *resourceInfo resource *resourceInfo
metric *metricInfo metric *metricInfo
metricLabelSelector labels.Selector
podReadiness []v1.ConditionStatus podReadiness []v1.ConditionStatus
podStartTime []metav1.Time podStartTime []metav1.Time
...@@ -235,9 +236,11 @@ func (tc *replicaCalcTestCase) prepareTestCMClient(t *testing.T) *cmfake.FakeCus ...@@ -235,9 +236,11 @@ func (tc *replicaCalcTestCase) prepareTestCMClient(t *testing.T) *cmfake.FakeCus
Name: fmt.Sprintf("%s-%d", podNamePrefix, i), Name: fmt.Sprintf("%s-%d", podNamePrefix, i),
Namespace: testNamespace, Namespace: testNamespace,
}, },
Timestamp: metav1.Time{Time: tc.timestamp}, Timestamp: metav1.Time{Time: tc.timestamp},
MetricName: tc.metric.name, Metric: cmapi.MetricIdentifier{
Value: *resource.NewMilliQuantity(level, resource.DecimalSI), Name: tc.metric.name,
},
Value: *resource.NewMilliQuantity(level, resource.DecimalSI),
} }
metrics.Items = append(metrics.Items, podMetric) metrics.Items = append(metrics.Items, podMetric)
} }
...@@ -265,9 +268,11 @@ func (tc *replicaCalcTestCase) prepareTestCMClient(t *testing.T) *cmfake.FakeCus ...@@ -265,9 +268,11 @@ func (tc *replicaCalcTestCase) prepareTestCMClient(t *testing.T) *cmfake.FakeCus
APIVersion: tc.metric.singleObject.APIVersion, APIVersion: tc.metric.singleObject.APIVersion,
Name: name, Name: name,
}, },
Timestamp: metav1.Time{Time: tc.timestamp}, Timestamp: metav1.Time{Time: tc.timestamp},
MetricName: tc.metric.name, Metric: cmapi.MetricIdentifier{
Value: *resource.NewMilliQuantity(int64(tc.metric.levels[0]), resource.DecimalSI), Name: tc.metric.name,
},
Value: *resource.NewMilliQuantity(int64(tc.metric.levels[0]), resource.DecimalSI),
}, },
} }
...@@ -322,7 +327,7 @@ func (tc *replicaCalcTestCase) prepareTestClient(t *testing.T) (*fake.Clientset, ...@@ -322,7 +327,7 @@ func (tc *replicaCalcTestCase) prepareTestClient(t *testing.T) (*fake.Clientset,
func (tc *replicaCalcTestCase) runTest(t *testing.T) { func (tc *replicaCalcTestCase) runTest(t *testing.T) {
testClient, testMetricsClient, testCMClient, testEMClient := tc.prepareTestClient(t) testClient, testMetricsClient, testCMClient, testEMClient := tc.prepareTestClient(t)
metricsClient := metrics.NewRESTMetricsClient(testMetricsClient.MetricsV1beta1(), testCMClient, testEMClient) metricsClient := metricsclient.NewRESTMetricsClient(testMetricsClient.MetricsV1beta1(), testCMClient, testEMClient)
replicaCalc := NewReplicaCalculator(metricsClient, testClient.Core(), defaultTestingTolerance, defaultTestingCpuTaintAfterStart, defaultTestingDelayOfInitialReadinessStatus) replicaCalc := NewReplicaCalculator(metricsClient, testClient.Core(), defaultTestingTolerance, defaultTestingCpuTaintAfterStart, defaultTestingDelayOfInitialReadinessStatus)
...@@ -357,7 +362,7 @@ func (tc *replicaCalcTestCase) runTest(t *testing.T) { ...@@ -357,7 +362,7 @@ func (tc *replicaCalcTestCase) runTest(t *testing.T) {
if tc.metric.singleObject == nil { if tc.metric.singleObject == nil {
t.Fatal("Metric specified as objectMetric but metric.singleObject is nil.") t.Fatal("Metric specified as objectMetric but metric.singleObject is nil.")
} }
outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetObjectMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, tc.metric.singleObject, selector) outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetObjectMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, tc.metric.singleObject, selector, nil)
case externalMetric: case externalMetric:
if tc.metric.selector == nil { if tc.metric.selector == nil {
t.Fatal("Metric specified as externalMetric but metric.selector is nil.") t.Fatal("Metric specified as externalMetric but metric.selector is nil.")
...@@ -376,7 +381,7 @@ func (tc *replicaCalcTestCase) runTest(t *testing.T) { ...@@ -376,7 +381,7 @@ func (tc *replicaCalcTestCase) runTest(t *testing.T) {
outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetExternalPerPodMetricReplicas(tc.currentReplicas, tc.metric.perPodTargetUtilization, tc.metric.name, testNamespace, tc.metric.selector) outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetExternalPerPodMetricReplicas(tc.currentReplicas, tc.metric.perPodTargetUtilization, tc.metric.name, testNamespace, tc.metric.selector)
case podMetric: case podMetric:
outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, selector) outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, selector, nil)
default: default:
t.Fatalf("Unknown metric type: %d", tc.metric.metricType) t.Fatalf("Unknown metric type: %d", tc.metric.metricType)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment