mirror of
https://github.com/kemko/nomad.git
synced 2026-01-06 18:35:44 +03:00
comments, refactor and help string
This commit is contained in:
242
command/plan.go
242
command/plan.go
@@ -30,6 +30,20 @@ func (c *PlanCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: nomad plan [options] <file>
|
||||
|
||||
Plan invokes a dry-run of the scheduler to determine the effects of submitting
|
||||
either a new or updated version of a job. The plan will not result in any
|
||||
changes to the cluster but gives insight into whether the job could be run
|
||||
successfully and how it would affect existing allocations.
|
||||
|
||||
A job modify index is returned with the plan. This value can be used when
|
||||
submitting the job using "nomad run -verify", which will check that the job
|
||||
was not modified between the plan and run command before invoking the
|
||||
scheduler. This ensures that the plan reflects the same modifications to the
|
||||
job as the run.
|
||||
|
||||
An annotated diff between the submitted job and the remote state is also
|
||||
displayed. This diff gives insight onto what the scheduler will attempt to do
|
||||
and why.
|
||||
|
||||
General Options:
|
||||
|
||||
@@ -44,7 +58,7 @@ Run Options:
|
||||
Disable colored output.
|
||||
|
||||
-verbose
|
||||
Increased diff verbosity
|
||||
Increase diff verbosity.
|
||||
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
@@ -111,27 +125,31 @@ func (c *PlanCommand) Run(args []string) int {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Print the diff if not disabled
|
||||
if diff {
|
||||
c.Ui.Output(fmt.Sprintf("%s\n",
|
||||
c.Colorize().Color(strings.TrimSpace(formatJobDiff(resp.Diff, verbose)))))
|
||||
}
|
||||
|
||||
// Print the scheduler dry-run output
|
||||
c.Ui.Output(c.Colorize().Color("[bold]Scheduler dry-run:[reset]"))
|
||||
c.Ui.Output(c.Colorize().Color(formatDryRun(resp.CreatedEvals)))
|
||||
|
||||
// Print the job index info
|
||||
c.Ui.Output(c.Colorize().Color(formatJobModifyIndex(resp.JobModifyIndex, file)))
|
||||
return 0
|
||||
}
|
||||
|
||||
// formatJobModifyIndex produces a help string that displays the job modify
|
||||
// index and how to submit a job with it.
|
||||
func formatJobModifyIndex(jobModifyIndex uint64, jobName string) string {
|
||||
help := fmt.Sprintf(jobModifyIndexHelp, jobModifyIndex, jobName)
|
||||
out := fmt.Sprintf("[reset][bold]Job Modify Index: %d[reset]\n%s", jobModifyIndex, help)
|
||||
return out
|
||||
}
|
||||
|
||||
// formatDryRun produces a string explaining the results of the dry run.
|
||||
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 {
|
||||
@@ -156,10 +174,14 @@ func formatDryRun(evals []*api.Evaluation) string {
|
||||
return out
|
||||
}
|
||||
|
||||
// formatJobDiff produces an annoted diff of the the job. If verbose mode is
|
||||
// set, added or deleted task groups and tasks are expanded.
|
||||
func formatJobDiff(job *api.JobDiff, verbose bool) string {
|
||||
marker, _ := getDiffString(job.Type)
|
||||
out := fmt.Sprintf("%s[bold]Job: %q\n", marker, job.ID)
|
||||
|
||||
// Determine the longest markers and fields so that the output can be
|
||||
// properly alligned.
|
||||
longestField, longestMarker := getLongestPrefixes(job.Fields, job.Objects)
|
||||
for _, tg := range job.TaskGroups {
|
||||
if _, l := getDiffString(tg.Type); l > longestMarker {
|
||||
@@ -167,43 +189,35 @@ func formatJobDiff(job *api.JobDiff, verbose bool) string {
|
||||
}
|
||||
}
|
||||
|
||||
subStartPrefix := ""
|
||||
// Only show the job's field and object diffs if the job is edited or
|
||||
// verbose mode is set.
|
||||
if job.Type == "Edited" || verbose {
|
||||
for _, field := range job.Fields {
|
||||
_, mLength := getDiffString(field.Type)
|
||||
kPrefix := longestMarker - mLength
|
||||
vPrefix := longestField - len(field.Name)
|
||||
out += fmt.Sprintf("%s\n", formatFieldDiff(
|
||||
field,
|
||||
subStartPrefix,
|
||||
strings.Repeat(" ", kPrefix),
|
||||
strings.Repeat(" ", vPrefix)))
|
||||
}
|
||||
|
||||
for _, object := range job.Objects {
|
||||
_, mLength := getDiffString(object.Type)
|
||||
kPrefix := longestMarker - mLength
|
||||
out += fmt.Sprintf("%s\n", formatObjectDiff(
|
||||
object,
|
||||
subStartPrefix,
|
||||
strings.Repeat(" ", kPrefix)))
|
||||
fo := alignedFieldAndObjects(job.Fields, job.Objects, 0, longestField, longestMarker)
|
||||
out += fo
|
||||
if len(fo) > 0 {
|
||||
out += "\n"
|
||||
}
|
||||
}
|
||||
|
||||
// Print the task groups
|
||||
for _, tg := range job.TaskGroups {
|
||||
_, mLength := getDiffString(tg.Type)
|
||||
kPrefix := longestMarker - mLength
|
||||
out += fmt.Sprintf("%s\n", formatTaskGroupDiff(tg, strings.Repeat(" ", kPrefix), verbose))
|
||||
out += fmt.Sprintf("%s\n", formatTaskGroupDiff(tg, kPrefix, verbose))
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func formatTaskGroupDiff(tg *api.TaskGroupDiff, tgPrefix string, verbose bool) string {
|
||||
// formatTaskGroupDiff produces an annotated diff of a task group. If the
|
||||
// verbose field is set, the task groups fields and objects are expanded even if
|
||||
// the full object is an addition or removal. tgPrefix is the number of spaces to prefix
|
||||
// the output of the task group.
|
||||
func formatTaskGroupDiff(tg *api.TaskGroupDiff, tgPrefix int, verbose bool) string {
|
||||
marker, _ := getDiffString(tg.Type)
|
||||
out := fmt.Sprintf("%s%s[bold]Task Group: %q[reset]", marker, tgPrefix, tg.Name)
|
||||
out := fmt.Sprintf("%s%s[bold]Task Group: %q[reset]", marker, strings.Repeat(" ", tgPrefix), tg.Name)
|
||||
|
||||
// Append the updates
|
||||
// Append the updates and colorize them
|
||||
if l := len(tg.Updates); l > 0 {
|
||||
updates := make([]string, 0, l)
|
||||
for updateType, count := range tg.Updates {
|
||||
@@ -228,6 +242,8 @@ func formatTaskGroupDiff(tg *api.TaskGroupDiff, tgPrefix string, verbose bool) s
|
||||
out += "[reset]\n"
|
||||
}
|
||||
|
||||
// Determine the longest field and markers so the output is properly
|
||||
// alligned
|
||||
longestField, longestMarker := getLongestPrefixes(tg.Fields, tg.Objects)
|
||||
for _, task := range tg.Tasks {
|
||||
if _, l := getDiffString(task.Type); l > longestMarker {
|
||||
@@ -235,41 +251,36 @@ func formatTaskGroupDiff(tg *api.TaskGroupDiff, tgPrefix string, verbose bool) s
|
||||
}
|
||||
}
|
||||
|
||||
subStartPrefix := strings.Repeat(" ", len(tgPrefix)+2)
|
||||
// Only show the task groups's field and object diffs if the group is edited or
|
||||
// verbose mode is set.
|
||||
subStartPrefix := tgPrefix + 2
|
||||
if tg.Type == "Edited" || verbose {
|
||||
for _, field := range tg.Fields {
|
||||
_, mLength := getDiffString(field.Type)
|
||||
kPrefix := longestMarker - mLength
|
||||
vPrefix := longestField - len(field.Name)
|
||||
out += fmt.Sprintf("%s\n", formatFieldDiff(
|
||||
field,
|
||||
subStartPrefix,
|
||||
strings.Repeat(" ", kPrefix),
|
||||
strings.Repeat(" ", vPrefix)))
|
||||
}
|
||||
|
||||
for _, object := range tg.Objects {
|
||||
_, mLength := getDiffString(object.Type)
|
||||
kPrefix := longestMarker - mLength
|
||||
out += fmt.Sprintf("%s\n", formatObjectDiff(
|
||||
object,
|
||||
subStartPrefix,
|
||||
strings.Repeat(" ", kPrefix)))
|
||||
fo := alignedFieldAndObjects(tg.Fields, tg.Objects, subStartPrefix, longestField, longestMarker)
|
||||
out += fo
|
||||
if len(fo) > 0 {
|
||||
out += "\n"
|
||||
}
|
||||
}
|
||||
|
||||
// Output the tasks
|
||||
for _, task := range tg.Tasks {
|
||||
_, mLength := getDiffString(task.Type)
|
||||
prefix := strings.Repeat(" ", (longestMarker - mLength))
|
||||
prefix := longestMarker - mLength
|
||||
out += fmt.Sprintf("%s\n", formatTaskDiff(task, subStartPrefix, prefix, verbose))
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func formatTaskDiff(task *api.TaskDiff, startPrefix, taskPrefix string, verbose bool) string {
|
||||
// formatTaskDiff produces an annotated diff of a task. If the verbose field is
|
||||
// set, the tasks fields and objects are expanded even if the full object is an
|
||||
// addition or removal. startPrefix is the number of spaces to prefix the output of
|
||||
// the task and taskPrefix is the number of spaces to put betwen the marker and
|
||||
// task name output.
|
||||
func formatTaskDiff(task *api.TaskDiff, startPrefix, taskPrefix int, verbose bool) string {
|
||||
marker, _ := getDiffString(task.Type)
|
||||
out := fmt.Sprintf("%s%s%s[bold]Task: %q", startPrefix, marker, taskPrefix, task.Name)
|
||||
out := fmt.Sprintf("%s%s%s[bold]Task: %q",
|
||||
strings.Repeat(" ", startPrefix), marker, strings.Repeat(" ", taskPrefix), task.Name)
|
||||
if len(task.Annotations) != 0 {
|
||||
out += fmt.Sprintf(" [reset](%s)", colorAnnotations(task.Annotations))
|
||||
}
|
||||
@@ -277,39 +288,46 @@ func formatTaskDiff(task *api.TaskDiff, startPrefix, taskPrefix string, verbose
|
||||
if task.Type == "None" {
|
||||
return out
|
||||
} else if (task.Type == "Deleted" || task.Type == "Added") && !verbose {
|
||||
// Exit early if the job was not edited and it isn't verbose output
|
||||
return out
|
||||
} else {
|
||||
out += "\n"
|
||||
}
|
||||
|
||||
subStartPrefix := strings.Repeat(" ", len(startPrefix)+2)
|
||||
subStartPrefix := startPrefix + 2
|
||||
longestField, longestMarker := getLongestPrefixes(task.Fields, task.Objects)
|
||||
for _, field := range task.Fields {
|
||||
_, mLength := getDiffString(field.Type)
|
||||
kPrefix := longestMarker - mLength
|
||||
vPrefix := longestField - len(field.Name)
|
||||
out += fmt.Sprintf("%s\n", formatFieldDiff(
|
||||
field,
|
||||
subStartPrefix,
|
||||
strings.Repeat(" ", kPrefix),
|
||||
strings.Repeat(" ", vPrefix)))
|
||||
}
|
||||
|
||||
for _, object := range task.Objects {
|
||||
_, mLength := getDiffString(object.Type)
|
||||
kPrefix := longestMarker - mLength
|
||||
out += fmt.Sprintf("%s\n", formatObjectDiff(
|
||||
object,
|
||||
subStartPrefix,
|
||||
strings.Repeat(" ", kPrefix)))
|
||||
}
|
||||
|
||||
out += alignedFieldAndObjects(task.Fields, task.Objects, subStartPrefix, longestField, longestMarker)
|
||||
return out
|
||||
}
|
||||
|
||||
func formatFieldDiff(diff *api.FieldDiff, startPrefix, keyPrefix, valuePrefix string) string {
|
||||
// formatObjectDiff produces an annotated diff of an object. startPrefix is the
|
||||
// number of spaces to prefix the output of the object and keyPrefix is the number
|
||||
// of spaces to put betwen the marker and object name output.
|
||||
func formatObjectDiff(diff *api.ObjectDiff, startPrefix, keyPrefix int) string {
|
||||
start := strings.Repeat(" ", startPrefix)
|
||||
marker, _ := getDiffString(diff.Type)
|
||||
out := fmt.Sprintf("%s%s%s%s: %s", startPrefix, marker, keyPrefix, diff.Name, valuePrefix)
|
||||
out := fmt.Sprintf("%s%s%s%s {\n", start, marker, strings.Repeat(" ", keyPrefix), diff.Name)
|
||||
|
||||
// Determine the length of the longest name and longest diff marker to
|
||||
// properly align names and values
|
||||
longestField, longestMarker := getLongestPrefixes(diff.Fields, diff.Objects)
|
||||
subStartPrefix := startPrefix + 2
|
||||
out += alignedFieldAndObjects(diff.Fields, diff.Objects, subStartPrefix, longestField, longestMarker)
|
||||
return fmt.Sprintf("%s\n%s}", out, start)
|
||||
}
|
||||
|
||||
// formatFieldDiff produces an annotated diff of a field. startPrefix is the
|
||||
// number of spaces to prefix the output of the field, keyPrefix is the number
|
||||
// of spaces to put betwen the marker and field name output and valuePrefix is
|
||||
// the number of spaces to put infront of the value for aligning values.
|
||||
func formatFieldDiff(diff *api.FieldDiff, startPrefix, keyPrefix, valuePrefix int) string {
|
||||
marker, _ := getDiffString(diff.Type)
|
||||
out := fmt.Sprintf("%s%s%s%s: %s",
|
||||
strings.Repeat(" ", startPrefix),
|
||||
marker, strings.Repeat(" ", keyPrefix),
|
||||
diff.Name,
|
||||
strings.Repeat(" ", valuePrefix))
|
||||
|
||||
switch diff.Type {
|
||||
case "Added":
|
||||
out += fmt.Sprintf("%q", diff.New)
|
||||
@@ -329,6 +347,43 @@ func formatFieldDiff(diff *api.FieldDiff, startPrefix, keyPrefix, valuePrefix st
|
||||
return out
|
||||
}
|
||||
|
||||
// alignedFieldAndObjects is a helper method that prints fields and objects
|
||||
// properly aligned.
|
||||
func alignedFieldAndObjects(fields []*api.FieldDiff, objects []*api.ObjectDiff,
|
||||
startPrefix, longestField, longestMarker int) string {
|
||||
|
||||
var out string
|
||||
numFields := len(fields)
|
||||
numObjects := len(objects)
|
||||
haveObjects := numObjects != 0
|
||||
for i, field := range fields {
|
||||
_, mLength := getDiffString(field.Type)
|
||||
kPrefix := longestMarker - mLength
|
||||
vPrefix := longestField - len(field.Name)
|
||||
out += formatFieldDiff(field, startPrefix, kPrefix, vPrefix)
|
||||
|
||||
// Avoid a dangling new line
|
||||
if i+1 != numFields || haveObjects {
|
||||
out += "\n"
|
||||
}
|
||||
}
|
||||
|
||||
for i, object := range objects {
|
||||
_, mLength := getDiffString(object.Type)
|
||||
kPrefix := longestMarker - mLength
|
||||
out += formatObjectDiff(object, startPrefix, kPrefix)
|
||||
|
||||
// Avoid a dangling new line
|
||||
if i+1 != numObjects {
|
||||
out += "\n"
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// getLongestPrefixes takes a list of fields and objects and determines the
|
||||
// longest field name and the longest marker.
|
||||
func getLongestPrefixes(fields []*api.FieldDiff, objects []*api.ObjectDiff) (longestField, longestMarker int) {
|
||||
for _, field := range fields {
|
||||
if l := len(field.Name); l > longestField {
|
||||
@@ -346,47 +401,8 @@ func getLongestPrefixes(fields []*api.FieldDiff, objects []*api.ObjectDiff) (lon
|
||||
return longestField, longestMarker
|
||||
}
|
||||
|
||||
func formatObjectDiff(diff *api.ObjectDiff, startPrefix, keyPrefix string) string {
|
||||
marker, _ := getDiffString(diff.Type)
|
||||
out := fmt.Sprintf("%s%s%s%s {\n", startPrefix, marker, keyPrefix, diff.Name)
|
||||
|
||||
// Determine the length of the longest name and longest diff marker to
|
||||
// properly align names and values
|
||||
longestField, longestMarker := getLongestPrefixes(diff.Fields, diff.Objects)
|
||||
subStartPrefix := strings.Repeat(" ", len(startPrefix)+2)
|
||||
numFields := len(diff.Fields)
|
||||
numObjects := len(diff.Objects)
|
||||
haveObjects := numObjects != 0
|
||||
for i, field := range diff.Fields {
|
||||
_, mLength := getDiffString(field.Type)
|
||||
kPrefix := longestMarker - mLength
|
||||
vPrefix := longestField - len(field.Name)
|
||||
out += formatFieldDiff(
|
||||
field,
|
||||
subStartPrefix,
|
||||
strings.Repeat(" ", kPrefix),
|
||||
strings.Repeat(" ", vPrefix))
|
||||
|
||||
// Avoid a dangling new line
|
||||
if i+1 != numFields || haveObjects {
|
||||
out += "\n"
|
||||
}
|
||||
}
|
||||
|
||||
for i, object := range diff.Objects {
|
||||
_, mLength := getDiffString(object.Type)
|
||||
kPrefix := longestMarker - mLength
|
||||
out += formatObjectDiff(object, subStartPrefix, strings.Repeat(" ", kPrefix))
|
||||
|
||||
// Avoid a dangling new line
|
||||
if i+1 != numObjects {
|
||||
out += "\n"
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s\n%s}", out, startPrefix)
|
||||
}
|
||||
|
||||
// getDiffString returns a colored diff marker and the length of the string
|
||||
// without color annotations.
|
||||
func getDiffString(diffType string) (string, int) {
|
||||
switch diffType {
|
||||
case "Added":
|
||||
@@ -400,6 +416,8 @@ func getDiffString(diffType string) (string, int) {
|
||||
}
|
||||
}
|
||||
|
||||
// colorAnnotations returns a comma concatonated list of the annotations where
|
||||
// the annotations are colored where possible.
|
||||
func colorAnnotations(annotations []string) string {
|
||||
l := len(annotations)
|
||||
if l == 0 {
|
||||
|
||||
Reference in New Issue
Block a user