fix: address review feedback - caption coloring, termWidth, O(1) pod detection, display tests
Agent-Logs-Url: https://github.com/helmfile/helmfile/sessions/147fc763-c3f2-4a7e-9591-6f972fb62667 Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
This commit is contained in:
parent
901c6c3a2a
commit
980dcb5d19
|
|
@ -7,6 +7,8 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/term"
|
||||
|
||||
"github.com/werf/kubedog/pkg/tracker/daemonset"
|
||||
"github.com/werf/kubedog/pkg/tracker/deployment"
|
||||
"github.com/werf/kubedog/pkg/tracker/indicators"
|
||||
|
|
@ -209,15 +211,16 @@ func displayChildPodsStatusProgress(t *utils.Table, prevPods, pods map[string]po
|
|||
sort.Strings(podsNames)
|
||||
|
||||
var podRows [][]interface{}
|
||||
|
||||
newPodSet := make(map[string]struct{}, len(newPodsNames))
|
||||
for _, name := range newPodsNames {
|
||||
newPodSet[name] = struct{}{}
|
||||
}
|
||||
|
||||
for _, podName := range podsNames {
|
||||
var podRow []interface{}
|
||||
|
||||
isPodNew := false
|
||||
for _, newPodName := range newPodsNames {
|
||||
if newPodName == podName {
|
||||
isPodNew = true
|
||||
}
|
||||
}
|
||||
_, isPodNew := newPodSet[podName]
|
||||
|
||||
prevPodStatus := prevPods[podName]
|
||||
podStatus := pods[podName]
|
||||
|
|
@ -278,6 +281,9 @@ func formatResourceWarning(reason string) string {
|
|||
}
|
||||
|
||||
func termWidth() int {
|
||||
if w, _, err := term.GetSize(int(os.Stderr.Fd())); err == nil && w > 0 {
|
||||
return w
|
||||
}
|
||||
return 140
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,445 @@
|
|||
package kubedog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/werf/kubedog/pkg/tracker/daemonset"
|
||||
"github.com/werf/kubedog/pkg/tracker/deployment"
|
||||
"github.com/werf/kubedog/pkg/tracker/job"
|
||||
"github.com/werf/kubedog/pkg/tracker/pod"
|
||||
"github.com/werf/kubedog/pkg/tracker/statefulset"
|
||||
)
|
||||
|
||||
// --- formatResourceCaption ---
|
||||
|
||||
func TestFormatResourceCaption_Ready(t *testing.T) {
|
||||
result := formatResourceCaption("deploy/myapp", true, false)
|
||||
assert.Contains(t, result, "deploy/myapp")
|
||||
// Green ANSI escape should be present
|
||||
assert.Contains(t, result, "\033[")
|
||||
}
|
||||
|
||||
func TestFormatResourceCaption_Failed(t *testing.T) {
|
||||
result := formatResourceCaption("deploy/myapp", false, true)
|
||||
assert.Contains(t, result, "deploy/myapp")
|
||||
assert.Contains(t, result, "\033[")
|
||||
}
|
||||
|
||||
func TestFormatResourceCaption_InProgress(t *testing.T) {
|
||||
result := formatResourceCaption("deploy/myapp", false, false)
|
||||
assert.Contains(t, result, "deploy/myapp")
|
||||
// Yellow for in-progress
|
||||
assert.Contains(t, result, "\033[")
|
||||
}
|
||||
|
||||
func TestFormatResourceCaption_ReadyTakesPrecedence(t *testing.T) {
|
||||
// isReady=true should win over isFailed=true
|
||||
resultReady := formatResourceCaption("x", true, false)
|
||||
resultFailed := formatResourceCaption("x", false, true)
|
||||
// Colors should differ
|
||||
assert.NotEqual(t, resultReady, resultFailed)
|
||||
}
|
||||
|
||||
// --- formatPodResourceCaption ---
|
||||
|
||||
func TestFormatPodResourceCaption_NotNew(t *testing.T) {
|
||||
result := formatPodResourceCaption("my-pod-abc", true, false, false)
|
||||
// Not a new pod: no coloring applied, just the plain name
|
||||
assert.Equal(t, "my-pod-abc", result)
|
||||
}
|
||||
|
||||
func TestFormatPodResourceCaption_NewAndReady(t *testing.T) {
|
||||
result := formatPodResourceCaption("my-pod-abc", true, false, true)
|
||||
assert.Contains(t, result, "my-pod-abc")
|
||||
assert.Contains(t, result, "\033[")
|
||||
}
|
||||
|
||||
func TestFormatPodResourceCaption_NewAndFailed(t *testing.T) {
|
||||
result := formatPodResourceCaption("my-pod-abc", false, true, true)
|
||||
assert.Contains(t, result, "my-pod-abc")
|
||||
assert.Contains(t, result, "\033[")
|
||||
}
|
||||
|
||||
func TestFormatPodResourceCaption_NewInProgress(t *testing.T) {
|
||||
result := formatPodResourceCaption("my-pod-abc", false, false, true)
|
||||
assert.Contains(t, result, "my-pod-abc")
|
||||
assert.Contains(t, result, "\033[")
|
||||
}
|
||||
|
||||
// --- formatResourceError / formatResourceWarning ---
|
||||
|
||||
func TestFormatResourceError(t *testing.T) {
|
||||
result := formatResourceError("CrashLoopBackOff")
|
||||
assert.Contains(t, result, "error:")
|
||||
assert.Contains(t, result, "CrashLoopBackOff")
|
||||
}
|
||||
|
||||
func TestFormatResourceWarning(t *testing.T) {
|
||||
result := formatResourceWarning("PodNotScheduled")
|
||||
assert.Contains(t, result, "warning:")
|
||||
assert.Contains(t, result, "PodNotScheduled")
|
||||
}
|
||||
|
||||
// --- termWidth ---
|
||||
|
||||
func TestTermWidth_ReturnsPositive(t *testing.T) {
|
||||
w := termWidth()
|
||||
assert.Greater(t, w, 0)
|
||||
}
|
||||
|
||||
// --- displayDeploymentStatusProgress ---
|
||||
|
||||
func TestDisplayDeploymentStatusProgress_ZeroStatus(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("deploy/myapp", false, false)
|
||||
var prev deployment.DeploymentStatus
|
||||
status := deployment.DeploymentStatus{}
|
||||
|
||||
// Must not panic and must produce some output
|
||||
assert.NotPanics(t, func() {
|
||||
displayDeploymentStatusProgress(&buf, caption, status, &prev)
|
||||
})
|
||||
out := buf.String()
|
||||
assert.NotEmpty(t, out)
|
||||
assert.Contains(t, out, "DEPLOYMENT")
|
||||
}
|
||||
|
||||
func TestDisplayDeploymentStatusProgress_Failed(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("deploy/myapp", false, true)
|
||||
var prev deployment.DeploymentStatus
|
||||
status := deployment.DeploymentStatus{
|
||||
IsFailed: true,
|
||||
FailedReason: "ImagePullBackOff",
|
||||
}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayDeploymentStatusProgress(&buf, caption, status, &prev)
|
||||
})
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "error:")
|
||||
assert.Contains(t, out, "ImagePullBackOff")
|
||||
}
|
||||
|
||||
func TestDisplayDeploymentStatusProgress_WithWaitingMessage(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("deploy/myapp", false, false)
|
||||
var prev deployment.DeploymentStatus
|
||||
// WaitingForMessages is only rendered when there are pods
|
||||
status := deployment.DeploymentStatus{
|
||||
StatusGeneration: 1,
|
||||
WaitingForMessages: []string{"up-to-date 1->3"},
|
||||
Pods: map[string]pod.PodStatus{
|
||||
"myapp-pod-abc": {ReadyContainers: 1, TotalContainers: 1},
|
||||
},
|
||||
}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayDeploymentStatusProgress(&buf, caption, status, &prev)
|
||||
})
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "Waiting for:")
|
||||
assert.Contains(t, out, "up-to-date 1->3")
|
||||
}
|
||||
|
||||
func TestDisplayDeploymentStatusProgress_WithPods(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("deploy/myapp", false, false)
|
||||
prev := deployment.DeploymentStatus{}
|
||||
status := deployment.DeploymentStatus{
|
||||
StatusGeneration: 1,
|
||||
Pods: map[string]pod.PodStatus{
|
||||
"myapp-abc-123": {ReadyContainers: 1, TotalContainers: 1},
|
||||
},
|
||||
NewPodsNames: []string{"myapp-abc-123"},
|
||||
}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayDeploymentStatusProgress(&buf, caption, status, &prev)
|
||||
})
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "POD")
|
||||
assert.Contains(t, out, "myapp-abc-123")
|
||||
}
|
||||
|
||||
// --- displayStatefulSetStatusProgress ---
|
||||
|
||||
func TestDisplayStatefulSetStatusProgress_ZeroStatus(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("sts/myapp", false, false)
|
||||
var prev statefulset.StatefulSetStatus
|
||||
status := statefulset.StatefulSetStatus{}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayStatefulSetStatusProgress(&buf, caption, status, &prev)
|
||||
})
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "STATEFULSET")
|
||||
}
|
||||
|
||||
func TestDisplayStatefulSetStatusProgress_WithWarnings(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("sts/myapp", false, false)
|
||||
var prev statefulset.StatefulSetStatus
|
||||
status := statefulset.StatefulSetStatus{
|
||||
WarningMessages: []string{"PodNotScheduled: insufficient resources"},
|
||||
}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayStatefulSetStatusProgress(&buf, caption, status, &prev)
|
||||
})
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "warning:")
|
||||
assert.Contains(t, out, "PodNotScheduled")
|
||||
}
|
||||
|
||||
func TestDisplayStatefulSetStatusProgress_Failed(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("sts/myapp", false, true)
|
||||
var prev statefulset.StatefulSetStatus
|
||||
status := statefulset.StatefulSetStatus{
|
||||
IsFailed: true,
|
||||
FailedReason: "timeout waiting for ready",
|
||||
}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayStatefulSetStatusProgress(&buf, caption, status, &prev)
|
||||
})
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "error:")
|
||||
assert.Contains(t, out, "timeout waiting for ready")
|
||||
}
|
||||
|
||||
// --- displayDaemonSetStatusProgress ---
|
||||
|
||||
func TestDisplayDaemonSetStatusProgress_ZeroStatus(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("ds/myapp", false, false)
|
||||
var prev daemonset.DaemonSetStatus
|
||||
status := daemonset.DaemonSetStatus{}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayDaemonSetStatusProgress(&buf, caption, status, &prev)
|
||||
})
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "DAEMONSET")
|
||||
}
|
||||
|
||||
func TestDisplayDaemonSetStatusProgress_Failed(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("ds/myapp", false, true)
|
||||
var prev daemonset.DaemonSetStatus
|
||||
status := daemonset.DaemonSetStatus{
|
||||
IsFailed: true,
|
||||
FailedReason: "node not ready",
|
||||
}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayDaemonSetStatusProgress(&buf, caption, status, &prev)
|
||||
})
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "error:")
|
||||
assert.Contains(t, out, "node not ready")
|
||||
}
|
||||
|
||||
// --- displayJobStatusProgress ---
|
||||
|
||||
func TestDisplayJobStatusProgress_ZeroStatus(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("job/myjob", false, false)
|
||||
var prev job.JobStatus
|
||||
status := job.JobStatus{}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayJobStatusProgress(&buf, caption, status, &prev)
|
||||
})
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "JOB")
|
||||
}
|
||||
|
||||
func TestDisplayJobStatusProgress_Active(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("job/myjob", false, false)
|
||||
var prev job.JobStatus
|
||||
status := job.JobStatus{
|
||||
StatusGeneration: 1,
|
||||
}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayJobStatusProgress(&buf, caption, status, &prev)
|
||||
})
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "ACTIVE")
|
||||
}
|
||||
|
||||
func TestDisplayJobStatusProgress_Failed(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("job/myjob", false, true)
|
||||
var prev job.JobStatus
|
||||
status := job.JobStatus{
|
||||
IsFailed: true,
|
||||
FailedReason: "BackoffLimitExceeded",
|
||||
}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayJobStatusProgress(&buf, caption, status, &prev)
|
||||
})
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "error:")
|
||||
assert.Contains(t, out, "BackoffLimitExceeded")
|
||||
}
|
||||
|
||||
func TestDisplayJobStatusProgress_WithWaitingMessage(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("job/myjob", false, false)
|
||||
var prev job.JobStatus
|
||||
status := job.JobStatus{
|
||||
WaitingForMessages: []string{"succeeded 0->1"},
|
||||
Pods: map[string]pod.PodStatus{
|
||||
"myjob-abc": {ReadyContainers: 0, TotalContainers: 1},
|
||||
},
|
||||
}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayJobStatusProgress(&buf, caption, status, &prev)
|
||||
})
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "Waiting for:")
|
||||
assert.Contains(t, out, "succeeded 0->1")
|
||||
}
|
||||
|
||||
// --- displayChildPodsStatusProgress ---
|
||||
|
||||
func TestDisplayChildPodsStatusProgress_Empty(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("deploy/myapp", false, false)
|
||||
// With no pods, only the header should be rendered
|
||||
prev := deployment.DeploymentStatus{}
|
||||
status := deployment.DeploymentStatus{
|
||||
Pods: map[string]pod.PodStatus{},
|
||||
}
|
||||
assert.NotPanics(t, func() {
|
||||
displayDeploymentStatusProgress(&buf, caption, status, &prev)
|
||||
})
|
||||
// No POD sub-table header when pods is empty
|
||||
out := buf.String()
|
||||
assert.NotContains(t, out, "POD")
|
||||
}
|
||||
|
||||
func TestDisplayChildPodsStatusProgress_NewPodSet(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("deploy/myapp", false, false)
|
||||
prev := deployment.DeploymentStatus{}
|
||||
// Two pods: one new, one old
|
||||
status := deployment.DeploymentStatus{
|
||||
StatusGeneration: 1,
|
||||
Pods: map[string]pod.PodStatus{
|
||||
"pod-new-abc": {ReadyContainers: 0, TotalContainers: 1},
|
||||
"pod-old-xyz": {ReadyContainers: 1, TotalContainers: 1},
|
||||
},
|
||||
NewPodsNames: []string{"pod-new-abc"},
|
||||
}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayDeploymentStatusProgress(&buf, caption, status, &prev)
|
||||
})
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "pod-new-abc")
|
||||
assert.Contains(t, out, "pod-old-xyz")
|
||||
}
|
||||
|
||||
func TestDisplayChildPodsStatusProgress_ManyPodsONCheck(t *testing.T) {
|
||||
// Verifies O(1) new-pod detection works correctly for many pods
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("deploy/myapp", false, false)
|
||||
prev := deployment.DeploymentStatus{}
|
||||
|
||||
pods := make(map[string]pod.PodStatus)
|
||||
newNames := make([]string, 0, 10)
|
||||
for i := 0; i < 20; i++ {
|
||||
name := strings.Repeat("a", i+1)
|
||||
pods[name] = pod.PodStatus{ReadyContainers: 1, TotalContainers: 1}
|
||||
if i%2 == 0 {
|
||||
newNames = append(newNames, name)
|
||||
}
|
||||
}
|
||||
status := deployment.DeploymentStatus{
|
||||
StatusGeneration: 1,
|
||||
Pods: pods,
|
||||
NewPodsNames: newNames,
|
||||
}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayDeploymentStatusProgress(&buf, caption, status, &prev)
|
||||
})
|
||||
assert.NotEmpty(t, buf.String())
|
||||
}
|
||||
|
||||
// --- displayCanaryStatus ---
|
||||
|
||||
func TestDisplayCanaryStatus_Normal(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("canary/myapp", false, false)
|
||||
view := CanaryStatusView{Phase: "Progressing", Age: "1m"}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayCanaryStatus(&buf, caption, view)
|
||||
})
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "Progressing")
|
||||
assert.Contains(t, out, "1m")
|
||||
}
|
||||
|
||||
func TestDisplayCanaryStatus_Failed(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("canary/myapp", false, true)
|
||||
view := CanaryStatusView{Phase: "Failed", IsFailed: true}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayCanaryStatus(&buf, caption, view)
|
||||
})
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "Failed")
|
||||
}
|
||||
|
||||
func TestDisplayCanaryStatus_Succeeded(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("canary/myapp", true, false)
|
||||
view := CanaryStatusView{Phase: "Succeeded"}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayCanaryStatus(&buf, caption, view)
|
||||
})
|
||||
out := buf.String()
|
||||
assert.Contains(t, out, "Succeeded")
|
||||
}
|
||||
|
||||
func TestDisplayCanaryStatus_EmptyPhaseAndAge(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
caption := formatResourceCaption("canary/myapp", false, false)
|
||||
view := CanaryStatusView{}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
displayCanaryStatus(&buf, caption, view)
|
||||
})
|
||||
// Should still produce output (at least the caption + newline)
|
||||
assert.NotEmpty(t, buf.String())
|
||||
}
|
||||
|
||||
// --- writeOut ---
|
||||
|
||||
func TestWriteOut(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
writeOut(&buf, "hello world")
|
||||
assert.Equal(t, "hello world", buf.String())
|
||||
}
|
||||
|
||||
func TestWriteOut_Empty(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
writeOut(&buf, "")
|
||||
assert.Equal(t, "", buf.String())
|
||||
}
|
||||
|
|
@ -316,21 +316,23 @@ func (t *Tracker) runDeploymentTracker(ctx context.Context, tr *deployment.Track
|
|||
func (t *Tracker) waitDeploymentTracker(ctx context.Context, tr *deployment.Tracker, trackErrCh <-chan error, doneCh <-chan struct{}) error {
|
||||
var prevStatus deployment.DeploymentStatus
|
||||
out := statusOutput()
|
||||
caption := formatResourceCaption(fmt.Sprintf("deploy/%s", tr.ResourceName), false, false)
|
||||
resourceName := fmt.Sprintf("deploy/%s", tr.ResourceName)
|
||||
|
||||
for {
|
||||
select {
|
||||
case status := <-tr.Added:
|
||||
displayDeploymentStatusProgress(out, caption, status, &prevStatus)
|
||||
displayDeploymentStatusProgress(out, formatResourceCaption(resourceName, false, false), status, &prevStatus)
|
||||
prevStatus = status
|
||||
case <-tr.Ready:
|
||||
displayDeploymentStatusProgress(out, formatResourceCaption(resourceName, true, false), prevStatus, &prevStatus)
|
||||
t.logger.Infof("Deployment %s/%s is ready", tr.Namespace, tr.ResourceName)
|
||||
return nil
|
||||
case status := <-tr.Failed:
|
||||
displayDeploymentStatusProgress(out, formatResourceCaption(resourceName, false, true), status, &prevStatus)
|
||||
return fmt.Errorf("deployment %s/%s failed: %s", tr.Namespace, tr.ResourceName, status.FailedReason)
|
||||
case status := <-tr.Status:
|
||||
if status.StatusGeneration > prevStatus.StatusGeneration {
|
||||
displayDeploymentStatusProgress(out, caption, status, &prevStatus)
|
||||
displayDeploymentStatusProgress(out, formatResourceCaption(resourceName, false, false), status, &prevStatus)
|
||||
prevStatus = status
|
||||
}
|
||||
case msg := <-tr.EventMsg:
|
||||
|
|
@ -362,21 +364,23 @@ func (t *Tracker) runStatefulSetTracker(ctx context.Context, tr *statefulset.Tra
|
|||
func (t *Tracker) waitStatefulSetTracker(ctx context.Context, tr *statefulset.Tracker, trackErrCh <-chan error, doneCh <-chan struct{}) error {
|
||||
var prevStatus statefulset.StatefulSetStatus
|
||||
out := statusOutput()
|
||||
caption := formatResourceCaption(fmt.Sprintf("sts/%s", tr.ResourceName), false, false)
|
||||
resourceName := fmt.Sprintf("sts/%s", tr.ResourceName)
|
||||
|
||||
for {
|
||||
select {
|
||||
case status := <-tr.Added:
|
||||
displayStatefulSetStatusProgress(out, caption, status, &prevStatus)
|
||||
displayStatefulSetStatusProgress(out, formatResourceCaption(resourceName, false, false), status, &prevStatus)
|
||||
prevStatus = status
|
||||
case <-tr.Ready:
|
||||
displayStatefulSetStatusProgress(out, formatResourceCaption(resourceName, true, false), prevStatus, &prevStatus)
|
||||
t.logger.Infof("StatefulSet %s/%s is ready", tr.Namespace, tr.ResourceName)
|
||||
return nil
|
||||
case status := <-tr.Failed:
|
||||
displayStatefulSetStatusProgress(out, formatResourceCaption(resourceName, false, true), status, &prevStatus)
|
||||
return fmt.Errorf("statefulset %s/%s failed: %s", tr.Namespace, tr.ResourceName, status.FailedReason)
|
||||
case status := <-tr.Status:
|
||||
if status.StatusGeneration > prevStatus.StatusGeneration {
|
||||
displayStatefulSetStatusProgress(out, caption, status, &prevStatus)
|
||||
displayStatefulSetStatusProgress(out, formatResourceCaption(resourceName, false, false), status, &prevStatus)
|
||||
prevStatus = status
|
||||
}
|
||||
case msg := <-tr.EventMsg:
|
||||
|
|
@ -407,21 +411,23 @@ func (t *Tracker) runDaemonSetTracker(ctx context.Context, tr *daemonset.Tracker
|
|||
func (t *Tracker) waitDaemonSetTracker(ctx context.Context, tr *daemonset.Tracker, trackErrCh <-chan error, doneCh <-chan struct{}) error {
|
||||
var prevStatus daemonset.DaemonSetStatus
|
||||
out := statusOutput()
|
||||
caption := formatResourceCaption(fmt.Sprintf("ds/%s", tr.ResourceName), false, false)
|
||||
resourceName := fmt.Sprintf("ds/%s", tr.ResourceName)
|
||||
|
||||
for {
|
||||
select {
|
||||
case status := <-tr.Added:
|
||||
displayDaemonSetStatusProgress(out, caption, status, &prevStatus)
|
||||
displayDaemonSetStatusProgress(out, formatResourceCaption(resourceName, false, false), status, &prevStatus)
|
||||
prevStatus = status
|
||||
case <-tr.Ready:
|
||||
displayDaemonSetStatusProgress(out, formatResourceCaption(resourceName, true, false), prevStatus, &prevStatus)
|
||||
t.logger.Infof("DaemonSet %s/%s is ready", tr.Namespace, tr.ResourceName)
|
||||
return nil
|
||||
case status := <-tr.Failed:
|
||||
displayDaemonSetStatusProgress(out, formatResourceCaption(resourceName, false, true), status, &prevStatus)
|
||||
return fmt.Errorf("daemonset %s/%s failed: %s", tr.Namespace, tr.ResourceName, status.FailedReason)
|
||||
case status := <-tr.Status:
|
||||
if status.StatusGeneration > prevStatus.StatusGeneration {
|
||||
displayDaemonSetStatusProgress(out, caption, status, &prevStatus)
|
||||
displayDaemonSetStatusProgress(out, formatResourceCaption(resourceName, false, false), status, &prevStatus)
|
||||
prevStatus = status
|
||||
}
|
||||
case msg := <-tr.EventMsg:
|
||||
|
|
@ -452,21 +458,23 @@ func (t *Tracker) runJobTracker(ctx context.Context, tr *job.Tracker, errCh chan
|
|||
func (t *Tracker) waitJobTracker(ctx context.Context, tr *job.Tracker, trackErrCh <-chan error, doneCh <-chan struct{}) error {
|
||||
var prevStatus job.JobStatus
|
||||
out := statusOutput()
|
||||
caption := formatResourceCaption(fmt.Sprintf("job/%s", tr.ResourceName), false, false)
|
||||
resourceName := fmt.Sprintf("job/%s", tr.ResourceName)
|
||||
|
||||
for {
|
||||
select {
|
||||
case status := <-tr.Added:
|
||||
displayJobStatusProgress(out, caption, status, &prevStatus)
|
||||
displayJobStatusProgress(out, formatResourceCaption(resourceName, false, false), status, &prevStatus)
|
||||
prevStatus = status
|
||||
case <-tr.Succeeded:
|
||||
displayJobStatusProgress(out, formatResourceCaption(resourceName, true, false), prevStatus, &prevStatus)
|
||||
t.logger.Infof("Job %s/%s succeeded", tr.Namespace, tr.ResourceName)
|
||||
return nil
|
||||
case status := <-tr.Failed:
|
||||
displayJobStatusProgress(out, formatResourceCaption(resourceName, false, true), status, &prevStatus)
|
||||
return fmt.Errorf("job %s/%s failed: %s", tr.Namespace, tr.ResourceName, status.FailedReason)
|
||||
case status := <-tr.Status:
|
||||
if status.StatusGeneration > prevStatus.StatusGeneration {
|
||||
displayJobStatusProgress(out, caption, status, &prevStatus)
|
||||
displayJobStatusProgress(out, formatResourceCaption(resourceName, false, false), status, &prevStatus)
|
||||
prevStatus = status
|
||||
}
|
||||
case msg := <-tr.EventMsg:
|
||||
|
|
@ -496,22 +504,30 @@ func (t *Tracker) runCanaryTracker(ctx context.Context, tr *canary.Tracker, errC
|
|||
|
||||
func (t *Tracker) waitCanaryTracker(ctx context.Context, tr *canary.Tracker, trackErrCh <-chan error, doneCh <-chan struct{}) error {
|
||||
out := statusOutput()
|
||||
caption := formatResourceCaption(fmt.Sprintf("canary/%s", tr.ResourceName), false, false)
|
||||
resourceName := fmt.Sprintf("canary/%s", tr.ResourceName)
|
||||
var lastView CanaryStatusView
|
||||
|
||||
for {
|
||||
select {
|
||||
case status := <-tr.Added:
|
||||
displayCanaryStatus(out, caption, CanaryStatusView{
|
||||
view := CanaryStatusView{
|
||||
Phase: string(status.CanaryStatus.Phase),
|
||||
IsFailed: status.IsFailed,
|
||||
})
|
||||
}
|
||||
displayCanaryStatus(out, formatResourceCaption(resourceName, false, false), view)
|
||||
lastView = view
|
||||
case <-tr.Succeeded:
|
||||
displayCanaryStatus(out, formatResourceCaption(resourceName, true, false), CanaryStatusView{Phase: lastView.Phase})
|
||||
t.logger.Infof("Canary %s/%s succeeded", tr.Namespace, tr.ResourceName)
|
||||
return nil
|
||||
case status := <-tr.Failed:
|
||||
displayCanaryStatus(out, formatResourceCaption(resourceName, false, true), CanaryStatusView{
|
||||
Phase: lastView.Phase,
|
||||
IsFailed: true,
|
||||
})
|
||||
return fmt.Errorf("canary %s/%s failed: %s", tr.Namespace, tr.ResourceName, status.FailedReason)
|
||||
case status := <-tr.Status:
|
||||
displayCanaryStatus(out, caption, CanaryStatusView{
|
||||
view := CanaryStatusView{
|
||||
Phase: func() string {
|
||||
if status.StatusIndicator != nil {
|
||||
return status.StatusIndicator.Value
|
||||
|
|
@ -520,7 +536,9 @@ func (t *Tracker) waitCanaryTracker(ctx context.Context, tr *canary.Tracker, tra
|
|||
}(),
|
||||
Age: status.Age,
|
||||
IsFailed: status.IsFailed,
|
||||
})
|
||||
}
|
||||
displayCanaryStatus(out, formatResourceCaption(resourceName, false, false), view)
|
||||
lastView = view
|
||||
case msg := <-tr.EventMsg:
|
||||
t.logger.Infof("canary/%s: %s", tr.ResourceName, msg)
|
||||
case err := <-trackErrCh:
|
||||
|
|
|
|||
Loading…
Reference in New Issue