mirror of https://github.com/k3s-io/k3s
Update kubectl to work with new HPA objects
This commit updates kubectl to work with the changes to the unversioned HPA object made to support the HPA v2alpha1 API.pull/6/head
parent
f6c78eb0de
commit
946ecb549e
|
@ -154,6 +154,7 @@ go_test(
|
|||
"//pkg/api/testapi:go_default_library",
|
||||
"//pkg/api/testing:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apis/autoscaling:go_default_library",
|
||||
"//pkg/apis/batch:go_default_library",
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/apis/extensions/v1beta1:go_default_library",
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
)
|
||||
|
||||
|
@ -109,7 +110,15 @@ func generateHPA(genericParams map[string]interface{}) (runtime.Object, error) {
|
|||
}
|
||||
if cpu >= 0 {
|
||||
c := int32(cpu)
|
||||
scaler.Spec.TargetCPUUtilizationPercentage = &c
|
||||
scaler.Spec.Metrics = []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ResourceMetricSourceType,
|
||||
Resource: &autoscaling.ResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
TargetAverageUtilization: &c,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
return &scaler, nil
|
||||
}
|
||||
|
|
|
@ -2191,13 +2191,43 @@ func (d *HorizontalPodAutoscalerDescriber) Describe(namespace, name string, desc
|
|||
w.Write(LEVEL_0, "Reference:\t%s/%s\n",
|
||||
hpa.Spec.ScaleTargetRef.Kind,
|
||||
hpa.Spec.ScaleTargetRef.Name)
|
||||
if hpa.Spec.TargetCPUUtilizationPercentage != nil {
|
||||
w.Write(LEVEL_0, "Target CPU utilization:\t%d%%\n", *hpa.Spec.TargetCPUUtilizationPercentage)
|
||||
w.Write(LEVEL_0, "Current CPU utilization:\t")
|
||||
if hpa.Status.CurrentCPUUtilizationPercentage != nil {
|
||||
w.Write(LEVEL_0, "%d%%\n", *hpa.Status.CurrentCPUUtilizationPercentage)
|
||||
} else {
|
||||
w.Write(LEVEL_0, "<unset>\n")
|
||||
w.Write(LEVEL_0, "Metrics:\t( current / target )\n")
|
||||
for i, metric := range hpa.Spec.Metrics {
|
||||
switch metric.Type {
|
||||
case autoscaling.PodsMetricSourceType:
|
||||
current := "<unknown>"
|
||||
if len(hpa.Status.CurrentMetrics) > i && hpa.Status.CurrentMetrics[i].Pods != nil {
|
||||
current = hpa.Status.CurrentMetrics[i].Pods.CurrentAverageValue.String()
|
||||
}
|
||||
w.Write(LEVEL_1, "%q on pods:\t%s / %s\n", metric.Pods.MetricName, current, metric.Pods.TargetAverageValue.String())
|
||||
case autoscaling.ObjectMetricSourceType:
|
||||
current := "<unknown>"
|
||||
if len(hpa.Status.CurrentMetrics) > i && hpa.Status.CurrentMetrics[i].Object != nil {
|
||||
current = hpa.Status.CurrentMetrics[i].Object.CurrentValue.String()
|
||||
}
|
||||
w.Write(LEVEL_1, "%q on %s/%s:\t%s / %s\n", metric.Object.MetricName, metric.Object.Target.Kind, metric.Object.Target.Name, current, metric.Object.TargetValue.String())
|
||||
case autoscaling.ResourceMetricSourceType:
|
||||
w.Write(LEVEL_1, "resource %s on pods", string(metric.Resource.Name))
|
||||
if metric.Resource.TargetAverageValue != nil {
|
||||
current := "<unknown>"
|
||||
if len(hpa.Status.CurrentMetrics) > i && hpa.Status.CurrentMetrics[i].Resource != nil {
|
||||
current = hpa.Status.CurrentMetrics[i].Resource.CurrentAverageValue.String()
|
||||
}
|
||||
w.Write(LEVEL_0, ":\t%s / %s\n", current, metric.Resource.TargetAverageValue.String())
|
||||
} else {
|
||||
current := "<unknown>"
|
||||
if len(hpa.Status.CurrentMetrics) > i && hpa.Status.CurrentMetrics[i].Resource != nil && hpa.Status.CurrentMetrics[i].Resource.CurrentAverageUtilization != nil {
|
||||
current = fmt.Sprintf("%d%% (%s)", *hpa.Status.CurrentMetrics[i].Resource.CurrentAverageUtilization, hpa.Status.CurrentMetrics[i].Resource.CurrentAverageValue.String())
|
||||
}
|
||||
|
||||
target := "<auto>"
|
||||
if metric.Resource.TargetAverageUtilization != nil {
|
||||
target = fmt.Sprintf("%d%%", *metric.Resource.TargetAverageUtilization)
|
||||
}
|
||||
w.Write(LEVEL_1, "(as a percentage of request):\t%s / %s\n", current, target)
|
||||
}
|
||||
default:
|
||||
w.Write(LEVEL_1, "<unknown metric type %q>", string(metric.Type))
|
||||
}
|
||||
}
|
||||
minReplicas := "<unset>"
|
||||
|
|
|
@ -33,6 +33,7 @@ import (
|
|||
fedfake "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset/fake"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/apis/policy"
|
||||
|
@ -766,6 +767,364 @@ func TestDescribePodDisruptionBudget(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestDescribeHorizontalPodAutoscaler(t *testing.T) {
|
||||
minReplicasVal := int32(2)
|
||||
targetUtilizationVal := int32(80)
|
||||
currentUtilizationVal := int32(50)
|
||||
tests := []struct {
|
||||
name string
|
||||
hpa autoscaling.HorizontalPodAutoscaler
|
||||
}{
|
||||
{
|
||||
"minReplicas unset",
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MaxReplicas: 10,
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"pods source type (no current)",
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.PodsMetricSourceType,
|
||||
Pods: &autoscaling.PodsMetricSource{
|
||||
MetricName: "some-pods-metric",
|
||||
TargetAverageValue: *resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"pods source type (with current)",
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.PodsMetricSourceType,
|
||||
Pods: &autoscaling.PodsMetricSource{
|
||||
MetricName: "some-pods-metric",
|
||||
TargetAverageValue: *resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
CurrentMetrics: []autoscaling.MetricStatus{
|
||||
{
|
||||
Type: autoscaling.PodsMetricSourceType,
|
||||
Pods: &autoscaling.PodsMetricStatus{
|
||||
MetricName: "some-pods-metric",
|
||||
CurrentAverageValue: *resource.NewMilliQuantity(50, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"object source type (no current)",
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ObjectMetricSourceType,
|
||||
Object: &autoscaling.ObjectMetricSource{
|
||||
Target: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-service",
|
||||
Kind: "Service",
|
||||
},
|
||||
MetricName: "some-service-metric",
|
||||
TargetValue: *resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"object source type (with current)",
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ObjectMetricSourceType,
|
||||
Object: &autoscaling.ObjectMetricSource{
|
||||
Target: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-service",
|
||||
Kind: "Service",
|
||||
},
|
||||
MetricName: "some-service-metric",
|
||||
TargetValue: *resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
CurrentMetrics: []autoscaling.MetricStatus{
|
||||
{
|
||||
Type: autoscaling.ObjectMetricSourceType,
|
||||
Object: &autoscaling.ObjectMetricStatus{
|
||||
Target: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-service",
|
||||
Kind: "Service",
|
||||
},
|
||||
MetricName: "some-service-metric",
|
||||
CurrentValue: *resource.NewMilliQuantity(50, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"resource source type, target average value (no current)",
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ResourceMetricSourceType,
|
||||
Resource: &autoscaling.ResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
TargetAverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"resource source type, target average value (with current)",
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ResourceMetricSourceType,
|
||||
Resource: &autoscaling.ResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
TargetAverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
CurrentMetrics: []autoscaling.MetricStatus{
|
||||
{
|
||||
Type: autoscaling.ResourceMetricSourceType,
|
||||
Resource: &autoscaling.ResourceMetricStatus{
|
||||
Name: api.ResourceCPU,
|
||||
CurrentAverageValue: *resource.NewMilliQuantity(50, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"resource source type, target utilization (no current)",
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ResourceMetricSourceType,
|
||||
Resource: &autoscaling.ResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
TargetAverageUtilization: &targetUtilizationVal,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"resource source type, target utilization (with current)",
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ResourceMetricSourceType,
|
||||
Resource: &autoscaling.ResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
TargetAverageUtilization: &targetUtilizationVal,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
CurrentMetrics: []autoscaling.MetricStatus{
|
||||
{
|
||||
Type: autoscaling.ResourceMetricSourceType,
|
||||
Resource: &autoscaling.ResourceMetricStatus{
|
||||
Name: api.ResourceCPU,
|
||||
CurrentAverageUtilization: ¤tUtilizationVal,
|
||||
CurrentAverageValue: *resource.NewMilliQuantity(40, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"multiple metrics",
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.PodsMetricSourceType,
|
||||
Pods: &autoscaling.PodsMetricSource{
|
||||
MetricName: "some-pods-metric",
|
||||
TargetAverageValue: *resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: autoscaling.ResourceMetricSourceType,
|
||||
Resource: &autoscaling.ResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
TargetAverageUtilization: &targetUtilizationVal,
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: autoscaling.PodsMetricSourceType,
|
||||
Pods: &autoscaling.PodsMetricSource{
|
||||
MetricName: "other-pods-metric",
|
||||
TargetAverageValue: *resource.NewMilliQuantity(400, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
CurrentMetrics: []autoscaling.MetricStatus{
|
||||
{
|
||||
Type: autoscaling.PodsMetricSourceType,
|
||||
Pods: &autoscaling.PodsMetricStatus{
|
||||
MetricName: "some-pods-metric",
|
||||
CurrentAverageValue: *resource.NewMilliQuantity(50, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: autoscaling.ResourceMetricSourceType,
|
||||
Resource: &autoscaling.ResourceMetricStatus{
|
||||
Name: api.ResourceCPU,
|
||||
CurrentAverageUtilization: ¤tUtilizationVal,
|
||||
CurrentAverageValue: *resource.NewMilliQuantity(40, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test.hpa.ObjectMeta = metav1.ObjectMeta{
|
||||
Name: "bar",
|
||||
Namespace: "foo",
|
||||
}
|
||||
fake := fake.NewSimpleClientset(&test.hpa)
|
||||
desc := HorizontalPodAutoscalerDescriber{fake}
|
||||
str, err := desc.Describe("foo", "bar", DescriberSettings{ShowEvents: true})
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error for test %s: %v", test.name, err)
|
||||
}
|
||||
if str == "" {
|
||||
t.Errorf("Unexpected empty string for test %s. Expected HPA Describer output", test.name)
|
||||
}
|
||||
t.Logf("Description for %q:\n%s", test.name, str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDescribeEvents(t *testing.T) {
|
||||
|
||||
events := &api.EventList{
|
||||
|
@ -815,7 +1174,6 @@ func TestDescribeEvents(t *testing.T) {
|
|||
}, events),
|
||||
},
|
||||
// TODO(jchaloup): add tests for:
|
||||
// - HorizontalPodAutoscalerDescriber
|
||||
// - IngressDescriber
|
||||
// - JobDescriber
|
||||
"NodeDescriber": &NodeDescriber{
|
||||
|
@ -874,6 +1232,14 @@ func TestDescribeEvents(t *testing.T) {
|
|||
},
|
||||
}, events),
|
||||
},
|
||||
"HorizontalPodAutoscaler": &HorizontalPodAutoscalerDescriber{
|
||||
fake.NewSimpleClientset(&autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "bar",
|
||||
Namespace: "foo",
|
||||
},
|
||||
}, events),
|
||||
},
|
||||
}
|
||||
|
||||
for name, d := range m {
|
||||
|
|
|
@ -533,7 +533,7 @@ var (
|
|||
|
||||
// TODO: consider having 'KIND' for third party resource data
|
||||
thirdPartyResourceDataColumns = []string{"NAME", "LABELS", "DATA"}
|
||||
horizontalPodAutoscalerColumns = []string{"NAME", "REFERENCE", "TARGET", "CURRENT", "MINPODS", "MAXPODS", "REPLICAS", "AGE"}
|
||||
horizontalPodAutoscalerColumns = []string{"NAME", "REFERENCE", "TARGETS", "MINPODS", "MAXPODS", "REPLICAS", "AGE"}
|
||||
withNamespacePrefixColumns = []string{"NAMESPACE"} // TODO(erictune): print cluster name too.
|
||||
deploymentColumns = []string{"NAME", "DESIRED", "CURRENT", "UP-TO-DATE", "AVAILABLE", "AGE"}
|
||||
deploymentWideColumns = []string{"CONTAINER(S)", "IMAGE(S)", "SELECTOR"}
|
||||
|
@ -2145,6 +2145,66 @@ func printDeploymentList(list *extensions.DeploymentList, w io.Writer, options P
|
|||
return nil
|
||||
}
|
||||
|
||||
func formatHPAMetrics(specs []autoscaling.MetricSpec, statuses []autoscaling.MetricStatus) string {
|
||||
if len(specs) == 0 {
|
||||
return "<none>"
|
||||
}
|
||||
list := []string{}
|
||||
max := 2
|
||||
more := false
|
||||
count := 0
|
||||
for i, spec := range specs {
|
||||
switch spec.Type {
|
||||
case autoscaling.PodsMetricSourceType:
|
||||
current := "<unknown>"
|
||||
if len(statuses) > i && statuses[i].Pods != nil {
|
||||
current = statuses[i].Pods.CurrentAverageValue.String()
|
||||
}
|
||||
list = append(list, fmt.Sprintf("%s / %s", current, spec.Pods.TargetAverageValue.String()))
|
||||
case autoscaling.ObjectMetricSourceType:
|
||||
current := "<unknown>"
|
||||
if len(statuses) > i && statuses[i].Object != nil {
|
||||
current = statuses[i].Object.CurrentValue.String()
|
||||
}
|
||||
list = append(list, fmt.Sprintf("%s / %s", current, spec.Object.TargetValue.String()))
|
||||
case autoscaling.ResourceMetricSourceType:
|
||||
if spec.Resource.TargetAverageValue != nil {
|
||||
current := "<unknown>"
|
||||
if len(statuses) > i && statuses[i].Resource != nil {
|
||||
current = statuses[i].Resource.CurrentAverageValue.String()
|
||||
}
|
||||
list = append(list, fmt.Sprintf("%s / %s", current, spec.Resource.TargetAverageValue.String()))
|
||||
} else {
|
||||
current := "<unknown>"
|
||||
if len(statuses) > i && statuses[i].Resource != nil && statuses[i].Resource.CurrentAverageUtilization != nil {
|
||||
current = fmt.Sprintf("%d%%", *statuses[i].Resource.CurrentAverageUtilization)
|
||||
}
|
||||
|
||||
target := "<auto>"
|
||||
if spec.Resource.TargetAverageUtilization != nil {
|
||||
target = fmt.Sprintf("%d%%", *spec.Resource.TargetAverageUtilization)
|
||||
}
|
||||
list = append(list, fmt.Sprintf("%s / %s", current, target))
|
||||
}
|
||||
default:
|
||||
list = append(list, "<unknown type>")
|
||||
}
|
||||
|
||||
count++
|
||||
}
|
||||
|
||||
if count > max {
|
||||
list = list[:max]
|
||||
more = true
|
||||
}
|
||||
|
||||
ret := strings.Join(list, ", ")
|
||||
if more {
|
||||
return fmt.Sprintf("%s + %d more...", ret, count-max)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func printHorizontalPodAutoscaler(hpa *autoscaling.HorizontalPodAutoscaler, w io.Writer, options PrintOptions) error {
|
||||
namespace := hpa.Namespace
|
||||
name := formatResourceName(options.Kind, hpa.Name, options.WithKind)
|
||||
|
@ -2152,15 +2212,8 @@ func printHorizontalPodAutoscaler(hpa *autoscaling.HorizontalPodAutoscaler, w io
|
|||
reference := fmt.Sprintf("%s/%s",
|
||||
hpa.Spec.ScaleTargetRef.Kind,
|
||||
hpa.Spec.ScaleTargetRef.Name)
|
||||
target := "<unset>"
|
||||
if hpa.Spec.TargetCPUUtilizationPercentage != nil {
|
||||
target = fmt.Sprintf("%d%%", *hpa.Spec.TargetCPUUtilizationPercentage)
|
||||
}
|
||||
current := "<waiting>"
|
||||
if hpa.Status.CurrentCPUUtilizationPercentage != nil {
|
||||
current = fmt.Sprintf("%d%%", *hpa.Status.CurrentCPUUtilizationPercentage)
|
||||
}
|
||||
minPods := "<unset>"
|
||||
metrics := formatHPAMetrics(hpa.Spec.Metrics, hpa.Status.CurrentMetrics)
|
||||
if hpa.Spec.MinReplicas != nil {
|
||||
minPods = fmt.Sprintf("%d", *hpa.Spec.MinReplicas)
|
||||
}
|
||||
|
@ -2173,11 +2226,10 @@ func printHorizontalPodAutoscaler(hpa *autoscaling.HorizontalPodAutoscaler, w io
|
|||
}
|
||||
}
|
||||
|
||||
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%d\t%d\t%s",
|
||||
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%d\t%d\t%s",
|
||||
name,
|
||||
reference,
|
||||
target,
|
||||
current,
|
||||
metrics,
|
||||
minPods,
|
||||
maxPods,
|
||||
currentReplicas,
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
@ -36,6 +37,7 @@ import (
|
|||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"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/apis/policy"
|
||||
|
@ -1650,6 +1652,383 @@ func TestPrintJob(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestPrintHPA(t *testing.T) {
|
||||
minReplicasVal := int32(2)
|
||||
targetUtilizationVal := int32(80)
|
||||
currentUtilizationVal := int32(50)
|
||||
tests := []struct {
|
||||
hpa autoscaling.HorizontalPodAutoscaler
|
||||
expected string
|
||||
}{
|
||||
// minReplicas unset
|
||||
{
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MaxReplicas: 10,
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
},
|
||||
},
|
||||
"some-hpa\tReplicationController/some-rc\t<none>\t<unset>\t10\t4\t<unknown>\n",
|
||||
},
|
||||
// pods source type (no current)
|
||||
{
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.PodsMetricSourceType,
|
||||
Pods: &autoscaling.PodsMetricSource{
|
||||
MetricName: "some-pods-metric",
|
||||
TargetAverageValue: *resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
},
|
||||
},
|
||||
"some-hpa\tReplicationController/some-rc\t<unknown> / 100m\t2\t10\t4\t<unknown>\n",
|
||||
},
|
||||
// pods source type
|
||||
{
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.PodsMetricSourceType,
|
||||
Pods: &autoscaling.PodsMetricSource{
|
||||
MetricName: "some-pods-metric",
|
||||
TargetAverageValue: *resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
CurrentMetrics: []autoscaling.MetricStatus{
|
||||
{
|
||||
Type: autoscaling.PodsMetricSourceType,
|
||||
Pods: &autoscaling.PodsMetricStatus{
|
||||
MetricName: "some-pods-metric",
|
||||
CurrentAverageValue: *resource.NewMilliQuantity(50, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"some-hpa\tReplicationController/some-rc\t50m / 100m\t2\t10\t4\t<unknown>\n",
|
||||
},
|
||||
// object source type (no current)
|
||||
{
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ObjectMetricSourceType,
|
||||
Object: &autoscaling.ObjectMetricSource{
|
||||
Target: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-service",
|
||||
Kind: "Service",
|
||||
},
|
||||
MetricName: "some-service-metric",
|
||||
TargetValue: *resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
},
|
||||
},
|
||||
"some-hpa\tReplicationController/some-rc\t<unknown> / 100m\t2\t10\t4\t<unknown>\n",
|
||||
},
|
||||
// object source type
|
||||
{
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ObjectMetricSourceType,
|
||||
Object: &autoscaling.ObjectMetricSource{
|
||||
Target: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-service",
|
||||
Kind: "Service",
|
||||
},
|
||||
MetricName: "some-service-metric",
|
||||
TargetValue: *resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
CurrentMetrics: []autoscaling.MetricStatus{
|
||||
{
|
||||
Type: autoscaling.ObjectMetricSourceType,
|
||||
Object: &autoscaling.ObjectMetricStatus{
|
||||
Target: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-service",
|
||||
Kind: "Service",
|
||||
},
|
||||
MetricName: "some-service-metric",
|
||||
CurrentValue: *resource.NewMilliQuantity(50, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"some-hpa\tReplicationController/some-rc\t50m / 100m\t2\t10\t4\t<unknown>\n",
|
||||
},
|
||||
// resource source type, targetVal (no current)
|
||||
{
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ResourceMetricSourceType,
|
||||
Resource: &autoscaling.ResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
TargetAverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
},
|
||||
},
|
||||
"some-hpa\tReplicationController/some-rc\t<unknown> / 100m\t2\t10\t4\t<unknown>\n",
|
||||
},
|
||||
// resource source type, targetVal
|
||||
{
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ResourceMetricSourceType,
|
||||
Resource: &autoscaling.ResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
TargetAverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
CurrentMetrics: []autoscaling.MetricStatus{
|
||||
{
|
||||
Type: autoscaling.ResourceMetricSourceType,
|
||||
Resource: &autoscaling.ResourceMetricStatus{
|
||||
Name: api.ResourceCPU,
|
||||
CurrentAverageValue: *resource.NewMilliQuantity(50, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"some-hpa\tReplicationController/some-rc\t50m / 100m\t2\t10\t4\t<unknown>\n",
|
||||
},
|
||||
// resource source type, targetUtil (no current)
|
||||
{
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ResourceMetricSourceType,
|
||||
Resource: &autoscaling.ResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
TargetAverageUtilization: &targetUtilizationVal,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
},
|
||||
},
|
||||
"some-hpa\tReplicationController/some-rc\t<unknown> / 80%\t2\t10\t4\t<unknown>\n",
|
||||
},
|
||||
// resource source type, targetUtil
|
||||
{
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.ResourceMetricSourceType,
|
||||
Resource: &autoscaling.ResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
TargetAverageUtilization: &targetUtilizationVal,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
CurrentMetrics: []autoscaling.MetricStatus{
|
||||
{
|
||||
Type: autoscaling.ResourceMetricSourceType,
|
||||
Resource: &autoscaling.ResourceMetricStatus{
|
||||
Name: api.ResourceCPU,
|
||||
CurrentAverageUtilization: ¤tUtilizationVal,
|
||||
CurrentAverageValue: *resource.NewMilliQuantity(40, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"some-hpa\tReplicationController/some-rc\t50% / 80%\t2\t10\t4\t<unknown>\n",
|
||||
},
|
||||
// multiple specs
|
||||
{
|
||||
autoscaling.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
|
||||
Spec: autoscaling.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
|
||||
Name: "some-rc",
|
||||
Kind: "ReplicationController",
|
||||
},
|
||||
MinReplicas: &minReplicasVal,
|
||||
MaxReplicas: 10,
|
||||
Metrics: []autoscaling.MetricSpec{
|
||||
{
|
||||
Type: autoscaling.PodsMetricSourceType,
|
||||
Pods: &autoscaling.PodsMetricSource{
|
||||
MetricName: "some-pods-metric",
|
||||
TargetAverageValue: *resource.NewMilliQuantity(100, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: autoscaling.ResourceMetricSourceType,
|
||||
Resource: &autoscaling.ResourceMetricSource{
|
||||
Name: api.ResourceCPU,
|
||||
TargetAverageUtilization: &targetUtilizationVal,
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: autoscaling.PodsMetricSourceType,
|
||||
Pods: &autoscaling.PodsMetricSource{
|
||||
MetricName: "other-pods-metric",
|
||||
TargetAverageValue: *resource.NewMilliQuantity(400, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: autoscaling.HorizontalPodAutoscalerStatus{
|
||||
CurrentReplicas: 4,
|
||||
DesiredReplicas: 5,
|
||||
CurrentMetrics: []autoscaling.MetricStatus{
|
||||
{
|
||||
Type: autoscaling.PodsMetricSourceType,
|
||||
Pods: &autoscaling.PodsMetricStatus{
|
||||
MetricName: "some-pods-metric",
|
||||
CurrentAverageValue: *resource.NewMilliQuantity(50, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: autoscaling.ResourceMetricSourceType,
|
||||
Resource: &autoscaling.ResourceMetricStatus{
|
||||
Name: api.ResourceCPU,
|
||||
CurrentAverageUtilization: ¤tUtilizationVal,
|
||||
CurrentAverageValue: *resource.NewMilliQuantity(40, resource.DecimalSI),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"some-hpa\tReplicationController/some-rc\t50m / 100m, 50% / 80% + 1 more...\t2\t10\t4\t<unknown>\n",
|
||||
},
|
||||
}
|
||||
|
||||
buff := bytes.NewBuffer([]byte{})
|
||||
for _, test := range tests {
|
||||
err := printHorizontalPodAutoscaler(&test.hpa, buff, PrintOptions{})
|
||||
if err != nil {
|
||||
t.Errorf("expected %q, got error: %v", test.expected, err)
|
||||
buff.Reset()
|
||||
continue
|
||||
}
|
||||
|
||||
if buff.String() != test.expected {
|
||||
t.Errorf("expected %q, got %q", test.expected, buff.String())
|
||||
}
|
||||
|
||||
buff.Reset()
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrintPodShowLabels(t *testing.T) {
|
||||
tests := []struct {
|
||||
pod api.Pod
|
||||
|
|
Loading…
Reference in New Issue