Skip to content

Commit

Permalink
Sort output of plan status and history commands (#1371)
Browse files Browse the repository at this point in the history
* Sort output of plan status and plan history commands

Alphabetise (by plan) the output of the plan status and history commands
so that they're consistent with each run.  This helps human operators
when monitoring a deployment.

Signed-off-by: Nick Jones <nick@dischord.org>
  • Loading branch information
yankcrime committed Mar 3, 2020
1 parent 9c8d6bc commit 4f1fce8
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 23 deletions.
22 changes: 14 additions & 8 deletions pkg/kudoctl/cmd/plan/plan_history.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import (
"errors"
"fmt"
"io"
"sort"

"github.com/spf13/cobra"
"github.com/thoas/go-funk"
"github.com/xlab/treeprint"

"github.com/kudobuilder/kudo/pkg/kudoctl/clog"
Expand Down Expand Up @@ -56,18 +58,22 @@ func planHistory(options *Options, settings *env.Settings) error {
tree := treeprint.New()
timeLayout := "2006-01-02T15:04:05"

for _, p := range instance.Status.PlanStatus {
plans, _ := funk.Keys(instance.Status.PlanStatus).([]string)
sort.Strings(plans)

for _, p := range plans {
plan := instance.Status.PlanStatus[p]
msg := "never run" // this is for the cases when status was not yet populated

if p.LastUpdatedTimestamp != nil && !p.LastUpdatedTimestamp.IsZero() { // plan already finished
t := p.LastUpdatedTimestamp.Format(timeLayout)
msg = fmt.Sprintf("last finished run at %s (%s)", t, string(p.Status))
} else if p.Status.IsRunning() {
if plan.LastUpdatedTimestamp != nil && !plan.LastUpdatedTimestamp.IsZero() { // plan already finished
t := plan.LastUpdatedTimestamp.Format(timeLayout)
msg = fmt.Sprintf("last finished run at %s (%s)", t, string(plan.Status))
} else if plan.Status.IsRunning() {
msg = "is running"
} else if p.Status != "" {
msg = string(p.Status)
} else if plan.Status != "" {
msg = string(plan.Status)
}
historyDisplay := fmt.Sprintf("%s (%s)", p.Name, msg)
historyDisplay := fmt.Sprintf("%s (%s)", plan.Name, msg)
tree.AddBranch(historyDisplay)
}

Expand Down
20 changes: 11 additions & 9 deletions pkg/kudoctl/cmd/plan/plan_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package plan

import (
"fmt"
"sort"

"github.com/thoas/go-funk"
"github.com/xlab/treeprint"

"github.com/kudobuilder/kudo/pkg/apis/kudo/v1beta1"
Expand Down Expand Up @@ -63,15 +65,15 @@ func status(kc *kudo.Client, options *Options, ns string) error {
rootDisplay := fmt.Sprintf("%s (Operator-Version: \"%s\" Active-Plan: \"%s\")", instance.Name, instance.Spec.OperatorVersion.Name, lastPlanStatus.Name)
rootBranchName := tree.AddBranch(rootDisplay)

for name, plan := range ov.Spec.Plans {
if name == lastPlanStatus.Name {
var planDisplay string
plans, _ := funk.Keys(ov.Spec.Plans).([]string)
sort.Strings(plans)

for _, plan := range plans {
if plan == lastPlanStatus.Name {
planDisplay := fmt.Sprintf("Plan %s (%s strategy) [%s]%s", plan, ov.Spec.Plans[plan].Strategy, lastPlanStatus.Status, printMessageIfAvailable(lastPlanStatus.Message))
if lastPlanStatus.LastUpdatedTimestamp != nil {
planDisplay = fmt.Sprintf("Plan %s (%s strategy) [%s]%s, last updated %s", name, plan.Strategy, lastPlanStatus.Status, printMessageIfAvailable(lastPlanStatus.Message), lastPlanStatus.LastUpdatedTimestamp.Format("2006-01-02 15:04:05"))
} else {
planDisplay = fmt.Sprintf("Plan %s (%s strategy) [%s]%s", name, plan.Strategy, lastPlanStatus.Status, printMessageIfAvailable(lastPlanStatus.Message))
planDisplay = fmt.Sprintf("%s, last updated %s", planDisplay, lastPlanStatus.LastUpdatedTimestamp.Format("2006-01-02 15:04:05"))
}

planBranchName := rootBranchName.AddBranch(planDisplay)
for _, phase := range lastPlanStatus.Phases {
phaseDisplay := fmt.Sprintf("Phase %s (%s strategy) [%s]%s", phase.Name, getPhaseStrategy(phase.Name), phase.Status, printMessageIfAvailable(phase.Message))
Expand All @@ -82,9 +84,9 @@ func status(kc *kudo.Client, options *Options, ns string) error {
}
}
} else {
planDisplay := fmt.Sprintf("Plan %s (%s strategy) [NOT ACTIVE]", name, plan.Strategy)
planDisplay := fmt.Sprintf("Plan %s (%s strategy) [NOT ACTIVE]", plan, ov.Spec.Plans[plan].Strategy)
planBranchName := rootBranchName.AddBranch(planDisplay)
for _, phase := range plan.Phases {
for _, phase := range ov.Spec.Plans[plan].Phases {
phaseDisplay := fmt.Sprintf("Phase %s (%s strategy) [NOT ACTIVE]", phase.Name, phase.Strategy)
phaseBranchName := planBranchName.AddBranch(phaseDisplay)
for _, steps := range phase.Steps {
Expand Down
50 changes: 44 additions & 6 deletions pkg/kudoctl/cmd/plan/plan_status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package plan
import (
"bytes"
"testing"
"time"

"github.com/stretchr/testify/assert"
v1 "k8s.io/api/core/v1"
Expand All @@ -13,6 +14,10 @@ import (
"github.com/kudobuilder/kudo/pkg/kudoctl/util/kudo"
)

var (
testTime = time.Date(2019, 10, 17, 1, 1, 1, 1, time.UTC)
)

func TestStatus(t *testing.T) {
ov := &v1beta1.OperatorVersion{
TypeMeta: metav1.TypeMeta{
Expand All @@ -24,7 +29,33 @@ func TestStatus(t *testing.T) {
},
Spec: v1beta1.OperatorVersionSpec{
Version: "1.0",
Plans: map[string]v1beta1.Plan{"deploy": {}},
Plans: map[string]v1beta1.Plan{
"zzzinvalid": {
Phases: []v1beta1.Phase{
v1beta1.Phase{
Name: "zzzinvalid",
Steps: []v1beta1.Step{
v1beta1.Step{
Name: "zzzinvalid",
},
},
},
},
},
"validate": {
Phases: []v1beta1.Phase{
v1beta1.Phase{
Name: "validate",
Steps: []v1beta1.Step{
v1beta1.Step{
Name: "validate",
},
},
},
},
},
"deploy": {},
},
}}
instance := &v1beta1.Instance{
TypeMeta: metav1.TypeMeta{
Expand All @@ -45,8 +76,9 @@ func TestStatus(t *testing.T) {
fatalErrInstance.Status = v1beta1.InstanceStatus{
PlanStatus: map[string]v1beta1.PlanStatus{
"deploy": {
Name: "deploy",
Status: v1beta1.ExecutionFatalError,
Name: "deploy",
Status: v1beta1.ExecutionFatalError,
LastUpdatedTimestamp: &metav1.Time{Time: testTime},
Phases: []v1beta1.PhaseStatus{
{
Name: "deploy",
Expand Down Expand Up @@ -78,9 +110,15 @@ func TestStatus(t *testing.T) {
{"fatal error in a plan", fatalErrInstance, ov, "test", "", `Plan(s) for "test" in namespace "default":
.
└── test (Operator-Version: "test-1.0" Active-Plan: "deploy")
└── Plan deploy ( strategy) [FATAL_ERROR]
└── Phase deploy ( strategy) [FATAL_ERROR]
└── Step deploy [FATAL_ERROR] (error detail)
├── Plan deploy ( strategy) [FATAL_ERROR], last updated 2019-10-17 01:01:01
│   └── Phase deploy ( strategy) [FATAL_ERROR]
│   └── Step deploy [FATAL_ERROR] (error detail)
├── Plan validate ( strategy) [NOT ACTIVE]
│   └── Phase validate ( strategy) [NOT ACTIVE]
│   └── Step validate [NOT ACTIVE]
└── Plan zzzinvalid ( strategy) [NOT ACTIVE]
└── Phase zzzinvalid ( strategy) [NOT ACTIVE]
└── Step zzzinvalid [NOT ACTIVE]
`},
}
Expand Down

0 comments on commit 4f1fce8

Please sign in to comment.