add time flag to add created column to allocation

This commit is contained in:
Cameron Davison
2016-08-04 20:36:22 -05:00
parent bc6db9c138
commit 40bc21fa8f
4 changed files with 65 additions and 8 deletions

View File

@@ -23,6 +23,7 @@ type StatusCommand struct {
length int
evals bool
verbose bool
time bool
}
func (c *StatusCommand) Help() string {
@@ -45,6 +46,9 @@ Status Options:
-evals
Display the evaluations associated with the job.
-time
Display allocation creation time.
-verbose
Display full information.
`
@@ -63,6 +67,7 @@ func (c *StatusCommand) Run(args []string) int {
flags.BoolVar(&short, "short", false, "")
flags.BoolVar(&c.evals, "evals", false, "")
flags.BoolVar(&c.verbose, "verbose", false, "")
flags.BoolVar(&c.time, "time", false, "")
if err := flags.Parse(args); err != nil {
return 1
@@ -302,6 +307,9 @@ func (c *StatusCommand) outputJobInfo(client *api.Client, job *api.Job) error {
if len(jobAllocs) > 0 {
allocs = make([]string, len(jobAllocs)+1)
allocs[0] = "ID|Eval ID|Node ID|Task Group|Desired|Status"
if c.time {
allocs[0] += "|Created"
}
for i, alloc := range jobAllocs {
allocs[i+1] = fmt.Sprintf("%s|%s|%s|%s|%s|%s",
limit(alloc.ID, c.length),
@@ -310,6 +318,10 @@ func (c *StatusCommand) outputJobInfo(client *api.Client, job *api.Job) error {
alloc.TaskGroup,
alloc.DesiredStatus,
alloc.ClientStatus)
if c.time {
allocs[i+1] += fmt.Sprintf("|%s",
c.formatUnixNanoTime(alloc.CreateTime))
}
}
c.Ui.Output(formatList(allocs))
@@ -346,6 +358,12 @@ func (c *StatusCommand) outputFailedPlacements(failedEval *api.Evaluation) {
}
}
// formatUnixNanoTime is a helper for formatting time for output.
func (c *StatusCommand) formatUnixNanoTime(nano int64) string {
t := time.Unix(0, nano)
return formatTime(t)
}
// convertApiJob is used to take a *api.Job and convert it to an *struct.Job.
// This function is just a hammer and probably needs to be revisited.
func convertApiJob(in *api.Job) (*structs.Job, error) {
@@ -363,7 +381,7 @@ func convertApiJob(in *api.Job) (*structs.Job, error) {
}
// list general information about a list of jobs
func createStatusListOutput(jobs []*structs.JobListStub) ([]string) {
func createStatusListOutput(jobs []*api.JobListStub) string {
out := make([]string, len(jobs)+1)
out[0] = "ID|Type|Priority|Status"
for i, job := range jobs {
@@ -374,4 +392,4 @@ func createStatusListOutput(jobs []*structs.JobListStub) ([]string) {
job.Status)
}
return formatList(out)
}
}

View File

@@ -5,6 +5,8 @@ import (
"testing"
"github.com/mitchellh/cli"
"github.com/hashicorp/nomad/testutil"
"github.com/hashicorp/nomad/api"
)
func TestStatusCommand_Implements(t *testing.T) {
@@ -12,7 +14,9 @@ func TestStatusCommand_Implements(t *testing.T) {
}
func TestStatusCommand_Run(t *testing.T) {
srv, client, url := testServer(t, nil)
srv, client, url := testServer(t, func(c *testutil.TestServerConfig) {
c.DevMode = true
})
defer srv.Stop()
ui := new(cli.MockUi)
@@ -33,14 +37,22 @@ func TestStatusCommand_Run(t *testing.T) {
// Register two jobs
job1 := testJob("job1_sfx")
evalId, _, err := client.Jobs().Register(job1, nil)
evalId1, _, err := client.Jobs().Register(job1, nil)
if err != nil {
t.Fatalf("err: %s", err)
}
if code := waitForSuccess(ui, client, fullId, t, evalId1); code != 0 {
t.Fatalf("status code non zero saw %d", code)
}
job2 := testJob("job2_sfx")
if _, _, err := client.Jobs().Register(job2, nil); err != nil {
evalId2, _, err := client.Jobs().Register(job2, nil);
if err != nil {
t.Fatalf("err: %s", err)
}
if code := waitForSuccess(ui, client, fullId, t, evalId2); code != 0 {
t.Fatalf("status code non zero saw %d", code)
}
// Query again and check the result
if code := cmd.Run([]string{"-address=" + url}); code != 0 {
@@ -98,6 +110,25 @@ func TestStatusCommand_Run(t *testing.T) {
if !strings.Contains(out, "Allocations") {
t.Fatalf("should dump allocations")
}
if strings.Contains(out, "Created") {
t.Fatal("should not have created header")
}
ui.OutputWriter.Reset()
// Query a single job in time mode
if code := cmd.Run([]string{"-address=" + url, "-time", "job1_sfx"}); code != 0 {
t.Fatalf("expected exit 0, got: %d", code)
}
out = ui.OutputWriter.String()
if strings.Contains(out, "job2_sfx") || !strings.Contains(out, "job1_sfx") {
t.Fatalf("expected only job1_sfx, got: %s", out)
}
if !strings.Contains(out, "Allocations") {
t.Fatal("should dump allocations")
}
if !strings.Contains(out, "Created") {
t.Fatal("should have created header")
}
ui.OutputWriter.Reset()
// Query jobs with prefix match
@@ -134,7 +165,7 @@ func TestStatusCommand_Run(t *testing.T) {
if strings.Contains(out, "Allocations") {
t.Fatalf("should not dump allocations")
}
if strings.Contains(out, evalId) {
if strings.Contains(out, evalId1) {
t.Fatalf("should not contain full identifiers, got %s", out)
}
ui.OutputWriter.Reset()
@@ -144,7 +175,7 @@ func TestStatusCommand_Run(t *testing.T) {
t.Fatalf("expected exit 0, got: %d", code)
}
out = ui.OutputWriter.String()
if !strings.Contains(out, evalId) {
if !strings.Contains(out, evalId1) {
t.Fatalf("should contain full identifiers, got %s", out)
}
}
@@ -170,3 +201,9 @@ func TestStatusCommand_Fails(t *testing.T) {
t.Fatalf("expected failed query error, got: %s", out)
}
}
func waitForSuccess(ui cli.Ui, client *api.Client, length int, t *testing.T, evalId string) int {
mon := newMonitor(ui, client, length)
monErr := mon.monitor(evalId, false)
return monErr
}

View File

@@ -39,7 +39,7 @@ func testServer(
}
func testJob(jobID string) *api.Job {
task := api.NewTask("task1", "exec").
task := api.NewTask("task1", "raw_exec").
SetConfig("command", "/bin/sleep").
Require(&api.Resources{
MemoryMB: 256,

View File

@@ -94,11 +94,13 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
Meta: meta,
}, nil
},
"plan": func() (cli.Command, error) {
return &command.PlanCommand{
Meta: meta,
}, nil
},
"run": func() (cli.Command, error) {
return &command.RunCommand{
Meta: meta,