Merge pull request #60096 from MaciekPytel/hpa_api_ext
Automatic merge from submit-queue (batch tested with PRs 60208, 60084, 60183, 59713, 60096). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Add external metric type to HPA API **What this PR does / why we need it**: Add external metric type to HPA API proposed in xref https://github.com/kubernetes/community/pull/1801 **Release note**: ```release-note Allows HorizontalPodAutoscaler to use global metrics not associated with any Kubernetes object (for example metrics from a hoster service running outside of Kubernetes cluster). ```
This commit is contained in:
@@ -111,6 +111,12 @@ var (
|
||||
// Kubernetes, and have special scaling options on top of those available
|
||||
// to normal per-pod metrics (the "pods" source).
|
||||
ResourceMetricSourceType MetricSourceType = "Resource"
|
||||
// ExternalMetricSourceType is a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
// (for example length of queue in cloud messaging service, or
|
||||
// QPS from loadbalancer running outside of cluster).
|
||||
ExternalMetricSourceType MetricSourceType = "External"
|
||||
)
|
||||
|
||||
// MetricSpec specifies how to scale based on a single metric
|
||||
@@ -136,6 +142,13 @@ type MetricSpec struct {
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
Resource *ResourceMetricSource
|
||||
// External refers to a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
// (for example length of queue in cloud messaging service, or
|
||||
// QPS from loadbalancer running outside of cluster).
|
||||
// +optional
|
||||
External *ExternalMetricSource
|
||||
}
|
||||
|
||||
// ObjectMetricSource indicates how to scale on a metric describing a
|
||||
@@ -184,6 +197,26 @@ type ResourceMetricSource struct {
|
||||
TargetAverageValue *resource.Quantity
|
||||
}
|
||||
|
||||
// ExternalMetricSource indicates how to scale on a metric not associated with
|
||||
// any Kubernetes object (for example length of queue in cloud
|
||||
// messaging service, or QPS from loadbalancer running outside of cluster).
|
||||
type ExternalMetricSource struct {
|
||||
// metricName is the name of the metric in question.
|
||||
MetricName string
|
||||
// MetricSelector is used to identify a specific time series
|
||||
// within a given metric.
|
||||
// +optional
|
||||
MetricSelector *metav1.LabelSelector
|
||||
// TargetValue is the target value of the metric (as a quantity).
|
||||
// Mutually exclusive with TargetAverageValue.
|
||||
// +optional
|
||||
TargetValue *resource.Quantity
|
||||
// TargetAverageValue is the target per-pod value of global metric (as a quantity).
|
||||
// Mutually exclusive with TargetValue.
|
||||
// +optional
|
||||
TargetAverageValue *resource.Quantity
|
||||
}
|
||||
|
||||
// HorizontalPodAutoscalerStatus describes the current status of a horizontal pod autoscaler.
|
||||
type HorizontalPodAutoscalerStatus struct {
|
||||
// ObservedGeneration is the most recent generation observed by this autoscaler.
|
||||
@@ -282,6 +315,13 @@ type MetricStatus struct {
|
||||
// to normal per-pod metrics using the "pods" source.
|
||||
// +optional
|
||||
Resource *ResourceMetricStatus
|
||||
// External refers to a global metric that is not associated
|
||||
// with any Kubernetes object. It allows autoscaling based on information
|
||||
// coming from components running outside of cluster
|
||||
// (for example length of queue in cloud messaging service, or
|
||||
// QPS from loadbalancer running outside of cluster).
|
||||
// +optional
|
||||
External *ExternalMetricStatus
|
||||
}
|
||||
|
||||
// ObjectMetricStatus indicates the current value of a metric describing a
|
||||
@@ -328,6 +368,23 @@ type ResourceMetricStatus struct {
|
||||
CurrentAverageValue resource.Quantity
|
||||
}
|
||||
|
||||
// ExternalMetricStatus indicates the current value of a global metric
|
||||
// not associated with any Kubernetes object.
|
||||
type ExternalMetricStatus struct {
|
||||
// MetricName is the name of a metric used for autoscaling in
|
||||
// metric system.
|
||||
MetricName string
|
||||
// MetricSelector is used to identify a specific time series
|
||||
// within a given metric.
|
||||
// +optional
|
||||
MetricSelector *metav1.LabelSelector
|
||||
// CurrentValue is the current value of the metric (as a quantity)
|
||||
CurrentValue resource.Quantity
|
||||
// CurrentAverageValue is the current value of metric averaged over autoscaled pods.
|
||||
// +optional
|
||||
CurrentAverageValue *resource.Quantity
|
||||
}
|
||||
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
|
60
pkg/apis/autoscaling/v1/zz_generated.conversion.go
generated
60
pkg/apis/autoscaling/v1/zz_generated.conversion.go
generated
@@ -43,6 +43,10 @@ func RegisterConversions(scheme *runtime.Scheme) error {
|
||||
return scheme.AddGeneratedConversionFuncs(
|
||||
Convert_v1_CrossVersionObjectReference_To_autoscaling_CrossVersionObjectReference,
|
||||
Convert_autoscaling_CrossVersionObjectReference_To_v1_CrossVersionObjectReference,
|
||||
Convert_v1_ExternalMetricSource_To_autoscaling_ExternalMetricSource,
|
||||
Convert_autoscaling_ExternalMetricSource_To_v1_ExternalMetricSource,
|
||||
Convert_v1_ExternalMetricStatus_To_autoscaling_ExternalMetricStatus,
|
||||
Convert_autoscaling_ExternalMetricStatus_To_v1_ExternalMetricStatus,
|
||||
Convert_v1_HorizontalPodAutoscaler_To_autoscaling_HorizontalPodAutoscaler,
|
||||
Convert_autoscaling_HorizontalPodAutoscaler_To_v1_HorizontalPodAutoscaler,
|
||||
Convert_v1_HorizontalPodAutoscalerCondition_To_autoscaling_HorizontalPodAutoscalerCondition,
|
||||
@@ -102,6 +106,58 @@ func Convert_autoscaling_CrossVersionObjectReference_To_v1_CrossVersionObjectRef
|
||||
return autoConvert_autoscaling_CrossVersionObjectReference_To_v1_CrossVersionObjectReference(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_ExternalMetricSource_To_autoscaling_ExternalMetricSource(in *v1.ExternalMetricSource, out *autoscaling.ExternalMetricSource, s conversion.Scope) error {
|
||||
out.MetricName = in.MetricName
|
||||
out.MetricSelector = (*meta_v1.LabelSelector)(unsafe.Pointer(in.MetricSelector))
|
||||
out.TargetValue = (*resource.Quantity)(unsafe.Pointer(in.TargetValue))
|
||||
out.TargetAverageValue = (*resource.Quantity)(unsafe.Pointer(in.TargetAverageValue))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_ExternalMetricSource_To_autoscaling_ExternalMetricSource is an autogenerated conversion function.
|
||||
func Convert_v1_ExternalMetricSource_To_autoscaling_ExternalMetricSource(in *v1.ExternalMetricSource, out *autoscaling.ExternalMetricSource, s conversion.Scope) error {
|
||||
return autoConvert_v1_ExternalMetricSource_To_autoscaling_ExternalMetricSource(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_autoscaling_ExternalMetricSource_To_v1_ExternalMetricSource(in *autoscaling.ExternalMetricSource, out *v1.ExternalMetricSource, s conversion.Scope) error {
|
||||
out.MetricName = in.MetricName
|
||||
out.MetricSelector = (*meta_v1.LabelSelector)(unsafe.Pointer(in.MetricSelector))
|
||||
out.TargetValue = (*resource.Quantity)(unsafe.Pointer(in.TargetValue))
|
||||
out.TargetAverageValue = (*resource.Quantity)(unsafe.Pointer(in.TargetAverageValue))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_autoscaling_ExternalMetricSource_To_v1_ExternalMetricSource is an autogenerated conversion function.
|
||||
func Convert_autoscaling_ExternalMetricSource_To_v1_ExternalMetricSource(in *autoscaling.ExternalMetricSource, out *v1.ExternalMetricSource, s conversion.Scope) error {
|
||||
return autoConvert_autoscaling_ExternalMetricSource_To_v1_ExternalMetricSource(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_ExternalMetricStatus_To_autoscaling_ExternalMetricStatus(in *v1.ExternalMetricStatus, out *autoscaling.ExternalMetricStatus, s conversion.Scope) error {
|
||||
out.MetricName = in.MetricName
|
||||
out.MetricSelector = (*meta_v1.LabelSelector)(unsafe.Pointer(in.MetricSelector))
|
||||
out.CurrentValue = in.CurrentValue
|
||||
out.CurrentAverageValue = (*resource.Quantity)(unsafe.Pointer(in.CurrentAverageValue))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_ExternalMetricStatus_To_autoscaling_ExternalMetricStatus is an autogenerated conversion function.
|
||||
func Convert_v1_ExternalMetricStatus_To_autoscaling_ExternalMetricStatus(in *v1.ExternalMetricStatus, out *autoscaling.ExternalMetricStatus, s conversion.Scope) error {
|
||||
return autoConvert_v1_ExternalMetricStatus_To_autoscaling_ExternalMetricStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_autoscaling_ExternalMetricStatus_To_v1_ExternalMetricStatus(in *autoscaling.ExternalMetricStatus, out *v1.ExternalMetricStatus, s conversion.Scope) error {
|
||||
out.MetricName = in.MetricName
|
||||
out.MetricSelector = (*meta_v1.LabelSelector)(unsafe.Pointer(in.MetricSelector))
|
||||
out.CurrentValue = in.CurrentValue
|
||||
out.CurrentAverageValue = (*resource.Quantity)(unsafe.Pointer(in.CurrentAverageValue))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_autoscaling_ExternalMetricStatus_To_v1_ExternalMetricStatus is an autogenerated conversion function.
|
||||
func Convert_autoscaling_ExternalMetricStatus_To_v1_ExternalMetricStatus(in *autoscaling.ExternalMetricStatus, out *v1.ExternalMetricStatus, s conversion.Scope) error {
|
||||
return autoConvert_autoscaling_ExternalMetricStatus_To_v1_ExternalMetricStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_HorizontalPodAutoscaler_To_autoscaling_HorizontalPodAutoscaler(in *v1.HorizontalPodAutoscaler, out *autoscaling.HorizontalPodAutoscaler, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
if err := Convert_v1_HorizontalPodAutoscalerSpec_To_autoscaling_HorizontalPodAutoscalerSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
@@ -238,6 +294,7 @@ func autoConvert_v1_MetricSpec_To_autoscaling_MetricSpec(in *v1.MetricSpec, out
|
||||
out.Object = (*autoscaling.ObjectMetricSource)(unsafe.Pointer(in.Object))
|
||||
out.Pods = (*autoscaling.PodsMetricSource)(unsafe.Pointer(in.Pods))
|
||||
out.Resource = (*autoscaling.ResourceMetricSource)(unsafe.Pointer(in.Resource))
|
||||
out.External = (*autoscaling.ExternalMetricSource)(unsafe.Pointer(in.External))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -251,6 +308,7 @@ func autoConvert_autoscaling_MetricSpec_To_v1_MetricSpec(in *autoscaling.MetricS
|
||||
out.Object = (*v1.ObjectMetricSource)(unsafe.Pointer(in.Object))
|
||||
out.Pods = (*v1.PodsMetricSource)(unsafe.Pointer(in.Pods))
|
||||
out.Resource = (*v1.ResourceMetricSource)(unsafe.Pointer(in.Resource))
|
||||
out.External = (*v1.ExternalMetricSource)(unsafe.Pointer(in.External))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -264,6 +322,7 @@ func autoConvert_v1_MetricStatus_To_autoscaling_MetricStatus(in *v1.MetricStatus
|
||||
out.Object = (*autoscaling.ObjectMetricStatus)(unsafe.Pointer(in.Object))
|
||||
out.Pods = (*autoscaling.PodsMetricStatus)(unsafe.Pointer(in.Pods))
|
||||
out.Resource = (*autoscaling.ResourceMetricStatus)(unsafe.Pointer(in.Resource))
|
||||
out.External = (*autoscaling.ExternalMetricStatus)(unsafe.Pointer(in.External))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -277,6 +336,7 @@ func autoConvert_autoscaling_MetricStatus_To_v1_MetricStatus(in *autoscaling.Met
|
||||
out.Object = (*v1.ObjectMetricStatus)(unsafe.Pointer(in.Object))
|
||||
out.Pods = (*v1.PodsMetricStatus)(unsafe.Pointer(in.Pods))
|
||||
out.Resource = (*v1.ResourceMetricStatus)(unsafe.Pointer(in.Resource))
|
||||
out.External = (*v1.ExternalMetricStatus)(unsafe.Pointer(in.External))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -24,9 +24,9 @@ import (
|
||||
unsafe "unsafe"
|
||||
|
||||
v2beta1 "k8s.io/api/autoscaling/v2beta1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
core_v1 "k8s.io/api/core/v1"
|
||||
resource "k8s.io/apimachinery/pkg/api/resource"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
autoscaling "k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
@@ -43,6 +43,10 @@ func RegisterConversions(scheme *runtime.Scheme) error {
|
||||
return scheme.AddGeneratedConversionFuncs(
|
||||
Convert_v2beta1_CrossVersionObjectReference_To_autoscaling_CrossVersionObjectReference,
|
||||
Convert_autoscaling_CrossVersionObjectReference_To_v2beta1_CrossVersionObjectReference,
|
||||
Convert_v2beta1_ExternalMetricSource_To_autoscaling_ExternalMetricSource,
|
||||
Convert_autoscaling_ExternalMetricSource_To_v2beta1_ExternalMetricSource,
|
||||
Convert_v2beta1_ExternalMetricStatus_To_autoscaling_ExternalMetricStatus,
|
||||
Convert_autoscaling_ExternalMetricStatus_To_v2beta1_ExternalMetricStatus,
|
||||
Convert_v2beta1_HorizontalPodAutoscaler_To_autoscaling_HorizontalPodAutoscaler,
|
||||
Convert_autoscaling_HorizontalPodAutoscaler_To_v2beta1_HorizontalPodAutoscaler,
|
||||
Convert_v2beta1_HorizontalPodAutoscalerCondition_To_autoscaling_HorizontalPodAutoscalerCondition,
|
||||
@@ -96,6 +100,58 @@ func Convert_autoscaling_CrossVersionObjectReference_To_v2beta1_CrossVersionObje
|
||||
return autoConvert_autoscaling_CrossVersionObjectReference_To_v2beta1_CrossVersionObjectReference(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v2beta1_ExternalMetricSource_To_autoscaling_ExternalMetricSource(in *v2beta1.ExternalMetricSource, out *autoscaling.ExternalMetricSource, s conversion.Scope) error {
|
||||
out.MetricName = in.MetricName
|
||||
out.MetricSelector = (*v1.LabelSelector)(unsafe.Pointer(in.MetricSelector))
|
||||
out.TargetValue = (*resource.Quantity)(unsafe.Pointer(in.TargetValue))
|
||||
out.TargetAverageValue = (*resource.Quantity)(unsafe.Pointer(in.TargetAverageValue))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v2beta1_ExternalMetricSource_To_autoscaling_ExternalMetricSource is an autogenerated conversion function.
|
||||
func Convert_v2beta1_ExternalMetricSource_To_autoscaling_ExternalMetricSource(in *v2beta1.ExternalMetricSource, out *autoscaling.ExternalMetricSource, s conversion.Scope) error {
|
||||
return autoConvert_v2beta1_ExternalMetricSource_To_autoscaling_ExternalMetricSource(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_autoscaling_ExternalMetricSource_To_v2beta1_ExternalMetricSource(in *autoscaling.ExternalMetricSource, out *v2beta1.ExternalMetricSource, s conversion.Scope) error {
|
||||
out.MetricName = in.MetricName
|
||||
out.MetricSelector = (*v1.LabelSelector)(unsafe.Pointer(in.MetricSelector))
|
||||
out.TargetValue = (*resource.Quantity)(unsafe.Pointer(in.TargetValue))
|
||||
out.TargetAverageValue = (*resource.Quantity)(unsafe.Pointer(in.TargetAverageValue))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_autoscaling_ExternalMetricSource_To_v2beta1_ExternalMetricSource is an autogenerated conversion function.
|
||||
func Convert_autoscaling_ExternalMetricSource_To_v2beta1_ExternalMetricSource(in *autoscaling.ExternalMetricSource, out *v2beta1.ExternalMetricSource, s conversion.Scope) error {
|
||||
return autoConvert_autoscaling_ExternalMetricSource_To_v2beta1_ExternalMetricSource(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v2beta1_ExternalMetricStatus_To_autoscaling_ExternalMetricStatus(in *v2beta1.ExternalMetricStatus, out *autoscaling.ExternalMetricStatus, s conversion.Scope) error {
|
||||
out.MetricName = in.MetricName
|
||||
out.MetricSelector = (*v1.LabelSelector)(unsafe.Pointer(in.MetricSelector))
|
||||
out.CurrentValue = in.CurrentValue
|
||||
out.CurrentAverageValue = (*resource.Quantity)(unsafe.Pointer(in.CurrentAverageValue))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v2beta1_ExternalMetricStatus_To_autoscaling_ExternalMetricStatus is an autogenerated conversion function.
|
||||
func Convert_v2beta1_ExternalMetricStatus_To_autoscaling_ExternalMetricStatus(in *v2beta1.ExternalMetricStatus, out *autoscaling.ExternalMetricStatus, s conversion.Scope) error {
|
||||
return autoConvert_v2beta1_ExternalMetricStatus_To_autoscaling_ExternalMetricStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_autoscaling_ExternalMetricStatus_To_v2beta1_ExternalMetricStatus(in *autoscaling.ExternalMetricStatus, out *v2beta1.ExternalMetricStatus, s conversion.Scope) error {
|
||||
out.MetricName = in.MetricName
|
||||
out.MetricSelector = (*v1.LabelSelector)(unsafe.Pointer(in.MetricSelector))
|
||||
out.CurrentValue = in.CurrentValue
|
||||
out.CurrentAverageValue = (*resource.Quantity)(unsafe.Pointer(in.CurrentAverageValue))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_autoscaling_ExternalMetricStatus_To_v2beta1_ExternalMetricStatus is an autogenerated conversion function.
|
||||
func Convert_autoscaling_ExternalMetricStatus_To_v2beta1_ExternalMetricStatus(in *autoscaling.ExternalMetricStatus, out *v2beta1.ExternalMetricStatus, s conversion.Scope) error {
|
||||
return autoConvert_autoscaling_ExternalMetricStatus_To_v2beta1_ExternalMetricStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v2beta1_HorizontalPodAutoscaler_To_autoscaling_HorizontalPodAutoscaler(in *v2beta1.HorizontalPodAutoscaler, out *autoscaling.HorizontalPodAutoscaler, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
if err := Convert_v2beta1_HorizontalPodAutoscalerSpec_To_autoscaling_HorizontalPodAutoscalerSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
@@ -144,7 +200,7 @@ func Convert_v2beta1_HorizontalPodAutoscalerCondition_To_autoscaling_HorizontalP
|
||||
|
||||
func autoConvert_autoscaling_HorizontalPodAutoscalerCondition_To_v2beta1_HorizontalPodAutoscalerCondition(in *autoscaling.HorizontalPodAutoscalerCondition, out *v2beta1.HorizontalPodAutoscalerCondition, s conversion.Scope) error {
|
||||
out.Type = v2beta1.HorizontalPodAutoscalerConditionType(in.Type)
|
||||
out.Status = v1.ConditionStatus(in.Status)
|
||||
out.Status = core_v1.ConditionStatus(in.Status)
|
||||
out.LastTransitionTime = in.LastTransitionTime
|
||||
out.Reason = in.Reason
|
||||
out.Message = in.Message
|
||||
@@ -210,7 +266,7 @@ func Convert_autoscaling_HorizontalPodAutoscalerSpec_To_v2beta1_HorizontalPodAut
|
||||
|
||||
func autoConvert_v2beta1_HorizontalPodAutoscalerStatus_To_autoscaling_HorizontalPodAutoscalerStatus(in *v2beta1.HorizontalPodAutoscalerStatus, out *autoscaling.HorizontalPodAutoscalerStatus, s conversion.Scope) error {
|
||||
out.ObservedGeneration = (*int64)(unsafe.Pointer(in.ObservedGeneration))
|
||||
out.LastScaleTime = (*meta_v1.Time)(unsafe.Pointer(in.LastScaleTime))
|
||||
out.LastScaleTime = (*v1.Time)(unsafe.Pointer(in.LastScaleTime))
|
||||
out.CurrentReplicas = in.CurrentReplicas
|
||||
out.DesiredReplicas = in.DesiredReplicas
|
||||
out.CurrentMetrics = *(*[]autoscaling.MetricStatus)(unsafe.Pointer(&in.CurrentMetrics))
|
||||
@@ -225,7 +281,7 @@ func Convert_v2beta1_HorizontalPodAutoscalerStatus_To_autoscaling_HorizontalPodA
|
||||
|
||||
func autoConvert_autoscaling_HorizontalPodAutoscalerStatus_To_v2beta1_HorizontalPodAutoscalerStatus(in *autoscaling.HorizontalPodAutoscalerStatus, out *v2beta1.HorizontalPodAutoscalerStatus, s conversion.Scope) error {
|
||||
out.ObservedGeneration = (*int64)(unsafe.Pointer(in.ObservedGeneration))
|
||||
out.LastScaleTime = (*meta_v1.Time)(unsafe.Pointer(in.LastScaleTime))
|
||||
out.LastScaleTime = (*v1.Time)(unsafe.Pointer(in.LastScaleTime))
|
||||
out.CurrentReplicas = in.CurrentReplicas
|
||||
out.DesiredReplicas = in.DesiredReplicas
|
||||
out.CurrentMetrics = *(*[]v2beta1.MetricStatus)(unsafe.Pointer(&in.CurrentMetrics))
|
||||
@@ -243,6 +299,7 @@ func autoConvert_v2beta1_MetricSpec_To_autoscaling_MetricSpec(in *v2beta1.Metric
|
||||
out.Object = (*autoscaling.ObjectMetricSource)(unsafe.Pointer(in.Object))
|
||||
out.Pods = (*autoscaling.PodsMetricSource)(unsafe.Pointer(in.Pods))
|
||||
out.Resource = (*autoscaling.ResourceMetricSource)(unsafe.Pointer(in.Resource))
|
||||
out.External = (*autoscaling.ExternalMetricSource)(unsafe.Pointer(in.External))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -256,6 +313,7 @@ func autoConvert_autoscaling_MetricSpec_To_v2beta1_MetricSpec(in *autoscaling.Me
|
||||
out.Object = (*v2beta1.ObjectMetricSource)(unsafe.Pointer(in.Object))
|
||||
out.Pods = (*v2beta1.PodsMetricSource)(unsafe.Pointer(in.Pods))
|
||||
out.Resource = (*v2beta1.ResourceMetricSource)(unsafe.Pointer(in.Resource))
|
||||
out.External = (*v2beta1.ExternalMetricSource)(unsafe.Pointer(in.External))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -269,6 +327,7 @@ func autoConvert_v2beta1_MetricStatus_To_autoscaling_MetricStatus(in *v2beta1.Me
|
||||
out.Object = (*autoscaling.ObjectMetricStatus)(unsafe.Pointer(in.Object))
|
||||
out.Pods = (*autoscaling.PodsMetricStatus)(unsafe.Pointer(in.Pods))
|
||||
out.Resource = (*autoscaling.ResourceMetricStatus)(unsafe.Pointer(in.Resource))
|
||||
out.External = (*autoscaling.ExternalMetricStatus)(unsafe.Pointer(in.External))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -282,6 +341,7 @@ func autoConvert_autoscaling_MetricStatus_To_v2beta1_MetricStatus(in *autoscalin
|
||||
out.Object = (*v2beta1.ObjectMetricStatus)(unsafe.Pointer(in.Object))
|
||||
out.Pods = (*v2beta1.PodsMetricStatus)(unsafe.Pointer(in.Pods))
|
||||
out.Resource = (*v2beta1.ResourceMetricStatus)(unsafe.Pointer(in.Resource))
|
||||
out.External = (*v2beta1.ExternalMetricStatus)(unsafe.Pointer(in.External))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -403,7 +463,7 @@ func Convert_v2beta1_ResourceMetricSource_To_autoscaling_ResourceMetricSource(in
|
||||
}
|
||||
|
||||
func autoConvert_autoscaling_ResourceMetricSource_To_v2beta1_ResourceMetricSource(in *autoscaling.ResourceMetricSource, out *v2beta1.ResourceMetricSource, s conversion.Scope) error {
|
||||
out.Name = v1.ResourceName(in.Name)
|
||||
out.Name = core_v1.ResourceName(in.Name)
|
||||
out.TargetAverageUtilization = (*int32)(unsafe.Pointer(in.TargetAverageUtilization))
|
||||
out.TargetAverageValue = (*resource.Quantity)(unsafe.Pointer(in.TargetAverageValue))
|
||||
return nil
|
||||
@@ -427,7 +487,7 @@ func Convert_v2beta1_ResourceMetricStatus_To_autoscaling_ResourceMetricStatus(in
|
||||
}
|
||||
|
||||
func autoConvert_autoscaling_ResourceMetricStatus_To_v2beta1_ResourceMetricStatus(in *autoscaling.ResourceMetricStatus, out *v2beta1.ResourceMetricStatus, s conversion.Scope) error {
|
||||
out.Name = v1.ResourceName(in.Name)
|
||||
out.Name = core_v1.ResourceName(in.Name)
|
||||
out.CurrentAverageUtilization = (*int32)(unsafe.Pointer(in.CurrentAverageUtilization))
|
||||
out.CurrentAverageValue = in.CurrentAverageValue
|
||||
return nil
|
||||
|
@@ -115,7 +115,7 @@ func validateMetrics(metrics []autoscaling.MetricSpec, fldPath *field.Path) fiel
|
||||
return allErrs
|
||||
}
|
||||
|
||||
var validMetricSourceTypes = sets.NewString(string(autoscaling.ObjectMetricSourceType), string(autoscaling.PodsMetricSourceType), string(autoscaling.ResourceMetricSourceType))
|
||||
var validMetricSourceTypes = sets.NewString(string(autoscaling.ObjectMetricSourceType), string(autoscaling.PodsMetricSourceType), string(autoscaling.ResourceMetricSourceType), string(autoscaling.ExternalMetricSourceType))
|
||||
var validMetricSourceTypesList = validMetricSourceTypes.List()
|
||||
|
||||
func validateMetricSpec(spec autoscaling.MetricSpec, fldPath *field.Path) field.ErrorList {
|
||||
@@ -137,6 +137,13 @@ func validateMetricSpec(spec autoscaling.MetricSpec, fldPath *field.Path) field.
|
||||
}
|
||||
}
|
||||
|
||||
if spec.External != nil {
|
||||
typesPresent.Insert("external")
|
||||
if typesPresent.Len() == 1 {
|
||||
allErrs = append(allErrs, validateExternalSource(spec.External, fldPath.Child("external"))...)
|
||||
}
|
||||
}
|
||||
|
||||
if spec.Pods != nil {
|
||||
typesPresent.Insert("pods")
|
||||
if typesPresent.Len() == 1 {
|
||||
@@ -183,6 +190,32 @@ func validateObjectSource(src *autoscaling.ObjectMetricSource, fldPath *field.Pa
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateExternalSource(src *autoscaling.ExternalMetricSource, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if len(src.MetricName) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("metricName"), "must specify a metric name"))
|
||||
}
|
||||
|
||||
if src.TargetValue == nil && src.TargetAverageValue == nil {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("targetValue"), "must set either a target value for metric or a per-pod target"))
|
||||
}
|
||||
|
||||
if src.TargetValue != nil && src.TargetAverageValue != nil {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("targetValue"), "may not set both a target value for metric and a per-pod target"))
|
||||
}
|
||||
|
||||
if src.TargetAverageValue != nil && src.TargetAverageValue.Sign() != 1 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("targetAverageValue"), src.TargetAverageValue, "must be positive"))
|
||||
}
|
||||
|
||||
if src.TargetValue != nil && src.TargetValue.Sign() != 1 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("targetValue"), src.TargetValue, "must be positive"))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validatePodsSource(src *autoscaling.PodsMetricSource, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
|
@@ -202,6 +202,62 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ExternalMetricSourceType,
|
||||
External: &autoscaling.ExternalMetricSource{
|
||||
MetricName: "some/metric",
|
||||
MetricSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"label": "value",
|
||||
},
|
||||
},
|
||||
TargetValue: resource.NewMilliQuantity(300, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ExternalMetricSourceType,
|
||||
External: &autoscaling.ExternalMetricSource{
|
||||
MetricName: "some/metric",
|
||||
MetricSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"label": "value",
|
||||
},
|
||||
},
|
||||
TargetAverageValue: resource.NewMilliQuantity(300, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, successCase := range successCases {
|
||||
if errs := ValidateHorizontalPodAutoscaler(&successCase); len(errs) != 0 {
|
||||
@@ -487,6 +543,130 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
|
||||
},
|
||||
msg: "must specify a metric name",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ExternalMetricSourceType,
|
||||
External: &autoscaling.ExternalMetricSource{
|
||||
MetricSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"label": "value",
|
||||
},
|
||||
},
|
||||
TargetValue: resource.NewMilliQuantity(300, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
msg: "must specify a metric name",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ExternalMetricSourceType,
|
||||
External: &autoscaling.ExternalMetricSource{
|
||||
MetricName: "some/metric",
|
||||
MetricSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"label": "value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
msg: "must set either a target value for metric or a per-pod target",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ExternalMetricSourceType,
|
||||
External: &autoscaling.ExternalMetricSource{
|
||||
MetricName: "some/metric",
|
||||
MetricSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"label": "value",
|
||||
},
|
||||
},
|
||||
TargetValue: resource.NewMilliQuantity(-300, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
msg: "must be positive",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ExternalMetricSourceType,
|
||||
External: &autoscaling.ExternalMetricSource{
|
||||
MetricName: "some/metric",
|
||||
MetricSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"label": "value",
|
||||
},
|
||||
},
|
||||
TargetAverageValue: resource.NewMilliQuantity(-300, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
msg: "must be positive",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ExternalMetricSourceType,
|
||||
External: &autoscaling.ExternalMetricSource{
|
||||
MetricName: "some/metric",
|
||||
MetricSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"label": "value",
|
||||
},
|
||||
},
|
||||
TargetValue: resource.NewMilliQuantity(300, resource.DecimalSI),
|
||||
TargetAverageValue: resource.NewMilliQuantity(300, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
msg: "may not set both a target value for metric and a per-pod target",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
|
||||
|
96
pkg/apis/autoscaling/zz_generated.deepcopy.go
generated
96
pkg/apis/autoscaling/zz_generated.deepcopy.go
generated
@@ -42,6 +42,84 @@ func (in *CrossVersionObjectReference) DeepCopy() *CrossVersionObjectReference {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ExternalMetricSource) DeepCopyInto(out *ExternalMetricSource) {
|
||||
*out = *in
|
||||
if in.MetricSelector != nil {
|
||||
in, out := &in.MetricSelector, &out.MetricSelector
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(v1.LabelSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
if in.TargetValue != nil {
|
||||
in, out := &in.TargetValue, &out.TargetValue
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(resource.Quantity)
|
||||
**out = (*in).DeepCopy()
|
||||
}
|
||||
}
|
||||
if in.TargetAverageValue != nil {
|
||||
in, out := &in.TargetAverageValue, &out.TargetAverageValue
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(resource.Quantity)
|
||||
**out = (*in).DeepCopy()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalMetricSource.
|
||||
func (in *ExternalMetricSource) DeepCopy() *ExternalMetricSource {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExternalMetricSource)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ExternalMetricStatus) DeepCopyInto(out *ExternalMetricStatus) {
|
||||
*out = *in
|
||||
if in.MetricSelector != nil {
|
||||
in, out := &in.MetricSelector, &out.MetricSelector
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(v1.LabelSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
out.CurrentValue = in.CurrentValue.DeepCopy()
|
||||
if in.CurrentAverageValue != nil {
|
||||
in, out := &in.CurrentAverageValue, &out.CurrentAverageValue
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(resource.Quantity)
|
||||
**out = (*in).DeepCopy()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalMetricStatus.
|
||||
func (in *ExternalMetricStatus) DeepCopy() *ExternalMetricStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExternalMetricStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HorizontalPodAutoscaler) DeepCopyInto(out *HorizontalPodAutoscaler) {
|
||||
*out = *in
|
||||
@@ -233,6 +311,15 @@ func (in *MetricSpec) DeepCopyInto(out *MetricSpec) {
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(ExternalMetricSource)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -276,6 +363,15 @@ func (in *MetricStatus) DeepCopyInto(out *MetricStatus) {
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
if in.External != nil {
|
||||
in, out := &in.External, &out.External
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(ExternalMetricStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user