github.com/Iqoqo/consul@v1.4.5/agent/operator_endpoint_test.go (about) 1 package agent 2 3 import ( 4 "bytes" 5 "fmt" 6 "net/http" 7 "net/http/httptest" 8 "strings" 9 "testing" 10 11 "github.com/hashicorp/consul/testrpc" 12 13 "github.com/hashicorp/consul/agent/consul/autopilot" 14 "github.com/hashicorp/consul/agent/structs" 15 "github.com/hashicorp/consul/api" 16 "github.com/hashicorp/consul/testutil/retry" 17 ) 18 19 func TestOperator_RaftConfiguration(t *testing.T) { 20 t.Parallel() 21 a := NewTestAgent(t, t.Name(), "") 22 defer a.Shutdown() 23 24 body := bytes.NewBuffer(nil) 25 req, _ := http.NewRequest("GET", "/v1/operator/raft/configuration", body) 26 resp := httptest.NewRecorder() 27 obj, err := a.srv.OperatorRaftConfiguration(resp, req) 28 if err != nil { 29 t.Fatalf("err: %v", err) 30 } 31 if resp.Code != 200 { 32 t.Fatalf("bad code: %d", resp.Code) 33 } 34 out, ok := obj.(structs.RaftConfigurationResponse) 35 if !ok { 36 t.Fatalf("unexpected: %T", obj) 37 } 38 if len(out.Servers) != 1 || 39 !out.Servers[0].Leader || 40 !out.Servers[0].Voter { 41 t.Fatalf("bad: %v", out) 42 } 43 } 44 45 func TestOperator_RaftPeer(t *testing.T) { 46 t.Parallel() 47 t.Run("", func(t *testing.T) { 48 a := NewTestAgent(t, t.Name(), "") 49 defer a.Shutdown() 50 51 body := bytes.NewBuffer(nil) 52 req, _ := http.NewRequest("DELETE", "/v1/operator/raft/peer?address=nope", body) 53 // If we get this error, it proves we sent the address all the 54 // way through. 55 resp := httptest.NewRecorder() 56 _, err := a.srv.OperatorRaftPeer(resp, req) 57 if err == nil || !strings.Contains(err.Error(), 58 "address \"nope\" was not found in the Raft configuration") { 59 t.Fatalf("err: %v", err) 60 } 61 }) 62 63 t.Run("", func(t *testing.T) { 64 a := NewTestAgent(t, t.Name(), "") 65 defer a.Shutdown() 66 67 body := bytes.NewBuffer(nil) 68 req, _ := http.NewRequest("DELETE", "/v1/operator/raft/peer?id=nope", body) 69 // If we get this error, it proves we sent the ID all the 70 // way through. 71 resp := httptest.NewRecorder() 72 _, err := a.srv.OperatorRaftPeer(resp, req) 73 if err == nil || !strings.Contains(err.Error(), 74 "id \"nope\" was not found in the Raft configuration") { 75 t.Fatalf("err: %v", err) 76 } 77 }) 78 } 79 80 func TestOperator_KeyringInstall(t *testing.T) { 81 t.Parallel() 82 oldKey := "H3/9gBxcKKRf45CaI2DlRg==" 83 newKey := "z90lFx3sZZLtTOkutXcwYg==" 84 a := NewTestAgent(t, t.Name(), ` 85 encrypt = "`+oldKey+`" 86 `) 87 defer a.Shutdown() 88 89 body := bytes.NewBufferString(fmt.Sprintf("{\"Key\":\"%s\"}", newKey)) 90 req, _ := http.NewRequest("POST", "/v1/operator/keyring", body) 91 resp := httptest.NewRecorder() 92 _, err := a.srv.OperatorKeyringEndpoint(resp, req) 93 if err != nil { 94 t.Fatalf("err: %s", err) 95 } 96 97 listResponse, err := a.ListKeys("", 0) 98 if err != nil { 99 t.Fatalf("err: %s", err) 100 } 101 if len(listResponse.Responses) != 2 { 102 t.Fatalf("bad: %d", len(listResponse.Responses)) 103 } 104 105 for _, response := range listResponse.Responses { 106 count, ok := response.Keys[newKey] 107 if !ok { 108 t.Fatalf("bad: %v", response.Keys) 109 } 110 if count != response.NumNodes { 111 t.Fatalf("bad: %d, %d", count, response.NumNodes) 112 } 113 } 114 } 115 116 func TestOperator_KeyringList(t *testing.T) { 117 t.Parallel() 118 key := "H3/9gBxcKKRf45CaI2DlRg==" 119 a := NewTestAgent(t, t.Name(), ` 120 encrypt = "`+key+`" 121 `) 122 defer a.Shutdown() 123 124 req, _ := http.NewRequest("GET", "/v1/operator/keyring", nil) 125 resp := httptest.NewRecorder() 126 r, err := a.srv.OperatorKeyringEndpoint(resp, req) 127 if err != nil { 128 t.Fatalf("err: %v", err) 129 } 130 responses, ok := r.([]*structs.KeyringResponse) 131 if !ok { 132 t.Fatalf("err: %v", !ok) 133 } 134 135 // Check that we get both a LAN and WAN response, and that they both only 136 // contain the original key 137 if len(responses) != 2 { 138 t.Fatalf("bad: %d", len(responses)) 139 } 140 141 // WAN 142 if len(responses[0].Keys) != 1 { 143 t.Fatalf("bad: %d", len(responses[0].Keys)) 144 } 145 if !responses[0].WAN { 146 t.Fatalf("bad: %v", responses[0].WAN) 147 } 148 if _, ok := responses[0].Keys[key]; !ok { 149 t.Fatalf("bad: %v", ok) 150 } 151 152 // LAN 153 if len(responses[1].Keys) != 1 { 154 t.Fatalf("bad: %d", len(responses[1].Keys)) 155 } 156 if responses[1].WAN { 157 t.Fatalf("bad: %v", responses[1].WAN) 158 } 159 if _, ok := responses[1].Keys[key]; !ok { 160 t.Fatalf("bad: %v", ok) 161 } 162 } 163 164 func TestOperator_KeyringRemove(t *testing.T) { 165 t.Parallel() 166 key := "H3/9gBxcKKRf45CaI2DlRg==" 167 tempKey := "z90lFx3sZZLtTOkutXcwYg==" 168 a := NewTestAgent(t, t.Name(), ` 169 encrypt = "`+key+`" 170 `) 171 defer a.Shutdown() 172 173 _, err := a.InstallKey(tempKey, "", 0) 174 if err != nil { 175 t.Fatalf("err: %v", err) 176 } 177 178 // Make sure the temp key is installed 179 list, err := a.ListKeys("", 0) 180 if err != nil { 181 t.Fatalf("err: %v", err) 182 } 183 responses := list.Responses 184 if len(responses) != 2 { 185 t.Fatalf("bad: %d", len(responses)) 186 } 187 for _, response := range responses { 188 if len(response.Keys) != 2 { 189 t.Fatalf("bad: %d", len(response.Keys)) 190 } 191 if _, ok := response.Keys[tempKey]; !ok { 192 t.Fatalf("bad: %v", ok) 193 } 194 } 195 196 body := bytes.NewBufferString(fmt.Sprintf("{\"Key\":\"%s\"}", tempKey)) 197 req, _ := http.NewRequest("DELETE", "/v1/operator/keyring", body) 198 resp := httptest.NewRecorder() 199 if _, err := a.srv.OperatorKeyringEndpoint(resp, req); err != nil { 200 t.Fatalf("err: %s", err) 201 } 202 203 // Make sure the temp key has been removed 204 list, err = a.ListKeys("", 0) 205 if err != nil { 206 t.Fatalf("err: %v", err) 207 } 208 responses = list.Responses 209 if len(responses) != 2 { 210 t.Fatalf("bad: %d", len(responses)) 211 } 212 for _, response := range responses { 213 if len(response.Keys) != 1 { 214 t.Fatalf("bad: %d", len(response.Keys)) 215 } 216 if _, ok := response.Keys[tempKey]; ok { 217 t.Fatalf("bad: %v", ok) 218 } 219 } 220 } 221 222 func TestOperator_KeyringUse(t *testing.T) { 223 t.Parallel() 224 oldKey := "H3/9gBxcKKRf45CaI2DlRg==" 225 newKey := "z90lFx3sZZLtTOkutXcwYg==" 226 a := NewTestAgent(t, t.Name(), ` 227 encrypt = "`+oldKey+`" 228 `) 229 defer a.Shutdown() 230 231 if _, err := a.InstallKey(newKey, "", 0); err != nil { 232 t.Fatalf("err: %v", err) 233 } 234 235 body := bytes.NewBufferString(fmt.Sprintf("{\"Key\":\"%s\"}", newKey)) 236 req, _ := http.NewRequest("PUT", "/v1/operator/keyring", body) 237 resp := httptest.NewRecorder() 238 _, err := a.srv.OperatorKeyringEndpoint(resp, req) 239 if err != nil { 240 t.Fatalf("err: %s", err) 241 } 242 243 if _, err := a.RemoveKey(oldKey, "", 0); err != nil { 244 t.Fatalf("err: %v", err) 245 } 246 247 // Make sure only the new key remains 248 list, err := a.ListKeys("", 0) 249 if err != nil { 250 t.Fatalf("err: %v", err) 251 } 252 responses := list.Responses 253 if len(responses) != 2 { 254 t.Fatalf("bad: %d", len(responses)) 255 } 256 for _, response := range responses { 257 if len(response.Keys) != 1 { 258 t.Fatalf("bad: %d", len(response.Keys)) 259 } 260 if _, ok := response.Keys[newKey]; !ok { 261 t.Fatalf("bad: %v", ok) 262 } 263 } 264 } 265 266 func TestOperator_Keyring_InvalidRelayFactor(t *testing.T) { 267 t.Parallel() 268 key := "H3/9gBxcKKRf45CaI2DlRg==" 269 a := NewTestAgent(t, t.Name(), ` 270 encrypt = "`+key+`" 271 `) 272 defer a.Shutdown() 273 274 cases := map[string]string{ 275 "999": "Relay factor must be in range", 276 "asdf": "Error parsing relay factor", 277 } 278 for relayFactor, errString := range cases { 279 req, _ := http.NewRequest("GET", "/v1/operator/keyring?relay-factor="+relayFactor, nil) 280 resp := httptest.NewRecorder() 281 _, err := a.srv.OperatorKeyringEndpoint(resp, req) 282 if err != nil { 283 t.Fatalf("err: %v", err) 284 } 285 body := resp.Body.String() 286 if !strings.Contains(body, errString) { 287 t.Fatalf("bad: %v", body) 288 } 289 } 290 } 291 292 func TestOperator_AutopilotGetConfiguration(t *testing.T) { 293 t.Parallel() 294 a := NewTestAgent(t, t.Name(), "") 295 defer a.Shutdown() 296 testrpc.WaitForTestAgent(t, a.RPC, "dc1") 297 298 body := bytes.NewBuffer(nil) 299 req, _ := http.NewRequest("GET", "/v1/operator/autopilot/configuration", body) 300 resp := httptest.NewRecorder() 301 obj, err := a.srv.OperatorAutopilotConfiguration(resp, req) 302 if err != nil { 303 t.Fatalf("err: %v", err) 304 } 305 if resp.Code != 200 { 306 t.Fatalf("bad code: %d", resp.Code) 307 } 308 out, ok := obj.(api.AutopilotConfiguration) 309 if !ok { 310 t.Fatalf("unexpected: %T", obj) 311 } 312 if !out.CleanupDeadServers { 313 t.Fatalf("bad: %#v", out) 314 } 315 } 316 317 func TestOperator_AutopilotSetConfiguration(t *testing.T) { 318 t.Parallel() 319 a := NewTestAgent(t, t.Name(), "") 320 defer a.Shutdown() 321 322 body := bytes.NewBuffer([]byte(`{"CleanupDeadServers": false}`)) 323 req, _ := http.NewRequest("PUT", "/v1/operator/autopilot/configuration", body) 324 resp := httptest.NewRecorder() 325 if _, err := a.srv.OperatorAutopilotConfiguration(resp, req); err != nil { 326 t.Fatalf("err: %v", err) 327 } 328 if resp.Code != 200 { 329 t.Fatalf("bad code: %d", resp.Code) 330 } 331 332 args := structs.DCSpecificRequest{ 333 Datacenter: "dc1", 334 } 335 336 var reply autopilot.Config 337 if err := a.RPC("Operator.AutopilotGetConfiguration", &args, &reply); err != nil { 338 t.Fatalf("err: %v", err) 339 } 340 if reply.CleanupDeadServers { 341 t.Fatalf("bad: %#v", reply) 342 } 343 } 344 345 func TestOperator_AutopilotCASConfiguration(t *testing.T) { 346 t.Parallel() 347 a := NewTestAgent(t, t.Name(), "") 348 defer a.Shutdown() 349 350 body := bytes.NewBuffer([]byte(`{"CleanupDeadServers": false}`)) 351 req, _ := http.NewRequest("PUT", "/v1/operator/autopilot/configuration", body) 352 resp := httptest.NewRecorder() 353 if _, err := a.srv.OperatorAutopilotConfiguration(resp, req); err != nil { 354 t.Fatalf("err: %v", err) 355 } 356 if resp.Code != 200 { 357 t.Fatalf("bad code: %d", resp.Code) 358 } 359 360 args := structs.DCSpecificRequest{ 361 Datacenter: "dc1", 362 } 363 364 var reply autopilot.Config 365 if err := a.RPC("Operator.AutopilotGetConfiguration", &args, &reply); err != nil { 366 t.Fatalf("err: %v", err) 367 } 368 369 if reply.CleanupDeadServers { 370 t.Fatalf("bad: %#v", reply) 371 } 372 373 // Create a CAS request, bad index 374 { 375 buf := bytes.NewBuffer([]byte(`{"CleanupDeadServers": true}`)) 376 req, _ := http.NewRequest("PUT", fmt.Sprintf("/v1/operator/autopilot/configuration?cas=%d", reply.ModifyIndex-1), buf) 377 resp := httptest.NewRecorder() 378 obj, err := a.srv.OperatorAutopilotConfiguration(resp, req) 379 if err != nil { 380 t.Fatalf("err: %v", err) 381 } 382 383 if res := obj.(bool); res { 384 t.Fatalf("should NOT work") 385 } 386 } 387 388 // Create a CAS request, good index 389 { 390 buf := bytes.NewBuffer([]byte(`{"CleanupDeadServers": true}`)) 391 req, _ := http.NewRequest("PUT", fmt.Sprintf("/v1/operator/autopilot/configuration?cas=%d", reply.ModifyIndex), buf) 392 resp := httptest.NewRecorder() 393 obj, err := a.srv.OperatorAutopilotConfiguration(resp, req) 394 if err != nil { 395 t.Fatalf("err: %v", err) 396 } 397 398 if res := obj.(bool); !res { 399 t.Fatalf("should work") 400 } 401 } 402 403 // Verify the update 404 if err := a.RPC("Operator.AutopilotGetConfiguration", &args, &reply); err != nil { 405 t.Fatalf("err: %v", err) 406 } 407 if !reply.CleanupDeadServers { 408 t.Fatalf("bad: %#v", reply) 409 } 410 } 411 412 func TestOperator_ServerHealth(t *testing.T) { 413 t.Parallel() 414 a := NewTestAgent(t, t.Name(), ` 415 raft_protocol = 3 416 `) 417 defer a.Shutdown() 418 419 body := bytes.NewBuffer(nil) 420 req, _ := http.NewRequest("GET", "/v1/operator/autopilot/health", body) 421 retry.Run(t, func(r *retry.R) { 422 resp := httptest.NewRecorder() 423 obj, err := a.srv.OperatorServerHealth(resp, req) 424 if err != nil { 425 r.Fatalf("err: %v", err) 426 } 427 if resp.Code != 200 { 428 r.Fatalf("bad code: %d", resp.Code) 429 } 430 out, ok := obj.(*api.OperatorHealthReply) 431 if !ok { 432 r.Fatalf("unexpected: %T", obj) 433 } 434 if len(out.Servers) != 1 || 435 !out.Servers[0].Healthy || 436 out.Servers[0].Name != a.Config.NodeName || 437 out.Servers[0].SerfStatus != "alive" || 438 out.FailureTolerance != 0 { 439 r.Fatalf("bad: %v", out) 440 } 441 }) 442 } 443 444 func TestOperator_ServerHealth_Unhealthy(t *testing.T) { 445 t.Parallel() 446 a := NewTestAgent(t, t.Name(), ` 447 raft_protocol = 3 448 autopilot { 449 last_contact_threshold = "-1s" 450 } 451 `) 452 defer a.Shutdown() 453 454 body := bytes.NewBuffer(nil) 455 req, _ := http.NewRequest("GET", "/v1/operator/autopilot/health", body) 456 retry.Run(t, func(r *retry.R) { 457 resp := httptest.NewRecorder() 458 obj, err := a.srv.OperatorServerHealth(resp, req) 459 if err != nil { 460 r.Fatalf("err: %v", err) 461 } 462 if resp.Code != 429 { 463 r.Fatalf("bad code: %d", resp.Code) 464 } 465 out, ok := obj.(*api.OperatorHealthReply) 466 if !ok { 467 r.Fatalf("unexpected: %T", obj) 468 } 469 if len(out.Servers) != 1 || 470 out.Healthy || 471 out.Servers[0].Name != a.Config.NodeName { 472 r.Fatalf("bad: %#v", out.Servers) 473 } 474 }) 475 }