github.com/kjdelisle/consul@v1.4.5/testrpc/wait.go (about) 1 package testrpc 2 3 import ( 4 "testing" 5 6 "github.com/hashicorp/consul/agent/structs" 7 "github.com/hashicorp/consul/testutil/retry" 8 ) 9 10 type rpcFn func(string, interface{}, interface{}) error 11 12 // WaitForLeader ensures we have a leader and a node registration. 13 func WaitForLeader(t *testing.T, rpc rpcFn, dc string) { 14 var out structs.IndexedNodes 15 retry.Run(t, func(r *retry.R) { 16 args := &structs.DCSpecificRequest{Datacenter: dc} 17 if err := rpc("Catalog.ListNodes", args, &out); err != nil { 18 r.Fatalf("Catalog.ListNodes failed: %v", err) 19 } 20 if !out.QueryMeta.KnownLeader { 21 r.Fatalf("No leader") 22 } 23 if out.Index < 2 { 24 r.Fatalf("Consul index should be at least 2") 25 } 26 }) 27 } 28 29 // WaitUntilNoLeader ensures no leader is present, useful for testing lost leadership. 30 func WaitUntilNoLeader(t *testing.T, rpc rpcFn, dc string) { 31 var out structs.IndexedNodes 32 retry.Run(t, func(r *retry.R) { 33 args := &structs.DCSpecificRequest{Datacenter: dc} 34 if err := rpc("Catalog.ListNodes", args, &out); err == nil { 35 r.Fatalf("It still has a leader: %#v", out) 36 } 37 if out.QueryMeta.KnownLeader { 38 r.Fatalf("Has still a leader") 39 } 40 }) 41 } 42 43 type waitOption struct { 44 Token string 45 } 46 47 func WithToken(token string) waitOption { 48 return waitOption{Token: token} 49 } 50 51 // WaitForTestAgent ensures we have a node with serfHealth check registered 52 func WaitForTestAgent(t *testing.T, rpc rpcFn, dc string, options ...waitOption) { 53 var nodes structs.IndexedNodes 54 var checks structs.IndexedHealthChecks 55 56 // first extra arg is an optional acl token 57 var token string 58 for _, opt := range options { 59 if opt.Token != "" { 60 token = opt.Token 61 } 62 } 63 64 retry.Run(t, func(r *retry.R) { 65 dcReq := &structs.DCSpecificRequest{ 66 Datacenter: dc, 67 QueryOptions: structs.QueryOptions{Token: token}, 68 } 69 if err := rpc("Catalog.ListNodes", dcReq, &nodes); err != nil { 70 r.Fatalf("Catalog.ListNodes failed: %v", err) 71 } 72 if len(nodes.Nodes) == 0 { 73 r.Fatalf("No registered nodes") 74 } 75 76 // This assumes that there is a single agent per dc, typically a TestAgent 77 nodeReq := &structs.NodeSpecificRequest{ 78 Datacenter: dc, 79 Node: nodes.Nodes[0].Node, 80 QueryOptions: structs.QueryOptions{Token: token}, 81 } 82 if err := rpc("Health.NodeChecks", nodeReq, &checks); err != nil { 83 r.Fatalf("Health.NodeChecks failed: %v", err) 84 } 85 86 var found bool 87 for _, check := range checks.HealthChecks { 88 if check.CheckID == "serfHealth" { 89 found = true 90 break 91 } 92 } 93 if !found { 94 r.Fatalf("serfHealth check not found") 95 } 96 }) 97 }