github.imxd.top/hashicorp/consul@v1.4.5/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 updated by node on idx 8 2984 if idx != 8 { 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 // Note that we can't overwhelm chan tracking any more since we optimized it 3025 // to only need to watch one chan in the happy path. The only path that does 3026 // bees to watch more stuff is where there are no service instances which also 3027 // means fewer than watchLimit chans too so effectively no way to trigger 3028 // Fallback watch any more. 3029 } 3030 3031 func TestStateStore_CheckConnectServiceNodes(t *testing.T) { 3032 assert := assert.New(t) 3033 s := testStateStore(t) 3034 3035 // Listing with no results returns an empty list. 3036 ws := memdb.NewWatchSet() 3037 idx, nodes, err := s.CheckConnectServiceNodes(ws, "db") 3038 assert.Nil(err) 3039 assert.Equal(idx, uint64(0)) 3040 assert.Len(nodes, 0) 3041 3042 // Create some nodes and services. 3043 assert.Nil(s.EnsureNode(10, &structs.Node{Node: "foo", Address: "127.0.0.1"})) 3044 assert.Nil(s.EnsureNode(11, &structs.Node{Node: "bar", Address: "127.0.0.2"})) 3045 assert.Nil(s.EnsureService(12, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: nil, Address: "", Port: 5000})) 3046 assert.Nil(s.EnsureService(13, "bar", &structs.NodeService{ID: "api", Service: "api", Tags: nil, Address: "", Port: 5000})) 3047 assert.Nil(s.EnsureService(14, "foo", &structs.NodeService{Kind: structs.ServiceKindConnectProxy, ID: "proxy", Service: "proxy", Proxy: structs.ConnectProxyConfig{DestinationServiceName: "db"}, Port: 8000})) 3048 assert.Nil(s.EnsureService(15, "bar", &structs.NodeService{Kind: structs.ServiceKindConnectProxy, ID: "proxy", Service: "proxy", Proxy: structs.ConnectProxyConfig{DestinationServiceName: "db"}, Port: 8000})) 3049 assert.Nil(s.EnsureService(16, "bar", &structs.NodeService{ID: "db2", Service: "db", Tags: []string{"slave"}, Address: "", Port: 8001})) 3050 assert.True(watchFired(ws)) 3051 3052 // Register node checks 3053 testRegisterCheck(t, s, 17, "foo", "", "check1", api.HealthPassing) 3054 testRegisterCheck(t, s, 18, "bar", "", "check2", api.HealthPassing) 3055 3056 // Register checks against the services. 3057 testRegisterCheck(t, s, 19, "foo", "db", "check3", api.HealthPassing) 3058 testRegisterCheck(t, s, 20, "bar", "proxy", "check4", api.HealthPassing) 3059 3060 // Read everything back. 3061 ws = memdb.NewWatchSet() 3062 idx, nodes, err = s.CheckConnectServiceNodes(ws, "db") 3063 assert.Nil(err) 3064 assert.Equal(idx, uint64(idx)) 3065 assert.Len(nodes, 2) 3066 3067 for _, n := range nodes { 3068 assert.Equal(structs.ServiceKindConnectProxy, n.Service.Kind) 3069 assert.Equal("db", n.Service.Proxy.DestinationServiceName) 3070 } 3071 } 3072 3073 func BenchmarkCheckServiceNodes(b *testing.B) { 3074 s, err := NewStateStore(nil) 3075 if err != nil { 3076 b.Fatalf("err: %s", err) 3077 } 3078 3079 if err := s.EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 3080 b.Fatalf("err: %v", err) 3081 } 3082 if err := s.EnsureService(2, "foo", &structs.NodeService{ID: "db1", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { 3083 b.Fatalf("err: %v", err) 3084 } 3085 check := &structs.HealthCheck{ 3086 Node: "foo", 3087 CheckID: "db", 3088 Name: "can connect", 3089 Status: api.HealthPassing, 3090 ServiceID: "db1", 3091 } 3092 if err := s.EnsureCheck(3, check); err != nil { 3093 b.Fatalf("err: %v", err) 3094 } 3095 check = &structs.HealthCheck{ 3096 Node: "foo", 3097 CheckID: "check1", 3098 Name: "check1", 3099 Status: api.HealthPassing, 3100 } 3101 if err := s.EnsureCheck(4, check); err != nil { 3102 b.Fatalf("err: %v", err) 3103 } 3104 3105 ws := memdb.NewWatchSet() 3106 for i := 0; i < b.N; i++ { 3107 s.CheckServiceNodes(ws, "db") 3108 } 3109 } 3110 3111 func TestStateStore_CheckServiceTagNodes(t *testing.T) { 3112 s := testStateStore(t) 3113 3114 if err := s.EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 3115 t.Fatalf("err: %v", err) 3116 } 3117 if err := s.EnsureService(2, "foo", &structs.NodeService{ID: "db1", Service: "db", Tags: []string{"master"}, Address: "", Port: 8000}); err != nil { 3118 t.Fatalf("err: %v", err) 3119 } 3120 check := &structs.HealthCheck{ 3121 Node: "foo", 3122 CheckID: "db", 3123 Name: "can connect", 3124 Status: api.HealthPassing, 3125 ServiceID: "db1", 3126 } 3127 if err := s.EnsureCheck(3, check); err != nil { 3128 t.Fatalf("err: %v", err) 3129 } 3130 check = &structs.HealthCheck{ 3131 Node: "foo", 3132 CheckID: "check1", 3133 Name: "another check", 3134 Status: api.HealthPassing, 3135 } 3136 if err := s.EnsureCheck(4, check); err != nil { 3137 t.Fatalf("err: %v", err) 3138 } 3139 3140 ws := memdb.NewWatchSet() 3141 idx, nodes, err := s.CheckServiceTagNodes(ws, "db", []string{"master"}) 3142 if err != nil { 3143 t.Fatalf("err: %s", err) 3144 } 3145 if idx != 4 { 3146 t.Fatalf("bad: %v", idx) 3147 } 3148 if len(nodes) != 1 { 3149 t.Fatalf("Bad: %v", nodes) 3150 } 3151 if nodes[0].Node.Node != "foo" { 3152 t.Fatalf("Bad: %v", nodes[0]) 3153 } 3154 if nodes[0].Service.ID != "db1" { 3155 t.Fatalf("Bad: %v", nodes[0]) 3156 } 3157 if len(nodes[0].Checks) != 2 { 3158 t.Fatalf("Bad: %v", nodes[0]) 3159 } 3160 if nodes[0].Checks[0].CheckID != "check1" { 3161 t.Fatalf("Bad: %v", nodes[0]) 3162 } 3163 if nodes[0].Checks[1].CheckID != "db" { 3164 t.Fatalf("Bad: %v", nodes[0]) 3165 } 3166 3167 // Changing a tag should fire the watch. 3168 if err := s.EnsureService(4, "foo", &structs.NodeService{ID: "db1", Service: "db", Tags: []string{"nope"}, Address: "", Port: 8000}); err != nil { 3169 t.Fatalf("err: %v", err) 3170 } 3171 if !watchFired(ws) { 3172 t.Fatalf("bad") 3173 } 3174 } 3175 3176 func TestStateStore_Check_Snapshot(t *testing.T) { 3177 s := testStateStore(t) 3178 3179 // Create a node, a service, and a service check as well as a node check. 3180 testRegisterNode(t, s, 0, "node1") 3181 testRegisterService(t, s, 1, "node1", "service1") 3182 checks := structs.HealthChecks{ 3183 &structs.HealthCheck{ 3184 Node: "node1", 3185 CheckID: "check1", 3186 Name: "node check", 3187 Status: api.HealthPassing, 3188 }, 3189 &structs.HealthCheck{ 3190 Node: "node1", 3191 CheckID: "check2", 3192 Name: "service check", 3193 Status: api.HealthCritical, 3194 ServiceID: "service1", 3195 }, 3196 } 3197 for i, hc := range checks { 3198 if err := s.EnsureCheck(uint64(i+1), hc); err != nil { 3199 t.Fatalf("err: %s", err) 3200 } 3201 } 3202 3203 // Create a second node/service to make sure node filtering works. This 3204 // will affect the index but not the dump. 3205 testRegisterNode(t, s, 3, "node2") 3206 testRegisterService(t, s, 4, "node2", "service2") 3207 testRegisterCheck(t, s, 5, "node2", "service2", "check3", api.HealthPassing) 3208 3209 // Snapshot the checks. 3210 snap := s.Snapshot() 3211 defer snap.Close() 3212 3213 // Alter the real state store. 3214 testRegisterCheck(t, s, 6, "node2", "service2", "check4", api.HealthPassing) 3215 3216 // Verify the snapshot. 3217 if idx := snap.LastIndex(); idx != 5 { 3218 t.Fatalf("bad index: %d", idx) 3219 } 3220 iter, err := snap.Checks("node1") 3221 if err != nil { 3222 t.Fatalf("err: %s", err) 3223 } 3224 for i := 0; i < len(checks); i++ { 3225 check := iter.Next().(*structs.HealthCheck) 3226 if check == nil { 3227 t.Fatalf("unexpected end of checks") 3228 } 3229 3230 checks[i].CreateIndex, checks[i].ModifyIndex = uint64(i+1), uint64(i+1) 3231 if !reflect.DeepEqual(check, checks[i]) { 3232 t.Fatalf("bad: %#v != %#v", check, checks[i]) 3233 } 3234 } 3235 if iter.Next() != nil { 3236 t.Fatalf("unexpected extra checks") 3237 } 3238 } 3239 3240 func TestStateStore_NodeInfo_NodeDump(t *testing.T) { 3241 s := testStateStore(t) 3242 3243 // Generating a node dump that matches nothing returns empty 3244 wsInfo := memdb.NewWatchSet() 3245 idx, dump, err := s.NodeInfo(wsInfo, "node1") 3246 if idx != 0 || dump != nil || err != nil { 3247 t.Fatalf("expected (0, nil, nil), got: (%d, %#v, %#v)", idx, dump, err) 3248 } 3249 wsDump := memdb.NewWatchSet() 3250 idx, dump, err = s.NodeDump(wsDump) 3251 if idx != 0 || dump != nil || err != nil { 3252 t.Fatalf("expected (0, nil, nil), got: (%d, %#v, %#v)", idx, dump, err) 3253 } 3254 3255 // Register some nodes 3256 testRegisterNode(t, s, 0, "node1") 3257 testRegisterNode(t, s, 1, "node2") 3258 3259 // Register services against them 3260 testRegisterService(t, s, 2, "node1", "service1") 3261 testRegisterService(t, s, 3, "node1", "service2") 3262 testRegisterService(t, s, 4, "node2", "service1") 3263 testRegisterService(t, s, 5, "node2", "service2") 3264 3265 // Register service-level checks 3266 testRegisterCheck(t, s, 6, "node1", "service1", "check1", api.HealthPassing) 3267 testRegisterCheck(t, s, 7, "node2", "service1", "check1", api.HealthPassing) 3268 3269 // Register node-level checks 3270 testRegisterCheck(t, s, 8, "node1", "", "check2", api.HealthPassing) 3271 testRegisterCheck(t, s, 9, "node2", "", "check2", api.HealthPassing) 3272 3273 // Both watches should have fired due to the changes above. 3274 if !watchFired(wsInfo) { 3275 t.Fatalf("bad") 3276 } 3277 if !watchFired(wsDump) { 3278 t.Fatalf("bad") 3279 } 3280 3281 // Check that our result matches what we expect. 3282 expect := structs.NodeDump{ 3283 &structs.NodeInfo{ 3284 Node: "node1", 3285 Checks: structs.HealthChecks{ 3286 &structs.HealthCheck{ 3287 Node: "node1", 3288 CheckID: "check1", 3289 ServiceID: "service1", 3290 ServiceName: "service1", 3291 Status: api.HealthPassing, 3292 RaftIndex: structs.RaftIndex{ 3293 CreateIndex: 6, 3294 ModifyIndex: 6, 3295 }, 3296 }, 3297 &structs.HealthCheck{ 3298 Node: "node1", 3299 CheckID: "check2", 3300 ServiceID: "", 3301 ServiceName: "", 3302 Status: api.HealthPassing, 3303 RaftIndex: structs.RaftIndex{ 3304 CreateIndex: 8, 3305 ModifyIndex: 8, 3306 }, 3307 }, 3308 }, 3309 Services: []*structs.NodeService{ 3310 &structs.NodeService{ 3311 ID: "service1", 3312 Service: "service1", 3313 Address: "1.1.1.1", 3314 Meta: make(map[string]string), 3315 Port: 1111, 3316 Weights: &structs.Weights{Passing: 1, Warning: 1}, 3317 RaftIndex: structs.RaftIndex{ 3318 CreateIndex: 2, 3319 ModifyIndex: 2, 3320 }, 3321 }, 3322 &structs.NodeService{ 3323 ID: "service2", 3324 Service: "service2", 3325 Address: "1.1.1.1", 3326 Meta: make(map[string]string), 3327 Port: 1111, 3328 Weights: &structs.Weights{Passing: 1, Warning: 1}, 3329 RaftIndex: structs.RaftIndex{ 3330 CreateIndex: 3, 3331 ModifyIndex: 3, 3332 }, 3333 }, 3334 }, 3335 }, 3336 &structs.NodeInfo{ 3337 Node: "node2", 3338 Checks: structs.HealthChecks{ 3339 &structs.HealthCheck{ 3340 Node: "node2", 3341 CheckID: "check1", 3342 ServiceID: "service1", 3343 ServiceName: "service1", 3344 Status: api.HealthPassing, 3345 RaftIndex: structs.RaftIndex{ 3346 CreateIndex: 7, 3347 ModifyIndex: 7, 3348 }, 3349 }, 3350 &structs.HealthCheck{ 3351 Node: "node2", 3352 CheckID: "check2", 3353 ServiceID: "", 3354 ServiceName: "", 3355 Status: api.HealthPassing, 3356 RaftIndex: structs.RaftIndex{ 3357 CreateIndex: 9, 3358 ModifyIndex: 9, 3359 }, 3360 }, 3361 }, 3362 Services: []*structs.NodeService{ 3363 &structs.NodeService{ 3364 ID: "service1", 3365 Service: "service1", 3366 Address: "1.1.1.1", 3367 Port: 1111, 3368 Meta: make(map[string]string), 3369 Weights: &structs.Weights{Passing: 1, Warning: 1}, 3370 RaftIndex: structs.RaftIndex{ 3371 CreateIndex: 4, 3372 ModifyIndex: 4, 3373 }, 3374 }, 3375 &structs.NodeService{ 3376 ID: "service2", 3377 Service: "service2", 3378 Address: "1.1.1.1", 3379 Port: 1111, 3380 Meta: make(map[string]string), 3381 Weights: &structs.Weights{Passing: 1, Warning: 1}, 3382 RaftIndex: structs.RaftIndex{ 3383 CreateIndex: 5, 3384 ModifyIndex: 5, 3385 }, 3386 }, 3387 }, 3388 }, 3389 } 3390 3391 // Get a dump of just a single node 3392 ws := memdb.NewWatchSet() 3393 idx, dump, err = s.NodeInfo(ws, "node1") 3394 if err != nil { 3395 t.Fatalf("err: %s", err) 3396 } 3397 if idx != 9 { 3398 t.Fatalf("bad index: %d", idx) 3399 } 3400 if len(dump) != 1 || !reflect.DeepEqual(dump[0], expect[0]) { 3401 t.Fatalf("bad: len=%#v dump=%#v expect=%#v", len(dump), dump[0], expect[0]) 3402 } 3403 3404 // Generate a dump of all the nodes 3405 idx, dump, err = s.NodeDump(nil) 3406 if err != nil { 3407 t.Fatalf("err: %s", err) 3408 } 3409 if idx != 9 { 3410 t.Fatalf("bad index: %d", 9) 3411 } 3412 if !reflect.DeepEqual(dump, expect) { 3413 t.Fatalf("bad: %#v", dump[0].Services[0]) 3414 } 3415 3416 // Registering some unrelated node + service + check should not fire the 3417 // watch. 3418 testRegisterNode(t, s, 10, "nope") 3419 testRegisterService(t, s, 11, "nope", "nope") 3420 if watchFired(ws) { 3421 t.Fatalf("bad") 3422 } 3423 } 3424 3425 func TestStateStore_ServiceIdxUpdateOnNodeUpdate(t *testing.T) { 3426 s := testStateStore(t) 3427 3428 // Create a service on a node 3429 err := s.EnsureNode(10, &structs.Node{Node: "node", Address: "127.0.0.1"}) 3430 require.Nil(t, err) 3431 err = s.EnsureService(12, "node", &structs.NodeService{ID: "srv", Service: "srv", Tags: nil, Address: "", Port: 5000}) 3432 require.Nil(t, err) 3433 3434 // Store the current service index 3435 ws := memdb.NewWatchSet() 3436 lastIdx, _, err := s.ServiceNodes(ws, "srv") 3437 require.Nil(t, err) 3438 3439 // Update the node with some meta 3440 err = s.EnsureNode(14, &structs.Node{Node: "node", Address: "127.0.0.1", Meta: map[string]string{"foo": "bar"}}) 3441 require.Nil(t, err) 3442 3443 // Read the new service index 3444 ws = memdb.NewWatchSet() 3445 newIdx, _, err := s.ServiceNodes(ws, "srv") 3446 require.Nil(t, err) 3447 3448 require.True(t, newIdx > lastIdx) 3449 }