1package dependency 2 3import ( 4 "fmt" 5 "testing" 6 7 "github.com/hashicorp/consul/api" 8 "github.com/stretchr/testify/assert" 9) 10 11func TestNewHealthServiceQuery(t *testing.T) { 12 t.Parallel() 13 14 cases := []struct { 15 name string 16 i string 17 exp *HealthServiceQuery 18 err bool 19 }{ 20 { 21 "empty", 22 "", 23 nil, 24 true, 25 }, 26 { 27 "dc_only", 28 "@dc1", 29 nil, 30 true, 31 }, 32 { 33 "near_only", 34 "~near", 35 nil, 36 true, 37 }, 38 { 39 "tag_only", 40 "tag.", 41 nil, 42 true, 43 }, 44 { 45 "name", 46 "name", 47 &HealthServiceQuery{ 48 filters: []string{"passing"}, 49 name: "name", 50 }, 51 false, 52 }, 53 { 54 "name_dc", 55 "name@dc1", 56 &HealthServiceQuery{ 57 dc: "dc1", 58 filters: []string{"passing"}, 59 name: "name", 60 }, 61 false, 62 }, 63 { 64 "name_dc_near", 65 "name@dc1~near", 66 &HealthServiceQuery{ 67 dc: "dc1", 68 filters: []string{"passing"}, 69 name: "name", 70 near: "near", 71 }, 72 false, 73 }, 74 { 75 "name_near", 76 "name~near", 77 &HealthServiceQuery{ 78 filters: []string{"passing"}, 79 name: "name", 80 near: "near", 81 }, 82 false, 83 }, 84 { 85 "tag_name", 86 "tag.name", 87 &HealthServiceQuery{ 88 filters: []string{"passing"}, 89 name: "name", 90 tag: "tag", 91 }, 92 false, 93 }, 94 { 95 "tag_name_dc", 96 "tag.name@dc", 97 &HealthServiceQuery{ 98 dc: "dc", 99 filters: []string{"passing"}, 100 name: "name", 101 tag: "tag", 102 }, 103 false, 104 }, 105 { 106 "tag_name_near", 107 "tag.name~near", 108 &HealthServiceQuery{ 109 filters: []string{"passing"}, 110 name: "name", 111 near: "near", 112 tag: "tag", 113 }, 114 false, 115 }, 116 { 117 "tag_name_dc_near", 118 "tag.name@dc~near", 119 &HealthServiceQuery{ 120 dc: "dc", 121 filters: []string{"passing"}, 122 name: "name", 123 near: "near", 124 tag: "tag", 125 }, 126 false, 127 }, 128 } 129 130 for i, tc := range cases { 131 t.Run(fmt.Sprintf("%d_%s", i, tc.name), func(t *testing.T) { 132 act, err := NewHealthServiceQuery(tc.i) 133 if (err != nil) != tc.err { 134 t.Fatal(err) 135 } 136 137 if act != nil { 138 act.stopCh = nil 139 } 140 141 assert.Equal(t, tc.exp, act) 142 }) 143 } 144 // Connect 145 // all tests above also test connect, just need to check enabling it 146 t.Run("connect_query", func(t *testing.T) { 147 act, err := NewHealthConnectQuery("name") 148 if err != nil { 149 t.Fatal(err) 150 } 151 if act != nil { 152 act.stopCh = nil 153 } 154 exp := &HealthServiceQuery{ 155 filters: []string{"passing"}, 156 name: "name", 157 connect: true, 158 } 159 160 assert.Equal(t, exp, act) 161 }) 162} 163 164func TestHealthConnectServiceQuery_Fetch(t *testing.T) { 165 t.Parallel() 166 cases := []struct { 167 name string 168 in string 169 exp []*HealthService 170 }{ 171 { 172 "connect-service", 173 "foo", 174 []*HealthService{ 175 &HealthService{ 176 Name: "foo-sidecar-proxy", 177 ID: "foo", 178 Port: 21999, 179 Status: "passing", 180 Address: "127.0.0.1", 181 NodeAddress: "127.0.0.1", 182 Tags: ServiceTags([]string{}), 183 NodeMeta: map[string]string{ 184 "consul-network-segment": ""}, 185 Weights: api.AgentWeights{ 186 Passing: 1, 187 Warning: 1, 188 }, 189 }, 190 }, 191 }, 192 } 193 for i, tc := range cases { 194 t.Run(fmt.Sprintf("%d_%s", i, tc.name), func(t *testing.T) { 195 d, err := NewHealthConnectQuery(tc.in) 196 if err != nil { 197 t.Fatal(err) 198 } 199 defer func() { 200 d.Stop() 201 }() 202 res, _, err := d.Fetch(testClients, nil) 203 if err != nil { 204 t.Fatal(err) 205 } 206 var act []*HealthService 207 if act = res.([]*HealthService); len(act) != 1 { 208 t.Fatal("Expected 1 result, got ", len(act)) 209 } 210 // blank out fields we don't want to test 211 inst := act[0] 212 inst.Node, inst.NodeID = "", "" 213 inst.Checks = nil 214 inst.NodeTaggedAddresses = nil 215 216 assert.Equal(t, tc.exp, act) 217 }) 218 } 219} 220 221func TestHealthServiceQuery_Fetch(t *testing.T) { 222 t.Parallel() 223 224 cases := []struct { 225 name string 226 i string 227 exp []*HealthService 228 }{ 229 { 230 "consul", 231 "consul", 232 []*HealthService{ 233 &HealthService{ 234 Node: testConsul.Config.NodeName, 235 NodeAddress: testConsul.Config.Bind, 236 NodeTaggedAddresses: map[string]string{ 237 "lan": "127.0.0.1", 238 "wan": "127.0.0.1", 239 }, 240 NodeMeta: map[string]string{ 241 "consul-network-segment": "", 242 }, 243 ServiceMeta: map[string]string{}, 244 Address: testConsul.Config.Bind, 245 ID: "consul", 246 Name: "consul", 247 Tags: []string{}, 248 Status: "passing", 249 Port: testConsul.Config.Ports.Server, 250 Weights: api.AgentWeights{ 251 Passing: 1, 252 Warning: 1, 253 }, 254 }, 255 }, 256 }, 257 { 258 "filters", 259 "consul|warning", 260 []*HealthService{}, 261 }, 262 { 263 "multifilter", 264 "consul|warning,passing", 265 []*HealthService{ 266 &HealthService{ 267 Node: testConsul.Config.NodeName, 268 NodeAddress: testConsul.Config.Bind, 269 NodeTaggedAddresses: map[string]string{ 270 "lan": "127.0.0.1", 271 "wan": "127.0.0.1", 272 }, 273 NodeMeta: map[string]string{ 274 "consul-network-segment": "", 275 }, 276 ServiceMeta: map[string]string{}, 277 Address: testConsul.Config.Bind, 278 ID: "consul", 279 Name: "consul", 280 Tags: []string{}, 281 Status: "passing", 282 Port: testConsul.Config.Ports.Server, 283 Weights: api.AgentWeights{ 284 Passing: 1, 285 Warning: 1, 286 }, 287 }, 288 }, 289 }, 290 { 291 "service-meta", 292 "service-meta", 293 []*HealthService{ 294 &HealthService{ 295 Node: testConsul.Config.NodeName, 296 NodeAddress: testConsul.Config.Bind, 297 NodeTaggedAddresses: map[string]string{ 298 "lan": "127.0.0.1", 299 "wan": "127.0.0.1", 300 }, 301 NodeMeta: map[string]string{ 302 "consul-network-segment": "", 303 }, 304 ServiceMeta: map[string]string{ 305 "meta1": "value1", 306 }, 307 Address: testConsul.Config.Bind, 308 ID: "service-meta", 309 Name: "service-meta", 310 Tags: []string{"tag1"}, 311 Status: "passing", 312 Weights: api.AgentWeights{ 313 Passing: 1, 314 Warning: 1, 315 }, 316 }, 317 }, 318 }, 319 { 320 "service-taggedAddresses", 321 "service-taggedAddresses", 322 []*HealthService{ 323 &HealthService{ 324 Node: testConsul.Config.NodeName, 325 NodeAddress: testConsul.Config.Bind, 326 NodeTaggedAddresses: map[string]string{ 327 "lan": "127.0.0.1", 328 "wan": "127.0.0.1", 329 }, 330 NodeMeta: map[string]string{ 331 "consul-network-segment": "", 332 }, 333 ServiceMeta: map[string]string{}, 334 Address: testConsul.Config.Bind, 335 ServiceTaggedAddresses: map[string]api.ServiceAddress{ 336 "lan": { 337 Address: "192.0.2.1", 338 Port: 80, 339 }, 340 "wan": { 341 Address: "192.0.2.2", 342 Port: 443, 343 }, 344 }, 345 ID: "service-taggedAddresses", 346 Name: "service-taggedAddresses", 347 Tags: []string{}, 348 Status: "passing", 349 Weights: api.AgentWeights{ 350 Passing: 1, 351 Warning: 1, 352 }, 353 }, 354 }, 355 }, 356 } 357 358 for i, tc := range cases { 359 t.Run(fmt.Sprintf("%d_%s", i, tc.name), func(t *testing.T) { 360 d, err := NewHealthServiceQuery(tc.i) 361 if err != nil { 362 t.Fatal(err) 363 } 364 365 act, _, err := d.Fetch(testClients, nil) 366 if err != nil { 367 t.Fatal(err) 368 } 369 370 if act != nil { 371 for _, v := range act.([]*HealthService) { 372 v.NodeID = "" 373 v.Checks = nil 374 // delete any version data from ServiceMeta 375 v.ServiceMeta = filterVersionMeta(v.ServiceMeta) 376 v.NodeTaggedAddresses = filterAddresses( 377 v.NodeTaggedAddresses) 378 } 379 } 380 381 assert.Equal(t, tc.exp, act) 382 }) 383 } 384} 385 386func TestHealthServiceQuery_String(t *testing.T) { 387 t.Parallel() 388 389 cases := []struct { 390 name string 391 i string 392 exp string 393 }{ 394 { 395 "name", 396 "name", 397 "health.service(name|passing)", 398 }, 399 { 400 "name_dc", 401 "name@dc", 402 "health.service(name@dc|passing)", 403 }, 404 { 405 "name_filter", 406 "name|any", 407 "health.service(name|any)", 408 }, 409 { 410 "name_multifilter", 411 "name|warning,passing", 412 "health.service(name|passing,warning)", 413 }, 414 { 415 "name_near", 416 "name~near", 417 "health.service(name~near|passing)", 418 }, 419 { 420 "name_near_filter", 421 "name~near|any", 422 "health.service(name~near|any)", 423 }, 424 { 425 "name_dc_near", 426 "name@dc~near", 427 "health.service(name@dc~near|passing)", 428 }, 429 { 430 "name_dc_near_filter", 431 "name@dc~near|any", 432 "health.service(name@dc~near|any)", 433 }, 434 { 435 "tag_name", 436 "tag.name", 437 "health.service(tag.name|passing)", 438 }, 439 { 440 "tag_name_dc", 441 "tag.name@dc", 442 "health.service(tag.name@dc|passing)", 443 }, 444 { 445 "tag_name_near", 446 "tag.name~near", 447 "health.service(tag.name~near|passing)", 448 }, 449 { 450 "tag_name_dc_near", 451 "tag.name@dc~near", 452 "health.service(tag.name@dc~near|passing)", 453 }, 454 } 455 456 for i, tc := range cases { 457 t.Run(fmt.Sprintf("%d_%s", i, tc.name), func(t *testing.T) { 458 d, err := NewHealthServiceQuery(tc.i) 459 if err != nil { 460 t.Fatal(err) 461 } 462 assert.Equal(t, tc.exp, d.String()) 463 }) 464 } 465} 466 467func TestHealthServiceQueryConnect_String(t *testing.T) { 468 t.Parallel() 469 470 cases := []struct { 471 name string 472 fact func(string) (*HealthServiceQuery, error) 473 in string 474 exp string 475 }{ 476 { 477 "name", 478 NewHealthServiceQuery, 479 "name", 480 "health.service(name|passing)", 481 }, 482 { 483 "name", 484 NewHealthConnectQuery, 485 "name", 486 "health.connect(name|passing)", 487 }, 488 } 489 490 for i, tc := range cases { 491 t.Run(fmt.Sprintf("%d_%s", i, tc.name), func(t *testing.T) { 492 d, err := tc.fact(tc.in) 493 if err != nil { 494 t.Fatal(err) 495 } 496 assert.Equal(t, tc.exp, d.String()) 497 }) 498 } 499} 500