open-nomad/command/agent/deployment_endpoint_test.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")
})
}