vitess.io/vitess@v0.16.2/go/vt/vtadmin/cluster/discovery/discovery_dynamic_test.go (about) 1 /* 2 Copyright 2022 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package discovery 18 19 import ( 20 "context" 21 "testing" 22 23 "github.com/stretchr/testify/assert" 24 "github.com/stretchr/testify/require" 25 26 vtadminpb "vitess.io/vitess/go/vt/proto/vtadmin" 27 ) 28 29 func TestDynamicDiscoverVTGate(t *testing.T) { 30 t.Parallel() 31 32 tests := []struct { 33 name string 34 contents []byte 35 expected *vtadminpb.VTGate 36 tags []string 37 shouldErr bool 38 }{ 39 { 40 name: "empty config", 41 contents: []byte(`{}`), 42 expected: nil, 43 shouldErr: true, 44 }, 45 { 46 name: "one gate", 47 contents: []byte(` 48 { 49 "vtgates": [{ 50 "host": { 51 "hostname": "127.0.0.1:12345" 52 } 53 }] 54 } 55 `), 56 expected: &vtadminpb.VTGate{ 57 Hostname: "127.0.0.1:12345", 58 }, 59 }, 60 { 61 name: "filtered by tags (one match)", 62 contents: []byte(` 63 { 64 "vtgates": [ 65 { 66 "host": { 67 "hostname": "127.0.0.1:11111" 68 }, 69 "tags": ["cell:cellA"] 70 }, 71 { 72 "host": { 73 "hostname": "127.0.0.1:22222" 74 }, 75 "tags": ["cell:cellB"] 76 }, 77 { 78 "host": { 79 "hostname": "127.0.0.1:33333" 80 }, 81 "tags": ["cell:cellA"] 82 } 83 ] 84 } 85 `), 86 expected: &vtadminpb.VTGate{ 87 Hostname: "127.0.0.1:22222", 88 }, 89 tags: []string{"cell:cellB"}, 90 }, 91 } 92 93 ctx := context.Background() 94 95 for _, tt := range tests { 96 tt := tt 97 98 t.Run(tt.name, func(t *testing.T) { 99 t.Parallel() 100 disco := &DynamicDiscovery{} 101 err := disco.parseConfig(tt.contents) 102 require.NoError(t, err) 103 104 gate, err := disco.DiscoverVTGate(ctx, tt.tags) 105 if tt.shouldErr { 106 assert.Error(t, err) 107 return 108 } 109 110 assert.NoError(t, err) 111 assert.Equal(t, tt.expected, gate) 112 }) 113 } 114 } 115 116 func TestDynamicDiscoverVTGates(t *testing.T) { 117 t.Parallel() 118 119 tests := []struct { 120 name string 121 contents []byte 122 tags []string 123 expected []*vtadminpb.VTGate 124 // True if the test should produce an error on the DiscoverVTGates call 125 shouldErr bool 126 // True if the test should produce an error on the disco.parseConfig step 127 shouldErrConfig bool 128 }{ 129 { 130 name: "empty config", 131 contents: []byte(`{}`), 132 expected: []*vtadminpb.VTGate{}, 133 shouldErr: false, 134 }, 135 { 136 name: "no tags", 137 contents: []byte(` 138 { 139 "vtgates": [ 140 { 141 "host": { 142 "hostname": "127.0.0.1:12345" 143 } 144 }, 145 { 146 "host": { 147 "hostname": "127.0.0.1:67890" 148 } 149 } 150 ] 151 } 152 `), 153 expected: []*vtadminpb.VTGate{ 154 {Hostname: "127.0.0.1:12345"}, 155 {Hostname: "127.0.0.1:67890"}, 156 }, 157 shouldErr: false, 158 }, 159 { 160 name: "filtered by tags", 161 contents: []byte(` 162 { 163 "vtgates": [ 164 { 165 "host": { 166 "hostname": "127.0.0.1:11111" 167 }, 168 "tags": ["cell:cellA"] 169 }, 170 { 171 "host": { 172 "hostname": "127.0.0.1:22222" 173 }, 174 "tags": ["cell:cellB"] 175 }, 176 { 177 "host": { 178 "hostname": "127.0.0.1:33333" 179 }, 180 "tags": ["cell:cellA"] 181 } 182 ] 183 } 184 `), 185 tags: []string{"cell:cellA"}, 186 expected: []*vtadminpb.VTGate{ 187 {Hostname: "127.0.0.1:11111"}, 188 {Hostname: "127.0.0.1:33333"}, 189 }, 190 shouldErr: false, 191 }, 192 { 193 name: "filtered by multiple tags", 194 contents: []byte(` 195 { 196 "vtgates": [ 197 { 198 "host": { 199 "hostname": "127.0.0.1:11111" 200 }, 201 "tags": ["cell:cellA"] 202 }, 203 { 204 "host": { 205 "hostname": "127.0.0.1:22222" 206 }, 207 "tags": ["cell:cellA", "pool:poolZ"] 208 }, 209 { 210 "host": { 211 "hostname": "127.0.0.1:33333" 212 }, 213 "tags": ["pool:poolZ"] 214 } 215 ] 216 } 217 `), 218 tags: []string{"cell:cellA", "pool:poolZ"}, 219 expected: []*vtadminpb.VTGate{ 220 {Hostname: "127.0.0.1:22222"}, 221 }, 222 shouldErr: false, 223 }, 224 { 225 name: "invalid json", 226 contents: []byte(` 227 { 228 "vtgates": "malformed" 229 } 230 `), 231 tags: []string{}, 232 shouldErr: false, 233 shouldErrConfig: true, 234 }, 235 } 236 237 ctx := context.Background() 238 239 for _, tt := range tests { 240 tt := tt 241 242 t.Run(tt.name, func(t *testing.T) { 243 t.Parallel() 244 245 disco := &DynamicDiscovery{} 246 247 err := disco.parseConfig(tt.contents) 248 if tt.shouldErrConfig { 249 assert.Error(t, err) 250 } else { 251 require.NoError(t, err) 252 } 253 254 gates, err := disco.DiscoverVTGates(ctx, tt.tags) 255 if tt.shouldErr { 256 assert.Error(t, err) 257 return 258 } 259 260 assert.NoError(t, err) 261 assert.ElementsMatch(t, tt.expected, gates) 262 }) 263 } 264 } 265 266 func TestDynamicDiscoverVtctld(t *testing.T) { 267 t.Parallel() 268 269 tests := []struct { 270 name string 271 contents []byte 272 expected *vtadminpb.Vtctld 273 tags []string 274 shouldErr bool 275 }{ 276 { 277 name: "empty config", 278 contents: []byte(`{}`), 279 expected: nil, 280 shouldErr: true, 281 }, 282 { 283 name: "one vtctld", 284 contents: []byte(` 285 { 286 "vtctlds": [{ 287 "host": { 288 "hostname": "127.0.0.1:12345" 289 } 290 }] 291 } 292 `), 293 expected: &vtadminpb.Vtctld{ 294 Hostname: "127.0.0.1:12345", 295 }, 296 }, 297 { 298 name: "filtered by tags (one match)", 299 contents: []byte(` 300 { 301 "vtctlds": [ 302 { 303 "host": { 304 "hostname": "127.0.0.1:11111" 305 }, 306 "tags": ["cell:cellA"] 307 }, 308 { 309 "host": { 310 "hostname": "127.0.0.1:22222" 311 }, 312 "tags": ["cell:cellB"] 313 }, 314 { 315 "host": { 316 "hostname": "127.0.0.1:33333" 317 }, 318 "tags": ["cell:cellA"] 319 } 320 ] 321 } 322 `), 323 expected: &vtadminpb.Vtctld{ 324 Hostname: "127.0.0.1:22222", 325 }, 326 tags: []string{"cell:cellB"}, 327 }, 328 } 329 330 ctx := context.Background() 331 332 for _, tt := range tests { 333 tt := tt 334 335 t.Run(tt.name, func(t *testing.T) { 336 t.Parallel() 337 338 disco := &DynamicDiscovery{} 339 err := disco.parseConfig(tt.contents) 340 require.NoError(t, err) 341 342 vtctld, err := disco.DiscoverVtctld(ctx, tt.tags) 343 if tt.shouldErr { 344 assert.Error(t, err) 345 return 346 } 347 348 assert.NoError(t, err) 349 assert.Equal(t, tt.expected, vtctld) 350 }) 351 } 352 } 353 354 func TestDynamicDiscoverVtctlds(t *testing.T) { 355 t.Parallel() 356 357 tests := []struct { 358 name string 359 contents []byte 360 tags []string 361 expected []*vtadminpb.Vtctld 362 // True if the test should produce an error on the DiscoverVTGates call 363 shouldErr bool 364 // True if the test should produce an error on the disco.parseConfig step 365 shouldErrConfig bool 366 }{ 367 { 368 name: "empty config", 369 contents: []byte(`{}`), 370 expected: []*vtadminpb.Vtctld{}, 371 shouldErr: false, 372 }, 373 { 374 name: "no tags", 375 contents: []byte(` 376 { 377 "vtctlds": [ 378 { 379 "host": { 380 "hostname": "127.0.0.1:12345" 381 } 382 }, 383 { 384 "host": { 385 "hostname": "127.0.0.1:67890" 386 } 387 } 388 ] 389 } 390 `), 391 expected: []*vtadminpb.Vtctld{ 392 {Hostname: "127.0.0.1:12345"}, 393 {Hostname: "127.0.0.1:67890"}, 394 }, 395 shouldErr: false, 396 }, 397 { 398 name: "filtered by tags", 399 contents: []byte(` 400 { 401 "vtctlds": [ 402 { 403 "host": { 404 "hostname": "127.0.0.1:11111" 405 }, 406 "tags": ["cell:cellA"] 407 }, 408 { 409 "host": { 410 "hostname": "127.0.0.1:22222" 411 }, 412 "tags": ["cell:cellB"] 413 }, 414 { 415 "host": { 416 "hostname": "127.0.0.1:33333" 417 }, 418 "tags": ["cell:cellA"] 419 } 420 ] 421 } 422 `), 423 tags: []string{"cell:cellA"}, 424 expected: []*vtadminpb.Vtctld{ 425 {Hostname: "127.0.0.1:11111"}, 426 {Hostname: "127.0.0.1:33333"}, 427 }, 428 shouldErr: false, 429 }, 430 { 431 name: "filtered by multiple tags", 432 contents: []byte(` 433 { 434 "vtctlds": [ 435 { 436 "host": { 437 "hostname": "127.0.0.1:11111" 438 }, 439 "tags": ["cell:cellA"] 440 }, 441 { 442 "host": { 443 "hostname": "127.0.0.1:22222" 444 }, 445 "tags": ["cell:cellA", "pool:poolZ"] 446 }, 447 { 448 "host": { 449 "hostname": "127.0.0.1:33333" 450 }, 451 "tags": ["pool:poolZ"] 452 } 453 ] 454 } 455 `), 456 tags: []string{"cell:cellA", "pool:poolZ"}, 457 expected: []*vtadminpb.Vtctld{ 458 {Hostname: "127.0.0.1:22222"}, 459 }, 460 shouldErr: false, 461 }, 462 { 463 name: "invalid json", 464 contents: []byte(` 465 { 466 "vtctlds": "malformed" 467 } 468 `), 469 tags: []string{}, 470 shouldErr: false, 471 shouldErrConfig: true, 472 }, 473 } 474 475 ctx := context.Background() 476 477 for _, tt := range tests { 478 tt := tt 479 480 t.Run(tt.name, func(t *testing.T) { 481 t.Parallel() 482 483 disco := &DynamicDiscovery{} 484 485 err := disco.parseConfig(tt.contents) 486 if tt.shouldErrConfig { 487 assert.Error(t, err) 488 } else { 489 require.NoError(t, err) 490 } 491 492 vtctlds, err := disco.DiscoverVtctlds(ctx, tt.tags) 493 if tt.shouldErr { 494 assert.Error(t, err) 495 return 496 } 497 498 assert.NoError(t, err) 499 assert.ElementsMatch(t, tt.expected, vtctlds) 500 }) 501 } 502 }