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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"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.",
|
"a path to a blueprint elsewhere can be provided as the [blueprint] argument.",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
if comp, plan := plan(cmd, args, delete); plan != nil {
|
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)
|
progress := newProgress(detailed)
|
||||||
if err, _, _ := plan.Apply(progress); err != nil {
|
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
|
// 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.
|
// probably want to plumb diag.Sink through apply so it can issue its own rich diagnostics.
|
||||||
comp.Diag().Errorf(errors.ErrorPlanApplyFailed, err)
|
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.
|
// applyProgress pretty-prints the plan application process as it goes.
|
||||||
type applyProgress struct {
|
type applyProgress struct {
|
||||||
c int
|
Steps int
|
||||||
detailed bool
|
Ops map[resource.StepOp]int
|
||||||
|
MaybeCorrupt bool
|
||||||
|
Detailed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newProgress(detailed bool) *applyProgress {
|
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) {
|
func (prog *applyProgress) Before(step resource.Step) {
|
||||||
|
// Print the step.
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
prog.c++
|
stepnum := prog.Steps + 1
|
||||||
b.WriteString(fmt.Sprintf("Applying step #%v\n", prog.c))
|
b.WriteString(fmt.Sprintf("Applying step #%v\n", stepnum))
|
||||||
printStep(&b, step, !prog.detailed, " ")
|
printStep(&b, step, !prog.Detailed, " ")
|
||||||
s := colors.Colorize(b.String())
|
s := colors.Colorize(b.String())
|
||||||
fmt.Printf(s)
|
fmt.Printf(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (prog *applyProgress) After(step resource.Step, err error, state resource.ResourceState) {
|
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
|
var b bytes.Buffer
|
||||||
// Print the state of the resource; we don't issue the error, because the apply above will do that.
|
// 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 {
|
switch state {
|
||||||
case resource.StateOK:
|
case resource.StateOK:
|
||||||
b.WriteString(colors.BrightYellow)
|
b.WriteString(colors.BrightYellow)
|
||||||
|
@ -87,6 +127,7 @@ func (prog *applyProgress) After(step resource.Step, err error, state resource.R
|
||||||
case resource.StateUnknown:
|
case resource.StateUnknown:
|
||||||
b.WriteString(colors.BrightRed)
|
b.WriteString(colors.BrightRed)
|
||||||
b.WriteString("this failure was catastrophic and the provider cannot guarantee recovery")
|
b.WriteString("this failure was catastrophic and the provider cannot guarantee recovery")
|
||||||
|
prog.MaybeCorrupt = true
|
||||||
default:
|
default:
|
||||||
contract.Failf("Unrecognized resource state: %v", state)
|
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) {
|
func opPrefix(op resource.StepOp) string {
|
||||||
// First print out the operation.
|
switch op {
|
||||||
switch step.Op() {
|
|
||||||
case resource.OpCreate:
|
case resource.OpCreate:
|
||||||
b.WriteString(colors.Green)
|
return colors.Green + "+ "
|
||||||
b.WriteString("+ ")
|
|
||||||
case resource.OpDelete:
|
case resource.OpDelete:
|
||||||
b.WriteString(colors.Red)
|
return colors.Red + "- "
|
||||||
b.WriteString("- ")
|
|
||||||
default:
|
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.
|
// Next print the resource moniker, properties, etc.
|
||||||
printResource(b, step.Resource(), summary, indent)
|
printResource(b, step.Resource(), summary, indent)
|
||||||
|
|
Loading…
Reference in a new issue