github.com/kjdelisle/consul@v1.4.5/agent/kvs_endpoint_test.go (about) 1 package agent 2 3 import ( 4 "bytes" 5 "fmt" 6 "net/http" 7 "net/http/httptest" 8 "reflect" 9 "testing" 10 11 "github.com/hashicorp/consul/testrpc" 12 13 "github.com/hashicorp/consul/agent/structs" 14 ) 15 16 func TestKVSEndpoint_PUT_GET_DELETE(t *testing.T) { 17 t.Parallel() 18 a := NewTestAgent(t, t.Name(), "") 19 defer a.Shutdown() 20 21 keys := []string{ 22 "baz", 23 "bar", 24 "foo/sub1", 25 "foo/sub2", 26 "zip", 27 } 28 29 for _, key := range keys { 30 buf := bytes.NewBuffer([]byte("test")) 31 req, _ := http.NewRequest("PUT", "/v1/kv/"+key, buf) 32 resp := httptest.NewRecorder() 33 obj, err := a.srv.KVSEndpoint(resp, req) 34 if err != nil { 35 t.Fatalf("err: %v", err) 36 } 37 38 if res := obj.(bool); !res { 39 t.Fatalf("should work") 40 } 41 } 42 43 for _, key := range keys { 44 req, _ := http.NewRequest("GET", "/v1/kv/"+key, nil) 45 resp := httptest.NewRecorder() 46 obj, err := a.srv.KVSEndpoint(resp, req) 47 if err != nil { 48 t.Fatalf("err: %v", err) 49 } 50 assertIndex(t, resp) 51 52 res, ok := obj.(structs.DirEntries) 53 if !ok { 54 t.Fatalf("should work") 55 } 56 57 if len(res) != 1 { 58 t.Fatalf("bad: %v", res) 59 } 60 61 if res[0].Key != key { 62 t.Fatalf("bad: %v", res) 63 } 64 } 65 66 for _, key := range keys { 67 req, _ := http.NewRequest("DELETE", "/v1/kv/"+key, nil) 68 resp := httptest.NewRecorder() 69 if _, err := a.srv.KVSEndpoint(resp, req); err != nil { 70 t.Fatalf("err: %v", err) 71 } 72 } 73 } 74 75 func TestKVSEndpoint_Recurse(t *testing.T) { 76 t.Parallel() 77 a := NewTestAgent(t, t.Name(), "") 78 defer a.Shutdown() 79 80 keys := []string{ 81 "bar", 82 "baz", 83 "foo/sub1", 84 "foo/sub2", 85 "zip", 86 } 87 88 for _, key := range keys { 89 buf := bytes.NewBuffer([]byte("test")) 90 req, _ := http.NewRequest("PUT", "/v1/kv/"+key, buf) 91 resp := httptest.NewRecorder() 92 obj, err := a.srv.KVSEndpoint(resp, req) 93 if err != nil { 94 t.Fatalf("err: %v", err) 95 } 96 97 if res := obj.(bool); !res { 98 t.Fatalf("should work") 99 } 100 } 101 102 { 103 // Get all the keys 104 req, _ := http.NewRequest("GET", "/v1/kv/?recurse", nil) 105 resp := httptest.NewRecorder() 106 obj, err := a.srv.KVSEndpoint(resp, req) 107 if err != nil { 108 t.Fatalf("err: %v", err) 109 } 110 assertIndex(t, resp) 111 112 res, ok := obj.(structs.DirEntries) 113 if !ok { 114 t.Fatalf("should work") 115 } 116 117 if len(res) != len(keys) { 118 t.Fatalf("bad: %v", res) 119 } 120 121 for idx, key := range keys { 122 if res[idx].Key != key { 123 t.Fatalf("bad: %v %v", res[idx].Key, key) 124 } 125 } 126 } 127 128 { 129 req, _ := http.NewRequest("DELETE", "/v1/kv/?recurse", nil) 130 resp := httptest.NewRecorder() 131 if _, err := a.srv.KVSEndpoint(resp, req); err != nil { 132 t.Fatalf("err: %v", err) 133 } 134 } 135 136 { 137 // Get all the keys 138 req, _ := http.NewRequest("GET", "/v1/kv/?recurse", nil) 139 resp := httptest.NewRecorder() 140 obj, err := a.srv.KVSEndpoint(resp, req) 141 if err != nil { 142 t.Fatalf("err: %v", err) 143 } 144 145 if obj != nil { 146 t.Fatalf("bad: %v", obj) 147 } 148 } 149 } 150 151 func TestKVSEndpoint_DELETE_CAS(t *testing.T) { 152 t.Parallel() 153 a := NewTestAgent(t, t.Name(), "") 154 defer a.Shutdown() 155 156 { 157 buf := bytes.NewBuffer([]byte("test")) 158 req, _ := http.NewRequest("PUT", "/v1/kv/test", buf) 159 resp := httptest.NewRecorder() 160 obj, err := a.srv.KVSEndpoint(resp, req) 161 if err != nil { 162 t.Fatalf("err: %v", err) 163 } 164 165 if res := obj.(bool); !res { 166 t.Fatalf("should work") 167 } 168 } 169 170 req, _ := http.NewRequest("GET", "/v1/kv/test", nil) 171 resp := httptest.NewRecorder() 172 obj, err := a.srv.KVSEndpoint(resp, req) 173 if err != nil { 174 t.Fatalf("err: %v", err) 175 } 176 d := obj.(structs.DirEntries)[0] 177 178 // Create a CAS request, bad index 179 { 180 buf := bytes.NewBuffer([]byte("zip")) 181 req, _ := http.NewRequest("DELETE", fmt.Sprintf("/v1/kv/test?cas=%d", d.ModifyIndex-1), buf) 182 resp := httptest.NewRecorder() 183 obj, err := a.srv.KVSEndpoint(resp, req) 184 if err != nil { 185 t.Fatalf("err: %v", err) 186 } 187 188 if res := obj.(bool); res { 189 t.Fatalf("should NOT work") 190 } 191 } 192 193 // Create a CAS request, good index 194 { 195 buf := bytes.NewBuffer([]byte("zip")) 196 req, _ := http.NewRequest("DELETE", fmt.Sprintf("/v1/kv/test?cas=%d", d.ModifyIndex), buf) 197 resp := httptest.NewRecorder() 198 obj, err := a.srv.KVSEndpoint(resp, req) 199 if err != nil { 200 t.Fatalf("err: %v", err) 201 } 202 203 if res := obj.(bool); !res { 204 t.Fatalf("should work") 205 } 206 } 207 208 // Verify the delete 209 req, _ = http.NewRequest("GET", "/v1/kv/test", nil) 210 resp = httptest.NewRecorder() 211 obj, _ = a.srv.KVSEndpoint(resp, req) 212 if obj != nil { 213 t.Fatalf("should be destroyed") 214 } 215 } 216 217 func TestKVSEndpoint_CAS(t *testing.T) { 218 t.Parallel() 219 a := NewTestAgent(t, t.Name(), "") 220 defer a.Shutdown() 221 222 { 223 buf := bytes.NewBuffer([]byte("test")) 224 req, _ := http.NewRequest("PUT", "/v1/kv/test?flags=50", buf) 225 resp := httptest.NewRecorder() 226 obj, err := a.srv.KVSEndpoint(resp, req) 227 if err != nil { 228 t.Fatalf("err: %v", err) 229 } 230 231 if res := obj.(bool); !res { 232 t.Fatalf("should work") 233 } 234 } 235 236 req, _ := http.NewRequest("GET", "/v1/kv/test", nil) 237 resp := httptest.NewRecorder() 238 obj, err := a.srv.KVSEndpoint(resp, req) 239 if err != nil { 240 t.Fatalf("err: %v", err) 241 } 242 d := obj.(structs.DirEntries)[0] 243 244 // Check the flags 245 if d.Flags != 50 { 246 t.Fatalf("bad: %v", d) 247 } 248 249 // Create a CAS request, bad index 250 { 251 buf := bytes.NewBuffer([]byte("zip")) 252 req, _ := http.NewRequest("PUT", fmt.Sprintf("/v1/kv/test?flags=42&cas=%d", d.ModifyIndex-1), buf) 253 resp := httptest.NewRecorder() 254 obj, err := a.srv.KVSEndpoint(resp, req) 255 if err != nil { 256 t.Fatalf("err: %v", err) 257 } 258 259 if res := obj.(bool); res { 260 t.Fatalf("should NOT work") 261 } 262 } 263 264 // Create a CAS request, good index 265 { 266 buf := bytes.NewBuffer([]byte("zip")) 267 req, _ := http.NewRequest("PUT", fmt.Sprintf("/v1/kv/test?flags=42&cas=%d", d.ModifyIndex), buf) 268 resp := httptest.NewRecorder() 269 obj, err := a.srv.KVSEndpoint(resp, req) 270 if err != nil { 271 t.Fatalf("err: %v", err) 272 } 273 274 if res := obj.(bool); !res { 275 t.Fatalf("should work") 276 } 277 } 278 279 // Verify the update 280 req, _ = http.NewRequest("GET", "/v1/kv/test", nil) 281 resp = httptest.NewRecorder() 282 obj, _ = a.srv.KVSEndpoint(resp, req) 283 d = obj.(structs.DirEntries)[0] 284 285 if d.Flags != 42 { 286 t.Fatalf("bad: %v", d) 287 } 288 if string(d.Value) != "zip" { 289 t.Fatalf("bad: %v", d) 290 } 291 } 292 293 func TestKVSEndpoint_ListKeys(t *testing.T) { 294 t.Parallel() 295 a := NewTestAgent(t, t.Name(), "") 296 defer a.Shutdown() 297 298 keys := []string{ 299 "bar", 300 "baz", 301 "foo/sub1", 302 "foo/sub2", 303 "zip", 304 } 305 306 for _, key := range keys { 307 buf := bytes.NewBuffer([]byte("test")) 308 req, _ := http.NewRequest("PUT", "/v1/kv/"+key, buf) 309 resp := httptest.NewRecorder() 310 obj, err := a.srv.KVSEndpoint(resp, req) 311 if err != nil { 312 t.Fatalf("err: %v", err) 313 } 314 315 if res := obj.(bool); !res { 316 t.Fatalf("should work") 317 } 318 } 319 320 { 321 // Get all the keys 322 req, _ := http.NewRequest("GET", "/v1/kv/?keys&seperator=/", nil) 323 resp := httptest.NewRecorder() 324 obj, err := a.srv.KVSEndpoint(resp, req) 325 if err != nil { 326 t.Fatalf("err: %v", err) 327 } 328 assertIndex(t, resp) 329 330 res, ok := obj.([]string) 331 if !ok { 332 t.Fatalf("should work") 333 } 334 335 expect := []string{"bar", "baz", "foo/", "zip"} 336 if !reflect.DeepEqual(res, expect) { 337 t.Fatalf("bad: %v", res) 338 } 339 } 340 } 341 342 func TestKVSEndpoint_AcquireRelease(t *testing.T) { 343 t.Parallel() 344 a := NewTestAgent(t, t.Name(), "") 345 defer a.Shutdown() 346 347 testrpc.WaitForTestAgent(t, a.RPC, "dc1") 348 349 // Acquire the lock 350 id := makeTestSession(t, a.srv) 351 req, _ := http.NewRequest("PUT", "/v1/kv/test?acquire="+id, bytes.NewReader(nil)) 352 resp := httptest.NewRecorder() 353 obj, err := a.srv.KVSEndpoint(resp, req) 354 if err != nil { 355 t.Fatalf("err: %v", err) 356 } 357 if res := obj.(bool); !res { 358 t.Fatalf("should work") 359 } 360 361 // Verify we have the lock 362 req, _ = http.NewRequest("GET", "/v1/kv/test", nil) 363 resp = httptest.NewRecorder() 364 obj, err = a.srv.KVSEndpoint(resp, req) 365 if err != nil { 366 t.Fatalf("err: %v", err) 367 } 368 d := obj.(structs.DirEntries)[0] 369 370 // Check the flags 371 if d.Session != id { 372 t.Fatalf("bad: %v", d) 373 } 374 375 // Release the lock 376 req, _ = http.NewRequest("PUT", "/v1/kv/test?release="+id, bytes.NewReader(nil)) 377 resp = httptest.NewRecorder() 378 obj, err = a.srv.KVSEndpoint(resp, req) 379 if err != nil { 380 t.Fatalf("err: %v", err) 381 } 382 if res := obj.(bool); !res { 383 t.Fatalf("should work") 384 } 385 386 // Verify we do not have the lock 387 req, _ = http.NewRequest("GET", "/v1/kv/test", nil) 388 resp = httptest.NewRecorder() 389 obj, err = a.srv.KVSEndpoint(resp, req) 390 if err != nil { 391 t.Fatalf("err: %v", err) 392 } 393 d = obj.(structs.DirEntries)[0] 394 395 // Check the flags 396 if d.Session != "" { 397 t.Fatalf("bad: %v", d) 398 } 399 } 400 401 func TestKVSEndpoint_GET_Raw(t *testing.T) { 402 t.Parallel() 403 a := NewTestAgent(t, t.Name(), "") 404 defer a.Shutdown() 405 406 buf := bytes.NewBuffer([]byte("test")) 407 req, _ := http.NewRequest("PUT", "/v1/kv/test", buf) 408 resp := httptest.NewRecorder() 409 obj, err := a.srv.KVSEndpoint(resp, req) 410 if err != nil { 411 t.Fatalf("err: %v", err) 412 } 413 if res := obj.(bool); !res { 414 t.Fatalf("should work") 415 } 416 417 req, _ = http.NewRequest("GET", "/v1/kv/test?raw", nil) 418 resp = httptest.NewRecorder() 419 obj, err = a.srv.KVSEndpoint(resp, req) 420 if err != nil { 421 t.Fatalf("err: %v", err) 422 } 423 assertIndex(t, resp) 424 425 // Check the body 426 if !bytes.Equal(resp.Body.Bytes(), []byte("test")) { 427 t.Fatalf("bad: %s", resp.Body.Bytes()) 428 } 429 } 430 431 func TestKVSEndpoint_PUT_ConflictingFlags(t *testing.T) { 432 t.Parallel() 433 a := NewTestAgent(t, t.Name(), "") 434 defer a.Shutdown() 435 436 req, _ := http.NewRequest("PUT", "/v1/kv/test?cas=0&acquire=xxx", nil) 437 resp := httptest.NewRecorder() 438 if _, err := a.srv.KVSEndpoint(resp, req); err != nil { 439 t.Fatalf("err: %v", err) 440 } 441 442 if resp.Code != 400 { 443 t.Fatalf("expected 400, got %d", resp.Code) 444 } 445 if !bytes.Contains(resp.Body.Bytes(), []byte("Conflicting")) { 446 t.Fatalf("expected conflicting args error") 447 } 448 } 449 450 func TestKVSEndpoint_DELETE_ConflictingFlags(t *testing.T) { 451 t.Parallel() 452 a := NewTestAgent(t, t.Name(), "") 453 defer a.Shutdown() 454 455 req, _ := http.NewRequest("DELETE", "/v1/kv/test?recurse&cas=0", nil) 456 resp := httptest.NewRecorder() 457 if _, err := a.srv.KVSEndpoint(resp, req); err != nil { 458 t.Fatalf("err: %v", err) 459 } 460 461 if resp.Code != 400 { 462 t.Fatalf("expected 400, got %d", resp.Code) 463 } 464 if !bytes.Contains(resp.Body.Bytes(), []byte("Conflicting")) { 465 t.Fatalf("expected conflicting args error") 466 } 467 }