From 62a0b409ed77ad5cf8091f4837566c062bf78e88 Mon Sep 17 00:00:00 2001 From: Haoyu Sun Date: Thu, 16 Oct 2025 12:52:33 +0200 Subject: [PATCH 1/2] test: trigger bundle test Signed-off-by: Haoyu Sun --- related_images.json | 1 + 1 file changed, 1 insertion(+) diff --git a/related_images.json b/related_images.json index f0c690b15..0f4a8dab6 100644 --- a/related_images.json +++ b/related_images.json @@ -32,4 +32,5 @@ "image": "registry.redhat.io/openshift-lightspeed/lightspeed-operator-bundle@sha256:2ca4638bfc967b0a623c7c6f4170765a38662189653a343b5de5cbd8e26d9595", "revision": "e8383723a47af947ec49f3d01659d65065c66c86" } + ] From 772230d5d19a2f9f4ce8537b29177e6725aa261c Mon Sep 17 00:00:00 2001 From: Haoyu Sun Date: Thu, 16 Oct 2025 14:48:43 +0200 Subject: [PATCH 2/2] test: show unavailable replica status in test Signed-off-by: Haoyu Sun --- test/e2e/client.go | 116 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/test/e2e/client.go b/test/e2e/client.go index 44292051e..fe5bce1bc 100644 --- a/test/e2e/client.go +++ b/test/e2e/client.go @@ -166,6 +166,7 @@ func (c *Client) WaitForDeploymentRollout(dep *appsv1.Deployment) error { dep.Status.Replicas, dep.Status.UpdatedReplicas) } if dep.Status.UnavailableReplicas != 0 { + c.ShowUnavailablePodsOfDeployment(dep) return false, fmt.Errorf("got %d unavailable replicas", dep.Status.UnavailableReplicas) } @@ -199,6 +200,121 @@ func (c *Client) WaitForDeploymentCondition(dep *appsv1.Deployment, condition fu return nil } +func (c *Client) ShowUnavailablePodsOfDeployment(dep *appsv1.Deployment) error { + err := c.Get(dep) + if err != nil { + return fmt.Errorf("failed to get deployment %s/%s: %w", dep.GetNamespace(), dep.GetName(), err) + } + + selector, err := metav1.LabelSelectorAsSelector(dep.Spec.Selector) + if err != nil { + return fmt.Errorf("failed to parse deployment selector: %w", err) + } + + pods := &corev1.PodList{} + err = c.List(pods, client.InNamespace(dep.GetNamespace()), client.MatchingLabelsSelector{ + Selector: selector, + }) + if err != nil { + return fmt.Errorf("failed to list pods for deployment %s/%s: %w", dep.GetNamespace(), dep.GetName(), err) + } + + if len(pods.Items) == 0 { + logf.Log.Info("No pods found for deployment", "deployment", fmt.Sprintf("%s/%s", dep.GetNamespace(), dep.GetName())) + return nil + } + + // Find unavailable pods + unavailablePods := []corev1.Pod{} + for _, pod := range pods.Items { + isAvailable := false + + // A pod is considered available if it's running and ready + if pod.Status.Phase == corev1.PodRunning && !c.isPodTerminating(&pod) { + for _, condition := range pod.Status.Conditions { + if condition.Type == corev1.PodReady && condition.Status == corev1.ConditionTrue { + isAvailable = true + break + } + } + } + + if !isAvailable { + unavailablePods = append(unavailablePods, pod) + } + } + + // Log unavailable pods and their status messages + if len(unavailablePods) == 0 { + logf.Log.Info("All pods are available for deployment", "deployment", fmt.Sprintf("%s/%s", dep.GetNamespace(), dep.GetName())) + } else { + logf.Log.Info("Found unavailable pods", "deployment", fmt.Sprintf("%s/%s", dep.GetNamespace(), dep.GetName()), "count", len(unavailablePods)) + + for _, pod := range unavailablePods { + logf.Log.Info("Unavailable pod details", + "pod", pod.Name, + "phase", pod.Status.Phase, + "reason", pod.Status.Reason, + "message", pod.Status.Message, + ) + + // Show container statuses + for _, containerStatus := range pod.Status.ContainerStatuses { + logf.Log.Info("Container status", + "pod", pod.Name, + "container", containerStatus.Name, + "ready", containerStatus.Ready, + "restartCount", containerStatus.RestartCount, + ) + + if containerStatus.State.Waiting != nil { + logf.Log.Info("Container waiting", + "pod", pod.Name, + "container", containerStatus.Name, + "reason", containerStatus.State.Waiting.Reason, + "message", containerStatus.State.Waiting.Message, + ) + } + + if containerStatus.State.Terminated != nil { + logf.Log.Info("Container terminated", + "pod", pod.Name, + "container", containerStatus.Name, + "reason", containerStatus.State.Terminated.Reason, + "message", containerStatus.State.Terminated.Message, + "exitCode", containerStatus.State.Terminated.ExitCode, + ) + } + + if containerStatus.LastTerminationState.Terminated != nil { + logf.Log.Info("Container last termination", + "pod", pod.Name, + "container", containerStatus.Name, + "reason", containerStatus.LastTerminationState.Terminated.Reason, + "message", containerStatus.LastTerminationState.Terminated.Message, + "exitCode", containerStatus.LastTerminationState.Terminated.ExitCode, + ) + } + } + + // Show pod conditions + for _, condition := range pod.Status.Conditions { + if condition.Status != corev1.ConditionTrue { + logf.Log.Info("Pod condition not met", + "pod", pod.Name, + "type", condition.Type, + "status", condition.Status, + "reason", condition.Reason, + "message", condition.Message, + ) + } + } + } + } + + return nil +} + func (c *Client) WaitForConfigMapContainString(cm *corev1.ConfigMap, key, substr string) error { var lastErr error err := wait.PollUntilContextTimeout(c.ctx, DefaultPollInterval, c.conditionCheckTimeout, true, func(ctx context.Context) (bool, error) {