Populate DisplayMessage in various http endpoints that return allocations, plus unit tests.

This commit is contained in:
Preetha Appan 2017-11-17 14:53:26 -06:00
parent 1d321f3556
commit 3592635ede
9 changed files with 109 additions and 4 deletions

View file

@ -34,6 +34,9 @@ func (s *HTTPServer) AllocsRequest(resp http.ResponseWriter, req *http.Request)
if out.Allocations == nil { if out.Allocations == nil {
out.Allocations = make([]*structs.AllocListStub, 0) out.Allocations = make([]*structs.AllocListStub, 0)
} }
for _, alloc := range out.Allocations {
alloc.SetEventDisplayMessages()
}
return out.Allocations, nil return out.Allocations, nil
} }
@ -70,6 +73,7 @@ func (s *HTTPServer) AllocSpecificRequest(resp http.ResponseWriter, req *http.Re
alloc = alloc.Copy() alloc = alloc.Copy()
alloc.Job.Payload = decoded alloc.Job.Payload = decoded
} }
alloc.SetEventDisplayMessages()
return alloc, nil return alloc, nil
} }

View file

@ -22,7 +22,17 @@ func TestHTTP_AllocsList(t *testing.T) {
// Directly manipulate the state // Directly manipulate the state
state := s.Agent.server.State() state := s.Agent.server.State()
alloc1 := mock.Alloc() alloc1 := mock.Alloc()
testEvent := structs.NewTaskEvent(structs.TaskSiblingFailed)
var events1 []*structs.TaskEvent
events1 = append(events1, testEvent)
taskState := &structs.TaskState{Events: events1}
alloc1.TaskStates = make(map[string]*structs.TaskState)
alloc1.TaskStates["test"] = taskState
alloc2 := mock.Alloc() alloc2 := mock.Alloc()
alloc2.TaskStates = make(map[string]*structs.TaskState)
alloc2.TaskStates["test"] = taskState
state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID)) state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID))
state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID)) state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID))
err := state.UpsertAllocs(1000, err := state.UpsertAllocs(1000,
@ -56,10 +66,15 @@ func TestHTTP_AllocsList(t *testing.T) {
} }
// Check the alloc // Check the alloc
n := obj.([]*structs.AllocListStub) allocs := obj.([]*structs.AllocListStub)
if len(n) != 2 { if len(allocs) != 2 {
t.Fatalf("bad: %#v", n) t.Fatalf("bad: %#v", allocs)
} }
expectedMsg := "Task's sibling failed"
displayMsg1 := allocs[0].TaskStates["test"].Events[0].DisplayMessage
assert.Equal(t, expectedMsg, displayMsg1, "DisplayMessage should be set")
displayMsg2 := allocs[0].TaskStates["test"].Events[0].DisplayMessage
assert.Equal(t, expectedMsg, displayMsg2, "DisplayMessage should be set")
}) })
} }
@ -73,6 +88,14 @@ func TestHTTP_AllocsPrefixList(t *testing.T) {
alloc1.ID = "aaaaaaaa-e8f7-fd38-c855-ab94ceb89706" alloc1.ID = "aaaaaaaa-e8f7-fd38-c855-ab94ceb89706"
alloc2 := mock.Alloc() alloc2 := mock.Alloc()
alloc2.ID = "aaabbbbb-e8f7-fd38-c855-ab94ceb89706" alloc2.ID = "aaabbbbb-e8f7-fd38-c855-ab94ceb89706"
testEvent := structs.NewTaskEvent(structs.TaskSiblingFailed)
var events1 []*structs.TaskEvent
events1 = append(events1, testEvent)
taskState := &structs.TaskState{Events: events1}
alloc2.TaskStates = make(map[string]*structs.TaskState)
alloc2.TaskStates["test"] = taskState
summary1 := mock.JobSummary(alloc1.JobID) summary1 := mock.JobSummary(alloc1.JobID)
summary2 := mock.JobSummary(alloc2.JobID) summary2 := mock.JobSummary(alloc2.JobID)
if err := state.UpsertJobSummary(998, summary1); err != nil { if err := state.UpsertJobSummary(998, summary1); err != nil {
@ -120,6 +143,10 @@ func TestHTTP_AllocsPrefixList(t *testing.T) {
if n[0].ID != alloc2.ID { if n[0].ID != alloc2.ID {
t.Fatalf("expected alloc ID: %v, Actual: %v", alloc2.ID, n[0].ID) t.Fatalf("expected alloc ID: %v, Actual: %v", alloc2.ID, n[0].ID)
} }
expectedMsg := "Task's sibling failed"
displayMsg1 := n[0].TaskStates["test"].Events[0].DisplayMessage
assert.Equal(t, expectedMsg, displayMsg1, "DisplayMessage should be set")
}) })
} }

