make describers of different versions work properly when autoscaling/v2beta2 is not supported

k3s-v1.15.3
Bruce Ma 2019-03-08 19:51:32 +08:00
parent 5c2fe63591
commit 814e1ca73f
3 changed files with 159 additions and 11 deletions

View File

@ -18,6 +18,7 @@ go_library(
"//pkg/kubectl/util/slice:go_default_library",
"//pkg/kubectl/util/storage:go_default_library",
"//staging/src/k8s.io/api/apps/v1:go_default_library",
"//staging/src/k8s.io/api/autoscaling/v1:go_default_library",
"//staging/src/k8s.io/api/autoscaling/v2beta2:go_default_library",
"//staging/src/k8s.io/api/batch/v1:go_default_library",
"//staging/src/k8s.io/api/batch/v1beta1:go_default_library",
@ -73,6 +74,7 @@ go_test(
deps = [
"//pkg/kubectl/describe:go_default_library",
"//staging/src/k8s.io/api/apps/v1:go_default_library",
"//staging/src/k8s.io/api/autoscaling/v1:go_default_library",
"//staging/src/k8s.io/api/autoscaling/v2beta2:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/api/networking/v1:go_default_library",

View File

@ -33,6 +33,7 @@ import (
"github.com/fatih/camelcase"
appsv1 "k8s.io/api/apps/v1"
autoscalingv1 "k8s.io/api/autoscaling/v1"
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
batchv1 "k8s.io/api/batch/v1"
batchv1beta1 "k8s.io/api/batch/v1beta1"
@ -3074,20 +3075,31 @@ type HorizontalPodAutoscalerDescriber struct {
}
func (d *HorizontalPodAutoscalerDescriber) Describe(namespace, name string, describerSettings describe.DescriberSettings) (string, error) {
hpa, err := d.client.AutoscalingV2beta2().HorizontalPodAutoscalers(namespace).Get(name, metav1.GetOptions{})
if err != nil {
return "", err
}
var events *corev1.EventList
if describerSettings.ShowEvents {
events, _ = d.client.CoreV1().Events(namespace).Search(scheme.Scheme, hpa)
// autoscaling/v2beta2 is introduced since v1.12 and autoscaling/v1 does not have full backward compatibility
// with autoscaling/v2beta2, so describer will try to get and describe hpa v2beta2 object firstly, if it fails,
// describer will fall back to do with hpa v1 object
hpaV2beta2, err := d.client.AutoscalingV2beta2().HorizontalPodAutoscalers(namespace).Get(name, metav1.GetOptions{})
if err == nil {
if describerSettings.ShowEvents {
events, _ = d.client.CoreV1().Events(namespace).Search(scheme.Scheme, hpaV2beta2)
}
return describeHorizontalPodAutoscalerV2beta2(hpaV2beta2, events, d)
}
return describeHorizontalPodAutoscaler(hpa, events, d)
hpaV1, err := d.client.AutoscalingV1().HorizontalPodAutoscalers(namespace).Get(name, metav1.GetOptions{})
if err == nil {
if describerSettings.ShowEvents {
events, _ = d.client.CoreV1().Events(namespace).Search(scheme.Scheme, hpaV1)
}
return describeHorizontalPodAutoscalerV1(hpaV1, events, d)
}
return "", err
}
func describeHorizontalPodAutoscaler(hpa *autoscalingv2beta2.HorizontalPodAutoscaler, events *corev1.EventList, d *HorizontalPodAutoscalerDescriber) (string, error) {
func describeHorizontalPodAutoscalerV2beta2(hpa *autoscalingv2beta2.HorizontalPodAutoscaler, events *corev1.EventList, d *HorizontalPodAutoscalerDescriber) (string, error) {
return tabbedString(func(out io.Writer) error {
w := NewPrefixWriter(out)
w.Write(LEVEL_0, "Name:\t%s\n", hpa.Name)
@ -3188,6 +3200,44 @@ func describeHorizontalPodAutoscaler(hpa *autoscalingv2beta2.HorizontalPodAutosc
})
}
func describeHorizontalPodAutoscalerV1(hpa *autoscalingv1.HorizontalPodAutoscaler, events *corev1.EventList, d *HorizontalPodAutoscalerDescriber) (string, error) {
return tabbedString(func(out io.Writer) error {
w := NewPrefixWriter(out)
w.Write(LEVEL_0, "Name:\t%s\n", hpa.Name)
w.Write(LEVEL_0, "Namespace:\t%s\n", hpa.Namespace)
printLabelsMultiline(w, "Labels", hpa.Labels)
printAnnotationsMultiline(w, "Annotations", hpa.Annotations)
w.Write(LEVEL_0, "CreationTimestamp:\t%s\n", hpa.CreationTimestamp.Time.Format(time.RFC1123Z))
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)
current := "<unknown>"
if hpa.Status.CurrentCPUUtilizationPercentage != nil {
current = fmt.Sprintf("%d", *hpa.Status.CurrentCPUUtilizationPercentage)
}
w.Write(LEVEL_0, "Current CPU utilization:\t%s%%\n", current)
}
minReplicas := "<unset>"
if hpa.Spec.MinReplicas != nil {
minReplicas = fmt.Sprintf("%d", *hpa.Spec.MinReplicas)
}
w.Write(LEVEL_0, "Min replicas:\t%s\n", minReplicas)
w.Write(LEVEL_0, "Max replicas:\t%d\n", hpa.Spec.MaxReplicas)
w.Write(LEVEL_0, "%s pods:\t", hpa.Spec.ScaleTargetRef.Kind)
w.Write(LEVEL_0, "%d current / %d desired\n", hpa.Status.CurrentReplicas, hpa.Status.DesiredReplicas)
if events != nil {
DescribeEvents(events, w)
}
return nil
})
}
func describeNodeResource(nodeNonTerminatedPodsList *corev1.PodList, node *corev1.Node, w PrefixWriter) {
w.Write(LEVEL_0, "Non-terminated Pods:\t(%d in total)\n", len(nodeNonTerminatedPodsList.Items))
w.Write(LEVEL_1, "Namespace\tName\t\tCPU Requests\tCPU Limits\tMemory Requests\tMemory Limits\tAGE\n")

View File

@ -26,6 +26,7 @@ import (
"time"
appsv1 "k8s.io/api/apps/v1"
autoscalingv1 "k8s.io/api/autoscaling/v1"
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
"k8s.io/api/core/v1"
corev1 "k8s.io/api/core/v1"
@ -1628,7 +1629,7 @@ func TestDescribeHorizontalPodAutoscaler(t *testing.T) {
if err != nil {
t.Errorf("unable to parse label selector: %v", err)
}
tests := []struct {
testsV2beta2 := []struct {
name string
hpa autoscalingv2beta2.HorizontalPodAutoscaler
}{
@ -2270,7 +2271,102 @@ func TestDescribeHorizontalPodAutoscaler(t *testing.T) {
},
}
for _, test := range tests {
for _, test := range testsV2beta2 {
t.Run(test.name, func(t *testing.T) {
test.hpa.ObjectMeta = metav1.ObjectMeta{
Name: "bar",
Namespace: "foo",
}
fake := fake.NewSimpleClientset(&test.hpa)
desc := HorizontalPodAutoscalerDescriber{fake}
str, err := desc.Describe("foo", "bar", describe.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)
})
}
testsV1 := []struct {
name string
hpa autoscalingv1.HorizontalPodAutoscaler
}{
{
"minReplicas unset",
autoscalingv1.HorizontalPodAutoscaler{
Spec: autoscalingv1.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{
Name: "some-rc",
Kind: "ReplicationController",
},
MaxReplicas: 10,
},
Status: autoscalingv1.HorizontalPodAutoscalerStatus{
CurrentReplicas: 4,
DesiredReplicas: 5,
},
},
},
{
"minReplicas set",
autoscalingv1.HorizontalPodAutoscaler{
Spec: autoscalingv1.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{
Name: "some-rc",
Kind: "ReplicationController",
},
MinReplicas: &minReplicasVal,
MaxReplicas: 10,
},
Status: autoscalingv1.HorizontalPodAutoscalerStatus{
CurrentReplicas: 4,
DesiredReplicas: 5,
},
},
},
{
"with target no current",
autoscalingv1.HorizontalPodAutoscaler{
Spec: autoscalingv1.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{
Name: "some-rc",
Kind: "ReplicationController",
},
MinReplicas: &minReplicasVal,
MaxReplicas: 10,
TargetCPUUtilizationPercentage: &targetUtilizationVal,
},
Status: autoscalingv1.HorizontalPodAutoscalerStatus{
CurrentReplicas: 4,
DesiredReplicas: 5,
},
},
},
{
"with target and current",
autoscalingv1.HorizontalPodAutoscaler{
Spec: autoscalingv1.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{
Name: "some-rc",
Kind: "ReplicationController",
},
MinReplicas: &minReplicasVal,
MaxReplicas: 10,
TargetCPUUtilizationPercentage: &targetUtilizationVal,
},
Status: autoscalingv1.HorizontalPodAutoscalerStatus{
CurrentReplicas: 4,
DesiredReplicas: 5,
CurrentCPUUtilizationPercentage: &currentUtilizationVal,
},
},
},
}
for _, test := range testsV1 {
t.Run(test.name, func(t *testing.T) {
test.hpa.ObjectMeta = metav1.ObjectMeta{
Name: "bar",