package cluster import ( "context" "fmt" "strconv" "strings" "time" ) // workloadReady runs one orchestration or CLI step. // Signature: (o *Orchestrator) workloadReady(ctx context.Context, w startupWorkload) (bool, error). // Why: keeps behavior explicit so startup/shutdown workflows remain maintainable as services evolve. func (o *Orchestrator) workloadReady(ctx context.Context, w startupWorkload) (bool, error) { out, err := o.kubectl( ctx, 20*time.Second, "-n", w.Namespace, "get", w.Kind, w.Name, "-o", "jsonpath={.status.readyReplicas}", ) if err != nil { return false, err } raw := strings.TrimSpace(out) if raw == "" || raw == "" { return false, nil } n, err := strconv.Atoi(raw) if err != nil { return false, fmt.Errorf("parse readyReplicas %q: %w", raw, err) } return n >= 1, nil } // isNotFoundErr runs one orchestration or CLI step. // Signature: isNotFoundErr(err error) bool. // Why: keeps behavior explicit so startup/shutdown workflows remain maintainable as services evolve. func isNotFoundErr(err error) bool { if err == nil { return false } msg := strings.ToLower(err.Error()) return strings.Contains(msg, "not found") || strings.Contains(msg, "(notfound)") }