View file

@ -166,6 +166,9 @@ func (s *HTTPServer) deploymentAllocations(resp http.ResponseWriter, req *http.R
if out.Allocations == nil { if out.Allocations == nil {
out.Allocations = make([]*structs.AllocListStub, 0) out.Allocations = make([]*structs.AllocListStub, 0)
} }
for _, alloc := range out.Allocations {
alloc.SetEventDisplayMessages()
}
return out.Allocations, nil return out.Allocations, nil
} }

View file

@ -87,9 +87,26 @@ func TestHTTP_DeploymentAllocations(t *testing.T) {
a1 := mock.Alloc() a1 := mock.Alloc()
a1.JobID = j.ID a1.JobID = j.ID
a1.DeploymentID = d.ID a1.DeploymentID = d.ID
testEvent := structs.NewTaskEvent(structs.TaskSiblingFailed)
var events1 []*structs.TaskEvent
events1 = append(events1, testEvent)
taskState := &structs.TaskState{Events: events1}
a1.TaskStates = make(map[string]*structs.TaskState)
a1.TaskStates["test"] = taskState
a2 := mock.Alloc() a2 := mock.Alloc()
a2.JobID = j.ID a2.JobID = j.ID
a2.DeploymentID = d.ID a2.DeploymentID = d.ID
// Create a test event
testEvent2 := structs.NewTaskEvent(structs.TaskSiblingFailed)
var events2 []*structs.TaskEvent
events2 = append(events2, testEvent2)
taskState2 := &structs.TaskState{Events: events2}
a2.TaskStates = make(map[string]*structs.TaskState)
a2.TaskStates["test"] = taskState2
assert.Nil(state.UpsertJob(998, j), "UpsertJob") assert.Nil(state.UpsertJob(998, j), "UpsertJob")
assert.Nil(state.UpsertDeployment(999, d), "UpsertDeployment") assert.Nil(state.UpsertDeployment(999, d), "UpsertDeployment")
assert.Nil(state.UpsertAllocs(1000, []*structs.Allocation{a1, a2}), "UpsertAllocs") assert.Nil(state.UpsertAllocs(1000, []*structs.Allocation{a1, a2}), "UpsertAllocs")
@ -108,9 +125,14 @@ func TestHTTP_DeploymentAllocations(t *testing.T) {
assert.Equal("true", respW.HeaderMap.Get("X-Nomad-KnownLeader"), "missing known leader") assert.Equal("true", respW.HeaderMap.Get("X-Nomad-KnownLeader"), "missing known leader")
assert.NotZero(respW.HeaderMap.Get("X-Nomad-LastContact"), "missing last contact") assert.NotZero(respW.HeaderMap.Get("X-Nomad-LastContact"), "missing last contact")
// Check the ouptput // Check the output
allocs := obj.([]*structs.AllocListStub) allocs := obj.([]*structs.AllocListStub)
assert.Len(allocs, 2, "Deployment Allocs") assert.Len(allocs, 2, "Deployment Allocs")
expectedMsg := "Task's sibling failed"
displayMsg1 := allocs[0].TaskStates["test"].Events[0].DisplayMessage
assert.Equal(expectedMsg, displayMsg1, "DisplayMessage should be set")
displayMsg2 := allocs[0].TaskStates["test"].Events[0].DisplayMessage
assert.Equal(expectedMsg, displayMsg2, "DisplayMessage should be set")
}) })
} }

View file

@ -217,6 +217,9 @@ func (s *HTTPServer) jobAllocations(resp http.ResponseWriter, req *http.Request,
if out.Allocations == nil { if out.Allocations == nil {
out.Allocations = make([]*structs.AllocListStub, 0) out.Allocations = make([]*structs.AllocListStub, 0)
} }
for _, alloc := range out.Allocations {
alloc.SetEventDisplayMessages()
}
return out.Allocations, nil return out.Allocations, nil
} }

View file

