-
Notifications
You must be signed in to change notification settings - Fork 201
Commit
* Enhancing the CLI to get the node and job status * Adding openebs to the path * Adding glide in build script * Update vendor directory during bootstrap * updating some specific packages * ignoring some-packges * Running By Shell * Enhancing the CLI to get the node and job status * Adding openebs to the path * Adding glide in build script * Update vendor directory during bootstrap * updating some specific packages * ignoring some-packges * Running By Shell * Merging master-changes * Fixing marge conflict * Updating dep * updating gitignore * Adding Master and host status CLI commands * Updating make
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,3 +9,4 @@ nohup.out | |
hello.nomad | ||
clientpeers | ||
serverpeers | ||
vendor/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,6 +48,7 @@ fi | |
|
||
# Build! | ||
echo "==> Building..." | ||
#glide up | ||
gox \ | ||
-os="${XC_OS}" \ | ||
-arch="${XC_ARCH}" \ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package command | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
prateekpandey14
Author
Contributor
|
||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"text/template" | ||
) | ||
|
||
//DataFormatter is a transformer of the data. | ||
type DataFormatter interface { | ||
// TransformData should return transformed string data. | ||
TransformData(interface{}) (string, error) | ||
} | ||
|
||
// DataFormat returns the data formatter specified format. | ||
func DataFormat(format, tmpl string) (DataFormatter, error) { | ||
switch format { | ||
case "json": | ||
if len(tmpl) > 0 { | ||
return nil, fmt.Errorf("json format does not support template option.") | ||
} | ||
return &JSONFormat{}, nil | ||
case "template": | ||
return &TemplateFormat{tmpl}, nil | ||
} | ||
return nil, fmt.Errorf("Unsupported format is specified.") | ||
} | ||
|
||
type JSONFormat struct { | ||
} | ||
|
||
// TransformData returns JSON format string data. | ||
func (p *JSONFormat) TransformData(data interface{}) (string, error) { | ||
out, err := json.MarshalIndent(&data, "", " ") | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
return string(out), nil | ||
} | ||
|
||
type TemplateFormat struct { | ||
tmpl string | ||
} | ||
|
||
// TransformData returns template format string data. | ||
func (p *TemplateFormat) TransformData(data interface{}) (string, error) { | ||
var out io.Writer = new(bytes.Buffer) | ||
if len(p.tmpl) == 0 { | ||
return "", fmt.Errorf("template needs to be specified the golang templates.") | ||
} | ||
|
||
t, err := template.New("format").Parse(p.tmpl) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
err = t.Execute(out, data) | ||
if err != nil { | ||
return "", err | ||
} | ||
return fmt.Sprint(out), nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,272 @@ | ||
package command | ||
|
||
import ( | ||
"fmt" | ||
"sort" | ||
"strings" | ||
|
||
"github.com/hashicorp/nomad/api" | ||
) | ||
|
||
type EvalStatusCommand struct { | ||
Meta | ||
} | ||
|
||
func (c *EvalStatusCommand) Help() string { | ||
helpText := ` | ||
Usage: nomad eval-status [options] <evaluation-id> | ||
This comment has been minimized.
Sorry, something went wrong.
AmitKumarDas
|
||
Display information about evaluations. This command can be used to inspect the | ||
current status of an evaluation as well as determine the reason an evaluation | ||
did not place all allocations. | ||
General Options: | ||
` + generalOptionsUsage() + ` | ||
Eval Status Options: | ||
-monitor | ||
Monitor an outstanding evaluation | ||
-verbose | ||
Show full information. | ||
-json | ||
Output the evaluation in its JSON format. | ||
-t | ||
Format and display evaluation using a Go template. | ||
` | ||
|
||
return strings.TrimSpace(helpText) | ||
} | ||
|
||
func (c *EvalStatusCommand) Synopsis() string { | ||
return "Display evaluation status and placement failure reasons" | ||
} | ||
|
||
func (c *EvalStatusCommand) Run(args []string) int { | ||
var monitor, verbose, json bool | ||
var tmpl string | ||
|
||
flags := c.Meta.FlagSet("eval-status", FlagSetClient) | ||
flags.Usage = func() { c.Ui.Output(c.Help()) } | ||
flags.BoolVar(&monitor, "monitor", false, "") | ||
flags.BoolVar(&verbose, "verbose", false, "") | ||
flags.BoolVar(&json, "json", false, "") | ||
flags.StringVar(&tmpl, "t", "", "") | ||
|
||
if err := flags.Parse(args); err != nil { | ||
return 1 | ||
} | ||
|
||
// Check that we got exactly one evaluation ID | ||
This comment has been minimized.
Sorry, something went wrong.
AmitKumarDas
|
||
args = flags.Args() | ||
|
||
// Get the HTTP client | ||
client, err := c.Meta.Client() | ||
if err != nil { | ||
c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) | ||
return 1 | ||
} | ||
|
||
// If args not specified but output format is specified, format and output the evaluations data list | ||
if len(args) == 0 { | ||
var format string | ||
if json && len(tmpl) > 0 { | ||
c.Ui.Error("Both -json and -t are not allowed") | ||
return 1 | ||
} else if json { | ||
format = "json" | ||
} else if len(tmpl) > 0 { | ||
format = "template" | ||
} | ||
if len(format) > 0 { | ||
evals, _, err := client.Evaluations().List(nil) | ||
if err != nil { | ||
c.Ui.Error(fmt.Sprintf("Error querying evaluations: %v", err)) | ||
return 1 | ||
} | ||
// Return nothing if no evaluations found | ||
if len(evals) == 0 { | ||
This comment has been minimized.
Sorry, something went wrong. |
||
return 0 | ||
} | ||
|
||
f, err := DataFormat(format, tmpl) | ||
if err != nil { | ||
c.Ui.Error(fmt.Sprintf("Error getting formatter: %s", err)) | ||
return 1 | ||
} | ||
|
||
out, err := f.TransformData(evals) | ||
if err != nil { | ||
c.Ui.Error(fmt.Sprintf("Error formatting the data: %s", err)) | ||
return 1 | ||
} | ||
c.Ui.Output(out) | ||
return 0 | ||
} | ||
} | ||
|
||
if len(args) != 1 { | ||
c.Ui.Error(c.Help()) | ||
return 1 | ||
} | ||
|
||
evalID := args[0] | ||
|
||
// Truncate the id unless full length is requested | ||
length := shortId | ||
if verbose { | ||
length = fullId | ||
} | ||
|
||
// Query the allocation info | ||
if len(evalID) == 1 { | ||
c.Ui.Error(fmt.Sprintf("Identifier must contain at least two characters.")) | ||
return 1 | ||
} | ||
if len(evalID)%2 == 1 { | ||
// Identifiers must be of even length, so we strip off the last byte | ||
// to provide a consistent user experience. | ||
evalID = evalID[:len(evalID)-1] | ||
} | ||
|
||
evals, _, err := client.Evaluations().PrefixList(evalID) | ||
if err != nil { | ||
c.Ui.Error(fmt.Sprintf("Error querying evaluation: %v", err)) | ||
return 1 | ||
} | ||
if len(evals) == 0 { | ||
c.Ui.Error(fmt.Sprintf("No evaluation(s) with prefix or id %q found", evalID)) | ||
return 1 | ||
} | ||
|
||
if len(evals) > 1 { | ||
// Format the evals | ||
out := make([]string, len(evals)+1) | ||
out[0] = "ID|Priority|Triggered By|Status|Placement Failures" | ||
for i, eval := range evals { | ||
failures, _ := evalFailureStatus(eval) | ||
out[i+1] = fmt.Sprintf("%s|%d|%s|%s|%s", | ||
limit(eval.ID, length), | ||
eval.Priority, | ||
eval.TriggeredBy, | ||
eval.Status, | ||
failures, | ||
) | ||
} | ||
c.Ui.Output(fmt.Sprintf("Prefix matched multiple evaluations\n\n%s", formatList(out))) | ||
return 0 | ||
} | ||
|
||
// If we are in monitor mode, monitor and exit | ||
if monitor { | ||
mon := newMonitor(c.Ui, client, length) | ||
return mon.monitor(evals[0].ID, true) | ||
} | ||
|
||
// Prefix lookup matched a single evaluation | ||
eval, _, err := client.Evaluations().Info(evals[0].ID, nil) | ||
if err != nil { | ||
c.Ui.Error(fmt.Sprintf("Error querying evaluation: %s", err)) | ||
return 1 | ||
} | ||
|
||
// If output format is specified, format and output the data | ||
var format string | ||
if json { | ||
format = "json" | ||
} else if len(tmpl) > 0 { | ||
format = "template" | ||
} | ||
if len(format) > 0 { | ||
f, err := DataFormat(format, tmpl) | ||
if err != nil { | ||
c.Ui.Error(fmt.Sprintf("Error getting formatter: %s", err)) | ||
return 1 | ||
} | ||
|
||
out, err := f.TransformData(eval) | ||
if err != nil { | ||
c.Ui.Error(fmt.Sprintf("Error formatting the data: %s", err)) | ||
return 1 | ||
} | ||
c.Ui.Output(out) | ||
return 0 | ||
} | ||
|
||
failureString, failures := evalFailureStatus(eval) | ||
triggerNoun, triggerSubj := getTriggerDetails(eval) | ||
statusDesc := eval.StatusDescription | ||
if statusDesc == "" { | ||
statusDesc = eval.Status | ||
} | ||
|
||
// Format the evaluation data | ||
basic := []string{ | ||
fmt.Sprintf("ID|%s", limit(eval.ID, length)), | ||
fmt.Sprintf("Status|%s", eval.Status), | ||
fmt.Sprintf("Status Description|%s", statusDesc), | ||
fmt.Sprintf("Type|%s", eval.Type), | ||
fmt.Sprintf("TriggeredBy|%s", eval.TriggeredBy), | ||
fmt.Sprintf("%s|%s", triggerNoun, triggerSubj), | ||
fmt.Sprintf("Priority|%d", eval.Priority), | ||
fmt.Sprintf("Placement Failures|%s", failureString), | ||
} | ||
|
||
if verbose { | ||
// NextEval, PreviousEval, BlockedEval | ||
basic = append(basic, | ||
fmt.Sprintf("Previous Eval|%s", eval.PreviousEval), | ||
fmt.Sprintf("Next Eval|%s", eval.NextEval), | ||
fmt.Sprintf("Blocked Eval|%s", eval.BlockedEval)) | ||
} | ||
c.Ui.Output(formatKV(basic)) | ||
|
||
if failures { | ||
c.Ui.Output(c.Colorize().Color("\n[bold]Failed Placements[reset]")) | ||
sorted := sortedTaskGroupFromMetrics(eval.FailedTGAllocs) | ||
for _, tg := range sorted { | ||
metrics := eval.FailedTGAllocs[tg] | ||
|
||
noun := "allocation" | ||
if metrics.CoalescedFailures > 0 { | ||
noun += "s" | ||
} | ||
c.Ui.Output(fmt.Sprintf("Task Group %q (failed to place %d %s):", tg, metrics.CoalescedFailures+1, noun)) | ||
c.Ui.Output(formatAllocMetrics(metrics, false, " ")) | ||
c.Ui.Output("") | ||
} | ||
|
||
if eval.BlockedEval != "" { | ||
c.Ui.Output(fmt.Sprintf("Evaluation %q waiting for additional capacity to place remainder", | ||
limit(eval.BlockedEval, length))) | ||
} | ||
} | ||
|
||
return 0 | ||
} | ||
|
||
func sortedTaskGroupFromMetrics(groups map[string]*api.AllocationMetric) []string { | ||
tgs := make([]string, 0, len(groups)) | ||
for tg, _ := range groups { | ||
tgs = append(tgs, tg) | ||
} | ||
sort.Strings(tgs) | ||
return tgs | ||
} | ||
|
||
func getTriggerDetails(eval *api.Evaluation) (noun, subject string) { | ||
switch eval.TriggeredBy { | ||
case "job-register", "job-deregister", "periodic-job", "rolling-update": | ||
return "Job ID", eval.JobID | ||
case "node-update": | ||
return "Node ID", eval.NodeID | ||
case "max-plan-attempts": | ||
return "Previous Eval", eval.PreviousEval | ||
default: | ||
return "", "" | ||
} | ||
} |
Did we try to use the original .go file by using go
import
?Do we need to duplicate this file ?
Is there anything that is Maya specific ?