mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-26 21:17:23 +00:00
Merge pull request #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
This commit is contained in:
commit
265f80eef9
@ -18,6 +18,7 @@ go_library(
|
|||||||
"//pkg/kubectl/util/slice:go_default_library",
|
"//pkg/kubectl/util/slice:go_default_library",
|
||||||
"//pkg/kubectl/util/storage: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/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/autoscaling/v2beta2:go_default_library",
|
||||||
"//staging/src/k8s.io/api/batch/v1:go_default_library",
|
"//staging/src/k8s.io/api/batch/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/api/batch/v1beta1:go_default_library",
|
"//staging/src/k8s.io/api/batch/v1beta1:go_default_library",
|
||||||
@ -73,6 +74,7 @@ go_test(
|
|||||||
deps = [
|
deps = [
|
||||||
"//pkg/kubectl/describe:go_default_library",
|
"//pkg/kubectl/describe:go_default_library",
|
||||||
"//staging/src/k8s.io/api/apps/v1: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/autoscaling/v2beta2:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/api/networking/v1:go_default_library",
|
"//staging/src/k8s.io/api/networking/v1:go_default_library",
|
||||||
|
@ -33,6 +33,7 @@ import (
|
|||||||
"github.com/fatih/camelcase"
|
"github.com/fatih/camelcase"
|
||||||
|
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
autoscalingv1 "k8s.io/api/autoscaling/v1"
|
||||||
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
|
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
|
||||||
batchv1 "k8s.io/api/batch/v1"
|
batchv1 "k8s.io/api/batch/v1"
|
||||||
batchv1beta1 "k8s.io/api/batch/v1beta1"
|
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) {
|
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
|
var events *corev1.EventList
|
||||||
|
|
||||||
|
// 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 {
|
if describerSettings.ShowEvents {
|
||||||
events, _ = d.client.CoreV1().Events(namespace).Search(scheme.Scheme, hpa)
|
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 {
|
return tabbedString(func(out io.Writer) error {
|
||||||
w := NewPrefixWriter(out)
|
w := NewPrefixWriter(out)
|
||||||
w.Write(LEVEL_0, "Name:\t%s\n", hpa.Name)
|
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) {
|
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_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")
|
w.Write(LEVEL_1, "Namespace\tName\t\tCPU Requests\tCPU Limits\tMemory Requests\tMemory Limits\tAGE\n")
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
autoscalingv1 "k8s.io/api/autoscaling/v1"
|
||||||
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
|
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
@ -1628,7 +1629,7 @@ func TestDescribeHorizontalPodAutoscaler(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unable to parse label selector: %v", err)
|
t.Errorf("unable to parse label selector: %v", err)
|
||||||
}
|
}
|
||||||
tests := []struct {
|
testsV2beta2 := []struct {
|
||||||
name string
|
name string
|
||||||
hpa autoscalingv2beta2.HorizontalPodAutoscaler
|
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: ¤tUtilizationVal,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testsV1 {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
test.hpa.ObjectMeta = metav1.ObjectMeta{
|
test.hpa.ObjectMeta = metav1.ObjectMeta{
|
||||||
Name: "bar",
|
Name: "bar",
|
||||||
|
Loading…
Reference in New Issue
Block a user