From 9277a3bfeacad91ecefcee4df1e0198ced71b382 Mon Sep 17 00:00:00 2001 From: Alex Dadgar Date: Fri, 13 May 2016 16:29:32 -0700 Subject: [PATCH] better colors and verify help text --- command/plan.go | 82 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 4 deletions(-) diff --git a/command/plan.go b/command/plan.go index dc4591265..f600402fe 100644 --- a/command/plan.go +++ b/command/plan.go @@ -10,6 +10,16 @@ import ( "github.com/mitchellh/colorstring" ) +const ( + casHelp = `To submit the job with version verification run: + +nomad run -verify %d %s + +When running the job with the verify flag, the job will only be run if the server side +version matches the the verify index returned. If the index has changed, another user has +modified the job and the plan's results are potentially invalid.` +) + type PlanCommand struct { Meta color *colorstring.Colorize @@ -101,12 +111,50 @@ func (c *PlanCommand) Run(args []string) int { } if diff { - c.Ui.Output(c.Colorize().Color(strings.TrimSpace(formatJobDiff(resp.Diff, verbose)))) + c.Ui.Output(fmt.Sprintf("%s\n", + c.Colorize().Color(strings.TrimSpace(formatJobDiff(resp.Diff, verbose))))) } + c.Ui.Output(c.Colorize().Color("[bold]Scheduler dry-run:[reset]")) + c.Ui.Output(c.Colorize().Color(formatDryRun(resp.CreatedEvals))) + + c.Ui.Output(c.Colorize().Color(formatCas(resp.Cas, file))) return 0 } +func formatCas(cas uint64, jobName string) string { + help := fmt.Sprintf(casHelp, cas, jobName) + out := fmt.Sprintf("[reset][bold]Job Verify Index: %d[reset]\n%s", cas, help) + return out +} + +func formatDryRun(evals []*api.Evaluation) string { + // "- All tasks successfully allocated." bold and green + + var rolling *api.Evaluation + var blocked *api.Evaluation + for _, eval := range evals { + if eval.TriggeredBy == "rolling-update" { + rolling = eval + } else if eval.Status == "blocked" { + blocked = eval + } + } + + var out string + if blocked == nil { + out = "[bold][green] - All tasks successfully allocated.[reset]\n" + } else { + out = "[bold][yellow] - WARNING: Failed to place all allocations.[reset]\n" + } + + if rolling != nil { + out += fmt.Sprintf("[green] - Rolling update, next evaluation will be in %s.\n", rolling.Wait) + } + + return out +} + func formatJobDiff(job *api.JobDiff, verbose bool) string { out := fmt.Sprintf("%s[bold]Job: %q\n", getDiffString(job.Type), job.ID) @@ -175,7 +223,7 @@ func formatTaskGroupDiff(tg *api.TaskGroupDiff, verbose bool) string { func formatTaskDiff(task *api.TaskDiff, verbose bool) string { out := fmt.Sprintf(" %s[bold]Task: %q", getDiffString(task.Type), task.Name) if len(task.Annotations) != 0 { - out += fmt.Sprintf(" [reset](%s)", strings.Join(task.Annotations, ", ")) + out += fmt.Sprintf(" [reset](%s)", colorAnnotations(task.Annotations)) } if task.Type == "None" { @@ -210,13 +258,39 @@ func formatFieldDiff(diff *api.FieldDiff, prefix string, verbose bool) string { out += fmt.Sprintf("%s: %q", diff.Name, diff.New) } - if len(diff.Annotations) != 0 { - out += fmt.Sprintf(" (%s)", strings.Join(diff.Annotations, ", ")) + // Color the annotations where possible + if l := len(diff.Annotations); l != 0 { + out += fmt.Sprintf(" (%s)", colorAnnotations(diff.Annotations)) } return out } +func colorAnnotations(annotations []string) string { + l := len(annotations) + if l == 0 { + return "" + } + + colored := make([]string, l) + for i, annotation := range annotations { + switch annotation { + case "forces create": + colored[i] = fmt.Sprintf("[green]%s[reset]", annotation) + case "forces destroy": + colored[i] = fmt.Sprintf("[red]%s[reset]", annotation) + case "forces in-place update": + colored[i] = fmt.Sprintf("[cyan]%s[reset]", annotation) + case "forces create/destroy update": + colored[i] = fmt.Sprintf("[yellow]%s[reset]", annotation) + default: + colored[i] = annotation + } + } + + return strings.Join(colored, ", ") +} + func formatObjectDiff(diff *api.ObjectDiff, prefix string, verbose bool) string { out := fmt.Sprintf("%s%s%s {\n", prefix, getDiffString(diff.Type), diff.Name)