github.com/Aestek/consul@v1.2.4-0.20190309222502-b2c31e33971a/agent/consul/state/catalog_test.go (about) 1 package state 2 3 import ( 4 "fmt" 5 "reflect" 6 "sort" 7 "strings" 8 "testing" 9 10 "github.com/hashicorp/consul/agent/structs" 11 "github.com/hashicorp/consul/api" 12 "github.com/hashicorp/consul/lib" 13 "github.com/hashicorp/consul/types" 14 "github.com/hashicorp/go-memdb" 15 uuid "github.com/hashicorp/go-uuid" 16 "github.com/pascaldekloe/goe/verify" 17 "github.com/stretchr/testify/assert" 18 "github.com/stretchr/testify/require" 19 ) 20 21 func makeRandomNodeID(t *testing.T) types.NodeID { 22 id, err := uuid.GenerateUUID() 23 if err != nil { 24 t.Fatalf("err: %v", err) 25 } 26 return types.NodeID(id) 27 } 28 29 func TestStateStore_GetNodeID(t *testing.T) { 30 s := testStateStore(t) 31 _, out, err := s.GetNodeID(types.NodeID("wrongId")) 32 if err == nil || out != nil || !strings.Contains(err.Error(), "node lookup by ID failed, wrong UUID") { 33 t.Fatalf("want an error, nil value, err:=%q ; out:=%q", err.Error(), out) 34 } 35 _, out, err = s.GetNodeID(types.NodeID("0123456789abcdefghijklmnopqrstuvwxyz")) 36 if err == nil || out != nil || !strings.Contains(err.Error(), "node lookup by ID failed, wrong UUID") { 37 t.Fatalf("want an error, nil value, err:=%q ; out:=%q", err, out) 38 } 39 40 _, out, err = s.GetNodeID(types.NodeID("00a916bc-a357-4a19-b886-59419fcee50Z")) 41 if err == nil || out != nil || !strings.Contains(err.Error(), "node lookup by ID failed, wrong UUID") { 42 t.Fatalf("want an error, nil value, err:=%q ; out:=%q", err, out) 43 } 44 45 _, out, err = s.GetNodeID(types.NodeID("00a916bc-a357-4a19-b886-59419fcee506")) 46 if err != nil || out != nil { 47 t.Fatalf("do not want any error nor returned value, err:=%q ; out:=%q", err, out) 48 } 49 50 nodeID := types.NodeID("00a916bc-a357-4a19-b886-59419fceeaaa") 51 req := &structs.RegisterRequest{ 52 ID: nodeID, 53 Node: "node1", 54 Address: "1.2.3.4", 55 } 56 if err := s.EnsureRegistration(1, req); err != nil { 57 t.Fatalf("err: %s", err) 58 } 59 60 _, out, err = s.GetNodeID(nodeID) 61 if err != nil { 62 t.Fatalf("got err %s want nil", err) 63 } 64 if out == nil || out.ID != nodeID { 65 t.Fatalf("out should not be nil and contain nodeId, but was:=%#v", out) 66 } 67 // Case insensitive lookup should work as well 68 _, out, err = s.GetNodeID(types.NodeID("00a916bC-a357-4a19-b886-59419fceeAAA")) 69 if err != nil { 70 t.Fatalf("got err %s want nil", err) 71 } 72 if out == nil || out.ID != nodeID { 73 t.Fatalf("out should not be nil and contain nodeId, but was:=%#v", out) 74 } 75 } 76 77 func TestStateStore_ensureNoNodeWithSimilarNameTxn(t *testing.T) { 78 t.Parallel() 79 s := testStateStore(t) 80 nodeID := makeRandomNodeID(t) 81 req := &structs.RegisterRequest{ 82 ID: nodeID, 83 Node: "node1", 84 Address: "1.2.3.4", 85 TaggedAddresses: map[string]string{"hello": "world"}, 86 NodeMeta: map[string]string{"somekey": "somevalue"}, 87 } 88 if err := s.EnsureRegistration(1, req); err != nil { 89 t.Fatalf("err: %s", err) 90 } 91 req = &structs.RegisterRequest{ 92 ID: types.NodeID(""), 93 Node: "node2", 94 Address: "10.0.0.1", 95 } 96 if err := s.EnsureRegistration(2, req); err != nil { 97 t.Fatalf("err: %s", err) 98 } 99 tx := s.db.Txn(true) 100 defer tx.Abort() 101 node := &structs.Node{ 102 ID: makeRandomNodeID(t), 103 Node: "NOdE1", // Name is similar but case is different 104 Address: "2.3.4.5", 105 } 106 // Lets conflict with node1 (has an ID) 107 if err := s.ensureNoNodeWithSimilarNameTxn(tx, node, false); err == nil { 108 t.Fatalf("Should return an error since another name with similar name exists") 109 } 110 if err := s.ensureNoNodeWithSimilarNameTxn(tx, node, true); err == nil { 111 t.Fatalf("Should return an error since another name with similar name exists") 112 } 113 // Lets conflict with node without ID 114 node.Node = "NoDe2" 115 if err := s.ensureNoNodeWithSimilarNameTxn(tx, node, false); err == nil { 116 t.Fatalf("Should return an error since another name with similar name exists") 117 } 118 if err := s.ensureNoNodeWithSimilarNameTxn(tx, node, true); err != nil { 119 t.Fatalf("Should not clash with another similar node name without ID, err:=%q", err) 120 } 121 122 } 123 124 func TestStateStore_EnsureRegistration(t *testing.T) { 125 t.Parallel() 126 s := testStateStore(t) 127 128 // Start with just a node. 129 nodeID := makeRandomNodeID(t) 130 req := &structs.RegisterRequest{ 131 ID: nodeID, 132 Node: "node1", 133 Address: "1.2.3.4", 134 TaggedAddresses: map[string]string{"hello": "world"}, 135 NodeMeta: map[string]string{"somekey": "somevalue"}, 136 } 137 if err := s.EnsureRegistration(1, req); err != nil { 138 t.Fatalf("err: %s", err) 139 } 140 141 // Retrieve the node and verify its contents. 142 verifyNode := func() { 143 node := &structs.Node{ 144 ID: nodeID, 145 Node: "node1", 146 Address: "1.2.3.4", 147 TaggedAddresses: map[string]string{"hello": "world"}, 148 Meta: map[string]string{"somekey": "somevalue"}, 149 RaftIndex: structs.RaftIndex{CreateIndex: 1, ModifyIndex: 1}, 150 } 151 152 _, out, err := s.GetNode("node1") 153 if err != nil { 154 t.Fatalf("got err %s want nil", err) 155 } 156 if got, want := out, node; !verify.Values(t, "GetNode", got, want) { 157 t.FailNow() 158 } 159 160 _, out2, err := s.GetNodeID(nodeID) 161 if err != nil { 162 t.Fatalf("got err %s want nil", err) 163 } 164 if out2 == nil { 165 t.Fatalf("out2 should not be nil") 166 } 167 if got, want := out, out2; !verify.Values(t, "GetNodeID", got, want) { 168 t.FailNow() 169 } 170 } 171 verifyNode() 172 173 // Add in a invalid service definition with too long Key value for Meta 174 req.Service = &structs.NodeService{ 175 ID: "redis1", 176 Service: "redis", 177 Address: "1.1.1.1", 178 Port: 8080, 179 Meta: map[string]string{strings.Repeat("a", 129): "somevalue"}, 180 Tags: []string{"master"}, 181 } 182 if err := s.EnsureRegistration(9, req); err == nil { 183 t.Fatalf("Service should not have been registered since Meta is invalid") 184 } 185 186 // Add in a service definition. 187 req.Service = &structs.NodeService{ 188 ID: "redis1", 189 Service: "redis", 190 Address: "1.1.1.1", 191 Port: 8080, 192 Tags: []string{"master"}, 193 Weights: &structs.Weights{Passing: 1, Warning: 1}, 194 } 195 if err := s.EnsureRegistration(2, req); err != nil { 196 t.Fatalf("err: %s", err) 197 } 198 199 // Verify that the service got registered. 200 verifyService := func() { 201 svcmap := map[string]*structs.NodeService{ 202 "redis1": &structs.NodeService{ 203 ID: "redis1", 204 Service: "redis", 205 Address: "1.1.1.1", 206 Port: 8080, 207 Tags: []string{"master"}, 208 Weights: &structs.Weights{Passing: 1, Warning: 1}, 209 RaftIndex: structs.RaftIndex{CreateIndex: 2, ModifyIndex: 2}, 210 }, 211 } 212 213 idx, out, err := s.NodeServices(nil, "node1") 214 if gotidx, wantidx := idx, uint64(2); err != nil || gotidx != wantidx { 215 t.Fatalf("got err, idx: %s, %d want nil, %d", err, gotidx, wantidx) 216 } 217 if got, want := out.Services, svcmap; !verify.Values(t, "NodeServices", got, want) { 218 t.FailNow() 219 } 220 221 idx, r, err := s.NodeService("node1", "redis1") 222 if gotidx, wantidx := idx, uint64(2); err != nil || gotidx != wantidx { 223 t.Fatalf("got err, idx: %s, %d want nil, %d", err, gotidx, wantidx) 224 } 225 if got, want := r, svcmap["redis1"]; !verify.Values(t, "NodeService", got, want) { 226 t.FailNow() 227 } 228 } 229 verifyNode() 230 verifyService() 231 232 // Add in a top-level check. 233 req.Check = &structs.HealthCheck{ 234 Node: "node1", 235 CheckID: "check1", 236 Name: "check", 237 } 238 if err := s.EnsureRegistration(3, req); err != nil { 239 t.Fatalf("err: %s", err) 240 } 241 242 // Verify that the check got registered. 243 verifyCheck := func() { 244 checks := structs.HealthChecks{ 245 &structs.HealthCheck{ 246 Node: "node1", 247 CheckID: "check1", 248 Name: "check", 249 Status: "critical", 250 RaftIndex: structs.RaftIndex{CreateIndex: 3, ModifyIndex: 3}, 251 }, 252 } 253 254 idx, out, err := s.NodeChecks(nil, "node1") 255 if gotidx, wantidx := idx, uint64(3); err != nil || gotidx != wantidx { 256 t.Fatalf("got err, idx: %s, %d want nil, %d", err, gotidx, wantidx) 257 } 258 if got, want := out, checks; !verify.Values(t, "NodeChecks", got, want) { 259 t.FailNow() 260 } 261 262 idx, c, err := s.NodeCheck("node1", "check1") 263 if gotidx, wantidx := idx, uint64(3); err != nil || gotidx != wantidx { 264 t.Fatalf("got err, idx: %s, %d want nil, %d", err, gotidx, wantidx) 265 } 266 if got, want := c, checks[0]; !verify.Values(t, "NodeCheck", got, want) { 267 t.FailNow() 268 } 269 } 270 verifyNode() 271 verifyService() 272 verifyCheck() 273 274 // Add a service check which should populate the ServiceName 275 // and ServiceTags fields in the response. 276 req.Checks = structs.HealthChecks{ 277 &structs.HealthCheck{ 278 Node: "node1", 279 CheckID: "check2", 280 Name: "check", 281 ServiceID: "redis1", 282 }, 283 } 284 if err := s.EnsureRegistration(4, req); err != nil { 285 t.Fatalf("err: %s", err) 286 } 287 288 // Verify that the additional check got registered. 289 verifyNode() 290 verifyService() 291 verifyChecks := func() { 292 checks := structs.HealthChecks{ 293 &structs.HealthCheck{ 294 Node: "node1", 295 CheckID: "check1", 296 Name: "check", 297 Status: "critical", 298 RaftIndex: structs.RaftIndex{CreateIndex: 3, ModifyIndex: 3}, 299 }, 300 &structs.HealthCheck{ 301 Node: "node1", 302 CheckID: "check2", 303 Name: "check", 304 Status: "critical", 305 ServiceID: "redis1", 306 ServiceName: "redis", 307 ServiceTags: []string{"master"}, 308 RaftIndex: structs.RaftIndex{CreateIndex: 4, ModifyIndex: 4}, 309 }, 310 } 311 312 idx, out, err := s.NodeChecks(nil, "node1") 313 if gotidx, wantidx := idx, uint64(4); err != nil || gotidx != wantidx { 314 t.Fatalf("got err, idx: %s, %d want nil, %d", err, gotidx, wantidx) 315 } 316 if got, want := out, checks; !verify.Values(t, "NodeChecks", got, want) { 317 t.FailNow() 318 } 319 } 320 verifyChecks() 321 322 // Try to register a check for some other node (top-level check). 323 req.Check = &structs.HealthCheck{ 324 Node: "nope", 325 CheckID: "check1", 326 Name: "check", 327 } 328 err := s.EnsureRegistration(5, req) 329 if err == nil || !strings.Contains(err.Error(), "does not match node") { 330 t.Fatalf("err: %s", err) 331 } 332 verifyNode() 333 verifyService() 334 verifyChecks() 335 336 // Try to register a check for some other node (checks array). 337 req.Check = nil 338 req.Checks = structs.HealthChecks{ 339 &structs.HealthCheck{ 340 Node: "nope", 341 CheckID: "check2", 342 Name: "check", 343 }, 344 } 345 err = s.EnsureRegistration(6, req) 346 if err == nil || !strings.Contains(err.Error(), "does not match node") { 347 t.Fatalf("err: %s", err) 348 } 349 verifyNode() 350 verifyService() 351 verifyChecks() 352 } 353 354 func TestStateStore_EnsureRegistration_Restore(t *testing.T) { 355 s := testStateStore(t) 356 357 // Start with just a node. 358 req := &structs.RegisterRequest{ 359 ID: makeRandomNodeID(t), 360 Node: "node1", 361 Address: "1.2.3.4", 362 } 363 nodeID := string(req.ID) 364 nodeName := string(req.Node) 365 restore := s.Restore() 366 if err := restore.Registration(1, req); err != nil { 367 t.Fatalf("err: %s", err) 368 } 369 restore.Commit() 370 371 // Retrieve the node and verify its contents. 372 verifyNode := func(nodeLookup string) { 373 _, out, err := s.GetNode(nodeLookup) 374 if err != nil { 375 t.Fatalf("err: %s", err) 376 } 377 if out == nil { 378 _, out, err = s.GetNodeID(types.NodeID(nodeLookup)) 379 if err != nil { 380 t.Fatalf("err: %s", err) 381 } 382 } 383 384 if out == nil || out.Address != "1.2.3.4" || 385 !(out.Node == nodeLookup || string(out.ID) == nodeLookup) || 386 out.CreateIndex != 1 || out.ModifyIndex != 1 { 387 t.Fatalf("bad node returned: %#v", out) 388 } 389 } 390 verifyNode(nodeID) 391 verifyNode(nodeName) 392 393 // Add in a service definition. 394 req.Service = &structs.NodeService{ 395 ID: "redis1", 396 Service: "redis", 397 Address: "1.1.1.1", 398 Port: 8080, 399 Weights: &structs.Weights{Passing: 1, Warning: 1}, 400 } 401 restore = s.Restore() 402 if err := restore.Registration(2, req); err != nil { 403 t.Fatalf("err: %s", err) 404 } 405 restore.Commit() 406 407 // Verify that the service got registered. 408 verifyService := func(nodeLookup string) { 409 idx, out, err := s.NodeServices(nil, nodeLookup) 410 if err != nil { 411 t.Fatalf("err: %s", err) 412 } 413 if idx != 2 { 414 t.Fatalf("bad index: %d", idx) 415 } 416 if len(out.Services) != 1 { 417 t.Fatalf("bad: %#v", out.Services) 418 } 419 s := out.Services["redis1"] 420 if s.ID != "redis1" || s.Service != "redis" || 421 s.Address != "1.1.1.1" || s.Port != 8080 || 422 s.CreateIndex != 2 || s.ModifyIndex != 2 { 423 t.Fatalf("bad service returned: %#v", s) 424 } 425 } 426 427 // Add in a top-level check. 428 req.Check = &structs.HealthCheck{ 429 Node: nodeName, 430 CheckID: "check1", 431 Name: "check", 432 } 433 restore = s.Restore() 434 if err := restore.Registration(3, req); err != nil { 435 t.Fatalf("err: %s", err) 436 } 437 restore.Commit() 438 439 // Verify that the check got registered. 440 verifyCheck := func() { 441 idx, out, err := s.NodeChecks(nil, nodeName) 442 if err != nil { 443 t.Fatalf("err: %s", err) 444 } 445 if idx != 3 { 446 t.Fatalf("bad index: %d", idx) 447 } 448 if len(out) != 1 { 449 t.Fatalf("bad: %#v", out) 450 } 451 c := out[0] 452 if c.Node != nodeName || c.CheckID != "check1" || c.Name != "check" || 453 c.CreateIndex != 3 || c.ModifyIndex != 3 { 454 t.Fatalf("bad check returned: %#v", c) 455 } 456 } 457 verifyNode(nodeID) 458 verifyNode(nodeName) 459 verifyService(nodeID) 460 verifyService(nodeName) 461 verifyCheck() 462 463 // Add in another check via the slice. 464 req.Checks = structs.HealthChecks{ 465 &structs.HealthCheck{ 466 Node: nodeName, 467 CheckID: "check2", 468 Name: "check", 469 }, 470 } 471 restore = s.Restore() 472 if err := restore.Registration(4, req); err != nil { 473 t.Fatalf("err: %s", err) 474 } 475 restore.Commit() 476 477 // Verify that the additional check got registered. 478 verifyNode(nodeID) 479 verifyNode(nodeName) 480 verifyService(nodeID) 481 verifyService(nodeName) 482 func() { 483 idx, out, err := s.NodeChecks(nil, nodeName) 484 if err != nil { 485 t.Fatalf("err: %s", err) 486 } 487 if idx != 4 { 488 t.Fatalf("bad index: %d", idx) 489 } 490 if len(out) != 2 { 491 t.Fatalf("bad: %#v", out) 492 } 493 c1 := out[0] 494 if c1.Node != nodeName || c1.CheckID != "check1" || c1.Name != "check" || 495 c1.CreateIndex != 3 || c1.ModifyIndex != 3 { 496 t.Fatalf("bad check returned, should not be modified: %#v", c1) 497 } 498 499 c2 := out[1] 500 if c2.Node != nodeName || c2.CheckID != "check2" || c2.Name != "check" || 501 c2.CreateIndex != 4 || c2.ModifyIndex != 4 { 502 t.Fatalf("bad check returned: %#v", c2) 503 } 504 }() 505 } 506 507 func deprecatedEnsureNodeWithoutIDCanRegister(t *testing.T, s *Store, nodeName string, txIdx uint64) { 508 // All the following is deprecated, and should be removed in future Consul versions 509 in := &structs.Node{ 510 Node: nodeName, 511 Address: "1.1.1.9", 512 Meta: map[string]string{ 513 "version": string(txIdx), 514 }, 515 } 516 if err := s.EnsureNode(txIdx, in); err != nil { 517 t.Fatalf("err: %s", err) 518 } 519 idx, out, err := s.GetNode(nodeName) 520 if err != nil { 521 t.Fatalf("err: %s", err) 522 } 523 if idx != txIdx { 524 t.Fatalf("index should be %v, was: %v", txIdx, idx) 525 } 526 if out.Node != nodeName { 527 t.Fatalf("unexpected result out = %v, nodeName supposed to be %s", out, nodeName) 528 } 529 } 530 531 func TestStateStore_EnsureNodeDeprecated(t *testing.T) { 532 s := testStateStore(t) 533 534 firstNodeName := "node-without-id" 535 deprecatedEnsureNodeWithoutIDCanRegister(t, s, firstNodeName, 1) 536 537 newNodeID := types.NodeID("00a916bc-a357-4a19-b886-59419fcee50c") 538 // With this request, we basically add a node ID to existing node 539 // and change its address 540 in := &structs.Node{ 541 ID: newNodeID, 542 Node: firstNodeName, 543 Address: "1.1.7.8", 544 } 545 if err := s.EnsureNode(4, in); err != nil { 546 t.Fatalf("err: %v", err) 547 } 548 // Retrieve the node again 549 idx, out, err := s.GetNode(firstNodeName) 550 if err != nil { 551 t.Fatalf("err: %s", err) 552 } 553 554 // Node has updated information 555 if idx != 4 || out.Node != firstNodeName || out.ID != newNodeID || out.Address != "1.1.7.8" { 556 t.Fatalf("[DEPRECATED] bad node returned: %#v", out) 557 } 558 if out.CreateIndex != 1 || out.ModifyIndex != 4 { 559 t.Fatalf("[DEPRECATED] bad CreateIndex/ModifyIndex returned: %#v", out) 560 } 561 562 // Now, lets update IP Address without providing any ID 563 // Only name of node will be used to match 564 in = &structs.Node{ 565 Node: firstNodeName, 566 Address: "1.1.7.10", 567 } 568 if err := s.EnsureNode(7, in); err != nil { 569 t.Fatalf("err: %v", err) 570 } 571 // Retrieve the node again 572 idx, out, err = s.GetNode(firstNodeName) 573 if err != nil { 574 t.Fatalf("err: %s", err) 575 } 576 577 // Node has updated information, its ID has been removed (deprecated, but working) 578 if idx != 7 || out.Node != firstNodeName || out.ID != "" || out.Address != "1.1.7.10" { 579 t.Fatalf("[DEPRECATED] bad node returned: %#v", out) 580 } 581 if out.CreateIndex != 1 || out.ModifyIndex != 7 { 582 t.Fatalf("[DEPRECATED] bad CreateIndex/ModifyIndex returned: %#v", out) 583 } 584 } 585 586 func TestNodeRenamingNodes(t *testing.T) { 587 s := testStateStore(t) 588 589 nodeID1 := types.NodeID("b789bf0a-d96b-4f70-a4a6-ac5dfaece53d") 590 nodeID2 := types.NodeID("27bee224-a4d7-45d0-9b8e-65b3c94a61ba") 591 592 // Node1 with ID 593 in1 := &structs.Node{ 594 ID: nodeID1, 595 Node: "node1", 596 Address: "1.1.1.1", 597 } 598 599 if err := s.EnsureNode(1, in1); err != nil { 600 t.Fatalf("err: %s", err) 601 } 602 603 // Node2 with ID 604 in2 := &structs.Node{ 605 ID: nodeID2, 606 Node: "node2", 607 Address: "1.1.1.2", 608 } 609 610 if err := s.EnsureNode(2, in2); err != nil { 611 t.Fatalf("err: %s", err) 612 } 613 614 // Node3 without ID 615 in3 := &structs.Node{ 616 Node: "node3", 617 Address: "1.1.1.3", 618 } 619 620 if err := s.EnsureNode(3, in3); err != nil { 621 t.Fatalf("err: %s", err) 622 } 623 624 if _, node, err := s.GetNodeID(nodeID1); err != nil || node == nil || node.ID != nodeID1 { 625 t.Fatalf("err: %s, node:= %q", err, node) 626 } 627 628 if _, node, err := s.GetNodeID(nodeID2); err != nil && node == nil || node.ID != nodeID2 { 629 t.Fatalf("err: %s", err) 630 } 631 632 // Renaming node2 into node1 should fail 633 in2Modify := &structs.Node{ 634 ID: nodeID2, 635 Node: "node1", 636 Address: "1.1.1.2", 637 } 638 if err := s.EnsureNode(4, in2Modify); err == nil { 639 t.Fatalf("Renaming node2 into node1 should fail") 640 } 641 642 // Conflict with case insensitive matching as well 643 in2Modify = &structs.Node{ 644 ID: nodeID2, 645 Node: "NoDe1", 646 Address: "1.1.1.2", 647 } 648 if err := s.EnsureNode(5, in2Modify); err == nil { 649 t.Fatalf("Renaming node2 into node1 should fail") 650 } 651 652 // Conflict with case insensitive on node without ID 653 in2Modify = &structs.Node{ 654 ID: nodeID2, 655 Node: "NoDe3", 656 Address: "1.1.1.2", 657 } 658 if err := s.EnsureNode(6, in2Modify); err == nil { 659 t.Fatalf("Renaming node2 into node1 should fail") 660 } 661 662 // No conflict, should work 663 in2Modify = &structs.Node{ 664 ID: nodeID2, 665 Node: "node2bis", 666 Address: "1.1.1.2", 667 } 668 if err := s.EnsureNode(6, in2Modify); err != nil { 669 t.Fatalf("Renaming node2 into node1 should fail") 670 } 671 672 // Retrieve the node again 673 idx, out, err := s.GetNode("node2bis") 674 if err != nil { 675 t.Fatalf("err: %s", err) 676 } 677 678 // Retrieve the node again 679 idx2, out2, err := s.GetNodeID(nodeID2) 680 if err != nil { 681 t.Fatalf("err: %s", err) 682 } 683 684 if idx != idx2 { 685 t.Fatalf("node should be the same") 686 } 687 688 if out.ID != out2.ID || out.Node != out2.Node { 689 t.Fatalf("all should match") 690 } 691 } 692 693 func TestStateStore_EnsureNode(t *testing.T) { 694 s := testStateStore(t) 695 696 // Fetching a non-existent node returns nil 697 if _, node, err := s.GetNode("node1"); node != nil || err != nil { 698 t.Fatalf("expected (nil, nil), got: (%#v, %#v)", node, err) 699 } 700 701 // Create a node registration request 702 in := &structs.Node{ 703 ID: types.NodeID("cda916bc-a357-4a19-b886-59419fcee50c"), 704 Node: "node1", 705 Address: "1.1.1.1", 706 } 707 708 // Ensure the node is registered in the db 709 if err := s.EnsureNode(1, in); err != nil { 710 t.Fatalf("err: %s", err) 711 } 712 713 // Retrieve the node again 714 idx, out, err := s.GetNode("node1") 715 if err != nil { 716 t.Fatalf("err: %s", err) 717 } 718 719 // Correct node was returned 720 if out.Node != "node1" || out.Address != "1.1.1.1" { 721 t.Fatalf("bad node returned: %#v", out) 722 } 723 724 // Indexes are set properly 725 if out.CreateIndex != 1 || out.ModifyIndex != 1 { 726 t.Fatalf("bad node index: %#v", out) 727 } 728 if idx != 1 { 729 t.Fatalf("bad index: %d", idx) 730 } 731 732 // Update the node registration 733 in2 := &structs.Node{ 734 ID: in.ID, 735 Node: in.Node, 736 Address: "1.1.1.2", 737 } 738 if err := s.EnsureNode(2, in2); err != nil { 739 t.Fatalf("err: %s", err) 740 } 741 742 // Retrieve the node 743 idx, out, err = s.GetNode("node1") 744 if err != nil { 745 t.Fatalf("err: %s", err) 746 } 747 748 // Node and indexes were updated 749 if out.CreateIndex != 1 || out.ModifyIndex != 2 || out.Address != "1.1.1.2" { 750 t.Fatalf("bad: %#v", out) 751 } 752 if idx != 2 { 753 t.Fatalf("bad index: %d", idx) 754 } 755 756 // Re-inserting data should not modify ModifiedIndex 757 if err := s.EnsureNode(3, in2); err != nil { 758 t.Fatalf("err: %s", err) 759 } 760 idx, out, err = s.GetNode("node1") 761 if err != nil { 762 t.Fatalf("err: %s", err) 763 } 764 if out.CreateIndex != 1 || out.ModifyIndex != 2 || out.Address != "1.1.1.2" { 765 t.Fatalf("node was modified: %#v", out) 766 } 767 768 // Node upsert preserves the create index 769 in3 := &structs.Node{ 770 ID: in.ID, 771 Node: in.Node, 772 Address: "1.1.1.3", 773 } 774 if err := s.EnsureNode(3, in3); err != nil { 775 t.Fatalf("err: %s", err) 776 } 777 idx, out, err = s.GetNode("node1") 778 if err != nil { 779 t.Fatalf("err: %s", err) 780 } 781 if out.CreateIndex != 1 || out.ModifyIndex != 3 || out.Address != "1.1.1.3" { 782 t.Fatalf("node was modified: %#v", out) 783 } 784 if idx != 3 { 785 t.Fatalf("bad index: %d", idx) 786 } 787 788 // Update index to 4, no change 789 if err := s.EnsureNode(4, in); err != nil { 790 t.Fatalf("err: %v", err) 791 } 792 793 // Now try to add another node with the same ID 794 in = &structs.Node{ 795 Node: "node1-renamed", 796 ID: types.NodeID("cda916bc-a357-4a19-b886-59419fcee50c"), 797 Address: "1.1.1.2", 798 } 799 if err := s.EnsureNode(6, in); err != nil { 800 t.Fatalf("err: %s", err) 801 } 802 803 // Retrieve the node 804 idx, out, err = s.GetNode("node1") 805 if out != nil { 806 t.Fatalf("Node should not exist anymore: %q", out) 807 } 808 809 idx, out, err = s.GetNode("node1-renamed") 810 if err != nil { 811 t.Fatalf("err: %s", err) 812 } 813 814 if out == nil { 815 t.Fatalf("err: %s", err) 816 } 817 818 // Node and indexes were updated 819 if out.CreateIndex != 1 || out.ModifyIndex != 6 || out.Address != "1.1.1.2" || out.Node != "node1-renamed" { 820 t.Fatalf("bad: %#v", out) 821 } 822 if idx != 6 { 823 t.Fatalf("bad index: %d", idx) 824 } 825 826 newNodeID := types.NodeID("d0347693-65cc-4d9f-a6e0-5025b2e6513f") 827 828 // Adding another node with same name should fail 829 in = &structs.Node{ 830 Node: "node1-renamed", 831 ID: newNodeID, 832 Address: "1.1.1.7", 833 } 834 if err := s.EnsureNode(8, in); err == nil { 835 t.Fatalf("There should be an error since node1-renamed already exists") 836 } 837 838 // Adding another node with same name but different case should fail 839 in = &structs.Node{ 840 Node: "Node1-RENAMED", 841 ID: newNodeID, 842 Address: "1.1.1.7", 843 } 844 if err := s.EnsureNode(8, in); err == nil { 845 t.Fatalf("err: %s", err) 846 } 847 848 // Lets add another valid node now 849 in = &structs.Node{ 850 Node: "Node1bis", 851 ID: newNodeID, 852 Address: "1.1.1.7", 853 } 854 if err := s.EnsureNode(9, in); err != nil { 855 t.Fatalf("err: %s", err) 856 } 857 858 // Retrieve the node 859 idx, out, err = s.GetNode("Node1bis") 860 if out == nil { 861 t.Fatalf("Node should exist, but was null") 862 } 863 864 // Renaming should fail 865 in = &structs.Node{ 866 Node: "Node1bis", 867 ID: newNodeID, 868 Address: "1.1.1.7", 869 } 870 if err := s.EnsureNode(9, in); err != nil { 871 t.Fatalf("err: %s", err) 872 } 873 874 idx, out, err = s.GetNode("Node1bis") 875 if err != nil { 876 t.Fatalf("err: %s", err) 877 } 878 879 // Node and indexes were updated 880 if out.ID != newNodeID || out.CreateIndex != 9 || out.ModifyIndex != 9 || out.Address != "1.1.1.7" || out.Node != "Node1bis" { 881 t.Fatalf("bad: %#v", out) 882 } 883 if idx != 9 { 884 t.Fatalf("bad index: %d", idx) 885 } 886 887 // Renaming to same value as first node should fail as well 888 // Adding another node with same name but different case should fail 889 in = &structs.Node{ 890 Node: "node1-renamed", 891 ID: newNodeID, 892 Address: "1.1.1.7", 893 } 894 if err := s.EnsureNode(10, in); err == nil { 895 t.Fatalf("err: %s", err) 896 } 897 898 // It should fail also with different case 899 in = &structs.Node{ 900 Node: "Node1-Renamed", 901 ID: newNodeID, 902 Address: "1.1.1.7", 903 } 904 if err := s.EnsureNode(10, in); err == nil { 905 t.Fatalf("err: %s", err) 906 } 907 908 // But should work if names are different 909 in = &structs.Node{ 910 Node: "Node1-Renamed2", 911 ID: newNodeID, 912 Address: "1.1.1.7", 913 } 914 if err := s.EnsureNode(11, in); err != nil { 915 t.Fatalf("err: %s", err) 916 } 917 idx, out, err = s.GetNode("Node1-Renamed2") 918 if err != nil { 919 t.Fatalf("err: %s", err) 920 } 921 922 // Node and indexes were updated 923 if out.ID != newNodeID || out.CreateIndex != 9 || out.ModifyIndex != 11 || out.Address != "1.1.1.7" || out.Node != "Node1-Renamed2" { 924 t.Fatalf("bad: %#v", out) 925 } 926 if idx != 11 { 927 t.Fatalf("bad index: %d", idx) 928 } 929 930 // All the remaining tests are deprecated, please remove them on next Consul major release 931 // See https://github.com/hashicorp/consul/pull/3983 for context 932 933 // Deprecated behavior is following 934 deprecatedEnsureNodeWithoutIDCanRegister(t, s, "new-node-without-id", 12) 935 936 // Deprecated, but should work as well 937 deprecatedEnsureNodeWithoutIDCanRegister(t, s, "new-node-without-id", 13) 938 939 // All of this is deprecated as well, should be removed 940 in = &structs.Node{ 941 Node: "Node1-Renamed2", 942 Address: "1.1.1.66", 943 } 944 if err := s.EnsureNode(14, in); err != nil { 945 t.Fatalf("[DEPRECATED] it should work, err:= %q", err) 946 } 947 idx, out, err = s.GetNode("Node1-Renamed2") 948 if err != nil { 949 t.Fatalf("[DEPRECATED] err: %s", err) 950 } 951 if out.CreateIndex != 9 { 952 t.Fatalf("[DEPRECATED] We expected to modify node previously added, but add index = %d for node %q", out.CreateIndex, out) 953 } 954 if out.Address != "1.1.1.66" || out.ModifyIndex != 14 { 955 t.Fatalf("[DEPRECATED] Node with newNodeID should have been updated, but was: %d with content := %q", out.CreateIndex, out) 956 } 957 } 958 959 func TestStateStore_GetNodes(t *testing.T) { 960 s := testStateStore(t) 961 962 // Listing with no results returns nil. 963 ws := memdb.NewWatchSet() 964 idx, res, err := s.Nodes(ws) 965 if idx != 0 || res != nil || err != nil { 966 t.Fatalf("expected (0, nil, nil), got: (%d, %#v, %#v)", idx, res, err) 967 } 968 969 // Create some nodes in the state store. 970 testRegisterNode(t, s, 0, "node0") 971 testRegisterNode(t, s, 1, "node1") 972 testRegisterNode(t, s, 2, "node2") 973 if !watchFired(ws) { 974 t.Fatalf("bad") 975 } 976 977 // Retrieve the nodes. 978 ws = memdb.NewWatchSet() 979 idx, nodes, err := s.Nodes(ws) 980 if err != nil { 981 t.Fatalf("err: %s", err) 982 } 983 984 // Highest index was returned. 985 if idx != 2 { 986 t.Fatalf("bad index: %d", idx) 987 } 988 989 // All nodes were returned. 990 if n := len(nodes); n != 3 { 991 t.Fatalf("bad node count: %d", n) 992 } 993 994 // Make sure the nodes match. 995 for i, node := range nodes { 996 if node.CreateIndex != uint64(i) || node.ModifyIndex != uint64(i) { 997 t.Fatalf("bad node index: %d, %d", node.CreateIndex, node.ModifyIndex) 998 } 999 name := fmt.Sprintf("node%d", i) 1000 if node.Node != name { 1001 t.Fatalf("bad: %#v", node) 1002 } 1003 } 1004 1005 // Make sure a node delete fires the watch. 1006 if watchFired(ws) { 1007 t.Fatalf("bad") 1008 } 1009 if err := s.DeleteNode(3, "node1"); err != nil { 1010 t.Fatalf("err: %s", err) 1011 } 1012 if !watchFired(ws) { 1013 t.Fatalf("bad") 1014 } 1015 } 1016 1017 func BenchmarkGetNodes(b *testing.B) { 1018 s, err := NewStateStore(nil) 1019 if err != nil { 1020 b.Fatalf("err: %s", err) 1021 } 1022 1023 if err := s.EnsureNode(100, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 1024 b.Fatalf("err: %v", err) 1025 } 1026 if err := s.EnsureNode(101, &structs.Node{Node: "bar", Address: "127.0.0.2"}); err != nil { 1027 b.Fatalf("err: %v", err) 1028 } 1029 1030 ws := memdb.NewWatchSet() 1031 for i := 0; i < b.N; i++ { 1032 s.Nodes(ws) 1033 } 1034 } 1035 1036 func TestStateStore_GetNodesByMeta(t *testing.T) { 1037 s := testStateStore(t) 1038 1039 // Listing with no results returns nil 1040 ws := memdb.NewWatchSet() 1041 idx, res, err := s.NodesByMeta(ws, map[string]string{"somekey": "somevalue"}) 1042 if idx != 0 || res != nil || err != nil { 1043 t.Fatalf("expected (0, nil, nil), got: (%d, %#v, %#v)", idx, res, err) 1044 } 1045 1046 // Create some nodes in the state store. 1047 testRegisterNodeWithMeta(t, s, 0, "node0", map[string]string{"role": "client"}) 1048 testRegisterNodeWithMeta(t, s, 1, "node1", map[string]string{"role": "client", "common": "1"}) 1049 testRegisterNodeWithMeta(t, s, 2, "node2", map[string]string{"role": "server", "common": "1"}) 1050 if !watchFired(ws) { 1051 t.Fatalf("bad") 1052 } 1053 1054 cases := []struct { 1055 filters map[string]string 1056 nodes []string 1057 }{ 1058 // Simple meta filter 1059 { 1060 filters: map[string]string{"role": "server"}, 1061 nodes: []string{"node2"}, 1062 }, 1063 // Common meta filter 1064 { 1065 filters: map[string]string{"common": "1"}, 1066 nodes: []string{"node1", "node2"}, 1067 }, 1068 // Invalid meta filter 1069 { 1070 filters: map[string]string{"invalid": "nope"}, 1071 nodes: []string{}, 1072 }, 1073 // Multiple meta filters 1074 { 1075 filters: map[string]string{"role": "client", "common": "1"}, 1076 nodes: []string{"node1"}, 1077 }, 1078 } 1079 1080 for _, tc := range cases { 1081 _, result, err := s.NodesByMeta(nil, tc.filters) 1082 if err != nil { 1083 t.Fatalf("bad: %v", err) 1084 } 1085 1086 if len(result) != len(tc.nodes) { 1087 t.Fatalf("bad: %v %v", result, tc.nodes) 1088 } 1089 1090 for i, node := range result { 1091 if node.Node != tc.nodes[i] { 1092 t.Fatalf("bad: %v %v", node.Node, tc.nodes[i]) 1093 } 1094 } 1095 } 1096 1097 // Set up a watch. 1098 ws = memdb.NewWatchSet() 1099 _, _, err = s.NodesByMeta(ws, map[string]string{"role": "client"}) 1100 if err != nil { 1101 t.Fatalf("err: %v", err) 1102 } 1103 1104 // Make an unrelated modification and make sure the watch doesn't fire. 1105 testRegisterNodeWithMeta(t, s, 3, "node3", map[string]string{"foo": "bar"}) 1106 if watchFired(ws) { 1107 t.Fatalf("bad") 1108 } 1109 1110 // Change a watched key and make sure it fires. 1111 testRegisterNodeWithMeta(t, s, 4, "node0", map[string]string{"role": "different"}) 1112 if !watchFired(ws) { 1113 t.Fatalf("bad") 1114 } 1115 } 1116 1117 func TestStateStore_NodeServices(t *testing.T) { 1118 s := testStateStore(t) 1119 1120 // Register some nodes with similar IDs. 1121 { 1122 req := &structs.RegisterRequest{ 1123 ID: types.NodeID("40e4a748-2192-161a-0510-aaaaaaaaaaaa"), 1124 Node: "node1", 1125 Address: "1.2.3.4", 1126 } 1127 if err := s.EnsureRegistration(1, req); err != nil { 1128 t.Fatalf("err: %s", err) 1129 } 1130 } 1131 { 1132 req := &structs.RegisterRequest{ 1133 ID: types.NodeID("40e4a748-2192-161a-0510-bbbbbbbbbbbb"), 1134 Node: "node2", 1135 Address: "5.6.7.8", 1136 } 1137 if err := s.EnsureRegistration(2, req); err != nil { 1138 t.Fatalf("err: %s", err) 1139 } 1140 } 1141 1142 // Look up by name. 1143 { 1144 _, ns, err := s.NodeServices(nil, "node1") 1145 if err != nil { 1146 t.Fatalf("err: %v", err) 1147 } 1148 if ns == nil || ns.Node.Node != "node1" { 1149 t.Fatalf("bad: %#v", *ns) 1150 } 1151 } 1152 { 1153 _, ns, err := s.NodeServices(nil, "node2") 1154 if err != nil { 1155 t.Fatalf("err: %v", err) 1156 } 1157 if ns == nil || ns.Node.Node != "node2" { 1158 t.Fatalf("bad: %#v", *ns) 1159 } 1160 } 1161 1162 // Look up by UUID. 1163 { 1164 _, ns, err := s.NodeServices(nil, "40e4a748-2192-161a-0510-aaaaaaaaaaaa") 1165 if err != nil { 1166 t.Fatalf("err: %v", err) 1167 } 1168 if ns == nil || ns.Node.Node != "node1" { 1169 t.Fatalf("bad: %#v", ns) 1170 } 1171 } 1172 { 1173 _, ns, err := s.NodeServices(nil, "40e4a748-2192-161a-0510-bbbbbbbbbbbb") 1174 if err != nil { 1175 t.Fatalf("err: %v", err) 1176 } 1177 if ns == nil || ns.Node.Node != "node2" { 1178 t.Fatalf("bad: %#v", ns) 1179 } 1180 } 1181 1182 // Ambiguous prefix. 1183 { 1184 _, ns, err := s.NodeServices(nil, "40e4a748-2192-161a-0510") 1185 if err != nil { 1186 t.Fatalf("err: %v", err) 1187 } 1188 if ns != nil { 1189 t.Fatalf("bad: %#v", ns) 1190 } 1191 } 1192 1193 // Bad node, and not a UUID (should not get a UUID error). 1194 { 1195 _, ns, err := s.NodeServices(nil, "nope") 1196 if err != nil { 1197 t.Fatalf("err: %v", err) 1198 } 1199 if ns != nil { 1200 t.Fatalf("bad: %#v", ns) 1201 } 1202 } 1203 1204 // Specific prefix. 1205 { 1206 _, ns, err := s.NodeServices(nil, "40e4a748-2192-161a-0510-bb") 1207 if err != nil { 1208 t.Fatalf("err: %v", err) 1209 } 1210 if ns == nil || ns.Node.Node != "node2" { 1211 t.Fatalf("bad: %#v", ns) 1212 } 1213 } 1214 } 1215 1216 func TestStateStore_DeleteNode(t *testing.T) { 1217 s := testStateStore(t) 1218 1219 // Create a node and register a service and health check with it. 1220 testRegisterNode(t, s, 0, "node1") 1221 testRegisterService(t, s, 1, "node1", "service1") 1222 testRegisterCheck(t, s, 2, "node1", "", "check1", api.HealthPassing) 1223 1224 // Delete the node 1225 if err := s.DeleteNode(3, "node1"); err != nil { 1226 t.Fatalf("err: %s", err) 1227 } 1228 1229 // The node was removed 1230 if idx, n, err := s.GetNode("node1"); err != nil || n != nil || idx != 3 { 1231 t.Fatalf("bad: %#v %d (err: %#v)", n, idx, err) 1232 } 1233 1234 // Associated service was removed. Need to query this directly out of 1235 // the DB to make sure it is actually gone. 1236 tx := s.db.Txn(false) 1237 defer tx.Abort() 1238 services, err := tx.Get("services", "id", "node1", "service1") 1239 if err != nil { 1240 t.Fatalf("err: %s", err) 1241 } 1242 if service := services.Next(); service != nil { 1243 t.Fatalf("bad: %#v", service) 1244 } 1245 1246 // Associated health check was removed. 1247 checks, err := tx.Get("checks", "id", "node1", "check1") 1248 if err != nil { 1249 t.Fatalf("err: %s", err) 1250 } 1251 if check := checks.Next(); check != nil { 1252 t.Fatalf("bad: %#v", check) 1253 } 1254 1255 // Indexes were updated. 1256 for _, tbl := range []string{"nodes", "services", "checks"} { 1257 if idx := s.maxIndex(tbl); idx != 3 { 1258 t.Fatalf("bad index: %d (%s)", idx, tbl) 1259 } 1260 } 1261 1262 // Deleting a nonexistent node should be idempotent and not return 1263 // an error 1264 if err := s.DeleteNode(4, "node1"); err != nil { 1265 t.Fatalf("err: %s", err) 1266 } 1267 if idx := s.maxIndex("nodes"); idx != 3 { 1268 t.Fatalf("bad index: %d", idx) 1269 } 1270 } 1271 1272 func TestStateStore_Node_Snapshot(t *testing.T) { 1273 s := testStateStore(t) 1274 1275 // Create some nodes in the state store. 1276 testRegisterNode(t, s, 0, "node0") 1277 testRegisterNode(t, s, 1, "node1") 1278 testRegisterNode(t, s, 2, "node2") 1279 1280 // Snapshot the nodes. 1281 snap := s.Snapshot() 1282 defer snap.Close() 1283 1284 // Alter the real state store. 1285 testRegisterNode(t, s, 3, "node3") 1286 1287 // Verify the snapshot. 1288 if idx := snap.LastIndex(); idx != 2 { 1289 t.Fatalf("bad index: %d", idx) 1290 } 1291 nodes, err := snap.Nodes() 1292 if err != nil { 1293 t.Fatalf("err: %s", err) 1294 } 1295 for i := 0; i < 3; i++ { 1296 node := nodes.Next().(*structs.Node) 1297 if node == nil { 1298 t.Fatalf("unexpected end of nodes") 1299 } 1300 1301 if node.CreateIndex != uint64(i) || node.ModifyIndex != uint64(i) { 1302 t.Fatalf("bad node index: %d, %d", node.CreateIndex, node.ModifyIndex) 1303 } 1304 if node.Node != fmt.Sprintf("node%d", i) { 1305 t.Fatalf("bad: %#v", node) 1306 } 1307 } 1308 if nodes.Next() != nil { 1309 t.Fatalf("unexpected extra nodes") 1310 } 1311 } 1312 1313 func TestStateStore_EnsureService(t *testing.T) { 1314 s := testStateStore(t) 1315 1316 // Fetching services for a node with none returns nil. 1317 ws := memdb.NewWatchSet() 1318 idx, res, err := s.NodeServices(ws, "node1") 1319 if err != nil || res != nil || idx != 0 { 1320 t.Fatalf("expected (0, nil, nil), got: (%d, %#v, %#v)", idx, res, err) 1321 } 1322 1323 // Create the service registration. 1324 ns1 := &structs.NodeService{ 1325 ID: "service1", 1326 Service: "redis", 1327 Tags: []string{"prod"}, 1328 Address: "1.1.1.1", 1329 Port: 1111, 1330 Weights: &structs.Weights{Passing: 1, Warning: 0}, 1331 } 1332 1333 // Creating a service without a node returns an error. 1334 if err := s.EnsureService(1, "node1", ns1); err != ErrMissingNode { 1335 t.Fatalf("expected %#v, got: %#v", ErrMissingNode, err) 1336 } 1337 if watchFired(ws) { 1338 t.Fatalf("bad") 1339 } 1340 1341 // Register the nodes. 1342 testRegisterNode(t, s, 0, "node1") 1343 testRegisterNode(t, s, 1, "node2") 1344 if !watchFired(ws) { 1345 t.Fatalf("bad") 1346 } 1347 1348 // Service successfully registers into the state store. 1349 ws = memdb.NewWatchSet() 1350 _, _, err = s.NodeServices(ws, "node1") 1351 if err != nil { 1352 t.Fatalf("err: %v", err) 1353 } 1354 if err = s.EnsureService(10, "node1", ns1); err != nil { 1355 t.Fatalf("err: %s", err) 1356 } 1357 if !watchFired(ws) { 1358 t.Fatalf("bad") 1359 } 1360 1361 // Register a similar service against both nodes. 1362 ns2 := *ns1 1363 ns2.ID = "service2" 1364 for _, n := range []string{"node1", "node2"} { 1365 if err := s.EnsureService(20, n, &ns2); err != nil { 1366 t.Fatalf("err: %s", err) 1367 } 1368 } 1369 1370 // Register a different service on the bad node. 1371 ws = memdb.NewWatchSet() 1372 _, _, err = s.NodeServices(ws, "node1") 1373 if err != nil { 1374 t.Fatalf("err: %v", err) 1375 } 1376 ns3 := *ns1 1377 ns3.ID = "service3" 1378 if err := s.EnsureService(30, "node2", &ns3); err != nil { 1379 t.Fatalf("err: %s", err) 1380 } 1381 if watchFired(ws) { 1382 t.Fatalf("bad") 1383 } 1384 1385 // Retrieve the services. 1386 ws = memdb.NewWatchSet() 1387 idx, out, err := s.NodeServices(ws, "node1") 1388 if err != nil { 1389 t.Fatalf("err: %s", err) 1390 } 1391 if idx != 30 { 1392 t.Fatalf("bad index: %d", idx) 1393 } 1394 1395 // Only the services for the requested node are returned. 1396 if out == nil || len(out.Services) != 2 { 1397 t.Fatalf("bad services: %#v", out) 1398 } 1399 1400 // Results match the inserted services and have the proper indexes set. 1401 expect1 := *ns1 1402 expect1.CreateIndex, expect1.ModifyIndex = 10, 10 1403 if svc := out.Services["service1"]; !reflect.DeepEqual(&expect1, svc) { 1404 t.Fatalf("bad: %#v", svc) 1405 } 1406 1407 expect2 := ns2 1408 expect2.CreateIndex, expect2.ModifyIndex = 20, 20 1409 if svc := out.Services["service2"]; !reflect.DeepEqual(&expect2, svc) { 1410 t.Fatalf("bad: %#v %#v", ns2, svc) 1411 } 1412 1413 // Index tables were updated. 1414 if idx := s.maxIndex("services"); idx != 30 { 1415 t.Fatalf("bad index: %d", idx) 1416 } 1417 1418 // Update a service registration. 1419 ns1.Address = "1.1.1.2" 1420 if err := s.EnsureService(40, "node1", ns1); err != nil { 1421 t.Fatalf("err: %s", err) 1422 } 1423 if !watchFired(ws) { 1424 t.Fatalf("bad") 1425 } 1426 1427 // Retrieve the service again and ensure it matches.. 1428 idx, out, err = s.NodeServices(nil, "node1") 1429 if err != nil { 1430 t.Fatalf("err: %s", err) 1431 } 1432 if idx != 40 { 1433 t.Fatalf("bad index: %d", idx) 1434 } 1435 if out == nil || len(out.Services) != 2 { 1436 t.Fatalf("bad: %#v", out) 1437 } 1438 expect1.Address = "1.1.1.2" 1439 expect1.ModifyIndex = 40 1440 if svc := out.Services["service1"]; !reflect.DeepEqual(&expect1, svc) { 1441 t.Fatalf("bad: %#v", svc) 1442 } 1443 1444 // Index tables were updated. 1445 if idx := s.maxIndex("services"); idx != 40 { 1446 t.Fatalf("bad index: %d", idx) 1447 } 1448 } 1449 1450 func TestStateStore_EnsureService_connectProxy(t *testing.T) { 1451 assert := assert.New(t) 1452 s := testStateStore(t) 1453 1454 // Create the service registration. 1455 ns1 := &structs.NodeService{ 1456 Kind: structs.ServiceKindConnectProxy, 1457 ID: "connect-proxy", 1458 Service: "connect-proxy", 1459 Address: "1.1.1.1", 1460 Port: 1111, 1461 Weights: &structs.Weights{ 1462 Passing: 1, 1463 Warning: 1, 1464 }, 1465 Proxy: structs.ConnectProxyConfig{DestinationServiceName: "foo"}, 1466 } 1467 1468 // Service successfully registers into the state store. 1469 testRegisterNode(t, s, 0, "node1") 1470 assert.Nil(s.EnsureService(10, "node1", ns1)) 1471 1472 // Retrieve and verify 1473 _, out, err := s.NodeServices(nil, "node1") 1474 assert.Nil(err) 1475 assert.NotNil(out) 1476 assert.Len(out.Services, 1) 1477 1478 expect1 := *ns1 1479 expect1.CreateIndex, expect1.ModifyIndex = 10, 10 1480 assert.Equal(&expect1, out.Services["connect-proxy"]) 1481 } 1482 1483 func TestStateStore_Services(t *testing.T) { 1484 s := testStateStore(t) 1485 1486 // Listing with no results returns an empty list. 1487 ws := memdb.NewWatchSet() 1488 idx, services, err := s.Services(ws) 1489 if err != nil { 1490 t.Fatalf("err: %s", err) 1491 } 1492 if idx != 0 { 1493 t.Fatalf("bad: %d", idx) 1494 } 1495 if len(services) != 0 { 1496 t.Fatalf("bad: %v", services) 1497 } 1498 1499 // Register several nodes and services. 1500 testRegisterNode(t, s, 1, "node1") 1501 ns1 := &structs.NodeService{ 1502 ID: "service1", 1503 Service: "redis", 1504 Tags: []string{"prod", "master"}, 1505 Address: "1.1.1.1", 1506 Port: 1111, 1507 } 1508 if err := s.EnsureService(2, "node1", ns1); err != nil { 1509 t.Fatalf("err: %s", err) 1510 } 1511 testRegisterService(t, s, 3, "node1", "dogs") 1512 testRegisterNode(t, s, 4, "node2") 1513 ns2 := &structs.NodeService{ 1514 ID: "service3", 1515 Service: "redis", 1516 Tags: []string{"prod", "slave"}, 1517 Address: "1.1.1.1", 1518 Port: 1111, 1519 } 1520 if err := s.EnsureService(5, "node2", ns2); err != nil { 1521 t.Fatalf("err: %s", err) 1522 } 1523 if !watchFired(ws) { 1524 t.Fatalf("bad") 1525 } 1526 1527 // Pull all the services. 1528 ws = memdb.NewWatchSet() 1529 idx, services, err = s.Services(ws) 1530 if err != nil { 1531 t.Fatalf("err: %s", err) 1532 } 1533 if idx != 5 { 1534 t.Fatalf("bad index: %d", idx) 1535 } 1536 1537 // Verify the result. We sort the lists since the order is 1538 // non-deterministic (it's built using a map internally). 1539 expected := structs.Services{ 1540 "redis": []string{"prod", "master", "slave"}, 1541 "dogs": []string{}, 1542 } 1543 sort.Strings(expected["redis"]) 1544 for _, tags := range services { 1545 sort.Strings(tags) 1546 } 1547 if !reflect.DeepEqual(expected, services) { 1548 t.Fatalf("bad: %#v", services) 1549 } 1550 1551 // Deleting a node with a service should fire the watch. 1552 if err := s.DeleteNode(6, "node1"); err != nil { 1553 t.Fatalf("err: %s", err) 1554 } 1555 if !watchFired(ws) { 1556 t.Fatalf("bad") 1557 } 1558 } 1559 1560 func TestStateStore_ServicesByNodeMeta(t *testing.T) { 1561 s := testStateStore(t) 1562 1563 // Listing with no results returns nil. 1564 ws := memdb.NewWatchSet() 1565 idx, res, err := s.ServicesByNodeMeta(ws, map[string]string{"somekey": "somevalue"}) 1566 if idx != 0 || len(res) != 0 || err != nil { 1567 t.Fatalf("expected (0, nil, nil), got: (%d, %#v, %#v)", idx, res, err) 1568 } 1569 1570 // Create some nodes and services in the state store. 1571 node0 := &structs.Node{Node: "node0", Address: "127.0.0.1", Meta: map[string]string{"role": "client", "common": "1"}} 1572 if err := s.EnsureNode(0, node0); err != nil { 1573 t.Fatalf("err: %v", err) 1574 } 1575 node1 := &structs.Node{Node: "node1", Address: "127.0.0.1", Meta: map[string]string{"role": "server", "common": "1"}} 1576 if err := s.EnsureNode(1, node1); err != nil { 1577 t.Fatalf("err: %v", err) 1578 } 1579 ns1 := &structs.NodeService{ 1580 ID: "service1", 1581 Service: "redis", 1582 Tags: []string{"prod", "master"}, 1583 Address: "1.1.1.1", 1584 Port: 1111, 1585 } 1586 if err := s.EnsureService(2, "node0", ns1); err != nil { 1587 t.Fatalf("err: %s", err) 1588 } 1589 ns2 := &structs.NodeService{ 1590 ID: "service1", 1591 Service: "redis", 1592 Tags: []string{"prod", "slave"}, 1593 Address: "1.1.1.1", 1594 Port: 1111, 1595 } 1596 if err := s.EnsureService(3, "node1", ns2); err != nil { 1597 t.Fatalf("err: %s", err) 1598 } 1599 if !watchFired(ws) { 1600 t.Fatalf("bad") 1601 } 1602 1603 // Filter the services by the first node's meta value. 1604 ws = memdb.NewWatchSet() 1605 _, res, err = s.ServicesByNodeMeta(ws, map[string]string{"role": "client"}) 1606 if err != nil { 1607 t.Fatalf("err: %s", err) 1608 } 1609 expected := structs.Services{ 1610 "redis": []string{"master", "prod"}, 1611 } 1612 sort.Strings(res["redis"]) 1613 if !reflect.DeepEqual(res, expected) { 1614 t.Fatalf("bad: %v %v", res, expected) 1615 } 1616 1617 // Get all services using the common meta value 1618 _, res, err = s.ServicesByNodeMeta(ws, map[string]string{"common": "1"}) 1619 if err != nil { 1620 t.Fatalf("err: %s", err) 1621 } 1622 expected = structs.Services{ 1623 "redis": []string{"master", "prod", "slave"}, 1624 } 1625 sort.Strings(res["redis"]) 1626 if !reflect.DeepEqual(res, expected) { 1627 t.Fatalf("bad: %v %v", res, expected) 1628 } 1629 1630 // Get an empty list for an invalid meta value 1631 _, res, err = s.ServicesByNodeMeta(ws, map[string]string{"invalid": "nope"}) 1632 if err != nil { 1633 t.Fatalf("err: %s", err) 1634 } 1635 expected = structs.Services{} 1636 if !reflect.DeepEqual(res, expected) { 1637 t.Fatalf("bad: %v %v", res, expected) 1638 } 1639 1640 // Get the first node's service instance using multiple meta filters 1641 _, res, err = s.ServicesByNodeMeta(ws, map[string]string{"role": "client", "common": "1"}) 1642 if err != nil { 1643 t.Fatalf("err: %s", err) 1644 } 1645 expected = structs.Services{ 1646 "redis": []string{"master", "prod"}, 1647 } 1648 sort.Strings(res["redis"]) 1649 if !reflect.DeepEqual(res, expected) { 1650 t.Fatalf("bad: %v %v", res, expected) 1651 } 1652 1653 // Sanity check the watch before we proceed. 1654 if watchFired(ws) { 1655 t.Fatalf("bad") 1656 } 1657 1658 // Registering some unrelated node + service should not fire the watch. 1659 testRegisterNode(t, s, 4, "nope") 1660 testRegisterService(t, s, 5, "nope", "nope") 1661 if watchFired(ws) { 1662 t.Fatalf("bad") 1663 } 1664 1665 // Overwhelm the service tracking. 1666 idx = 6 1667 for i := 0; i < 2*watchLimit; i++ { 1668 node := fmt.Sprintf("many%d", i) 1669 testRegisterNodeWithMeta(t, s, idx, node, map[string]string{"common": "1"}) 1670 idx++ 1671 testRegisterService(t, s, idx, node, "nope") 1672 idx++ 1673 } 1674 1675 // Now get a fresh watch, which will be forced to watch the whole 1676 // service table. 1677 ws = memdb.NewWatchSet() 1678 _, _, err = s.ServicesByNodeMeta(ws, map[string]string{"common": "1"}) 1679 if err != nil { 1680 t.Fatalf("err: %s", err) 1681 } 1682 1683 // Registering some unrelated node + service should not fire the watch. 1684 testRegisterService(t, s, idx, "nope", "more-nope") 1685 if !watchFired(ws) { 1686 t.Fatalf("bad") 1687 } 1688 } 1689 1690 func TestStateStore_ServiceNodes(t *testing.T) { 1691 s := testStateStore(t) 1692 1693 // Listing with no results returns an empty list. 1694 ws := memdb.NewWatchSet() 1695 idx, nodes, err := s.ServiceNodes(ws, "db") 1696 if err != nil { 1697 t.Fatalf("err: %s", err) 1698 } 1699 if idx != 0 { 1700 t.Fatalf("bad: %d", idx) 1701 } 1702 if len(nodes) != 0 { 1703 t.Fatalf("bad: %v", nodes) 1704 } 1705 1706 // Create some nodes and services. 1707 if err := s.EnsureNode(10, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 1708 t.Fatalf("err: %v", err) 1709 } 1710 if err := s.EnsureNode(11, &structs.Node{Node: "bar", Address: "127.0.0.2"}); err != nil { 1711 t.Fatalf("err: %v", err) 1712 } 1713 if err := s.EnsureService(12, "foo", &structs.NodeService{ID: "api", Service: "api", Tags: nil, Address: "", Port: 5000}); err != nil { 1714 t.Fatalf("err: %v", err) 1715 } 1716 if err := s.EnsureService(13, "bar", &structs.NodeService{ID: "api", Service: "api", Tags: nil, Address: "", Port: 5000}); err != nil { 1717 t.Fatalf("err: %v", err) 1718 } 1719 if err := s.EnsureService(14, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { 1720 t.Fatalf("err: %v", err) 1721 } 1722 if err := s.EnsureService(15, "bar", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"slave"}, Address: "", Port: 8000}); err != nil { 1723 t.Fatalf("err: %v", err) 1724 } 1725 if err := s.EnsureService(16, "bar", &structs.NodeService{ID: "db2", Service: "db", Tags: []string{"slave"}, Address: "", Port: 8001}); err != nil { 1726 t.Fatalf("err: %v", err) 1727 } 1728 if !watchFired(ws) { 1729 t.Fatalf("bad") 1730 } 1731 1732 // Read everything back. 1733 ws = memdb.NewWatchSet() 1734 idx, nodes, err = s.ServiceNodes(ws, "db") 1735 if err != nil { 1736 t.Fatalf("err: %s", err) 1737 } 1738 if idx != 16 { 1739 t.Fatalf("bad: %d", idx) 1740 } 1741 if len(nodes) != 3 { 1742 t.Fatalf("bad: %v", nodes) 1743 } 1744 if nodes[0].Node != "bar" { 1745 t.Fatalf("bad: %v", nodes) 1746 } 1747 if nodes[0].Address != "127.0.0.2" { 1748 t.Fatalf("bad: %v", nodes) 1749 } 1750 if nodes[0].ServiceID != "db" { 1751 t.Fatalf("bad: %v", nodes) 1752 } 1753 if !lib.StrContains(nodes[0].ServiceTags, "slave") { 1754 t.Fatalf("bad: %v", nodes) 1755 } 1756 if nodes[0].ServicePort != 8000 { 1757 t.Fatalf("bad: %v", nodes) 1758 } 1759 if nodes[1].Node != "bar" { 1760 t.Fatalf("bad: %v", nodes) 1761 } 1762 if nodes[1].Address != "127.0.0.2" { 1763 t.Fatalf("bad: %v", nodes) 1764 } 1765 if nodes[1].ServiceID != "db2" { 1766 t.Fatalf("bad: %v", nodes) 1767 } 1768 if !lib.StrContains(nodes[1].ServiceTags, "slave") { 1769 t.Fatalf("bad: %v", nodes) 1770 } 1771 if nodes[1].ServicePort != 8001 { 1772 t.Fatalf("bad: %v", nodes) 1773 } 1774 if nodes[2].Node != "foo" { 1775 t.Fatalf("bad: %v", nodes) 1776 } 1777 if nodes[2].Address != "127.0.0.1" { 1778 t.Fatalf("bad: %v", nodes) 1779 } 1780 if nodes[2].ServiceID != "db" { 1781 t.Fatalf("bad: %v", nodes) 1782 } 1783 if !lib.StrContains(nodes[2].ServiceTags, "master") { 1784 t.Fatalf("bad: %v", nodes) 1785 } 1786 if nodes[2].ServicePort != 8000 { 1787 t.Fatalf("bad: %v", nodes) 1788 } 1789 1790 // Registering some unrelated node should not fire the watch. 1791 testRegisterNode(t, s, 17, "nope") 1792 if watchFired(ws) { 1793 t.Fatalf("bad") 1794 } 1795 1796 // But removing a node with the "db" service should fire the watch. 1797 if err := s.DeleteNode(18, "bar"); err != nil { 1798 t.Fatalf("err: %s", err) 1799 } 1800 if !watchFired(ws) { 1801 t.Fatalf("bad") 1802 } 1803 1804 // Overwhelm the node tracking. 1805 idx = 19 1806 for i := 0; i < 2*watchLimit; i++ { 1807 node := fmt.Sprintf("many%d", i) 1808 if err := s.EnsureNode(idx, &structs.Node{Node: node, Address: "127.0.0.1"}); err != nil { 1809 t.Fatalf("err: %v", err) 1810 } 1811 if err := s.EnsureService(idx, node, &structs.NodeService{ID: "db", Service: "db", Port: 8000}); err != nil { 1812 t.Fatalf("err: %v", err) 1813 } 1814 idx++ 1815 } 1816 1817 // Now get a fresh watch, which will be forced to watch the whole nodes 1818 // table. 1819 ws = memdb.NewWatchSet() 1820 _, _, err = s.ServiceNodes(ws, "db") 1821 if err != nil { 1822 t.Fatalf("err: %s", err) 1823 } 1824 1825 // Registering some unrelated node should fire the watch now. 1826 testRegisterNode(t, s, idx, "more-nope") 1827 if !watchFired(ws) { 1828 t.Fatalf("bad") 1829 } 1830 } 1831 1832 func TestStateStore_ServiceTagNodes(t *testing.T) { 1833 s := testStateStore(t) 1834 1835 // Listing with no results returns an empty list. 1836 ws := memdb.NewWatchSet() 1837 idx, nodes, err := s.ServiceTagNodes(ws, "db", []string{"master"}) 1838 if err != nil { 1839 t.Fatalf("err: %s", err) 1840 } 1841 if idx != 0 { 1842 t.Fatalf("bad: %d", idx) 1843 } 1844 if len(nodes) != 0 { 1845 t.Fatalf("bad: %v", nodes) 1846 } 1847 1848 // Create some nodes and services. 1849 if err := s.EnsureNode(15, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 1850 t.Fatalf("err: %v", err) 1851 } 1852 if err := s.EnsureNode(16, &structs.Node{Node: "bar", Address: "127.0.0.2"}); err != nil { 1853 t.Fatalf("err: %v", err) 1854 } 1855 if err := s.EnsureService(17, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { 1856 t.Fatalf("err: %v", err) 1857 } 1858 if err := s.EnsureService(18, "foo", &structs.NodeService{ID: "db2", Service: "db", Tags: []string{"slave"}, Address: "", Port: 8001}); err != nil { 1859 t.Fatalf("err: %v", err) 1860 } 1861 if err := s.EnsureService(19, "bar", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"slave"}, Address: "", Port: 8000}); err != nil { 1862 t.Fatalf("err: %v", err) 1863 } 1864 if !watchFired(ws) { 1865 t.Fatalf("bad") 1866 } 1867 1868 // Read everything back. 1869 ws = memdb.NewWatchSet() 1870 idx, nodes, err = s.ServiceTagNodes(ws, "db", []string{"master"}) 1871 if err != nil { 1872 t.Fatalf("err: %s", err) 1873 } 1874 if idx != 19 { 1875 t.Fatalf("bad: %v", idx) 1876 } 1877 if len(nodes) != 1 { 1878 t.Fatalf("bad: %v", nodes) 1879 } 1880 if nodes[0].Node != "foo" { 1881 t.Fatalf("bad: %v", nodes) 1882 } 1883 if nodes[0].Address != "127.0.0.1" { 1884 t.Fatalf("bad: %v", nodes) 1885 } 1886 if !lib.StrContains(nodes[0].ServiceTags, "master") { 1887 t.Fatalf("bad: %v", nodes) 1888 } 1889 if nodes[0].ServicePort != 8000 { 1890 t.Fatalf("bad: %v", nodes) 1891 } 1892 1893 // Registering some unrelated node should not fire the watch. 1894 testRegisterNode(t, s, 20, "nope") 1895 if watchFired(ws) { 1896 t.Fatalf("bad") 1897 } 1898 1899 // But removing a node with the "db:master" service should fire the watch. 1900 if err := s.DeleteNode(21, "foo"); err != nil { 1901 t.Fatalf("err: %s", err) 1902 } 1903 if !watchFired(ws) { 1904 t.Fatalf("bad") 1905 } 1906 } 1907 1908 func TestStateStore_ServiceTagNodes_MultipleTags(t *testing.T) { 1909 s := testStateStore(t) 1910 1911 if err := s.EnsureNode(15, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 1912 t.Fatalf("err: %v", err) 1913 } 1914 1915 if err := s.EnsureNode(16, &structs.Node{Node: "bar", Address: "127.0.0.2"}); err != nil { 1916 t.Fatalf("err: %v", err) 1917 } 1918 1919 if err := s.EnsureService(17, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"master", "v2"}, Address: "", Port: 8000}); err != nil { 1920 t.Fatalf("err: %v", err) 1921 } 1922 1923 if err := s.EnsureService(18, "foo", &structs.NodeService{ID: "db2", Service: "db", Tags: []string{"slave", "v2", "dev"}, Address: "", Port: 8001}); err != nil { 1924 t.Fatalf("err: %v", err) 1925 } 1926 1927 if err := s.EnsureService(19, "bar", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"slave", "v2"}, Address: "", Port: 8000}); err != nil { 1928 t.Fatalf("err: %v", err) 1929 } 1930 1931 idx, nodes, err := s.ServiceTagNodes(nil, "db", []string{"master"}) 1932 require.NoError(t, err) 1933 require.Equal(t, int(idx), 19) 1934 require.Len(t, nodes, 1) 1935 require.Equal(t, nodes[0].Node, "foo") 1936 require.Equal(t, nodes[0].Address, "127.0.0.1") 1937 require.Contains(t, nodes[0].ServiceTags, "master") 1938 require.Equal(t, nodes[0].ServicePort, 8000) 1939 1940 idx, nodes, err = s.ServiceTagNodes(nil, "db", []string{"v2"}) 1941 require.NoError(t, err) 1942 require.Equal(t, int(idx), 19) 1943 require.Len(t, nodes, 3) 1944 1945 // Test filtering on multiple tags 1946 idx, nodes, err = s.ServiceTagNodes(nil, "db", []string{"v2", "slave"}) 1947 require.NoError(t, err) 1948 require.Equal(t, int(idx), 19) 1949 require.Len(t, nodes, 2) 1950 require.Contains(t, nodes[0].ServiceTags, "v2") 1951 require.Contains(t, nodes[0].ServiceTags, "slave") 1952 require.Contains(t, nodes[1].ServiceTags, "v2") 1953 require.Contains(t, nodes[1].ServiceTags, "slave") 1954 1955 idx, nodes, err = s.ServiceTagNodes(nil, "db", []string{"dev"}) 1956 require.NoError(t, err) 1957 require.Equal(t, int(idx), 19) 1958 require.Len(t, nodes, 1) 1959 require.Equal(t, nodes[0].Node, "foo") 1960 require.Equal(t, nodes[0].Address, "127.0.0.1") 1961 require.Contains(t, nodes[0].ServiceTags, "dev") 1962 require.Equal(t, nodes[0].ServicePort, 8001) 1963 } 1964 1965 func TestStateStore_DeleteService(t *testing.T) { 1966 s := testStateStore(t) 1967 1968 // Register a node with one service and a check. 1969 testRegisterNode(t, s, 1, "node1") 1970 testRegisterService(t, s, 2, "node1", "service1") 1971 testRegisterCheck(t, s, 3, "node1", "service1", "check1", api.HealthPassing) 1972 1973 // Delete the service. 1974 ws := memdb.NewWatchSet() 1975 _, _, err := s.NodeServices(ws, "node1") 1976 if err := s.DeleteService(4, "node1", "service1"); err != nil { 1977 t.Fatalf("err: %s", err) 1978 } 1979 if !watchFired(ws) { 1980 t.Fatalf("bad") 1981 } 1982 1983 // Service doesn't exist. 1984 ws = memdb.NewWatchSet() 1985 _, ns, err := s.NodeServices(ws, "node1") 1986 if err != nil || ns == nil || len(ns.Services) != 0 { 1987 t.Fatalf("bad: %#v (err: %#v)", ns, err) 1988 } 1989 1990 // Check doesn't exist. Check using the raw DB so we can test 1991 // that it actually is removed in the state store. 1992 tx := s.db.Txn(false) 1993 defer tx.Abort() 1994 check, err := tx.First("checks", "id", "node1", "check1") 1995 if err != nil || check != nil { 1996 t.Fatalf("bad: %#v (err: %s)", check, err) 1997 } 1998 1999 // Index tables were updated. 2000 if idx := s.maxIndex("services"); idx != 4 { 2001 t.Fatalf("bad index: %d", idx) 2002 } 2003 if idx := s.maxIndex("checks"); idx != 4 { 2004 t.Fatalf("bad index: %d", idx) 2005 } 2006 2007 // Deleting a nonexistent service should be idempotent and not return an 2008 // error, nor fire a watch. 2009 if err := s.DeleteService(5, "node1", "service1"); err != nil { 2010 t.Fatalf("err: %s", err) 2011 } 2012 if idx := s.maxIndex("services"); idx != 4 { 2013 t.Fatalf("bad index: %d", idx) 2014 } 2015 if watchFired(ws) { 2016 t.Fatalf("bad") 2017 } 2018 } 2019 2020 func TestStateStore_ConnectServiceNodes(t *testing.T) { 2021 assert := assert.New(t) 2022 s := testStateStore(t) 2023 2024 // Listing with no results returns an empty list. 2025 ws := memdb.NewWatchSet() 2026 idx, nodes, err := s.ConnectServiceNodes(ws, "db") 2027 assert.Nil(err) 2028 assert.Equal(idx, uint64(0)) 2029 assert.Len(nodes, 0) 2030 2031 // Create some nodes and services. 2032 assert.Nil(s.EnsureNode(10, &structs.Node{Node: "foo", Address: "127.0.0.1"})) 2033 assert.Nil(s.EnsureNode(11, &structs.Node{Node: "bar", Address: "127.0.0.2"})) 2034 assert.Nil(s.EnsureService(12, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: nil, Address: "", Port: 5000})) 2035 assert.Nil(s.EnsureService(13, "bar", &structs.NodeService{ID: "api", Service: "api", Tags: nil, Address: "", Port: 5000})) 2036 assert.Nil(s.EnsureService(14, "foo", &structs.NodeService{Kind: structs.ServiceKindConnectProxy, ID: "proxy", Service: "proxy", Proxy: structs.ConnectProxyConfig{DestinationServiceName: "db"}, Port: 8000})) 2037 assert.Nil(s.EnsureService(15, "bar", &structs.NodeService{Kind: structs.ServiceKindConnectProxy, ID: "proxy", Service: "proxy", Proxy: structs.ConnectProxyConfig{DestinationServiceName: "db"}, Port: 8000})) 2038 assert.Nil(s.EnsureService(16, "bar", &structs.NodeService{ID: "native-db", Service: "db", Connect: structs.ServiceConnect{Native: true}})) 2039 assert.Nil(s.EnsureService(17, "bar", &structs.NodeService{ID: "db2", Service: "db", Tags: []string{"slave"}, Address: "", Port: 8001})) 2040 assert.True(watchFired(ws)) 2041 2042 // Read everything back. 2043 ws = memdb.NewWatchSet() 2044 idx, nodes, err = s.ConnectServiceNodes(ws, "db") 2045 assert.Nil(err) 2046 assert.Equal(idx, uint64(idx)) 2047 assert.Len(nodes, 3) 2048 2049 for _, n := range nodes { 2050 assert.True( 2051 n.ServiceKind == structs.ServiceKindConnectProxy || 2052 n.ServiceConnect.Native, 2053 "either proxy or connect native") 2054 } 2055 2056 // Registering some unrelated node should not fire the watch. 2057 testRegisterNode(t, s, 17, "nope") 2058 assert.False(watchFired(ws)) 2059 2060 // But removing a node with the "db" service should fire the watch. 2061 assert.Nil(s.DeleteNode(18, "bar")) 2062 assert.True(watchFired(ws)) 2063 } 2064 2065 func TestStateStore_Service_Snapshot(t *testing.T) { 2066 s := testStateStore(t) 2067 2068 // Register a node with two services. 2069 testRegisterNode(t, s, 0, "node1") 2070 ns := []*structs.NodeService{ 2071 &structs.NodeService{ 2072 ID: "service1", 2073 Service: "redis", 2074 Tags: []string{"prod"}, 2075 Address: "1.1.1.1", 2076 Port: 1111, 2077 Weights: &structs.Weights{Passing: 1, Warning: 0}, 2078 }, 2079 &structs.NodeService{ 2080 ID: "service2", 2081 Service: "nomad", 2082 Tags: []string{"dev"}, 2083 Address: "1.1.1.2", 2084 Port: 1112, 2085 Weights: &structs.Weights{Passing: 1, Warning: 1}, 2086 }, 2087 } 2088 for i, svc := range ns { 2089 if err := s.EnsureService(uint64(i+1), "node1", svc); err != nil { 2090 t.Fatalf("err: %s", err) 2091 } 2092 } 2093 2094 // Create a second node/service to make sure node filtering works. This 2095 // will affect the index but not the dump. 2096 testRegisterNode(t, s, 3, "node2") 2097 testRegisterService(t, s, 4, "node2", "service2") 2098 2099 // Snapshot the service. 2100 snap := s.Snapshot() 2101 defer snap.Close() 2102 2103 // Alter the real state store. 2104 testRegisterService(t, s, 5, "node2", "service3") 2105 2106 // Verify the snapshot. 2107 if idx := snap.LastIndex(); idx != 4 { 2108 t.Fatalf("bad index: %d", idx) 2109 } 2110 services, err := snap.Services("node1") 2111 if err != nil { 2112 t.Fatalf("err: %s", err) 2113 } 2114 for i := 0; i < len(ns); i++ { 2115 svc := services.Next().(*structs.ServiceNode) 2116 if svc == nil { 2117 t.Fatalf("unexpected end of services") 2118 } 2119 2120 ns[i].CreateIndex, ns[i].ModifyIndex = uint64(i+1), uint64(i+1) 2121 if !reflect.DeepEqual(ns[i], svc.ToNodeService()) { 2122 t.Fatalf("bad: %#v != %#v", svc, ns[i]) 2123 } 2124 } 2125 if services.Next() != nil { 2126 t.Fatalf("unexpected extra services") 2127 } 2128 } 2129 2130 func TestStateStore_EnsureCheck(t *testing.T) { 2131 s := testStateStore(t) 2132 2133 // Create a check associated with the node 2134 check := &structs.HealthCheck{ 2135 Node: "node1", 2136 CheckID: "check1", 2137 Name: "redis check", 2138 Status: api.HealthPassing, 2139 Notes: "test check", 2140 Output: "aaa", 2141 ServiceID: "service1", 2142 ServiceName: "redis", 2143 } 2144 2145 // Creating a check without a node returns error 2146 if err := s.EnsureCheck(1, check); err != ErrMissingNode { 2147 t.Fatalf("expected %#v, got: %#v", ErrMissingNode, err) 2148 } 2149 2150 // Register the node 2151 testRegisterNode(t, s, 1, "node1") 2152 2153 // Creating a check with a bad services returns error 2154 if err := s.EnsureCheck(1, check); err != ErrMissingService { 2155 t.Fatalf("expected: %#v, got: %#v", ErrMissingService, err) 2156 } 2157 2158 // Register the service 2159 testRegisterService(t, s, 2, "node1", "service1") 2160 2161 // Inserting the check with the prerequisites succeeds 2162 if err := s.EnsureCheck(3, check); err != nil { 2163 t.Fatalf("err: %s", err) 2164 } 2165 2166 // Retrieve the check and make sure it matches 2167 idx, checks, err := s.NodeChecks(nil, "node1") 2168 if err != nil { 2169 t.Fatalf("err: %s", err) 2170 } 2171 if idx != 3 { 2172 t.Fatalf("bad index: %d", idx) 2173 } 2174 if len(checks) != 1 { 2175 t.Fatalf("wrong number of checks: %d", len(checks)) 2176 } 2177 if !reflect.DeepEqual(checks[0], check) { 2178 t.Fatalf("bad: %#v", checks[0]) 2179 } 2180 2181 testCheckOutput := func(expectedNodeIndex, expectedIndexForCheck uint64, outputTxt string) { 2182 // Check that we successfully updated 2183 idx, checks, err = s.NodeChecks(nil, "node1") 2184 if err != nil { 2185 t.Fatalf("err: %s", err) 2186 } 2187 if idx != expectedNodeIndex { 2188 t.Fatalf("bad index: %d", idx) 2189 } 2190 2191 if len(checks) != 1 { 2192 t.Fatalf("wrong number of checks: %d", len(checks)) 2193 } 2194 if checks[0].Output != outputTxt { 2195 t.Fatalf("wrong check output: %#v", checks[0]) 2196 } 2197 if checks[0].CreateIndex != 3 || checks[0].ModifyIndex != expectedIndexForCheck { 2198 t.Fatalf("bad index: %#v, expectedIndexForCheck:=%v ", checks[0], expectedIndexForCheck) 2199 } 2200 } 2201 // Do not really modify the health check content the health check 2202 check = &structs.HealthCheck{ 2203 Node: "node1", 2204 CheckID: "check1", 2205 Name: "redis check", 2206 Status: api.HealthPassing, 2207 Notes: "test check", 2208 Output: "aaa", 2209 ServiceID: "service1", 2210 ServiceName: "redis", 2211 } 2212 if err := s.EnsureCheck(4, check); err != nil { 2213 t.Fatalf("err: %s", err) 2214 } 2215 testCheckOutput(4, 3, check.Output) 2216 2217 // Do modify the heathcheck 2218 check = &structs.HealthCheck{ 2219 Node: "node1", 2220 CheckID: "check1", 2221 Name: "redis check", 2222 Status: api.HealthPassing, 2223 Notes: "test check", 2224 Output: "bbbmodified", 2225 ServiceID: "service1", 2226 ServiceName: "redis", 2227 } 2228 if err := s.EnsureCheck(5, check); err != nil { 2229 t.Fatalf("err: %s", err) 2230 } 2231 testCheckOutput(5, 5, "bbbmodified") 2232 2233 // Index tables were updated 2234 if idx := s.maxIndex("checks"); idx != 5 { 2235 t.Fatalf("bad index: %d", idx) 2236 } 2237 } 2238 2239 func TestStateStore_EnsureCheck_defaultStatus(t *testing.T) { 2240 s := testStateStore(t) 2241 2242 // Register a node 2243 testRegisterNode(t, s, 1, "node1") 2244 2245 // Create and register a check with no health status 2246 check := &structs.HealthCheck{ 2247 Node: "node1", 2248 CheckID: "check1", 2249 Status: "", 2250 } 2251 if err := s.EnsureCheck(2, check); err != nil { 2252 t.Fatalf("err: %s", err) 2253 } 2254 2255 // Get the check again 2256 _, result, err := s.NodeChecks(nil, "node1") 2257 if err != nil { 2258 t.Fatalf("err: %s", err) 2259 } 2260 2261 // Check that the status was set to the proper default 2262 if len(result) != 1 || result[0].Status != api.HealthCritical { 2263 t.Fatalf("bad: %#v", result) 2264 } 2265 } 2266 2267 func TestStateStore_NodeChecks(t *testing.T) { 2268 s := testStateStore(t) 2269 2270 // Do an initial query for a node that doesn't exist. 2271 ws := memdb.NewWatchSet() 2272 idx, checks, err := s.NodeChecks(ws, "node1") 2273 if err != nil { 2274 t.Fatalf("err: %s", err) 2275 } 2276 if idx != 0 { 2277 t.Fatalf("bad: %d", idx) 2278 } 2279 if len(checks) != 0 { 2280 t.Fatalf("bad: %#v", checks) 2281 } 2282 2283 // Create some nodes and checks. 2284 testRegisterNode(t, s, 0, "node1") 2285 testRegisterService(t, s, 1, "node1", "service1") 2286 testRegisterCheck(t, s, 2, "node1", "service1", "check1", api.HealthPassing) 2287 testRegisterCheck(t, s, 3, "node1", "service1", "check2", api.HealthPassing) 2288 testRegisterNode(t, s, 4, "node2") 2289 testRegisterService(t, s, 5, "node2", "service2") 2290 testRegisterCheck(t, s, 6, "node2", "service2", "check3", api.HealthPassing) 2291 if !watchFired(ws) { 2292 t.Fatalf("bad") 2293 } 2294 2295 // Try querying for all checks associated with node1 2296 ws = memdb.NewWatchSet() 2297 idx, checks, err = s.NodeChecks(ws, "node1") 2298 if err != nil { 2299 t.Fatalf("err: %s", err) 2300 } 2301 if idx != 6 { 2302 t.Fatalf("bad index: %d", idx) 2303 } 2304 if len(checks) != 2 || checks[0].CheckID != "check1" || checks[1].CheckID != "check2" { 2305 t.Fatalf("bad checks: %#v", checks) 2306 } 2307 2308 // Creating some unrelated node should not fire the watch. 2309 testRegisterNode(t, s, 7, "node3") 2310 testRegisterCheck(t, s, 8, "node3", "", "check1", api.HealthPassing) 2311 if watchFired(ws) { 2312 t.Fatalf("bad") 2313 } 2314 2315 // Try querying for all checks associated with node2 2316 ws = memdb.NewWatchSet() 2317 idx, checks, err = s.NodeChecks(ws, "node2") 2318 if err != nil { 2319 t.Fatalf("err: %s", err) 2320 } 2321 if idx != 8 { 2322 t.Fatalf("bad index: %d", idx) 2323 } 2324 if len(checks) != 1 || checks[0].CheckID != "check3" { 2325 t.Fatalf("bad checks: %#v", checks) 2326 } 2327 2328 // Changing node2 should fire the watch. 2329 testRegisterCheck(t, s, 9, "node2", "service2", "check3", api.HealthCritical) 2330 if !watchFired(ws) { 2331 t.Fatalf("bad") 2332 } 2333 } 2334 2335 func TestStateStore_ServiceChecks(t *testing.T) { 2336 s := testStateStore(t) 2337 2338 // Do an initial query for a service that doesn't exist. 2339 ws := memdb.NewWatchSet() 2340 idx, checks, err := s.ServiceChecks(ws, "service1") 2341 if err != nil { 2342 t.Fatalf("err: %s", err) 2343 } 2344 if idx != 0 { 2345 t.Fatalf("bad: %d", idx) 2346 } 2347 if len(checks) != 0 { 2348 t.Fatalf("bad: %#v", checks) 2349 } 2350 2351 // Create some nodes and checks. 2352 testRegisterNode(t, s, 0, "node1") 2353 testRegisterService(t, s, 1, "node1", "service1") 2354 testRegisterCheck(t, s, 2, "node1", "service1", "check1", api.HealthPassing) 2355 testRegisterCheck(t, s, 3, "node1", "service1", "check2", api.HealthPassing) 2356 testRegisterNode(t, s, 4, "node2") 2357 testRegisterService(t, s, 5, "node2", "service2") 2358 testRegisterCheck(t, s, 6, "node2", "service2", "check3", api.HealthPassing) 2359 if !watchFired(ws) { 2360 t.Fatalf("bad") 2361 } 2362 2363 // Try querying for all checks associated with service1. 2364 ws = memdb.NewWatchSet() 2365 idx, checks, err = s.ServiceChecks(ws, "service1") 2366 if err != nil { 2367 t.Fatalf("err: %s", err) 2368 } 2369 if idx != 6 { 2370 t.Fatalf("bad index: %d", idx) 2371 } 2372 if len(checks) != 2 || checks[0].CheckID != "check1" || checks[1].CheckID != "check2" { 2373 t.Fatalf("bad checks: %#v", checks) 2374 } 2375 2376 // Adding some unrelated service + check should not fire the watch. 2377 testRegisterService(t, s, 7, "node1", "service3") 2378 testRegisterCheck(t, s, 8, "node1", "service3", "check3", api.HealthPassing) 2379 if watchFired(ws) { 2380 t.Fatalf("bad") 2381 } 2382 2383 // Updating a related check should fire the watch. 2384 testRegisterCheck(t, s, 9, "node1", "service1", "check2", api.HealthCritical) 2385 if !watchFired(ws) { 2386 t.Fatalf("bad") 2387 } 2388 } 2389 2390 func TestStateStore_ServiceChecksByNodeMeta(t *testing.T) { 2391 s := testStateStore(t) 2392 2393 // Querying with no results returns nil. 2394 ws := memdb.NewWatchSet() 2395 idx, checks, err := s.ServiceChecksByNodeMeta(ws, "service1", nil) 2396 if err != nil { 2397 t.Fatalf("err: %s", err) 2398 } 2399 if idx != 0 { 2400 t.Fatalf("bad: %d", idx) 2401 } 2402 if len(checks) != 0 { 2403 t.Fatalf("bad: %#v", checks) 2404 } 2405 2406 // Create some nodes and checks. 2407 testRegisterNodeWithMeta(t, s, 0, "node1", map[string]string{"somekey": "somevalue", "common": "1"}) 2408 testRegisterService(t, s, 1, "node1", "service1") 2409 testRegisterCheck(t, s, 2, "node1", "service1", "check1", api.HealthPassing) 2410 testRegisterCheck(t, s, 3, "node1", "service1", "check2", api.HealthPassing) 2411 testRegisterNodeWithMeta(t, s, 4, "node2", map[string]string{"common": "1"}) 2412 testRegisterService(t, s, 5, "node2", "service1") 2413 testRegisterCheck(t, s, 6, "node2", "service1", "check3", api.HealthPassing) 2414 if !watchFired(ws) { 2415 t.Fatalf("bad") 2416 } 2417 2418 cases := []struct { 2419 filters map[string]string 2420 checks []string 2421 }{ 2422 // Basic meta filter 2423 { 2424 filters: map[string]string{"somekey": "somevalue"}, 2425 checks: []string{"check1", "check2"}, 2426 }, 2427 // Common meta field 2428 { 2429 filters: map[string]string{"common": "1"}, 2430 checks: []string{"check1", "check2", "check3"}, 2431 }, 2432 // Invalid meta filter 2433 { 2434 filters: map[string]string{"invalid": "nope"}, 2435 checks: []string{}, 2436 }, 2437 // Multiple filters 2438 { 2439 filters: map[string]string{"somekey": "somevalue", "common": "1"}, 2440 checks: []string{"check1", "check2"}, 2441 }, 2442 } 2443 2444 // Try querying for all checks associated with service1. 2445 idx = 7 2446 for _, tc := range cases { 2447 ws = memdb.NewWatchSet() 2448 _, checks, err := s.ServiceChecksByNodeMeta(ws, "service1", tc.filters) 2449 if err != nil { 2450 t.Fatalf("err: %s", err) 2451 } 2452 if len(checks) != len(tc.checks) { 2453 t.Fatalf("bad checks: %#v", checks) 2454 } 2455 for i, check := range checks { 2456 if check.CheckID != types.CheckID(tc.checks[i]) { 2457 t.Fatalf("bad checks: %#v", checks) 2458 } 2459 } 2460 2461 // Registering some unrelated node should not fire the watch. 2462 testRegisterNode(t, s, idx, fmt.Sprintf("nope%d", idx)) 2463 idx++ 2464 if watchFired(ws) { 2465 t.Fatalf("bad") 2466 } 2467 } 2468 2469 // Overwhelm the node tracking. 2470 for i := 0; i < 2*watchLimit; i++ { 2471 node := fmt.Sprintf("many%d", idx) 2472 testRegisterNodeWithMeta(t, s, idx, node, map[string]string{"common": "1"}) 2473 idx++ 2474 testRegisterService(t, s, idx, node, "service1") 2475 idx++ 2476 testRegisterCheck(t, s, idx, node, "service1", "check1", api.HealthPassing) 2477 idx++ 2478 } 2479 2480 // Now get a fresh watch, which will be forced to watch the whole 2481 // node table. 2482 ws = memdb.NewWatchSet() 2483 _, _, err = s.ServiceChecksByNodeMeta(ws, "service1", 2484 map[string]string{"common": "1"}) 2485 if err != nil { 2486 t.Fatalf("err: %s", err) 2487 } 2488 2489 // Registering some unrelated node should now fire the watch. 2490 testRegisterNode(t, s, idx, "nope") 2491 if !watchFired(ws) { 2492 t.Fatalf("bad") 2493 } 2494 } 2495 2496 func TestStateStore_ChecksInState(t *testing.T) { 2497 s := testStateStore(t) 2498 2499 // Querying with no results returns nil 2500 ws := memdb.NewWatchSet() 2501 idx, res, err := s.ChecksInState(ws, api.HealthPassing) 2502 if idx != 0 || res != nil || err != nil { 2503 t.Fatalf("expected (0, nil, nil), got: (%d, %#v, %#v)", idx, res, err) 2504 } 2505 2506 // Register a node with checks in varied states 2507 testRegisterNode(t, s, 0, "node1") 2508 testRegisterCheck(t, s, 1, "node1", "", "check1", api.HealthPassing) 2509 testRegisterCheck(t, s, 2, "node1", "", "check2", api.HealthCritical) 2510 testRegisterCheck(t, s, 3, "node1", "", "check3", api.HealthPassing) 2511 if !watchFired(ws) { 2512 t.Fatalf("bad") 2513 } 2514 2515 // Query the state store for passing checks. 2516 ws = memdb.NewWatchSet() 2517 _, checks, err := s.ChecksInState(ws, api.HealthPassing) 2518 if err != nil { 2519 t.Fatalf("err: %s", err) 2520 } 2521 2522 // Make sure we only get the checks which match the state 2523 if n := len(checks); n != 2 { 2524 t.Fatalf("expected 2 checks, got: %d", n) 2525 } 2526 if checks[0].CheckID != "check1" || checks[1].CheckID != "check3" { 2527 t.Fatalf("bad: %#v", checks) 2528 } 2529 if watchFired(ws) { 2530 t.Fatalf("bad") 2531 } 2532 2533 // Changing the state of a check should fire the watch. 2534 testRegisterCheck(t, s, 4, "node1", "", "check1", api.HealthCritical) 2535 if !watchFired(ws) { 2536 t.Fatalf("bad") 2537 } 2538 2539 // HealthAny just returns everything. 2540 ws = memdb.NewWatchSet() 2541 _, checks, err = s.ChecksInState(ws, api.HealthAny) 2542 if err != nil { 2543 t.Fatalf("err: %s", err) 2544 } 2545 if n := len(checks); n != 3 { 2546 t.Fatalf("expected 3 checks, got: %d", n) 2547 } 2548 if watchFired(ws) { 2549 t.Fatalf("bad") 2550 } 2551 2552 // Adding a new check should fire the watch. 2553 testRegisterCheck(t, s, 5, "node1", "", "check4", api.HealthCritical) 2554 if !watchFired(ws) { 2555 t.Fatalf("bad") 2556 } 2557 } 2558 2559 func TestStateStore_ChecksInStateByNodeMeta(t *testing.T) { 2560 s := testStateStore(t) 2561 2562 // Querying with no results returns nil. 2563 ws := memdb.NewWatchSet() 2564 idx, res, err := s.ChecksInStateByNodeMeta(ws, api.HealthPassing, nil) 2565 if idx != 0 || res != nil || err != nil { 2566 t.Fatalf("expected (0, nil, nil), got: (%d, %#v, %#v)", idx, res, err) 2567 } 2568 2569 // Register a node with checks in varied states. 2570 testRegisterNodeWithMeta(t, s, 0, "node1", map[string]string{"somekey": "somevalue", "common": "1"}) 2571 testRegisterCheck(t, s, 1, "node1", "", "check1", api.HealthPassing) 2572 testRegisterCheck(t, s, 2, "node1", "", "check2", api.HealthCritical) 2573 testRegisterNodeWithMeta(t, s, 3, "node2", map[string]string{"common": "1"}) 2574 testRegisterCheck(t, s, 4, "node2", "", "check3", api.HealthPassing) 2575 if !watchFired(ws) { 2576 t.Fatalf("bad") 2577 } 2578 2579 cases := []struct { 2580 filters map[string]string 2581 state string 2582 checks []string 2583 }{ 2584 // Basic meta filter, any status 2585 { 2586 filters: map[string]string{"somekey": "somevalue"}, 2587 state: api.HealthAny, 2588 checks: []string{"check2", "check1"}, 2589 }, 2590 // Basic meta filter, only passing 2591 { 2592 filters: map[string]string{"somekey": "somevalue"}, 2593 state: api.HealthPassing, 2594 checks: []string{"check1"}, 2595 }, 2596 // Common meta filter, any status 2597 { 2598 filters: map[string]string{"common": "1"}, 2599 state: api.HealthAny, 2600 checks: []string{"check2", "check1", "check3"}, 2601 }, 2602 // Common meta filter, only passing 2603 { 2604 filters: map[string]string{"common": "1"}, 2605 state: api.HealthPassing, 2606 checks: []string{"check1", "check3"}, 2607 }, 2608 // Invalid meta filter 2609 { 2610 filters: map[string]string{"invalid": "nope"}, 2611 checks: []string{}, 2612 }, 2613 // Multiple filters, any status 2614 { 2615 filters: map[string]string{"somekey": "somevalue", "common": "1"}, 2616 state: api.HealthAny, 2617 checks: []string{"check2", "check1"}, 2618 }, 2619 // Multiple filters, only passing 2620 { 2621 filters: map[string]string{"somekey": "somevalue", "common": "1"}, 2622 state: api.HealthPassing, 2623 checks: []string{"check1"}, 2624 }, 2625 } 2626 2627 // Try querying for all checks associated with service1. 2628 idx = 5 2629 for _, tc := range cases { 2630 ws = memdb.NewWatchSet() 2631 _, checks, err := s.ChecksInStateByNodeMeta(ws, tc.state, tc.filters) 2632 if err != nil { 2633 t.Fatalf("err: %s", err) 2634 } 2635 if len(checks) != len(tc.checks) { 2636 t.Fatalf("bad checks: %#v", checks) 2637 } 2638 for i, check := range checks { 2639 if check.CheckID != types.CheckID(tc.checks[i]) { 2640 t.Fatalf("bad checks: %#v, %v", checks, tc.checks) 2641 } 2642 } 2643 2644 // Registering some unrelated node should not fire the watch. 2645 testRegisterNode(t, s, idx, fmt.Sprintf("nope%d", idx)) 2646 idx++ 2647 if watchFired(ws) { 2648 t.Fatalf("bad") 2649 } 2650 } 2651 2652 // Overwhelm the node tracking. 2653 for i := 0; i < 2*watchLimit; i++ { 2654 node := fmt.Sprintf("many%d", idx) 2655 testRegisterNodeWithMeta(t, s, idx, node, map[string]string{"common": "1"}) 2656 idx++ 2657 testRegisterService(t, s, idx, node, "service1") 2658 idx++ 2659 testRegisterCheck(t, s, idx, node, "service1", "check1", api.HealthPassing) 2660 idx++ 2661 } 2662 2663 // Now get a fresh watch, which will be forced to watch the whole 2664 // node table. 2665 ws = memdb.NewWatchSet() 2666 _, _, err = s.ChecksInStateByNodeMeta(ws, api.HealthPassing, 2667 map[string]string{"common": "1"}) 2668 if err != nil { 2669 t.Fatalf("err: %s", err) 2670 } 2671 2672 // Registering some unrelated node should now fire the watch. 2673 testRegisterNode(t, s, idx, "nope") 2674 if !watchFired(ws) { 2675 t.Fatalf("bad") 2676 } 2677 } 2678 2679 func TestStateStore_DeleteCheck(t *testing.T) { 2680 s := testStateStore(t) 2681 2682 // Register a node and a node-level health check. 2683 testRegisterNode(t, s, 1, "node1") 2684 testRegisterCheck(t, s, 2, "node1", "", "check1", api.HealthPassing) 2685 testRegisterService(t, s, 2, "node1", "service1") 2686 2687 // Make sure the check is there. 2688 ws := memdb.NewWatchSet() 2689 _, checks, err := s.NodeChecks(ws, "node1") 2690 if err != nil { 2691 t.Fatalf("err: %s", err) 2692 } 2693 if len(checks) != 1 { 2694 t.Fatalf("bad: %#v", checks) 2695 } 2696 2697 ensureServiceVersion(t, s, ws, "service1", 2, 1) 2698 2699 // Delete the check. 2700 if err := s.DeleteCheck(3, "node1", "check1"); err != nil { 2701 t.Fatalf("err: %s", err) 2702 } 2703 if idx, check, err := s.NodeCheck("node1", "check1"); idx != 3 || err != nil || check != nil { 2704 t.Fatalf("Node check should have been deleted idx=%d, node=%v, err=%s", idx, check, err) 2705 } 2706 if idx := s.maxIndex("checks"); idx != 3 { 2707 t.Fatalf("bad index for checks: %d", idx) 2708 } 2709 if !watchFired(ws) { 2710 t.Fatalf("bad") 2711 } 2712 // All services linked to this node should have their index updated 2713 ensureServiceVersion(t, s, ws, "service1", 3, 1) 2714 2715 // Check is gone 2716 ws = memdb.NewWatchSet() 2717 _, checks, err = s.NodeChecks(ws, "node1") 2718 if err != nil { 2719 t.Fatalf("err: %s", err) 2720 } 2721 if len(checks) != 0 { 2722 t.Fatalf("bad: %#v", checks) 2723 } 2724 2725 // Index tables were updated. 2726 if idx := s.maxIndex("checks"); idx != 3 { 2727 t.Fatalf("bad index: %d", idx) 2728 } 2729 2730 // Deleting a nonexistent check should be idempotent and not return an 2731 // error. 2732 if err := s.DeleteCheck(4, "node1", "check1"); err != nil { 2733 t.Fatalf("err: %s", err) 2734 } 2735 if idx := s.maxIndex("checks"); idx != 3 { 2736 t.Fatalf("bad index: %d", idx) 2737 } 2738 if watchFired(ws) { 2739 t.Fatalf("bad") 2740 } 2741 } 2742 2743 func ensureServiceVersion(t *testing.T, s *Store, ws memdb.WatchSet, serviceID string, expectedIdx uint64, expectedSize int) { 2744 idx, services, err := s.ServiceNodes(ws, serviceID) 2745 t.Helper() 2746 if err != nil { 2747 t.Fatalf("err: %s", err) 2748 } 2749 if idx != expectedIdx { 2750 t.Fatalf("bad: %d, expected %d", idx, expectedIdx) 2751 } 2752 if len(services) != expectedSize { 2753 t.Fatalf("expected size: %d, but was %d", expectedSize, len(services)) 2754 } 2755 } 2756 2757 // Ensure index exist, if expectedIndex = -1, ensure the index does not exists 2758 func ensureIndexForService(t *testing.T, s *Store, ws memdb.WatchSet, serviceName string, expectedIndex uint64) { 2759 t.Helper() 2760 tx := s.db.Txn(false) 2761 defer tx.Abort() 2762 transaction, err := tx.First("index", "id", fmt.Sprintf("service.%s", serviceName)) 2763 if err == nil { 2764 if idx, ok := transaction.(*IndexEntry); ok { 2765 if expectedIndex != idx.Value { 2766 t.Fatalf("Expected index %d, but had %d for %s", expectedIndex, idx.Value, serviceName) 2767 } 2768 return 2769 } 2770 } 2771 if expectedIndex != 0 { 2772 t.Fatalf("Index for %s was expected but not found", serviceName) 2773 } 2774 } 2775 2776 // TestIndexIndependence test that changes on a given service does not impact the 2777 // index of other services. It allows to have huge benefits for watches since 2778 // watchers are notified ONLY when there are changes in the given service 2779 func TestIndexIndependence(t *testing.T) { 2780 s := testStateStore(t) 2781 2782 // Querying with no matches gives an empty response 2783 ws := memdb.NewWatchSet() 2784 idx, res, err := s.CheckServiceNodes(ws, "service1") 2785 if idx != 0 || res != nil || err != nil { 2786 t.Fatalf("expected (0, nil, nil), got: (%d, %#v, %#v)", idx, res, err) 2787 } 2788 2789 // Register some nodes. 2790 testRegisterNode(t, s, 0, "node1") 2791 testRegisterNode(t, s, 1, "node2") 2792 2793 // Register node-level checks. These should be the final result. 2794 testRegisterCheck(t, s, 2, "node1", "", "check1", api.HealthPassing) 2795 testRegisterCheck(t, s, 3, "node2", "", "check2", api.HealthPassing) 2796 2797 // Register a service against the nodes. 2798 testRegisterService(t, s, 4, "node1", "service1") 2799 testRegisterService(t, s, 5, "node2", "service2") 2800 ensureServiceVersion(t, s, ws, "service2", 5, 1) 2801 2802 // Register checks against the services. 2803 testRegisterCheck(t, s, 6, "node1", "service1", "check3", api.HealthPassing) 2804 testRegisterCheck(t, s, 7, "node2", "service2", "check4", api.HealthPassing) 2805 // Index must be updated when checks are updated 2806 ensureServiceVersion(t, s, ws, "service1", 6, 1) 2807 ensureServiceVersion(t, s, ws, "service2", 7, 1) 2808 2809 if !watchFired(ws) { 2810 t.Fatalf("bad") 2811 } 2812 // We ensure the idx for service2 has not been changed 2813 testRegisterCheck(t, s, 8, "node2", "service2", "check4", api.HealthWarning) 2814 ensureServiceVersion(t, s, ws, "service2", 8, 1) 2815 testRegisterCheck(t, s, 9, "node2", "service2", "check4", api.HealthPassing) 2816 ensureServiceVersion(t, s, ws, "service2", 9, 1) 2817 2818 // Add a new check on node1, while not on service, it should impact 2819 // indexes of all services running on node1, aka service1 2820 testRegisterCheck(t, s, 10, "node1", "", "check_node", api.HealthPassing) 2821 2822 // Service2 should not be modified 2823 ensureServiceVersion(t, s, ws, "service2", 9, 1) 2824 // Service1 should be modified 2825 ensureServiceVersion(t, s, ws, "service1", 10, 1) 2826 2827 if !watchFired(ws) { 2828 t.Fatalf("bad") 2829 } 2830 2831 testRegisterService(t, s, 11, "node1", "service_shared") 2832 ensureServiceVersion(t, s, ws, "service_shared", 11, 1) 2833 testRegisterService(t, s, 12, "node2", "service_shared") 2834 ensureServiceVersion(t, s, ws, "service_shared", 12, 2) 2835 2836 testRegisterCheck(t, s, 13, "node2", "service_shared", "check_service_shared", api.HealthCritical) 2837 ensureServiceVersion(t, s, ws, "service_shared", 13, 2) 2838 testRegisterCheck(t, s, 14, "node2", "service_shared", "check_service_shared", api.HealthPassing) 2839 ensureServiceVersion(t, s, ws, "service_shared", 14, 2) 2840 2841 s.DeleteCheck(15, "node2", types.CheckID("check_service_shared")) 2842 ensureServiceVersion(t, s, ws, "service_shared", 15, 2) 2843 ensureIndexForService(t, s, ws, "service_shared", 15) 2844 s.DeleteService(16, "node2", "service_shared") 2845 ensureServiceVersion(t, s, ws, "service_shared", 16, 1) 2846 ensureIndexForService(t, s, ws, "service_shared", 16) 2847 s.DeleteService(17, "node1", "service_shared") 2848 ensureServiceVersion(t, s, ws, "service_shared", 17, 0) 2849 2850 testRegisterService(t, s, 18, "node1", "service_new") 2851 2852 // Since service does not exists anymore, its index should be that of 2853 // the last deleted service 2854 ensureServiceVersion(t, s, ws, "service_shared", 17, 0) 2855 2856 // No index should exist anymore, it must have been garbage collected 2857 ensureIndexForService(t, s, ws, "service_shared", 0) 2858 if !watchFired(ws) { 2859 t.Fatalf("bad") 2860 } 2861 } 2862 2863 func TestMissingServiceIndex(t *testing.T) { 2864 s := testStateStore(t) 2865 2866 // Querying with no matches gives an empty response 2867 ws := memdb.NewWatchSet() 2868 idx, res, err := s.CheckServiceNodes(ws, "service1") 2869 require.Nil(t, err) 2870 require.Nil(t, res) 2871 2872 // index should be 0 for a non existing service at startup 2873 require.Equal(t, uint64(0), idx) 2874 2875 testRegisterNode(t, s, 0, "node1") 2876 2877 // node operations should not affect missing service index 2878 ensureServiceVersion(t, s, ws, "service1", 0, 0) 2879 2880 testRegisterService(t, s, 10, "node1", "service1") 2881 ensureServiceVersion(t, s, ws, "service1", 10, 1) 2882 2883 s.DeleteService(11, "node1", "service1") 2884 // service1 is now missing, its index is now that of the last index a service was 2885 // deleted at 2886 ensureServiceVersion(t, s, ws, "service1", 11, 0) 2887 2888 testRegisterService(t, s, 12, "node1", "service2") 2889 ensureServiceVersion(t, s, ws, "service2", 12, 1) 2890 2891 // missing service index does not change even though another service have been 2892 // registered 2893 ensureServiceVersion(t, s, ws, "service1", 11, 0) 2894 ensureServiceVersion(t, s, ws, "i_do_not_exist", 11, 0) 2895 2896 // registering a service on another node does not affect missing service 2897 // index 2898 testRegisterNode(t, s, 13, "node2") 2899 testRegisterService(t, s, 14, "node2", "service3") 2900 ensureServiceVersion(t, s, ws, "service3", 14, 1) 2901 ensureServiceVersion(t, s, ws, "service1", 11, 0) 2902 2903 // unregistering a service bumps missing service index 2904 s.DeleteService(15, "node2", "service3") 2905 ensureServiceVersion(t, s, ws, "service3", 15, 0) 2906 ensureServiceVersion(t, s, ws, "service2", 12, 1) 2907 ensureServiceVersion(t, s, ws, "service1", 15, 0) 2908 ensureServiceVersion(t, s, ws, "i_do_not_exist", 15, 0) 2909 2910 // registering again a missing service correctly updates its index 2911 testRegisterService(t, s, 16, "node1", "service1") 2912 ensureServiceVersion(t, s, ws, "service1", 16, 1) 2913 } 2914 2915 func TestStateStore_CheckServiceNodes(t *testing.T) { 2916 s := testStateStore(t) 2917 2918 // Querying with no matches gives an empty response 2919 ws := memdb.NewWatchSet() 2920 idx, res, err := s.CheckServiceNodes(ws, "service1") 2921 if idx != 0 || res != nil || err != nil { 2922 t.Fatalf("expected (0, nil, nil), got: (%d, %#v, %#v)", idx, res, err) 2923 } 2924 2925 // Register some nodes. 2926 testRegisterNode(t, s, 0, "node1") 2927 testRegisterNode(t, s, 1, "node2") 2928 2929 // Register node-level checks. These should be the final result. 2930 testRegisterCheck(t, s, 2, "node1", "", "check1", api.HealthPassing) 2931 testRegisterCheck(t, s, 3, "node2", "", "check2", api.HealthPassing) 2932 2933 // Register a service against the nodes. 2934 testRegisterService(t, s, 4, "node1", "service1") 2935 testRegisterService(t, s, 5, "node2", "service2") 2936 2937 // Register checks against the services. 2938 testRegisterCheck(t, s, 6, "node1", "service1", "check3", api.HealthPassing) 2939 testRegisterCheck(t, s, 7, "node2", "service2", "check4", api.HealthPassing) 2940 2941 // At this point all the changes should have fired the watch. 2942 if !watchFired(ws) { 2943 t.Fatalf("bad") 2944 } 2945 2946 // We ensure the idx for service2 has not been changed 2947 ensureServiceVersion(t, s, ws, "service2", 7, 1) 2948 2949 // Query the state store for nodes and checks which have been registered 2950 // with a specific service. 2951 ws = memdb.NewWatchSet() 2952 ensureServiceVersion(t, s, ws, "service1", 6, 1) 2953 idx, results, err := s.CheckServiceNodes(ws, "service1") 2954 if err != nil { 2955 t.Fatalf("err: %s", err) 2956 } 2957 // registered with ensureServiceVersion(t, s, ws, "service1", 6, 1) 2958 if idx != 6 { 2959 t.Fatalf("bad index: %d", idx) 2960 } 2961 2962 // Make sure we get the expected result (service check + node check). 2963 if n := len(results); n != 1 { 2964 t.Fatalf("expected 1 result, got: %d", n) 2965 } 2966 csn := results[0] 2967 if csn.Node == nil || csn.Service == nil || len(csn.Checks) != 2 || 2968 csn.Checks[0].ServiceID != "" || csn.Checks[0].CheckID != "check1" || 2969 csn.Checks[1].ServiceID != "service1" || csn.Checks[1].CheckID != "check3" { 2970 t.Fatalf("bad output: %#v", csn) 2971 } 2972 2973 // Node updates alter the returned index and fire the watch. 2974 testRegisterNodeWithChange(t, s, 8, "node1") 2975 if !watchFired(ws) { 2976 t.Fatalf("bad") 2977 } 2978 ws = memdb.NewWatchSet() 2979 idx, results, err = s.CheckServiceNodes(ws, "service1") 2980 if err != nil { 2981 t.Fatalf("err: %s", err) 2982 } 2983 // service1 has been registered at idx=6, other different registrations do not count 2984 if idx != 6 { 2985 t.Fatalf("bad index: %d", idx) 2986 } 2987 2988 // Service updates alter the returned index and fire the watch. 2989 2990 testRegisterServiceWithChange(t, s, 9, "node1", "service1", true) 2991 if !watchFired(ws) { 2992 t.Fatalf("bad") 2993 } 2994 ws = memdb.NewWatchSet() 2995 idx, results, err = s.CheckServiceNodes(ws, "service1") 2996 if err != nil { 2997 t.Fatalf("err: %s", err) 2998 } 2999 if idx != 9 { 3000 t.Fatalf("bad index: %d", idx) 3001 } 3002 3003 // Check updates alter the returned index and fire the watch. 3004 testRegisterCheck(t, s, 10, "node1", "service1", "check1", api.HealthCritical) 3005 if !watchFired(ws) { 3006 t.Fatalf("bad") 3007 } 3008 ws = memdb.NewWatchSet() 3009 idx, results, err = s.CheckServiceNodes(ws, "service1") 3010 if err != nil { 3011 t.Fatalf("err: %s", err) 3012 } 3013 if idx != 10 { 3014 t.Fatalf("bad index: %d", idx) 3015 } 3016 3017 // Registering some unrelated node + service should not fire the watch. 3018 testRegisterNode(t, s, 11, "nope") 3019 testRegisterService(t, s, 12, "nope", "nope") 3020 if watchFired(ws) { 3021 t.Fatalf("bad") 3022 } 3023 3024 // Overwhelm node and check tracking. 3025 idx = 13 3026 for i := 0; i < 2*watchLimit; i++ { 3027 node := fmt.Sprintf("many%d", i) 3028 testRegisterNode(t, s, idx, node) 3029 idx++ 3030 testRegisterCheck(t, s, idx, node, "", "check1", api.HealthPassing) 3031 idx++ 3032 testRegisterService(t, s, idx, node, "service1") 3033 idx++ 3034 testRegisterCheck(t, s, idx, node, "service1", "check2", api.HealthPassing) 3035 idx++ 3036 } 3037 3038 // Now registering an unrelated node will fire the watch. 3039 ws = memdb.NewWatchSet() 3040 idx, results, err = s.CheckServiceNodes(ws, "service1") 3041 if err != nil { 3042 t.Fatalf("err: %s", err) 3043 } 3044 testRegisterNode(t, s, idx, "more-nope") 3045 idx++ 3046 if !watchFired(ws) { 3047 t.Fatalf("bad") 3048 } 3049 3050 // Also, registering an unrelated check will fire the watch. 3051 ws = memdb.NewWatchSet() 3052 idx, results, err = s.CheckServiceNodes(ws, "service1") 3053 if err != nil { 3054 t.Fatalf("err: %s", err) 3055 } 3056 testRegisterCheck(t, s, idx, "more-nope", "", "check1", api.HealthPassing) 3057 idx++ 3058 if !watchFired(ws) { 3059 t.Fatalf("bad") 3060 } 3061 } 3062 3063 func TestStateStore_CheckConnectServiceNodes(t *testing.T) { 3064 assert := assert.New(t) 3065 s := testStateStore(t) 3066 3067 // Listing with no results returns an empty list. 3068 ws := memdb.NewWatchSet() 3069 idx, nodes, err := s.CheckConnectServiceNodes(ws, "db") 3070 assert.Nil(err) 3071 assert.Equal(idx, uint64(0)) 3072 assert.Len(nodes, 0) 3073 3074 // Create some nodes and services. 3075 assert.Nil(s.EnsureNode(10, &structs.Node{Node: "foo", Address: "127.0.0.1"})) 3076 assert.Nil(s.EnsureNode(11, &structs.Node{Node: "bar", Address: "127.0.0.2"})) 3077 assert.Nil(s.EnsureService(12, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: nil, Address: "", Port: 5000})) 3078 assert.Nil(s.EnsureService(13, "bar", &structs.NodeService{ID: "api", Service: "api", Tags: nil, Address: "", Port: 5000})) 3079 assert.Nil(s.EnsureService(14, "foo", &structs.NodeService{Kind: structs.ServiceKindConnectProxy, ID: "proxy", Service: "proxy", Proxy: structs.ConnectProxyConfig{DestinationServiceName: "db"}, Port: 8000})) 3080 assert.Nil(s.EnsureService(15, "bar", &structs.NodeService{Kind: structs.ServiceKindConnectProxy, ID: "proxy", Service: "proxy", Proxy: structs.ConnectProxyConfig{DestinationServiceName: "db"}, Port: 8000})) 3081 assert.Nil(s.EnsureService(16, "bar", &structs.NodeService{ID: "db2", Service: "db", Tags: []string{"slave"}, Address: "", Port: 8001})) 3082 assert.True(watchFired(ws)) 3083 3084 // Register node checks 3085 testRegisterCheck(t, s, 17, "foo", "", "check1", api.HealthPassing) 3086 testRegisterCheck(t, s, 18, "bar", "", "check2", api.HealthPassing) 3087 3088 // Register checks against the services. 3089 testRegisterCheck(t, s, 19, "foo", "db", "check3", api.HealthPassing) 3090 testRegisterCheck(t, s, 20, "bar", "proxy", "check4", api.HealthPassing) 3091 3092 // Read everything back. 3093 ws = memdb.NewWatchSet() 3094 idx, nodes, err = s.CheckConnectServiceNodes(ws, "db") 3095 assert.Nil(err) 3096 assert.Equal(idx, uint64(idx)) 3097 assert.Len(nodes, 2) 3098 3099 for _, n := range nodes { 3100 assert.Equal(structs.ServiceKindConnectProxy, n.Service.Kind) 3101 assert.Equal("db", n.Service.Proxy.DestinationServiceName) 3102 } 3103 } 3104 3105 func BenchmarkCheckServiceNodes(b *testing.B) { 3106 s, err := NewStateStore(nil) 3107 if err != nil { 3108 b.Fatalf("err: %s", err) 3109 } 3110 3111 if err := s.EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 3112 b.Fatalf("err: %v", err) 3113 } 3114 if err := s.EnsureService(2, "foo", &structs.NodeService{ID: "db1", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { 3115 b.Fatalf("err: %v", err) 3116 } 3117 check := &structs.HealthCheck{ 3118 Node: "foo", 3119 CheckID: "db", 3120 Name: "can connect", 3121 Status: api.HealthPassing, 3122 ServiceID: "db1", 3123 } 3124 if err := s.EnsureCheck(3, check); err != nil { 3125 b.Fatalf("err: %v", err) 3126 } 3127 check = &structs.HealthCheck{ 3128 Node: "foo", 3129 CheckID: "check1", 3130 Name: "check1", 3131 Status: api.HealthPassing, 3132 } 3133 if err := s.EnsureCheck(4, check); err != nil { 3134 b.Fatalf("err: %v", err) 3135 } 3136 3137 ws := memdb.NewWatchSet() 3138 for i := 0; i < b.N; i++ { 3139 s.CheckServiceNodes(ws, "db") 3140 } 3141 } 3142 3143 func TestStateStore_CheckServiceTagNodes(t *testing.T) { 3144 s := testStateStore(t) 3145 3146 if err := s.EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 3147 t.Fatalf("err: %v", err) 3148 } 3149 if err := s.EnsureService(2, "foo", &structs.NodeService{ID: "db1", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { 3150 t.Fatalf("err: %v", err) 3151 } 3152 check := &structs.HealthCheck{ 3153 Node: "foo", 3154 CheckID: "db", 3155 Name: "can connect", 3156 Status: api.HealthPassing, 3157 ServiceID: "db1", 3158 } 3159 if err := s.EnsureCheck(3, check); err != nil { 3160 t.Fatalf("err: %v", err) 3161 } 3162 check = &structs.HealthCheck{ 3163 Node: "foo", 3164 CheckID: "check1", 3165 Name: "another check", 3166 Status: api.HealthPassing, 3167 } 3168 if err := s.EnsureCheck(4, check); err != nil { 3169 t.Fatalf("err: %v", err) 3170 } 3171 3172 ws := memdb.NewWatchSet() 3173 idx, nodes, err := s.CheckServiceTagNodes(ws, "db", []string{"master"}) 3174 if err != nil { 3175 t.Fatalf("err: %s", err) 3176 } 3177 if idx != 4 { 3178 t.Fatalf("bad: %v", idx) 3179 } 3180 if len(nodes) != 1 { 3181 t.Fatalf("Bad: %v", nodes) 3182 } 3183 if nodes[0].Node.Node != "foo" { 3184 t.Fatalf("Bad: %v", nodes[0]) 3185 } 3186 if nodes[0].Service.ID != "db1" { 3187 t.Fatalf("Bad: %v", nodes[0]) 3188 } 3189 if len(nodes[0].Checks) != 2 { 3190 t.Fatalf("Bad: %v", nodes[0]) 3191 } 3192 if nodes[0].Checks[0].CheckID != "check1" { 3193 t.Fatalf("Bad: %v", nodes[0]) 3194 } 3195 if nodes[0].Checks[1].CheckID != "db" { 3196 t.Fatalf("Bad: %v", nodes[0]) 3197 } 3198 3199 // Changing a tag should fire the watch. 3200 if err := s.EnsureService(4, "foo", &structs.NodeService{ID: "db1", Service: "db", Tags: []string{"nope"}, Address: "", Port: 8000}); err != nil { 3201 t.Fatalf("err: %v", err) 3202 } 3203 if !watchFired(ws) { 3204 t.Fatalf("bad") 3205 } 3206 } 3207 3208 func TestStateStore_Check_Snapshot(t *testing.T) { 3209 s := testStateStore(t) 3210 3211 // Create a node, a service, and a service check as well as a node check. 3212 testRegisterNode(t, s, 0, "node1") 3213 testRegisterService(t, s, 1, "node1", "service1") 3214 checks := structs.HealthChecks{ 3215 &structs.HealthCheck{ 3216 Node: "node1", 3217 CheckID: "check1", 3218 Name: "node check", 3219 Status: api.HealthPassing, 3220 }, 3221 &structs.HealthCheck{ 3222 Node: "node1", 3223 CheckID: "check2", 3224 Name: "service check", 3225 Status: api.HealthCritical, 3226 ServiceID: "service1", 3227 }, 3228 } 3229 for i, hc := range checks { 3230 if err := s.EnsureCheck(uint64(i+1), hc); err != nil { 3231 t.Fatalf("err: %s", err) 3232 } 3233 } 3234 3235 // Create a second node/service to make sure node filtering works. This 3236 // will affect the index but not the dump. 3237 testRegisterNode(t, s, 3, "node2") 3238 testRegisterService(t, s, 4, "node2", "service2") 3239 testRegisterCheck(t, s, 5, "node2", "service2", "check3", api.HealthPassing) 3240 3241 // Snapshot the checks. 3242 snap := s.Snapshot() 3243 defer snap.Close() 3244 3245 // Alter the real state store. 3246 testRegisterCheck(t, s, 6, "node2", "service2", "check4", api.HealthPassing) 3247 3248 // Verify the snapshot. 3249 if idx := snap.LastIndex(); idx != 5 { 3250 t.Fatalf("bad index: %d", idx) 3251 } 3252 iter, err := snap.Checks("node1") 3253 if err != nil { 3254 t.Fatalf("err: %s", err) 3255 } 3256 for i := 0; i < len(checks); i++ { 3257 check := iter.Next().(*structs.HealthCheck) 3258 if check == nil { 3259 t.Fatalf("unexpected end of checks") 3260 } 3261 3262 checks[i].CreateIndex, checks[i].ModifyIndex = uint64(i+1), uint64(i+1) 3263 if !reflect.DeepEqual(check, checks[i]) { 3264 t.Fatalf("bad: %#v != %#v", check, checks[i]) 3265 } 3266 } 3267 if iter.Next() != nil { 3268 t.Fatalf("unexpected extra checks") 3269 } 3270 } 3271 3272 func TestStateStore_NodeInfo_NodeDump(t *testing.T) { 3273 s := testStateStore(t) 3274 3275 // Generating a node dump that matches nothing returns empty 3276 wsInfo := memdb.NewWatchSet() 3277 idx, dump, err := s.NodeInfo(wsInfo, "node1") 3278 if idx != 0 || dump != nil || err != nil { 3279 t.Fatalf("expected (0, nil, nil), got: (%d, %#v, %#v)", idx, dump, err) 3280 } 3281 wsDump := memdb.NewWatchSet() 3282 idx, dump, err = s.NodeDump(wsDump) 3283 if idx != 0 || dump != nil || err != nil { 3284 t.Fatalf("expected (0, nil, nil), got: (%d, %#v, %#v)", idx, dump, err) 3285 } 3286 3287 // Register some nodes 3288 testRegisterNode(t, s, 0, "node1") 3289 testRegisterNode(t, s, 1, "node2") 3290 3291 // Register services against them 3292 testRegisterService(t, s, 2, "node1", "service1") 3293 testRegisterService(t, s, 3, "node1", "service2") 3294 testRegisterService(t, s, 4, "node2", "service1") 3295 testRegisterService(t, s, 5, "node2", "service2") 3296 3297 // Register service-level checks 3298 testRegisterCheck(t, s, 6, "node1", "service1", "check1", api.HealthPassing) 3299 testRegisterCheck(t, s, 7, "node2", "service1", "check1", api.HealthPassing) 3300 3301 // Register node-level checks 3302 testRegisterCheck(t, s, 8, "node1", "", "check2", api.HealthPassing) 3303 testRegisterCheck(t, s, 9, "node2", "", "check2", api.HealthPassing) 3304 3305 // Both watches should have fired due to the changes above. 3306 if !watchFired(wsInfo) { 3307 t.Fatalf("bad") 3308 } 3309 if !watchFired(wsDump) { 3310 t.Fatalf("bad") 3311 } 3312 3313 // Check that our result matches what we expect. 3314 expect := structs.NodeDump{ 3315 &structs.NodeInfo{ 3316 Node: "node1", 3317 Checks: structs.HealthChecks{ 3318 &structs.HealthCheck{ 3319 Node: "node1", 3320 CheckID: "check1", 3321 ServiceID: "service1", 3322 ServiceName: "service1", 3323 Status: api.HealthPassing, 3324 RaftIndex: structs.RaftIndex{ 3325 CreateIndex: 6, 3326 ModifyIndex: 6, 3327 }, 3328 }, 3329 &structs.HealthCheck{ 3330 Node: "node1", 3331 CheckID: "check2", 3332 ServiceID: "", 3333 ServiceName: "", 3334 Status: api.HealthPassing, 3335 RaftIndex: structs.RaftIndex{ 3336 CreateIndex: 8, 3337 ModifyIndex: 8, 3338 }, 3339 }, 3340 }, 3341 Services: []*structs.NodeService{ 3342 &structs.NodeService{ 3343 ID: "service1", 3344 Service: "service1", 3345 Address: "1.1.1.1", 3346 Meta: make(map[string]string), 3347 Port: 1111, 3348 Weights: &structs.Weights{Passing: 1, Warning: 1}, 3349 RaftIndex: structs.RaftIndex{ 3350 CreateIndex: 2, 3351 ModifyIndex: 2, 3352 }, 3353 }, 3354 &structs.NodeService{ 3355 ID: "service2", 3356 Service: "service2", 3357 Address: "1.1.1.1", 3358 Meta: make(map[string]string), 3359 Port: 1111, 3360 Weights: &structs.Weights{Passing: 1, Warning: 1}, 3361 RaftIndex: structs.RaftIndex{ 3362 CreateIndex: 3, 3363 ModifyIndex: 3, 3364 }, 3365 }, 3366 }, 3367 }, 3368 &structs.NodeInfo{ 3369 Node: "node2", 3370 Checks: structs.HealthChecks{ 3371 &structs.HealthCheck{ 3372 Node: "node2", 3373 CheckID: "check1", 3374 ServiceID: "service1", 3375 ServiceName: "service1", 3376 Status: api.HealthPassing, 3377 RaftIndex: structs.RaftIndex{ 3378 CreateIndex: 7, 3379 ModifyIndex: 7, 3380 }, 3381 }, 3382 &structs.HealthCheck{ 3383 Node: "node2", 3384 CheckID: "check2", 3385 ServiceID: "", 3386 ServiceName: "", 3387 Status: api.HealthPassing, 3388 RaftIndex: structs.RaftIndex{ 3389 CreateIndex: 9, 3390 ModifyIndex: 9, 3391 }, 3392 }, 3393 }, 3394 Services: []*structs.NodeService{ 3395 &structs.NodeService{ 3396 ID: "service1", 3397 Service: "service1", 3398 Address: "1.1.1.1", 3399 Port: 1111, 3400 Meta: make(map[string]string), 3401 Weights: &structs.Weights{Passing: 1, Warning: 1}, 3402 RaftIndex: structs.RaftIndex{ 3403 CreateIndex: 4, 3404 ModifyIndex: 4, 3405 }, 3406 }, 3407 &structs.NodeService{ 3408 ID: "service2", 3409 Service: "service2", 3410 Address: "1.1.1.1", 3411 Port: 1111, 3412 Meta: make(map[string]string), 3413 Weights: &structs.Weights{Passing: 1, Warning: 1}, 3414 RaftIndex: structs.RaftIndex{ 3415 CreateIndex: 5, 3416 ModifyIndex: 5, 3417 }, 3418 }, 3419 }, 3420 }, 3421 } 3422 3423 // Get a dump of just a single node 3424 ws := memdb.NewWatchSet() 3425 idx, dump, err = s.NodeInfo(ws, "node1") 3426 if err != nil { 3427 t.Fatalf("err: %s", err) 3428 } 3429 if idx != 9 { 3430 t.Fatalf("bad index: %d", idx) 3431 } 3432 if len(dump) != 1 || !reflect.DeepEqual(dump[0], expect[0]) { 3433 t.Fatalf("bad: len=%#v dump=%#v expect=%#v", len(dump), dump[0], expect[0]) 3434 } 3435 3436 // Generate a dump of all the nodes 3437 idx, dump, err = s.NodeDump(nil) 3438 if err != nil { 3439 t.Fatalf("err: %s", err) 3440 } 3441 if idx != 9 { 3442 t.Fatalf("bad index: %d", 9) 3443 } 3444 if !reflect.DeepEqual(dump, expect) { 3445 t.Fatalf("bad: %#v", dump[0].Services[0]) 3446 } 3447 3448 // Registering some unrelated node + service + check should not fire the 3449 // watch. 3450 testRegisterNode(t, s, 10, "nope") 3451 testRegisterService(t, s, 11, "nope", "nope") 3452 if watchFired(ws) { 3453 t.Fatalf("bad") 3454 } 3455 } 3456 3457 func TestStateStore_ServiceIdxUpdateOnNodeUpdate(t *testing.T) { 3458 s := testStateStore(t) 3459 3460 // Create a service on a node 3461 err := s.EnsureNode(10, &structs.Node{Node: "node", Address: "127.0.0.1"}) 3462 require.Nil(t, err) 3463 err = s.EnsureService(12, "node", &structs.NodeService{ID: "srv", Service: "srv", Tags: nil, Address: "", Port: 5000}) 3464 require.Nil(t, err) 3465 3466 // Store the current service index 3467 ws := memdb.NewWatchSet() 3468 lastIdx, _, err := s.ServiceNodes(ws, "srv") 3469 require.Nil(t, err) 3470 3471 // Update the node with some meta 3472 err = s.EnsureNode(14, &structs.Node{Node: "node", Address: "127.0.0.1", Meta: map[string]string{"foo": "bar"}}) 3473 require.Nil(t, err) 3474 3475 // Read the new service index 3476 ws = memdb.NewWatchSet() 3477 newIdx, _, err := s.ServiceNodes(ws, "srv") 3478 require.Nil(t, err) 3479 3480 require.True(t, newIdx > lastIdx) 3481 }