diff --git a/api/allocations.go b/api/allocations.go index d622f86b0a5..80987fb4b45 100644 --- a/api/allocations.go +++ b/api/allocations.go @@ -86,6 +86,7 @@ type Allocation struct { EvalID string Name string NodeID string + NodeName string JobID string Job *Job TaskGroup string @@ -149,6 +150,7 @@ type AllocationListStub struct { Name string Namespace string NodeID string + NodeName string JobID string JobType string JobVersion uint64 diff --git a/command/alloc_status.go b/command/alloc_status.go index 44ae2bb0a10..b656657b8aa 100644 --- a/command/alloc_status.go +++ b/command/alloc_status.go @@ -233,6 +233,7 @@ func formatAllocBasicInfo(alloc *api.Allocation, client *api.Client, uuidLength fmt.Sprintf("Eval ID|%s", limit(alloc.EvalID, uuidLength)), fmt.Sprintf("Name|%s", alloc.Name), fmt.Sprintf("Node ID|%s", limit(alloc.NodeID, uuidLength)), + fmt.Sprintf("Node Name|%s", alloc.NodeName), fmt.Sprintf("Job ID|%s", alloc.JobID), fmt.Sprintf("Job Version|%d", getVersion(alloc.Job)), fmt.Sprintf("Client Status|%s", alloc.ClientStatus), diff --git a/command/alloc_status_test.go b/command/alloc_status_test.go index fbd19942497..b3c7fef2070 100644 --- a/command/alloc_status_test.go +++ b/command/alloc_status_test.go @@ -120,9 +120,11 @@ func TestAllocStatusCommand_Run(t *testing.T) { } // get an alloc id allocId1 := "" + nodeName := "" if allocs, _, err := client.Jobs().Allocations(jobID, false, nil); err == nil { if len(allocs) > 0 { allocId1 = allocs[0].ID + nodeName = allocs[0].NodeName } } if allocId1 == "" { @@ -141,6 +143,9 @@ func TestAllocStatusCommand_Run(t *testing.T) { t.Fatalf("expected to have 'Modified' but saw: %s", out) } + nodeNameRegexpStr := fmt.Sprintf(`\nNode Name\s+= %s\n`, regexp.QuoteMeta(nodeName)) + require.Regexp(t, regexp.MustCompile(nodeNameRegexpStr), out) + ui.OutputWriter.Reset() if code := cmd.Run([]string{"-address=" + url, "-verbose", allocId1}); code != 0 { diff --git a/command/job_status.go b/command/job_status.go index 9e7f9db8bb8..6fa696ba5ab 100644 --- a/command/job_status.go +++ b/command/job_status.go @@ -413,12 +413,13 @@ func formatAllocListStubs(stubs []*api.AllocationListStub, verbose bool, uuidLen allocs := make([]string, len(stubs)+1) if verbose { - allocs[0] = "ID|Eval ID|Node ID|Task Group|Version|Desired|Status|Created|Modified" + allocs[0] = "ID|Eval ID|Node ID|Node Name|Task Group|Version|Desired|Status|Created|Modified" for i, alloc := range stubs { - allocs[i+1] = fmt.Sprintf("%s|%s|%s|%s|%d|%s|%s|%s|%s", + allocs[i+1] = fmt.Sprintf("%s|%s|%s|%s|%s|%d|%s|%s|%s|%s", limit(alloc.ID, uuidLength), limit(alloc.EvalID, uuidLength), limit(alloc.NodeID, uuidLength), + alloc.NodeName, alloc.TaskGroup, alloc.JobVersion, alloc.DesiredStatus, diff --git a/command/job_status_test.go b/command/job_status_test.go index e0bc40b565b..745af018e4c 100644 --- a/command/job_status_test.go +++ b/command/job_status_test.go @@ -2,6 +2,7 @@ package command import ( "fmt" + "regexp" "strings" "testing" "time" @@ -123,6 +124,14 @@ func TestJobStatusCommand_Run(t *testing.T) { if code := cmd.Run([]string{"-address=" + url, "-verbose", "job2_sfx"}); code != 0 { t.Fatalf("expected exit 0, got: %d", code) } + + nodeName := "" + if allocs, _, err := client.Jobs().Allocations("job2_sfx", false, nil); err == nil { + if len(allocs) > 0 { + nodeName = allocs[0].NodeName + } + } + out = ui.OutputWriter.String() if strings.Contains(out, "job1_sfx") || !strings.Contains(out, "job2_sfx") { t.Fatalf("expected only job2_sfx, got: %s", out) @@ -139,6 +148,15 @@ func TestJobStatusCommand_Run(t *testing.T) { if !strings.Contains(out, "Modified") { t.Fatal("should have modified header") } + + // string calculations based on 1-byte chars, not using runes + allocationsTableName := "Allocations\n" + allocationsTableStr := strings.Split(out, allocationsTableName)[1] + nodeNameHeaderStr := "Node Name" + nodeNameHeaderIndex := strings.Index(allocationsTableStr, nodeNameHeaderStr) + nodeNameRegexpStr := fmt.Sprintf(`.*%s.*\n.{%d}%s`, nodeNameHeaderStr, nodeNameHeaderIndex, regexp.QuoteMeta(nodeName)) + require.Regexp(t, regexp.MustCompile(nodeNameRegexpStr), out) + ui.ErrorWriter.Reset() ui.OutputWriter.Reset() diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index b735d6e37e1..203e45b6127 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -7125,6 +7125,9 @@ type Allocation struct { // NodeID is the node this is being placed on NodeID string + // NodeName is the name of the node this is being placed on. + NodeName string + // Job is the parent job of the task group being allocated. // This is copied at allocation time to avoid issues if the job // definition is updated. @@ -7582,6 +7585,7 @@ func (a *Allocation) Stub() *AllocListStub { Name: a.Name, Namespace: a.Namespace, NodeID: a.NodeID, + NodeName: a.NodeName, JobID: a.JobID, JobType: a.Job.Type, JobVersion: a.Job.Version, @@ -7609,6 +7613,7 @@ type AllocListStub struct { Name string Namespace string NodeID string + NodeName string JobID string JobType string JobVersion uint64 diff --git a/scheduler/generic_sched.go b/scheduler/generic_sched.go index 93f982ede7d..7b276c1c238 100644 --- a/scheduler/generic_sched.go +++ b/scheduler/generic_sched.go @@ -6,7 +6,7 @@ import ( log "github.com/hashicorp/go-hclog" memdb "github.com/hashicorp/go-memdb" - "github.com/hashicorp/go-multierror" + multierror "github.com/hashicorp/go-multierror" "github.com/hashicorp/nomad/helper/uuid" "github.com/hashicorp/nomad/nomad/structs" ) @@ -495,6 +495,7 @@ func (s *GenericScheduler) computePlacements(destructive, place []placementResul TaskGroup: tg.Name, Metrics: s.ctx.Metrics(), NodeID: option.Node.ID, + NodeName: option.Node.Name, DeploymentID: deploymentID, TaskResources: resources.OldTaskResources(), AllocatedResources: resources, diff --git a/scheduler/system_sched.go b/scheduler/system_sched.go index e3f4015fbd1..fc19e714d70 100644 --- a/scheduler/system_sched.go +++ b/scheduler/system_sched.go @@ -331,6 +331,7 @@ func (s *SystemScheduler) computePlacements(place []allocTuple) error { TaskGroup: missing.TaskGroup.Name, Metrics: s.ctx.Metrics(), NodeID: option.Node.ID, + NodeName: option.Node.Name, TaskResources: resources.OldTaskResources(), AllocatedResources: resources, DesiredStatus: structs.AllocDesiredStatusRun,