Ctrl K
ComunidadGuías…

pkg/health/controller.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package health

import (
	"fmt"
	corev1 "k8s.io/api/core/v1"
)

// ControllerPodHealth summarizes readiness and failure signals from controller pods.
type ControllerPodHealth struct {
	Ready       int
	Total       int
	Crashing    int
	Pending     int
	CrashReason string
}

// SummarizeControllerPods counts the supplied pods without filtering their lifecycle.
// Callers that require only active pods must filter before calling.
func SummarizeControllerPods(pods []*corev1.Pod) ControllerPodHealth {
	out := ControllerPodHealth{Total: len(pods)}
	for _, p := range pods {
		for _, cs := range p.Status.ContainerStatuses {
			if cs.State.Waiting != nil && (cs.State.Waiting.Reason == "CrashLoopBackOff" || cs.State.Waiting.Reason == "Error") {
				out.Crashing++
				if out.CrashReason == "" {
					out.CrashReason = cs.State.Waiting.Reason
				}
				break
			}
		}
		ready := p.Status.Phase == corev1.PodRunning
		for _, cs := range p.Status.ContainerStatuses {
			if !cs.Ready {
				ready = false
			}
		}
		if ready {
			out.Ready++
		}
		if p.Status.Phase == corev1.PodPending {
			out.Pending++
		}
	}
	if out.Ready > out.Total {
		out.Ready = out.Total
	}
	return out
}

// SummarizeControllerHealth distills a slice of controller pods into a
// short, operator-readable status verb. Aggregates over multiple
// replicas (Argo's controller is typically deployed as a 2-replica
// StatefulSet for HA): if any pod is in CrashLoopBackOff or Error, that
// fact dominates the status. If all pods are Ready, "healthy". Anything
// in between is "degraded" with a count.
func SummarizeControllerHealth(controller string, pods []*corev1.Pod) string {
	return controller + " is " + DescribeControllerHealth(pods)
}

// DescribeControllerHealth returns the status phrase SummarizeControllerHealth
// puts after "<controller> is", such as "CrashLoopBackOff (1/1 pods)".
func DescribeControllerHealth(pods []*corev1.Pod) string {
	health := SummarizeControllerPods(pods)
	switch {
	case health.Crashing > 0:
		return fmt.Sprintf("%s (%d/%d pods)", health.CrashReason, health.Crashing, health.Total)
	case health.Ready == health.Total && health.Total > 0:
		// All pods Ready — if the resource is *still* stuck deleting
		// despite a healthy controller, it's a different problem (RBAC,
		// network, broken finalizer logic). Surface the healthy state
		// so the operator knows to dig into the controller's logs
		// rather than its lifecycle.
		suffix := "s"
		if health.Ready == 1 {
			suffix = ""
		}
		return fmt.Sprintf("healthy (%d pod%s ready)", health.Ready, suffix)
	case health.Pending > 0:
		return fmt.Sprintf("pending start (%d/%d pods Pending)", health.Pending, health.Total)
	default:
		return fmt.Sprintf("degraded (%d/%d pods ready)", health.Ready, health.Total)
	}
}