github.imxd.top/hashicorp/consul@v1.4.5/agent/consul/util_test.go (about) 1 package consul 2 3 import ( 4 "errors" 5 "fmt" 6 "net" 7 "regexp" 8 "testing" 9 10 "github.com/hashicorp/go-version" 11 "github.com/hashicorp/serf/serf" 12 ) 13 14 func TestGetPrivateIP(t *testing.T) { 15 t.Parallel() 16 ip, _, err := net.ParseCIDR("10.1.2.3/32") 17 if err != nil { 18 t.Fatalf("failed to parse private cidr: %v", err) 19 } 20 21 pubIP, _, err := net.ParseCIDR("8.8.8.8/32") 22 if err != nil { 23 t.Fatalf("failed to parse public cidr: %v", err) 24 } 25 26 tests := []struct { 27 addrs []net.Addr 28 expected net.IP 29 err error 30 }{ 31 { 32 addrs: []net.Addr{ 33 &net.IPAddr{ 34 IP: ip, 35 }, 36 &net.IPAddr{ 37 IP: pubIP, 38 }, 39 }, 40 expected: ip, 41 }, 42 { 43 addrs: []net.Addr{ 44 &net.IPAddr{ 45 IP: pubIP, 46 }, 47 }, 48 err: errors.New("No private IP address found"), 49 }, 50 { 51 addrs: []net.Addr{ 52 &net.IPAddr{ 53 IP: ip, 54 }, 55 &net.IPAddr{ 56 IP: ip, 57 }, 58 &net.IPAddr{ 59 IP: pubIP, 60 }, 61 }, 62 err: errors.New("Multiple private IPs found. Please configure one."), 63 }, 64 } 65 66 for _, test := range tests { 67 ip, err := getPrivateIP(test.addrs) 68 switch { 69 case test.err != nil && err != nil: 70 if err.Error() != test.err.Error() { 71 t.Fatalf("unexpected error: %v != %v", test.err, err) 72 } 73 case (test.err == nil && err != nil) || (test.err != nil && err == nil): 74 t.Fatalf("unexpected error: %v != %v", test.err, err) 75 default: 76 if !test.expected.Equal(ip) { 77 t.Fatalf("unexpected ip: %v != %v", ip, test.expected) 78 } 79 } 80 } 81 } 82 83 func TestIsPrivateIP(t *testing.T) { 84 t.Parallel() 85 if !isPrivateIP("192.168.1.1") { 86 t.Fatalf("bad") 87 } 88 if !isPrivateIP("172.16.45.100") { 89 t.Fatalf("bad") 90 } 91 if !isPrivateIP("10.1.2.3") { 92 t.Fatalf("bad") 93 } 94 if !isPrivateIP("100.115.110.19") { 95 t.Fatalf("bad") 96 } 97 if isPrivateIP("8.8.8.8") { 98 t.Fatalf("bad") 99 } 100 if !isPrivateIP("127.0.0.1") { 101 t.Fatalf("bad") 102 } 103 } 104 105 func TestUtil_CanServersUnderstandProtocol(t *testing.T) { 106 t.Parallel() 107 var members []serf.Member 108 109 // All empty list cases should return false. 110 for v := ProtocolVersionMin; v <= ProtocolVersionMax; v++ { 111 grok, err := CanServersUnderstandProtocol(members, v) 112 if err != nil { 113 t.Fatalf("err: %v", err) 114 } 115 if grok { 116 t.Fatalf("empty list should always return false") 117 } 118 } 119 120 // Add a non-server member. 121 members = append(members, serf.Member{ 122 Tags: map[string]string{ 123 "vsn_min": fmt.Sprintf("%d", ProtocolVersionMin), 124 "vsn_max": fmt.Sprintf("%d", ProtocolVersionMax), 125 }, 126 }) 127 128 // Make sure it doesn't get counted. 129 for v := ProtocolVersionMin; v <= ProtocolVersionMax; v++ { 130 grok, err := CanServersUnderstandProtocol(members, v) 131 if err != nil { 132 t.Fatalf("err: %v", err) 133 } 134 if grok { 135 t.Fatalf("non-server members should not be counted") 136 } 137 } 138 139 // Add a server member. 140 members = append(members, serf.Member{ 141 Tags: map[string]string{ 142 "role": "consul", 143 "vsn_min": fmt.Sprintf("%d", ProtocolVersionMin), 144 "vsn_max": fmt.Sprintf("%d", ProtocolVersionMax), 145 }, 146 }) 147 148 // Now it should report that it understands. 149 for v := ProtocolVersionMin; v <= ProtocolVersionMax; v++ { 150 grok, err := CanServersUnderstandProtocol(members, v) 151 if err != nil { 152 t.Fatalf("err: %v", err) 153 } 154 if !grok { 155 t.Fatalf("server should grok") 156 } 157 } 158 159 // Nobody should understand anything from the future. 160 for v := uint8(ProtocolVersionMax + 1); v <= uint8(ProtocolVersionMax+10); v++ { 161 grok, err := CanServersUnderstandProtocol(members, v) 162 if err != nil { 163 t.Fatalf("err: %v", err) 164 } 165 if grok { 166 t.Fatalf("server should not grok") 167 } 168 } 169 170 // Add an older server. 171 members = append(members, serf.Member{ 172 Tags: map[string]string{ 173 "role": "consul", 174 "vsn_min": fmt.Sprintf("%d", ProtocolVersionMin), 175 "vsn_max": fmt.Sprintf("%d", ProtocolVersionMax-1), 176 }, 177 }) 178 179 // The servers should no longer understand the max version. 180 for v := ProtocolVersionMin; v <= ProtocolVersionMax; v++ { 181 grok, err := CanServersUnderstandProtocol(members, v) 182 if err != nil { 183 t.Fatalf("err: %v", err) 184 } 185 expected := v < ProtocolVersionMax 186 if grok != expected { 187 t.Fatalf("bad: %v != %v", grok, expected) 188 } 189 } 190 191 // Try a version that's too low for the minimum. 192 { 193 grok, err := CanServersUnderstandProtocol(members, 0) 194 if err != nil { 195 t.Fatalf("err: %v", err) 196 } 197 if grok { 198 t.Fatalf("server should not grok") 199 } 200 } 201 } 202 203 func TestIsConsulNode(t *testing.T) { 204 t.Parallel() 205 m := serf.Member{ 206 Tags: map[string]string{ 207 "role": "node", 208 "dc": "east-aws", 209 }, 210 } 211 valid, dc := isConsulNode(m) 212 if !valid || dc != "east-aws" { 213 t.Fatalf("bad: %v %v", valid, dc) 214 } 215 } 216 217 func TestByteConversion(t *testing.T) { 218 t.Parallel() 219 var val uint64 = 2 << 50 220 raw := uint64ToBytes(val) 221 if bytesToUint64(raw) != val { 222 t.Fatalf("no match") 223 } 224 } 225 226 func TestGenerateUUID(t *testing.T) { 227 t.Parallel() 228 prev := generateUUID() 229 for i := 0; i < 100; i++ { 230 id := generateUUID() 231 if prev == id { 232 t.Fatalf("Should get a new ID!") 233 } 234 235 matched, err := regexp.MatchString( 236 "[\\da-f]{8}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{12}", id) 237 if !matched || err != nil { 238 t.Fatalf("expected match %s %v %s", id, matched, err) 239 } 240 } 241 } 242 243 func TestGetPublicIPv6(t *testing.T) { 244 t.Parallel() 245 ip, _, err := net.ParseCIDR("fe80::1/128") 246 if err != nil { 247 t.Fatalf("failed to parse link-local cidr: %v", err) 248 } 249 250 ip2, _, err := net.ParseCIDR("::1/128") 251 if err != nil { 252 t.Fatalf("failed to parse loopback cidr: %v", err) 253 } 254 255 ip3, _, err := net.ParseCIDR("fc00::1/128") 256 if err != nil { 257 t.Fatalf("failed to parse ULA cidr: %v", err) 258 } 259 260 pubIP, _, err := net.ParseCIDR("2001:0db8:85a3::8a2e:0370:7334/128") 261 if err != nil { 262 t.Fatalf("failed to parse public cidr: %v", err) 263 } 264 265 tests := []struct { 266 addrs []net.Addr 267 expected net.IP 268 err error 269 }{ 270 { 271 addrs: []net.Addr{ 272 &net.IPAddr{ 273 IP: ip, 274 }, 275 &net.IPAddr{ 276 IP: ip2, 277 }, 278 &net.IPAddr{ 279 IP: ip3, 280 }, 281 &net.IPAddr{ 282 IP: pubIP, 283 }, 284 }, 285 expected: pubIP, 286 }, 287 { 288 addrs: []net.Addr{ 289 &net.IPAddr{ 290 IP: ip, 291 }, 292 &net.IPAddr{ 293 IP: ip2, 294 }, 295 &net.IPAddr{ 296 IP: ip3, 297 }, 298 }, 299 err: errors.New("No public IPv6 address found"), 300 }, 301 { 302 addrs: []net.Addr{ 303 &net.IPAddr{ 304 IP: ip, 305 }, 306 &net.IPAddr{ 307 IP: ip, 308 }, 309 &net.IPAddr{ 310 IP: pubIP, 311 }, 312 &net.IPAddr{ 313 IP: pubIP, 314 }, 315 }, 316 err: errors.New("Multiple public IPv6 addresses found. Please configure one."), 317 }, 318 } 319 320 for _, test := range tests { 321 ip, err := getPublicIPv6(test.addrs) 322 switch { 323 case test.err != nil && err != nil: 324 if err.Error() != test.err.Error() { 325 t.Fatalf("unexpected error: %v != %v", test.err, err) 326 } 327 case (test.err == nil && err != nil) || (test.err != nil && err == nil): 328 t.Fatalf("unexpected error: %v != %v", test.err, err) 329 default: 330 if !test.expected.Equal(ip) { 331 t.Fatalf("unexpected ip: %v != %v", ip, test.expected) 332 } 333 } 334 } 335 } 336 337 func TestServersMeetMinimumVersion(t *testing.T) { 338 t.Parallel() 339 makeMember := func(version string) serf.Member { 340 return serf.Member{ 341 Name: "foo", 342 Addr: net.IP([]byte{127, 0, 0, 1}), 343 Tags: map[string]string{ 344 "role": "consul", 345 "id": "asdf", 346 "dc": "east-aws", 347 "port": "10000", 348 "build": version, 349 "wan_join_port": "1234", 350 "vsn": "1", 351 "expect": "3", 352 "raft_vsn": "3", 353 }, 354 Status: serf.StatusAlive, 355 } 356 } 357 358 cases := []struct { 359 members []serf.Member 360 ver *version.Version 361 expected bool 362 }{ 363 // One server, meets reqs 364 { 365 members: []serf.Member{ 366 makeMember("0.7.5"), 367 }, 368 ver: version.Must(version.NewVersion("0.7.5")), 369 expected: true, 370 }, 371 // One server, doesn't meet reqs 372 { 373 members: []serf.Member{ 374 makeMember("0.7.5"), 375 }, 376 ver: version.Must(version.NewVersion("0.8.0")), 377 expected: false, 378 }, 379 // Multiple servers, meets req version 380 { 381 members: []serf.Member{ 382 makeMember("0.7.5"), 383 makeMember("0.8.0"), 384 }, 385 ver: version.Must(version.NewVersion("0.7.5")), 386 expected: true, 387 }, 388 // Multiple servers, doesn't meet req version 389 { 390 members: []serf.Member{ 391 makeMember("0.7.5"), 392 makeMember("0.8.0"), 393 }, 394 ver: version.Must(version.NewVersion("0.8.0")), 395 expected: false, 396 }, 397 } 398 399 for _, tc := range cases { 400 result := ServersMeetMinimumVersion(tc.members, tc.ver) 401 if result != tc.expected { 402 t.Fatalf("bad: %v, %v, %v", result, tc.ver.String(), tc) 403 } 404 } 405 }