7
. "github.com/onsi/ginkgo/v2"
8
. "github.com/onsi/gomega"
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"
35
var _ = Describe("Context", func() {
36
Describe("ZoneResourceMapper", func() {
37
var rm manager.ResourceManager
38
var mapper reconcile.ResourceMapper
40
type testCase struct {
41
resource model.Resource
46
cfg := kuma_cp.DefaultConfig()
47
cfg.Store.Type = config_store.KubernetesStore
48
cfg.Multizone.Zone.Name = "zone"
50
rm = manager.NewResourceManager(memory.NewStore())
51
defaultContext := context.DefaultContext(stdcontext.Background(), rm, cfg)
52
mapper = defaultContext.ZoneResourceMapper
55
DescribeTable("should zero generation field",
56
func(given testCase) {
58
out, _ := mapper(kds.Features{}, given.resource)
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()))
65
Entry("should zero generation on DataplaneInsight", testCase{
66
resource: &core_mesh.DataplaneInsightResource{
67
Meta: &test_model.ResourceMeta{
70
Spec: &mesh_proto.DataplaneInsight{
71
MTLS: &mesh_proto.DataplaneInsight_MTLS{
72
IssuedBackend: "test",
73
SupportedBackends: []string{"one", "two"},
75
Subscriptions: []*mesh_proto.DiscoverySubscription{
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",
96
Spec: &mesh_proto.DataplaneInsight{
97
MTLS: &mesh_proto.DataplaneInsight_MTLS{
98
IssuedBackend: "test",
99
SupportedBackends: []string{"one", "two"},
101
Subscriptions: []*mesh_proto.DiscoverySubscription{
114
Entry("should zero generation on ZoneIngressInsight", testCase{
115
resource: &core_mesh.ZoneIngressInsightResource{
116
Meta: &test_model.ResourceMeta{
119
Spec: &mesh_proto.ZoneIngressInsight{
120
Subscriptions: []*mesh_proto.DiscoverySubscription{
122
ControlPlaneInstanceId: "ID1",
126
ControlPlaneInstanceId: "ID2",
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",
141
Spec: &mesh_proto.ZoneIngressInsight{
142
Subscriptions: []*mesh_proto.DiscoverySubscription{
144
ControlPlaneInstanceId: "ID1",
148
ControlPlaneInstanceId: "ID2",
155
Entry("should zero generation on ZoneEgressInsight", testCase{
156
resource: &core_mesh.ZoneEgressInsightResource{
157
Meta: &test_model.ResourceMeta{
160
Spec: &mesh_proto.ZoneEgressInsight{
161
Subscriptions: []*mesh_proto.DiscoverySubscription{
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",
180
Spec: &mesh_proto.ZoneEgressInsight{
181
Subscriptions: []*mesh_proto.DiscoverySubscription{
192
Entry("should not change non-insight", testCase{
193
resource: &core_mesh.CircuitBreakerResource{
194
Meta: &test_model.ResourceMeta{
197
Spec: &mesh_proto.CircuitBreaker{
198
Sources: []*mesh_proto.Selector{
200
Match: map[string]string{
205
Destinations: []*mesh_proto.Selector{
207
Match: map[string]string{
212
Conf: &mesh_proto.CircuitBreaker_Conf{
213
SplitExternalAndLocalErrors: true,
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",
226
Spec: &mesh_proto.CircuitBreaker{
227
Sources: []*mesh_proto.Selector{
229
Match: map[string]string{
234
Destinations: []*mesh_proto.Selector{
236
Match: map[string]string{
241
Conf: &mesh_proto.CircuitBreaker_Conf{
242
SplitExternalAndLocalErrors: true,
249
Describe("GlobalProvidedFilter", func() {
250
var rm manager.ResourceManager
251
var predicate reconcile.ResourceFilter
253
clusterID := "cluster-id"
254
configs := map[string]bool{
255
config_manager.ClusterIdConfigKey: true,
258
type testCase struct {
259
resource model.Resource
262
// zone ingresses and egresses
263
zoneResource *core_system.ZoneResource
268
rm = manager.NewResourceManager(memory.NewStore())
269
predicate = context.GlobalProvidedFilter(rm, configs)
272
It("should filter out configs if not in provided argument", func() {
273
ctx := stdcontext.Background()
275
config1 := &core_system.ConfigResource{
276
Meta: &test_model.ResourceMeta{
277
Name: config_manager.ClusterIdConfigKey,
280
config2 := &core_system.ConfigResource{
281
Meta: &test_model.ResourceMeta{
282
Name: "config-which-should-be-filtered-out",
287
ok := predicate(ctx, clusterID, kds.Features{}, config1)
290
Expect(ok).To(BeTrue())
293
ok = predicate(ctx, clusterID, kds.Features{}, config2)
296
Expect(ok).To(BeFalse())
299
DescribeTable("global secrets",
300
func(given testCase) {
301
ctx := stdcontext.Background()
303
ok := predicate(ctx, clusterID, kds.Features{
304
kds.FeatureZoneToken: true,
308
Expect(ok).To(Equal(given.expect))
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",
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",
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",
336
DescribeTable("zone ingresses",
337
func(given testCase) {
338
ctx := stdcontext.Background()
340
if given.zoneResource != nil {
344
core_store.CreateByKey(given.zoneName, ""),
349
ok := predicate(ctx, clusterID, kds.Features{}, given.resource)
352
Expect(ok).To(Equal(given.expect))
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",
359
Spec: &mesh_proto.ZoneIngress{
360
Zone: "different-zone",
363
zoneResource: &core_system.ZoneResource{
364
Meta: &test_model.ResourceMeta{
365
Name: "different-zone",
367
Spec: &system_proto.Zone{
368
Enabled: util_proto.Bool(true),
371
zoneName: "different-zone",
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",
379
Spec: &mesh_proto.ZoneIngress{
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",
390
Spec: &mesh_proto.ZoneIngress{
391
Zone: "different-zone",
394
zoneResource: &core_system.ZoneResource{
395
Meta: &test_model.ResourceMeta{
396
Name: "different-zone",
398
Spec: &system_proto.Zone{
399
Enabled: util_proto.Bool(false),
402
zoneName: "different-zone",
407
Context("global provided resources", func() {
408
// we are ignoring this types, as we should already test them in
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: {},
418
var entries []TableEntry
419
for _, descriptor := range registry.Global().ObjectDescriptors() {
420
name := descriptor.Name
421
_, ignoreType := ignoreTypes[name]
423
if descriptor.KDSFlags.Has(model.GlobalToAllZonesFlag) && !ignoreType {
424
resource := descriptor.NewObject()
425
resource.SetMeta(&test_model.ResourceMeta{
429
entries = append(entries, Entry(
430
fmt.Sprintf("should return true for %s", name),
431
testCase{resource: resource},
436
DescribeTable("returned predicate function",
437
func(given testCase) {
438
ctx := stdcontext.Background()
440
ok := predicate(ctx, clusterID, kds.Features{}, given.resource)
443
Expect(ok).To(BeTrue())
449
Describe("GlobalResourceMapper", func() {
451
storeType config_store.StoreType
452
k8sSystemNamespace string
455
type testCase struct {
460
isResourcePluginOriginated bool
461
scope model.ResourceScope
462
features kds.Features
465
genConfig := func(caseCfg config) kuma_cp.Config {
466
cfg := kuma_cp.DefaultConfig()
468
if caseCfg.storeType != "" {
469
cfg.Store.Type = caseCfg.storeType
472
if caseCfg.k8sSystemNamespace != "" {
473
cfg.Store.Kubernetes.SystemNamespace = caseCfg.k8sSystemNamespace
479
resource := func(given testCase) model.Resource {
480
var r model.Resource = core_mesh.NewCircuitBreakerResource()
482
case model.ScopeGlobal:
483
r = core_mesh.NewZoneIngressResource()
485
if given.isResourcePluginOriginated {
486
r = v1alpha1.NewMeshCircuitBreakerResource()
489
meta := &test_model.ResourceMeta{
491
Labels: map[string]string{
492
mesh_proto.DisplayName: given.displayName,
499
DescribeTable("system namespace suffix from in resource names",
500
func(given testCase) {
502
ctx := stdcontext.Background()
503
rm := manager.NewResourceManager(memory.NewStore())
504
cfg := genConfig(given.config)
505
kdsCtx := context.DefaultContext(ctx, rm, cfg)
508
out, err := kdsCtx.GlobalResourceMapper(given.features, resource(given))
509
Expect(err).ToNot(HaveOccurred())
512
Expect(out.GetMeta().GetName()).To(Equal(given.expectedName))
514
Entry("should be removed when store type is kubernetes "+
515
"and resource is plugin originated", testCase{
516
isResourcePluginOriginated: true,
518
storeType: config_store.KubernetesStore,
519
k8sSystemNamespace: "custom-namespace",
521
name: "foo.custom-namespace",
523
expectedName: "foo-zxw6c95d42zfz9cc",
524
scope: model.ScopeMesh,
525
features: map[string]bool{
526
kds.FeatureHashSuffix: true,
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,
533
storeType: config_store.KubernetesStore,
534
k8sSystemNamespace: "custom-namespace",
536
name: "foo.custom-namespace",
538
scope: model.ScopeMesh,
539
features: map[string]bool{},
541
Entry("shouldn't be removed when store type is kubernetes "+
542
"and resource isn't plugin originated", testCase{
543
isResourcePluginOriginated: false,
545
storeType: config_store.KubernetesStore,
546
k8sSystemNamespace: "custom-namespace",
549
expectedName: "foo.default",
550
scope: model.ScopeGlobal,
551
features: map[string]bool{
552
kds.FeatureHashSuffix: true,