mirror of https://github.com/k3s-io/k3s
Move internal types of hpa from pkg/apis/extensions to pkg/apis/autoscaling
parent
fa95788e56
commit
212b459817
|
@ -34,7 +34,7 @@ import (
|
|||
|
||||
var (
|
||||
test = flag.BoolP("test", "t", false, "set this flag to generate the client code for the testdata")
|
||||
inputVersions = flag.StringSlice("input", []string{"api/", "extensions/", "batch/"}, "group/versions that client-gen will generate clients for. At most one version per group is allowed. Specified in the format \"group1/version1,group2/version2...\". Default to \"api/,extensions/,batch/\"")
|
||||
inputVersions = flag.StringSlice("input", []string{"api/", "extensions/", "autoscaling/", "batch/"}, "group/versions that client-gen will generate clients for. At most one version per group is allowed. Specified in the format \"group1/version1,group2/version2...\". Default to \"api/,extensions/,autoscaling/,batch/\"")
|
||||
basePath = flag.String("input-base", "k8s.io/kubernetes/pkg/apis", "base path to look for the api group. Default to \"k8s.io/kubernetes/pkg/apis\"")
|
||||
clientsetName = flag.StringP("clientset-name", "n", "internalclientset", "the name of the generated clientset package.")
|
||||
clientsetPath = flag.String("clientset-path", "k8s.io/kubernetes/pkg/client/clientset_generated/", "the generated clientset will be output to <clientset-path>/<clientset-name>. Default to \"k8s.io/kubernetes/pkg/client/clientset_generated/\"")
|
||||
|
|
|
@ -70,6 +70,7 @@ func DefaultNameSystem() string {
|
|||
var fallbackPackages = []string{
|
||||
"k8s.io/kubernetes/pkg/api/unversioned",
|
||||
"k8s.io/kubernetes/pkg/apis/extensions",
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling",
|
||||
"k8s.io/kubernetes/pkg/apis/batch",
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
|
@ -377,15 +378,12 @@ func FuzzerFor(t *testing.T, version unversioned.GroupVersion, src rand.Source)
|
|||
c.FuzzNoCustom(s)
|
||||
s.Allocatable = s.Capacity
|
||||
},
|
||||
func(s *extensions.HorizontalPodAutoscalerSpec, c fuzz.Continue) {
|
||||
func(s *autoscaling.HorizontalPodAutoscalerSpec, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(s) // fuzz self without calling this function again
|
||||
minReplicas := int32(c.Rand.Int31())
|
||||
s.MinReplicas = &minReplicas
|
||||
s.CPUUtilization = &extensions.CPUTargetUtilization{TargetPercentage: int32(c.RandUint64())}
|
||||
},
|
||||
func(s *extensions.SubresourceReference, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(s) // fuzz self without calling this function again
|
||||
s.Subresource = "scale"
|
||||
targetCpu := int32(c.RandUint64())
|
||||
s.TargetCPUUtilizationPercentage = &targetCpu
|
||||
},
|
||||
func(psp *extensions.PodSecurityPolicySpec, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(psp) // fuzz self without calling this function again
|
||||
|
|
|
@ -19,7 +19,6 @@ package autoscaling
|
|||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
|
@ -48,10 +47,12 @@ func AddToScheme(scheme *runtime.Scheme) {
|
|||
func addKnownTypes(scheme *runtime.Scheme) {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&Scale{},
|
||||
&extensions.HorizontalPodAutoscaler{},
|
||||
&extensions.HorizontalPodAutoscalerList{},
|
||||
&HorizontalPodAutoscaler{},
|
||||
&HorizontalPodAutoscalerList{},
|
||||
&api.ListOptions{},
|
||||
)
|
||||
}
|
||||
|
||||
func (obj *Scale) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *Scale) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *HorizontalPodAutoscaler) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *HorizontalPodAutoscalerList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
|
|
|
@ -51,3 +51,70 @@ type ScaleStatus struct {
|
|||
// More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md#label-selectors
|
||||
Selector string `json:"selector,omitempty"`
|
||||
}
|
||||
|
||||
// CrossVersionObjectReference contains enough information to let you identify the referred resource.
|
||||
type CrossVersionObjectReference struct {
|
||||
// Kind of the referent; More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds"
|
||||
Kind string `json:"kind" protobuf:"bytes,1,opt,name=kind"`
|
||||
// Name of the referent; More info: http://releases.k8s.io/HEAD/docs/user-guide/identifiers.md#names
|
||||
Name string `json:"name" protobuf:"bytes,2,opt,name=name"`
|
||||
// API version of the referent
|
||||
APIVersion string `json:"apiVersion,omitempty" protobuf:"bytes,3,opt,name=apiVersion"`
|
||||
}
|
||||
|
||||
// specification of a horizontal pod autoscaler.
|
||||
type HorizontalPodAutoscalerSpec struct {
|
||||
// reference to scaled resource; horizontal pod autoscaler will learn the current resource consumption
|
||||
// and will set the desired number of pods by using its Scale subresource.
|
||||
ScaleTargetRef CrossVersionObjectReference `json:"scaleTargetRef"`
|
||||
// lower limit for the number of pods that can be set by the autoscaler, default 1.
|
||||
MinReplicas *int32 `json:"minReplicas,omitempty"`
|
||||
// upper limit for the number of pods that can be set by the autoscaler. It cannot be smaller than MinReplicas.
|
||||
MaxReplicas int32 `json:"maxReplicas"`
|
||||
// target average CPU utilization (represented as a percentage of requested CPU) over all the pods;
|
||||
// if not specified the default autoscaling policy will be used.
|
||||
TargetCPUUtilizationPercentage *int32 `json:"targetCPUUtilizationPercentage,omitempty"`
|
||||
}
|
||||
|
||||
// current status of a horizontal pod autoscaler
|
||||
type HorizontalPodAutoscalerStatus struct {
|
||||
// most recent generation observed by this autoscaler.
|
||||
ObservedGeneration *int64 `json:"observedGeneration,omitempty"`
|
||||
|
||||
// last time the HorizontalPodAutoscaler scaled the number of pods;
|
||||
// used by the autoscaler to control how often the number of pods is changed.
|
||||
LastScaleTime *unversioned.Time `json:"lastScaleTime,omitempty"`
|
||||
|
||||
// current number of replicas of pods managed by this autoscaler.
|
||||
CurrentReplicas int32 `json:"currentReplicas"`
|
||||
|
||||
// desired number of replicas of pods managed by this autoscaler.
|
||||
DesiredReplicas int32 `json:"desiredReplicas"`
|
||||
|
||||
// current average CPU utilization over all pods, represented as a percentage of requested CPU,
|
||||
// e.g. 70 means that an average pod is using now 70% of its requested CPU.
|
||||
CurrentCPUUtilizationPercentage *int32 `json:"currentCPUUtilizationPercentage,omitempty"`
|
||||
}
|
||||
|
||||
// +genclient=true
|
||||
|
||||
// configuration of a horizontal pod autoscaler.
|
||||
type HorizontalPodAutoscaler struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
api.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// behaviour of autoscaler. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status.
|
||||
Spec HorizontalPodAutoscalerSpec `json:"spec,omitempty"`
|
||||
|
||||
// current information about the autoscaler.
|
||||
Status HorizontalPodAutoscalerStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// list of horizontal pod autoscaler objects.
|
||||
type HorizontalPodAutoscalerList struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
unversioned.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
// list of horizontal pod autoscaler objects.
|
||||
Items []HorizontalPodAutoscaler `json:"items"`
|
||||
}
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 v1
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/conversion"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
func addConversionFuncs(scheme *runtime.Scheme) {
|
||||
// Add non-generated conversion functions
|
||||
err := scheme.AddConversionFuncs(
|
||||
Convert_extensions_SubresourceReference_To_v1_CrossVersionObjectReference,
|
||||
Convert_v1_CrossVersionObjectReference_To_extensions_SubresourceReference,
|
||||
Convert_extensions_HorizontalPodAutoscalerSpec_To_v1_HorizontalPodAutoscalerSpec,
|
||||
Convert_v1_HorizontalPodAutoscalerSpec_To_extensions_HorizontalPodAutoscalerSpec,
|
||||
)
|
||||
if err != nil {
|
||||
// If one of the conversion functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Convert_extensions_SubresourceReference_To_v1_CrossVersionObjectReference(in *extensions.SubresourceReference, out *CrossVersionObjectReference, s conversion.Scope) error {
|
||||
out.Kind = in.Kind
|
||||
out.Name = in.Name
|
||||
out.APIVersion = in.APIVersion
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_CrossVersionObjectReference_To_extensions_SubresourceReference(in *CrossVersionObjectReference, out *extensions.SubresourceReference, s conversion.Scope) error {
|
||||
out.Kind = in.Kind
|
||||
out.Name = in.Name
|
||||
out.APIVersion = in.APIVersion
|
||||
out.Subresource = "scale"
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_extensions_HorizontalPodAutoscalerSpec_To_v1_HorizontalPodAutoscalerSpec(in *extensions.HorizontalPodAutoscalerSpec, out *HorizontalPodAutoscalerSpec, s conversion.Scope) error {
|
||||
if err := Convert_extensions_SubresourceReference_To_v1_CrossVersionObjectReference(&in.ScaleRef, &out.ScaleTargetRef, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.MinReplicas != nil {
|
||||
out.MinReplicas = new(int32)
|
||||
*out.MinReplicas = int32(*in.MinReplicas)
|
||||
} else {
|
||||
out.MinReplicas = nil
|
||||
}
|
||||
out.MaxReplicas = int32(in.MaxReplicas)
|
||||
if in.CPUUtilization != nil {
|
||||
out.TargetCPUUtilizationPercentage = new(int32)
|
||||
*out.TargetCPUUtilizationPercentage = int32(in.CPUUtilization.TargetPercentage)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_HorizontalPodAutoscalerSpec_To_extensions_HorizontalPodAutoscalerSpec(in *HorizontalPodAutoscalerSpec, out *extensions.HorizontalPodAutoscalerSpec, s conversion.Scope) error {
|
||||
if err := Convert_v1_CrossVersionObjectReference_To_extensions_SubresourceReference(&in.ScaleTargetRef, &out.ScaleRef, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.MinReplicas != nil {
|
||||
out.MinReplicas = new(int32)
|
||||
*out.MinReplicas = *in.MinReplicas
|
||||
} else {
|
||||
out.MinReplicas = nil
|
||||
}
|
||||
out.MaxReplicas = in.MaxReplicas
|
||||
if in.TargetCPUUtilizationPercentage != nil {
|
||||
out.CPUUtilization = &extensions.CPUTargetUtilization{TargetPercentage: *in.TargetCPUUtilizationPercentage}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -32,7 +32,6 @@ var SchemeGroupVersion = unversioned.GroupVersion{Group: GroupName, Version: "v1
|
|||
func AddToScheme(scheme *runtime.Scheme) {
|
||||
addKnownTypes(scheme)
|
||||
addDefaultingFuncs(scheme)
|
||||
addConversionFuncs(scheme)
|
||||
}
|
||||
|
||||
// Adds the list of known types to api.Scheme.
|
||||
|
|
|
@ -17,8 +17,12 @@ limitations under the License.
|
|||
package validation
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
apivalidation "k8s.io/kubernetes/pkg/api/validation"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/controller/podautoscaler"
|
||||
"k8s.io/kubernetes/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
|
@ -32,3 +36,92 @@ func ValidateScale(scale *autoscaling.Scale) field.ErrorList {
|
|||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateHorizontalPodAutoscaler can be used to check whether the given autoscaler name is valid.
|
||||
// Prefix indicates this name will be used as part of generation, in which case trailing dashes are allowed.
|
||||
func ValidateHorizontalPodAutoscalerName(name string, prefix bool) (bool, string) {
|
||||
// TODO: finally move it to pkg/api/validation and use nameIsDNSSubdomain function
|
||||
return apivalidation.ValidateReplicationControllerName(name, prefix)
|
||||
}
|
||||
|
||||
func validateHorizontalPodAutoscalerSpec(autoscaler autoscaling.HorizontalPodAutoscalerSpec, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if autoscaler.MinReplicas != nil && *autoscaler.MinReplicas < 1 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("minReplicas"), *autoscaler.MinReplicas, "must be greater than 0"))
|
||||
}
|
||||
if autoscaler.MaxReplicas < 1 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("maxReplicas"), autoscaler.MaxReplicas, "must be greater than 0"))
|
||||
}
|
||||
if autoscaler.MinReplicas != nil && autoscaler.MaxReplicas < *autoscaler.MinReplicas {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("maxReplicas"), autoscaler.MaxReplicas, "must be greater than or equal to `minReplicas`"))
|
||||
}
|
||||
if autoscaler.TargetCPUUtilizationPercentage != nil && *autoscaler.TargetCPUUtilizationPercentage < 1 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("targetCPUUtilizationPercentage"), autoscaler.TargetCPUUtilizationPercentage, "must be greater than 0"))
|
||||
}
|
||||
if refErrs := ValidateCrossVersionObjectReference(autoscaler.ScaleTargetRef, fldPath.Child("scaleTargetRef")); len(refErrs) > 0 {
|
||||
allErrs = append(allErrs, refErrs...)
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateCrossVersionObjectReference(ref autoscaling.CrossVersionObjectReference, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(ref.Kind) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("kind"), ""))
|
||||
} else if ok, msg := apivalidation.IsValidPathSegmentName(ref.Kind); !ok {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("kind"), ref.Kind, msg))
|
||||
}
|
||||
|
||||
if len(ref.Name) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("name"), ""))
|
||||
} else if ok, msg := apivalidation.IsValidPathSegmentName(ref.Name); !ok {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), ref.Name, msg))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateHorizontalPodAutoscalerAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if annotationValue, found := annotations[podautoscaler.HpaCustomMetricsTargetAnnotationName]; found {
|
||||
// Try to parse the annotation
|
||||
var targetList extensions.CustomMetricTargetList
|
||||
if err := json.Unmarshal([]byte(annotationValue), &targetList); err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("annotations"), annotations, "failed to parse custom metrics target annotation"))
|
||||
} else {
|
||||
if len(targetList.Items) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("annotations", "items"), "custom metrics target must not be empty"))
|
||||
}
|
||||
for _, target := range targetList.Items {
|
||||
if target.Name == "" {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("annotations", "items", "name"), "missing custom metric target name"))
|
||||
}
|
||||
if target.TargetValue.MilliValue() <= 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("annotations", "items", "value"), target.TargetValue, "custom metric target value must be greater than 0"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateHorizontalPodAutoscaler(autoscaler *autoscaling.HorizontalPodAutoscaler) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMeta(&autoscaler.ObjectMeta, true, ValidateHorizontalPodAutoscalerName, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, validateHorizontalPodAutoscalerSpec(autoscaler.Spec, field.NewPath("spec"))...)
|
||||
allErrs = append(allErrs, validateHorizontalPodAutoscalerAnnotations(autoscaler.Annotations, field.NewPath("metadata"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateHorizontalPodAutoscalerUpdate(newAutoscaler, oldAutoscaler *autoscaling.HorizontalPodAutoscaler) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMetaUpdate(&newAutoscaler.ObjectMeta, &oldAutoscaler.ObjectMeta, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, validateHorizontalPodAutoscalerSpec(newAutoscaler.Spec, field.NewPath("spec"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateHorizontalPodAutoscalerStatusUpdate(newAutoscaler, oldAutoscaler *autoscaling.HorizontalPodAutoscaler) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMetaUpdate(&newAutoscaler.ObjectMeta, &oldAutoscaler.ObjectMeta, field.NewPath("metadata"))
|
||||
status := newAutoscaler.Status
|
||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.CurrentReplicas), field.NewPath("status", "currentReplicas"))...)
|
||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.DesiredReplicas), field.NewPath("status", "desiredReplicasa"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/controller/podautoscaler"
|
||||
)
|
||||
|
||||
func TestValidateScale(t *testing.T) {
|
||||
|
@ -87,3 +88,251 @@ func TestValidateScale(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateHorizontalPodAutoscaler(t *testing.T) {
|
||||
successCases := []autoscaling.HorizontalPodAutoscaler{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
TargetCPUUtilizationPercentage: newInt32(70),
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
Annotations: map[string]string{
|
||||
podautoscaler.HpaCustomMetricsTargetAnnotationName: "{\"items\":[{\"name\":\"qps\",\"value\":\"20\"}]}",
|
||||
},
|
||||
},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, successCase := range successCases {
|
||||
if errs := ValidateHorizontalPodAutoscaler(&successCase); len(errs) != 0 {
|
||||
t.Errorf("expected success: %v", errs)
|
||||
}
|
||||
}
|
||||
|
||||
errorCases := []struct {
|
||||
horizontalPodAutoscaler autoscaling.HorizontalPodAutoscaler
|
||||
msg string
|
||||
}{
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Name: "myrc"},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
TargetCPUUtilizationPercentage: newInt32(70),
|
||||
},
|
||||
},
|
||||
msg: "scaleTargetRef.kind: Required",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Kind: "..", Name: "myrc"},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
TargetCPUUtilizationPercentage: newInt32(70),
|
||||
},
|
||||
},
|
||||
msg: "scaleTargetRef.kind: Invalid",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Kind: "ReplicationController"},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
TargetCPUUtilizationPercentage: newInt32(70),
|
||||
},
|
||||
},
|
||||
msg: "scaleTargetRef.name: Required",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{Kind: "ReplicationController", Name: ".."},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
TargetCPUUtilizationPercentage: newInt32(70),
|
||||
},
|
||||
},
|
||||
msg: "scaleTargetRef.name: Invalid",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{},
|
||||
MinReplicas: newInt32(-1),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
msg: "must be greater than 0",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{},
|
||||
MinReplicas: newInt32(7),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
msg: "must be greater than or equal to `minReplicas`",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
TargetCPUUtilizationPercentage: newInt32(-70),
|
||||
},
|
||||
},
|
||||
msg: "must be greater than 0",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
Annotations: map[string]string{
|
||||
podautoscaler.HpaCustomMetricsTargetAnnotationName: "broken",
|
||||
},
|
||||
},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
msg: "failed to parse custom metrics target annotation",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
Annotations: map[string]string{
|
||||
podautoscaler.HpaCustomMetricsTargetAnnotationName: "{}",
|
||||
},
|
||||
},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
msg: "custom metrics target must not be empty",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
Annotations: map[string]string{
|
||||
podautoscaler.HpaCustomMetricsTargetAnnotationName: "{\"items\":[{\"value\":\"20\"}]}",
|
||||
},
|
||||
},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
msg: "missing custom metric target name",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
Annotations: map[string]string{
|
||||
podautoscaler.HpaCustomMetricsTargetAnnotationName: "{\"items\":[{\"name\":\"qps\",\"value\":\"0\"}]}",
|
||||
},
|
||||
},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
msg: "custom metric target value must be greater than 0",
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range errorCases {
|
||||
errs := ValidateHorizontalPodAutoscaler(&c.horizontalPodAutoscaler)
|
||||
if len(errs) == 0 {
|
||||
t.Errorf("expected failure for %q", c.msg)
|
||||
} else if !strings.Contains(errs[0].Error(), c.msg) {
|
||||
t.Errorf("unexpected error: %q, expected: %q", errs[0], c.msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newInt32(val int32) *int32 {
|
||||
p := new(int32)
|
||||
*p = val
|
||||
return p
|
||||
}
|
||||
|
|
|
@ -78,10 +78,9 @@ func TestInterfacesFor(t *testing.T) {
|
|||
|
||||
func TestRESTMapper(t *testing.T) {
|
||||
gv := v1beta1.SchemeGroupVersion
|
||||
hpaGVK := gv.WithKind("HorizontalPodAutoscaler")
|
||||
daemonSetGVK := gv.WithKind("DaemonSet")
|
||||
|
||||
if gvk, err := registered.GroupOrDie(extensions.GroupName).RESTMapper.KindFor(gv.WithResource("horizontalpodautoscalers")); err != nil || gvk != hpaGVK {
|
||||
if gvk, err := registered.GroupOrDie(extensions.GroupName).RESTMapper.KindFor(gv.WithResource("daemonsets")); err != nil || gvk != daemonSetGVK {
|
||||
t.Errorf("unexpected version mapping: %v %v", gvk, err)
|
||||
}
|
||||
|
||||
|
@ -90,12 +89,12 @@ func TestRESTMapper(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, version := range registered.GroupOrDie(extensions.GroupName).GroupVersions {
|
||||
mapping, err := registered.GroupOrDie(extensions.GroupName).RESTMapper.RESTMapping(hpaGVK.GroupKind(), version.Version)
|
||||
mapping, err := registered.GroupOrDie(extensions.GroupName).RESTMapper.RESTMapping(daemonSetGVK.GroupKind(), version.Version)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if mapping.Resource != "horizontalpodautoscalers" {
|
||||
if mapping.Resource != "daemonsets" {
|
||||
t.Errorf("incorrect resource name: %#v", mapping)
|
||||
}
|
||||
if mapping.GroupVersionKind.GroupVersion() != version {
|
||||
|
@ -107,7 +106,7 @@ func TestRESTMapper(t *testing.T) {
|
|||
t.Errorf("unexpected: %#v, expected: %#v", mapping, interfaces)
|
||||
}
|
||||
|
||||
rc := &extensions.HorizontalPodAutoscaler{ObjectMeta: api.ObjectMeta{Name: "foo"}}
|
||||
rc := &extensions.DaemonSet{ObjectMeta: api.ObjectMeta{Name: "foo"}}
|
||||
name, err := mapping.MetadataAccessor.Name(rc)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
|
|
|
@ -19,6 +19,7 @@ package extensions
|
|||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
@ -51,8 +52,8 @@ func addKnownTypes(scheme *runtime.Scheme) {
|
|||
&Deployment{},
|
||||
&DeploymentList{},
|
||||
&DeploymentRollback{},
|
||||
&HorizontalPodAutoscaler{},
|
||||
&HorizontalPodAutoscalerList{},
|
||||
&autoscaling.HorizontalPodAutoscaler{},
|
||||
&autoscaling.HorizontalPodAutoscalerList{},
|
||||
&batch.Job{},
|
||||
&batch.JobList{},
|
||||
&ReplicationControllerDummy{},
|
||||
|
@ -74,22 +75,20 @@ func addKnownTypes(scheme *runtime.Scheme) {
|
|||
)
|
||||
}
|
||||
|
||||
func (obj *Deployment) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *DeploymentList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *DeploymentRollback) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *HorizontalPodAutoscaler) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *HorizontalPodAutoscalerList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ReplicationControllerDummy) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *Scale) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ThirdPartyResource) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ThirdPartyResourceList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *DaemonSet) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *DaemonSetList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ThirdPartyResourceData) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ThirdPartyResourceDataList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *Ingress) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *IngressList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ReplicaSet) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ReplicaSetList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *PodSecurityPolicy) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *PodSecurityPolicyList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *Deployment) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *DeploymentList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *DeploymentRollback) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ReplicationControllerDummy) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *Scale) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ThirdPartyResource) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ThirdPartyResourceList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *DaemonSet) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *DaemonSetList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ThirdPartyResourceData) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ThirdPartyResourceDataList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *Ingress) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *IngressList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ReplicaSet) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ReplicaSetList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *PodSecurityPolicy) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *PodSecurityPolicyList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
|
|
|
@ -71,24 +71,6 @@ type ReplicationControllerDummy struct {
|
|||
unversioned.TypeMeta `json:",inline"`
|
||||
}
|
||||
|
||||
// SubresourceReference contains enough information to let you inspect or modify the referred subresource.
|
||||
type SubresourceReference struct {
|
||||
// Kind of the referent; More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds"
|
||||
Kind string `json:"kind,omitempty"`
|
||||
// Name of the referent; More info: http://releases.k8s.io/HEAD/docs/user-guide/identifiers.md#names
|
||||
Name string `json:"name,omitempty"`
|
||||
// API version of the referent
|
||||
APIVersion string `json:"apiVersion,omitempty"`
|
||||
// Subresource name of the referent
|
||||
Subresource string `json:"subresource,omitempty"`
|
||||
}
|
||||
|
||||
type CPUTargetUtilization struct {
|
||||
// fraction of the requested CPU that should be utilized/used,
|
||||
// e.g. 70 means that 70% of the requested CPU should be in use.
|
||||
TargetPercentage int32 `json:"targetPercentage"`
|
||||
}
|
||||
|
||||
// Alpha-level support for Custom Metrics in HPA (as annotations).
|
||||
type CustomMetricTarget struct {
|
||||
// Custom Metric name.
|
||||
|
@ -112,63 +94,6 @@ type CustomMetricCurrentStatusList struct {
|
|||
Items []CustomMetricCurrentStatus `json:"items"`
|
||||
}
|
||||
|
||||
// specification of a horizontal pod autoscaler.
|
||||
type HorizontalPodAutoscalerSpec struct {
|
||||
// reference to Scale subresource; horizontal pod autoscaler will learn the current resource consumption from its status,
|
||||
// and will set the desired number of pods by modifying its spec.
|
||||
ScaleRef SubresourceReference `json:"scaleRef"`
|
||||
// lower limit for the number of pods that can be set by the autoscaler, default 1.
|
||||
MinReplicas *int32 `json:"minReplicas,omitempty"`
|
||||
// upper limit for the number of pods that can be set by the autoscaler. It cannot be smaller than MinReplicas.
|
||||
MaxReplicas int32 `json:"maxReplicas"`
|
||||
// target average CPU utilization (represented as a percentage of requested CPU) over all the pods;
|
||||
// if not specified it defaults to the target CPU utilization at 80% of the requested resources.
|
||||
CPUUtilization *CPUTargetUtilization `json:"cpuUtilization,omitempty"`
|
||||
}
|
||||
|
||||
// current status of a horizontal pod autoscaler
|
||||
type HorizontalPodAutoscalerStatus struct {
|
||||
// most recent generation observed by this autoscaler.
|
||||
ObservedGeneration *int64 `json:"observedGeneration,omitempty"`
|
||||
|
||||
// last time the HorizontalPodAutoscaler scaled the number of pods;
|
||||
// used by the autoscaler to control how often the number of pods is changed.
|
||||
LastScaleTime *unversioned.Time `json:"lastScaleTime,omitempty"`
|
||||
|
||||
// current number of replicas of pods managed by this autoscaler.
|
||||
CurrentReplicas int32 `json:"currentReplicas"`
|
||||
|
||||
// desired number of replicas of pods managed by this autoscaler.
|
||||
DesiredReplicas int32 `json:"desiredReplicas"`
|
||||
|
||||
// current average CPU utilization over all pods, represented as a percentage of requested CPU,
|
||||
// e.g. 70 means that an average pod is using now 70% of its requested CPU.
|
||||
CurrentCPUUtilizationPercentage *int32 `json:"currentCPUUtilizationPercentage,omitempty"`
|
||||
}
|
||||
|
||||
// +genclient=true
|
||||
|
||||
// configuration of a horizontal pod autoscaler.
|
||||
type HorizontalPodAutoscaler struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
api.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// behaviour of autoscaler. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status.
|
||||
Spec HorizontalPodAutoscalerSpec `json:"spec,omitempty"`
|
||||
|
||||
// current information about the autoscaler.
|
||||
Status HorizontalPodAutoscalerStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// list of horizontal pod autoscaler objects.
|
||||
type HorizontalPodAutoscalerList struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
unversioned.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
// list of horizontal pod autoscaler objects.
|
||||
Items []HorizontalPodAutoscaler `json:"items"`
|
||||
}
|
||||
|
||||
// +genclient=true,nonNamespaced=true
|
||||
|
||||
// A ThirdPartyResource is a generic representation of a resource, it is used by add-ons and plugins to add new resource
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/conversion"
|
||||
|
@ -42,6 +43,11 @@ func addConversionFuncs(scheme *runtime.Scheme) {
|
|||
Convert_v1beta1_RollingUpdateDeployment_To_extensions_RollingUpdateDeployment,
|
||||
Convert_extensions_ReplicaSetSpec_To_v1beta1_ReplicaSetSpec,
|
||||
Convert_v1beta1_ReplicaSetSpec_To_extensions_ReplicaSetSpec,
|
||||
// autoscaling
|
||||
Convert_autoscaling_CrossVersionObjectReference_To_v1beta1_SubresourceReference,
|
||||
Convert_v1beta1_SubresourceReference_To_autoscaling_CrossVersionObjectReference,
|
||||
Convert_autoscaling_HorizontalPodAutoscalerSpec_To_v1beta1_HorizontalPodAutoscalerSpec,
|
||||
Convert_v1beta1_HorizontalPodAutoscalerSpec_To_autoscaling_HorizontalPodAutoscalerSpec,
|
||||
// batch
|
||||
Convert_batch_JobSpec_To_v1beta1_JobSpec,
|
||||
Convert_v1beta1_JobSpec_To_batch_JobSpec,
|
||||
|
@ -346,3 +352,53 @@ func Convert_v1beta1_JobSpec_To_batch_JobSpec(in *JobSpec, out *batch.JobSpec, s
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_autoscaling_CrossVersionObjectReference_To_v1beta1_SubresourceReference(in *autoscaling.CrossVersionObjectReference, out *SubresourceReference, s conversion.Scope) error {
|
||||
out.Kind = in.Kind
|
||||
out.Name = in.Name
|
||||
out.APIVersion = in.APIVersion
|
||||
out.Subresource = "scale"
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1beta1_SubresourceReference_To_autoscaling_CrossVersionObjectReference(in *SubresourceReference, out *autoscaling.CrossVersionObjectReference, s conversion.Scope) error {
|
||||
out.Kind = in.Kind
|
||||
out.Name = in.Name
|
||||
out.APIVersion = in.APIVersion
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_autoscaling_HorizontalPodAutoscalerSpec_To_v1beta1_HorizontalPodAutoscalerSpec(in *autoscaling.HorizontalPodAutoscalerSpec, out *HorizontalPodAutoscalerSpec, s conversion.Scope) error {
|
||||
if err := Convert_autoscaling_CrossVersionObjectReference_To_v1beta1_SubresourceReference(&in.ScaleTargetRef, &out.ScaleRef, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.MinReplicas != nil {
|
||||
out.MinReplicas = new(int32)
|
||||
*out.MinReplicas = *in.MinReplicas
|
||||
} else {
|
||||
out.MinReplicas = nil
|
||||
}
|
||||
out.MaxReplicas = in.MaxReplicas
|
||||
if in.TargetCPUUtilizationPercentage != nil {
|
||||
out.CPUUtilization = &CPUTargetUtilization{TargetPercentage: *in.TargetCPUUtilizationPercentage}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1beta1_HorizontalPodAutoscalerSpec_To_autoscaling_HorizontalPodAutoscalerSpec(in *HorizontalPodAutoscalerSpec, out *autoscaling.HorizontalPodAutoscalerSpec, s conversion.Scope) error {
|
||||
if err := Convert_v1beta1_SubresourceReference_To_autoscaling_CrossVersionObjectReference(&in.ScaleRef, &out.ScaleTargetRef, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.MinReplicas != nil {
|
||||
out.MinReplicas = new(int32)
|
||||
*out.MinReplicas = int32(*in.MinReplicas)
|
||||
} else {
|
||||
out.MinReplicas = nil
|
||||
}
|
||||
out.MaxReplicas = int32(in.MaxReplicas)
|
||||
if in.CPUUtilization != nil {
|
||||
out.TargetCPUUtilizationPercentage = new(int32)
|
||||
*out.TargetCPUUtilizationPercentage = int32(in.CPUUtilization.TargetPercentage)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
package validation
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
@ -28,7 +27,6 @@ import (
|
|||
unversionedvalidation "k8s.io/kubernetes/pkg/api/unversioned/validation"
|
||||
apivalidation "k8s.io/kubernetes/pkg/api/validation"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/controller/podautoscaler"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/util/intstr"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
|
@ -36,102 +34,6 @@ import (
|
|||
"k8s.io/kubernetes/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
// ValidateHorizontalPodAutoscaler can be used to check whether the given autoscaler name is valid.
|
||||
// Prefix indicates this name will be used as part of generation, in which case trailing dashes are allowed.
|
||||
func ValidateHorizontalPodAutoscalerName(name string, prefix bool) (bool, string) {
|
||||
// TODO: finally move it to pkg/api/validation and use nameIsDNSSubdomain function
|
||||
return apivalidation.ValidateReplicationControllerName(name, prefix)
|
||||
}
|
||||
|
||||
func validateHorizontalPodAutoscalerSpec(autoscaler extensions.HorizontalPodAutoscalerSpec, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if autoscaler.MinReplicas != nil && *autoscaler.MinReplicas < 1 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("minReplicas"), *autoscaler.MinReplicas, "must be greater than 0"))
|
||||
}
|
||||
if autoscaler.MaxReplicas < 1 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("maxReplicas"), autoscaler.MaxReplicas, "must be greater than 0"))
|
||||
}
|
||||
if autoscaler.MinReplicas != nil && autoscaler.MaxReplicas < *autoscaler.MinReplicas {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("maxReplicas"), autoscaler.MaxReplicas, "must be greater than or equal to `minReplicas`"))
|
||||
}
|
||||
if autoscaler.CPUUtilization != nil && autoscaler.CPUUtilization.TargetPercentage < 1 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("cpuUtilization", "targetPercentage"), autoscaler.CPUUtilization.TargetPercentage, "must be greater than 0"))
|
||||
}
|
||||
if refErrs := ValidateSubresourceReference(autoscaler.ScaleRef, fldPath.Child("scaleRef")); len(refErrs) > 0 {
|
||||
allErrs = append(allErrs, refErrs...)
|
||||
} else if autoscaler.ScaleRef.Subresource != "scale" {
|
||||
allErrs = append(allErrs, field.NotSupported(fldPath.Child("scaleRef", "subresource"), autoscaler.ScaleRef.Subresource, []string{"scale"}))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateSubresourceReference(ref extensions.SubresourceReference, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(ref.Kind) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("kind"), ""))
|
||||
} else if ok, msg := apivalidation.IsValidPathSegmentName(ref.Kind); !ok {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("kind"), ref.Kind, msg))
|
||||
}
|
||||
|
||||
if len(ref.Name) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("name"), ""))
|
||||
} else if ok, msg := apivalidation.IsValidPathSegmentName(ref.Name); !ok {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), ref.Name, msg))
|
||||
}
|
||||
|
||||
if len(ref.Subresource) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("subresource"), ""))
|
||||
} else if ok, msg := apivalidation.IsValidPathSegmentName(ref.Subresource); !ok {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("subresource"), ref.Subresource, msg))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateHorizontalPodAutoscalerAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if annotationValue, found := annotations[podautoscaler.HpaCustomMetricsTargetAnnotationName]; found {
|
||||
// Try to parse the annotation
|
||||
var targetList extensions.CustomMetricTargetList
|
||||
if err := json.Unmarshal([]byte(annotationValue), &targetList); err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("annotations"), annotations, "failed to parse custom metrics target annotation"))
|
||||
} else {
|
||||
if len(targetList.Items) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("annotations", "items"), "custom metrics target must not be empty"))
|
||||
}
|
||||
for _, target := range targetList.Items {
|
||||
if target.Name == "" {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("annotations", "items", "name"), "missing custom metric target name"))
|
||||
}
|
||||
if target.TargetValue.MilliValue() <= 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("annotations", "items", "value"), target.TargetValue, "custom metric target value must be greater than 0"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateHorizontalPodAutoscaler(autoscaler *extensions.HorizontalPodAutoscaler) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMeta(&autoscaler.ObjectMeta, true, ValidateHorizontalPodAutoscalerName, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, validateHorizontalPodAutoscalerSpec(autoscaler.Spec, field.NewPath("spec"))...)
|
||||
allErrs = append(allErrs, validateHorizontalPodAutoscalerAnnotations(autoscaler.Annotations, field.NewPath("metadata"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateHorizontalPodAutoscalerUpdate(newAutoscaler, oldAutoscaler *extensions.HorizontalPodAutoscaler) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMetaUpdate(&newAutoscaler.ObjectMeta, &oldAutoscaler.ObjectMeta, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, validateHorizontalPodAutoscalerSpec(newAutoscaler.Spec, field.NewPath("spec"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateHorizontalPodAutoscalerStatusUpdate(newAutoscaler, oldAutoscaler *extensions.HorizontalPodAutoscaler) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMetaUpdate(&newAutoscaler.ObjectMeta, &oldAutoscaler.ObjectMeta, field.NewPath("metadata"))
|
||||
status := newAutoscaler.Status
|
||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.CurrentReplicas), field.NewPath("status", "currentReplicas"))...)
|
||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.DesiredReplicas), field.NewPath("status", "desiredReplicasa"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateThirdPartyResourceUpdate(update, old *extensions.ThirdPartyResource) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&update.ObjectMeta, &old.ObjectMeta, field.NewPath("metadata"))...)
|
||||
|
|
|
@ -24,301 +24,9 @@ import (
|
|||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/controller/podautoscaler"
|
||||
"k8s.io/kubernetes/pkg/util/intstr"
|
||||
)
|
||||
|
||||
func TestValidateHorizontalPodAutoscaler(t *testing.T) {
|
||||
successCases := []extensions.HorizontalPodAutoscaler{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
Subresource: "scale",
|
||||
},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: 70},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
Subresource: "scale",
|
||||
},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
Annotations: map[string]string{
|
||||
podautoscaler.HpaCustomMetricsTargetAnnotationName: "{\"items\":[{\"name\":\"qps\",\"value\":\"20\"}]}",
|
||||
},
|
||||
},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
Subresource: "scale",
|
||||
},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, successCase := range successCases {
|
||||
if errs := ValidateHorizontalPodAutoscaler(&successCase); len(errs) != 0 {
|
||||
t.Errorf("expected success: %v", errs)
|
||||
}
|
||||
}
|
||||
|
||||
errorCases := []struct {
|
||||
horizontalPodAutoscaler extensions.HorizontalPodAutoscaler
|
||||
msg string
|
||||
}{
|
||||
{
|
||||
horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{Name: "myrc", Subresource: "scale"},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: 70},
|
||||
},
|
||||
},
|
||||
msg: "scaleRef.kind: Required",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{Kind: "..", Name: "myrc", Subresource: "scale"},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: 70},
|
||||
},
|
||||
},
|
||||
msg: "scaleRef.kind: Invalid",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{Kind: "ReplicationController", Subresource: "scale"},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: 70},
|
||||
},
|
||||
},
|
||||
msg: "scaleRef.name: Required",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{Kind: "ReplicationController", Name: "..", Subresource: "scale"},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: 70},
|
||||
},
|
||||
},
|
||||
msg: "scaleRef.name: Invalid",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{Kind: "ReplicationController", Name: "myrc", Subresource: ""},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: 70},
|
||||
},
|
||||
},
|
||||
msg: "scaleRef.subresource: Required",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{Kind: "ReplicationController", Name: "myrc", Subresource: ".."},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: 70},
|
||||
},
|
||||
},
|
||||
msg: "scaleRef.subresource: Invalid",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{Kind: "ReplicationController", Name: "myrc", Subresource: "randomsubresource"},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: 70},
|
||||
},
|
||||
},
|
||||
msg: "scaleRef.subresource: Unsupported",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{
|
||||
Subresource: "scale",
|
||||
},
|
||||
MinReplicas: newInt32(-1),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
msg: "must be greater than 0",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{
|
||||
Subresource: "scale",
|
||||
},
|
||||
MinReplicas: newInt32(7),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
msg: "must be greater than or equal to `minReplicas`",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{
|
||||
Subresource: "scale",
|
||||
},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: -70},
|
||||
},
|
||||
},
|
||||
msg: "must be greater than 0",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
Annotations: map[string]string{
|
||||
podautoscaler.HpaCustomMetricsTargetAnnotationName: "broken",
|
||||
},
|
||||
},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
Subresource: "scale",
|
||||
},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
msg: "failed to parse custom metrics target annotation",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
Annotations: map[string]string{
|
||||
podautoscaler.HpaCustomMetricsTargetAnnotationName: "{}",
|
||||
},
|
||||
},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
Subresource: "scale",
|
||||
},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
msg: "custom metrics target must not be empty",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
Annotations: map[string]string{
|
||||
podautoscaler.HpaCustomMetricsTargetAnnotationName: "{\"items\":[{\"value\":\"20\"}]}",
|
||||
},
|
||||
},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
Subresource: "scale",
|
||||
},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
msg: "missing custom metric target name",
|
||||
},
|
||||
{
|
||||
horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "myautoscaler",
|
||||
Namespace: api.NamespaceDefault,
|
||||
Annotations: map[string]string{
|
||||
podautoscaler.HpaCustomMetricsTargetAnnotationName: "{\"items\":[{\"name\":\"qps\",\"value\":\"0\"}]}",
|
||||
},
|
||||
},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
Subresource: "scale",
|
||||
},
|
||||
MinReplicas: newInt32(1),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
msg: "custom metric target value must be greater than 0",
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range errorCases {
|
||||
errs := ValidateHorizontalPodAutoscaler(&c.horizontalPodAutoscaler)
|
||||
if len(errs) == 0 {
|
||||
t.Errorf("expected failure for %q", c.msg)
|
||||
} else if !strings.Contains(errs[0].Error(), c.msg) {
|
||||
t.Errorf("unexpected error: %q, expected: %q", errs[0], c.msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDaemonSetStatusUpdate(t *testing.T) {
|
||||
type dsUpdateTest struct {
|
||||
old extensions.DaemonSet
|
||||
|
@ -1709,12 +1417,6 @@ func TestValidateReplicaSet(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func newInt32(val int32) *int32 {
|
||||
p := new(int32)
|
||||
*p = val
|
||||
return p
|
||||
}
|
||||
|
||||
func TestValidatePodSecurityPolicy(t *testing.T) {
|
||||
validSCC := func() *extensions.PodSecurityPolicy {
|
||||
return &extensions.PodSecurityPolicy{
|
||||
|
|
|
@ -33,7 +33,7 @@ type AutoscalingClient struct {
|
|||
}
|
||||
|
||||
func (c *AutoscalingClient) HorizontalPodAutoscalers(namespace string) HorizontalPodAutoscalerInterface {
|
||||
return newHorizontalPodAutoscalersV1(c, namespace)
|
||||
return newHorizontalPodAutoscalers(c, namespace)
|
||||
}
|
||||
|
||||
func NewAutoscaling(c *restclient.Config) (*AutoscalingClient, error) {
|
||||
|
|
|
@ -28,7 +28,6 @@ import (
|
|||
// Features of Extensions group are not supported and may be changed or removed in
|
||||
// incompatible ways at any time.
|
||||
type ExtensionsInterface interface {
|
||||
HorizontalPodAutoscalersNamespacer
|
||||
ScaleNamespacer
|
||||
DaemonSetsNamespacer
|
||||
DeploymentsNamespacer
|
||||
|
@ -50,10 +49,6 @@ func (c *ExtensionsClient) PodSecurityPolicies() PodSecurityPolicyInterface {
|
|||
return newPodSecurityPolicy(c)
|
||||
}
|
||||
|
||||
func (c *ExtensionsClient) HorizontalPodAutoscalers(namespace string) HorizontalPodAutoscalerInterface {
|
||||
return newHorizontalPodAutoscalers(c, namespace)
|
||||
}
|
||||
|
||||
func (c *ExtensionsClient) Scales(namespace string) ScaleInterface {
|
||||
return newScales(c, namespace)
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ package unversioned
|
|||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/watch"
|
||||
)
|
||||
|
||||
|
@ -29,23 +29,23 @@ type HorizontalPodAutoscalersNamespacer interface {
|
|||
|
||||
// HorizontalPodAutoscalerInterface has methods to work with HorizontalPodAutoscaler resources.
|
||||
type HorizontalPodAutoscalerInterface interface {
|
||||
List(opts api.ListOptions) (*extensions.HorizontalPodAutoscalerList, error)
|
||||
Get(name string) (*extensions.HorizontalPodAutoscaler, error)
|
||||
List(opts api.ListOptions) (*autoscaling.HorizontalPodAutoscalerList, error)
|
||||
Get(name string) (*autoscaling.HorizontalPodAutoscaler, error)
|
||||
Delete(name string, options *api.DeleteOptions) error
|
||||
Create(horizontalPodAutoscaler *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error)
|
||||
Update(horizontalPodAutoscaler *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error)
|
||||
UpdateStatus(horizontalPodAutoscaler *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error)
|
||||
Create(horizontalPodAutoscaler *autoscaling.HorizontalPodAutoscaler) (*autoscaling.HorizontalPodAutoscaler, error)
|
||||
Update(horizontalPodAutoscaler *autoscaling.HorizontalPodAutoscaler) (*autoscaling.HorizontalPodAutoscaler, error)
|
||||
UpdateStatus(horizontalPodAutoscaler *autoscaling.HorizontalPodAutoscaler) (*autoscaling.HorizontalPodAutoscaler, error)
|
||||
Watch(opts api.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// horizontalPodAutoscalers implements HorizontalPodAutoscalersNamespacer interface
|
||||
// horizontalPodAutoscalers implements HorizontalPodAutoscalersNamespacer interface using AutoscalingClient internally
|
||||
type horizontalPodAutoscalers struct {
|
||||
client *ExtensionsClient
|
||||
client *AutoscalingClient
|
||||
ns string
|
||||
}
|
||||
|
||||
// newHorizontalPodAutoscalers returns a horizontalPodAutoscalers
|
||||
func newHorizontalPodAutoscalers(c *ExtensionsClient, namespace string) *horizontalPodAutoscalers {
|
||||
func newHorizontalPodAutoscalers(c *AutoscalingClient, namespace string) *horizontalPodAutoscalers {
|
||||
return &horizontalPodAutoscalers{
|
||||
client: c,
|
||||
ns: namespace,
|
||||
|
@ -53,15 +53,15 @@ func newHorizontalPodAutoscalers(c *ExtensionsClient, namespace string) *horizon
|
|||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of horizontalPodAutoscalers that match those selectors.
|
||||
func (c *horizontalPodAutoscalers) List(opts api.ListOptions) (result *extensions.HorizontalPodAutoscalerList, err error) {
|
||||
result = &extensions.HorizontalPodAutoscalerList{}
|
||||
func (c *horizontalPodAutoscalers) List(opts api.ListOptions) (result *autoscaling.HorizontalPodAutoscalerList, err error) {
|
||||
result = &autoscaling.HorizontalPodAutoscalerList{}
|
||||
err = c.client.Get().Namespace(c.ns).Resource("horizontalPodAutoscalers").VersionedParams(&opts, api.ParameterCodec).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Get takes the name of the horizontalPodAutoscaler, and returns the corresponding HorizontalPodAutoscaler object, and an error if it occurs
|
||||
func (c *horizontalPodAutoscalers) Get(name string) (result *extensions.HorizontalPodAutoscaler, err error) {
|
||||
result = &extensions.HorizontalPodAutoscaler{}
|
||||
func (c *horizontalPodAutoscalers) Get(name string) (result *autoscaling.HorizontalPodAutoscaler, err error) {
|
||||
result = &autoscaling.HorizontalPodAutoscaler{}
|
||||
err = c.client.Get().Namespace(c.ns).Resource("horizontalPodAutoscalers").Name(name).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
@ -72,22 +72,22 @@ func (c *horizontalPodAutoscalers) Delete(name string, options *api.DeleteOption
|
|||
}
|
||||
|
||||
// Create takes the representation of a horizontalPodAutoscaler and creates it. Returns the server's representation of the horizontalPodAutoscaler, and an error, if it occurs.
|
||||
func (c *horizontalPodAutoscalers) Create(horizontalPodAutoscaler *extensions.HorizontalPodAutoscaler) (result *extensions.HorizontalPodAutoscaler, err error) {
|
||||
result = &extensions.HorizontalPodAutoscaler{}
|
||||
func (c *horizontalPodAutoscalers) Create(horizontalPodAutoscaler *autoscaling.HorizontalPodAutoscaler) (result *autoscaling.HorizontalPodAutoscaler, err error) {
|
||||
result = &autoscaling.HorizontalPodAutoscaler{}
|
||||
err = c.client.Post().Namespace(c.ns).Resource("horizontalPodAutoscalers").Body(horizontalPodAutoscaler).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a horizontalPodAutoscaler and updates it. Returns the server's representation of the horizontalPodAutoscaler, and an error, if it occurs.
|
||||
func (c *horizontalPodAutoscalers) Update(horizontalPodAutoscaler *extensions.HorizontalPodAutoscaler) (result *extensions.HorizontalPodAutoscaler, err error) {
|
||||
result = &extensions.HorizontalPodAutoscaler{}
|
||||
func (c *horizontalPodAutoscalers) Update(horizontalPodAutoscaler *autoscaling.HorizontalPodAutoscaler) (result *autoscaling.HorizontalPodAutoscaler, err error) {
|
||||
result = &autoscaling.HorizontalPodAutoscaler{}
|
||||
err = c.client.Put().Namespace(c.ns).Resource("horizontalPodAutoscalers").Name(horizontalPodAutoscaler.Name).Body(horizontalPodAutoscaler).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatus takes the representation of a horizontalPodAutoscaler and updates it. Returns the server's representation of the horizontalPodAutoscaler, and an error, if it occurs.
|
||||
func (c *horizontalPodAutoscalers) UpdateStatus(horizontalPodAutoscaler *extensions.HorizontalPodAutoscaler) (result *extensions.HorizontalPodAutoscaler, err error) {
|
||||
result = &extensions.HorizontalPodAutoscaler{}
|
||||
func (c *horizontalPodAutoscalers) UpdateStatus(horizontalPodAutoscaler *autoscaling.HorizontalPodAutoscaler) (result *autoscaling.HorizontalPodAutoscaler, err error) {
|
||||
result = &autoscaling.HorizontalPodAutoscaler{}
|
||||
err = c.client.Put().Namespace(c.ns).Resource("horizontalPodAutoscalers").Name(horizontalPodAutoscaler.Name).SubResource("status").Body(horizontalPodAutoscaler).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
@ -101,68 +101,3 @@ func (c *horizontalPodAutoscalers) Watch(opts api.ListOptions) (watch.Interface,
|
|||
VersionedParams(&opts, api.ParameterCodec).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// horizontalPodAutoscalersV1 implements HorizontalPodAutoscalersNamespacer interface using AutoscalingClient internally
|
||||
// TODO(piosz): get back to one client implementation once HPA will be graduated to GA completely
|
||||
type horizontalPodAutoscalersV1 struct {
|
||||
client *AutoscalingClient
|
||||
ns string
|
||||
}
|
||||
|
||||
// newHorizontalPodAutoscalers returns a horizontalPodAutoscalers
|
||||
func newHorizontalPodAutoscalersV1(c *AutoscalingClient, namespace string) *horizontalPodAutoscalersV1 {
|
||||
return &horizontalPodAutoscalersV1{
|
||||
client: c,
|
||||
ns: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of horizontalPodAutoscalers that match those selectors.
|
||||
func (c *horizontalPodAutoscalersV1) List(opts api.ListOptions) (result *extensions.HorizontalPodAutoscalerList, err error) {
|
||||
result = &extensions.HorizontalPodAutoscalerList{}
|
||||
err = c.client.Get().Namespace(c.ns).Resource("horizontalPodAutoscalers").VersionedParams(&opts, api.ParameterCodec).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Get takes the name of the horizontalPodAutoscaler, and returns the corresponding HorizontalPodAutoscaler object, and an error if it occurs
|
||||
func (c *horizontalPodAutoscalersV1) Get(name string) (result *extensions.HorizontalPodAutoscaler, err error) {
|
||||
result = &extensions.HorizontalPodAutoscaler{}
|
||||
err = c.client.Get().Namespace(c.ns).Resource("horizontalPodAutoscalers").Name(name).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes the name of the horizontalPodAutoscaler and deletes it. Returns an error if one occurs.
|
||||
func (c *horizontalPodAutoscalersV1) Delete(name string, options *api.DeleteOptions) error {
|
||||
return c.client.Delete().Namespace(c.ns).Resource("horizontalPodAutoscalers").Name(name).Body(options).Do().Error()
|
||||
}
|
||||
|
||||
// Create takes the representation of a horizontalPodAutoscaler and creates it. Returns the server's representation of the horizontalPodAutoscaler, and an error, if it occurs.
|
||||
func (c *horizontalPodAutoscalersV1) Create(horizontalPodAutoscaler *extensions.HorizontalPodAutoscaler) (result *extensions.HorizontalPodAutoscaler, err error) {
|
||||
result = &extensions.HorizontalPodAutoscaler{}
|
||||
err = c.client.Post().Namespace(c.ns).Resource("horizontalPodAutoscalers").Body(horizontalPodAutoscaler).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a horizontalPodAutoscaler and updates it. Returns the server's representation of the horizontalPodAutoscaler, and an error, if it occurs.
|
||||
func (c *horizontalPodAutoscalersV1) Update(horizontalPodAutoscaler *extensions.HorizontalPodAutoscaler) (result *extensions.HorizontalPodAutoscaler, err error) {
|
||||
result = &extensions.HorizontalPodAutoscaler{}
|
||||
err = c.client.Put().Namespace(c.ns).Resource("horizontalPodAutoscalers").Name(horizontalPodAutoscaler.Name).Body(horizontalPodAutoscaler).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatus takes the representation of a horizontalPodAutoscaler and updates it. Returns the server's representation of the horizontalPodAutoscaler, and an error, if it occurs.
|
||||
func (c *horizontalPodAutoscalersV1) UpdateStatus(horizontalPodAutoscaler *extensions.HorizontalPodAutoscaler) (result *extensions.HorizontalPodAutoscaler, err error) {
|
||||
result = &extensions.HorizontalPodAutoscaler{}
|
||||
err = c.client.Put().Namespace(c.ns).Resource("horizontalPodAutoscalers").Name(horizontalPodAutoscaler.Name).SubResource("status").Body(horizontalPodAutoscaler).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested horizontalPodAutoscalers.
|
||||
func (c *horizontalPodAutoscalersV1) Watch(opts api.ListOptions) (watch.Interface, error) {
|
||||
return c.client.Get().
|
||||
Prefix("watch").
|
||||
Namespace(c.ns).
|
||||
Resource("horizontalPodAutoscalers").
|
||||
VersionedParams(&opts, api.ParameterCodec).
|
||||
Watch()
|
||||
}
|
||||
|
|
|
@ -23,8 +23,6 @@ import (
|
|||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/testclient/simple"
|
||||
)
|
||||
|
||||
|
@ -32,21 +30,9 @@ func getHorizontalPodAutoscalersResoureName() string {
|
|||
return "horizontalpodautoscalers"
|
||||
}
|
||||
|
||||
func getHPAClient(t *testing.T, c *simple.Client, ns, resourceGroup string) unversioned.HorizontalPodAutoscalerInterface {
|
||||
switch resourceGroup {
|
||||
case autoscaling.GroupName:
|
||||
return c.Setup(t).Autoscaling().HorizontalPodAutoscalers(ns)
|
||||
case extensions.GroupName:
|
||||
return c.Setup(t).Extensions().HorizontalPodAutoscalers(ns)
|
||||
default:
|
||||
t.Fatalf("Unknown group %v", resourceGroup)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func testHorizontalPodAutoscalerCreate(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
func TestHorizontalPodAutoscalerCreate(t *testing.T) {
|
||||
ns := api.NamespaceDefault
|
||||
horizontalPodAutoscaler := extensions.HorizontalPodAutoscaler{
|
||||
horizontalPodAutoscaler := autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "abc",
|
||||
Namespace: ns,
|
||||
|
@ -55,15 +41,15 @@ func testHorizontalPodAutoscalerCreate(t *testing.T, group testapi.TestGroup, re
|
|||
c := &simple.Client{
|
||||
Request: simple.Request{
|
||||
Method: "POST",
|
||||
Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, ""),
|
||||
Path: testapi.Autoscaling.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, ""),
|
||||
Query: simple.BuildQueryValues(nil),
|
||||
Body: &horizontalPodAutoscaler,
|
||||
},
|
||||
Response: simple.Response{StatusCode: 200, Body: &horizontalPodAutoscaler},
|
||||
ResourceGroup: resourceGroup,
|
||||
ResourceGroup: autoscaling.GroupName,
|
||||
}
|
||||
|
||||
response, err := getHPAClient(t, c, ns, resourceGroup).Create(&horizontalPodAutoscaler)
|
||||
response, err := c.Setup(t).Autoscaling().HorizontalPodAutoscalers(ns).Create(&horizontalPodAutoscaler)
|
||||
defer c.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
|
@ -71,14 +57,9 @@ func testHorizontalPodAutoscalerCreate(t *testing.T, group testapi.TestGroup, re
|
|||
c.Validate(t, response, err)
|
||||
}
|
||||
|
||||
func TestHorizontalPodAutoscalerCreate(t *testing.T) {
|
||||
testHorizontalPodAutoscalerCreate(t, testapi.Extensions, extensions.GroupName)
|
||||
testHorizontalPodAutoscalerCreate(t, testapi.Autoscaling, autoscaling.GroupName)
|
||||
}
|
||||
|
||||
func testHorizontalPodAutoscalerGet(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
func TestHorizontalPodAutoscalerGet(t *testing.T) {
|
||||
ns := api.NamespaceDefault
|
||||
horizontalPodAutoscaler := &extensions.HorizontalPodAutoscaler{
|
||||
horizontalPodAutoscaler := &autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "abc",
|
||||
Namespace: ns,
|
||||
|
@ -87,28 +68,23 @@ func testHorizontalPodAutoscalerGet(t *testing.T, group testapi.TestGroup, resou
|
|||
c := &simple.Client{
|
||||
Request: simple.Request{
|
||||
Method: "GET",
|
||||
Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "abc"),
|
||||
Path: testapi.Autoscaling.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "abc"),
|
||||
Query: simple.BuildQueryValues(nil),
|
||||
Body: nil,
|
||||
},
|
||||
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscaler},
|
||||
ResourceGroup: resourceGroup,
|
||||
ResourceGroup: autoscaling.GroupName,
|
||||
}
|
||||
|
||||
response, err := getHPAClient(t, c, ns, resourceGroup).Get("abc")
|
||||
response, err := c.Setup(t).Autoscaling().HorizontalPodAutoscalers(ns).Get("abc")
|
||||
defer c.Close()
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
|
||||
func TestHorizontalPodAutoscalerGet(t *testing.T) {
|
||||
testHorizontalPodAutoscalerGet(t, testapi.Extensions, extensions.GroupName)
|
||||
testHorizontalPodAutoscalerGet(t, testapi.Autoscaling, autoscaling.GroupName)
|
||||
}
|
||||
|
||||
func testHorizontalPodAutoscalerList(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
func TestHorizontalPodAutoscalerList(t *testing.T) {
|
||||
ns := api.NamespaceDefault
|
||||
horizontalPodAutoscalerList := &extensions.HorizontalPodAutoscalerList{
|
||||
Items: []extensions.HorizontalPodAutoscaler{
|
||||
horizontalPodAutoscalerList := &autoscaling.HorizontalPodAutoscalerList{
|
||||
Items: []autoscaling.HorizontalPodAutoscaler{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "foo",
|
||||
|
@ -120,50 +96,21 @@ func testHorizontalPodAutoscalerList(t *testing.T, group testapi.TestGroup, reso
|
|||
c := &simple.Client{
|
||||
Request: simple.Request{
|
||||
Method: "GET",
|
||||
Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, ""),
|
||||
Path: testapi.Autoscaling.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, ""),
|
||||
Query: simple.BuildQueryValues(nil),
|
||||
Body: nil,
|
||||
},
|
||||
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscalerList},
|
||||
ResourceGroup: resourceGroup,
|
||||
ResourceGroup: autoscaling.GroupName,
|
||||
}
|
||||
response, err := getHPAClient(t, c, ns, resourceGroup).List(api.ListOptions{})
|
||||
defer c.Close()
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
|
||||
func TestHorizontalPodAutoscalerList(t *testing.T) {
|
||||
testHorizontalPodAutoscalerList(t, testapi.Extensions, extensions.GroupName)
|
||||
testHorizontalPodAutoscalerList(t, testapi.Autoscaling, autoscaling.GroupName)
|
||||
}
|
||||
|
||||
func testHorizontalPodAutoscalerUpdate(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
ns := api.NamespaceDefault
|
||||
horizontalPodAutoscaler := &extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "abc",
|
||||
Namespace: ns,
|
||||
ResourceVersion: "1",
|
||||
},
|
||||
}
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{Method: "PUT", Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "abc"), Query: simple.BuildQueryValues(nil)},
|
||||
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscaler},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
response, err := getHPAClient(t, c, ns, resourceGroup).Update(horizontalPodAutoscaler)
|
||||
response, err := c.Setup(t).Autoscaling().HorizontalPodAutoscalers(ns).List(api.ListOptions{})
|
||||
defer c.Close()
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
|
||||
func TestHorizontalPodAutoscalerUpdate(t *testing.T) {
|
||||
testHorizontalPodAutoscalerUpdate(t, testapi.Extensions, extensions.GroupName)
|
||||
testHorizontalPodAutoscalerUpdate(t, testapi.Autoscaling, autoscaling.GroupName)
|
||||
}
|
||||
|
||||
func testHorizontalPodAutoscalerUpdateStatus(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
ns := api.NamespaceDefault
|
||||
horizontalPodAutoscaler := &extensions.HorizontalPodAutoscaler{
|
||||
horizontalPodAutoscaler := &autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "abc",
|
||||
Namespace: ns,
|
||||
|
@ -171,52 +118,56 @@ func testHorizontalPodAutoscalerUpdateStatus(t *testing.T, group testapi.TestGro
|
|||
},
|
||||
}
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{Method: "PUT", Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "abc") + "/status", Query: simple.BuildQueryValues(nil)},
|
||||
Request: simple.Request{Method: "PUT", Path: testapi.Autoscaling.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "abc"), Query: simple.BuildQueryValues(nil)},
|
||||
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscaler},
|
||||
ResourceGroup: resourceGroup,
|
||||
ResourceGroup: autoscaling.GroupName,
|
||||
}
|
||||
response, err := getHPAClient(t, c, ns, resourceGroup).UpdateStatus(horizontalPodAutoscaler)
|
||||
response, err := c.Setup(t).Autoscaling().HorizontalPodAutoscalers(ns).Update(horizontalPodAutoscaler)
|
||||
defer c.Close()
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
|
||||
func TestHorizontalPodAutoscalerUpdateStatus(t *testing.T) {
|
||||
testHorizontalPodAutoscalerUpdateStatus(t, testapi.Extensions, extensions.GroupName)
|
||||
testHorizontalPodAutoscalerUpdateStatus(t, testapi.Autoscaling, autoscaling.GroupName)
|
||||
}
|
||||
|
||||
func testHorizontalPodAutoscalerDelete(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
ns := api.NamespaceDefault
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{Method: "DELETE", Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "foo"), Query: simple.BuildQueryValues(nil)},
|
||||
Response: simple.Response{StatusCode: 200},
|
||||
ResourceGroup: resourceGroup,
|
||||
horizontalPodAutoscaler := &autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "abc",
|
||||
Namespace: ns,
|
||||
ResourceVersion: "1",
|
||||
},
|
||||
}
|
||||
err := getHPAClient(t, c, ns, resourceGroup).Delete("foo", nil)
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{Method: "PUT", Path: testapi.Autoscaling.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "abc") + "/status", Query: simple.BuildQueryValues(nil)},
|
||||
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscaler},
|
||||
ResourceGroup: autoscaling.GroupName,
|
||||
}
|
||||
response, err := c.Setup(t).Autoscaling().HorizontalPodAutoscalers(ns).UpdateStatus(horizontalPodAutoscaler)
|
||||
defer c.Close()
|
||||
c.Validate(t, nil, err)
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
|
||||
func TestHorizontalPodAutoscalerDelete(t *testing.T) {
|
||||
testHorizontalPodAutoscalerDelete(t, testapi.Extensions, extensions.GroupName)
|
||||
testHorizontalPodAutoscalerDelete(t, testapi.Autoscaling, autoscaling.GroupName)
|
||||
}
|
||||
|
||||
func testHorizontalPodAutoscalerWatch(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
ns := api.NamespaceDefault
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{
|
||||
Method: "GET",
|
||||
Path: group.ResourcePathWithPrefix("watch", getHorizontalPodAutoscalersResoureName(), "", ""),
|
||||
Query: url.Values{"resourceVersion": []string{}}},
|
||||
Request: simple.Request{Method: "DELETE", Path: testapi.Autoscaling.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "foo"), Query: simple.BuildQueryValues(nil)},
|
||||
Response: simple.Response{StatusCode: 200},
|
||||
ResourceGroup: resourceGroup,
|
||||
ResourceGroup: autoscaling.GroupName,
|
||||
}
|
||||
_, err := getHPAClient(t, c, api.NamespaceAll, resourceGroup).Watch(api.ListOptions{})
|
||||
err := c.Setup(t).Autoscaling().HorizontalPodAutoscalers(ns).Delete("foo", nil)
|
||||
defer c.Close()
|
||||
c.Validate(t, nil, err)
|
||||
}
|
||||
|
||||
func TestHorizontalPodAutoscalerWatch(t *testing.T) {
|
||||
testHorizontalPodAutoscalerWatch(t, testapi.Extensions, extensions.GroupName)
|
||||
testHorizontalPodAutoscalerWatch(t, testapi.Autoscaling, autoscaling.GroupName)
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{
|
||||
Method: "GET",
|
||||
Path: testapi.Autoscaling.ResourcePathWithPrefix("watch", getHorizontalPodAutoscalersResoureName(), "", ""),
|
||||
Query: url.Values{"resourceVersion": []string{}}},
|
||||
Response: simple.Response{StatusCode: 200},
|
||||
ResourceGroup: autoscaling.GroupName,
|
||||
}
|
||||
_, err := c.Setup(t).Autoscaling().HorizontalPodAutoscalers(api.NamespaceAll).Watch(api.ListOptions{})
|
||||
defer c.Close()
|
||||
c.Validate(t, nil, err)
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ package testclient
|
|||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/watch"
|
||||
)
|
||||
|
@ -26,21 +26,21 @@ import (
|
|||
// FakeHorizontalPodAutoscalers implements HorizontalPodAutoscalerInterface. Meant to be embedded into a struct to get a default
|
||||
// implementation. This makes faking out just the methods you want to test easier.
|
||||
type FakeHorizontalPodAutoscalers struct {
|
||||
Fake *FakeExperimental
|
||||
Fake *FakeAutoscaling
|
||||
Namespace string
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalers) Get(name string) (*extensions.HorizontalPodAutoscaler, error) {
|
||||
obj, err := c.Fake.Invokes(NewGetAction("horizontalpodautoscalers", c.Namespace, name), &extensions.HorizontalPodAutoscaler{})
|
||||
func (c *FakeHorizontalPodAutoscalers) Get(name string) (*autoscaling.HorizontalPodAutoscaler, error) {
|
||||
obj, err := c.Fake.Invokes(NewGetAction("horizontalpodautoscalers", c.Namespace, name), &autoscaling.HorizontalPodAutoscaler{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*extensions.HorizontalPodAutoscaler), err
|
||||
return obj.(*autoscaling.HorizontalPodAutoscaler), err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalers) List(opts api.ListOptions) (*extensions.HorizontalPodAutoscalerList, error) {
|
||||
obj, err := c.Fake.Invokes(NewListAction("horizontalpodautoscalers", c.Namespace, opts), &extensions.HorizontalPodAutoscalerList{})
|
||||
func (c *FakeHorizontalPodAutoscalers) List(opts api.ListOptions) (*autoscaling.HorizontalPodAutoscalerList, error) {
|
||||
obj, err := c.Fake.Invokes(NewListAction("horizontalpodautoscalers", c.Namespace, opts), &autoscaling.HorizontalPodAutoscalerList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -48,8 +48,8 @@ func (c *FakeHorizontalPodAutoscalers) List(opts api.ListOptions) (*extensions.H
|
|||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &extensions.HorizontalPodAutoscalerList{}
|
||||
for _, a := range obj.(*extensions.HorizontalPodAutoscalerList).Items {
|
||||
list := &autoscaling.HorizontalPodAutoscalerList{}
|
||||
for _, a := range obj.(*autoscaling.HorizontalPodAutoscalerList).Items {
|
||||
if label.Matches(labels.Set(a.Labels)) {
|
||||
list.Items = append(list.Items, a)
|
||||
}
|
||||
|
@ -57,108 +57,37 @@ func (c *FakeHorizontalPodAutoscalers) List(opts api.ListOptions) (*extensions.H
|
|||
return list, err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalers) Create(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) {
|
||||
func (c *FakeHorizontalPodAutoscalers) Create(a *autoscaling.HorizontalPodAutoscaler) (*autoscaling.HorizontalPodAutoscaler, error) {
|
||||
obj, err := c.Fake.Invokes(NewCreateAction("horizontalpodautoscalers", c.Namespace, a), a)
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*extensions.HorizontalPodAutoscaler), err
|
||||
return obj.(*autoscaling.HorizontalPodAutoscaler), err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalers) Update(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) {
|
||||
func (c *FakeHorizontalPodAutoscalers) Update(a *autoscaling.HorizontalPodAutoscaler) (*autoscaling.HorizontalPodAutoscaler, error) {
|
||||
obj, err := c.Fake.Invokes(NewUpdateAction("horizontalpodautoscalers", c.Namespace, a), a)
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*extensions.HorizontalPodAutoscaler), err
|
||||
return obj.(*autoscaling.HorizontalPodAutoscaler), err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalers) UpdateStatus(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) {
|
||||
obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("horizontalpodautoscalers", "status", c.Namespace, a), &extensions.HorizontalPodAutoscaler{})
|
||||
func (c *FakeHorizontalPodAutoscalers) UpdateStatus(a *autoscaling.HorizontalPodAutoscaler) (*autoscaling.HorizontalPodAutoscaler, error) {
|
||||
obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("horizontalpodautoscalers", "status", c.Namespace, a), &autoscaling.HorizontalPodAutoscaler{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*extensions.HorizontalPodAutoscaler), err
|
||||
return obj.(*autoscaling.HorizontalPodAutoscaler), err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalers) Delete(name string, options *api.DeleteOptions) error {
|
||||
_, err := c.Fake.Invokes(NewDeleteAction("horizontalpodautoscalers", c.Namespace, name), &extensions.HorizontalPodAutoscaler{})
|
||||
_, err := c.Fake.Invokes(NewDeleteAction("horizontalpodautoscalers", c.Namespace, name), &autoscaling.HorizontalPodAutoscaler{})
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalers) Watch(opts api.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.InvokesWatch(NewWatchAction("horizontalpodautoscalers", c.Namespace, opts))
|
||||
}
|
||||
|
||||
// FakeHorizontalPodAutoscalers implements HorizontalPodAutoscalerInterface. Meant to be embedded into a struct to get a default
|
||||
// implementation. This makes faking out just the methods you want to test easier.
|
||||
// This is a test implementation of HorizontalPodAutoscalersV1
|
||||
// TODO(piosz): get back to one client implementation once HPA will be graduated to GA completely
|
||||
type FakeHorizontalPodAutoscalersV1 struct {
|
||||
Fake *FakeAutoscaling
|
||||
Namespace string
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalersV1) Get(name string) (*extensions.HorizontalPodAutoscaler, error) {
|
||||
obj, err := c.Fake.Invokes(NewGetAction("horizontalpodautoscalers", c.Namespace, name), &extensions.HorizontalPodAutoscaler{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*extensions.HorizontalPodAutoscaler), err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalersV1) List(opts api.ListOptions) (*extensions.HorizontalPodAutoscalerList, error) {
|
||||
obj, err := c.Fake.Invokes(NewListAction("horizontalpodautoscalers", c.Namespace, opts), &extensions.HorizontalPodAutoscalerList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
label := opts.LabelSelector
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &extensions.HorizontalPodAutoscalerList{}
|
||||
for _, a := range obj.(*extensions.HorizontalPodAutoscalerList).Items {
|
||||
if label.Matches(labels.Set(a.Labels)) {
|
||||
list.Items = append(list.Items, a)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalersV1) Create(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) {
|
||||
obj, err := c.Fake.Invokes(NewCreateAction("horizontalpodautoscalers", c.Namespace, a), a)
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*extensions.HorizontalPodAutoscaler), err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalersV1) Update(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) {
|
||||
obj, err := c.Fake.Invokes(NewUpdateAction("horizontalpodautoscalers", c.Namespace, a), a)
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*extensions.HorizontalPodAutoscaler), err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalersV1) UpdateStatus(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) {
|
||||
obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("horizontalpodautoscalers", "status", c.Namespace, a), &extensions.HorizontalPodAutoscaler{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*extensions.HorizontalPodAutoscaler), err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalersV1) Delete(name string, options *api.DeleteOptions) error {
|
||||
_, err := c.Fake.Invokes(NewDeleteAction("horizontalpodautoscalers", c.Namespace, name), &extensions.HorizontalPodAutoscaler{})
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalersV1) Watch(opts api.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.InvokesWatch(NewWatchAction("horizontalpodautoscalers", c.Namespace, opts))
|
||||
}
|
||||
|
|
|
@ -325,7 +325,7 @@ type FakeAutoscaling struct {
|
|||
}
|
||||
|
||||
func (c *FakeAutoscaling) HorizontalPodAutoscalers(namespace string) client.HorizontalPodAutoscalerInterface {
|
||||
return &FakeHorizontalPodAutoscalersV1{Fake: c, Namespace: namespace}
|
||||
return &FakeHorizontalPodAutoscalers{Fake: c, Namespace: namespace}
|
||||
}
|
||||
|
||||
// NewSimpleFakeBatch returns a client that will respond with the provided objects
|
||||
|
@ -354,10 +354,6 @@ func (c *FakeExperimental) DaemonSets(namespace string) client.DaemonSetInterfac
|
|||
return &FakeDaemonSets{Fake: c, Namespace: namespace}
|
||||
}
|
||||
|
||||
func (c *FakeExperimental) HorizontalPodAutoscalers(namespace string) client.HorizontalPodAutoscalerInterface {
|
||||
return &FakeHorizontalPodAutoscalers{Fake: c, Namespace: namespace}
|
||||
}
|
||||
|
||||
func (c *FakeExperimental) Deployments(namespace string) client.DeploymentInterface {
|
||||
return &FakeDeployments{Fake: c, Namespace: namespace}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,10 @@ import (
|
|||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/client/cache"
|
||||
unversionedautoscaling "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/autoscaling/unversioned"
|
||||
unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned"
|
||||
unversionedextensions "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned"
|
||||
"k8s.io/kubernetes/pkg/client/record"
|
||||
|
@ -51,7 +53,7 @@ const (
|
|||
|
||||
type HorizontalController struct {
|
||||
scaleNamespacer unversionedextensions.ScalesGetter
|
||||
hpaNamespacer unversionedextensions.HorizontalPodAutoscalersGetter
|
||||
hpaNamespacer unversionedautoscaling.HorizontalPodAutoscalersGetter
|
||||
|
||||
metricsClient metrics.MetricsClient
|
||||
eventRecorder record.EventRecorder
|
||||
|
@ -75,12 +77,12 @@ func newInformer(controller *HorizontalController, resyncPeriod time.Duration) (
|
|||
return controller.hpaNamespacer.HorizontalPodAutoscalers(api.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&extensions.HorizontalPodAutoscaler{},
|
||||
&autoscaling.HorizontalPodAutoscaler{},
|
||||
resyncPeriod,
|
||||
framework.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
hpa := obj.(*extensions.HorizontalPodAutoscaler)
|
||||
hasCPUPolicy := hpa.Spec.CPUUtilization != nil
|
||||
hpa := obj.(*autoscaling.HorizontalPodAutoscaler)
|
||||
hasCPUPolicy := hpa.Spec.TargetCPUUtilizationPercentage != nil
|
||||
_, hasCustomMetricsPolicy := hpa.Annotations[HpaCustomMetricsTargetAnnotationName]
|
||||
if !hasCPUPolicy && !hasCustomMetricsPolicy {
|
||||
controller.eventRecorder.Event(hpa, api.EventTypeNormal, "DefaultPolicy", "No scaling policy specified - will use default one. See documentation for details")
|
||||
|
@ -91,7 +93,7 @@ func newInformer(controller *HorizontalController, resyncPeriod time.Duration) (
|
|||
}
|
||||
},
|
||||
UpdateFunc: func(old, cur interface{}) {
|
||||
hpa := cur.(*extensions.HorizontalPodAutoscaler)
|
||||
hpa := cur.(*autoscaling.HorizontalPodAutoscaler)
|
||||
err := controller.reconcileAutoscaler(hpa)
|
||||
if err != nil {
|
||||
glog.Warningf("Failed to reconcile %s: %v", hpa.Name, err)
|
||||
|
@ -102,7 +104,7 @@ func newInformer(controller *HorizontalController, resyncPeriod time.Duration) (
|
|||
)
|
||||
}
|
||||
|
||||
func NewHorizontalController(evtNamespacer unversionedcore.EventsGetter, scaleNamespacer unversionedextensions.ScalesGetter, hpaNamespacer unversionedextensions.HorizontalPodAutoscalersGetter, metricsClient metrics.MetricsClient, resyncPeriod time.Duration) *HorizontalController {
|
||||
func NewHorizontalController(evtNamespacer unversionedcore.EventsGetter, scaleNamespacer unversionedextensions.ScalesGetter, hpaNamespacer unversionedautoscaling.HorizontalPodAutoscalersGetter, metricsClient metrics.MetricsClient, resyncPeriod time.Duration) *HorizontalController {
|
||||
broadcaster := record.NewBroadcaster()
|
||||
broadcaster.StartRecordingToSink(&unversionedcore.EventSinkImpl{Interface: evtNamespacer.Events("")})
|
||||
recorder := broadcaster.NewRecorder(api.EventSource{Component: "horizontal-pod-autoscaler"})
|
||||
|
@ -128,10 +130,10 @@ func (a *HorizontalController) Run(stopCh <-chan struct{}) {
|
|||
glog.Infof("Shutting down HPA Controller")
|
||||
}
|
||||
|
||||
func (a *HorizontalController) computeReplicasForCPUUtilization(hpa *extensions.HorizontalPodAutoscaler, scale *extensions.Scale) (int32, *int32, time.Time, error) {
|
||||
func (a *HorizontalController) computeReplicasForCPUUtilization(hpa *autoscaling.HorizontalPodAutoscaler, scale *extensions.Scale) (int32, *int32, time.Time, error) {
|
||||
targetUtilization := int32(defaultTargetCPUUtilizationPercentage)
|
||||
if hpa.Spec.CPUUtilization != nil {
|
||||
targetUtilization = hpa.Spec.CPUUtilization.TargetPercentage
|
||||
if hpa.Spec.TargetCPUUtilizationPercentage != nil {
|
||||
targetUtilization = *hpa.Spec.TargetCPUUtilizationPercentage
|
||||
}
|
||||
currentReplicas := scale.Status.Replicas
|
||||
|
||||
|
@ -170,7 +172,7 @@ func (a *HorizontalController) computeReplicasForCPUUtilization(hpa *extensions.
|
|||
// Returns number of replicas, metric which required highest number of replicas,
|
||||
// status string (also json-serialized extensions.CustomMetricsCurrentStatusList),
|
||||
// last timestamp of the metrics involved in computations or error, if occurred.
|
||||
func (a *HorizontalController) computeReplicasForCustomMetrics(hpa *extensions.HorizontalPodAutoscaler, scale *extensions.Scale,
|
||||
func (a *HorizontalController) computeReplicasForCustomMetrics(hpa *autoscaling.HorizontalPodAutoscaler, scale *extensions.Scale,
|
||||
cmAnnotation string) (replicas int32, metric string, status string, timestamp time.Time, err error) {
|
||||
|
||||
currentReplicas := scale.Status.Replicas
|
||||
|
@ -246,10 +248,10 @@ func (a *HorizontalController) computeReplicasForCustomMetrics(hpa *extensions.H
|
|||
return replicas, metric, string(byteStatusList), timestamp, nil
|
||||
}
|
||||
|
||||
func (a *HorizontalController) reconcileAutoscaler(hpa *extensions.HorizontalPodAutoscaler) error {
|
||||
reference := fmt.Sprintf("%s/%s/%s", hpa.Spec.ScaleRef.Kind, hpa.Namespace, hpa.Spec.ScaleRef.Name)
|
||||
func (a *HorizontalController) reconcileAutoscaler(hpa *autoscaling.HorizontalPodAutoscaler) error {
|
||||
reference := fmt.Sprintf("%s/%s/%s", hpa.Spec.ScaleTargetRef.Kind, hpa.Namespace, hpa.Spec.ScaleTargetRef.Name)
|
||||
|
||||
scale, err := a.scaleNamespacer.Scales(hpa.Namespace).Get(hpa.Spec.ScaleRef.Kind, hpa.Spec.ScaleRef.Name)
|
||||
scale, err := a.scaleNamespacer.Scales(hpa.Namespace).Get(hpa.Spec.ScaleTargetRef.Kind, hpa.Spec.ScaleTargetRef.Name)
|
||||
if err != nil {
|
||||
a.eventRecorder.Event(hpa, api.EventTypeWarning, "FailedGetScale", err.Error())
|
||||
return fmt.Errorf("failed to query scale subresource for %s: %v", reference, err)
|
||||
|
@ -282,7 +284,7 @@ func (a *HorizontalController) reconcileAutoscaler(hpa *extensions.HorizontalPod
|
|||
// All basic scenarios covered, the state should be sane, lets use metrics.
|
||||
cmAnnotation, cmAnnotationFound := hpa.Annotations[HpaCustomMetricsTargetAnnotationName]
|
||||
|
||||
if hpa.Spec.CPUUtilization != nil || !cmAnnotationFound {
|
||||
if hpa.Spec.TargetCPUUtilizationPercentage != nil || !cmAnnotationFound {
|
||||
cpuDesiredReplicas, cpuCurrentUtilization, cpuTimestamp, err = a.computeReplicasForCPUUtilization(hpa, scale)
|
||||
if err != nil {
|
||||
a.updateCurrentReplicasInStatus(hpa, currentReplicas)
|
||||
|
@ -334,7 +336,7 @@ func (a *HorizontalController) reconcileAutoscaler(hpa *extensions.HorizontalPod
|
|||
rescale := shouldScale(hpa, currentReplicas, desiredReplicas, timestamp)
|
||||
if rescale {
|
||||
scale.Spec.Replicas = desiredReplicas
|
||||
_, err = a.scaleNamespacer.Scales(hpa.Namespace).Update(hpa.Spec.ScaleRef.Kind, scale)
|
||||
_, err = a.scaleNamespacer.Scales(hpa.Namespace).Update(hpa.Spec.ScaleTargetRef.Kind, scale)
|
||||
if err != nil {
|
||||
a.eventRecorder.Eventf(hpa, api.EventTypeWarning, "FailedRescale", "New size: %d; reason: %s; error: %v", desiredReplicas, rescaleReason, err.Error())
|
||||
return fmt.Errorf("failed to rescale %s: %v", reference, err)
|
||||
|
@ -349,7 +351,7 @@ func (a *HorizontalController) reconcileAutoscaler(hpa *extensions.HorizontalPod
|
|||
return a.updateStatus(hpa, currentReplicas, desiredReplicas, cpuCurrentUtilization, cmStatus, rescale)
|
||||
}
|
||||
|
||||
func shouldScale(hpa *extensions.HorizontalPodAutoscaler, currentReplicas, desiredReplicas int32, timestamp time.Time) bool {
|
||||
func shouldScale(hpa *autoscaling.HorizontalPodAutoscaler, currentReplicas, desiredReplicas int32, timestamp time.Time) bool {
|
||||
if desiredReplicas != currentReplicas {
|
||||
// Going down only if the usageRatio dropped significantly below the target
|
||||
// and there was no rescaling in the last downscaleForbiddenWindow.
|
||||
|
@ -370,15 +372,15 @@ func shouldScale(hpa *extensions.HorizontalPodAutoscaler, currentReplicas, desir
|
|||
return false
|
||||
}
|
||||
|
||||
func (a *HorizontalController) updateCurrentReplicasInStatus(hpa *extensions.HorizontalPodAutoscaler, currentReplicas int32) {
|
||||
func (a *HorizontalController) updateCurrentReplicasInStatus(hpa *autoscaling.HorizontalPodAutoscaler, currentReplicas int32) {
|
||||
err := a.updateStatus(hpa, currentReplicas, hpa.Status.DesiredReplicas, hpa.Status.CurrentCPUUtilizationPercentage, hpa.Annotations[HpaCustomMetricsStatusAnnotationName], false)
|
||||
if err != nil {
|
||||
glog.Errorf("%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *HorizontalController) updateStatus(hpa *extensions.HorizontalPodAutoscaler, currentReplicas, desiredReplicas int32, cpuCurrentUtilization *int32, cmStatus string, rescale bool) error {
|
||||
hpa.Status = extensions.HorizontalPodAutoscalerStatus{
|
||||
func (a *HorizontalController) updateStatus(hpa *autoscaling.HorizontalPodAutoscaler, currentReplicas, desiredReplicas int32, cpuCurrentUtilization *int32, cmStatus string, rescale bool) error {
|
||||
hpa.Status = autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: currentReplicas,
|
||||
DesiredReplicas: desiredReplicas,
|
||||
CurrentCPUUtilizationPercentage: cpuCurrentUtilization,
|
||||
|
|
|
@ -28,6 +28,7 @@ import (
|
|||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
_ "k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned"
|
||||
|
@ -138,25 +139,24 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
|
|||
tc.Lock()
|
||||
defer tc.Unlock()
|
||||
|
||||
obj := &extensions.HorizontalPodAutoscalerList{
|
||||
Items: []extensions.HorizontalPodAutoscaler{
|
||||
obj := &autoscaling.HorizontalPodAutoscalerList{
|
||||
Items: []autoscaling.HorizontalPodAutoscaler{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: hpaName,
|
||||
Namespace: namespace,
|
||||
SelfLink: "experimental/v1/namespaces/" + namespace + "/horizontalpodautoscalers/" + hpaName,
|
||||
},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{
|
||||
Kind: tc.resource.kind,
|
||||
Name: tc.resource.name,
|
||||
APIVersion: tc.resource.apiVersion,
|
||||
Subresource: "scale",
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Kind: tc.resource.kind,
|
||||
Name: tc.resource.name,
|
||||
APIVersion: tc.resource.apiVersion,
|
||||
},
|
||||
MinReplicas: &tc.minReplicas,
|
||||
MaxReplicas: tc.maxReplicas,
|
||||
},
|
||||
Status: extensions.HorizontalPodAutoscalerStatus{
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: tc.initialReplicas,
|
||||
DesiredReplicas: tc.initialReplicas,
|
||||
},
|
||||
|
@ -165,7 +165,7 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
|
|||
}
|
||||
|
||||
if tc.CPUTarget > 0.0 {
|
||||
obj.Items[0].Spec.CPUUtilization = &extensions.CPUTargetUtilization{TargetPercentage: tc.CPUTarget}
|
||||
obj.Items[0].Spec.TargetCPUUtilizationPercentage = &tc.CPUTarget
|
||||
}
|
||||
if tc.cmTarget != nil {
|
||||
b, err := json.Marshal(tc.cmTarget)
|
||||
|
@ -327,7 +327,7 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
|
|||
tc.Lock()
|
||||
defer tc.Unlock()
|
||||
|
||||
obj := action.(core.UpdateAction).GetObject().(*extensions.HorizontalPodAutoscaler)
|
||||
obj := action.(core.UpdateAction).GetObject().(*autoscaling.HorizontalPodAutoscaler)
|
||||
assert.Equal(t, namespace, obj.Namespace)
|
||||
assert.Equal(t, hpaName, obj.Name)
|
||||
assert.Equal(t, tc.desiredReplicas, obj.Status.DesiredReplicas)
|
||||
|
@ -383,7 +383,7 @@ func (tc *testCase) runTest(t *testing.T) {
|
|||
metricsClient: metricsClient,
|
||||
eventRecorder: recorder,
|
||||
scaleNamespacer: testClient.Extensions(),
|
||||
hpaNamespacer: testClient.Extensions(),
|
||||
hpaNamespacer: testClient.Autoscaling(),
|
||||
}
|
||||
|
||||
store, frameworkController := newInformer(hpaController, time.Minute)
|
||||
|
|
|
@ -21,7 +21,7 @@ import (
|
|||
"strconv"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
|
@ -86,16 +86,15 @@ func (HorizontalPodAutoscalerV1Beta1) Generate(genericParams map[string]interfac
|
|||
}
|
||||
}
|
||||
|
||||
scaler := extensions.HorizontalPodAutoscaler{
|
||||
scaler := autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{
|
||||
Kind: params["scaleRef-kind"],
|
||||
Name: params["scaleRef-name"],
|
||||
APIVersion: params["scaleRef-apiVersion"],
|
||||
Subresource: scaleSubResource,
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Kind: params["scaleRef-kind"],
|
||||
Name: params["scaleRef-name"],
|
||||
APIVersion: params["scaleRef-apiVersion"],
|
||||
},
|
||||
MaxReplicas: int32(max),
|
||||
},
|
||||
|
@ -105,7 +104,8 @@ func (HorizontalPodAutoscalerV1Beta1) Generate(genericParams map[string]interfac
|
|||
scaler.Spec.MinReplicas = &v
|
||||
}
|
||||
if cpu >= 0 {
|
||||
scaler.Spec.CPUUtilization = &extensions.CPUTargetUtilization{TargetPercentage: int32(cpu)}
|
||||
c := int32(cpu)
|
||||
scaler.Spec.TargetCPUUtilizationPercentage = &c
|
||||
}
|
||||
return &scaler, nil
|
||||
}
|
||||
|
|
|
@ -1710,7 +1710,7 @@ type HorizontalPodAutoscalerDescriber struct {
|
|||
}
|
||||
|
||||
func (d *HorizontalPodAutoscalerDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) {
|
||||
hpa, err := d.client.Extensions().HorizontalPodAutoscalers(namespace).Get(name)
|
||||
hpa, err := d.client.Autoscaling().HorizontalPodAutoscalers(namespace).Get(name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -1720,12 +1720,11 @@ func (d *HorizontalPodAutoscalerDescriber) Describe(namespace, name string, desc
|
|||
printLabelsMultiline(out, "Labels", hpa.Labels)
|
||||
printLabelsMultiline(out, "Annotations", hpa.Annotations)
|
||||
fmt.Fprintf(out, "CreationTimestamp:\t%s\n", hpa.CreationTimestamp.Time.Format(time.RFC1123Z))
|
||||
fmt.Fprintf(out, "Reference:\t%s/%s/%s\n",
|
||||
hpa.Spec.ScaleRef.Kind,
|
||||
hpa.Spec.ScaleRef.Name,
|
||||
hpa.Spec.ScaleRef.Subresource)
|
||||
if hpa.Spec.CPUUtilization != nil {
|
||||
fmt.Fprintf(out, "Target CPU utilization:\t%d%%\n", hpa.Spec.CPUUtilization.TargetPercentage)
|
||||
fmt.Fprintf(out, "Reference:\t%s/%s\n",
|
||||
hpa.Spec.ScaleTargetRef.Kind,
|
||||
hpa.Spec.ScaleTargetRef.Name)
|
||||
if hpa.Spec.TargetCPUUtilizationPercentage != nil {
|
||||
fmt.Fprintf(out, "Target CPU utilization:\t%d%%\n", *hpa.Spec.TargetCPUUtilizationPercentage)
|
||||
fmt.Fprintf(out, "Current CPU utilization:\t")
|
||||
if hpa.Status.CurrentCPUUtilizationPercentage != nil {
|
||||
fmt.Fprintf(out, "%d%%\n", *hpa.Status.CurrentCPUUtilizationPercentage)
|
||||
|
@ -1741,9 +1740,9 @@ func (d *HorizontalPodAutoscalerDescriber) Describe(namespace, name string, desc
|
|||
fmt.Fprintf(out, "Max replicas:\t%d\n", hpa.Spec.MaxReplicas)
|
||||
|
||||
// TODO: switch to scale subresource once the required code is submitted.
|
||||
if strings.ToLower(hpa.Spec.ScaleRef.Kind) == "replicationcontroller" {
|
||||
if strings.ToLower(hpa.Spec.ScaleTargetRef.Kind) == "replicationcontroller" {
|
||||
fmt.Fprintf(out, "ReplicationController pods:\t")
|
||||
rc, err := d.client.ReplicationControllers(hpa.Namespace).Get(hpa.Spec.ScaleRef.Name)
|
||||
rc, err := d.client.ReplicationControllers(hpa.Namespace).Get(hpa.Spec.ScaleTargetRef.Name)
|
||||
if err == nil {
|
||||
fmt.Fprintf(out, "%d current / %d desired\n", rc.Status.Replicas, rc.Spec.Replicas)
|
||||
} else {
|
||||
|
|
|
@ -36,6 +36,7 @@ import (
|
|||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
|
@ -1607,16 +1608,15 @@ func printDeploymentList(list *extensions.DeploymentList, w io.Writer, options P
|
|||
return nil
|
||||
}
|
||||
|
||||
func printHorizontalPodAutoscaler(hpa *extensions.HorizontalPodAutoscaler, w io.Writer, options PrintOptions) error {
|
||||
func printHorizontalPodAutoscaler(hpa *autoscaling.HorizontalPodAutoscaler, w io.Writer, options PrintOptions) error {
|
||||
namespace := hpa.Namespace
|
||||
name := hpa.Name
|
||||
reference := fmt.Sprintf("%s/%s/%s",
|
||||
hpa.Spec.ScaleRef.Kind,
|
||||
hpa.Spec.ScaleRef.Name,
|
||||
hpa.Spec.ScaleRef.Subresource)
|
||||
reference := fmt.Sprintf("%s/%s",
|
||||
hpa.Spec.ScaleTargetRef.Kind,
|
||||
hpa.Spec.ScaleTargetRef.Name)
|
||||
target := "<unset>"
|
||||
if hpa.Spec.CPUUtilization != nil {
|
||||
target = fmt.Sprintf("%d%%", hpa.Spec.CPUUtilization.TargetPercentage)
|
||||
if hpa.Spec.TargetCPUUtilizationPercentage != nil {
|
||||
target = fmt.Sprintf("%d%%", *hpa.Spec.TargetCPUUtilizationPercentage)
|
||||
}
|
||||
current := "<waiting>"
|
||||
if hpa.Status.CurrentCPUUtilizationPercentage != nil {
|
||||
|
@ -1651,7 +1651,7 @@ func printHorizontalPodAutoscaler(hpa *extensions.HorizontalPodAutoscaler, w io.
|
|||
return err
|
||||
}
|
||||
|
||||
func printHorizontalPodAutoscalerList(list *extensions.HorizontalPodAutoscalerList, w io.Writer, options PrintOptions) error {
|
||||
func printHorizontalPodAutoscalerList(list *autoscaling.HorizontalPodAutoscalerList, w io.Writer, options PrintOptions) error {
|
||||
for i := range list.Items {
|
||||
if err := printHorizontalPodAutoscaler(&list.Items[i], w, options); err != nil {
|
||||
return err
|
||||
|
|
|
@ -18,7 +18,7 @@ package etcd
|
|||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/registry/cachesize"
|
||||
|
@ -36,12 +36,12 @@ type REST struct {
|
|||
func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
||||
prefix := "/horizontalpodautoscalers"
|
||||
|
||||
newListFunc := func() runtime.Object { return &extensions.HorizontalPodAutoscalerList{} }
|
||||
newListFunc := func() runtime.Object { return &autoscaling.HorizontalPodAutoscalerList{} }
|
||||
storageInterface := opts.Decorator(
|
||||
opts.Storage, cachesize.GetWatchCacheSizeByResource(cachesize.HorizontalPodAutoscalers), &extensions.HorizontalPodAutoscaler{}, prefix, horizontalpodautoscaler.Strategy, newListFunc)
|
||||
opts.Storage, cachesize.GetWatchCacheSizeByResource(cachesize.HorizontalPodAutoscalers), &autoscaling.HorizontalPodAutoscaler{}, prefix, horizontalpodautoscaler.Strategy, newListFunc)
|
||||
|
||||
store := ®istry.Store{
|
||||
NewFunc: func() runtime.Object { return &extensions.HorizontalPodAutoscaler{} },
|
||||
NewFunc: func() runtime.Object { return &autoscaling.HorizontalPodAutoscaler{} },
|
||||
// NewListFunc returns an object capable of storing results of an etcd list.
|
||||
NewListFunc: newListFunc,
|
||||
// Produces a path that etcd understands, to the root of the resource
|
||||
|
@ -56,13 +56,13 @@ func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
|||
},
|
||||
// Retrieve the name field of an autoscaler
|
||||
ObjectNameFunc: func(obj runtime.Object) (string, error) {
|
||||
return obj.(*extensions.HorizontalPodAutoscaler).Name, nil
|
||||
return obj.(*autoscaling.HorizontalPodAutoscaler).Name, nil
|
||||
},
|
||||
// Used to match objects based on labels/fields for list
|
||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||
return horizontalpodautoscaler.MatchAutoscaler(label, field)
|
||||
},
|
||||
QualifiedResource: extensions.Resource("horizontalpodautoscalers"),
|
||||
QualifiedResource: autoscaling.Resource("horizontalpodautoscalers"),
|
||||
DeleteCollectionWorkers: opts.DeleteCollectionWorkers,
|
||||
|
||||
// Used to validate autoscaler creation
|
||||
|
@ -85,7 +85,7 @@ type StatusREST struct {
|
|||
}
|
||||
|
||||
func (r *StatusREST) New() runtime.Object {
|
||||
return &extensions.HorizontalPodAutoscaler{}
|
||||
return &autoscaling.HorizontalPodAutoscaler{}
|
||||
}
|
||||
|
||||
// Update alters the status subset of an object.
|
||||
|
|
|
@ -20,9 +20,9 @@ import (
|
|||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
// Ensure that extensions/v1beta1 package is initialized.
|
||||
_ "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
// Ensure that autoscaling/v1 package is initialized.
|
||||
_ "k8s.io/kubernetes/pkg/apis/autoscaling/v1"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/registry/generic"
|
||||
|
@ -32,26 +32,26 @@ import (
|
|||
)
|
||||
|
||||
func newStorage(t *testing.T) (*REST, *StatusREST, *etcdtesting.EtcdTestServer) {
|
||||
etcdStorage, server := registrytest.NewEtcdStorage(t, extensions.GroupName)
|
||||
etcdStorage, server := registrytest.NewEtcdStorage(t, autoscaling.GroupName)
|
||||
restOptions := generic.RESTOptions{Storage: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1}
|
||||
horizontalPodAutoscalerStorage, statusStorage := NewREST(restOptions)
|
||||
return horizontalPodAutoscalerStorage, statusStorage, server
|
||||
}
|
||||
|
||||
func validNewHorizontalPodAutoscaler(name string) *extensions.HorizontalPodAutoscaler {
|
||||
return &extensions.HorizontalPodAutoscaler{
|
||||
func validNewHorizontalPodAutoscaler(name string) *autoscaling.HorizontalPodAutoscaler {
|
||||
cpu := int32(70)
|
||||
return &autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: api.NamespaceDefault,
|
||||
},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
Subresource: "scale",
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Kind: "ReplicationController",
|
||||
Name: "myrc",
|
||||
},
|
||||
MaxReplicas: 5,
|
||||
CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: 70},
|
||||
MaxReplicas: 5,
|
||||
TargetCPUUtilizationPercentage: &cpu,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ func TestCreate(t *testing.T) {
|
|||
// valid
|
||||
autoscaler,
|
||||
// invalid
|
||||
&extensions.HorizontalPodAutoscaler{},
|
||||
&autoscaling.HorizontalPodAutoscaler{},
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ func TestUpdate(t *testing.T) {
|
|||
validNewHorizontalPodAutoscaler("foo"),
|
||||
// updateFunc
|
||||
func(obj runtime.Object) runtime.Object {
|
||||
object := obj.(*extensions.HorizontalPodAutoscaler)
|
||||
object := obj.(*autoscaling.HorizontalPodAutoscaler)
|
||||
object.Spec.MaxReplicas = object.Spec.MaxReplicas + 1
|
||||
return object
|
||||
},
|
||||
|
|
|
@ -20,8 +20,8 @@ import (
|
|||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions/validation"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling/validation"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/registry/generic"
|
||||
|
@ -46,15 +46,15 @@ func (autoscalerStrategy) NamespaceScoped() bool {
|
|||
|
||||
// PrepareForCreate clears fields that are not allowed to be set by end users on creation.
|
||||
func (autoscalerStrategy) PrepareForCreate(obj runtime.Object) {
|
||||
newHPA := obj.(*extensions.HorizontalPodAutoscaler)
|
||||
newHPA := obj.(*autoscaling.HorizontalPodAutoscaler)
|
||||
|
||||
// create cannot set status
|
||||
newHPA.Status = extensions.HorizontalPodAutoscalerStatus{}
|
||||
newHPA.Status = autoscaling.HorizontalPodAutoscalerStatus{}
|
||||
}
|
||||
|
||||
// Validate validates a new autoscaler.
|
||||
func (autoscalerStrategy) Validate(ctx api.Context, obj runtime.Object) field.ErrorList {
|
||||
autoscaler := obj.(*extensions.HorizontalPodAutoscaler)
|
||||
autoscaler := obj.(*autoscaling.HorizontalPodAutoscaler)
|
||||
return validation.ValidateHorizontalPodAutoscaler(autoscaler)
|
||||
}
|
||||
|
||||
|
@ -69,22 +69,22 @@ func (autoscalerStrategy) AllowCreateOnUpdate() bool {
|
|||
|
||||
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
||||
func (autoscalerStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
||||
newHPA := obj.(*extensions.HorizontalPodAutoscaler)
|
||||
oldHPA := old.(*extensions.HorizontalPodAutoscaler)
|
||||
newHPA := obj.(*autoscaling.HorizontalPodAutoscaler)
|
||||
oldHPA := old.(*autoscaling.HorizontalPodAutoscaler)
|
||||
// Update is not allowed to set status
|
||||
newHPA.Status = oldHPA.Status
|
||||
}
|
||||
|
||||
// ValidateUpdate is the default update validation for an end user.
|
||||
func (autoscalerStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) field.ErrorList {
|
||||
return validation.ValidateHorizontalPodAutoscalerUpdate(obj.(*extensions.HorizontalPodAutoscaler), old.(*extensions.HorizontalPodAutoscaler))
|
||||
return validation.ValidateHorizontalPodAutoscalerUpdate(obj.(*autoscaling.HorizontalPodAutoscaler), old.(*autoscaling.HorizontalPodAutoscaler))
|
||||
}
|
||||
|
||||
func (autoscalerStrategy) AllowUnconditionalUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func AutoscalerToSelectableFields(limitRange *extensions.HorizontalPodAutoscaler) fields.Set {
|
||||
func AutoscalerToSelectableFields(limitRange *autoscaling.HorizontalPodAutoscaler) fields.Set {
|
||||
return fields.Set{}
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ func MatchAutoscaler(label labels.Selector, field fields.Selector) generic.Match
|
|||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
hpa, ok := obj.(*extensions.HorizontalPodAutoscaler)
|
||||
hpa, ok := obj.(*autoscaling.HorizontalPodAutoscaler)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("given object is not a horizontal pod autoscaler.")
|
||||
}
|
||||
|
@ -109,12 +109,12 @@ type autoscalerStatusStrategy struct {
|
|||
var StatusStrategy = autoscalerStatusStrategy{Strategy}
|
||||
|
||||
func (autoscalerStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
||||
newAutoscaler := obj.(*extensions.HorizontalPodAutoscaler)
|
||||
oldAutoscaler := old.(*extensions.HorizontalPodAutoscaler)
|
||||
newAutoscaler := obj.(*autoscaling.HorizontalPodAutoscaler)
|
||||
oldAutoscaler := old.(*autoscaling.HorizontalPodAutoscaler)
|
||||
// status changes are not allowed to update spec
|
||||
newAutoscaler.Spec = oldAutoscaler.Spec
|
||||
}
|
||||
|
||||
func (autoscalerStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) field.ErrorList {
|
||||
return validation.ValidateHorizontalPodAutoscalerStatusUpdate(obj.(*extensions.HorizontalPodAutoscaler), old.(*extensions.HorizontalPodAutoscaler))
|
||||
return validation.ValidateHorizontalPodAutoscalerStatusUpdate(obj.(*autoscaling.HorizontalPodAutoscaler), old.(*autoscaling.HorizontalPodAutoscaler))
|
||||
}
|
||||
|
|
|
@ -22,15 +22,15 @@ import (
|
|||
_ "k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
)
|
||||
|
||||
func TestSelectableFieldLabelConversions(t *testing.T) {
|
||||
apitesting.TestSelectableFieldLabelConversionsOfKind(t,
|
||||
testapi.Extensions.GroupVersion().String(),
|
||||
testapi.Autoscaling.GroupVersion().String(),
|
||||
"Autoscaler",
|
||||
labels.Set(AutoscalerToSelectableFields(&extensions.HorizontalPodAutoscaler{})),
|
||||
labels.Set(AutoscalerToSelectableFields(&autoscaling.HorizontalPodAutoscaler{})),
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import (
|
|||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/test/e2e/framework"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
|
@ -87,7 +87,7 @@ var _ = framework.KubeDescribe("Horizontal pod autoscaling (scale resource: CPU)
|
|||
}
|
||||
scaleTest.run("rc-light", kindRC, rc, f)
|
||||
})
|
||||
It("Should scale from 2 pods to 1 pod using HPA version v1", func() {
|
||||
It("Should scale from 2 pods to 1 pod", func() {
|
||||
scaleTest := &HPAScaleTest{
|
||||
initPods: 2,
|
||||
totalInitialCPUUsage: 50,
|
||||
|
@ -96,7 +96,6 @@ var _ = framework.KubeDescribe("Horizontal pod autoscaling (scale resource: CPU)
|
|||
minPods: 1,
|
||||
maxPods: 2,
|
||||
firstScale: 1,
|
||||
useV1: true,
|
||||
}
|
||||
scaleTest.run("rc-light", kindRC, rc, f)
|
||||
})
|
||||
|
@ -116,7 +115,6 @@ type HPAScaleTest struct {
|
|||
cpuBurst int
|
||||
secondScale int32
|
||||
secondScaleStasis time.Duration
|
||||
useV1 bool
|
||||
}
|
||||
|
||||
// run is a method which runs an HPA lifecycle, from a starting state, to an expected
|
||||
|
@ -127,7 +125,7 @@ type HPAScaleTest struct {
|
|||
func (scaleTest *HPAScaleTest) run(name, kind string, rc *ResourceConsumer, f *framework.Framework) {
|
||||
rc = NewDynamicResourceConsumer(name, kind, int(scaleTest.initPods), int(scaleTest.totalInitialCPUUsage), 0, 0, scaleTest.perPodCPURequest, 100, f)
|
||||
defer rc.CleanUp()
|
||||
createCPUHorizontalPodAutoscaler(rc, scaleTest.targetCPUUtilizationPercent, scaleTest.minPods, scaleTest.maxPods, scaleTest.useV1)
|
||||
createCPUHorizontalPodAutoscaler(rc, scaleTest.targetCPUUtilizationPercent, scaleTest.minPods, scaleTest.maxPods)
|
||||
rc.WaitForReplicas(int(scaleTest.firstScale))
|
||||
if scaleTest.firstScaleStasis > 0 {
|
||||
rc.EnsureDesiredReplicas(int(scaleTest.firstScale), scaleTest.firstScaleStasis)
|
||||
|
@ -170,28 +168,22 @@ func scaleDown(name, kind string, rc *ResourceConsumer, f *framework.Framework)
|
|||
scaleTest.run(name, kind, rc, f)
|
||||
}
|
||||
|
||||
func createCPUHorizontalPodAutoscaler(rc *ResourceConsumer, cpu, minReplicas, maxRepl int32, useV1 bool) {
|
||||
hpa := &extensions.HorizontalPodAutoscaler{
|
||||
func createCPUHorizontalPodAutoscaler(rc *ResourceConsumer, cpu, minReplicas, maxRepl int32) {
|
||||
hpa := &autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: rc.name,
|
||||
Namespace: rc.framework.Namespace.Name,
|
||||
},
|
||||
Spec: extensions.HorizontalPodAutoscalerSpec{
|
||||
ScaleRef: extensions.SubresourceReference{
|
||||
Kind: rc.kind,
|
||||
Name: rc.name,
|
||||
Subresource: subresource,
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Kind: rc.kind,
|
||||
Name: rc.name,
|
||||
},
|
||||
MinReplicas: &minReplicas,
|
||||
MaxReplicas: maxRepl,
|
||||
CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: cpu},
|
||||
MinReplicas: &minReplicas,
|
||||
MaxReplicas: maxRepl,
|
||||
TargetCPUUtilizationPercentage: &cpu,
|
||||
},
|
||||
}
|
||||
var errHPA error
|
||||
if useV1 {
|
||||
_, errHPA = rc.framework.Client.Autoscaling().HorizontalPodAutoscalers(rc.framework.Namespace.Name).Create(hpa)
|
||||
} else {
|
||||
_, errHPA = rc.framework.Client.Extensions().HorizontalPodAutoscalers(rc.framework.Namespace.Name).Create(hpa)
|
||||
}
|
||||
_, errHPA := rc.framework.Client.Autoscaling().HorizontalPodAutoscalers(rc.framework.Namespace.Name).Create(hpa)
|
||||
framework.ExpectNoError(errHPA)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue