diff --git a/changelogs/unreleased/8271-mcluseau b/changelogs/unreleased/8271-mcluseau new file mode 100644 index 0000000000..189d797bc8 --- /dev/null +++ b/changelogs/unreleased/8271-mcluseau @@ -0,0 +1 @@ +fix(pkg/repository/maintenance): don't panic when there's no container statuses diff --git a/pkg/repository/maintenance.go b/pkg/repository/maintenance.go index 1a137cba90..5ea63979f0 100644 --- a/pkg/repository/maintenance.go +++ b/pkg/repository/maintenance.go @@ -117,7 +117,20 @@ func GetMaintenanceResultFromJob(cli client.Client, job *batchv1.Job) (string, e } // we only have one maintenance pod for the job - return podList.Items[0].Status.ContainerStatuses[0].State.Terminated.Message, nil + pod := podList.Items[0] + + statuses := pod.Status.ContainerStatuses + if len(statuses) == 0 { + return "", fmt.Errorf("no container statuses found for job %s", job.Name) + } + + // we only have one maintenance container + terminated := statuses[0].State.Terminated + if terminated == nil { + return "", fmt.Errorf("container for job %s is not terminated", job.Name) + } + + return terminated.Message, nil } func GetLatestMaintenanceJob(cli client.Client, ns string) (*batchv1.Job, error) { diff --git a/pkg/repository/maintenance_test.go b/pkg/repository/maintenance_test.go index 5077942180..f6344b166a 100644 --- a/pkg/repository/maintenance_test.go +++ b/pkg/repository/maintenance_test.go @@ -188,33 +188,54 @@ func TestGetMaintenanceResultFromJob(t *testing.T) { }, } - // Set up test pod + // Set up test pod with no status pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "test-pod", Namespace: "default", Labels: map[string]string{"job-name": job.Name}, }, - Status: v1.PodStatus{ - ContainerStatuses: []v1.ContainerStatus{ - { - State: v1.ContainerState{ - Terminated: &v1.ContainerStateTerminated{ - Message: "test message", - }, - }, - }, - }, - }, } // Create a fake Kubernetes client cli := fake.NewClientBuilder().WithObjects(job, pod).Build() - // Call the function + // test an error should be returned result, err := GetMaintenanceResultFromJob(cli, job) + assert.Error(t, err) + assert.Equal(t, "", result) + + // Set a non-terminated container status to the pod + pod.Status = v1.PodStatus{ + ContainerStatuses: []v1.ContainerStatus{ + { + State: v1.ContainerState{}, + }, + }, + } + + // Test an error should be returned + cli = fake.NewClientBuilder().WithObjects(job, pod).Build() + result, err = GetMaintenanceResultFromJob(cli, job) + assert.Error(t, err) + assert.Equal(t, "", result) + + // Set a terminated container status to the pod + pod.Status = v1.PodStatus{ + ContainerStatuses: []v1.ContainerStatus{ + { + State: v1.ContainerState{ + Terminated: &v1.ContainerStateTerminated{ + Message: "test message", + }, + }, + }, + }, + } - // Check if the result and error match the expectation + // This call should return the termination message with no error + cli = fake.NewClientBuilder().WithObjects(job, pod).Build() + result, err = GetMaintenanceResultFromJob(cli, job) assert.NoError(t, err) assert.Equal(t, "test message", result) }