github.com/kiali/kiali@v1.84.0/business/checkers/destinationrules/multi_match_checker_test.go (about) 1 package destinationrules 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/assert" 7 networking_v1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" 8 9 "github.com/kiali/kiali/config" 10 "github.com/kiali/kiali/kubernetes" 11 "github.com/kiali/kiali/models" 12 "github.com/kiali/kiali/tests/data" 13 "github.com/kiali/kiali/tests/testutils/validations" 14 ) 15 16 func TestMultiHostMatchCorrect(t *testing.T) { 17 conf := config.NewConfig() 18 config.Set(conf) 19 20 assert := assert.New(t) 21 22 destinationRules := []*networking_v1beta1.DestinationRule{ 23 data.CreateTestDestinationRule("test", "rule1", "host1"), 24 data.CreateTestDestinationRule("test", "rule2", "host2.test.svc.cluster.local"), 25 } 26 27 vals := MultiMatchChecker{ 28 DestinationRules: destinationRules, 29 }.Check() 30 31 assert.Empty(vals) 32 validation, ok := vals[models.IstioValidationKey{ObjectType: "destinationrule", Namespace: "test", Name: "rule2"}] 33 assert.False(ok) 34 assert.Nil(validation) 35 } 36 37 func TestMultiHostMatchInvalid(t *testing.T) { 38 conf := config.NewConfig() 39 config.Set(conf) 40 41 assert := assert.New(t) 42 43 destinationRules := []*networking_v1beta1.DestinationRule{ 44 data.CreateTestDestinationRule("test", "rule1", "host1"), 45 data.CreateTestDestinationRule("test", "rule2", "host1.test.svc.cluster.local"), 46 data.CreateTestDestinationRule("test", "rule3", "host1"), 47 } 48 49 vals := MultiMatchChecker{ 50 DestinationRules: destinationRules, 51 }.Check() 52 53 assert.NotEmpty(vals) 54 assert.Equal(3, len(vals)) 55 56 // Rule1 assertions 57 validationAssertion(assert, vals, "rule1", []string{"rule2", "rule3"}) 58 validationAssertion(assert, vals, "rule2", []string{"rule1", "rule3"}) 59 validationAssertion(assert, vals, "rule3", []string{"rule1", "rule2"}) 60 } 61 62 func validationAssertion(assert *assert.Assertions, vals models.IstioValidations, drName string, refNames []string) { 63 validation, ok := vals[models.IstioValidationKey{ObjectType: "destinationrule", Namespace: "test", Name: drName}] 64 assert.True(ok) 65 assert.True(validation.Valid) // As long as it is warning, this is true 66 assert.NotEmpty(validation.Checks) 67 assert.Equal(models.WarningSeverity, validation.Checks[0].Severity) 68 assert.NoError(validations.ConfirmIstioCheckMessage("destinationrules.multimatch", validation.Checks[0])) 69 70 assert.NotEmpty(validation.References) 71 for _, refName := range refNames { 72 assert.Contains(validation.References, 73 models.IstioValidationKey{ 74 ObjectType: "destinationrule", 75 Namespace: "test", 76 Name: refName, 77 }, 78 ) 79 } 80 } 81 82 func TestMultiHostMatchInvalidShortFormat(t *testing.T) { 83 conf := config.NewConfig() 84 config.Set(conf) 85 86 assert := assert.New(t) 87 88 destinationRules := []*networking_v1beta1.DestinationRule{ 89 data.CreateTestDestinationRule("test", "rule1", "host1"), 90 data.CreateTestDestinationRule("test", "rule2", "host1.test"), 91 } 92 93 vals := MultiMatchChecker{ 94 DestinationRules: destinationRules, 95 }.Check() 96 97 assert.NotEmpty(vals) 98 assert.Equal(2, len(vals)) 99 validation, ok := vals[models.IstioValidationKey{ObjectType: "destinationrule", Namespace: "test", Name: "rule2"}] 100 assert.True(ok) 101 assert.True(validation.Valid) // As long as it is warning, this is true 102 assert.NotEmpty(validation.Checks) 103 assert.Equal(models.WarningSeverity, validation.Checks[0].Severity) 104 assert.NoError(validations.ConfirmIstioCheckMessage("destinationrules.multimatch", validation.Checks[0])) 105 106 assert.NotEmpty(validation.References) 107 assert.Equal("rule1", validation.References[0].Name) 108 } 109 110 func TestMultiHostMatchValidShortFormat(t *testing.T) { 111 conf := config.NewConfig() 112 config.Set(conf) 113 114 assert := assert.New(t) 115 116 destinationRules := []*networking_v1beta1.DestinationRule{ 117 data.CreateTestDestinationRule("test", "rule1", "host1"), 118 data.CreateTestDestinationRule("test", "rule2", "host2.test"), 119 } 120 121 vals := MultiMatchChecker{ 122 DestinationRules: destinationRules, 123 }.Check() 124 125 assert.Empty(vals) 126 validation, ok := vals[models.IstioValidationKey{ObjectType: "destinationrule", Namespace: "test", Name: "rule2"}] 127 assert.False(ok) 128 assert.Nil(validation) 129 } 130 131 func TestMultiHostMatchValidShortFormatDiffNamespace(t *testing.T) { 132 conf := config.NewConfig() 133 config.Set(conf) 134 135 assert := assert.New(t) 136 137 destinationRules := []*networking_v1beta1.DestinationRule{ 138 data.CreateTestDestinationRule("test", "rule1", "host1"), 139 data.CreateTestDestinationRule("test", "rule2", "host2.bookinfo"), 140 } 141 142 vals := MultiMatchChecker{ 143 Namespaces: models.Namespaces{ 144 models.Namespace{Name: "bookinfo"}, 145 models.Namespace{Name: "test"}, 146 }, 147 DestinationRules: destinationRules, 148 }.Check() 149 150 // MultiMatchChecker shouldn't fail if a host is in a different namespace 151 assert.Empty(vals) 152 } 153 154 func TestMultiHostMatchWildcardInvalid(t *testing.T) { 155 conf := config.NewConfig() 156 config.Set(conf) 157 158 assert := assert.New(t) 159 160 destinationRules := []*networking_v1beta1.DestinationRule{ 161 data.CreateTestDestinationRule("test", "rule1", "host1"), 162 data.CreateTestDestinationRule("test", "rule2", "*.test.svc.cluster.local"), 163 } 164 165 vals := MultiMatchChecker{ 166 DestinationRules: destinationRules, 167 }.Check() 168 169 assert.NotEmpty(vals) 170 validation, ok := vals[models.IstioValidationKey{ObjectType: "destinationrule", Namespace: "test", Name: "rule2"}] 171 assert.True(ok) 172 assert.True(validation.Valid) // As long as it is warning, this is true 173 assert.NotEmpty(validation.Checks) 174 assert.Equal(models.WarningSeverity, validation.Checks[0].Severity) 175 176 assert.NotEmpty(validation.References) 177 assert.Equal("rule1", validation.References[0].Name) 178 179 destinationRules = []*networking_v1beta1.DestinationRule{ 180 data.CreateTestDestinationRule("test", "rule2", "*.test.svc.cluster.local"), 181 data.CreateTestDestinationRule("test", "rule1", "host1"), 182 } 183 184 vals = MultiMatchChecker{ 185 DestinationRules: destinationRules, 186 }.Check() 187 188 assert.NotEmpty(vals) 189 validation, ok = vals[models.IstioValidationKey{ObjectType: "destinationrule", Namespace: "test", Name: "rule1"}] 190 assert.True(ok) 191 assert.True(validation.Valid) // As long as it is warning, this is true 192 assert.NotEmpty(validation.Checks) 193 assert.Equal(models.WarningSeverity, validation.Checks[0].Severity) 194 195 assert.NotEmpty(validation.References) 196 assert.Equal("rule2", validation.References[0].Name) 197 } 198 199 func TestMultiHostMatchBothWildcardInvalid(t *testing.T) { 200 conf := config.NewConfig() 201 config.Set(conf) 202 203 assert := assert.New(t) 204 205 destinationRules := []*networking_v1beta1.DestinationRule{ 206 data.CreateTestDestinationRule("test", "rule1", "*"), 207 data.CreateTestDestinationRule("test", "rule2", "*.test.svc.cluster.local"), 208 } 209 210 vals := MultiMatchChecker{ 211 DestinationRules: destinationRules, 212 }.Check() 213 214 assert.NotEmpty(vals) 215 validation, ok := vals[models.IstioValidationKey{ObjectType: "destinationrule", Namespace: "test", Name: "rule2"}] 216 assert.True(ok) 217 assert.True(validation.Valid) // As long as it is warning, this is true 218 assert.NotEmpty(validation.Checks) 219 assert.Equal(models.WarningSeverity, validation.Checks[0].Severity) 220 221 assert.NotEmpty(validation.References) 222 assert.Equal("rule1", validation.References[0].Name) 223 224 destinationRules = []*networking_v1beta1.DestinationRule{ 225 data.CreateTestDestinationRule("test", "rule2", "*.test.svc.cluster.local"), 226 data.CreateTestDestinationRule("test", "rule1", "*"), 227 } 228 229 vals = MultiMatchChecker{ 230 DestinationRules: destinationRules, 231 }.Check() 232 233 assert.NotEmpty(vals) 234 validation, ok = vals[models.IstioValidationKey{ObjectType: "destinationrule", Namespace: "test", Name: "rule1"}] 235 assert.True(ok) 236 assert.True(validation.Valid) // As long as it is warning, this is true 237 assert.NotEmpty(validation.Checks) 238 assert.Equal(models.WarningSeverity, validation.Checks[0].Severity) 239 240 assert.NotEmpty(validation.References) 241 assert.Equal("rule2", validation.References[0].Name) 242 } 243 244 func TestMultiHostMatchingMeshWideMTLSDestinationRule(t *testing.T) { 245 conf := config.NewConfig() 246 config.Set(conf) 247 248 assert := assert.New(t) 249 250 destinationRules := []*networking_v1beta1.DestinationRule{ 251 data.CreateTestDestinationRule("test", "rule1", "host1"), 252 data.AddTrafficPolicyToDestinationRule(data.CreateMTLSTrafficPolicyForDestinationRules(), 253 data.CreateTestDestinationRule("test", "rule2", "*.local")), 254 } 255 256 vals := MultiMatchChecker{ 257 DestinationRules: destinationRules, 258 }.Check() 259 260 assert.Empty(vals) 261 validation, ok := vals[models.IstioValidationKey{ObjectType: "destinationrule", Namespace: "test", Name: "rule2"}] 262 assert.False(ok) 263 assert.Nil(validation) 264 } 265 266 func TestMultiHostMatchingNamespaceWideMTLSDestinationRule(t *testing.T) { 267 conf := config.NewConfig() 268 config.Set(conf) 269 270 assert := assert.New(t) 271 272 destinationRules := []*networking_v1beta1.DestinationRule{ 273 data.CreateTestDestinationRule("test", "rule1", "host1"), 274 data.AddTrafficPolicyToDestinationRule(data.CreateMTLSTrafficPolicyForDestinationRules(), 275 data.CreateTestDestinationRule("test", "rule2", "*.test.svc.cluster.local")), 276 } 277 278 vals := MultiMatchChecker{ 279 DestinationRules: destinationRules, 280 }.Check() 281 282 assert.Empty(vals) 283 validation, ok := vals[models.IstioValidationKey{ObjectType: "destinationrule", Namespace: "test", Name: "rule2"}] 284 assert.False(ok) 285 assert.Nil(validation) 286 } 287 288 func TestMultiHostMatchDifferentSubsets(t *testing.T) { 289 conf := config.NewConfig() 290 config.Set(conf) 291 292 assert := assert.New(t) 293 294 destinationRules := []*networking_v1beta1.DestinationRule{ 295 data.AddSubsetToDestinationRule(data.CreateSubset("v1", "v1"), 296 data.AddSubsetToDestinationRule(data.CreateSubset("v2", "v2"), data.CreateEmptyDestinationRule("test", "rule1", "host1"))), 297 data.AddSubsetToDestinationRule(data.CreateSubset("v3", "v3"), 298 data.AddSubsetToDestinationRule(data.CreateSubset("v4", "v4"), data.CreateEmptyDestinationRule("test", "rule2", "host1"))), 299 } 300 301 vals := MultiMatchChecker{ 302 DestinationRules: destinationRules, 303 }.Check() 304 305 assert.Empty(vals) 306 307 destinationRules = append(destinationRules, 308 data.AddSubsetToDestinationRule(data.CreateSubset("v1", "v1"), 309 data.AddSubsetToDestinationRule(data.CreateSubset("v5", "v5"), data.CreateEmptyDestinationRule("test", "rule5", "*.test.svc.cluster.local"))), 310 ) 311 312 vals = MultiMatchChecker{ 313 DestinationRules: destinationRules, 314 }.Check() 315 316 assert.NotEmpty(vals) 317 } 318 319 func TestReviewsExample(t *testing.T) { 320 conf := config.NewConfig() 321 config.Set(conf) 322 323 assert := assert.New(t) 324 325 destinationRules := []*networking_v1beta1.DestinationRule{ 326 data.AddSubsetToDestinationRule(data.CreateSubset("v2", "v2"), 327 data.AddSubsetToDestinationRule(data.CreateSubset("v3", "v3"), data.CreateEmptyDestinationRule("bookinfo", "reviews", "reviews"))), 328 data.AddSubsetToDestinationRule(data.CreateSubset("v1", "v1"), data.CreateEmptyDestinationRule("bookinfo", "reviews2", "reviews")), 329 } 330 331 vals := MultiMatchChecker{ 332 DestinationRules: destinationRules, 333 }.Check() 334 335 assert.Empty(vals) 336 337 allMatch := data.CreateEmptyDestinationRule("bookinfo", "reviews3", "reviews") 338 destinationRules = append(destinationRules, allMatch) 339 340 vals = MultiMatchChecker{ 341 DestinationRules: destinationRules, 342 }.Check() 343 344 assert.NotEmpty(vals) 345 assert.Equal(3, len(vals)) 346 validation, ok := vals[models.IstioValidationKey{ObjectType: "destinationrule", Namespace: "bookinfo", Name: "reviews3"}] 347 assert.True(ok) 348 assert.True(validation.Valid) 349 assert.NotEmpty(validation.Checks) 350 assert.Equal(models.WarningSeverity, validation.Checks[0].Severity) 351 assert.Equal(1, len(validation.Checks)) 352 353 assert.Equal(2, len(validation.References)) // Both reviews and reviews2 is faulty 354 } 355 356 func TestMultiServiceEntry(t *testing.T) { 357 conf := config.NewConfig() 358 config.Set(conf) 359 360 assert := assert.New(t) 361 362 seA := data.AddPortDefinitionToServiceEntry(data.CreateEmptyServicePortDefinition(443, "https", "TLS"), data.CreateEmptyMeshExternalServiceEntry("service-a", "test", []string{"api.service_a.com"})) 363 seB := data.AddPortDefinitionToServiceEntry(data.CreateEmptyServicePortDefinition(443, "https", "TLS"), data.CreateEmptyMeshExternalServiceEntry("service-b", "test", []string{"api.service_b.com"})) 364 365 drA := data.CreateEmptyDestinationRule("test", "service-a", "api.service_a.com") 366 drB := data.CreateEmptyDestinationRule("test", "service-b", "api.service_b.com") 367 368 vals := MultiMatchChecker{ 369 DestinationRules: []*networking_v1beta1.DestinationRule{drA, drB}, 370 ServiceEntries: kubernetes.ServiceEntryHostnames([]*networking_v1beta1.ServiceEntry{seA, seB}), 371 }.Check() 372 373 assert.Empty(vals) 374 } 375 376 func TestMultiServiceEntryInvalid(t *testing.T) { 377 conf := config.NewConfig() 378 config.Set(conf) 379 380 assert := assert.New(t) 381 382 seA := data.AddPortDefinitionToServiceEntry(data.CreateEmptyServicePortDefinition(443, "https", "TLS"), data.CreateEmptyMeshExternalServiceEntry("service-a", "test", []string{"api.service_a.com"})) 383 384 drA := data.CreateEmptyDestinationRule("test", "service-a", "api.service_a.com") 385 drB := data.CreateEmptyDestinationRule("test", "service-a2", "api.service_a.com") 386 387 vals := MultiMatchChecker{ 388 DestinationRules: []*networking_v1beta1.DestinationRule{drA, drB}, 389 ServiceEntries: kubernetes.ServiceEntryHostnames([]*networking_v1beta1.ServiceEntry{seA}), 390 }.Check() 391 392 assert.NotEmpty(vals) 393 assert.Equal(2, len(vals)) 394 validation, ok := vals[models.IstioValidationKey{ObjectType: "destinationrule", Namespace: "test", Name: "service-a2"}] 395 assert.True(ok) 396 assert.True(validation.Valid) 397 assert.NotEmpty(validation.Checks) 398 assert.Equal(models.WarningSeverity, validation.Checks[0].Severity) 399 assert.Equal(1, len(validation.Checks)) 400 401 assert.Equal(1, len(validation.References)) // Both reviews and reviews2 is faulty 402 }