Added functionality and API for pod autoscaling based on container resources

Signed-off-by: Arjun Naik <anaik@redhat.com>
This commit is contained in:
Arjun Naik
2020-10-21 11:29:17 +02:00
parent 7509c4eb47
commit 0fec7b0f7e
54 changed files with 5526 additions and 806 deletions

View File

@@ -204,6 +204,12 @@ const (
// (for example length of queue in cloud messaging service, or
// QPS from loadbalancer running outside of cluster).
ExternalMetricSourceType MetricSourceType = "External"
// ContainerResourceMetricSourceType is a resource metric known to Kubernetes, as
// specified in requests and limits, describing a single container in each pod in the current
// scale target (e.g. CPU or memory). Such metrics are built in to
// Kubernetes, and have special scaling options on top of those available
// to normal per-pod metrics (the "pods" source).
ContainerResourceMetricSourceType MetricSourceType = "ContainerResource"
)
// MetricSpec specifies how to scale based on a single metric
@@ -229,6 +235,13 @@ type MetricSpec struct {
// to normal per-pod metrics using the "pods" source.
// +optional
Resource *ResourceMetricSource
// ContainerResource refers to a resource metric (such as those specified in
// requests and limits) known to Kubernetes describing a single container in each pod of the
// current scale target (e.g. CPU or memory). Such metrics are built in to
// Kubernetes, and have special scaling options on top of those available
// to normal per-pod metrics using the "pods" source.
// +optional
ContainerResource *ContainerResourceMetricSource
// 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
@@ -271,6 +284,22 @@ type ResourceMetricSource struct {
Target MetricTarget
}
// ContainerResourceMetricSource indicates how to scale on a resource metric known to
// Kubernetes, as specified in the requests and limits, describing a single container in
// each of the pods of the current scale target(e.g. CPU or memory). The values will be
// averaged together before being compared to the target. Such metrics are built into
// Kubernetes, and have special scaling options on top of those available to
// normal per-pod metrics using the "pods" source. Only one "target" type
// should be set.
type ContainerResourceMetricSource struct {
// name is the name of the of the resource
Name api.ResourceName
// container is the name of the container in the pods of the scaling target.
Container string
// target specifies the target value for the given metric
Target MetricTarget
}
// 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).
@@ -420,6 +449,13 @@ type MetricStatus struct {
// to normal per-pod metrics using the "pods" source.
// +optional
Resource *ResourceMetricStatus
// ContainerResource refers to a resource metric (such as those specified in
// requests and limits) known to Kubernetes describing a single container in each pod in the
// current scale target (e.g. CPU or memory). Such metrics are built in to
// Kubernetes, and have special scaling options on top of those available
// to normal per-pod metrics using the "pods" source.
// +optional
ContainerResource *ContainerResourceMetricStatus
// 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
@@ -456,6 +492,18 @@ type ResourceMetricStatus struct {
Current MetricValueStatus
}
// ContainerResourceMetricStatus indicates the current value of a resource metric known to
// Kubernetes, as specified in requests and limits, describing each pod in the
// current scale target (e.g. CPU or memory). Such metrics are built in to
// Kubernetes, and have special scaling options on top of those available to
// normal per-pod metrics using the "pods" source.
type ContainerResourceMetricStatus struct {
// Name is the name of the resource in question.
Name api.ResourceName
Container string
Current MetricValueStatus
}
// ExternalMetricStatus indicates the current value of a global metric
// not associated with any Kubernetes object.
type ExternalMetricStatus struct {

View File

@@ -235,6 +235,28 @@ func Convert_autoscaling_ResourceMetricSource_To_v1_ResourceMetricSource(in *aut
return nil
}
func Convert_v1_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(in *autoscalingv1.ContainerResourceMetricStatus, out *autoscaling.ContainerResourceMetricStatus, s conversion.Scope) error {
out.Name = core.ResourceName(in.Name)
out.Container = in.Container
utilization := in.CurrentAverageUtilization
averageValue := &in.CurrentAverageValue
out.Current = autoscaling.MetricValueStatus{
AverageValue: averageValue,
AverageUtilization: utilization,
}
return nil
}
func Convert_autoscaling_ContainerResourceMetricStatus_To_v1_ContainerResourceMetricStatus(in *autoscaling.ContainerResourceMetricStatus, out *autoscalingv1.ContainerResourceMetricStatus, s conversion.Scope) error {
out.Name = v1.ResourceName(in.Name)
out.Container = in.Container
out.CurrentAverageUtilization = in.Current.AverageUtilization
if in.Current.AverageValue != nil {
out.CurrentAverageValue = *in.Current.AverageValue
}
return nil
}
func Convert_v1_ResourceMetricStatus_To_autoscaling_ResourceMetricStatus(in *autoscalingv1.ResourceMetricStatus, out *autoscaling.ResourceMetricStatus, s conversion.Scope) error {
out.Name = core.ResourceName(in.Name)
utilization := in.CurrentAverageUtilization
@@ -517,3 +539,30 @@ func Convert_v1_HorizontalPodAutoscalerStatus_To_autoscaling_HorizontalPodAutosc
}
return nil
}
func Convert_v1_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(in *autoscalingv1.ContainerResourceMetricSource, out *autoscaling.ContainerResourceMetricSource, s conversion.Scope) error {
out.Name = core.ResourceName(in.Name)
out.Container = in.Container
utilization := in.TargetAverageUtilization
averageValue := in.TargetAverageValue
var metricType autoscaling.MetricTargetType
if utilization == nil {
metricType = autoscaling.AverageValueMetricType
} else {
metricType = autoscaling.UtilizationMetricType
}
out.Target = autoscaling.MetricTarget{
Type: metricType,
AverageValue: averageValue,
AverageUtilization: utilization,
}
return nil
}
func Convert_autoscaling_ContainerResourceMetricSource_To_v1_ContainerResourceMetricSource(in *autoscaling.ContainerResourceMetricSource, out *autoscalingv1.ContainerResourceMetricSource, s conversion.Scope) error {
out.Name = v1.ResourceName(in.Name)
out.Container = in.Container
out.TargetAverageUtilization = in.Target.AverageUtilization
out.TargetAverageValue = in.Target.AverageValue
return nil
}

View File

@@ -119,6 +119,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddConversionFunc((*autoscaling.ContainerResourceMetricSource)(nil), (*v1.ContainerResourceMetricSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_autoscaling_ContainerResourceMetricSource_To_v1_ContainerResourceMetricSource(a.(*autoscaling.ContainerResourceMetricSource), b.(*v1.ContainerResourceMetricSource), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*autoscaling.ContainerResourceMetricStatus)(nil), (*v1.ContainerResourceMetricStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_autoscaling_ContainerResourceMetricStatus_To_v1_ContainerResourceMetricStatus(a.(*autoscaling.ContainerResourceMetricStatus), b.(*v1.ContainerResourceMetricStatus), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*autoscaling.ExternalMetricSource)(nil), (*v1.ExternalMetricSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_autoscaling_ExternalMetricSource_To_v1_ExternalMetricSource(a.(*autoscaling.ExternalMetricSource), b.(*v1.ExternalMetricSource), scope)
}); err != nil {
@@ -179,6 +189,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddConversionFunc((*v1.ContainerResourceMetricSource)(nil), (*autoscaling.ContainerResourceMetricSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(a.(*v1.ContainerResourceMetricSource), b.(*autoscaling.ContainerResourceMetricSource), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*v1.ContainerResourceMetricStatus)(nil), (*autoscaling.ContainerResourceMetricStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(a.(*v1.ContainerResourceMetricStatus), b.(*autoscaling.ContainerResourceMetricStatus), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*v1.CrossVersionObjectReference)(nil), (*autoscaling.MetricTarget)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_CrossVersionObjectReference_To_autoscaling_MetricTarget(a.(*v1.CrossVersionObjectReference), b.(*autoscaling.MetricTarget), scope)
}); err != nil {
@@ -242,6 +262,36 @@ func RegisterConversions(s *runtime.Scheme) error {
return nil
}
func autoConvert_v1_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(in *v1.ContainerResourceMetricSource, out *autoscaling.ContainerResourceMetricSource, s conversion.Scope) error {
out.Name = core.ResourceName(in.Name)
// WARNING: in.TargetAverageUtilization requires manual conversion: does not exist in peer-type
// WARNING: in.TargetAverageValue requires manual conversion: does not exist in peer-type
out.Container = in.Container
return nil
}
func autoConvert_autoscaling_ContainerResourceMetricSource_To_v1_ContainerResourceMetricSource(in *autoscaling.ContainerResourceMetricSource, out *v1.ContainerResourceMetricSource, s conversion.Scope) error {
out.Name = corev1.ResourceName(in.Name)
out.Container = in.Container
// WARNING: in.Target requires manual conversion: does not exist in peer-type
return nil
}
func autoConvert_v1_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(in *v1.ContainerResourceMetricStatus, out *autoscaling.ContainerResourceMetricStatus, s conversion.Scope) error {
out.Name = core.ResourceName(in.Name)
// WARNING: in.CurrentAverageUtilization requires manual conversion: does not exist in peer-type
// WARNING: in.CurrentAverageValue requires manual conversion: does not exist in peer-type
out.Container = in.Container
return nil
}
func autoConvert_autoscaling_ContainerResourceMetricStatus_To_v1_ContainerResourceMetricStatus(in *autoscaling.ContainerResourceMetricStatus, out *v1.ContainerResourceMetricStatus, s conversion.Scope) error {
out.Name = corev1.ResourceName(in.Name)
out.Container = in.Container
// WARNING: in.Current requires manual conversion: does not exist in peer-type
return nil
}
func autoConvert_v1_CrossVersionObjectReference_To_autoscaling_CrossVersionObjectReference(in *v1.CrossVersionObjectReference, out *autoscaling.CrossVersionObjectReference, s conversion.Scope) error {
out.Kind = in.Kind
out.Name = in.Name
@@ -455,6 +505,15 @@ func autoConvert_v1_MetricSpec_To_autoscaling_MetricSpec(in *v1.MetricSpec, out
} else {
out.Resource = nil
}
if in.ContainerResource != nil {
in, out := &in.ContainerResource, &out.ContainerResource
*out = new(autoscaling.ContainerResourceMetricSource)
if err := Convert_v1_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(*in, *out, s); err != nil {
return err
}
} else {
out.ContainerResource = nil
}
if in.External != nil {
in, out := &in.External, &out.External
*out = new(autoscaling.ExternalMetricSource)
@@ -501,6 +560,15 @@ func autoConvert_autoscaling_MetricSpec_To_v1_MetricSpec(in *autoscaling.MetricS
} else {
out.Resource = nil
}
if in.ContainerResource != nil {
in, out := &in.ContainerResource, &out.ContainerResource
*out = new(v1.ContainerResourceMetricSource)
if err := Convert_autoscaling_ContainerResourceMetricSource_To_v1_ContainerResourceMetricSource(*in, *out, s); err != nil {
return err
}
} else {
out.ContainerResource = nil
}
if in.External != nil {
in, out := &in.External, &out.External
*out = new(v1.ExternalMetricSource)
@@ -547,6 +615,15 @@ func autoConvert_v1_MetricStatus_To_autoscaling_MetricStatus(in *v1.MetricStatus
} else {
out.Resource = nil
}
if in.ContainerResource != nil {
in, out := &in.ContainerResource, &out.ContainerResource
*out = new(autoscaling.ContainerResourceMetricStatus)
if err := Convert_v1_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(*in, *out, s); err != nil {
return err
}
} else {
out.ContainerResource = nil
}
if in.External != nil {
in, out := &in.External, &out.External
*out = new(autoscaling.ExternalMetricStatus)
@@ -593,6 +670,15 @@ func autoConvert_autoscaling_MetricStatus_To_v1_MetricStatus(in *autoscaling.Met
} else {
out.Resource = nil
}
if in.ContainerResource != nil {
in, out := &in.ContainerResource, &out.ContainerResource
*out = new(v1.ContainerResourceMetricStatus)
if err := Convert_autoscaling_ContainerResourceMetricStatus_To_v1_ContainerResourceMetricStatus(*in, *out, s); err != nil {
return err
}
} else {
out.ContainerResource = nil
}
if in.External != nil {
in, out := &in.External, &out.External
*out = new(v1.ExternalMetricStatus)

View File

@@ -35,6 +35,28 @@ func Convert_v2beta1_CrossVersionObjectReference_To_autoscaling_MetricTarget(in
return nil
}
func Convert_v2beta1_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(in *autoscalingv2beta1.ContainerResourceMetricStatus, out *autoscaling.ContainerResourceMetricStatus, s conversion.Scope) error {
out.Name = core.ResourceName(in.Name)
out.Container = in.Container
utilization := in.CurrentAverageUtilization
averageValue := in.CurrentAverageValue
out.Current = autoscaling.MetricValueStatus{
AverageValue: &averageValue,
AverageUtilization: utilization,
}
return nil
}
func Convert_autoscaling_ContainerResourceMetricStatus_To_v2beta1_ContainerResourceMetricStatus(in *autoscaling.ContainerResourceMetricStatus, out *autoscalingv2beta1.ContainerResourceMetricStatus, s conversion.Scope) error {
out.Name = v1.ResourceName(in.Name)
out.Container = in.Container
out.CurrentAverageUtilization = in.Current.AverageUtilization
if in.Current.AverageValue != nil {
out.CurrentAverageValue = *in.Current.AverageValue
}
return nil
}
func Convert_v2beta1_ResourceMetricStatus_To_autoscaling_ResourceMetricStatus(in *autoscalingv2beta1.ResourceMetricStatus, out *autoscaling.ResourceMetricStatus, s conversion.Scope) error {
out.Name = core.ResourceName(in.Name)
utilization := in.CurrentAverageUtilization
@@ -309,3 +331,29 @@ func Convert_v2beta1_HorizontalPodAutoscaler_To_autoscaling_HorizontalPodAutosca
func Convert_autoscaling_HorizontalPodAutoscalerSpec_To_v2beta1_HorizontalPodAutoscalerSpec(in *autoscaling.HorizontalPodAutoscalerSpec, out *autoscalingv2beta1.HorizontalPodAutoscalerSpec, s conversion.Scope) error {
return autoConvert_autoscaling_HorizontalPodAutoscalerSpec_To_v2beta1_HorizontalPodAutoscalerSpec(in, out, s)
}
func Convert_v2beta1_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(in *autoscalingv2beta1.ContainerResourceMetricSource, out *autoscaling.ContainerResourceMetricSource, s conversion.Scope) error {
out.Name = core.ResourceName(in.Name)
utilization := in.TargetAverageUtilization
averageValue := in.TargetAverageValue
var metricType autoscaling.MetricTargetType
if utilization == nil {
metricType = autoscaling.AverageValueMetricType
} else {
metricType = autoscaling.UtilizationMetricType
}
out.Target = autoscaling.MetricTarget{
Type: metricType,
AverageValue: averageValue,
AverageUtilization: utilization,
}
return nil
}
func Convert_autoscaling_ContainerResourceMetricSource_To_v2beta1_ContainerResourceMetricSource(in *autoscaling.ContainerResourceMetricSource, out *autoscalingv2beta1.ContainerResourceMetricSource, s conversion.Scope) error {
out.Name = v1.ResourceName(in.Name)
out.TargetAverageUtilization = in.Target.AverageUtilization
out.TargetAverageValue = in.Target.AverageValue
return nil
}

View File

@@ -104,6 +104,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddConversionFunc((*autoscaling.ContainerResourceMetricSource)(nil), (*v2beta1.ContainerResourceMetricSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_autoscaling_ContainerResourceMetricSource_To_v2beta1_ContainerResourceMetricSource(a.(*autoscaling.ContainerResourceMetricSource), b.(*v2beta1.ContainerResourceMetricSource), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*autoscaling.ContainerResourceMetricStatus)(nil), (*v2beta1.ContainerResourceMetricStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_autoscaling_ContainerResourceMetricStatus_To_v2beta1_ContainerResourceMetricStatus(a.(*autoscaling.ContainerResourceMetricStatus), b.(*v2beta1.ContainerResourceMetricStatus), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*autoscaling.ExternalMetricSource)(nil), (*v2beta1.ExternalMetricSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_autoscaling_ExternalMetricSource_To_v2beta1_ExternalMetricSource(a.(*autoscaling.ExternalMetricSource), b.(*v2beta1.ExternalMetricSource), scope)
}); err != nil {
@@ -159,6 +169,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddConversionFunc((*v2beta1.ContainerResourceMetricSource)(nil), (*autoscaling.ContainerResourceMetricSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v2beta1_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(a.(*v2beta1.ContainerResourceMetricSource), b.(*autoscaling.ContainerResourceMetricSource), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*v2beta1.ContainerResourceMetricStatus)(nil), (*autoscaling.ContainerResourceMetricStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v2beta1_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(a.(*v2beta1.ContainerResourceMetricStatus), b.(*autoscaling.ContainerResourceMetricStatus), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*v2beta1.CrossVersionObjectReference)(nil), (*autoscaling.MetricTarget)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v2beta1_CrossVersionObjectReference_To_autoscaling_MetricTarget(a.(*v2beta1.CrossVersionObjectReference), b.(*autoscaling.MetricTarget), scope)
}); err != nil {
@@ -212,6 +232,36 @@ func RegisterConversions(s *runtime.Scheme) error {
return nil
}
func autoConvert_v2beta1_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(in *v2beta1.ContainerResourceMetricSource, out *autoscaling.ContainerResourceMetricSource, s conversion.Scope) error {
out.Name = core.ResourceName(in.Name)
// WARNING: in.TargetAverageUtilization requires manual conversion: does not exist in peer-type
// WARNING: in.TargetAverageValue requires manual conversion: does not exist in peer-type
out.Container = in.Container
return nil
}
func autoConvert_autoscaling_ContainerResourceMetricSource_To_v2beta1_ContainerResourceMetricSource(in *autoscaling.ContainerResourceMetricSource, out *v2beta1.ContainerResourceMetricSource, s conversion.Scope) error {
out.Name = v1.ResourceName(in.Name)
out.Container = in.Container
// WARNING: in.Target requires manual conversion: does not exist in peer-type
return nil
}
func autoConvert_v2beta1_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(in *v2beta1.ContainerResourceMetricStatus, out *autoscaling.ContainerResourceMetricStatus, s conversion.Scope) error {
out.Name = core.ResourceName(in.Name)
// WARNING: in.CurrentAverageUtilization requires manual conversion: does not exist in peer-type
// WARNING: in.CurrentAverageValue requires manual conversion: does not exist in peer-type
out.Container = in.Container
return nil
}
func autoConvert_autoscaling_ContainerResourceMetricStatus_To_v2beta1_ContainerResourceMetricStatus(in *autoscaling.ContainerResourceMetricStatus, out *v2beta1.ContainerResourceMetricStatus, s conversion.Scope) error {
out.Name = v1.ResourceName(in.Name)
out.Container = in.Container
// WARNING: in.Current requires manual conversion: does not exist in peer-type
return nil
}
func autoConvert_v2beta1_CrossVersionObjectReference_To_autoscaling_CrossVersionObjectReference(in *v2beta1.CrossVersionObjectReference, out *autoscaling.CrossVersionObjectReference, s conversion.Scope) error {
out.Kind = in.Kind
out.Name = in.Name
@@ -481,6 +531,15 @@ func autoConvert_v2beta1_MetricSpec_To_autoscaling_MetricSpec(in *v2beta1.Metric
} else {
out.Resource = nil
}
if in.ContainerResource != nil {
in, out := &in.ContainerResource, &out.ContainerResource
*out = new(autoscaling.ContainerResourceMetricSource)
if err := Convert_v2beta1_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(*in, *out, s); err != nil {
return err
}
} else {
out.ContainerResource = nil
}
if in.External != nil {
in, out := &in.External, &out.External
*out = new(autoscaling.ExternalMetricSource)
@@ -527,6 +586,15 @@ func autoConvert_autoscaling_MetricSpec_To_v2beta1_MetricSpec(in *autoscaling.Me
} else {
out.Resource = nil
}
if in.ContainerResource != nil {
in, out := &in.ContainerResource, &out.ContainerResource
*out = new(v2beta1.ContainerResourceMetricSource)
if err := Convert_autoscaling_ContainerResourceMetricSource_To_v2beta1_ContainerResourceMetricSource(*in, *out, s); err != nil {
return err
}
} else {
out.ContainerResource = nil
}
if in.External != nil {
in, out := &in.External, &out.External
*out = new(v2beta1.ExternalMetricSource)
@@ -573,6 +641,15 @@ func autoConvert_v2beta1_MetricStatus_To_autoscaling_MetricStatus(in *v2beta1.Me
} else {
out.Resource = nil
}
if in.ContainerResource != nil {
in, out := &in.ContainerResource, &out.ContainerResource
*out = new(autoscaling.ContainerResourceMetricStatus)
if err := Convert_v2beta1_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(*in, *out, s); err != nil {
return err
}
} else {
out.ContainerResource = nil
}
if in.External != nil {
in, out := &in.External, &out.External
*out = new(autoscaling.ExternalMetricStatus)
@@ -619,6 +696,15 @@ func autoConvert_autoscaling_MetricStatus_To_v2beta1_MetricStatus(in *autoscalin
} else {
out.Resource = nil
}
if in.ContainerResource != nil {
in, out := &in.ContainerResource, &out.ContainerResource
*out = new(v2beta1.ContainerResourceMetricStatus)
if err := Convert_autoscaling_ContainerResourceMetricStatus_To_v2beta1_ContainerResourceMetricStatus(*in, *out, s); err != nil {
return err
}
} else {
out.ContainerResource = nil
}
if in.External != nil {
in, out := &in.External, &out.External
*out = new(v2beta1.ExternalMetricStatus)

View File

@@ -40,6 +40,26 @@ 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((*v2beta2.ContainerResourceMetricSource)(nil), (*autoscaling.ContainerResourceMetricSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v2beta2_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(a.(*v2beta2.ContainerResourceMetricSource), b.(*autoscaling.ContainerResourceMetricSource), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*autoscaling.ContainerResourceMetricSource)(nil), (*v2beta2.ContainerResourceMetricSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_autoscaling_ContainerResourceMetricSource_To_v2beta2_ContainerResourceMetricSource(a.(*autoscaling.ContainerResourceMetricSource), b.(*v2beta2.ContainerResourceMetricSource), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v2beta2.ContainerResourceMetricStatus)(nil), (*autoscaling.ContainerResourceMetricStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v2beta2_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(a.(*v2beta2.ContainerResourceMetricStatus), b.(*autoscaling.ContainerResourceMetricStatus), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*autoscaling.ContainerResourceMetricStatus)(nil), (*v2beta2.ContainerResourceMetricStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_autoscaling_ContainerResourceMetricStatus_To_v2beta2_ContainerResourceMetricStatus(a.(*autoscaling.ContainerResourceMetricStatus), b.(*v2beta2.ContainerResourceMetricStatus), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v2beta2.CrossVersionObjectReference)(nil), (*autoscaling.CrossVersionObjectReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v2beta2_CrossVersionObjectReference_To_autoscaling_CrossVersionObjectReference(a.(*v2beta2.CrossVersionObjectReference), b.(*autoscaling.CrossVersionObjectReference), scope)
}); err != nil {
@@ -263,6 +283,62 @@ func RegisterConversions(s *runtime.Scheme) error {
return nil
}
func autoConvert_v2beta2_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(in *v2beta2.ContainerResourceMetricSource, out *autoscaling.ContainerResourceMetricSource, s conversion.Scope) error {
out.Name = core.ResourceName(in.Name)
if err := Convert_v2beta2_MetricTarget_To_autoscaling_MetricTarget(&in.Target, &out.Target, s); err != nil {
return err
}
out.Container = in.Container
return nil
}
// Convert_v2beta2_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource is an autogenerated conversion function.
func Convert_v2beta2_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(in *v2beta2.ContainerResourceMetricSource, out *autoscaling.ContainerResourceMetricSource, s conversion.Scope) error {
return autoConvert_v2beta2_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(in, out, s)
}
func autoConvert_autoscaling_ContainerResourceMetricSource_To_v2beta2_ContainerResourceMetricSource(in *autoscaling.ContainerResourceMetricSource, out *v2beta2.ContainerResourceMetricSource, s conversion.Scope) error {
out.Name = v1.ResourceName(in.Name)
out.Container = in.Container
if err := Convert_autoscaling_MetricTarget_To_v2beta2_MetricTarget(&in.Target, &out.Target, s); err != nil {
return err
}
return nil
}
// Convert_autoscaling_ContainerResourceMetricSource_To_v2beta2_ContainerResourceMetricSource is an autogenerated conversion function.
func Convert_autoscaling_ContainerResourceMetricSource_To_v2beta2_ContainerResourceMetricSource(in *autoscaling.ContainerResourceMetricSource, out *v2beta2.ContainerResourceMetricSource, s conversion.Scope) error {
return autoConvert_autoscaling_ContainerResourceMetricSource_To_v2beta2_ContainerResourceMetricSource(in, out, s)
}
func autoConvert_v2beta2_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(in *v2beta2.ContainerResourceMetricStatus, out *autoscaling.ContainerResourceMetricStatus, s conversion.Scope) error {
out.Name = core.ResourceName(in.Name)
if err := Convert_v2beta2_MetricValueStatus_To_autoscaling_MetricValueStatus(&in.Current, &out.Current, s); err != nil {
return err
}
out.Container = in.Container
return nil
}
// Convert_v2beta2_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus is an autogenerated conversion function.
func Convert_v2beta2_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(in *v2beta2.ContainerResourceMetricStatus, out *autoscaling.ContainerResourceMetricStatus, s conversion.Scope) error {
return autoConvert_v2beta2_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(in, out, s)
}
func autoConvert_autoscaling_ContainerResourceMetricStatus_To_v2beta2_ContainerResourceMetricStatus(in *autoscaling.ContainerResourceMetricStatus, out *v2beta2.ContainerResourceMetricStatus, s conversion.Scope) error {
out.Name = v1.ResourceName(in.Name)
out.Container = in.Container
if err := Convert_autoscaling_MetricValueStatus_To_v2beta2_MetricValueStatus(&in.Current, &out.Current, s); err != nil {
return err
}
return nil
}
// Convert_autoscaling_ContainerResourceMetricStatus_To_v2beta2_ContainerResourceMetricStatus is an autogenerated conversion function.
func Convert_autoscaling_ContainerResourceMetricStatus_To_v2beta2_ContainerResourceMetricStatus(in *autoscaling.ContainerResourceMetricStatus, out *v2beta2.ContainerResourceMetricStatus, s conversion.Scope) error {
return autoConvert_autoscaling_ContainerResourceMetricStatus_To_v2beta2_ContainerResourceMetricStatus(in, out, s)
}
func autoConvert_v2beta2_CrossVersionObjectReference_To_autoscaling_CrossVersionObjectReference(in *v2beta2.CrossVersionObjectReference, out *autoscaling.CrossVersionObjectReference, s conversion.Scope) error {
out.Kind = in.Kind
out.Name = in.Name
@@ -515,7 +591,17 @@ func autoConvert_v2beta2_HorizontalPodAutoscalerSpec_To_autoscaling_HorizontalPo
}
out.MinReplicas = (*int32)(unsafe.Pointer(in.MinReplicas))
out.MaxReplicas = in.MaxReplicas
out.Metrics = *(*[]autoscaling.MetricSpec)(unsafe.Pointer(&in.Metrics))
if in.Metrics != nil {
in, out := &in.Metrics, &out.Metrics
*out = make([]autoscaling.MetricSpec, len(*in))
for i := range *in {
if err := Convert_v2beta2_MetricSpec_To_autoscaling_MetricSpec(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Metrics = nil
}
out.Behavior = (*autoscaling.HorizontalPodAutoscalerBehavior)(unsafe.Pointer(in.Behavior))
return nil
}
@@ -531,7 +617,17 @@ func autoConvert_autoscaling_HorizontalPodAutoscalerSpec_To_v2beta2_HorizontalPo
}
out.MinReplicas = (*int32)(unsafe.Pointer(in.MinReplicas))
out.MaxReplicas = in.MaxReplicas
out.Metrics = *(*[]v2beta2.MetricSpec)(unsafe.Pointer(&in.Metrics))
if in.Metrics != nil {
in, out := &in.Metrics, &out.Metrics
*out = make([]v2beta2.MetricSpec, len(*in))
for i := range *in {
if err := Convert_autoscaling_MetricSpec_To_v2beta2_MetricSpec(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Metrics = nil
}
out.Behavior = (*v2beta2.HorizontalPodAutoscalerBehavior)(unsafe.Pointer(in.Behavior))
return nil
}
@@ -546,7 +642,17 @@ func autoConvert_v2beta2_HorizontalPodAutoscalerStatus_To_autoscaling_Horizontal
out.LastScaleTime = (*metav1.Time)(unsafe.Pointer(in.LastScaleTime))
out.CurrentReplicas = in.CurrentReplicas
out.DesiredReplicas = in.DesiredReplicas
out.CurrentMetrics = *(*[]autoscaling.MetricStatus)(unsafe.Pointer(&in.CurrentMetrics))
if in.CurrentMetrics != nil {
in, out := &in.CurrentMetrics, &out.CurrentMetrics
*out = make([]autoscaling.MetricStatus, len(*in))
for i := range *in {
if err := Convert_v2beta2_MetricStatus_To_autoscaling_MetricStatus(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.CurrentMetrics = nil
}
out.Conditions = *(*[]autoscaling.HorizontalPodAutoscalerCondition)(unsafe.Pointer(&in.Conditions))
return nil
}
@@ -561,7 +667,17 @@ func autoConvert_autoscaling_HorizontalPodAutoscalerStatus_To_v2beta2_Horizontal
out.LastScaleTime = (*metav1.Time)(unsafe.Pointer(in.LastScaleTime))
out.CurrentReplicas = in.CurrentReplicas
out.DesiredReplicas = in.DesiredReplicas
out.CurrentMetrics = *(*[]v2beta2.MetricStatus)(unsafe.Pointer(&in.CurrentMetrics))
if in.CurrentMetrics != nil {
in, out := &in.CurrentMetrics, &out.CurrentMetrics
*out = make([]v2beta2.MetricStatus, len(*in))
for i := range *in {
if err := Convert_autoscaling_MetricStatus_To_v2beta2_MetricStatus(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.CurrentMetrics = nil
}
out.Conditions = *(*[]v2beta2.HorizontalPodAutoscalerCondition)(unsafe.Pointer(&in.Conditions))
return nil
}
@@ -598,6 +714,15 @@ func autoConvert_v2beta2_MetricSpec_To_autoscaling_MetricSpec(in *v2beta2.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))
if in.ContainerResource != nil {
in, out := &in.ContainerResource, &out.ContainerResource
*out = new(autoscaling.ContainerResourceMetricSource)
if err := Convert_v2beta2_ContainerResourceMetricSource_To_autoscaling_ContainerResourceMetricSource(*in, *out, s); err != nil {
return err
}
} else {
out.ContainerResource = nil
}
out.External = (*autoscaling.ExternalMetricSource)(unsafe.Pointer(in.External))
return nil
}
@@ -612,6 +737,15 @@ func autoConvert_autoscaling_MetricSpec_To_v2beta2_MetricSpec(in *autoscaling.Me
out.Object = (*v2beta2.ObjectMetricSource)(unsafe.Pointer(in.Object))
out.Pods = (*v2beta2.PodsMetricSource)(unsafe.Pointer(in.Pods))
out.Resource = (*v2beta2.ResourceMetricSource)(unsafe.Pointer(in.Resource))
if in.ContainerResource != nil {
in, out := &in.ContainerResource, &out.ContainerResource
*out = new(v2beta2.ContainerResourceMetricSource)
if err := Convert_autoscaling_ContainerResourceMetricSource_To_v2beta2_ContainerResourceMetricSource(*in, *out, s); err != nil {
return err
}
} else {
out.ContainerResource = nil
}
out.External = (*v2beta2.ExternalMetricSource)(unsafe.Pointer(in.External))
return nil
}
@@ -626,6 +760,15 @@ func autoConvert_v2beta2_MetricStatus_To_autoscaling_MetricStatus(in *v2beta2.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))
if in.ContainerResource != nil {
in, out := &in.ContainerResource, &out.ContainerResource
*out = new(autoscaling.ContainerResourceMetricStatus)
if err := Convert_v2beta2_ContainerResourceMetricStatus_To_autoscaling_ContainerResourceMetricStatus(*in, *out, s); err != nil {
return err
}
} else {
out.ContainerResource = nil
}
out.External = (*autoscaling.ExternalMetricStatus)(unsafe.Pointer(in.External))
return nil
}
@@ -640,6 +783,15 @@ func autoConvert_autoscaling_MetricStatus_To_v2beta2_MetricStatus(in *autoscalin
out.Object = (*v2beta2.ObjectMetricStatus)(unsafe.Pointer(in.Object))
out.Pods = (*v2beta2.PodsMetricStatus)(unsafe.Pointer(in.Pods))
out.Resource = (*v2beta2.ResourceMetricStatus)(unsafe.Pointer(in.Resource))
if in.ContainerResource != nil {
in, out := &in.ContainerResource, &out.ContainerResource
*out = new(v2beta2.ContainerResourceMetricStatus)
if err := Convert_autoscaling_ContainerResourceMetricStatus_To_v2beta2_ContainerResourceMetricStatus(*in, *out, s); err != nil {
return err
}
} else {
out.ContainerResource = nil
}
out.External = (*v2beta2.ExternalMetricStatus)(unsafe.Pointer(in.External))
return nil
}

View File

@@ -12,6 +12,7 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/apis/autoscaling/validation",
deps = [
"//pkg/apis/autoscaling:go_default_library",
"//pkg/apis/core/v1/validation:go_default_library",
"//pkg/apis/core/validation:go_default_library",
"//pkg/features:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/validation:go_default_library",

View File

@@ -18,14 +18,13 @@ package validation
import (
"fmt"
"strings"
apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
pathvalidation "k8s.io/apimachinery/pkg/api/validation/path"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation/field"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/apis/autoscaling"
corevalidation "k8s.io/kubernetes/pkg/apis/core/v1/validation"
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
"k8s.io/kubernetes/pkg/features"
)
@@ -239,7 +238,10 @@ func validateScalingPolicy(policy autoscaling.HPAScalingPolicy, fldPath *field.P
return allErrs
}
var validMetricSourceTypes = sets.NewString(string(autoscaling.ObjectMetricSourceType), string(autoscaling.PodsMetricSourceType), string(autoscaling.ResourceMetricSourceType), string(autoscaling.ExternalMetricSourceType))
var validMetricSourceTypes = sets.NewString(
string(autoscaling.ObjectMetricSourceType), string(autoscaling.PodsMetricSourceType),
string(autoscaling.ResourceMetricSourceType), string(autoscaling.ExternalMetricSourceType),
string(autoscaling.ContainerResourceMetricSourceType))
var validMetricSourceTypesList = validMetricSourceTypes.List()
func validateMetricSpec(spec autoscaling.MetricSpec, fldPath *field.Path) field.ErrorList {
@@ -282,10 +284,47 @@ func validateMetricSpec(spec autoscaling.MetricSpec, fldPath *field.Path) field.
}
}
expectedField := strings.ToLower(string(spec.Type))
if spec.ContainerResource != nil {
typesPresent.Insert("containerResource")
if typesPresent.Len() == 1 {
allErrs = append(allErrs, validateContainerResourceSource(spec.ContainerResource, fldPath.Child("containerResource"))...)
}
}
if !typesPresent.Has(expectedField) {
allErrs = append(allErrs, field.Required(fldPath.Child(expectedField), "must populate information for the given metric source"))
var expectedField string
switch spec.Type {
case autoscaling.ObjectMetricSourceType:
if spec.Object == nil {
allErrs = append(allErrs, field.Required(fldPath.Child("object"), "must populate information for the given metric source"))
}
expectedField = "object"
case autoscaling.PodsMetricSourceType:
if spec.Pods == nil {
allErrs = append(allErrs, field.Required(fldPath.Child("pods"), "must populate information for the given metric source"))
}
expectedField = "pods"
case autoscaling.ResourceMetricSourceType:
if spec.Resource == nil {
allErrs = append(allErrs, field.Required(fldPath.Child("resource"), "must populate information for the given metric source"))
}
expectedField = "resource"
case autoscaling.ExternalMetricSourceType:
if spec.External == nil {
allErrs = append(allErrs, field.Required(fldPath.Child("external"), "must populate information for the given metric source"))
}
expectedField = "external"
case autoscaling.ContainerResourceMetricSourceType:
if spec.ContainerResource == nil {
if utilfeature.DefaultFeatureGate.Enabled(features.HPAContainerMetrics) {
allErrs = append(allErrs, field.Required(fldPath.Child("containerResource"), "must populate information for the given metric source"))
} else {
allErrs = append(allErrs, field.Required(fldPath.Child("containerResource"), "must populate information for the given metric source (only allowed when HPAContainerMetrics feature is enabled)"))
}
}
expectedField = "containerResource"
default:
allErrs = append(allErrs, field.NotSupported(fldPath.Child("type"), spec.Type, validMetricSourceTypesList))
}
if typesPresent.Len() != 1 {
@@ -342,6 +381,34 @@ func validatePodsSource(src *autoscaling.PodsMetricSource, fldPath *field.Path)
return allErrs
}
func validateContainerResourceSource(src *autoscaling.ContainerResourceMetricSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(src.Name) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("name"), "must specify a resource name"))
} else {
allErrs = append(allErrs, corevalidation.ValidateContainerResourceName(string(src.Name), fldPath.Child("name"))...)
}
if len(src.Container) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("container"), "must specify a container"))
} else {
allErrs = append(allErrs, apivalidation.ValidateDNS1123Label(src.Container, fldPath.Child("container"))...)
}
allErrs = append(allErrs, validateMetricTarget(src.Target, fldPath.Child("target"))...)
if src.Target.AverageUtilization == nil && src.Target.AverageValue == nil {
allErrs = append(allErrs, field.Required(fldPath.Child("target").Child("averageUtilization"), "must set either a target raw value or a target utilization"))
}
if src.Target.AverageUtilization != nil && src.Target.AverageValue != nil {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("target").Child("averageValue"), "may not set both a target raw value and a target utilization"))
}
return allErrs
}
func validateResourceSource(src *autoscaling.ResourceMetricSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}

View File

@@ -565,6 +565,60 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "myautoscaler",
Namespace: metav1.NamespaceDefault,
},
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
Kind: "ReplicationController",
Name: "myrc",
},
MinReplicas: utilpointer.Int32Ptr(1),
MaxReplicas: 5,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ContainerResourceMetricSourceType,
ContainerResource: &autoscaling.ContainerResourceMetricSource{
Name: api.ResourceCPU,
Container: "test-container",
Target: autoscaling.MetricTarget{
Type: autoscaling.UtilizationMetricType,
AverageUtilization: utilpointer.Int32Ptr(70),
},
},
},
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "myautoscaler",
Namespace: metav1.NamespaceDefault,
},
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
Kind: "ReplicationController",
Name: "myrc",
},
MinReplicas: utilpointer.Int32Ptr(1),
MaxReplicas: 5,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ContainerResourceMetricSourceType,
ContainerResource: &autoscaling.ContainerResourceMetricSource{
Name: api.ResourceCPU,
Container: "test-container",
Target: autoscaling.MetricTarget{
Type: autoscaling.AverageValueMetricType,
AverageValue: resource.NewMilliQuantity(300, resource.DecimalSI),
},
},
},
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "myautoscaler",
@@ -689,6 +743,30 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
},
msg: "scaleTargetRef.kind: Required",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc"},
MinReplicas: utilpointer.Int32Ptr(1),
MaxReplicas: 5,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ContainerResourceMetricSourceType,
ContainerResource: &autoscaling.ContainerResourceMetricSource{
Name: api.ResourceCPU,
Container: "test-application",
Target: autoscaling.MetricTarget{
Type: autoscaling.UtilizationMetricType,
AverageUtilization: utilpointer.Int32Ptr(70),
},
},
},
},
},
},
msg: "scaleTargetRef.kind: Required",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
@@ -712,6 +790,30 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
},
msg: "scaleTargetRef.kind: Invalid",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Kind: "..", Name: "myrc"},
MinReplicas: utilpointer.Int32Ptr(1),
MaxReplicas: 5,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ContainerResourceMetricSourceType,
ContainerResource: &autoscaling.ContainerResourceMetricSource{
Name: api.ResourceCPU,
Container: "test-application",
Target: autoscaling.MetricTarget{
Type: autoscaling.UtilizationMetricType,
AverageUtilization: utilpointer.Int32Ptr(70),
},
},
},
},
},
},
msg: "scaleTargetRef.kind: Invalid",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
@@ -735,6 +837,30 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
},
msg: "scaleTargetRef.name: Required",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Kind: "ReplicationController"},
MinReplicas: utilpointer.Int32Ptr(1),
MaxReplicas: 5,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ContainerResourceMetricSourceType,
ContainerResource: &autoscaling.ContainerResourceMetricSource{
Name: api.ResourceCPU,
Container: "test-application",
Target: autoscaling.MetricTarget{
Type: autoscaling.UtilizationMetricType,
AverageUtilization: utilpointer.Int32Ptr(70),
},
},
},
},
},
},
msg: "scaleTargetRef.name: Required",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
@@ -758,6 +884,30 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
},
msg: "scaleTargetRef.name: Invalid",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Kind: "ReplicationController", Name: ".."},
MinReplicas: utilpointer.Int32Ptr(1),
MaxReplicas: 5,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ContainerResourceMetricSourceType,
ContainerResource: &autoscaling.ContainerResourceMetricSource{
Name: api.ResourceCPU,
Container: "test-application",
Target: autoscaling.MetricTarget{
Type: autoscaling.UtilizationMetricType,
AverageUtilization: utilpointer.Int32Ptr(70),
},
},
},
},
},
},
msg: "scaleTargetRef.name: Invalid",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
@@ -813,6 +963,34 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
},
msg: "may not set both a target raw value and a target utilization",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "myautoscaler",
Namespace: metav1.NamespaceDefault,
},
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
MinReplicas: utilpointer.Int32Ptr(1),
MaxReplicas: 5,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ContainerResourceMetricSourceType,
ContainerResource: &autoscaling.ContainerResourceMetricSource{
Name: api.ResourceCPU,
Container: "test-application",
Target: autoscaling.MetricTarget{
Type: autoscaling.UtilizationMetricType,
AverageUtilization: utilpointer.Int32Ptr(70),
AverageValue: resource.NewMilliQuantity(300, resource.DecimalSI),
},
},
},
},
},
},
msg: "may not set both a target raw value and a target utilization",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
@@ -835,6 +1013,53 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
},
msg: "must specify a resource name",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
MinReplicas: utilpointer.Int32Ptr(1),
MaxReplicas: 5,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ContainerResourceMetricSourceType,
ContainerResource: &autoscaling.ContainerResourceMetricSource{
Container: "test-application",
Target: autoscaling.MetricTarget{
Type: autoscaling.UtilizationMetricType,
AverageUtilization: utilpointer.Int32Ptr(70),
},
},
},
},
},
},
msg: "must specify a resource name",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
MinReplicas: utilpointer.Int32Ptr(1),
MaxReplicas: 5,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ContainerResourceMetricSourceType,
ContainerResource: &autoscaling.ContainerResourceMetricSource{
Name: "InvalidResource",
Container: "test-application",
Target: autoscaling.MetricTarget{
Type: autoscaling.UtilizationMetricType,
AverageUtilization: utilpointer.Int32Ptr(70),
},
},
},
},
},
},
msg: "Invalid value: \"InvalidResource\": must be a standard resource type or fully qualified",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
@@ -858,6 +1083,77 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
},
msg: "must be greater than 0",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
MinReplicas: utilpointer.Int32Ptr(1),
MaxReplicas: 5,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ContainerResourceMetricSourceType,
ContainerResource: &autoscaling.ContainerResourceMetricSource{
Name: api.ResourceCPU,
Container: "test-application",
Target: autoscaling.MetricTarget{
Type: autoscaling.UtilizationMetricType,
AverageUtilization: utilpointer.Int32Ptr(-10),
},
},
},
},
},
},
msg: "must be greater than 0",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
MinReplicas: utilpointer.Int32Ptr(1),
MaxReplicas: 5,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ContainerResourceMetricSourceType,
ContainerResource: &autoscaling.ContainerResourceMetricSource{
Name: api.ResourceCPU,
Target: autoscaling.MetricTarget{
Type: autoscaling.UtilizationMetricType,
AverageUtilization: utilpointer.Int32Ptr(-10),
},
},
},
},
},
},
msg: "must specify a container",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
MinReplicas: utilpointer.Int32Ptr(1),
MaxReplicas: 5,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ContainerResourceMetricSourceType,
ContainerResource: &autoscaling.ContainerResourceMetricSource{
Name: api.ResourceCPU,
Container: "---***",
Target: autoscaling.MetricTarget{
Type: autoscaling.UtilizationMetricType,
AverageUtilization: utilpointer.Int32Ptr(-10),
},
},
},
},
},
},
msg: "Invalid value: \"---***\"",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
@@ -880,6 +1176,29 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
},
msg: "must set either a target raw value or a target utilization",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc", Kind: "ReplicationController"},
MinReplicas: utilpointer.Int32Ptr(1),
MaxReplicas: 5,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ContainerResourceMetricSourceType,
ContainerResource: &autoscaling.ContainerResourceMetricSource{
Name: api.ResourceCPU,
Container: "test-application",
Target: autoscaling.MetricTarget{
Type: autoscaling.ValueMetricType,
},
},
},
},
},
},
msg: "must set either a target raw value or a target utilization",
},
{
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "myautoscaler", Namespace: metav1.NamespaceDefault},
@@ -1321,6 +1640,16 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
},
},
},
autoscaling.ContainerResourceMetricSourceType: {
ContainerResource: &autoscaling.ContainerResourceMetricSource{
Name: api.ResourceCPU,
Container: "test-application",
Target: autoscaling.MetricTarget{
Type: autoscaling.AverageValueMetricType,
AverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
},
},
},
autoscaling.PodsMetricSourceType: {
Pods: &autoscaling.PodsMetricSource{
Metric: autoscaling.MetricIdentifier{

View File

@@ -25,6 +25,40 @@ 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 *ContainerResourceMetricSource) DeepCopyInto(out *ContainerResourceMetricSource) {
*out = *in
in.Target.DeepCopyInto(&out.Target)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerResourceMetricSource.
func (in *ContainerResourceMetricSource) DeepCopy() *ContainerResourceMetricSource {
if in == nil {
return nil
}
out := new(ContainerResourceMetricSource)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ContainerResourceMetricStatus) DeepCopyInto(out *ContainerResourceMetricStatus) {
*out = *in
in.Current.DeepCopyInto(&out.Current)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerResourceMetricStatus.
func (in *ContainerResourceMetricStatus) DeepCopy() *ContainerResourceMetricStatus {
if in == nil {
return nil
}
out := new(ContainerResourceMetricStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CrossVersionObjectReference) DeepCopyInto(out *CrossVersionObjectReference) {
*out = *in
@@ -340,6 +374,11 @@ func (in *MetricSpec) DeepCopyInto(out *MetricSpec) {
*out = new(ResourceMetricSource)
(*in).DeepCopyInto(*out)
}
if in.ContainerResource != nil {
in, out := &in.ContainerResource, &out.ContainerResource
*out = new(ContainerResourceMetricSource)
(*in).DeepCopyInto(*out)
}
if in.External != nil {
in, out := &in.External, &out.External
*out = new(ExternalMetricSource)
@@ -376,6 +415,11 @@ func (in *MetricStatus) DeepCopyInto(out *MetricStatus) {
*out = new(ResourceMetricStatus)
(*in).DeepCopyInto(*out)
}
if in.ContainerResource != nil {
in, out := &in.ContainerResource, &out.ContainerResource
*out = new(ContainerResourceMetricStatus)
(*in).DeepCopyInto(*out)
}
if in.External != nil {
in, out := &in.External, &out.External
*out = new(ExternalMetricStatus)