From 8854d360a5d75d71b47178c9ac2788dd2de5319a Mon Sep 17 00:00:00 2001 From: Ivan Valdes Date: Fri, 16 Feb 2024 13:02:23 -0800 Subject: [PATCH] printers: add status to jobs table --- pkg/printers/internalversion/printers.go | 26 +++- pkg/printers/internalversion/printers_test.go | 133 ++++++++++++++++-- 2 files changed, 145 insertions(+), 14 deletions(-) diff --git a/pkg/printers/internalversion/printers.go b/pkg/printers/internalversion/printers.go index 6ce614d3a274..15b27f73b92b 100644 --- a/pkg/printers/internalversion/printers.go +++ b/pkg/printers/internalversion/printers.go @@ -167,6 +167,7 @@ func AddHandlers(h printers.PrintHandler) { jobColumnDefinitions := []metav1.TableColumnDefinition{ {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, + {Name: "Status", Type: "string", Description: "Status of the job."}, {Name: "Completions", Type: "string", Description: batchv1.JobStatus{}.SwaggerDoc()["succeeded"]}, {Name: "Duration", Type: "string", Description: "Time required to complete the job."}, {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, @@ -1013,6 +1014,15 @@ func hasPodReadyCondition(conditions []api.PodCondition) bool { return false } +func hasJobCondition(conditions []batch.JobCondition, conditionType batch.JobConditionType) bool { + for _, condition := range conditions { + if condition.Type == conditionType { + return condition.Status == api.ConditionTrue + } + } + return false +} + func printPodTemplate(obj *api.PodTemplate, options printers.GenerateOptions) ([]metav1.TableRow, error) { row := metav1.TableRow{ Object: runtime.RawExtension{Object: obj}, @@ -1155,8 +1165,22 @@ func printJob(obj *batch.Job, options printers.GenerateOptions) ([]metav1.TableR default: jobDuration = duration.HumanDuration(obj.Status.CompletionTime.Sub(obj.Status.StartTime.Time)) } + var status string + if hasJobCondition(obj.Status.Conditions, batch.JobComplete) { + status = "Complete" + } else if hasJobCondition(obj.Status.Conditions, batch.JobFailed) { + status = "Failed" + } else if obj.ObjectMeta.DeletionTimestamp != nil { + status = "Terminating" + } else if hasJobCondition(obj.Status.Conditions, batch.JobSuspended) { + status = "Suspended" + } else if hasJobCondition(obj.Status.Conditions, batch.JobFailureTarget) { + status = "FailureTarget" + } else { + status = "Running" + } - row.Cells = append(row.Cells, obj.Name, completions, jobDuration, translateTimestampSince(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, status, completions, jobDuration, translateTimestampSince(obj.CreationTimestamp)) if options.Wide { names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers) row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.Selector)) diff --git a/pkg/printers/internalversion/printers_test.go b/pkg/printers/internalversion/printers_test.go index 3311cb05e3f6..5a359103dd24 100644 --- a/pkg/printers/internalversion/printers_test.go +++ b/pkg/printers/internalversion/printers_test.go @@ -2527,8 +2527,8 @@ func TestPrintJob(t *testing.T) { }, }, options: printers.GenerateOptions{}, - // Columns: Name, Completions, Duration, Age - expected: []metav1.TableRow{{Cells: []interface{}{"job1", "1/2", "", "0s"}}}, + // Columns: Name, Status, Completions, Duration, Age + expected: []metav1.TableRow{{Cells: []interface{}{"job1", "Running", "1/2", "", "0s"}}}, }, // Generate table rows for Job with generate options "Wide". { @@ -2560,10 +2560,10 @@ func TestPrintJob(t *testing.T) { }, }, options: printers.GenerateOptions{Wide: true}, - // Columns: Name, Completions, Duration, Age, Containers, Images, Selectors + // Columns: Name, Status, Completions, Duration, Age, Containers, Images, Selectors expected: []metav1.TableRow{ { - Cells: []interface{}{"job1", "1/2", "", "0s", "fake-job-container1,fake-job-container2", "fake-job-image1,fake-job-image2", "job-label=job-label-value"}, + Cells: []interface{}{"job1", "Running", "1/2", "", "0s", "fake-job-container1,fake-job-container2", "fake-job-image1,fake-job-image2", "job-label=job-label-value"}, }, }, }, @@ -2582,8 +2582,8 @@ func TestPrintJob(t *testing.T) { }, }, options: printers.GenerateOptions{}, - // Columns: Name, Completions, Duration, Age - expected: []metav1.TableRow{{Cells: []interface{}{"job2", "0/1", "", "10y"}}}, + // Columns: Name, Status, Completions, Duration, Age + expected: []metav1.TableRow{{Cells: []interface{}{"job2", "Running", "0/1", "", "10y"}}}, }, // Job with duration. { @@ -2602,8 +2602,8 @@ func TestPrintJob(t *testing.T) { }, }, options: printers.GenerateOptions{}, - // Columns: Name, Completions, Duration, Age - expected: []metav1.TableRow{{Cells: []interface{}{"job3", "0/1", "30m", "10y"}}}, + // Columns: Name, Status, Completions, Duration, Age + expected: []metav1.TableRow{{Cells: []interface{}{"job3", "Running", "0/1", "30m", "10y"}}}, }, { job: batch.Job{ @@ -2620,8 +2620,115 @@ func TestPrintJob(t *testing.T) { }, }, options: printers.GenerateOptions{}, - // Columns: Name, Completions, Duration, Age - expected: []metav1.TableRow{{Cells: []interface{}{"job4", "0/1", "20m", "10y"}}}, + // Columns: Name, Status, Completions, Duration, Age + expected: []metav1.TableRow{{Cells: []interface{}{"job4", "Running", "0/1", "20m", "10y"}}}, + }, + { + job: batch.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: "job5", + CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)}, + }, + Spec: batch.JobSpec{ + Completions: nil, + }, + Status: batch.JobStatus{ + Succeeded: 0, + Conditions: []batch.JobCondition{ + { + Type: batch.JobComplete, + Status: api.ConditionTrue, + }, + }, + }, + }, + options: printers.GenerateOptions{}, + // Columns: Name, Status, Completions, Duration, Age + expected: []metav1.TableRow{{Cells: []interface{}{"job5", "Complete", "0/1", "", "0s"}}}, + }, + { + job: batch.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: "job6", + CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)}, + }, + Spec: batch.JobSpec{ + Completions: nil, + }, + Status: batch.JobStatus{ + Succeeded: 0, + Conditions: []batch.JobCondition{ + { + Type: batch.JobFailed, + Status: api.ConditionTrue, + }, + }, + }, + }, + options: printers.GenerateOptions{}, + // Columns: Name, Status, Completions, Duration, Age + expected: []metav1.TableRow{{Cells: []interface{}{"job6", "Failed", "0/1", "", "0s"}}}, + }, + { + job: batch.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: "job7", + CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)}, + }, + Spec: batch.JobSpec{ + Completions: nil, + }, + Status: batch.JobStatus{ + Succeeded: 0, + Conditions: []batch.JobCondition{ + { + Type: batch.JobSuspended, + Status: api.ConditionTrue, + }, + }, + }, + }, + options: printers.GenerateOptions{}, + // Columns: Name, Status, Completions, Duration, Age + expected: []metav1.TableRow{{Cells: []interface{}{"job7", "Suspended", "0/1", "", "0s"}}}, + }, + { + job: batch.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: "job8", + CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)}, + }, + Spec: batch.JobSpec{ + Completions: nil, + }, + Status: batch.JobStatus{ + Succeeded: 0, + Conditions: []batch.JobCondition{ + { + Type: batch.JobFailureTarget, + Status: api.ConditionTrue, + }, + }, + }, + }, + options: printers.GenerateOptions{}, + // Columns: Name, Status, Completions, Duration, Age + expected: []metav1.TableRow{{Cells: []interface{}{"job8", "FailureTarget", "0/1", "", "0s"}}}, + }, + { + job: batch.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: "job9", + CreationTimestamp: metav1.Time{Time: time.Now().Add(1.9e9)}, + DeletionTimestamp: &metav1.Time{Time: time.Now().Add(1.9e9)}, + }, + Spec: batch.JobSpec{ + Completions: nil, + }, + }, + options: printers.GenerateOptions{}, + // Columns: Name, Status, Completions, Duration, Age + expected: []metav1.TableRow{{Cells: []interface{}{"job9", "Terminating", "0/1", "", "0s"}}}, }, } @@ -2701,10 +2808,10 @@ func TestPrintJobList(t *testing.T) { }, } - // Columns: Name, Completions, Duration, Age + // Columns: Name, Status, Completions, Duration, Age expectedRows := []metav1.TableRow{ - {Cells: []interface{}{"job1", "1/2", "", "0s"}}, - {Cells: []interface{}{"job2", "2/2", "20m", "0s"}}, + {Cells: []interface{}{"job1", "Running", "1/2", "", "0s"}}, + {Cells: []interface{}{"job2", "Running", "2/2", "20m", "0s"}}, } rows, err := printJobList(&jobList, printers.GenerateOptions{})