Add a summary to the apply command
This commit is contained in:
parent
60a51f1222
commit
dcb6c958b3
57
cmd/apply.go
57
cmd/apply.go
|
@ -5,6 +5,7 @@ package cmd
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
|
@ -34,6 +35,8 @@ func newApplyCmd() *cobra.Command {
|
|||
"a path to a blueprint elsewhere can be provided as the [blueprint] argument.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if comp, plan := plan(cmd, args, delete); plan != nil {
|
||||
// Create an object to track progress and perform the actual operations.
|
||||
start := time.Now()
|
||||
progress := newProgress(detailed)
|
||||
if err, _, _ := plan.Apply(progress); err != nil {
|
||||
// TODO: we want richer diagnostics in the event that a plan apply fails. For instance, we want to
|
||||
|
@ -41,6 +44,31 @@ func newApplyCmd() *cobra.Command {
|
|||
// probably want to plumb diag.Sink through apply so it can issue its own rich diagnostics.
|
||||
comp.Diag().Errorf(errors.ErrorPlanApplyFailed, err)
|
||||
}
|
||||
|
||||
// Print out the total number of steps performed (and their kinds), if any succeeded.
|
||||
var b bytes.Buffer
|
||||
if progress.Steps > 0 {
|
||||
b.WriteString(fmt.Sprintf("%v total operations in %v:\n", progress.Steps, time.Since(start)))
|
||||
if c := progress.Ops[resource.OpCreate]; c > 0 {
|
||||
b.WriteString(fmt.Sprintf(" %v%v resources created%v\n",
|
||||
opPrefix(resource.OpCreate), c, colors.Reset))
|
||||
}
|
||||
if c := progress.Ops[resource.OpUpdate]; c > 0 {
|
||||
b.WriteString(fmt.Sprintf(" %v%v resources updated%v\n",
|
||||
opPrefix(resource.OpUpdate), c, colors.Reset))
|
||||
}
|
||||
if c := progress.Ops[resource.OpDelete]; c > 0 {
|
||||
b.WriteString(fmt.Sprintf(" %v%v resources deleted%v\n",
|
||||
opPrefix(resource.OpDelete), c, colors.Reset))
|
||||
}
|
||||
}
|
||||
if progress.MaybeCorrupt {
|
||||
b.WriteString(fmt.Sprintf(
|
||||
"%vfatal: A catastrophic error occurred; resources states may be unknown%v\n",
|
||||
colors.Red, colors.Reset))
|
||||
}
|
||||
s := b.String()
|
||||
fmt.Printf(colors.Colorize(s))
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -58,28 +86,40 @@ func newApplyCmd() *cobra.Command {
|
|||
|
||||
// applyProgress pretty-prints the plan application process as it goes.
|
||||
type applyProgress struct {
|
||||
c int
|
||||
detailed bool
|
||||
Steps int
|
||||
Ops map[resource.StepOp]int
|
||||
MaybeCorrupt bool
|
||||
Detailed bool
|
||||
}
|
||||
|
||||
func newProgress(detailed bool) *applyProgress {
|
||||
return &applyProgress{detailed: detailed}
|
||||
return &applyProgress{
|
||||
Steps: 0,
|
||||
Ops: make(map[resource.StepOp]int),
|
||||
Detailed: detailed,
|
||||
}
|
||||
}
|
||||
|
||||
func (prog *applyProgress) Before(step resource.Step) {
|
||||
// Print the step.
|
||||
var b bytes.Buffer
|
||||
prog.c++
|
||||
b.WriteString(fmt.Sprintf("Applying step #%v\n", prog.c))
|
||||
printStep(&b, step, !prog.detailed, " ")
|
||||
stepnum := prog.Steps + 1
|
||||
b.WriteString(fmt.Sprintf("Applying step #%v\n", stepnum))
|
||||
printStep(&b, step, !prog.Detailed, " ")
|
||||
s := colors.Colorize(b.String())
|
||||
fmt.Printf(s)
|
||||
}
|
||||
|
||||
func (prog *applyProgress) After(step resource.Step, err error, state resource.ResourceState) {
|
||||
if err != nil {
|
||||
if err == nil {
|
||||
// Increment the counters.
|
||||
prog.Steps++
|
||||
prog.Ops[step.Op()]++
|
||||
} else {
|
||||
var b bytes.Buffer
|
||||
// Print the state of the resource; we don't issue the error, because the apply above will do that.
|
||||
b.WriteString(fmt.Sprintf("Step #%v failed: ", prog.c))
|
||||
stepnum := prog.Steps + 1
|
||||
b.WriteString(fmt.Sprintf("Step #%v failed: ", stepnum))
|
||||
switch state {
|
||||
case resource.StateOK:
|
||||
b.WriteString(colors.BrightYellow)
|
||||
|
@ -87,6 +127,7 @@ func (prog *applyProgress) After(step resource.Step, err error, state resource.R
|
|||
case resource.StateUnknown:
|
||||
b.WriteString(colors.BrightRed)
|
||||
b.WriteString("this failure was catastrophic and the provider cannot guarantee recovery")
|
||||
prog.MaybeCorrupt = true
|
||||
default:
|
||||
contract.Failf("Unrecognized resource state: %v", state)
|
||||
}
|
||||
|
|
18
cmd/plan.go
18
cmd/plan.go
|
@ -67,18 +67,20 @@ func printPlan(plan resource.Plan, summary bool) {
|
|||
}
|
||||
}
|
||||
|
||||
func printStep(b *bytes.Buffer, step resource.Step, summary bool, indent string) {
|
||||
// First print out the operation.
|
||||
switch step.Op() {
|
||||
func opPrefix(op resource.StepOp) string {
|
||||
switch op {
|
||||
case resource.OpCreate:
|
||||
b.WriteString(colors.Green)
|
||||
b.WriteString("+ ")
|
||||
return colors.Green + "+ "
|
||||
case resource.OpDelete:
|
||||
b.WriteString(colors.Red)
|
||||
b.WriteString("- ")
|
||||
return colors.Red + "- "
|
||||
default:
|
||||
b.WriteString(" ")
|
||||
return " "
|
||||
}
|
||||
}
|
||||
|
||||
func printStep(b *bytes.Buffer, step resource.Step, summary bool, indent string) {
|
||||
// First print out the operation's prefix.
|
||||
b.WriteString(opPrefix(step.Op()))
|
||||
|
||||
// Next print the resource moniker, properties, etc.
|
||||
printResource(b, step.Resource(), summary, indent)
|
||||
|
|
Loading…
Reference in a new issue