@ -646,6 +646,13 @@ func TestHTTP_JobAllocations(t *testing.T) {
} }
// Directly manipulate the state // Directly manipulate the state
expectedDisplayMsg := "test message"
testEvent := structs.NewTaskEvent("test event").SetMessage(expectedDisplayMsg)
var events []*structs.TaskEvent
events = append(events, testEvent)
taskState := &structs.TaskState{Events: events}
alloc1.TaskStates = make(map[string]*structs.TaskState)
alloc1.TaskStates["test"] = taskState
state := s.Agent.server.State() state := s.Agent.server.State()
err := state.UpsertAllocs(1000, []*structs.Allocation{alloc1}) err := state.UpsertAllocs(1000, []*structs.Allocation{alloc1})
if err != nil { if err != nil {
@ -670,6 +677,8 @@ func TestHTTP_JobAllocations(t *testing.T) {
if len(allocs) != 1 && allocs[0].ID != alloc1.ID { if len(allocs) != 1 && allocs[0].ID != alloc1.ID {
t.Fatalf("bad: %v", allocs) t.Fatalf("bad: %v", allocs)
} }
displayMsg := allocs[0].TaskStates["test"].Events[0].DisplayMessage
assert.Equal(t, expectedDisplayMsg, displayMsg)
// Check for the index // Check for the index
if respW.HeaderMap.Get("X-Nomad-Index") == "" { if respW.HeaderMap.Get("X-Nomad-Index") == "" {

View file

@ -89,6 +89,9 @@ func (s *HTTPServer) nodeAllocations(resp http.ResponseWriter, req *http.Request
if out.Allocs == nil { if out.Allocs == nil {
out.Allocs = make([]*structs.Allocation, 0) out.Allocs = make([]*structs.Allocation, 0)
} }
for _, alloc := range out.Allocs {
alloc.SetEventDisplayMessages()
}
return out.Allocs, nil return out.Allocs, nil
} }

View file

@ -7,6 +7,7 @@ import (
"github.com/hashicorp/nomad/nomad/mock" "github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs"
"github.com/stretchr/testify/assert"
) )
func TestHTTP_NodesList(t *testing.T) { func TestHTTP_NodesList(t *testing.T) {
@ -187,6 +188,14 @@ func TestHTTP_NodeAllocations(t *testing.T) {
if err := state.UpsertJobSummary(999, mock.JobSummary(alloc1.JobID)); err != nil { if err := state.UpsertJobSummary(999, mock.JobSummary(alloc1.JobID)); err != nil {
t.Fatal(err) t.Fatal(err)
} }
// Create a test event for the allocation
testEvent := structs.NewTaskEvent(structs.TaskStarted)
var events []*structs.TaskEvent
events = append(events, testEvent)
taskState := &structs.TaskState{Events: events}
alloc1.TaskStates = make(map[string]*structs.TaskState)
alloc1.TaskStates["test"] = taskState
err := state.UpsertAllocs(1000, []*structs.Allocation{alloc1}) err := state.UpsertAllocs(1000, []*structs.Allocation{alloc1})
if err != nil { if err != nil {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
@ -221,6 +230,9 @@ func TestHTTP_NodeAllocations(t *testing.T) {
if len(allocs) != 1 || allocs[0].ID != alloc1.ID { if len(allocs) != 1 || allocs[0].ID != alloc1.ID {
t.Fatalf("bad: %#v", allocs) t.Fatalf("bad: %#v", allocs)
} }
expectedDisplayMsg := "Task started by client"
displayMsg := allocs[0].TaskStates["test"].Events[0].DisplayMessage
assert.Equal(t, expectedDisplayMsg, displayMsg)
}) })
} }

View file

@ -4919,6 +4919,12 @@ func (a *Allocation) ShouldMigrate() bool {
return true return true
} }
// SetEventDisplayMessage populates the display message if its not already set
// this is to handle old allocations that don't have it, and this method will be removed in a future release
func (a *Allocation) SetEventDisplayMessages() {
setDisplayMsg(a.TaskStates)
}
// Stub returns a list stub for the allocation // Stub returns a list stub for the allocation
func (a *Allocation) Stub() *AllocListStub { func (a *Allocation) Stub() *AllocListStub {
return &AllocListStub{ return &AllocListStub{
@ -4963,6 +4969,22 @@ type AllocListStub struct {
ModifyTime int64 ModifyTime int64
} }
// SetEventDisplayMessage populates the display message if its not already set
// this is a temporary fix to handle old allocations that don't have display message populated, and this method will be removed in a future release
func (a *AllocListStub) SetEventDisplayMessages() {
setDisplayMsg(a.TaskStates)
}
func setDisplayMsg(taskStates map[string]*TaskState) {
if taskStates != nil {
for _, taskState := range taskStates {
for _, event := range taskState.Events {
event.PopulateEventDisplayMessage()
}
}
}
}
// AllocMetric is used to track various metrics while attempting // AllocMetric is used to track various metrics while attempting
// to make an allocation. These are used to debug a job, or to better // to make an allocation. These are used to debug a job, or to better
// understand the pressure within the system. // understand the pressure within the system.