fixed output and completed pod phase

Signed-off-by: Suleiman Dibirov <idsulik@gmail.com>
pull/13121/head
Suleiman Dibirov 2 weeks ago
parent 8a7581f03f
commit 56fc24668f

@ -19,7 +19,9 @@ package kube // import "helm.sh/helm/v3/pkg/kube"
import ( import (
"context" "context"
"fmt" "fmt"
"strings"
"github.com/hashicorp/go-multierror"
appsv1 "k8s.io/api/apps/v1" appsv1 "k8s.io/api/apps/v1"
appsv1beta1 "k8s.io/api/apps/v1beta1" appsv1beta1 "k8s.io/api/apps/v1beta1"
appsv1beta2 "k8s.io/api/apps/v1beta2" appsv1beta2 "k8s.io/api/apps/v1beta2"
@ -38,13 +40,6 @@ import (
deploymentutil "helm.sh/helm/v3/internal/third_party/k8s.io/kubernetes/deployment/util" deploymentutil "helm.sh/helm/v3/internal/third_party/k8s.io/kubernetes/deployment/util"
) )
type podError struct {
podName string
container string
reason string
message string
}
// ReadyCheckerOption is a function that configures a ReadyChecker. // ReadyCheckerOption is a function that configures a ReadyChecker.
type ReadyCheckerOption func(*ReadyChecker) type ReadyCheckerOption func(*ReadyChecker)
@ -100,12 +95,11 @@ func (c *ReadyChecker) IsReady(ctx context.Context, v *resource.Info) (bool, err
switch value := AsVersioned(v).(type) { switch value := AsVersioned(v).(type) {
case *corev1.Pod: case *corev1.Pod:
pod, err := c.client.CoreV1().Pods(v.Namespace).Get(ctx, v.Name, metav1.GetOptions{}) pod, err := c.client.CoreV1().Pods(v.Namespace).Get(ctx, v.Name, metav1.GetOptions{})
if err != nil || !c.isPodReady(pod) { if err != nil {
if err == nil {
err = c.getPodFailedError(pod)
}
return false, err return false, err
} }
ready, err := c.isPodReady(pod)
return ready, err
case *batchv1.Job: case *batchv1.Job:
if c.checkJobs { if c.checkJobs {
job, err := c.client.BatchV1().Jobs(v.Namespace).Get(ctx, v.Name, metav1.GetOptions{}) job, err := c.client.BatchV1().Jobs(v.Namespace).Get(ctx, v.Name, metav1.GetOptions{})
@ -215,7 +209,7 @@ func (c *ReadyChecker) IsReady(ctx context.Context, v *resource.Info) (bool, err
} }
func (c *ReadyChecker) getPodFailedError(pod *corev1.Pod) error { func (c *ReadyChecker) getPodFailedError(pod *corev1.Pod) error {
podErrors := make([]podError, 0) var err error
if pod.Status.Phase == corev1.PodFailed { if pod.Status.Phase == corev1.PodFailed {
containerStatuses := pod.Status.ContainerStatuses containerStatuses := pod.Status.ContainerStatuses
if pod.Status.InitContainerStatuses != nil { if pod.Status.InitContainerStatuses != nil {
@ -224,28 +218,32 @@ func (c *ReadyChecker) getPodFailedError(pod *corev1.Pod) error {
for _, cs := range containerStatuses { for _, cs := range containerStatuses {
if cs.State.Terminated != nil { if cs.State.Terminated != nil {
podErrors = append(podErrors, podError{ err = multierror.Append(
podName: pod.Name, err,
container: cs.Name, fmt.Errorf(
reason: cs.State.Terminated.Reason, "pod: %q, container: %q. reason: %q. message: %q",
message: cs.State.Terminated.Message, pod.Name,
}) cs.Name,
cs.State.Terminated.Reason,
strings.TrimSpace(cs.State.Terminated.Message),
),
)
} else if cs.State.Waiting != nil { } else if cs.State.Waiting != nil {
podErrors = append(podErrors, podError{ err = multierror.Append(
podName: pod.Name, err,
container: cs.Name, fmt.Errorf(
reason: cs.State.Waiting.Reason, "pod: %q, container: %q. reason: %q. message: %q",
message: cs.State.Waiting.Message, pod.Name,
}) cs.Name,
cs.State.Waiting.Reason,
strings.TrimSpace(cs.State.Waiting.Message),
),
)
} }
} }
} }
if len(podErrors) > 0 { return err
return fmt.Errorf("%+v", podErrors)
}
return nil
} }
func (c *ReadyChecker) podsReadyForObject(ctx context.Context, namespace string, obj runtime.Object) (bool, error) { func (c *ReadyChecker) podsReadyForObject(ctx context.Context, namespace string, obj runtime.Object) (bool, error) {
@ -254,8 +252,8 @@ func (c *ReadyChecker) podsReadyForObject(ctx context.Context, namespace string,
return false, err return false, err
} }
for _, pod := range pods { for _, pod := range pods {
if !c.isPodReady(&pod) { if isReady, err := c.isPodReady(&pod); !isReady {
return false, nil return false, err
} }
} }
return true, nil return true, nil
@ -270,15 +268,26 @@ func (c *ReadyChecker) podsforObject(ctx context.Context, namespace string, obj
return list, err return list, err
} }
// isPodReady returns true if a pod is ready; false otherwise. // isPodReady returns true if the pod is ready, false if it is not ready, and an error if the pod is in a failed state.
func (c *ReadyChecker) isPodReady(pod *corev1.Pod) bool { func (c *ReadyChecker) isPodReady(pod *corev1.Pod) (bool, error) {
for _, c := range pod.Status.Conditions { if pod.Status.Phase == corev1.PodSucceeded {
if c.Type == corev1.PodReady && c.Status == corev1.ConditionTrue { return true, nil
return true }
err := c.getPodFailedError(pod)
if err != nil {
c.log("Pod is failed: %s/%s", pod.GetNamespace(), pod.GetName())
return false, err
}
for _, condition := range pod.Status.Conditions {
if condition.Type == corev1.PodReady && condition.Status == corev1.ConditionTrue {
return true, nil
} }
} }
c.log("Pod is not ready: %s/%s", pod.GetNamespace(), pod.GetName()) c.log("Pod is not ready: %s/%s", pod.GetNamespace(), pod.GetName())
return false return false, nil
} }
func (c *ReadyChecker) jobReady(job *batchv1.Job) (bool, error) { func (c *ReadyChecker) jobReady(job *batchv1.Job) (bool, error) {

Loading…
Cancel
Save