kuma

Форк
0
/
context_test.go 
557 строк · 15.0 Кб
1
package context_test
2

3
import (
4
	stdcontext "context"
5
	"fmt"
6

7
	. "github.com/onsi/ginkgo/v2"
8
	. "github.com/onsi/gomega"
9

10
	mesh_proto "github.com/kumahq/kuma/api/mesh/v1alpha1"
11
	system_proto "github.com/kumahq/kuma/api/system/v1alpha1"
12
	kuma_cp "github.com/kumahq/kuma/pkg/config/app/kuma-cp"
13
	config_store "github.com/kumahq/kuma/pkg/config/core/resources/store"
14
	config_manager "github.com/kumahq/kuma/pkg/core/config/manager"
15
	core_mesh "github.com/kumahq/kuma/pkg/core/resources/apis/mesh"
16
	core_system "github.com/kumahq/kuma/pkg/core/resources/apis/system"
17
	"github.com/kumahq/kuma/pkg/core/resources/manager"
18
	"github.com/kumahq/kuma/pkg/core/resources/model"
19
	"github.com/kumahq/kuma/pkg/core/resources/registry"
20
	core_store "github.com/kumahq/kuma/pkg/core/resources/store"
21
	"github.com/kumahq/kuma/pkg/kds"
22
	"github.com/kumahq/kuma/pkg/kds/context"
23
	"github.com/kumahq/kuma/pkg/kds/hash"
24
	"github.com/kumahq/kuma/pkg/kds/reconcile"
25
	"github.com/kumahq/kuma/pkg/kds/util"
26
	"github.com/kumahq/kuma/pkg/plugins/policies/meshcircuitbreaker/api/v1alpha1"
27
	"github.com/kumahq/kuma/pkg/plugins/resources/memory"
28
	"github.com/kumahq/kuma/pkg/test/matchers"
29
	test_model "github.com/kumahq/kuma/pkg/test/resources/model"
30
	zone_tokens "github.com/kumahq/kuma/pkg/tokens/builtin/zone"
31
	"github.com/kumahq/kuma/pkg/tokens/builtin/zoneingress"
32
	util_proto "github.com/kumahq/kuma/pkg/util/proto"
33
)
34

