328 lines
11 KiB
Go
328 lines
11 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package agent
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/hashicorp/nomad/ci"
|
|
"github.com/hashicorp/nomad/nomad/mock"
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestHTTP_DeploymentList(t *testing.T) {
|
|
ci.Parallel(t)
|
|
assert := assert.New(t)
|
|
httpTest(t, nil, func(s *TestAgent) {
|
|
// Directly manipulate the state
|
|
state := s.Agent.server.State()
|
|
d1 := mock.Deployment()
|
|
d2 := mock.Deployment()
|
|
assert.Nil(state.UpsertDeployment(999, d1), "UpsertDeployment")
|
|
assert.Nil(state.UpsertDeployment(1000, d2), "UpsertDeployment")
|
|
|
|
// Make the HTTP request
|
|
req, err := http.NewRequest(http.MethodGet, "/v1/deployments", nil)
|
|
assert.Nil(err, "HTTP Request")
|
|
respW := httptest.NewRecorder()
|
|
|
|
// Make the request
|
|
obj, err := s.Server.DeploymentsRequest(respW, req)
|
|
assert.Nil(err, "Deployment Request")
|
|
|
|
// Check for the index
|
|
assert.NotZero(respW.Result().Header.Get("X-Nomad-Index"), "missing index")
|
|
assert.Equal("true", respW.Result().Header.Get("X-Nomad-KnownLeader"), "missing known leader")
|
|
assert.NotZero(respW.Result().Header.Get("X-Nomad-LastContact"), "missing last contact")
|
|
|
|
// Check the deployments
|
|
deploys := obj.([]*structs.Deployment)
|
|
assert.Len(deploys, 2, "Deployments")
|
|
})
|
|
}
|
|
|
|
func TestHTTP_DeploymentPrefixList(t *testing.T) {
|
|
ci.Parallel(t)
|
|
assert := assert.New(t)
|
|
httpTest(t, nil, func(s *TestAgent) {
|
|
// Directly manipulate the state
|
|
state := s.Agent.server.State()
|
|
d1 := mock.Deployment()
|
|
d1.ID = "aaabbbbb-e8f7-fd38-c855-ab94ceb89706"
|
|
d2 := mock.Deployment()
|
|
d2.ID = "aaabbbbb-e8f7-fd38-c855-ab94ceb89706"
|
|
assert.Nil(state.UpsertDeployment(999, d1), "UpsertDeployment")
|
|
assert.Nil(state.UpsertDeployment(1000, d2), "UpsertDeployment")
|
|
|
|
// Make the HTTP request
|
|
req, err := http.NewRequest(http.MethodGet, "/v1/deployments?prefix=aaab", nil)
|
|
assert.Nil(err, "HTTP Request")
|
|
respW := httptest.NewRecorder()
|
|
|
|
// Make the request
|
|
obj, err := s.Server.DeploymentsRequest(respW, req)
|
|
assert.Nil(err, "Deployment Request")
|
|
|
|
// Check for the index
|
|
assert.NotZero(respW.Result().Header.Get("X-Nomad-Index"), "missing index")
|
|
assert.Equal("true", respW.Result().Header.Get("X-Nomad-KnownLeader"), "missing known leader")
|
|
assert.NotZero(respW.Result().Header.Get("X-Nomad-LastContact"), "missing last contact")
|
|
|
|
// Check the deployments
|
|
deploys := obj.([]*structs.Deployment)
|
|
assert.Len(deploys, 1, "Deployments")
|
|
assert.Equal(d1.ID, deploys[0].ID, "Wrong Deployment")
|
|
})
|
|
}
|
|
|
|
func TestHTTP_DeploymentAllocations(t *testing.T) {
|
|
ci.Parallel(t)
|
|
assert := assert.New(t)
|
|
httpTest(t, nil, func(s *TestAgent) {
|
|
// Directly manipulate the state
|
|
state := s.Agent.server.State()
|
|
j := mock.Job()
|
|
d := mock.Deployment()
|
|
d.JobID = j.ID
|
|
a1 := mock.Alloc()
|
|
a1.JobID = j.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.JobID = j.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(structs.MsgTypeTestSetup, 998, nil, j), "UpsertJob")
|
|
assert.Nil(state.UpsertDeployment(999, d), "UpsertDeployment")
|
|
assert.Nil(state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{a1, a2}), "UpsertAllocs")
|
|
|
|
// Make the HTTP request
|
|
req, err := http.NewRequest(http.MethodGet, "/v1/deployment/allocations/"+d.ID, nil)
|
|
assert.Nil(err, "HTTP Request")
|
|
respW := httptest.NewRecorder()
|
|
|
|
// Make the request
|
|
obj, err := s.Server.DeploymentSpecificRequest(respW, req)
|
|
assert.Nil(err, "DeploymentSpecificRequest")
|
|
|
|
// Check for the index
|
|
assert.NotZero(respW.Result().Header.Get("X-Nomad-Index"), "missing index")
|
|
assert.Equal("true", respW.Result().Header.Get("X-Nomad-KnownLeader"), "missing known leader")
|
|
assert.NotZero(respW.Result().Header.Get("X-Nomad-LastContact"), "missing last contact")
|
|
|
|
// Check the output
|
|
allocs := obj.([]*structs.AllocListStub)
|
|
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")
|
|
})
|
|
}
|
|
|
|
func TestHTTP_DeploymentQuery(t *testing.T) {
|
|
ci.Parallel(t)
|
|
assert := assert.New(t)
|
|
httpTest(t, nil, func(s *TestAgent) {
|
|
// Directly manipulate the state
|
|
state := s.Agent.server.State()
|
|
d := mock.Deployment()
|
|
assert.Nil(state.UpsertDeployment(1000, d), "UpsertDeployment")
|
|
|
|
// Make the HTTP request
|
|
req, err := http.NewRequest(http.MethodGet, "/v1/deployment/"+d.ID, nil)
|
|
assert.Nil(err, "HTTP Request")
|
|
respW := httptest.NewRecorder()
|
|
|
|
// Make the request
|
|
obj, err := s.Server.DeploymentSpecificRequest(respW, req)
|
|
assert.Nil(err, "Deployment Request")
|
|
|
|
// Check for the index
|
|
assert.NotZero(respW.Result().Header.Get("X-Nomad-Index"), "missing index")
|
|
assert.Equal("true", respW.Result().Header.Get("X-Nomad-KnownLeader"), "missing known leader")
|
|
assert.NotZero(respW.Result().Header.Get("X-Nomad-LastContact"), "missing last contact")
|
|
|
|
// Check the job
|
|
out := obj.(*structs.Deployment)
|
|
assert.Equal(d.ID, out.ID, "ID mismatch")
|
|
})
|
|
}
|
|
|
|
func TestHTTP_DeploymentPause(t *testing.T) {
|
|
ci.Parallel(t)
|
|
assert := assert.New(t)
|
|
httpTest(t, nil, func(s *TestAgent) {
|
|
// Directly manipulate the state
|
|
state := s.Agent.server.State()
|
|
j := mock.Job()
|
|
d := mock.Deployment()
|
|
d.JobID = j.ID
|
|
assert.Nil(state.UpsertJob(structs.MsgTypeTestSetup, 999, nil, j), "UpsertJob")
|
|
assert.Nil(state.UpsertDeployment(1000, d), "UpsertDeployment")
|
|
|
|
// Create the pause request
|
|
args := structs.DeploymentPauseRequest{
|
|
DeploymentID: d.ID,
|
|
Pause: false,
|
|
WriteRequest: structs.WriteRequest{
|
|
Region: "global",
|
|
Namespace: structs.DefaultNamespace,
|
|
},
|
|
}
|
|
buf := encodeReq(args)
|
|
|
|
// Make the HTTP request
|
|
req, err := http.NewRequest(http.MethodPut, "/v1/deployment/pause/"+d.ID, buf)
|
|
assert.Nil(err, "HTTP Request")
|
|
respW := httptest.NewRecorder()
|
|
|
|
// Make the request
|
|
obj, err := s.Server.DeploymentSpecificRequest(respW, req)
|
|
assert.Nil(err, "Deployment Request")
|
|
|
|
// Check the response
|
|
resp := obj.(structs.DeploymentUpdateResponse)
|
|
assert.NotZero(resp.EvalID, "Expect Eval")
|
|
assert.NotZero(resp.EvalCreateIndex, "Expect Eval")
|
|
assert.NotZero(resp.DeploymentModifyIndex, "Expect Deployment to be Modified")
|
|
assert.NotZero(respW.Result().Header.Get("X-Nomad-Index"), "missing index")
|
|
})
|
|
}
|
|
|
|
func TestHTTP_DeploymentPromote(t *testing.T) {
|
|
ci.Parallel(t)
|
|
assert := assert.New(t)
|
|
httpTest(t, nil, func(s *TestAgent) {
|
|
// Directly manipulate the state
|
|
state := s.Agent.server.State()
|
|
j := mock.Job()
|
|
d := mock.Deployment()
|
|
d.JobID = j.ID
|
|
assert.Nil(state.UpsertJob(structs.MsgTypeTestSetup, 999, nil, j), "UpsertJob")
|
|
assert.Nil(state.UpsertDeployment(1000, d), "UpsertDeployment")
|
|
|
|
// Create the pause request
|
|
args := structs.DeploymentPromoteRequest{
|
|
DeploymentID: d.ID,
|
|
All: true,
|
|
WriteRequest: structs.WriteRequest{
|
|
Region: "global",
|
|
Namespace: structs.DefaultNamespace,
|
|
},
|
|
}
|
|
buf := encodeReq(args)
|
|
|
|
// Make the HTTP request
|
|
req, err := http.NewRequest(http.MethodPut, "/v1/deployment/pause/"+d.ID, buf)
|
|
assert.Nil(err, "HTTP Request")
|
|
respW := httptest.NewRecorder()
|
|
|
|
// Make the request
|
|
obj, err := s.Server.DeploymentSpecificRequest(respW, req)
|
|
assert.Nil(err, "Deployment Request")
|
|
|
|
// Check the response
|
|
resp := obj.(structs.DeploymentUpdateResponse)
|
|
assert.NotZero(resp.EvalID, "Expect Eval")
|
|
assert.NotZero(resp.EvalCreateIndex, "Expect Eval")
|
|
assert.NotZero(resp.DeploymentModifyIndex, "Expect Deployment to be Modified")
|
|
assert.NotZero(respW.Result().Header.Get("X-Nomad-Index"), "missing index")
|
|
})
|
|
}
|
|
|
|
func TestHTTP_DeploymentAllocHealth(t *testing.T) {
|
|
ci.Parallel(t)
|
|
assert := assert.New(t)
|
|
httpTest(t, nil, func(s *TestAgent) {
|
|
// Directly manipulate the state
|
|
state := s.Agent.server.State()
|
|
j := mock.Job()
|
|
d := mock.Deployment()
|
|
d.JobID = j.ID
|
|
a := mock.Alloc()
|
|
a.JobID = j.ID
|
|
a.DeploymentID = d.ID
|
|
assert.Nil(state.UpsertJob(structs.MsgTypeTestSetup, 998, nil, j), "UpsertJob")
|
|
assert.Nil(state.UpsertDeployment(999, d), "UpsertDeployment")
|
|
assert.Nil(state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{a}), "UpsertAllocs")
|
|
|
|
// Create the pause request
|
|
args := structs.DeploymentAllocHealthRequest{
|
|
DeploymentID: d.ID,
|
|
HealthyAllocationIDs: []string{a.ID},
|
|
WriteRequest: structs.WriteRequest{
|
|
Region: "global",
|
|
Namespace: structs.DefaultNamespace,
|
|
},
|
|
}
|
|
buf := encodeReq(args)
|
|
|
|
// Make the HTTP request
|
|
req, err := http.NewRequest(http.MethodPut, "/v1/deployment/allocation-health/"+d.ID, buf)
|
|
assert.Nil(err, "HTTP Request")
|
|
respW := httptest.NewRecorder()
|
|
|
|
// Make the request
|
|
obj, err := s.Server.DeploymentSpecificRequest(respW, req)
|
|
assert.Nil(err, "Deployment Request")
|
|
|
|
// Check the response
|
|
resp := obj.(structs.DeploymentUpdateResponse)
|
|
assert.NotZero(resp.EvalID, "Expect Eval")
|
|
assert.NotZero(resp.EvalCreateIndex, "Expect Eval")
|
|
assert.NotZero(resp.DeploymentModifyIndex, "Expect Deployment to be Modified")
|
|
assert.NotZero(respW.Result().Header.Get("X-Nomad-Index"), "missing index")
|
|
})
|
|
}
|
|
|
|
func TestHTTP_DeploymentFail(t *testing.T) {
|
|
ci.Parallel(t)
|
|
assert := assert.New(t)
|
|
httpTest(t, nil, func(s *TestAgent) {
|
|
// Directly manipulate the state
|
|
state := s.Agent.server.State()
|
|
j := mock.Job()
|
|
d := mock.Deployment()
|
|
d.JobID = j.ID
|
|
assert.Nil(state.UpsertJob(structs.MsgTypeTestSetup, 998, nil, j), "UpsertJob")
|
|
assert.Nil(state.UpsertDeployment(999, d), "UpsertDeployment")
|
|
|
|
// Make the HTTP request
|
|
req, err := http.NewRequest(http.MethodPut, "/v1/deployment/fail/"+d.ID, nil)
|
|
assert.Nil(err, "HTTP Request")
|
|
respW := httptest.NewRecorder()
|
|
|
|
// Make the request
|
|
obj, err := s.Server.DeploymentSpecificRequest(respW, req)
|
|
assert.Nil(err, "Deployment Request")
|
|
|
|
// Check the response
|
|
resp := obj.(structs.DeploymentUpdateResponse)
|
|
assert.NotZero(resp.EvalID, "Expect Eval")
|
|
assert.NotZero(resp.EvalCreateIndex, "Expect Eval")
|
|
assert.NotZero(resp.DeploymentModifyIndex, "Expect Deployment to be Modified")
|
|
assert.NotZero(respW.Result().Header.Get("X-Nomad-Index"), "missing index")
|
|
})
|
|
}
|