github.com/hspak/nomad@v0.7.2-0.20180309000617-bc4ae22a39a5/command/agent/node_endpoint_test.go (about) 1 package agent 2 3 import ( 4 "net/http" 5 "net/http/httptest" 6 "testing" 7 8 "github.com/hashicorp/nomad/nomad/mock" 9 "github.com/hashicorp/nomad/nomad/structs" 10 "github.com/stretchr/testify/assert" 11 ) 12 13 func TestHTTP_NodesList(t *testing.T) { 14 t.Parallel() 15 httpTest(t, nil, func(s *TestAgent) { 16 for i := 0; i < 3; i++ { 17 // Create the node 18 node := mock.Node() 19 args := structs.NodeRegisterRequest{ 20 Node: node, 21 WriteRequest: structs.WriteRequest{Region: "global"}, 22 } 23 var resp structs.NodeUpdateResponse 24 if err := s.Agent.RPC("Node.Register", &args, &resp); err != nil { 25 t.Fatalf("err: %v", err) 26 } 27 } 28 29 // Make the HTTP request 30 req, err := http.NewRequest("GET", "/v1/nodes", nil) 31 if err != nil { 32 t.Fatalf("err: %v", err) 33 } 34 respW := httptest.NewRecorder() 35 36 // Make the request 37 obj, err := s.Server.NodesRequest(respW, req) 38 if err != nil { 39 t.Fatalf("err: %v", err) 40 } 41 42 // Check for the index 43 if respW.HeaderMap.Get("X-Nomad-Index") == "" { 44 t.Fatalf("missing index") 45 } 46 if respW.HeaderMap.Get("X-Nomad-KnownLeader") != "true" { 47 t.Fatalf("missing known leader") 48 } 49 if respW.HeaderMap.Get("X-Nomad-LastContact") == "" { 50 t.Fatalf("missing last contact") 51 } 52 53 // Check the nodes 54 n := obj.([]*structs.NodeListStub) 55 if len(n) < 3 { // Maybe 4 including client 56 t.Fatalf("bad: %#v", n) 57 } 58 }) 59 } 60 61 func TestHTTP_NodesPrefixList(t *testing.T) { 62 t.Parallel() 63 httpTest(t, nil, func(s *TestAgent) { 64 ids := []string{ 65 "12345678-abcd-efab-cdef-123456789abc", 66 "12345678-aaaa-efab-cdef-123456789abc", 67 "1234aaaa-abcd-efab-cdef-123456789abc", 68 "1234bbbb-abcd-efab-cdef-123456789abc", 69 "1234cccc-abcd-efab-cdef-123456789abc", 70 "1234dddd-abcd-efab-cdef-123456789abc", 71 } 72 for i := 0; i < 5; i++ { 73 // Create the node 74 node := mock.Node() 75 node.ID = ids[i] 76 args := structs.NodeRegisterRequest{ 77 Node: node, 78 WriteRequest: structs.WriteRequest{Region: "global"}, 79 } 80 var resp structs.NodeUpdateResponse 81 if err := s.Agent.RPC("Node.Register", &args, &resp); err != nil { 82 t.Fatalf("err: %v", err) 83 } 84 } 85 86 // Make the HTTP request 87 req, err := http.NewRequest("GET", "/v1/nodes?prefix=12345678", nil) 88 if err != nil { 89 t.Fatalf("err: %v", err) 90 } 91 respW := httptest.NewRecorder() 92 93 // Make the request 94 obj, err := s.Server.NodesRequest(respW, req) 95 if err != nil { 96 t.Fatalf("err: %v", err) 97 } 98 99 // Check for the index 100 if respW.HeaderMap.Get("X-Nomad-Index") == "" { 101 t.Fatalf("missing index") 102 } 103 if respW.HeaderMap.Get("X-Nomad-KnownLeader") != "true" { 104 t.Fatalf("missing known leader") 105 } 106 if respW.HeaderMap.Get("X-Nomad-LastContact") == "" { 107 t.Fatalf("missing last contact") 108 } 109 110 // Check the nodes 111 n := obj.([]*structs.NodeListStub) 112 if len(n) != 2 { 113 t.Fatalf("bad: %#v", n) 114 } 115 }) 116 } 117 118 func TestHTTP_NodeForceEval(t *testing.T) { 119 t.Parallel() 120 httpTest(t, nil, func(s *TestAgent) { 121 // Create the node 122 node := mock.Node() 123 args := structs.NodeRegisterRequest{ 124 Node: node, 125 WriteRequest: structs.WriteRequest{Region: "global"}, 126 } 127 var resp structs.NodeUpdateResponse 128 if err := s.Agent.RPC("Node.Register", &args, &resp); err != nil { 129 t.Fatalf("err: %v", err) 130 } 131 132 // Directly manipulate the state 133 state := s.Agent.server.State() 134 alloc1 := mock.Alloc() 135 alloc1.NodeID = node.ID 136 if err := state.UpsertJobSummary(999, mock.JobSummary(alloc1.JobID)); err != nil { 137 t.Fatal(err) 138 } 139 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc1}) 140 if err != nil { 141 t.Fatalf("err: %v", err) 142 } 143 144 // Make the HTTP request 145 req, err := http.NewRequest("POST", "/v1/node/"+node.ID+"/evaluate", nil) 146 if err != nil { 147 t.Fatalf("err: %v", err) 148 } 149 respW := httptest.NewRecorder() 150 151 // Make the request 152 obj, err := s.Server.NodeSpecificRequest(respW, req) 153 if err != nil { 154 t.Fatalf("err: %v", err) 155 } 156 157 // Check for the index 158 if respW.HeaderMap.Get("X-Nomad-Index") == "" { 159 t.Fatalf("missing index") 160 } 161 162 // Check the response 163 upd := obj.(structs.NodeUpdateResponse) 164 if len(upd.EvalIDs) == 0 { 165 t.Fatalf("bad: %v", upd) 166 } 167 }) 168 } 169 170 func TestHTTP_NodeAllocations(t *testing.T) { 171 t.Parallel() 172 httpTest(t, nil, func(s *TestAgent) { 173 // Create the job 174 node := mock.Node() 175 args := structs.NodeRegisterRequest{ 176 Node: node, 177 WriteRequest: structs.WriteRequest{Region: "global"}, 178 } 179 var resp structs.NodeUpdateResponse 180 if err := s.Agent.RPC("Node.Register", &args, &resp); err != nil { 181 t.Fatalf("err: %v", err) 182 } 183 184 // Directly manipulate the state 185 state := s.Agent.server.State() 186 alloc1 := mock.Alloc() 187 alloc1.NodeID = node.ID 188 if err := state.UpsertJobSummary(999, mock.JobSummary(alloc1.JobID)); err != nil { 189 t.Fatal(err) 190 } 191 // Create a test event for the allocation 192 testEvent := structs.NewTaskEvent(structs.TaskStarted) 193 var events []*structs.TaskEvent 194 events = append(events, testEvent) 195 taskState := &structs.TaskState{Events: events} 196 alloc1.TaskStates = make(map[string]*structs.TaskState) 197 alloc1.TaskStates["test"] = taskState 198 199 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc1}) 200 if err != nil { 201 t.Fatalf("err: %v", err) 202 } 203 204 // Make the HTTP request 205 req, err := http.NewRequest("GET", "/v1/node/"+node.ID+"/allocations", nil) 206 if err != nil { 207 t.Fatalf("err: %v", err) 208 } 209 respW := httptest.NewRecorder() 210 211 // Make the request 212 obj, err := s.Server.NodeSpecificRequest(respW, req) 213 if err != nil { 214 t.Fatalf("err: %v", err) 215 } 216 217 // Check for the index 218 if respW.HeaderMap.Get("X-Nomad-Index") == "" { 219 t.Fatalf("missing index") 220 } 221 if respW.HeaderMap.Get("X-Nomad-KnownLeader") != "true" { 222 t.Fatalf("missing known leader") 223 } 224 if respW.HeaderMap.Get("X-Nomad-LastContact") == "" { 225 t.Fatalf("missing last contact") 226 } 227 228 // Check the node 229 allocs := obj.([]*structs.Allocation) 230 if len(allocs) != 1 || allocs[0].ID != alloc1.ID { 231 t.Fatalf("bad: %#v", allocs) 232 } 233 expectedDisplayMsg := "Task started by client" 234 displayMsg := allocs[0].TaskStates["test"].Events[0].DisplayMessage 235 assert.Equal(t, expectedDisplayMsg, displayMsg) 236 }) 237 } 238 239 func TestHTTP_NodeDrain(t *testing.T) { 240 t.Parallel() 241 httpTest(t, nil, func(s *TestAgent) { 242 // Create the node 243 node := mock.Node() 244 args := structs.NodeRegisterRequest{ 245 Node: node, 246 WriteRequest: structs.WriteRequest{Region: "global"}, 247 } 248 var resp structs.NodeUpdateResponse 249 if err := s.Agent.RPC("Node.Register", &args, &resp); err != nil { 250 t.Fatalf("err: %v", err) 251 } 252 253 // Directly manipulate the state 254 state := s.Agent.server.State() 255 alloc1 := mock.Alloc() 256 alloc1.NodeID = node.ID 257 if err := state.UpsertJobSummary(999, mock.JobSummary(alloc1.JobID)); err != nil { 258 t.Fatal(err) 259 } 260 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc1}) 261 if err != nil { 262 t.Fatalf("err: %v", err) 263 } 264 265 // Make the HTTP request 266 req, err := http.NewRequest("POST", "/v1/node/"+node.ID+"/drain?enable=1", nil) 267 if err != nil { 268 t.Fatalf("err: %v", err) 269 } 270 respW := httptest.NewRecorder() 271 272 // Make the request 273 obj, err := s.Server.NodeSpecificRequest(respW, req) 274 if err != nil { 275 t.Fatalf("err: %v", err) 276 } 277 278 // Check for the index 279 if respW.HeaderMap.Get("X-Nomad-Index") == "" { 280 t.Fatalf("missing index") 281 } 282 283 // Check the response 284 upd := obj.(structs.NodeDrainUpdateResponse) 285 if len(upd.EvalIDs) == 0 { 286 t.Fatalf("bad: %v", upd) 287 } 288 }) 289 } 290 291 func TestHTTP_NodePurge(t *testing.T) { 292 t.Parallel() 293 httpTest(t, nil, func(s *TestAgent) { 294 // Create the node 295 node := mock.Node() 296 args := structs.NodeRegisterRequest{ 297 Node: node, 298 WriteRequest: structs.WriteRequest{Region: "global"}, 299 } 300 var resp structs.NodeUpdateResponse 301 if err := s.Agent.RPC("Node.Register", &args, &resp); err != nil { 302 t.Fatalf("err: %v", err) 303 } 304 305 // Add some allocations to the node 306 state := s.Agent.server.State() 307 alloc1 := mock.Alloc() 308 alloc1.NodeID = node.ID 309 if err := state.UpsertJobSummary(999, mock.JobSummary(alloc1.JobID)); err != nil { 310 t.Fatal(err) 311 } 312 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc1}) 313 if err != nil { 314 t.Fatalf("err: %v", err) 315 } 316 317 // Make the HTTP request to purge it 318 req, err := http.NewRequest("POST", "/v1/node/"+node.ID+"/purge", nil) 319 if err != nil { 320 t.Fatalf("err: %v", err) 321 } 322 respW := httptest.NewRecorder() 323 324 // Make the request 325 obj, err := s.Server.NodeSpecificRequest(respW, req) 326 if err != nil { 327 t.Fatalf("err: %v", err) 328 } 329 330 // Check for the index 331 if respW.HeaderMap.Get("X-Nomad-Index") == "" { 332 t.Fatalf("missing index") 333 } 334 335 // Check the response 336 upd := obj.(structs.NodeUpdateResponse) 337 if len(upd.EvalIDs) == 0 { 338 t.Fatalf("bad: %v", upd) 339 } 340 341 // Ensure that the node is not present anymore 342 args1 := structs.NodeSpecificRequest{ 343 NodeID: node.ID, 344 QueryOptions: structs.QueryOptions{Region: "global"}, 345 } 346 var resp1 structs.SingleNodeResponse 347 if err := s.Agent.RPC("Node.GetNode", &args1, &resp1); err != nil { 348 t.Fatalf("err: %v", err) 349 } 350 if resp1.Node != nil { 351 t.Fatalf("node still exists after purging: %#v", resp1.Node) 352 } 353 }) 354 } 355 356 func TestHTTP_NodeQuery(t *testing.T) { 357 t.Parallel() 358 httpTest(t, nil, func(s *TestAgent) { 359 // Create the job 360 node := mock.Node() 361 args := structs.NodeRegisterRequest{ 362 Node: node, 363 WriteRequest: structs.WriteRequest{Region: "global"}, 364 } 365 var resp structs.NodeUpdateResponse 366 if err := s.Agent.RPC("Node.Register", &args, &resp); err != nil { 367 t.Fatalf("err: %v", err) 368 } 369 370 // Make the HTTP request 371 req, err := http.NewRequest("GET", "/v1/node/"+node.ID, nil) 372 if err != nil { 373 t.Fatalf("err: %v", err) 374 } 375 respW := httptest.NewRecorder() 376 377 // Make the request 378 obj, err := s.Server.NodeSpecificRequest(respW, req) 379 if err != nil { 380 t.Fatalf("err: %v", err) 381 } 382 383 // Check for the index 384 if respW.HeaderMap.Get("X-Nomad-Index") == "" { 385 t.Fatalf("missing index") 386 } 387 if respW.HeaderMap.Get("X-Nomad-KnownLeader") != "true" { 388 t.Fatalf("missing known leader") 389 } 390 if respW.HeaderMap.Get("X-Nomad-LastContact") == "" { 391 t.Fatalf("missing last contact") 392 } 393 394 // Check the node 395 n := obj.(*structs.Node) 396 if n.ID != node.ID { 397 t.Fatalf("bad: %#v", n) 398 } 399 }) 400 }