diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json
index 53d1c1cc535..2f52c9eb9bd 100644
--- a/api/openapi-spec/swagger.json
+++ b/api/openapi-spec/swagger.json
@@ -79039,11 +79039,6 @@
},
"io.k8s.api.autoscaling.v2beta2.MetricValueStatus": {
"description": "MetricValueStatus holds the current value for a metric",
- "required": [
- "value",
- "averageValue",
- "averageUtilization"
- ],
"properties": {
"averageUtilization": {
"description": "currentAverageUtilization is the current value of the average of the resource metric across all relevant pods, represented as a percentage of the requested value of the resource for the pods.",
diff --git a/api/swagger-spec/autoscaling_v2beta2.json b/api/swagger-spec/autoscaling_v2beta2.json
index 82faa15867a..626fbb33c01 100644
--- a/api/swagger-spec/autoscaling_v2beta2.json
+++ b/api/swagger-spec/autoscaling_v2beta2.json
@@ -1840,11 +1840,6 @@
"v2beta2.MetricValueStatus": {
"id": "v2beta2.MetricValueStatus",
"description": "MetricValueStatus holds the current value for a metric",
- "required": [
- "value",
- "averageValue",
- "averageUtilization"
- ],
"properties": {
"value": {
"type": "string",
diff --git a/cmd/kube-controller-manager/app/autoscaling.go b/cmd/kube-controller-manager/app/autoscaling.go
index e8b7decfdda..98fb1b56a59 100644
--- a/cmd/kube-controller-manager/app/autoscaling.go
+++ b/cmd/kube-controller-manager/app/autoscaling.go
@@ -28,6 +28,7 @@ import (
"k8s.io/client-go/scale"
"k8s.io/kubernetes/pkg/controller/podautoscaler"
"k8s.io/kubernetes/pkg/controller/podautoscaler/metrics"
+
resourceclient "k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1"
"k8s.io/metrics/pkg/client/custom_metrics"
"k8s.io/metrics/pkg/client/external_metrics"
@@ -48,9 +49,19 @@ func startHPAController(ctx ControllerContext) (http.Handler, bool, error) {
func startHPAControllerWithRESTClient(ctx ControllerContext) (http.Handler, bool, error) {
clientConfig := ctx.ClientBuilder.ConfigOrDie("horizontal-pod-autoscaler")
+ hpaClient := ctx.ClientBuilder.ClientOrDie("horizontal-pod-autoscaler")
+
+ apiVersionsGetter := custom_metrics.NewAvailableAPIsGetter(hpaClient.Discovery())
+ // invalidate the discovery information roughly once per resync interval our API
+ // information is *at most* two resync intervals old.
+ go custom_metrics.PeriodicallyInvalidate(
+ apiVersionsGetter,
+ ctx.ComponentConfig.HPAController.HorizontalPodAutoscalerSyncPeriod.Duration,
+ ctx.Stop)
+
metricsClient := metrics.NewRESTMetricsClient(
resourceclient.NewForConfigOrDie(clientConfig),
- custom_metrics.NewForConfigOrDie(clientConfig),
+ custom_metrics.NewForConfig(clientConfig, ctx.RESTMapper, apiVersionsGetter),
external_metrics.NewForConfigOrDie(clientConfig),
)
return startHPAControllerWithMetricsClient(ctx, metricsClient)
diff --git a/docs/api-reference/autoscaling/v2beta2/definitions.html b/docs/api-reference/autoscaling/v2beta2/definitions.html
index 9264640854e..28559ba3536 100755
--- a/docs/api-reference/autoscaling/v2beta2/definitions.html
+++ b/docs/api-reference/autoscaling/v2beta2/definitions.html
@@ -1002,21 +1002,21 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
value |
value is the current value of the metric (as a quantity). |
-true |
+false |
string |
|
averageValue |
averageValue is the current value of the average of the metric across all relevant pods (as a quantity) |
-true |
+false |
string |
|
averageUtilization |
currentAverageUtilization is the current value of the average of the resource metric across all relevant pods, represented as a percentage of the requested value of the resource for the pods. |
-true |
+false |
integer (int32) |
|
diff --git a/staging/src/k8s.io/api/autoscaling/v2beta2/generated.proto b/staging/src/k8s.io/api/autoscaling/v2beta2/generated.proto
index 38f099ae74b..b4e4c95a3b1 100644
--- a/staging/src/k8s.io/api/autoscaling/v2beta2/generated.proto
+++ b/staging/src/k8s.io/api/autoscaling/v2beta2/generated.proto
@@ -259,31 +259,37 @@ message MetricTarget {
optional string type = 1;
// value is the target value of the metric (as a quantity).
+ // +optional
optional k8s.io.apimachinery.pkg.api.resource.Quantity value = 2;
// averageValue is the target value of the average of the
// metric across all relevant pods (as a quantity)
+ // +optional
optional k8s.io.apimachinery.pkg.api.resource.Quantity averageValue = 3;
// averageUtilization is the target value of the average of the
// resource metric across all relevant pods, represented as a percentage of
// the requested value of the resource for the pods.
// Currently only valid for Resource metric source type
+ // +optional
optional int32 averageUtilization = 4;
}
// MetricValueStatus holds the current value for a metric
message MetricValueStatus {
// value is the current value of the metric (as a quantity).
+ // +optional
optional k8s.io.apimachinery.pkg.api.resource.Quantity value = 1;
// averageValue is the current value of the average of the
// metric across all relevant pods (as a quantity)
+ // +optional
optional k8s.io.apimachinery.pkg.api.resource.Quantity averageValue = 2;
// currentAverageUtilization is the current value of the average of the
// resource metric across all relevant pods, represented as a percentage of
// the requested value of the resource for the pods.
+ // +optional
optional int32 averageUtilization = 3;
}
diff --git a/staging/src/k8s.io/api/autoscaling/v2beta2/types.go b/staging/src/k8s.io/api/autoscaling/v2beta2/types.go
index e873971f3fb..2d337953740 100644
--- a/staging/src/k8s.io/api/autoscaling/v2beta2/types.go
+++ b/staging/src/k8s.io/api/autoscaling/v2beta2/types.go
@@ -200,16 +200,18 @@ type MetricTarget struct {
// type represents whether the metric type is Utilization, Value, or AverageValue
Type MetricTargetType `json:"type" protobuf:"bytes,1,name=type"`
// value is the target value of the metric (as a quantity).
- Value *resource.Quantity `json:"value,omitempty" protobuf:"bytes,2,name=value"`
+ // +optional
+ Value *resource.Quantity `json:"value,omitempty" protobuf:"bytes,2,opt,name=value"`
// averageValue is the target value of the average of the
// metric across all relevant pods (as a quantity)
- AverageValue *resource.Quantity `json:"averageValue,omitempty" protobuf:"bytes,3,name=averageValue"`
-
+ // +optional
+ AverageValue *resource.Quantity `json:"averageValue,omitempty" protobuf:"bytes,3,opt,name=averageValue"`
// averageUtilization is the target value of the average of the
// resource metric across all relevant pods, represented as a percentage of
// the requested value of the resource for the pods.
// Currently only valid for Resource metric source type
- AverageUtilization *int32 `json:"averageUtilization,omitempty" protobuf:"bytes,4,name=averageUtilization"`
+ // +optional
+ AverageUtilization *int32 `json:"averageUtilization,omitempty" protobuf:"bytes,4,opt,name=averageUtilization"`
}
// MetricTargetType specifies the type of metric being targeted, and should be either
@@ -364,14 +366,17 @@ type ExternalMetricStatus struct {
// MetricValueStatus holds the current value for a metric
type MetricValueStatus struct {
// value is the current value of the metric (as a quantity).
- Value *resource.Quantity `json:"value" protobuf:"bytes,1,name=value"`
+ // +optional
+ Value *resource.Quantity `json:"value,omitempty" protobuf:"bytes,1,opt,name=value"`
// averageValue is the current value of the average of the
// metric across all relevant pods (as a quantity)
- AverageValue *resource.Quantity `json:"averageValue" protobuf:"bytes,2,name=averageValue"`
+ // +optional
+ AverageValue *resource.Quantity `json:"averageValue,omitempty" protobuf:"bytes,2,opt,name=averageValue"`
// currentAverageUtilization is the current value of the average of the
// resource metric across all relevant pods, represented as a percentage of
// the requested value of the resource for the pods.
- AverageUtilization *int32 `json:"averageUtilization" protobuf:"bytes,3,name=averageUtilization"`
+ // +optional
+ AverageUtilization *int32 `json:"averageUtilization,omitempty" protobuf:"bytes,3,opt,name=averageUtilization"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
diff --git a/staging/src/k8s.io/metrics/Godeps/Godeps.json b/staging/src/k8s.io/metrics/Godeps/Godeps.json
index 8a3032fd29c..5a2e5ba459b 100644
--- a/staging/src/k8s.io/metrics/Godeps/Godeps.json
+++ b/staging/src/k8s.io/metrics/Godeps/Godeps.json
@@ -90,6 +90,18 @@
"ImportPath": "github.com/peterbourgon/diskv",
"Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6"
},
+ {
+ "ImportPath": "github.com/pmezard/go-difflib/difflib",
+ "Rev": "d8ed2627bdf02c080bf22230dbb337003b7aba2d"
+ },
+ {
+ "ImportPath": "github.com/stretchr/testify/assert",
+ "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69"
+ },
+ {
+ "ImportPath": "github.com/stretchr/testify/require",
+ "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69"
+ },
{
"ImportPath": "golang.org/x/crypto/ssh/terminal",
"Rev": "de0752318171da717af4ce24d0a2e8626afaeb11"
diff --git a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/register.go b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/register.go
index 091fcc483d5..a44b8b410cc 100644
--- a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/register.go
+++ b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/register.go
@@ -46,6 +46,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&MetricValue{},
&MetricValueList{},
+ &MetricListOptions{},
)
return nil
}
diff --git a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/types.go b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/types.go
index b426c019954..a39d5c460d0 100644
--- a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/types.go
+++ b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/types.go
@@ -71,6 +71,22 @@ type MetricValue struct {
// for all objects matching the given label selector
const AllObjects = "*"
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// MetricListOptions is used to select metrics by their label selectors
+type MetricListOptions struct {
+ metav1.TypeMeta `json:",inline"`
+
+ // A selector to restrict the list of returned objects by their labels.
+ // Defaults to everything.
+ // +optional
+ LabelSelector string `json:"labelSelector,omitempty" protobuf:"bytes,1,opt,name=labelSelector"`
+
+ // A selector to restrict the list of returned metrics by their labels
+ // +optional
+ MetricLabelSelector string `json:"metricLabelSelector,omitempty" protobuf:"bytes,2,opt,name=metricLabelSelector"`
+}
+
// NOTE: ObjectReference is copied from k8s.io/kubernetes/pkg/api/types.go. We
// cannot depend on k8s.io/kubernetes/pkg/api because that creates cyclic
// dependency between k8s.io/metrics and k8s.io/kubernetes. We cannot depend on
diff --git a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.pb.go b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.pb.go
index 3191ebd3de2..704c8cc6345 100644
--- a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.pb.go
+++ b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.pb.go
@@ -25,6 +25,7 @@ limitations under the License.
k8s.io/kubernetes/vendor/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.proto
It has these top-level messages:
+ MetricListOptions
MetricValue
MetricValueList
*/
@@ -52,18 +53,49 @@ var _ = math.Inf
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+func (m *MetricListOptions) Reset() { *m = MetricListOptions{} }
+func (*MetricListOptions) ProtoMessage() {}
+func (*MetricListOptions) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{0} }
+
func (m *MetricValue) Reset() { *m = MetricValue{} }
func (*MetricValue) ProtoMessage() {}
-func (*MetricValue) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{0} }
+func (*MetricValue) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{1} }
func (m *MetricValueList) Reset() { *m = MetricValueList{} }
func (*MetricValueList) ProtoMessage() {}
-func (*MetricValueList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{1} }
+func (*MetricValueList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{2} }
func init() {
+ proto.RegisterType((*MetricListOptions)(nil), "k8s.io.metrics.pkg.apis.custom_metrics.v1beta1.MetricListOptions")
proto.RegisterType((*MetricValue)(nil), "k8s.io.metrics.pkg.apis.custom_metrics.v1beta1.MetricValue")
proto.RegisterType((*MetricValueList)(nil), "k8s.io.metrics.pkg.apis.custom_metrics.v1beta1.MetricValueList")
}
+func (m *MetricListOptions) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MetricListOptions) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintGenerated(dAtA, i, uint64(len(m.LabelSelector)))
+ i += copy(dAtA[i:], m.LabelSelector)
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintGenerated(dAtA, i, uint64(len(m.MetricLabelSelector)))
+ i += copy(dAtA[i:], m.MetricLabelSelector)
+ return i, nil
+}
+
func (m *MetricValue) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@@ -190,6 +222,16 @@ func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v)
return offset + 1
}
+func (m *MetricListOptions) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.LabelSelector)
+ n += 1 + l + sovGenerated(uint64(l))
+ l = len(m.MetricLabelSelector)
+ n += 1 + l + sovGenerated(uint64(l))
+ return n
+}
+
func (m *MetricValue) Size() (n int) {
var l int
_ = l
@@ -238,6 +280,17 @@ func sovGenerated(x uint64) (n int) {
func sozGenerated(x uint64) (n int) {
return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
+func (this *MetricListOptions) String() string {
+ if this == nil {
+ return "nil"
+ }
+ s := strings.Join([]string{`&MetricListOptions{`,
+ `LabelSelector:` + fmt.Sprintf("%v", this.LabelSelector) + `,`,
+ `MetricLabelSelector:` + fmt.Sprintf("%v", this.MetricLabelSelector) + `,`,
+ `}`,
+ }, "")
+ return s
+}
func (this *MetricValue) String() string {
if this == nil {
return "nil"
@@ -272,6 +325,114 @@ func valueToStringGenerated(v interface{}) string {
pv := reflect.Indirect(rv).Interface()
return fmt.Sprintf("*%v", pv)
}
+func (m *MetricListOptions) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenerated
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MetricListOptions: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MetricListOptions: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field LabelSelector", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenerated
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthGenerated
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.LabelSelector = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field MetricLabelSelector", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenerated
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthGenerated
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.MetricLabelSelector = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipGenerated(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthGenerated
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
func (m *MetricValue) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
@@ -715,41 +876,44 @@ func init() {
}
var fileDescriptorGenerated = []byte{
- // 566 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0x4f, 0x6f, 0xd3, 0x3e,
- 0x18, 0xc7, 0x9b, 0xf5, 0xd7, 0xfd, 0x3a, 0x8f, 0x69, 0x2c, 0x17, 0xa2, 0x1d, 0xd2, 0x6a, 0x5c,
- 0x0a, 0xd2, 0x6c, 0x6d, 0x20, 0x84, 0xc4, 0x2d, 0xe2, 0x82, 0xb4, 0x81, 0xc8, 0x26, 0x26, 0xf1,
- 0x47, 0xe0, 0x38, 0x4f, 0x53, 0xd3, 0x26, 0x8e, 0x6c, 0xa7, 0xd3, 0x6e, 0xbc, 0x04, 0x5e, 0x56,
- 0x8f, 0xe3, 0xb6, 0x53, 0x45, 0x83, 0x78, 0x1f, 0x28, 0x89, 0xd3, 0x76, 0x1b, 0x7f, 0xb6, 0x5b,
- 0x6c, 0x3f, 0xdf, 0x8f, 0xbf, 0xcf, 0xf7, 0x71, 0xd0, 0xc9, 0xf0, 0xa9, 0xc2, 0x5c, 0x90, 0x61,
- 0x16, 0x80, 0x4c, 0x40, 0x83, 0x22, 0x63, 0x48, 0x42, 0x21, 0x89, 0x39, 0x88, 0x41, 0x4b, 0xce,
- 0x14, 0x49, 0x87, 0x11, 0xa1, 0x29, 0x57, 0x84, 0x65, 0x4a, 0x8b, 0xf8, 0x63, 0xbd, 0x3f, 0xde,
- 0x0b, 0x40, 0xd3, 0x3d, 0x12, 0x41, 0x02, 0x92, 0x6a, 0x08, 0x71, 0x2a, 0x85, 0x16, 0x36, 0xae,
- 0xf4, 0xd8, 0xd4, 0xe1, 0x74, 0x18, 0xe1, 0x42, 0x8f, 0x2f, 0xeb, 0xb1, 0xd1, 0x6f, 0xef, 0x46,
- 0x5c, 0x0f, 0xb2, 0x00, 0x33, 0x11, 0x93, 0x48, 0x44, 0x82, 0x94, 0x98, 0x20, 0xeb, 0x97, 0xab,
- 0x72, 0x51, 0x7e, 0x55, 0xf8, 0xed, 0x1d, 0x63, 0x8f, 0xa6, 0x9c, 0x30, 0x21, 0x81, 0x8c, 0xaf,
- 0x59, 0xd8, 0x7e, 0xbc, 0xa8, 0x89, 0x29, 0x1b, 0xf0, 0x04, 0xe4, 0x59, 0xdd, 0x07, 0x91, 0xa0,
- 0x44, 0x26, 0x19, 0xdc, 0x4a, 0xa5, 0x8a, 0x38, 0xe8, 0xef, 0xee, 0x22, 0x7f, 0x52, 0xc9, 0x2c,
- 0xd1, 0x3c, 0xbe, 0x7e, 0xcd, 0x93, 0x7f, 0x09, 0x14, 0x1b, 0x40, 0x4c, 0xaf, 0xea, 0x76, 0x7e,
- 0x36, 0xd1, 0xfa, 0x61, 0x99, 0xdd, 0x1b, 0x3a, 0xca, 0xc0, 0xee, 0xa3, 0xcd, 0x10, 0x14, 0x93,
- 0x3c, 0x80, 0xf0, 0x55, 0xf0, 0x19, 0x98, 0x76, 0xac, 0xae, 0xd5, 0x5b, 0xdf, 0xbf, 0x5f, 0x4f,
- 0x80, 0xa6, 0x1c, 0x17, 0x11, 0xe1, 0xf1, 0x1e, 0xae, 0x2a, 0x7c, 0xe8, 0x83, 0x84, 0x84, 0x81,
- 0x77, 0x6f, 0x32, 0xed, 0x34, 0xf2, 0x69, 0x67, 0xf3, 0xf9, 0x65, 0x86, 0x7f, 0x15, 0x6a, 0xef,
- 0x23, 0x54, 0x8d, 0xec, 0x25, 0x8d, 0xc1, 0x59, 0xe9, 0x5a, 0xbd, 0x35, 0xcf, 0x36, 0x6a, 0x74,
- 0x38, 0x3f, 0xf1, 0x97, 0xaa, 0xec, 0x77, 0x68, 0xad, 0x68, 0x45, 0x69, 0x1a, 0xa7, 0x4e, 0xb3,
- 0x74, 0xf5, 0x70, 0xc9, 0xd5, 0xbc, 0xef, 0xc5, 0xe3, 0x28, 0xe2, 0x2d, 0x7c, 0x1e, 0xf3, 0x18,
- 0xbc, 0x2d, 0x83, 0x5f, 0x3b, 0xae, 0x21, 0xfe, 0x82, 0x67, 0x3f, 0x40, 0xab, 0xa7, 0x3c, 0x09,
- 0xc5, 0xa9, 0xf3, 0x5f, 0xd7, 0xea, 0x35, 0xbd, 0xad, 0x7c, 0xda, 0xd9, 0x38, 0x29, 0x77, 0x8e,
- 0x80, 0x89, 0x24, 0x54, 0xbe, 0x29, 0xb0, 0x8f, 0x50, 0x6b, 0x5c, 0x84, 0xe5, 0xb4, 0x4a, 0x0f,
- 0xf8, 0x6f, 0x1e, 0x70, 0xfd, 0x30, 0xf0, 0xeb, 0x8c, 0x26, 0x9a, 0xeb, 0x33, 0x6f, 0xc3, 0xf8,
- 0x68, 0x95, 0x89, 0xfb, 0x15, 0xcb, 0xfe, 0x80, 0xda, 0x0a, 0x46, 0xc0, 0xb4, 0x90, 0xce, 0x6a,
- 0xc9, 0x7d, 0x74, 0xb3, 0xde, 0x0e, 0x68, 0x00, 0xa3, 0x23, 0x23, 0xf5, 0xee, 0xe4, 0xd3, 0x4e,
- 0xbb, 0x5e, 0xf9, 0x73, 0xe4, 0xce, 0x37, 0x0b, 0x6d, 0x2e, 0xcd, 0xf9, 0x80, 0x2b, 0x6d, 0xbf,
- 0x47, 0xed, 0x02, 0x12, 0x52, 0x4d, 0xcd, 0x90, 0xf1, 0x0d, 0xaf, 0xe4, 0x4a, 0x1f, 0x82, 0xa6,
- 0xde, 0x5d, 0xd3, 0x4a, 0xbb, 0xde, 0xf1, 0xe7, 0x44, 0xfb, 0x13, 0x6a, 0x71, 0x0d, 0xb1, 0x72,
- 0x56, 0xba, 0xcd, 0xde, 0xfa, 0xfe, 0xb3, 0x5b, 0xfe, 0xc1, 0x78, 0xc9, 0xed, 0x22, 0xb2, 0x17,
- 0x05, 0xd1, 0xaf, 0xc0, 0xde, 0xee, 0x64, 0xe6, 0x36, 0xce, 0x67, 0x6e, 0xe3, 0x62, 0xe6, 0x36,
- 0xbe, 0xe4, 0xae, 0x35, 0xc9, 0x5d, 0xeb, 0x3c, 0x77, 0xad, 0x8b, 0xdc, 0xb5, 0xbe, 0xe7, 0xae,
- 0xf5, 0xf5, 0x87, 0xdb, 0x78, 0xfb, 0xbf, 0x01, 0xfe, 0x0a, 0x00, 0x00, 0xff, 0xff, 0xdb, 0xed,
- 0x64, 0xfc, 0x9c, 0x04, 0x00, 0x00,
+ // 616 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x94, 0x4f, 0x4f, 0x14, 0x3f,
+ 0x1c, 0xc6, 0x77, 0xd8, 0xdf, 0xf2, 0x5b, 0x8a, 0x04, 0x19, 0x62, 0xdc, 0x60, 0x32, 0x90, 0xf5,
+ 0x82, 0x26, 0xb4, 0x01, 0x8d, 0x31, 0xe1, 0x36, 0xf1, 0x62, 0xc2, 0x4a, 0x1c, 0x88, 0x24, 0xfe,
+ 0x89, 0x76, 0x3a, 0x5f, 0x96, 0xba, 0x3b, 0xd3, 0x49, 0xdb, 0x59, 0xc2, 0xcd, 0x97, 0xe0, 0x3b,
+ 0xf0, 0xed, 0x70, 0xc4, 0x1b, 0x27, 0x22, 0x63, 0x7c, 0x1f, 0x66, 0x3a, 0x9d, 0xfd, 0xc3, 0xa2,
+ 0xc2, 0x6d, 0xa7, 0x7d, 0x9e, 0x4f, 0x9f, 0x7e, 0x9f, 0x66, 0xd1, 0x41, 0xef, 0xb9, 0xc2, 0x5c,
+ 0x90, 0x5e, 0x16, 0x82, 0x4c, 0x40, 0x83, 0x22, 0x03, 0x48, 0x22, 0x21, 0x89, 0xdd, 0x88, 0x41,
+ 0x4b, 0xce, 0x14, 0x49, 0x7b, 0x5d, 0x42, 0x53, 0xae, 0x08, 0xcb, 0x94, 0x16, 0xf1, 0xc7, 0x6a,
+ 0x7d, 0xb0, 0x19, 0x82, 0xa6, 0x9b, 0xa4, 0x0b, 0x09, 0x48, 0xaa, 0x21, 0xc2, 0xa9, 0x14, 0x5a,
+ 0xb8, 0xb8, 0xf4, 0x63, 0xab, 0xc3, 0x69, 0xaf, 0x8b, 0x0b, 0x3f, 0x9e, 0xf4, 0x63, 0xeb, 0x5f,
+ 0xd9, 0xe8, 0x72, 0x7d, 0x94, 0x85, 0x98, 0x89, 0x98, 0x74, 0x45, 0x57, 0x10, 0x83, 0x09, 0xb3,
+ 0x43, 0xf3, 0x65, 0x3e, 0xcc, 0xaf, 0x12, 0xbf, 0xd2, 0xb6, 0xf1, 0x68, 0xca, 0x09, 0x13, 0x12,
+ 0xc8, 0x60, 0x2a, 0xc2, 0xca, 0xd3, 0x91, 0x26, 0xa6, 0xec, 0x88, 0x27, 0x20, 0x4f, 0xaa, 0x7b,
+ 0x10, 0x09, 0x4a, 0x64, 0x92, 0xc1, 0xad, 0x5c, 0xaa, 0x18, 0x07, 0xbd, 0xee, 0x2c, 0xf2, 0x27,
+ 0x97, 0xcc, 0x12, 0xcd, 0xe3, 0xe9, 0x63, 0x9e, 0xfd, 0xcb, 0xa0, 0xd8, 0x11, 0xc4, 0xf4, 0xaa,
+ 0xaf, 0xfd, 0xcd, 0x41, 0x4b, 0x1d, 0x33, 0xbb, 0x1d, 0xae, 0xf4, 0x6e, 0xaa, 0xb9, 0x48, 0x94,
+ 0xbb, 0x8d, 0x16, 0xfa, 0x34, 0x84, 0xfe, 0x1e, 0xf4, 0x81, 0x69, 0x21, 0x5b, 0xce, 0x9a, 0xb3,
+ 0x3e, 0xe7, 0xdf, 0x3b, 0xbd, 0x58, 0xad, 0xe5, 0x17, 0xab, 0x0b, 0x3b, 0xe3, 0x9b, 0xc1, 0xa4,
+ 0xd6, 0xed, 0xa0, 0xe5, 0xb2, 0x8d, 0x09, 0x55, 0x6b, 0xc6, 0x20, 0x1e, 0x58, 0xc4, 0x72, 0x67,
+ 0x5a, 0x12, 0x5c, 0xe7, 0x6b, 0xff, 0xaa, 0xa3, 0xf9, 0x52, 0xfc, 0x86, 0xf6, 0x33, 0x70, 0x0f,
+ 0xd1, 0x62, 0x04, 0x8a, 0x49, 0x1e, 0x42, 0xb4, 0x1b, 0x7e, 0x06, 0xa6, 0x4d, 0xba, 0xf9, 0xad,
+ 0x87, 0xd5, 0x1b, 0xa1, 0x29, 0xc7, 0x45, 0x89, 0x78, 0xb0, 0x89, 0x4b, 0x45, 0x00, 0x87, 0x20,
+ 0x21, 0x61, 0xe0, 0xdf, 0xb7, 0xe7, 0x2f, 0xbe, 0x98, 0x64, 0x04, 0x57, 0xa1, 0xee, 0x16, 0x42,
+ 0x65, 0x9c, 0x57, 0x34, 0x06, 0x9b, 0xde, 0xb5, 0x6e, 0xd4, 0x19, 0xee, 0x04, 0x63, 0x2a, 0xf7,
+ 0x1d, 0x9a, 0x2b, 0x86, 0xad, 0x34, 0x8d, 0xd3, 0x56, 0xdd, 0xa4, 0x7a, 0x3c, 0x96, 0x6a, 0xd8,
+ 0xcc, 0xe8, 0xf9, 0x16, 0x0f, 0xa0, 0xc8, 0xb9, 0xcf, 0x63, 0xf0, 0x97, 0x2c, 0x7e, 0x6e, 0xbf,
+ 0x82, 0x04, 0x23, 0x9e, 0xfb, 0x08, 0xcd, 0x1e, 0xf3, 0x24, 0x12, 0xc7, 0xad, 0xff, 0xd6, 0x9c,
+ 0xf5, 0xba, 0xbf, 0x54, 0x34, 0x71, 0x60, 0x56, 0xf6, 0x80, 0x89, 0x24, 0x52, 0x81, 0x15, 0xb8,
+ 0x7b, 0xa8, 0x31, 0x28, 0x86, 0xd5, 0x6a, 0x98, 0x0c, 0xf8, 0x6f, 0x19, 0x70, 0xf5, 0x74, 0xf1,
+ 0xeb, 0x8c, 0x26, 0x9a, 0xeb, 0x13, 0x7f, 0xc1, 0xe6, 0x68, 0x98, 0x89, 0x07, 0x25, 0xcb, 0xfd,
+ 0x80, 0x9a, 0xaa, 0x2a, 0x73, 0xd6, 0x70, 0x9f, 0xdc, 0xec, 0x6e, 0x13, 0x7d, 0xfa, 0x77, 0xf2,
+ 0x8b, 0xd5, 0xe6, 0xb0, 0xf2, 0x21, 0xb2, 0xfd, 0xdd, 0x41, 0x8b, 0x63, 0x3d, 0x17, 0xcf, 0xd1,
+ 0x7d, 0x8f, 0x9a, 0x05, 0x24, 0xa2, 0x9a, 0xda, 0x92, 0xf1, 0x0d, 0x8f, 0xe4, 0x4a, 0x77, 0x40,
+ 0x53, 0xff, 0xae, 0xbd, 0x4a, 0xb3, 0x5a, 0x09, 0x86, 0x44, 0xf7, 0x13, 0x6a, 0x70, 0x0d, 0xb1,
+ 0x6a, 0xcd, 0xac, 0xd5, 0xd7, 0xe7, 0xb7, 0xb6, 0x6f, 0xf9, 0x1f, 0x83, 0xc7, 0xd2, 0x8e, 0x46,
+ 0xf6, 0xb2, 0x20, 0x06, 0x25, 0xd8, 0xdf, 0x38, 0xbd, 0xf4, 0x6a, 0x67, 0x97, 0x5e, 0xed, 0xfc,
+ 0xd2, 0xab, 0x7d, 0xc9, 0x3d, 0xe7, 0x34, 0xf7, 0x9c, 0xb3, 0xdc, 0x73, 0xce, 0x73, 0xcf, 0xf9,
+ 0x91, 0x7b, 0xce, 0xd7, 0x9f, 0x5e, 0xed, 0xed, 0xff, 0x16, 0xf8, 0x3b, 0x00, 0x00, 0xff, 0xff,
+ 0xf5, 0x23, 0xb5, 0xdc, 0x3e, 0x05, 0x00, 0x00,
}
diff --git a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.proto b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.proto
index 76b8995056d..9d4d2596798 100644
--- a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.proto
+++ b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/generated.proto
@@ -30,6 +30,18 @@ import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto";
// Package-wide variables from generator "generated".
option go_package = "v1beta1";
+// MetricListOptions is used to select metrics by their label selectors
+message MetricListOptions {
+ // A selector to restrict the list of returned objects by their labels.
+ // Defaults to everything.
+ // +optional
+ optional string labelSelector = 1;
+
+ // A selector to restrict the list of returned metrics by their labels
+ // +optional
+ optional string metricLabelSelector = 2;
+}
+
// a metric value for some object
message MetricValue {
// a reference to the described object
diff --git a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/register.go b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/register.go
index 42fd2b92f02..f1b43e9cb60 100644
--- a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/register.go
+++ b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/register.go
@@ -43,6 +43,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&MetricValue{},
&MetricValueList{},
+ &MetricListOptions{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
diff --git a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/types.go b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/types.go
index 8f5901896a2..aa97053ca62 100644
--- a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/types.go
+++ b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/types.go
@@ -65,6 +65,22 @@ type MetricValue struct {
Selector *metav1.LabelSelector `json:"selector" protobuf:"bytes,6,opt,name=selector"`
}
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// MetricListOptions is used to select metrics by their label selectors
+type MetricListOptions struct {
+ metav1.TypeMeta `json:",inline"`
+
+ // A selector to restrict the list of returned objects by their labels.
+ // Defaults to everything.
+ // +optional
+ LabelSelector string `json:"labelSelector,omitempty" protobuf:"bytes,1,opt,name=labelSelector"`
+
+ // A selector to restrict the list of returned metrics by their labels
+ // +optional
+ MetricLabelSelector string `json:"metricLabelSelector,omitempty" protobuf:"bytes,2,opt,name=metricLabelSelector"`
+}
+
// allObjects is a wildcard used to select metrics
// for all objects matching the given label selector
const AllObjects = "*"
diff --git a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.conversion.go b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.conversion.go
index 5122f74d9d6..d3c587b8b6f 100644
--- a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.conversion.go
+++ b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.conversion.go
@@ -35,6 +35,16 @@ func init() {
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(s *runtime.Scheme) error {
+ if err := s.AddGeneratedConversionFunc((*MetricListOptions)(nil), (*custommetrics.MetricListOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1beta1_MetricListOptions_To_custom_metrics_MetricListOptions(a.(*MetricListOptions), b.(*custommetrics.MetricListOptions), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*custommetrics.MetricListOptions)(nil), (*MetricListOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_custom_metrics_MetricListOptions_To_v1beta1_MetricListOptions(a.(*custommetrics.MetricListOptions), b.(*MetricListOptions), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddGeneratedConversionFunc((*MetricValue)(nil), (*custommetrics.MetricValue)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_MetricValue_To_custom_metrics_MetricValue(a.(*MetricValue), b.(*custommetrics.MetricValue), scope)
}); err != nil {
@@ -68,6 +78,28 @@ func RegisterConversions(s *runtime.Scheme) error {
return nil
}
+func autoConvert_v1beta1_MetricListOptions_To_custom_metrics_MetricListOptions(in *MetricListOptions, out *custommetrics.MetricListOptions, s conversion.Scope) error {
+ out.LabelSelector = in.LabelSelector
+ out.MetricLabelSelector = in.MetricLabelSelector
+ return nil
+}
+
+// Convert_v1beta1_MetricListOptions_To_custom_metrics_MetricListOptions is an autogenerated conversion function.
+func Convert_v1beta1_MetricListOptions_To_custom_metrics_MetricListOptions(in *MetricListOptions, out *custommetrics.MetricListOptions, s conversion.Scope) error {
+ return autoConvert_v1beta1_MetricListOptions_To_custom_metrics_MetricListOptions(in, out, s)
+}
+
+func autoConvert_custom_metrics_MetricListOptions_To_v1beta1_MetricListOptions(in *custommetrics.MetricListOptions, out *MetricListOptions, s conversion.Scope) error {
+ out.LabelSelector = in.LabelSelector
+ out.MetricLabelSelector = in.MetricLabelSelector
+ return nil
+}
+
+// Convert_custom_metrics_MetricListOptions_To_v1beta1_MetricListOptions is an autogenerated conversion function.
+func Convert_custom_metrics_MetricListOptions_To_v1beta1_MetricListOptions(in *custommetrics.MetricListOptions, out *MetricListOptions, s conversion.Scope) error {
+ return autoConvert_custom_metrics_MetricListOptions_To_v1beta1_MetricListOptions(in, out, s)
+}
+
func autoConvert_v1beta1_MetricValue_To_custom_metrics_MetricValue(in *MetricValue, out *custommetrics.MetricValue, s conversion.Scope) error {
// TODO: Inefficient conversion - can we improve it?
if err := s.Convert(&in.DescribedObject, &out.DescribedObject, 0); err != nil {
diff --git a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.deepcopy.go b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.deepcopy.go
index c3e6a2614a2..4d2e11c725a 100644
--- a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.deepcopy.go
+++ b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1/zz_generated.deepcopy.go
@@ -25,6 +25,31 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *MetricListOptions) DeepCopyInto(out *MetricListOptions) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricListOptions.
+func (in *MetricListOptions) DeepCopy() *MetricListOptions {
+ if in == nil {
+ return nil
+ }
+ out := new(MetricListOptions)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *MetricListOptions) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MetricValue) DeepCopyInto(out *MetricValue) {
*out = *in
diff --git a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2/zz_generated.conversion.go b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2/zz_generated.conversion.go
index bb38f4cb312..6a12d034447 100644
--- a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2/zz_generated.conversion.go
+++ b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2/zz_generated.conversion.go
@@ -46,6 +46,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
+ if err := s.AddGeneratedConversionFunc((*MetricListOptions)(nil), (*custommetrics.MetricListOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_v1beta2_MetricListOptions_To_custom_metrics_MetricListOptions(a.(*MetricListOptions), b.(*custommetrics.MetricListOptions), scope)
+ }); err != nil {
+ return err
+ }
+ if err := s.AddGeneratedConversionFunc((*custommetrics.MetricListOptions)(nil), (*MetricListOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
+ return Convert_custom_metrics_MetricListOptions_To_v1beta2_MetricListOptions(a.(*custommetrics.MetricListOptions), b.(*MetricListOptions), scope)
+ }); err != nil {
+ return err
+ }
if err := s.AddGeneratedConversionFunc((*MetricValue)(nil), (*custommetrics.MetricValue)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta2_MetricValue_To_custom_metrics_MetricValue(a.(*MetricValue), b.(*custommetrics.MetricValue), scope)
}); err != nil {
@@ -91,6 +101,28 @@ func Convert_custom_metrics_MetricIdentifier_To_v1beta2_MetricIdentifier(in *cus
return autoConvert_custom_metrics_MetricIdentifier_To_v1beta2_MetricIdentifier(in, out, s)
}
+func autoConvert_v1beta2_MetricListOptions_To_custom_metrics_MetricListOptions(in *MetricListOptions, out *custommetrics.MetricListOptions, s conversion.Scope) error {
+ out.LabelSelector = in.LabelSelector
+ out.MetricLabelSelector = in.MetricLabelSelector
+ return nil
+}
+
+// Convert_v1beta2_MetricListOptions_To_custom_metrics_MetricListOptions is an autogenerated conversion function.
+func Convert_v1beta2_MetricListOptions_To_custom_metrics_MetricListOptions(in *MetricListOptions, out *custommetrics.MetricListOptions, s conversion.Scope) error {
+ return autoConvert_v1beta2_MetricListOptions_To_custom_metrics_MetricListOptions(in, out, s)
+}
+
+func autoConvert_custom_metrics_MetricListOptions_To_v1beta2_MetricListOptions(in *custommetrics.MetricListOptions, out *MetricListOptions, s conversion.Scope) error {
+ out.LabelSelector = in.LabelSelector
+ out.MetricLabelSelector = in.MetricLabelSelector
+ return nil
+}
+
+// Convert_custom_metrics_MetricListOptions_To_v1beta2_MetricListOptions is an autogenerated conversion function.
+func Convert_custom_metrics_MetricListOptions_To_v1beta2_MetricListOptions(in *custommetrics.MetricListOptions, out *MetricListOptions, s conversion.Scope) error {
+ return autoConvert_custom_metrics_MetricListOptions_To_v1beta2_MetricListOptions(in, out, s)
+}
+
func autoConvert_v1beta2_MetricValue_To_custom_metrics_MetricValue(in *MetricValue, out *custommetrics.MetricValue, s conversion.Scope) error {
// TODO: Inefficient conversion - can we improve it?
if err := s.Convert(&in.DescribedObject, &out.DescribedObject, 0); err != nil {
diff --git a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/zz_generated.deepcopy.go b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/zz_generated.deepcopy.go
index 0c110bbf519..a80a69130f0 100644
--- a/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/zz_generated.deepcopy.go
+++ b/staging/src/k8s.io/metrics/pkg/apis/custom_metrics/zz_generated.deepcopy.go
@@ -46,6 +46,31 @@ func (in *MetricIdentifier) DeepCopy() *MetricIdentifier {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *MetricListOptions) DeepCopyInto(out *MetricListOptions) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricListOptions.
+func (in *MetricListOptions) DeepCopy() *MetricListOptions {
+ if in == nil {
+ return nil
+ }
+ out := new(MetricListOptions)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *MetricListOptions) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MetricValue) DeepCopyInto(out *MetricValue) {
*out = *in
diff --git a/staging/src/k8s.io/metrics/pkg/client/custom_metrics/BUILD b/staging/src/k8s.io/metrics/pkg/client/custom_metrics/BUILD
index 262d485c936..90c00c99198 100644
--- a/staging/src/k8s.io/metrics/pkg/client/custom_metrics/BUILD
+++ b/staging/src/k8s.io/metrics/pkg/client/custom_metrics/BUILD
@@ -1,21 +1,29 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_library")
+load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
- "client.go",
+ "converter.go",
+ "discovery.go",
"interfaces.go",
+ "multi_client.go",
+ "versioned_client.go",
],
importmap = "k8s.io/kubernetes/vendor/k8s.io/metrics/pkg/client/custom_metrics",
importpath = "k8s.io/metrics/pkg/client/custom_metrics",
visibility = ["//visibility:public"],
deps = [
"//staging/src/k8s.io/apimachinery/pkg/api/meta: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/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
+ "//staging/src/k8s.io/client-go/discovery:go_default_library",
"//staging/src/k8s.io/client-go/rest:go_default_library",
"//staging/src/k8s.io/client-go/util/flowcontrol:go_default_library",
+ "//staging/src/k8s.io/metrics/pkg/apis/custom_metrics: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/client/custom_metrics/scheme:go_default_library",
],
@@ -38,3 +46,18 @@ filegroup(
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
+
+go_test(
+ name = "go_default_test",
+ srcs = ["util_test.go"],
+ embed = [":go_default_library"],
+ deps = [
+ "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
+ "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
+ "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
+ "//staging/src/k8s.io/metrics/pkg/apis/custom_metrics: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",
+ "//vendor/github.com/stretchr/testify/require:go_default_library",
+ ],
+)
diff --git a/staging/src/k8s.io/metrics/pkg/client/custom_metrics/converter.go b/staging/src/k8s.io/metrics/pkg/client/custom_metrics/converter.go
new file mode 100644
index 00000000000..d83d4670201
--- /dev/null
+++ b/staging/src/k8s.io/metrics/pkg/client/custom_metrics/converter.go
@@ -0,0 +1,122 @@
+/*
+Copyright 2018 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 custom_metrics
+
+import (
+ "fmt"
+
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/runtime/serializer"
+ "k8s.io/client-go/rest"
+
+ cmint "k8s.io/metrics/pkg/apis/custom_metrics"
+ cmv1beta1 "k8s.io/metrics/pkg/apis/custom_metrics/v1beta1"
+ cmv1beta2 "k8s.io/metrics/pkg/apis/custom_metrics/v1beta2"
+ "k8s.io/metrics/pkg/client/custom_metrics/scheme"
+)
+
+var (
+ // MetricVersions is the set of metric versions accepted by the converter.
+ MetricVersions = []schema.GroupVersion{
+ cmv1beta2.SchemeGroupVersion,
+ cmv1beta1.SchemeGroupVersion,
+ cmint.SchemeGroupVersion,
+ }
+)
+
+// MetricConverter knows how to convert between external MetricValue versions.
+type MetricConverter struct {
+ scheme *runtime.Scheme
+ codecs serializer.CodecFactory
+ internalVersioner runtime.GroupVersioner
+}
+
+// NewMetricConverter creates a MetricConverter which knows how to convert objects
+// between different versions of the custom metrics api.
+func NewMetricConverter() *MetricConverter {
+ return &MetricConverter{
+ scheme: scheme.Scheme,
+ codecs: serializer.NewCodecFactory(scheme.Scheme),
+ internalVersioner: runtime.NewMultiGroupVersioner(
+ scheme.SchemeGroupVersion,
+ schema.GroupKind{Group: cmint.GroupName, Kind: ""},
+ schema.GroupKind{Group: cmv1beta1.GroupName, Kind: ""},
+ schema.GroupKind{Group: cmv1beta2.GroupName, Kind: ""},
+ ),
+ }
+}
+
+// Scheme returns the scheme used by this metric converter.
+func (c *MetricConverter) Scheme() *runtime.Scheme {
+ return c.scheme
+}
+
+// Codecs returns the codecs used by this metric converter
+func (c *MetricConverter) Codecs() serializer.CodecFactory {
+ return c.codecs
+}
+
+// ConvertListOptionsToVersion converts converts a set of MetricListOptions
+// to the provided GroupVersion.
+func (c *MetricConverter) ConvertListOptionsToVersion(opts *cmint.MetricListOptions, version schema.GroupVersion) (runtime.Object, error) {
+ paramObj, err := c.UnsafeConvertToVersionVia(opts, version)
+ if err != nil {
+ return nil, err
+ }
+ return paramObj, nil
+}
+
+// ConvertResultToVersion converts a Result to the provided GroupVersion
+func (c *MetricConverter) ConvertResultToVersion(res rest.Result, gv schema.GroupVersion) (runtime.Object, error) {
+ if err := res.Error(); err != nil {
+ return nil, err
+ }
+
+ metricBytes, err := res.Raw()
+ if err != nil {
+ return nil, err
+ }
+
+ decoder := c.codecs.UniversalDecoder(MetricVersions...)
+ rawMetricObj, err := runtime.Decode(decoder, metricBytes)
+ if err != nil {
+ return nil, err
+ }
+
+ metricObj, err := c.UnsafeConvertToVersionVia(rawMetricObj, gv)
+ if err != nil {
+ return nil, err
+ }
+ return metricObj, nil
+}
+
+// unsafeConvertToVersionVia is like Scheme.UnsafeConvertToVersion, but it does so via an internal version first.
+// We use it here to work with the v1beta2 client internally, while preserving backwards compatibility for existing custom metrics adapters
+func (c *MetricConverter) UnsafeConvertToVersionVia(obj runtime.Object, externalVersion schema.GroupVersion) (runtime.Object, error) {
+ objInt, err := c.scheme.UnsafeConvertToVersion(obj, schema.GroupVersion{Group: externalVersion.Group, Version: runtime.APIVersionInternal})
+ if err != nil {
+ return nil, fmt.Errorf("failed to convert the given object to the internal version: %v", err)
+ }
+
+ objExt, err := c.scheme.UnsafeConvertToVersion(objInt, externalVersion)
+ if err != nil {
+ return nil, fmt.Errorf("failed to convert the given object back to the external version: %v", err)
+ }
+
+ return objExt, err
+}
diff --git a/staging/src/k8s.io/metrics/pkg/client/custom_metrics/discovery.go b/staging/src/k8s.io/metrics/pkg/client/custom_metrics/discovery.go
new file mode 100644
index 00000000000..7c9f8951bbc
--- /dev/null
+++ b/staging/src/k8s.io/metrics/pkg/client/custom_metrics/discovery.go
@@ -0,0 +1,145 @@
+/*
+Copyright 2018 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 custom_metrics
+
+import (
+ "fmt"
+ "sync"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/client-go/discovery"
+
+ cmint "k8s.io/metrics/pkg/apis/custom_metrics"
+)
+
+var (
+ // metricVersionsToGV is the map of string group-versions
+ // accepted by the converter to group-version objects (so
+ // we don't have to re-parse)
+ metricVersionsToGV map[string]schema.GroupVersion
+)
+
+func init() {
+ metricVersionsToGV = make(map[string]schema.GroupVersion)
+ for _, ver := range MetricVersions {
+ metricVersionsToGV[ver.String()] = ver
+ }
+}
+
+// NewAvailableAPIsGetter creates an AvailableAPIsGetter that checks discovery
+// to find the available versions of the custom metrics api.
+func NewAvailableAPIsGetter(client discovery.DiscoveryInterface) AvailableAPIsGetter {
+ return &apiVersionsFromDiscovery{
+ client: client,
+ }
+}
+
+// apiVersionsFromDiscovery caches a preferred version of the custom metrics api.
+type apiVersionsFromDiscovery struct {
+ client discovery.DiscoveryInterface
+
+ // just cache the group directly since the discovery interface doesn't yet allow
+ // asking for a single API group's versions.
+ prefVersion *schema.GroupVersion
+ mu sync.RWMutex
+}
+
+// fetchVersions fetches the versions, but doesn't try to invalidate on cache misses.
+func (d *apiVersionsFromDiscovery) fetchVersions() (*metav1.APIGroup, error) {
+ // TODO(directxman12): amend the discovery interface to ask for a particular group (/apis/foo)
+ groups, err := d.client.ServerGroups()
+ if err != nil {
+ return nil, err
+ }
+
+ // Determine the preferred version on the server by first finding the custom metrics group
+ var apiGroup *metav1.APIGroup
+ for _, group := range groups.Groups {
+ if group.Name == cmint.GroupName {
+ apiGroup = &group
+ break
+ }
+ }
+
+ if apiGroup == nil {
+ return nil, fmt.Errorf("no custom metrics API (%s) registered", cmint.GroupName)
+ }
+
+ return apiGroup, nil
+}
+
+// chooseVersion sets a preferred version of the custom metrics api based on available versions.
+func (d *apiVersionsFromDiscovery) chooseVersion(apiGroup *metav1.APIGroup) (schema.GroupVersion, error) {
+ var preferredVersion *schema.GroupVersion
+ if gv, present := metricVersionsToGV[apiGroup.PreferredVersion.GroupVersion]; present && len(apiGroup.PreferredVersion.GroupVersion) != 0 {
+ preferredVersion = &gv
+ } else {
+ for _, version := range apiGroup.Versions {
+ if gv, present := metricVersionsToGV[version.GroupVersion]; present {
+ preferredVersion = &gv
+ break
+ }
+ }
+ }
+
+ if preferredVersion == nil {
+ return schema.GroupVersion{}, fmt.Errorf("no known available metric versions found")
+ }
+ return *preferredVersion, nil
+}
+
+// PreferredVersion returns the current preferred version of the custom metrics api.
+// If none is specified, it will use the first known one.
+func (d *apiVersionsFromDiscovery) PreferredVersion() (schema.GroupVersion, error) {
+ d.mu.RLock()
+ if d.prefVersion != nil {
+ // if we've already got one, proceed with that
+ defer d.mu.RUnlock()
+ return *d.prefVersion, nil
+ }
+ d.mu.RUnlock()
+
+ d.mu.Lock()
+ defer d.mu.Unlock()
+
+ // double check, someone might have beaten us to it
+ if d.prefVersion != nil {
+ return *d.prefVersion, nil
+ }
+
+ // populate our cache
+ groupInfo, err := d.fetchVersions()
+ if err != nil {
+ return schema.GroupVersion{}, err
+ }
+ prefVersion, err := d.chooseVersion(groupInfo)
+ if err != nil {
+ return schema.GroupVersion{}, err
+ }
+
+ d.prefVersion = &prefVersion
+ return *d.prefVersion, nil
+}
+
+// Invalidate refreshes the preferred version information.
+func (d *apiVersionsFromDiscovery) Invalidate() {
+ d.mu.Lock()
+ defer d.mu.Unlock()
+
+ d.prefVersion = nil
+}
diff --git a/staging/src/k8s.io/metrics/pkg/client/custom_metrics/multi_client.go b/staging/src/k8s.io/metrics/pkg/client/custom_metrics/multi_client.go
new file mode 100644
index 00000000000..cbc91a9d26e
--- /dev/null
+++ b/staging/src/k8s.io/metrics/pkg/client/custom_metrics/multi_client.go
@@ -0,0 +1,138 @@
+/*
+Copyright 2018 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 custom_metrics
+
+import (
+ "sync"
+ "time"
+
+ "k8s.io/apimachinery/pkg/api/meta"
+ "k8s.io/apimachinery/pkg/labels"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/client-go/rest"
+
+ "k8s.io/metrics/pkg/apis/custom_metrics/v1beta2"
+)
+
+// AvailableAPIsGetter knows how to fetch and cache the preferred custom metrics API version,
+// and invalidate that cache when asked.
+type AvailableAPIsGetter interface {
+ PreferredVersion() (schema.GroupVersion, error)
+ Invalidate()
+}
+
+// PeriodicallyInvalidate periodically invalidates the preferred version cache until
+// told to stop.
+func PeriodicallyInvalidate(cache AvailableAPIsGetter, interval time.Duration, stopCh <-chan struct{}) {
+ ticker := time.NewTicker(interval)
+ defer ticker.Stop()
+
+ for {
+ select {
+ case <-ticker.C:
+ cache.Invalidate()
+ case <-stopCh:
+ break
+ }
+ }
+}
+
+// NewForConfig creates a new custom metrics client which delegates to a client which
+// uses the preferred api version.
+func NewForConfig(baseConfig *rest.Config, mapper meta.RESTMapper, availableAPIs AvailableAPIsGetter) CustomMetricsClient {
+ return &multiClient{
+ clients: make(map[schema.GroupVersion]CustomMetricsClient),
+ availableAPIs: availableAPIs,
+
+ newClient: func(ver schema.GroupVersion) (CustomMetricsClient, error) {
+ return NewForVersionForConfig(rest.CopyConfig(baseConfig), mapper, ver)
+ },
+ }
+}
+
+// multiClient is a CustomMetricsClient that can work with *any* metrics API version.
+type multiClient struct {
+ newClient func(schema.GroupVersion) (CustomMetricsClient, error)
+ clients map[schema.GroupVersion]CustomMetricsClient
+ availableAPIs AvailableAPIsGetter
+ mu sync.RWMutex
+}
+
+// getPreferredClient returns a custom metrics client of the preferred api version.
+func (c *multiClient) getPreferredClient() (CustomMetricsClient, error) {
+ pref, err := c.availableAPIs.PreferredVersion()
+ if err != nil {
+ return nil, err
+ }
+
+ c.mu.RLock()
+ client, present := c.clients[pref]
+ c.mu.RUnlock()
+ if present {
+ return client, nil
+ }
+
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ client, err = c.newClient(pref)
+ if err != nil {
+ return nil, err
+ }
+ c.clients[pref] = client
+
+ return client, nil
+}
+
+func (c *multiClient) RootScopedMetrics() MetricsInterface {
+ return &multiClientInterface{clients: c}
+}
+
+func (c *multiClient) NamespacedMetrics(namespace string) MetricsInterface {
+ return &multiClientInterface{
+ clients: c,
+ namespace: &namespace,
+ }
+}
+
+type multiClientInterface struct {
+ clients *multiClient
+ namespace *string
+}
+
+func (m *multiClientInterface) GetForObject(groupKind schema.GroupKind, name string, metricName string, metricSelector labels.Selector) (*v1beta2.MetricValue, error) {
+ client, err := m.clients.getPreferredClient()
+ if err != nil {
+ return nil, err
+ }
+ if m.namespace == nil {
+ return client.RootScopedMetrics().GetForObject(groupKind, name, metricName, metricSelector)
+ } else {
+ return client.NamespacedMetrics(*m.namespace).GetForObject(groupKind, name, metricName, metricSelector)
+ }
+}
+
+func (m *multiClientInterface) GetForObjects(groupKind schema.GroupKind, selector labels.Selector, metricName string, metricSelector labels.Selector) (*v1beta2.MetricValueList, error) {
+ client, err := m.clients.getPreferredClient()
+ if err != nil {
+ return nil, err
+ }
+ if m.namespace == nil {
+ return client.RootScopedMetrics().GetForObjects(groupKind, selector, metricName, metricSelector)
+ } else {
+ return client.NamespacedMetrics(*m.namespace).GetForObjects(groupKind, selector, metricName, metricSelector)
+ }
+}
diff --git a/staging/src/k8s.io/metrics/pkg/client/custom_metrics/scheme/BUILD b/staging/src/k8s.io/metrics/pkg/client/custom_metrics/scheme/BUILD
index 42e136a6edb..85e6e80a57f 100644
--- a/staging/src/k8s.io/metrics/pkg/client/custom_metrics/scheme/BUILD
+++ b/staging/src/k8s.io/metrics/pkg/client/custom_metrics/scheme/BUILD
@@ -11,6 +11,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
+ "//staging/src/k8s.io/metrics/pkg/apis/custom_metrics: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",
],
diff --git a/staging/src/k8s.io/metrics/pkg/client/custom_metrics/scheme/register.go b/staging/src/k8s.io/metrics/pkg/client/custom_metrics/scheme/register.go
index 314415517a5..9875f42f9c0 100644
--- a/staging/src/k8s.io/metrics/pkg/client/custom_metrics/scheme/register.go
+++ b/staging/src/k8s.io/metrics/pkg/client/custom_metrics/scheme/register.go
@@ -21,10 +21,15 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
+ cmint "k8s.io/metrics/pkg/apis/custom_metrics"
cmv1beta1 "k8s.io/metrics/pkg/apis/custom_metrics/v1beta1"
cmv1beta2 "k8s.io/metrics/pkg/apis/custom_metrics/v1beta2"
)
+const GroupName = cmv1beta1.GroupName
+
+var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
+
var Scheme = runtime.NewScheme()
var Codecs = serializer.NewCodecFactory(Scheme)
var ParameterCodec = runtime.NewParameterCodec(Scheme)
@@ -49,6 +54,7 @@ func init() {
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
// correctly.
func AddToScheme(scheme *runtime.Scheme) {
+ cmint.AddToScheme(scheme)
cmv1beta1.AddToScheme(scheme)
cmv1beta2.AddToScheme(scheme)
}
diff --git a/staging/src/k8s.io/metrics/pkg/client/custom_metrics/util_test.go b/staging/src/k8s.io/metrics/pkg/client/custom_metrics/util_test.go
new file mode 100644
index 00000000000..5d5dd12ef92
--- /dev/null
+++ b/staging/src/k8s.io/metrics/pkg/client/custom_metrics/util_test.go
@@ -0,0 +1,65 @@
+/*
+Copyright 2018 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 custom_metrics
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+
+ cmint "k8s.io/metrics/pkg/apis/custom_metrics"
+ cmv1beta1 "k8s.io/metrics/pkg/apis/custom_metrics/v1beta1"
+ cmv1beta2 "k8s.io/metrics/pkg/apis/custom_metrics/v1beta2"
+)
+
+func TestMetricConverter(t *testing.T) {
+ testCases := []struct {
+ name string
+ group schema.GroupVersion
+ expected runtime.Object
+ }{
+ {
+ name: "Use custom metrics v1beta2",
+ group: cmv1beta2.SchemeGroupVersion,
+ expected: &cmv1beta2.MetricListOptions{
+ TypeMeta: metav1.TypeMeta{Kind: "MetricListOptions", APIVersion: cmv1beta2.SchemeGroupVersion.String()},
+ MetricLabelSelector: "foo",
+ },
+ },
+ {
+ name: "Use custom metrics v1beta1",
+ group: cmv1beta1.SchemeGroupVersion,
+ expected: &cmv1beta1.MetricListOptions{
+ TypeMeta: metav1.TypeMeta{Kind: "MetricListOptions", APIVersion: cmv1beta1.SchemeGroupVersion.String()},
+ MetricLabelSelector: "foo",
+ },
+ },
+ }
+
+ for _, test := range testCases {
+ t.Run(test.name, func(t *testing.T) {
+ metricConverter := NewMetricConverter()
+ opts := &cmint.MetricListOptions{MetricLabelSelector: "foo"}
+ res, err := metricConverter.ConvertListOptionsToVersion(opts, test.group)
+ require.NoError(t, err)
+ require.Equal(t, test.expected, res)
+ })
+ }
+}
diff --git a/staging/src/k8s.io/metrics/pkg/client/custom_metrics/client.go b/staging/src/k8s.io/metrics/pkg/client/custom_metrics/versioned_client.go
similarity index 61%
rename from staging/src/k8s.io/metrics/pkg/client/custom_metrics/client.go
rename to staging/src/k8s.io/metrics/pkg/client/custom_metrics/versioned_client.go
index d399ca059c1..f26785bf8ec 100644
--- a/staging/src/k8s.io/metrics/pkg/client/custom_metrics/client.go
+++ b/staging/src/k8s.io/metrics/pkg/client/custom_metrics/versioned_client.go
@@ -25,22 +25,35 @@ import (
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/client-go/rest"
"k8s.io/client-go/util/flowcontrol"
+
+ cmint "k8s.io/metrics/pkg/apis/custom_metrics"
+ "k8s.io/metrics/pkg/apis/custom_metrics/v1beta1"
"k8s.io/metrics/pkg/apis/custom_metrics/v1beta2"
"k8s.io/metrics/pkg/client/custom_metrics/scheme"
)
+var (
+ codecs = serializer.NewCodecFactory(scheme.Scheme)
+ versionConverter = NewMetricConverter()
+)
+
type customMetricsClient struct {
- client rest.Interface
- mapper meta.RESTMapper
+ client rest.Interface
+ version schema.GroupVersion
+ mapper meta.RESTMapper
}
-func New(client rest.Interface) CustomMetricsClient {
+// NewForVersion returns a new CustomMetricsClient for a particular api version.
+func NewForVersion(client rest.Interface, mapper meta.RESTMapper, version schema.GroupVersion) CustomMetricsClient {
return &customMetricsClient{
- client: client,
+ client: client,
+ version: version,
+ mapper: mapper,
}
}
-func NewForConfig(c *rest.Config) (CustomMetricsClient, error) {
+// NewForVersionForConfig returns a new CustomMetricsClient for a particular api version and base configuration.
+func NewForVersionForConfig(c *rest.Config, mapper meta.RESTMapper, version schema.GroupVersion) (CustomMetricsClient, error) {
configShallowCopy := *c
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
@@ -49,7 +62,7 @@ func NewForConfig(c *rest.Config) (CustomMetricsClient, error) {
if configShallowCopy.UserAgent == "" {
configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent()
}
- configShallowCopy.GroupVersion = &v1beta2.SchemeGroupVersion
+ configShallowCopy.GroupVersion = &version
configShallowCopy.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
client, err := rest.RESTClientFor(&configShallowCopy)
@@ -57,24 +70,7 @@ func NewForConfig(c *rest.Config) (CustomMetricsClient, error) {
return nil, err
}
- return New(client), nil
-}
-
-func NewForConfigOrDie(c *rest.Config) CustomMetricsClient {
- client, err := NewForConfig(c)
- if err != nil {
- panic(err)
- }
- return client
-}
-
-// NewForMapper constructs the client with a RESTMapper, which allows more
-// accurate translation from GroupVersionKind to GroupVersionResource.
-func NewForMapper(client rest.Interface, mapper meta.RESTMapper) CustomMetricsClient {
- return &customMetricsClient{
- client: client,
- mapper: mapper,
- }
+ return NewForVersion(client, mapper, version), nil
}
func (c *customMetricsClient) RootScopedMetrics() MetricsInterface {
@@ -88,16 +84,8 @@ func (c *customMetricsClient) NamespacedMetrics(namespace string) MetricsInterfa
}
}
+// qualResourceForKind returns the string format of a qualified group resource for the specified GroupKind
func (c *customMetricsClient) qualResourceForKind(groupKind schema.GroupKind) (string, error) {
- if c.mapper == nil {
- // the version doesn't matter
- gvk := groupKind.WithVersion("")
- gvr, _ := meta.UnsafeGuessKindToResource(gvk)
- gr := gvr.GroupResource()
- return gr.String(), nil
- }
-
- // use the mapper if it's available
mapping, err := c.mapper.RESTMapping(groupKind)
if err != nil {
return "", fmt.Errorf("unable to map kind %s to resource: %v", groupKind.String(), err)
@@ -112,21 +100,26 @@ type rootScopedMetrics struct {
}
func (m *rootScopedMetrics) getForNamespace(namespace string, metricName string, metricSelector labels.Selector) (*v1beta2.MetricValue, error) {
- res := &v1beta2.MetricValueList{}
- err := m.client.client.Get().
- Resource("metrics").
- Namespace(namespace).
- Name(metricName).
- VersionedParams(&v1beta2.MetricListOptions{
- MetricLabelSelector: metricSelector.String(),
- }, scheme.ParameterCodec).
- Do().
- Into(res)
-
+ params, err := versionConverter.ConvertListOptionsToVersion(&cmint.MetricListOptions{
+ MetricLabelSelector: metricSelector.String(),
+ }, m.client.version)
if err != nil {
return nil, err
}
+ result := m.client.client.Get().
+ Resource("metrics").
+ Namespace(namespace).
+ Name(metricName).
+ VersionedParams(params, scheme.ParameterCodec).
+ Do()
+
+ metricObj, err := versionConverter.ConvertResultToVersion(result, v1beta2.SchemeGroupVersion)
+ if err != nil {
+ return nil, err
+ }
+
+ res := metricObj.(*v1beta2.MetricValueList)
if len(res.Items) != 1 {
return nil, fmt.Errorf("the custom metrics API server returned %v results when we asked for exactly one", len(res.Items))
}
@@ -145,21 +138,26 @@ func (m *rootScopedMetrics) GetForObject(groupKind schema.GroupKind, name string
return nil, err
}
- res := &v1beta2.MetricValueList{}
- err = m.client.client.Get().
- Resource(resourceName).
- Name(name).
- SubResource(metricName).
- VersionedParams(&v1beta2.MetricListOptions{
- MetricLabelSelector: metricSelector.String(),
- }, scheme.ParameterCodec).
- Do().
- Into(res)
-
+ params, err := versionConverter.ConvertListOptionsToVersion(&cmint.MetricListOptions{
+ MetricLabelSelector: metricSelector.String(),
+ }, m.client.version)
if err != nil {
return nil, err
}
+ result := m.client.client.Get().
+ Resource(resourceName).
+ Name(name).
+ SubResource(metricName).
+ VersionedParams(params, scheme.ParameterCodec).
+ Do()
+
+ metricObj, err := versionConverter.ConvertResultToVersion(result, v1beta2.SchemeGroupVersion)
+ if err != nil {
+ return nil, err
+ }
+
+ res := metricObj.(*v1beta2.MetricValueList)
if len(res.Items) != 1 {
return nil, fmt.Errorf("the custom metrics API server returned %v results when we asked for exactly one", len(res.Items))
}
@@ -178,22 +176,27 @@ func (m *rootScopedMetrics) GetForObjects(groupKind schema.GroupKind, selector l
return nil, err
}
- res := &v1beta2.MetricValueList{}
- err = m.client.client.Get().
- Resource(resourceName).
- Name(v1beta2.AllObjects).
- SubResource(metricName).
- VersionedParams(&v1beta2.MetricListOptions{
- LabelSelector: selector.String(),
- MetricLabelSelector: metricSelector.String(),
- }, scheme.ParameterCodec).
- Do().
- Into(res)
-
+ params, err := versionConverter.ConvertListOptionsToVersion(&cmint.MetricListOptions{
+ LabelSelector: selector.String(),
+ MetricLabelSelector: metricSelector.String(),
+ }, m.client.version)
if err != nil {
return nil, err
}
+ result := m.client.client.Get().
+ Resource(resourceName).
+ Name(v1beta1.AllObjects).
+ SubResource(metricName).
+ VersionedParams(params, scheme.ParameterCodec).
+ Do()
+
+ metricObj, err := versionConverter.ConvertResultToVersion(result, v1beta2.SchemeGroupVersion)
+ if err != nil {
+ return nil, err
+ }
+
+ res := metricObj.(*v1beta2.MetricValueList)
return res, nil
}
@@ -208,22 +211,27 @@ func (m *namespacedMetrics) GetForObject(groupKind schema.GroupKind, name string
return nil, err
}
- res := &v1beta2.MetricValueList{}
- err = m.client.client.Get().
- Resource(resourceName).
- Namespace(m.namespace).
- Name(name).
- SubResource(metricName).
- VersionedParams(&v1beta2.MetricListOptions{
- MetricLabelSelector: metricSelector.String(),
- }, scheme.ParameterCodec).
- Do().
- Into(res)
-
+ params, err := versionConverter.ConvertListOptionsToVersion(&cmint.MetricListOptions{
+ MetricLabelSelector: metricSelector.String(),
+ }, m.client.version)
if err != nil {
return nil, err
}
+ result := m.client.client.Get().
+ Resource(resourceName).
+ Namespace(m.namespace).
+ Name(name).
+ SubResource(metricName).
+ VersionedParams(params, scheme.ParameterCodec).
+ Do()
+
+ metricObj, err := versionConverter.ConvertResultToVersion(result, v1beta2.SchemeGroupVersion)
+ if err != nil {
+ return nil, err
+ }
+
+ res := metricObj.(*v1beta2.MetricValueList)
if len(res.Items) != 1 {
return nil, fmt.Errorf("the custom metrics API server returned %v results when we asked for exactly one", len(res.Items))
}
@@ -237,22 +245,27 @@ func (m *namespacedMetrics) GetForObjects(groupKind schema.GroupKind, selector l
return nil, err
}
- res := &v1beta2.MetricValueList{}
- err = m.client.client.Get().
- Resource(resourceName).
- Namespace(m.namespace).
- Name(v1beta2.AllObjects).
- SubResource(metricName).
- VersionedParams(&v1beta2.MetricListOptions{
- LabelSelector: selector.String(),
- MetricLabelSelector: metricSelector.String(),
- }, scheme.ParameterCodec).
- Do().
- Into(res)
-
+ params, err := versionConverter.ConvertListOptionsToVersion(&cmint.MetricListOptions{
+ LabelSelector: selector.String(),
+ MetricLabelSelector: metricSelector.String(),
+ }, m.client.version)
if err != nil {
return nil, err
}
+ result := m.client.client.Get().
+ Resource(resourceName).
+ Namespace(m.namespace).
+ Name(v1beta1.AllObjects).
+ SubResource(metricName).
+ VersionedParams(params, scheme.ParameterCodec).
+ Do()
+
+ metricObj, err := versionConverter.ConvertResultToVersion(result, v1beta2.SchemeGroupVersion)
+ if err != nil {
+ return nil, err
+ }
+
+ res := metricObj.(*v1beta2.MetricValueList)
return res, nil
}
diff --git a/test/e2e/instrumentation/monitoring/BUILD b/test/e2e/instrumentation/monitoring/BUILD
index a712842964f..8f647a964c3 100644
--- a/test/e2e/instrumentation/monitoring/BUILD
+++ b/test/e2e/instrumentation/monitoring/BUILD
@@ -22,6 +22,7 @@ go_library(
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/api/extensions/v1beta1:go_default_library",
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
+ "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource: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",
@@ -30,6 +31,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/client-go/discovery:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
+ "//staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1:go_default_library",
"//staging/src/k8s.io/metrics/pkg/client/custom_metrics:go_default_library",
"//staging/src/k8s.io/metrics/pkg/client/external_metrics:go_default_library",
"//test/e2e/common:go_default_library",
diff --git a/test/e2e/instrumentation/monitoring/custom_metrics_stackdriver.go b/test/e2e/instrumentation/monitoring/custom_metrics_stackdriver.go
index 6f586b6219d..36bed14bc69 100644
--- a/test/e2e/instrumentation/monitoring/custom_metrics_stackdriver.go
+++ b/test/e2e/instrumentation/monitoring/custom_metrics_stackdriver.go
@@ -29,11 +29,13 @@ import (
gcm "google.golang.org/api/monitoring/v3"
"k8s.io/api/core/v1"
+ "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/selection"
"k8s.io/client-go/discovery"
"k8s.io/kubernetes/test/e2e/framework"
+ cmv1beta1 "k8s.io/metrics/pkg/apis/custom_metrics/v1beta1"
customclient "k8s.io/metrics/pkg/client/custom_metrics"
externalclient "k8s.io/metrics/pkg/client/external_metrics"
)
@@ -57,8 +59,10 @@ var _ = instrumentation.SIGDescribe("Stackdriver Monitoring", func() {
if err != nil {
framework.Failf("Failed to load config: %s", err)
}
- customMetricsClient := customclient.NewForConfigOrDie(config)
discoveryClient := discovery.NewDiscoveryClientForConfigOrDie(config)
+ apiVersionsGetter := customclient.NewAvailableAPIsGetter(discoveryClient)
+ restMapper := meta.NewDefaultRESTMapper([]schema.GroupVersion{cmv1beta1.SchemeGroupVersion})
+ customMetricsClient := customclient.NewForConfig(config, restMapper, apiVersionsGetter)
testCustomMetrics(f, kubeClient, customMetricsClient, discoveryClient, AdapterForOldResourceModel)
})
@@ -68,8 +72,10 @@ var _ = instrumentation.SIGDescribe("Stackdriver Monitoring", func() {
if err != nil {
framework.Failf("Failed to load config: %s", err)
}
- customMetricsClient := customclient.NewForConfigOrDie(config)
discoveryClient := discovery.NewDiscoveryClientForConfigOrDie(config)
+ apiVersionsGetter := customclient.NewAvailableAPIsGetter(discoveryClient)
+ restMapper := meta.NewDefaultRESTMapper([]schema.GroupVersion{cmv1beta1.SchemeGroupVersion})
+ customMetricsClient := customclient.NewForConfig(config, restMapper, apiVersionsGetter)
testCustomMetrics(f, kubeClient, customMetricsClient, discoveryClient, AdapterForNewResourceModel)
})