From 6d65c063caaee8e35a7ae02f2f74cb7b081fdef0 Mon Sep 17 00:00:00 2001 From: Ivan Valdes Date: Fri, 5 Jan 2024 14:29:01 -0800 Subject: [PATCH] describer: improve job and pod template output * Add Node-Selectors and Tolerations to pod template's describe output. * Add Suspend, BackoffLimit and TTLSecondsAfterFinished to job's describe output. --- .../k8s.io/kubectl/pkg/describe/describe.go | 11 +++ .../kubectl/pkg/describe/describe_test.go | 80 ++++++++++++++----- .../pkg/polymorphichelpers/history_test.go | 6 ++ 3 files changed, 77 insertions(+), 20 deletions(-) diff --git a/staging/src/k8s.io/kubectl/pkg/describe/describe.go b/staging/src/k8s.io/kubectl/pkg/describe/describe.go index 53ba5dfc946..8648a786fbe 100644 --- a/staging/src/k8s.io/kubectl/pkg/describe/describe.go +++ b/staging/src/k8s.io/kubectl/pkg/describe/describe.go @@ -2212,6 +2212,8 @@ func DescribePodTemplate(template *corev1.PodTemplateSpec, w PrefixWriter) { if len(template.Spec.PriorityClassName) > 0 { w.Write(LEVEL_1, "Priority Class Name:\t%s\n", template.Spec.PriorityClassName) } + printLabelsMultiline(w, " Node-Selectors", template.Spec.NodeSelector) + printPodTolerationsMultiline(w, " Tolerations", template.Spec.Tolerations) } // ReplicaSetDescriber generates information about a ReplicaSet and the pods it has created. @@ -2321,6 +2323,15 @@ func describeJob(job *batchv1.Job, events *corev1.EventList) (string, error) { if job.Spec.CompletionMode != nil { w.Write(LEVEL_0, "Completion Mode:\t%s\n", *job.Spec.CompletionMode) } + if job.Spec.Suspend != nil { + w.Write(LEVEL_0, "Suspend:\t%v\n", *job.Spec.Suspend) + } + if job.Spec.BackoffLimit != nil { + w.Write(LEVEL_0, "Backoff Limit:\t%v\n", *job.Spec.BackoffLimit) + } + if job.Spec.TTLSecondsAfterFinished != nil { + w.Write(LEVEL_0, "TTL Seconds After Finished:\t%v\n", *job.Spec.TTLSecondsAfterFinished) + } if job.Status.StartTime != nil { w.Write(LEVEL_0, "Start Time:\t%s\n", job.Status.StartTime.Time.Format(time.RFC1123Z)) } diff --git a/staging/src/k8s.io/kubectl/pkg/describe/describe_test.go b/staging/src/k8s.io/kubectl/pkg/describe/describe_test.go index 09673bf0b63..b18ec73a1db 100644 --- a/staging/src/k8s.io/kubectl/pkg/describe/describe_test.go +++ b/staging/src/k8s.io/kubectl/pkg/describe/describe_test.go @@ -49,6 +49,7 @@ import ( "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/fake" utilpointer "k8s.io/utils/pointer" + "k8s.io/utils/ptr" ) type describeClient struct { @@ -2260,9 +2261,11 @@ func TestDescribeDeployment(t *testing.T) { "Replicas: 1 desired | 0 updated | 0 total | 0 available | 0 unavailable", "Image: mytest-image:latest", "Mounts:\n /tmp/vol-bar from vol-bar (rw)\n /tmp/vol-foo from vol-foo (rw)", - "OldReplicaSets: ", - "NewReplicaSet: bar-001 (1/1 replicas created)", - "Events: ", + "OldReplicaSets: ", + "NewReplicaSet: bar-001 (1/1 replicas created)", + "Events: ", + "Node-Selectors: ", + "Tolerations: ", }, }, { @@ -2516,8 +2519,8 @@ func TestDescribeDeployment(t *testing.T) { expects: []string{ "Replicas: 2 desired | 1 updated | 3 total | 2 available | 1 unavailable", "Image: mytest-image:v2.0", - "OldReplicaSets: bar-001 (2/2 replicas created)", - "NewReplicaSet: bar-002 (1/1 replicas created)", + "OldReplicaSets: bar-001 (2/2 replicas created)", + "NewReplicaSet: bar-002 (1/1 replicas created)", "Events:\n", "Normal ScalingReplicaSet 12m (x3 over 20m) deployment-controller Scaled up replica set bar-002 to 1", "Normal ScalingReplicaSet 10m deployment-controller Scaled up replica set bar-001 to 2", @@ -2810,8 +2813,8 @@ func TestDescribeDeployment(t *testing.T) { expects: []string{ "Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable", "Image: mytest-image:v2.0", - "OldReplicaSets: bar-001 (0/0 replicas created)", - "NewReplicaSet: bar-002 (2/2 replicas created)", + "OldReplicaSets: bar-001 (0/0 replicas created)", + "NewReplicaSet: bar-002 (2/2 replicas created)", "Events:\n", "Normal ScalingReplicaSet 12m (x3 over 20m) deployment-controller Scaled up replica set bar-002 to 1", "Normal ScalingReplicaSet 10m deployment-controller Scaled up replica set bar-001 to 2", @@ -2844,10 +2847,11 @@ func TestDescribeDeployment(t *testing.T) { func TestDescribeJob(t *testing.T) { indexedCompletion := batchv1.IndexedCompletion cases := map[string]struct { - job *batchv1.Job - wantCompletedIndexes string + job *batchv1.Job + wantElements []string + dontWantElements []string }{ - "not indexed": { + "empty job": { job: &batchv1.Job{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", @@ -2855,8 +2859,9 @@ func TestDescribeJob(t *testing.T) { }, Spec: batchv1.JobSpec{}, }, + dontWantElements: []string{"Completed Indexes:", "Suspend:", "Backoff Limit:", "TTL Seconds After Finished:"}, }, - "no indexes": { + "no completed indexes": { job: &batchv1.Job{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", @@ -2866,7 +2871,7 @@ func TestDescribeJob(t *testing.T) { CompletionMode: &indexedCompletion, }, }, - wantCompletedIndexes: "", + wantElements: []string{"Completed Indexes: "}, }, "few completed indexes": { job: &batchv1.Job{ @@ -2881,7 +2886,7 @@ func TestDescribeJob(t *testing.T) { CompletedIndexes: "0-5,7,9,10,12,13,15,16,18,20,21,23,24,26,27,29,30,32", }, }, - wantCompletedIndexes: "0-5,7,9,10,12,13,15,16,18,20,21,23,24,26,27,29,30,32", + wantElements: []string{"Completed Indexes: 0-5,7,9,10,12,13,15,16,18,20,21,23,24,26,27,29,30,32"}, }, "too many completed indexes": { job: &batchv1.Job{ @@ -2896,7 +2901,37 @@ func TestDescribeJob(t *testing.T) { CompletedIndexes: "0-5,7,9,10,12,13,15,16,18,20,21,23,24,26,27,29,30,32-34,36,37", }, }, - wantCompletedIndexes: "0-5,7,9,10,12,13,15,16,18,20,21,23,24,26,27,29,30,32-34,...", + wantElements: []string{"Completed Indexes: 0-5,7,9,10,12,13,15,16,18,20,21,23,24,26,27,29,30,32-34,..."}, + }, + "suspend set to true": { + job: &batchv1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: "bar", + Namespace: "foo", + }, + Spec: batchv1.JobSpec{ + Suspend: ptr.To(true), + TTLSecondsAfterFinished: ptr.To(int32(123)), + BackoffLimit: ptr.To(int32(1)), + }, + }, + wantElements: []string{ + "Suspend: true", + "TTL Seconds After Finished: 123", + "Backoff Limit: 1", + }, + }, + "suspend set to false": { + job: &batchv1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: "bar", + Namespace: "foo", + }, + Spec: batchv1.JobSpec{ + Suspend: ptr.To(false), + }, + }, + wantElements: []string{"Suspend: false"}, }, } for name, tc := range cases { @@ -2909,14 +2944,19 @@ func TestDescribeJob(t *testing.T) { describer := JobDescriber{Interface: client} out, err := describer.Describe(tc.job.Namespace, tc.job.Name, DescriberSettings{ShowEvents: true}) if err != nil { - t.Fatalf("Unexpected error describing object: %v", err) + t.Fatalf("unexpected error describing object: %v", err) } - if tc.wantCompletedIndexes != "" { - if !strings.Contains(out, fmt.Sprintf("Completed Indexes: %s\n", tc.wantCompletedIndexes)) { - t.Errorf("Output didn't contain wanted Completed Indexes:\n%s", out) + + for _, expected := range tc.wantElements { + if !strings.Contains(out, expected) { + t.Errorf("expected to find %q in output:\n %s", expected, out) + } + } + + for _, unexpected := range tc.dontWantElements { + if strings.Contains(out, unexpected) { + t.Errorf("unexpected to find %q in output:\n %s", unexpected, out) } - } else if strings.Contains(out, "Completed Indexes:") { - t.Errorf("Output contains unexpected completed indexes:\n%s", out) } }) } diff --git a/staging/src/k8s.io/kubectl/pkg/polymorphichelpers/history_test.go b/staging/src/k8s.io/kubectl/pkg/polymorphichelpers/history_test.go index 4f55326d0d5..239f30c6580 100644 --- a/staging/src/k8s.io/kubectl/pkg/polymorphichelpers/history_test.go +++ b/staging/src/k8s.io/kubectl/pkg/polymorphichelpers/history_test.go @@ -159,6 +159,8 @@ func TestViewDeploymentHistory(t *testing.T) { Environment: Mounts: Volumes: + Node-Selectors: + Tolerations: ` if result != expected { t.Fatalf("unexpected output (%v was expected but got %v)", expected, result) @@ -267,6 +269,8 @@ func TestViewHistory(t *testing.T) { Environment: Mounts: Volumes: + Node-Selectors: + Tolerations: ` if result != expected { @@ -371,6 +375,8 @@ func TestViewHistory(t *testing.T) { Environment: Mounts: Volumes: + Node-Selectors: + Tolerations: ` if result != expected {