From 9f90614c0a672e1e3343c6b58a3f5e5cc3b2c4a6 Mon Sep 17 00:00:00 2001 From: Dave Walter Date: Wed, 12 Jul 2023 17:57:50 -0700 Subject: [PATCH] Improve Build resource conditions Follow on from #1221 to set status condition reasons and messages on Builds based on the status of the corresponding build pod. Signed-off-by: Dave Walter --- pkg/reconciler/build/build.go | 17 ++++ pkg/reconciler/build/build_test.go | 131 +++++++++++++++++++++++------ 2 files changed, 121 insertions(+), 27 deletions(-) diff --git a/pkg/reconciler/build/build.go b/pkg/reconciler/build/build.go index d4fe734b3..961dd9f6e 100644 --- a/pkg/reconciler/build/build.go +++ b/pkg/reconciler/build/build.go @@ -240,6 +240,7 @@ func conditionForPod(pod *corev1.Pod, stepsCompleted []string) corev1alpha1.Cond { Type: corev1alpha1.ConditionSucceeded, Status: corev1.ConditionTrue, + Reason: ReasonCompleted, LastTransitionTime: corev1alpha1.VolatileTime{Inner: metav1.Now()}, }, } @@ -249,14 +250,30 @@ func conditionForPod(pod *corev1.Pod, stepsCompleted []string) corev1alpha1.Cond { Type: corev1alpha1.ConditionSucceeded, Status: corev1.ConditionTrue, + Reason: ReasonCompleted, LastTransitionTime: corev1alpha1.VolatileTime{Inner: metav1.Now()}, }, } } + for _, c := range pod.Status.InitContainerStatuses { + if c.State.Terminated != nil && c.State.Terminated.ExitCode != 0 && c.State.Terminated.Message != "" { + return corev1alpha1.Conditions{ + { + Type: corev1alpha1.ConditionSucceeded, + Status: corev1.ConditionFalse, + Reason: string(corev1.PodFailed), + Message: c.Name + " failed: " + c.State.Terminated.Message, + LastTransitionTime: corev1alpha1.VolatileTime{Inner: metav1.Now()}, + }, + } + } + } return corev1alpha1.Conditions{ { Type: corev1alpha1.ConditionSucceeded, Status: corev1.ConditionFalse, + Reason: string(corev1.PodFailed), + Message: pod.Status.Message, LastTransitionTime: corev1alpha1.VolatileTime{Inner: metav1.Now()}, }, } diff --git a/pkg/reconciler/build/build_test.go b/pkg/reconciler/build/build_test.go index 75c1d5f14..78d86ac6b 100644 --- a/pkg/reconciler/build/build_test.go +++ b/pkg/reconciler/build/build_test.go @@ -572,6 +572,7 @@ func testBuildReconciler(t *testing.T, when spec.G, it spec.S) { { Type: corev1alpha1.ConditionSucceeded, Status: corev1.ConditionTrue, + Reason: build.ReasonCompleted, }, }, }, @@ -752,6 +753,7 @@ func testBuildReconciler(t *testing.T, when spec.G, it spec.S) { { Type: corev1alpha1.ConditionSucceeded, Status: corev1.ConditionTrue, + Reason: build.ReasonCompleted, }, }, }, @@ -901,8 +903,10 @@ func testBuildReconciler(t *testing.T, when spec.G, it spec.S) { ObservedGeneration: originalGeneration, Conditions: corev1alpha1.Conditions{ { - Type: corev1alpha1.ConditionSucceeded, - Status: corev1.ConditionFalse, + Type: corev1alpha1.ConditionSucceeded, + Status: corev1.ConditionFalse, + Reason: string(corev1.PodFailed), + Message: "prepare failed: Errors", }, }, }, @@ -974,6 +978,83 @@ func testBuildReconciler(t *testing.T, when spec.G, it spec.S) { WantErr: false, }) }) + + when("the failed container's status does not include a message", func() { + it("sets the build's status condition message to the pod's status message", func() { + pod, err := podGenerator.Generate(ctx, bld) + require.NoError(t, err) + pod.Status.Phase = corev1.PodFailed + pod.Status.InitContainerStatuses = []corev1.ContainerStatus{ + { + Name: "prepare", + State: corev1.ContainerState{ + Terminated: &corev1.ContainerStateTerminated{ + ExitCode: 1, + Reason: "Terminated", + ContainerID: "container.ID", + }, + }, + }, + { + Name: "analyze", + State: corev1.ContainerState{ + Waiting: &corev1.ContainerStateWaiting{ + Reason: "Waiting", + Message: "My Turn", + }, + }, + }, + } + pod.Status.Message = "Something bad happened" + + rt.Test(rtesting.TableRow{ + Key: key, + Objects: []runtime.Object{ + bld, + pod, + }, + WantErr: false, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{ + { + Object: &buildapi.Build{ + ObjectMeta: bld.ObjectMeta, + Spec: bld.Spec, + Status: buildapi.BuildStatus{ + Status: corev1alpha1.Status{ + ObservedGeneration: originalGeneration, + Conditions: corev1alpha1.Conditions{ + { + Type: corev1alpha1.ConditionSucceeded, + Status: corev1.ConditionFalse, + Reason: string(corev1.PodFailed), + Message: "Something bad happened", + }, + }, + }, + PodName: "build-name-build-pod", + StepStates: []corev1.ContainerState{ + { + Terminated: &corev1.ContainerStateTerminated{ + ExitCode: 1, + Reason: "Terminated", + ContainerID: "container.ID", + }, + }, + { + Waiting: &corev1.ContainerStateWaiting{ + Reason: "Waiting", + Message: "My Turn", + }, + }, + }, + StepsCompleted: []string{}, + }, + }, + }, + }, + }) + }) + }) }) when("a build pod cannot be created", func() { @@ -1130,7 +1211,6 @@ func testBuildReconciler(t *testing.T, when spec.G, it spec.S) { }) it("marks build as successful if completion completes even if pod fails", func() { - compressedBuildMetadata, err := os.ReadFile(filepath.Join("testdata", "metadata")) require.NoError(t, err) @@ -1184,40 +1264,36 @@ func testBuildReconciler(t *testing.T, when spec.G, it spec.S) { }, } - build := &buildapi.Build{ - ObjectMeta: bld.ObjectMeta, - Spec: bld.Spec, - Status: buildapi.BuildStatus{ - Status: corev1alpha1.Status{ - ObservedGeneration: originalGeneration, - Conditions: corev1alpha1.Conditions{ - { - Type: corev1alpha1.ConditionSucceeded, - Status: corev1.ConditionUnknown, - }, - }, - }, - PodName: "build-name-build-pod", - StepStates: []corev1.ContainerState{ + bld.Status = buildapi.BuildStatus{ + Status: corev1alpha1.Status{ + ObservedGeneration: originalGeneration, + Conditions: corev1alpha1.Conditions{ { - Terminated: &corev1.ContainerStateTerminated{ - ExitCode: 0, - Reason: "Terminated", - Message: string(compressedBuildMetadata), - ContainerID: "container.ID", - }, + Type: corev1alpha1.ConditionSucceeded, + Status: corev1.ConditionUnknown, }, }, - StepsCompleted: []string{ - "completion", + }, + PodName: "build-name-build-pod", + StepStates: []corev1.ContainerState{ + { + Terminated: &corev1.ContainerStateTerminated{ + ExitCode: 0, + Reason: "Terminated", + Message: string(compressedBuildMetadata), + ContainerID: "container.ID", + }, }, }, + StepsCompleted: []string{ + "completion", + }, } rt.Test(rtesting.TableRow{ Key: key, Objects: []runtime.Object{ - build, + bld, pod, }, WantErr: false, @@ -1233,6 +1309,7 @@ func testBuildReconciler(t *testing.T, when spec.G, it spec.S) { { Type: corev1alpha1.ConditionSucceeded, Status: corev1.ConditionTrue, + Reason: build.ReasonCompleted, }, }, },