github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/cli/haproxy_test.go (about) 1 // Copyright 2017 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package cli 12 13 import ( 14 "reflect" 15 "testing" 16 17 "github.com/cockroachdb/cockroach/pkg/base" 18 "github.com/cockroachdb/cockroach/pkg/kv/kvserver/kvserverpb" 19 "github.com/cockroachdb/cockroach/pkg/roachpb" 20 "github.com/cockroachdb/cockroach/pkg/server/serverpb" 21 "github.com/cockroachdb/cockroach/pkg/server/status/statuspb" 22 "github.com/cockroachdb/cockroach/pkg/util" 23 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 24 ) 25 26 func TestNodeStatusToNodeInfoConversion(t *testing.T) { 27 defer leaktest.AfterTest(t)() 28 29 testCases := []struct { 30 input serverpb.NodesResponse 31 expected []haProxyNodeInfo 32 }{ 33 { 34 serverpb.NodesResponse{Nodes: []statuspb.NodeStatus{ 35 { 36 Desc: roachpb.NodeDescriptor{ 37 NodeID: 1, 38 Address: util.UnresolvedAddr{ 39 AddressField: "addr", 40 }, 41 }, 42 // Flags but no http port. 43 Args: []string{"--unwanted", "-unwanted"}, 44 }, 45 }}, 46 []haProxyNodeInfo{ 47 { 48 NodeID: 1, 49 NodeAddr: "addr", 50 CheckPort: base.DefaultHTTPPort, 51 }, 52 }, 53 }, 54 { 55 serverpb.NodesResponse{Nodes: []statuspb.NodeStatus{ 56 { 57 Desc: roachpb.NodeDescriptor{NodeID: 1}, 58 Args: []string{"--unwanted", "--http-port=1234"}, 59 }, 60 { 61 Desc: roachpb.NodeDescriptor{NodeID: 2}, 62 Args: nil, 63 }, 64 { 65 Desc: roachpb.NodeDescriptor{NodeID: 3}, 66 Args: []string{"--http-addr=foo:4567"}, 67 }, 68 }}, 69 []haProxyNodeInfo{ 70 { 71 NodeID: 1, 72 CheckPort: "1234", 73 }, 74 { 75 NodeID: 2, 76 CheckPort: base.DefaultHTTPPort, 77 }, 78 { 79 NodeID: 3, 80 CheckPort: "4567", 81 }, 82 }, 83 }, 84 { 85 serverpb.NodesResponse{Nodes: []statuspb.NodeStatus{ 86 { 87 Desc: roachpb.NodeDescriptor{NodeID: 1}, 88 Args: []string{"--http-port", "5678", "--unwanted"}, 89 }, 90 }}, 91 []haProxyNodeInfo{ 92 { 93 NodeID: 1, 94 CheckPort: "5678", 95 }, 96 }, 97 }, 98 { 99 serverpb.NodesResponse{Nodes: []statuspb.NodeStatus{ 100 { 101 Desc: roachpb.NodeDescriptor{NodeID: 1}, 102 // We shouldn't see this, because the flag needs an argument on startup, 103 // but check that we fall back to the default port. 104 Args: []string{"-http-port"}, 105 }, 106 }}, 107 []haProxyNodeInfo{ 108 { 109 NodeID: 1, 110 CheckPort: base.DefaultHTTPPort, 111 }, 112 }, 113 }, 114 // Check that decommission{ing,ed} nodes are not considered for 115 // generating the configuration. 116 { 117 serverpb.NodesResponse{ 118 Nodes: []statuspb.NodeStatus{ 119 {Desc: roachpb.NodeDescriptor{NodeID: 1}}, 120 {Desc: roachpb.NodeDescriptor{NodeID: 2}}, 121 {Desc: roachpb.NodeDescriptor{NodeID: 3}}, 122 {Desc: roachpb.NodeDescriptor{NodeID: 4}}, 123 {Desc: roachpb.NodeDescriptor{NodeID: 5}}, 124 {Desc: roachpb.NodeDescriptor{NodeID: 6}}, 125 }, 126 LivenessByNodeID: map[roachpb.NodeID]kvserverpb.NodeLivenessStatus{ 127 1: kvserverpb.NodeLivenessStatus_DEAD, 128 2: kvserverpb.NodeLivenessStatus_DECOMMISSIONING, 129 3: kvserverpb.NodeLivenessStatus_UNKNOWN, 130 4: kvserverpb.NodeLivenessStatus_UNAVAILABLE, 131 5: kvserverpb.NodeLivenessStatus_LIVE, 132 6: kvserverpb.NodeLivenessStatus_DECOMMISSIONED, 133 }, 134 }, 135 []haProxyNodeInfo{ 136 {NodeID: 1, CheckPort: base.DefaultHTTPPort}, 137 // Node 2 is decommissioning. 138 {NodeID: 3, CheckPort: base.DefaultHTTPPort}, 139 {NodeID: 4, CheckPort: base.DefaultHTTPPort}, 140 {NodeID: 5, CheckPort: base.DefaultHTTPPort}, 141 // Node 6 is decommissioned. 142 }, 143 }, 144 } 145 146 for i, testCase := range testCases { 147 output := nodeStatusesToNodeInfos(&testCase.input) 148 if !reflect.DeepEqual(output, testCase.expected) { 149 t.Fatalf("test %d: unexpected output %v, expected %v", i, output, testCase.expected) 150 } 151 } 152 } 153 154 func TestMatchLocalityRegexp(t *testing.T) { 155 defer leaktest.AfterTest(t)() 156 157 testCases := []struct { 158 locality string // The locality as passed to `start --locality=xx` 159 desired string // The desired locality as passed to `gen haproxy --locality=xx` 160 matches bool 161 }{ 162 {"", "", true}, 163 {"region=us-east1", "", true}, 164 {"country=us,region=us-east1,datacenter=blah", "", true}, 165 {"country=us,region=us-east1,datacenter=blah", "country=us", true}, 166 {"country=us,region=us-east1,datacenter=blah", "count.*=us", false}, 167 {"country=us,region=us-east1,datacenter=blah", "country=u", false}, 168 {"country=us,region=us-east1,datacenter=blah", "try=us", false}, 169 {"country=us,region=us-east1,datacenter=blah", "region=us-east1", true}, 170 {"country=us,region=us-east1,datacenter=blah", "region=us.*", true}, 171 {"country=us,region=us-east1,datacenter=blah", "region=us.*,country=us", true}, 172 {"country=us,region=us-east1,datacenter=blah", "region=notus", false}, 173 {"country=us,region=us-east1,datacenter=blah", "something=else", false}, 174 {"country=us,region=us-east1,datacenter=blah", "region=us.*,zone=foo", false}, 175 } 176 177 for testNum, testCase := range testCases { 178 // We're not testing locality parsing: fail on error. 179 var locality, desired roachpb.Locality 180 if testCase.locality != "" { 181 if err := locality.Set(testCase.locality); err != nil { 182 t.Fatal(err) 183 } 184 } 185 if testCase.desired != "" { 186 if err := desired.Set(testCase.desired); err != nil { 187 t.Fatal(err) 188 } 189 } 190 matches, _ := localityMatches(locality, desired) 191 if matches != testCase.matches { 192 t.Errorf("#%d: expected match %t, got %t", testNum, testCase.matches, matches) 193 } 194 } 195 }