Merge pull request #20703 from mwielgus/hpa-cm-validation
Auto commit by PR queue bot
This commit is contained in:
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package validation
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"regexp"
|
||||
"strconv"
|
||||
@@ -27,6 +28,7 @@ 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"
|
||||
@@ -85,9 +87,34 @@ func ValidateSubresourceReference(ref extensions.SubresourceReference, fldPath *
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ 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"
|
||||
)
|
||||
|
||||
@@ -60,6 +61,24 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
|
||||
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: newInt(1),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, successCase := range successCases {
|
||||
if errs := ValidateHorizontalPodAutoscaler(&successCase); len(errs) != 0 {
|
||||
@@ -204,6 +223,90 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
|
||||
},
|
||||
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: newInt(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: newInt(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: newInt(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: newInt(1),
|
||||
MaxReplicas: 5,
|
||||
},
|
||||
},
|
||||
msg: "custom metric target value must be greater than 0",
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range errorCases {
|
||||
|
||||
Reference in New Issue
Block a user