35
var _ = Describe("Context", func() {
36
	Describe("ZoneResourceMapper", func() {
37
		var rm manager.ResourceManager
38
		var mapper reconcile.ResourceMapper
39

40
		type testCase struct {
41
			resource model.Resource
42
			expect   model.Resource
43
		}
44

45
		BeforeEach(func() {
46
			cfg := kuma_cp.DefaultConfig()
47
			cfg.Store.Type = config_store.KubernetesStore
48
			cfg.Multizone.Zone.Name = "zone"
49

50
			rm = manager.NewResourceManager(memory.NewStore())
51
			defaultContext := context.DefaultContext(stdcontext.Background(), rm, cfg)
52
			mapper = defaultContext.ZoneResourceMapper
53
		})
54

55
		DescribeTable("should zero generation field",
56
			func(given testCase) {
57
				// when
58
				out, _ := mapper(kds.Features{}, given.resource)
59

60
				// then
61
				Expect(out.GetMeta()).To(Equal(util.CloneResourceMeta(given.expect.GetMeta())))
62
				Expect(out.Descriptor()).To(Equal(given.expect.Descriptor()))
63
				Expect(out.GetSpec()).To(matchers.MatchProto(given.expect.GetSpec()))
64
			},
65
			Entry("should zero generation on DataplaneInsight", testCase{
66
				resource: &core_mesh.DataplaneInsightResource{
67
					Meta: &test_model.ResourceMeta{
68
						Name: "dpi-1",
69
					},
70
					Spec: &mesh_proto.DataplaneInsight{
71
						MTLS: &mesh_proto.DataplaneInsight_MTLS{
72
							IssuedBackend:     "test",
73
							SupportedBackends: []string{"one", "two"},
74
						},
75
						Subscriptions: []*mesh_proto.DiscoverySubscription{
76
							{
77
								Id:         "sub1",
78
								Generation: 10,
79
							},
80
							{
81
								Id:         "sub2",
82
								Generation: 15,
83
							},
84
						},
85
					},
86
				},
87
				expect: &core_mesh.DataplaneInsightResource{
88
					Meta: &test_model.ResourceMeta{
89
						Name: hash.HashedName("", "dpi-1", "zone"),
90
						Labels: map[string]string{
91
							"kuma.io/origin":       "zone",
92
							"kuma.io/zone":         "zone",
93
							"kuma.io/display-name": "dpi-1",
94
						},
95
					},
96
					Spec: &mesh_proto.DataplaneInsight{
97
						MTLS: &mesh_proto.DataplaneInsight_MTLS{
98
							IssuedBackend:     "test",
99
							SupportedBackends: []string{"one", "two"},
100
						},
101
						Subscriptions: []*mesh_proto.DiscoverySubscription{
102
							{
103
								Id:         "sub1",
104
								Generation: 0,
105
							},
106
							{
107
								Id:         "sub2",
108
								Generation: 0,
109
							},
110
						},
111
					},
112
				},
113
			}),
114
			Entry("should zero generation on ZoneIngressInsight", testCase{
115
				resource: &core_mesh.ZoneIngressInsightResource{
116
					Meta: &test_model.ResourceMeta{
117
						Name: "zii-1",
118
					},
119
					Spec: &mesh_proto.ZoneIngressInsight{
120
						Subscriptions: []*mesh_proto.DiscoverySubscription{
121
							{
122
								ControlPlaneInstanceId: "ID1",
123
								Generation:             10,
124
							},
125
							{
126
								ControlPlaneInstanceId: "ID2",
127
								Generation:             15,
128
							},
129
						},
130
					},
131
				},
132
				expect: &core_mesh.ZoneIngressInsightResource{
133
					Meta: &test_model.ResourceMeta{
134
						Name: hash.HashedName("", "zii-1", "zone"),
135
						Labels: map[string]string{
136
							"kuma.io/display-name": "zii-1",
137
							"kuma.io/origin":       "zone",
138
							"kuma.io/zone":         "zone",
139
						},
140
					},
141
					Spec: &mesh_proto.ZoneIngressInsight{
142
						Subscriptions: []*mesh_proto.DiscoverySubscription{
143
							{
144
								ControlPlaneInstanceId: "ID1",
145
								Generation:             0,
146
							},
147
							{
148
								ControlPlaneInstanceId: "ID2",
149
								Generation:             0,
150
							},
151
						},
152
					},
153
				},
154
			}),
155
			Entry("should zero generation on ZoneEgressInsight", testCase{
156
				resource: &core_mesh.ZoneEgressInsightResource{
157
					Meta: &test_model.ResourceMeta{
158
						Name: "zei-1",
159
					},
160
					Spec: &mesh_proto.ZoneEgressInsight{
161
						Subscriptions: []*mesh_proto.DiscoverySubscription{
162
							{
163
								Generation: 10,
164
							},
165
							{
166
								Generation: 15,
167
							},
168
						},
169
					},
170
				},
171
				expect: &core_mesh.ZoneEgressInsightResource{
172
					Meta: &test_model.ResourceMeta{
173
						Name: hash.HashedName("", "zei-1", "zone"),
174
						Labels: map[string]string{
175
							"kuma.io/zone":         "zone",
176
							"kuma.io/display-name": "zei-1",
177
							"kuma.io/origin":       "zone",
178
						},
179
					},
180
					Spec: &mesh_proto.ZoneEgressInsight{
181
						Subscriptions: []*mesh_proto.DiscoverySubscription{
182
							{
183
								Generation: 0,
184
							},
185
							{
186
								Generation: 0,
187
							},
188
						},
189
					},
190
				},
191
			}),
192
			Entry("should not change non-insight", testCase{
193
				resource: &core_mesh.CircuitBreakerResource{
194
					Meta: &test_model.ResourceMeta{
195
						Name: "cb-1",
196
					},
197
					Spec: &mesh_proto.CircuitBreaker{
198
						Sources: []*mesh_proto.Selector{
199
							{
200
								Match: map[string]string{
201
									"match1": "source",
202
								},
203
							},
204
						},
205
						Destinations: []*mesh_proto.Selector{
206
							{
207
								Match: map[string]string{
208
									"match2": "dest",
209
								},
210
							},
211
						},
212
						Conf: &mesh_proto.CircuitBreaker_Conf{
213
							SplitExternalAndLocalErrors: true,
214
						},
215
					},
216
				},
217
				expect: &core_mesh.CircuitBreakerResource{
218
					Meta: &test_model.ResourceMeta{
219
						Name: hash.HashedName("", "cb-1", "zone"),
220
						Labels: map[string]string{
221
							"kuma.io/display-name": "cb-1",
222
							"kuma.io/origin":       "zone",
223
							"kuma.io/zone":         "zone",
224
						},
225
					},
226
					Spec: &mesh_proto.CircuitBreaker{
227
						Sources: []*mesh_proto.Selector{
228
							{
229
								Match: map[string]string{
230
									"match1": "source",
231
								},
232
							},
233
						},
234
						Destinations: []*mesh_proto.Selector{
235
							{
236
								Match: map[string]string{
237
									"match2": "dest",
238
								},
239
							},
240
						},
241
						Conf: &mesh_proto.CircuitBreaker_Conf{
242
							SplitExternalAndLocalErrors: true,
243
						},
244
					},
245
				},
246
			}),
247
		)
248
	})
249
	Describe("GlobalProvidedFilter", func() {
250
		var rm manager.ResourceManager
251
		var predicate reconcile.ResourceFilter
252

253
		clusterID := "cluster-id"
254
		configs := map[string]bool{
255
			config_manager.ClusterIdConfigKey: true,
256
		}
257

258
		type testCase struct {
259
			resource model.Resource
260
			expect   bool
261

262
			// zone ingresses and egresses
263
			zoneResource *core_system.ZoneResource
264
			zoneName     string
265
		}
266

267
		BeforeEach(func() {
268
			rm = manager.NewResourceManager(memory.NewStore())
269
			predicate = context.GlobalProvidedFilter(rm, configs)
270
		})
271

272
		It("should filter out configs if not in provided argument", func() {
273
			ctx := stdcontext.Background()
274
			// given
275
			config1 := &core_system.ConfigResource{
276
				Meta: &test_model.ResourceMeta{
277
					Name: config_manager.ClusterIdConfigKey,
278
				},
279
			}
280
			config2 := &core_system.ConfigResource{
281
				Meta: &test_model.ResourceMeta{
282
					Name: "config-which-should-be-filtered-out",
283
				},
284
			}
285

286
			// when
287
			ok := predicate(ctx, clusterID, kds.Features{}, config1)
288

289
			// then
290
			Expect(ok).To(BeTrue())
291

292
			// when
293
			ok = predicate(ctx, clusterID, kds.Features{}, config2)
294

295
			// then
296
			Expect(ok).To(BeFalse())
297
		})
298

299
		DescribeTable("global secrets",
300
			func(given testCase) {
301
				ctx := stdcontext.Background()
302
				// when
303
				ok := predicate(ctx, clusterID, kds.Features{
304
					kds.FeatureZoneToken: true,
305
				}, given.resource)
306

307
				// then
308
				Expect(ok).To(Equal(given.expect))
309
			},
310
			Entry("should not filter out zone ingress token signing key", testCase{
311
				resource: &core_system.GlobalSecretResource{
312
					Meta: &test_model.ResourceMeta{
313
						Name: zoneingress.ZoneIngressSigningKeyPrefix + "-1",
314
					},
315
				},
316
				expect: true,
317
			}),
318
			Entry("should not filter out zone token signing key", testCase{
319
				resource: &core_system.GlobalSecretResource{
320
					Meta: &test_model.ResourceMeta{
321
						Name: zone_tokens.SigningKeyPrefix + "-1",
322
					},
323
				},
324
				expect: true,
325
			}),
326
			Entry("should filter out when not signing key", testCase{
327
				resource: &core_system.GlobalSecretResource{
328
					Meta: &test_model.ResourceMeta{
329
						Name: "some-non-signing-key-global-secret",
330
					},
331
				},
332
				expect: false,
333
			}),
334
		)
335

336
		DescribeTable("zone ingresses",
337
			func(given testCase) {
338
				ctx := stdcontext.Background()
339
				// given
340
				if given.zoneResource != nil {
341
					Expect(rm.Create(
342
						ctx,
343
						given.zoneResource,
344
						core_store.CreateByKey(given.zoneName, ""),
345
					)).To(Succeed())
346
				}
347

348
				// when
349
				ok := predicate(ctx, clusterID, kds.Features{}, given.resource)
350

351
				// then
352
				Expect(ok).To(Equal(given.expect))
353
			},
354
			Entry("should not filter out zone ingresses from the different, enabled zone", testCase{
355
				resource: &core_mesh.ZoneIngressResource{
356
					Meta: &test_model.ResourceMeta{
357
						Name: "zone-ingress-1",
358
					},
359
					Spec: &mesh_proto.ZoneIngress{
360
						Zone: "different-zone",
361
					},
362
				},
363
				zoneResource: &core_system.ZoneResource{
364
					Meta: &test_model.ResourceMeta{
365
						Name: "different-zone",
366
					},
367
					Spec: &system_proto.Zone{
368
						Enabled: util_proto.Bool(true),
369
					},
370
				},
371
				zoneName: "different-zone",
372
				expect:   true,
373
			}),
374
			Entry("should filter out zone ingresses from the same zone", testCase{
375
				resource: &core_mesh.ZoneIngressResource{
376
					Meta: &test_model.ResourceMeta{
377
						Name: "zone-ingress-1",
378
					},
379
					Spec: &mesh_proto.ZoneIngress{
380
						Zone: clusterID,
381
					},
382
				},
383
				expect: false,
384
			}),
385
			Entry("should filter out zone ingresses from the different, not enabled zone", testCase{
386
				resource: &core_mesh.ZoneIngressResource{
387
					Meta: &test_model.ResourceMeta{
388
						Name: "zone-ingress-1",
389
					},
390
					Spec: &mesh_proto.ZoneIngress{
391
						Zone: "different-zone",
392
					},
393
				},
394
				zoneResource: &core_system.ZoneResource{
395
					Meta: &test_model.ResourceMeta{
396
						Name: "different-zone",
397
					},
398
					Spec: &system_proto.Zone{
399
						Enabled: util_proto.Bool(false),
400
					},
401
				},
402
				zoneName: "different-zone",
403
				expect:   false,
404
			}),
405
		)
406

407
		Context("global provided resources", func() {
408
			// we are ignoring this types, as we should already test them in
409
			// earlier tests
410
			ignoreTypes := map[model.ResourceType]struct{}{
411
				core_system.ConfigType:       {},
412
				core_system.GlobalSecretType: {},
413
				core_mesh.DataplaneType:      {},
414
				core_mesh.ZoneIngressType:    {},
415
				core_mesh.ZoneEgressType:     {},
416
			}
417

418
			var entries []TableEntry
419
			for _, descriptor := range registry.Global().ObjectDescriptors() {
420
				name := descriptor.Name
421
				_, ignoreType := ignoreTypes[name]
422

423
				if descriptor.KDSFlags.Has(model.GlobalToAllZonesFlag) && !ignoreType {
424
					resource := descriptor.NewObject()
425
					resource.SetMeta(&test_model.ResourceMeta{
426
						Name: string(name),
427
					})
428

429
					entries = append(entries, Entry(
430
						fmt.Sprintf("should return true for %s", name),
431
						testCase{resource: resource},
432
					))
433
				}
434
			}
435

436
			DescribeTable("returned predicate function",
437
				func(given testCase) {
438
					ctx := stdcontext.Background()
439
					// when
440
					ok := predicate(ctx, clusterID, kds.Features{}, given.resource)
441

442
					// then
443
					Expect(ok).To(BeTrue())
444
				},
445
				entries,
446
			)
447
		})
448
	})
449
	Describe("GlobalResourceMapper", func() {
450
		type config struct {
451
			storeType          config_store.StoreType
452
			k8sSystemNamespace string
453
		}
454

455
		type testCase struct {
456
			config                     config
457
			name                       string
458
			displayName                string
459
			expectedName               string
460
			isResourcePluginOriginated bool
461
			scope                      model.ResourceScope
462
			features                   kds.Features
463
		}
464

465
		genConfig := func(caseCfg config) kuma_cp.Config {
466
			cfg := kuma_cp.DefaultConfig()
467

468
			if caseCfg.storeType != "" {
469
				cfg.Store.Type = caseCfg.storeType
470
			}
471

472
			if caseCfg.k8sSystemNamespace != "" {
473
				cfg.Store.Kubernetes.SystemNamespace = caseCfg.k8sSystemNamespace
474
			}
475

476
			return cfg
477
		}
478

479
		resource := func(given testCase) model.Resource {
480
			var r model.Resource = core_mesh.NewCircuitBreakerResource()
481
			switch given.scope {
482
			case model.ScopeGlobal:
483
				r = core_mesh.NewZoneIngressResource()
484
			}
485
			if given.isResourcePluginOriginated {
486
				r = v1alpha1.NewMeshCircuitBreakerResource()
487
			}
488

489
			meta := &test_model.ResourceMeta{
490
				Name: given.name,
491
				Labels: map[string]string{
492
					mesh_proto.DisplayName: given.displayName,
493
				},
494
			}
495
			r.SetMeta(meta)
496
			return r
497
		}
498

499
		DescribeTable("system namespace suffix from in resource names",
500
			func(given testCase) {
501
				// given
502
				ctx := stdcontext.Background()
503
				rm := manager.NewResourceManager(memory.NewStore())
504
				cfg := genConfig(given.config)
505
				kdsCtx := context.DefaultContext(ctx, rm, cfg)
506

507
				// when
508
				out, err := kdsCtx.GlobalResourceMapper(given.features, resource(given))
509
				Expect(err).ToNot(HaveOccurred())
510

511
				// then
512
				Expect(out.GetMeta().GetName()).To(Equal(given.expectedName))
513
			},
514
			Entry("should be removed when store type is kubernetes "+
515
				"and resource is plugin originated", testCase{
516
				isResourcePluginOriginated: true,
517
				config: config{
518
					storeType:          config_store.KubernetesStore,
519
					k8sSystemNamespace: "custom-namespace",
520
				},
521
				name:         "foo.custom-namespace",
522
				displayName:  "foo",
523
				expectedName: "foo-zxw6c95d42zfz9cc",
524
				scope:        model.ScopeMesh,
525
				features: map[string]bool{
526
					kds.FeatureHashSuffix: true,
527
				},
528
			}),
529
			Entry("should be removed when store type is kubernetes "+
530
				"resource is plugin originated and no KDS hash-suffix feature", testCase{
531
				isResourcePluginOriginated: true,
532
				config: config{
533
					storeType:          config_store.KubernetesStore,
534
					k8sSystemNamespace: "custom-namespace",
535
				},
536
				name:         "foo.custom-namespace",
537
				expectedName: "foo",
538
				scope:        model.ScopeMesh,
539
				features:     map[string]bool{},
540
			}),
541
			Entry("shouldn't be removed when store type is kubernetes "+
542
				"and resource isn't plugin originated", testCase{
543
				isResourcePluginOriginated: false,
544
				config: config{
545
					storeType:          config_store.KubernetesStore,
546
					k8sSystemNamespace: "custom-namespace",
547
				},
548
				name:         "foo.default",
549
				expectedName: "foo.default",
550
				scope:        model.ScopeGlobal,
551
				features: map[string]bool{
552
					kds.FeatureHashSuffix: true,
553
				},
554
			}),
555
		)
556
	})
557
})
558

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.