Skip to content

Commit 265f80e

Browse files
authored
Merge pull request kubernetes#75176 from mars1024/bugfix/hpa_not_working_in_kubectl_since_v1.13
make describers of different versions work properly when autoscaling/v2beta2 is not supported
2 parents 057ad6d + 814e1ca commit 265f80e

File tree

3 files changed

+158
-10
lines changed

3 files changed

+158
-10
lines changed

pkg/kubectl/describe/versioned/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ go_library(
1818
"//pkg/kubectl/util/slice:go_default_library",
1919
"//pkg/kubectl/util/storage:go_default_library",
2020
"//staging/src/k8s.io/api/apps/v1:go_default_library",
21+
"//staging/src/k8s.io/api/autoscaling/v1:go_default_library",
2122
"//staging/src/k8s.io/api/autoscaling/v2beta2:go_default_library",
2223
"//staging/src/k8s.io/api/batch/v1:go_default_library",
2324
"//staging/src/k8s.io/api/batch/v1beta1:go_default_library",
@@ -73,6 +74,7 @@ go_test(
7374
deps = [
7475
"//pkg/kubectl/describe:go_default_library",
7576
"//staging/src/k8s.io/api/apps/v1:go_default_library",
77+
"//staging/src/k8s.io/api/autoscaling/v1:go_default_library",
7678
"//staging/src/k8s.io/api/autoscaling/v2beta2:go_default_library",
7779
"//staging/src/k8s.io/api/core/v1:go_default_library",
7880
"//staging/src/k8s.io/api/networking/v1:go_default_library",

pkg/kubectl/describe/versioned/describe.go

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"github.com/fatih/camelcase"
3434

3535
appsv1 "k8s.io/api/apps/v1"
36+
autoscalingv1 "k8s.io/api/autoscaling/v1"
3637
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
3738
batchv1 "k8s.io/api/batch/v1"
3839
batchv1beta1 "k8s.io/api/batch/v1beta1"
@@ -3074,20 +3075,31 @@ type HorizontalPodAutoscalerDescriber struct {
30743075
}
30753076

30763077
func (d *HorizontalPodAutoscalerDescriber) Describe(namespace, name string, describerSettings describe.DescriberSettings) (string, error) {
3077-
hpa, err := d.client.AutoscalingV2beta2().HorizontalPodAutoscalers(namespace).Get(name, metav1.GetOptions{})
3078-
if err != nil {
3079-
return "", err
3078+
var events *corev1.EventList
3079+
3080+
// autoscaling/v2beta2 is introduced since v1.12 and autoscaling/v1 does not have full backward compatibility
3081+
// with autoscaling/v2beta2, so describer will try to get and describe hpa v2beta2 object firstly, if it fails,
3082+
// describer will fall back to do with hpa v1 object
3083+
hpaV2beta2, err := d.client.AutoscalingV2beta2().HorizontalPodAutoscalers(namespace).Get(name, metav1.GetOptions{})
3084+
if err == nil {
3085+
if describerSettings.ShowEvents {
3086+
events, _ = d.client.CoreV1().Events(namespace).Search(scheme.Scheme, hpaV2beta2)
3087+
}
3088+
return describeHorizontalPodAutoscalerV2beta2(hpaV2beta2, events, d)
30803089
}
30813090

3082-
var events *corev1.EventList
3083-
if describerSettings.ShowEvents {
3084-
events, _ = d.client.CoreV1().Events(namespace).Search(scheme.Scheme, hpa)
3091+
hpaV1, err := d.client.AutoscalingV1().HorizontalPodAutoscalers(namespace).Get(name, metav1.GetOptions{})
3092+
if err == nil {
3093+
if describerSettings.ShowEvents {
3094+
events, _ = d.client.CoreV1().Events(namespace).Search(scheme.Scheme, hpaV1)
3095+
}
3096+
return describeHorizontalPodAutoscalerV1(hpaV1, events, d)
30853097
}
30863098

3087-
return describeHorizontalPodAutoscaler(hpa, events, d)
3099+
return "", err
30883100
}
30893101

3090-
func describeHorizontalPodAutoscaler(hpa *autoscalingv2beta2.HorizontalPodAutoscaler, events *corev1.EventList, d *HorizontalPodAutoscalerDescriber) (string, error) {
3102+
func describeHorizontalPodAutoscalerV2beta2(hpa *autoscalingv2beta2.HorizontalPodAutoscaler, events *corev1.EventList, d *HorizontalPodAutoscalerDescriber) (string, error) {
30913103
return tabbedString(func(out io.Writer) error {
30923104
w := NewPrefixWriter(out)
30933105
w.Write(LEVEL_0, "Name:\t%s\n", hpa.Name)
@@ -3188,6 +3200,44 @@ func describeHorizontalPodAutoscaler(hpa *autoscalingv2beta2.HorizontalPodAutosc
31883200
})
31893201
}
31903202

3203+
func describeHorizontalPodAutoscalerV1(hpa *autoscalingv1.HorizontalPodAutoscaler, events *corev1.EventList, d *HorizontalPodAutoscalerDescriber) (string, error) {
3204+
return tabbedString(func(out io.Writer) error {
3205+
w := NewPrefixWriter(out)
3206+
w.Write(LEVEL_0, "Name:\t%s\n", hpa.Name)
3207+
w.Write(LEVEL_0, "Namespace:\t%s\n", hpa.Namespace)
3208+
printLabelsMultiline(w, "Labels", hpa.Labels)
3209+
printAnnotationsMultiline(w, "Annotations", hpa.Annotations)
3210+
w.Write(LEVEL_0, "CreationTimestamp:\t%s\n", hpa.CreationTimestamp.Time.Format(time.RFC1123Z))
3211+
w.Write(LEVEL_0, "Reference:\t%s/%s\n",
3212+
hpa.Spec.ScaleTargetRef.Kind,
3213+
hpa.Spec.ScaleTargetRef.Name)
3214+
3215+
if hpa.Spec.TargetCPUUtilizationPercentage != nil {
3216+
w.Write(LEVEL_0, "Target CPU utilization:\t%d%%\n", *hpa.Spec.TargetCPUUtilizationPercentage)
3217+
current := "<unknown>"
3218+
if hpa.Status.CurrentCPUUtilizationPercentage != nil {
3219+
current = fmt.Sprintf("%d", *hpa.Status.CurrentCPUUtilizationPercentage)
3220+
}
3221+
w.Write(LEVEL_0, "Current CPU utilization:\t%s%%\n", current)
3222+
}
3223+
3224+
minReplicas := "<unset>"
3225+
if hpa.Spec.MinReplicas != nil {
3226+
minReplicas = fmt.Sprintf("%d", *hpa.Spec.MinReplicas)
3227+
}
3228+
w.Write(LEVEL_0, "Min replicas:\t%s\n", minReplicas)
3229+
w.Write(LEVEL_0, "Max replicas:\t%d\n", hpa.Spec.MaxReplicas)
3230+
w.Write(LEVEL_0, "%s pods:\t", hpa.Spec.ScaleTargetRef.Kind)
3231+
w.Write(LEVEL_0, "%d current / %d desired\n", hpa.Status.CurrentReplicas, hpa.Status.DesiredReplicas)
3232+
3233+
if events != nil {
3234+
DescribeEvents(events, w)
3235+
}
3236+
3237+
return nil
3238+
})
3239+
}
3240+
31913241
func describeNodeResource(nodeNonTerminatedPodsList *corev1.PodList, node *corev1.Node, w PrefixWriter) {
31923242
w.Write(LEVEL_0, "Non-terminated Pods:\t(%d in total)\n", len(nodeNonTerminatedPodsList.Items))
31933243
w.Write(LEVEL_1, "Namespace\tName\t\tCPU Requests\tCPU Limits\tMemory Requests\tMemory Limits\tAGE\n")

pkg/kubectl/describe/versioned/describe_test.go

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"time"
2727

2828
appsv1 "k8s.io/api/apps/v1"
29+
autoscalingv1 "k8s.io/api/autoscaling/v1"
2930
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
3031
"k8s.io/api/core/v1"
3132
corev1 "k8s.io/api/core/v1"
@@ -1628,7 +1629,7 @@ func TestDescribeHorizontalPodAutoscaler(t *testing.T) {
16281629
if err != nil {
16291630
t.Errorf("unable to parse label selector: %v", err)
16301631
}
1631-
tests := []struct {
1632+
testsV2beta2 := []struct {
16321633
name string
16331634
hpa autoscalingv2beta2.HorizontalPodAutoscaler
16341635
}{
@@ -2270,7 +2271,102 @@ func TestDescribeHorizontalPodAutoscaler(t *testing.T) {
22702271
},
22712272
}
22722273

2273-
for _, test := range tests {
2274+
for _, test := range testsV2beta2 {
2275+
t.Run(test.name, func(t *testing.T) {
2276+
test.hpa.ObjectMeta = metav1.ObjectMeta{
2277+
Name: "bar",
2278+
Namespace: "foo",
2279+
}
2280+
fake := fake.NewSimpleClientset(&test.hpa)
2281+
desc := HorizontalPodAutoscalerDescriber{fake}
2282+
str, err := desc.Describe("foo", "bar", describe.DescriberSettings{ShowEvents: true})
2283+
if err != nil {
2284+
t.Errorf("Unexpected error for test %s: %v", test.name, err)
2285+
}
2286+
if str == "" {
2287+
t.Errorf("Unexpected empty string for test %s. Expected HPA Describer output", test.name)
2288+
}
2289+
t.Logf("Description for %q:\n%s", test.name, str)
2290+
})
2291+
}
2292+
2293+
testsV1 := []struct {
2294+
name string
2295+
hpa autoscalingv1.HorizontalPodAutoscaler
2296+
}{
2297+
{
2298+
"minReplicas unset",
2299+
autoscalingv1.HorizontalPodAutoscaler{
2300+
Spec: autoscalingv1.HorizontalPodAutoscalerSpec{
2301+
ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{
2302+
Name: "some-rc",
2303+
Kind: "ReplicationController",
2304+
},
2305+
MaxReplicas: 10,
2306+
},
2307+
Status: autoscalingv1.HorizontalPodAutoscalerStatus{
2308+
CurrentReplicas: 4,
2309+
DesiredReplicas: 5,
2310+
},
2311+
},
2312+
},
2313+
{
2314+
"minReplicas set",
2315+
autoscalingv1.HorizontalPodAutoscaler{
2316+
Spec: autoscalingv1.HorizontalPodAutoscalerSpec{
2317+
ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{
2318+
Name: "some-rc",
2319+
Kind: "ReplicationController",
2320+
},
2321+
MinReplicas: &minReplicasVal,
2322+
MaxReplicas: 10,
2323+
},
2324+
Status: autoscalingv1.HorizontalPodAutoscalerStatus{
2325+
CurrentReplicas: 4,
2326+
DesiredReplicas: 5,
2327+
},
2328+
},
2329+
},
2330+
{
2331+
"with target no current",
2332+
autoscalingv1.HorizontalPodAutoscaler{
2333+
Spec: autoscalingv1.HorizontalPodAutoscalerSpec{
2334+
ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{
2335+
Name: "some-rc",
2336+
Kind: "ReplicationController",
2337+
},
2338+
MinReplicas: &minReplicasVal,
2339+
MaxReplicas: 10,
2340+
TargetCPUUtilizationPercentage: &targetUtilizationVal,
2341+
},
2342+
Status: autoscalingv1.HorizontalPodAutoscalerStatus{
2343+
CurrentReplicas: 4,
2344+
DesiredReplicas: 5,
2345+
},
2346+
},
2347+
},
2348+
{
2349+
"with target and current",
2350+
autoscalingv1.HorizontalPodAutoscaler{
2351+
Spec: autoscalingv1.HorizontalPodAutoscalerSpec{
2352+
ScaleTargetRef: autoscalingv1.CrossVersionObjectReference{
2353+
Name: "some-rc",
2354+
Kind: "ReplicationController",
2355+
},
2356+
MinReplicas: &minReplicasVal,
2357+
MaxReplicas: 10,
2358+
TargetCPUUtilizationPercentage: &targetUtilizationVal,
2359+
},
2360+
Status: autoscalingv1.HorizontalPodAutoscalerStatus{
2361+
CurrentReplicas: 4,
2362+
DesiredReplicas: 5,
2363+
CurrentCPUUtilizationPercentage: &currentUtilizationVal,
2364+
},
2365+
},
2366+
},
2367+
}
2368+
2369+
for _, test := range testsV1 {
22742370
t.Run(test.name, func(t *testing.T) {
22752371
test.hpa.ObjectMeta = metav1.ObjectMeta{
22762372
Name: "bar",

0 commit comments

Comments
 (0)