kubelatte-ce
Форк от sbertech/kubelatte-ce
2411 строк · 53.6 Кб
1package match
2
3import (
4"context"
5"github.com/stretchr/testify/assert"
6"gitverse.ru/synapse/kubelatte/pkg/api/common"
7"gitverse.ru/synapse/kubelatte/pkg/api/v1alpha1"
8"gitverse.ru/synapse/kubelatte/pkg/observability/logger/lib"
9"gitverse.ru/synapse/kubelatte/pkg/storage"
10"go.uber.org/zap"
11"k8s.io/api/admission/v1beta1"
12corev1 "k8s.io/api/core/v1"
13v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14"testing"
15)
16
17func TestMatchCompatibility(t *testing.T) {
18type args struct {
19data common.ARFields
20match v1alpha1.Match
21}
22tests := []struct {
23name string
24args args
25want bool
26}{
27{
28name: "full_match",
29args: args{
30data: common.ARFields{
31Kind: v1.GroupVersionKind{
32Group: "ApiGroup",
33Version: "v1",
34Kind: "Pod",
35},
36Namespace: "incl_ns",
37UserInfo: common.ARUserInfo{Username: "kate"},
38Operation: v1beta1.Create,
39OldObject: nil,
40Object: map[string]interface{}{
41"metadata": map[string]interface{}{
42"name": "some_name",
43"namespace": "incl_ns",
44"annotations": map[string]interface{}{"annotNS/annotTr": Enabled},
45"labels": map[string]interface{}{"key": "val"},
46},
47},
48},
49match: v1alpha1.Match{
50Kinds: []v1alpha1.Kind{
51{
52Kind: []string{"Pod"},
53ApiGroups: []string{"ApiGroup"},
54},
55},
56UserInfo: v1alpha1.UserInfo{Username: "kate"},
57Name: v1alpha1.Name{
58Value: "some_name",
59},
60Scope: scopeNamespaced,
61NamespaceSelector: v1alpha1.NamespaceSelector{MatchExpressions: []v1alpha1.MatchExpression{
62{
63Key: "matching Key",
64Operator: string(In),
65Values: []string{"matching Val"},
66}, {
67Key: "matching Key",
68Operator: string(NotIn),
69Values: []string{"mismatching Val"},
70}, {
71
72Key: "matching Key",
73Operator: string(Exists),
74}, {
75Key: "Another key",
76Operator: string(DoesNotExist),
77}}},
78ExcludedNamespaces: v1alpha1.Namespace{
79Values: []string{"excl_ns"},
80},
81IncludedNamespaces: v1alpha1.Namespace{
82Values: []string{"incl_ns"},
83},
84Operations: []string{"CREATE"},
85AnnotationSelector: v1alpha1.AnnotationSelector{
86MatchExpressions: []v1alpha1.MatchExpression{
87{
88Key: "annotNS/annotTr",
89Operator: "In",
90Values: []string{Enabled},
91},
92},
93},
94LabelSelector: v1alpha1.LabelSelector{
95MatchExpressions: []v1alpha1.MatchExpression{{
96Key: "key",
97Operator: string(In),
98Values: []string{"val"},
99}, {
100Key: "Key",
101Operator: string(NotIn),
102Values: []string{"another Val"},
103}, {
104
105Key: "key",
106Operator: string(Exists),
107}, {
108Key: "Another key",
109Operator: string(DoesNotExist),
110},
111},
112},
113},
114},
115want: true,
116},
117{
118name: "not matched",
119args: args{
120data: common.ARFields{
121Kind: v1.GroupVersionKind{
122Group: "ApiGroup",
123Version: "v1",
124Kind: "Deployment",
125},
126Namespace: "incl_ns",
127UserInfo: common.ARUserInfo{Username: "kate"},
128Operation: v1beta1.Create,
129OldObject: nil,
130Object: map[string]interface{}{
131"metadata": map[string]interface{}{
132"name": "some_name",
133"namespace": "incl_ns",
134"annotations": map[string]interface{}{"annotNS/annotTr": Enabled},
135"labels": map[string]interface{}{"key": "val"},
136},
137},
138},
139match: v1alpha1.Match{
140Kinds: []v1alpha1.Kind{
141{
142Kind: []string{"Pod"},
143ApiGroups: []string{"ApiGroup"},
144},
145},
146UserInfo: v1alpha1.UserInfo{Username: "kate"},
147Name: v1alpha1.Name{
148Value: "some_name",
149},
150Scope: scopeNamespaced,
151NamespaceSelector: v1alpha1.NamespaceSelector{MatchExpressions: []v1alpha1.MatchExpression{}},
152ExcludedNamespaces: v1alpha1.Namespace{
153Values: []string{"excl_ns"},
154},
155IncludedNamespaces: v1alpha1.Namespace{
156Values: []string{"incl_ns"},
157},
158Operations: []string{"CREATE"},
159AnnotationSelector: v1alpha1.AnnotationSelector{
160MatchExpressions: []v1alpha1.MatchExpression{
161{
162Key: "annotNS/annotTr",
163Operator: "In",
164Values: []string{Enabled},
165},
166},
167},
168LabelSelector: v1alpha1.LabelSelector{
169MatchExpressions: []v1alpha1.MatchExpression{{
170Key: "key",
171Operator: "In",
172Values: []string{"val"},
173}},
174},
175},
176},
177want: false,
178},
179{
180name: "empty match section",
181args: args{
182data: common.ARFields{
183Namespace: "incl_ns",
184Operation: v1beta1.Create,
185},
186match: v1alpha1.Match{},
187},
188want: true,
189},
190}
191for _, tt := range tests {
192t.Run(tt.name, func(t *testing.T) {
193lib.ZapLogger = zap.NewNop()
194storage.Storage = &storage.StorageController{}
195storage.Storage.Start(false, false)
196storage.Storage.UpdateNamespace(corev1.Namespace{
197TypeMeta: v1.TypeMeta{},
198ObjectMeta: v1.ObjectMeta{
199Namespace: "incl_ns",
200Name: "incl_ns",
201Labels: map[string]string{"matching Key": "matching Val"},
202},
203Spec: corev1.NamespaceSpec{},
204Status: corev1.NamespaceStatus{},
205})
206
207m := Matcher{}
208if got, _ := m.Match(context.Background(), tt.args.data, tt.args.match); got != tt.want {
209t.Errorf("CheckMatching() = %v, want %v", got, tt.want)
210}
211})
212}
213}
214
215func Test_doesAnnotationSelectorMatches(t *testing.T) {
216type args struct {
217fields common.ARFields
218match v1alpha1.Match
219}
220tests := []struct {
221name string
222args args
223wantMatches bool
224wantReason string
225}{
226{
227name: "match annotations",
228args: args{
229fields: common.ARFields{
230Operation: v1beta1.Create,
231Object: map[string]interface{}{
232"metadata": map[string]interface{}{
233"name": "name-obj",
234"generateName": "generateName-obj",
235"annotations": map[string]interface{}{
236"kblt/key": Enabled,
237},
238},
239},
240},
241match: v1alpha1.Match{
242AnnotationSelector: v1alpha1.AnnotationSelector{
243MatchExpressions: []v1alpha1.MatchExpression{
244{
245Key: "kblt/key",
246Operator: "In",
247Values: []string{Enabled, "true"},
248},
249},
250},
251},
252},
253wantMatches: true,
254wantReason: "annotation selector",
255},
256{
257name: "empty match section",
258args: args{
259fields: common.ARFields{
260Operation: v1beta1.Create,
261Object: map[string]interface{}{
262"metadata": map[string]interface{}{
263"name": "name-obj",
264"generateName": "generateName-obj",
265"annotations": map[string]interface{}{
266"kblt/key": Enabled,
267},
268},
269},
270},
271match: v1alpha1.Match{
272AnnotationSelector: v1alpha1.AnnotationSelector{},
273},
274},
275wantMatches: true,
276wantReason: "",
277},
278{
279name: "wrong annotations format",
280args: args{
281fields: common.ARFields{
282Operation: v1beta1.Create,
283Object: map[string]interface{}{
284"metadata": map[string]interface{}{
285"name": "name-obj",
286"generateName": "generateName-obj",
287"annotations": map[bool]interface{}{
288true: Enabled,
289},
290},
291},
292},
293match: v1alpha1.Match{
294AnnotationSelector: v1alpha1.AnnotationSelector{
295MatchExpressions: []v1alpha1.MatchExpression{
296{
297Key: "kblt/key",
298Operator: "In",
299Values: []string{Enabled, "true"},
300},
301},
302},
303},
304},
305wantMatches: false,
306wantReason: "request.metadata.annotations",
307},
308}
309for _, tt := range tests {
310t.Run(tt.name, func(t *testing.T) {
311lib.ZapLogger = zap.NewNop()
312m := Matcher{}
313gotMatches, gotReason := m.doesAnnotationSelectorMatches(context.Background(), tt.args.fields, tt.args.match)
314if gotMatches != tt.wantMatches {
315t.Errorf("doesAnnotationSelectorMatches() gotMatches = %v, want %v", gotMatches, tt.wantMatches)
316}
317if gotReason != tt.wantReason {
318t.Errorf("doesAnnotationSelectorMatches() gotReason = %v, want %v", gotReason, tt.wantReason)
319}
320})
321}
322}
323
324func Test_doesIncludeExcludeNssMatch(t *testing.T) {
325type args struct {
326fields common.ARFields
327match v1alpha1.Match
328}
329tests := []struct {
330name string
331args args
332want bool
333want1 string
334}{
335{
336name: "included match",
337args: args{
338fields: common.ARFields{
339Operation: v1beta1.Create,
340Namespace: "kblt",
341Object: map[string]interface{}{
342"metadata": map[string]interface{}{},
343},
344},
345match: v1alpha1.Match{
346IncludedNamespaces: v1alpha1.Namespace{
347Values: []string{"kblt"},
348},
349},
350},
351want: true,
352want1: "",
353},
354{
355name: "included not match",
356args: args{
357fields: common.ARFields{
358Operation: v1beta1.Create,
359Namespace: "kblt",
360Object: map[string]interface{}{
361"metadata": map[string]interface{}{},
362},
363},
364match: v1alpha1.Match{
365IncludedNamespaces: v1alpha1.Namespace{
366Values: []string{"test"},
367},
368},
369},
370want: false,
371want1: "included namespace value",
372},
373{
374name: "included empty section match",
375args: args{
376fields: common.ARFields{
377Operation: v1beta1.Create,
378Namespace: "kblt",
379Object: map[string]interface{}{
380"metadata": map[string]interface{}{},
381},
382},
383match: v1alpha1.Match{
384IncludedNamespaces: v1alpha1.Namespace{},
385},
386},
387want: true,
388want1: "",
389},
390{
391name: "included regex match",
392args: args{
393fields: common.ARFields{
394Operation: v1beta1.Create,
395Namespace: "kblt",
396},
397match: v1alpha1.Match{
398IncludedNamespaces: v1alpha1.Namespace{
399Regex: []string{"kbl.*"},
400},
401},
402},
403want: true,
404want1: "",
405},
406{
407name: "included regex not match",
408args: args{
409fields: common.ARFields{
410Operation: v1beta1.Create,
411Namespace: "test",
412},
413match: v1alpha1.Match{
414IncludedNamespaces: v1alpha1.Namespace{
415Regex: []string{"kbl.*"},
416},
417},
418},
419want: false,
420want1: "included namespace regex",
421},
422{
423name: "included wrong regex",
424args: args{
425fields: common.ARFields{
426Operation: v1beta1.Create,
427Namespace: "kblt",
428},
429match: v1alpha1.Match{
430IncludedNamespaces: v1alpha1.Namespace{
431Regex: []string{"a(b"},
432},
433},
434},
435want: false,
436want1: "namespace invalid regex",
437},
438{
439name: "excluded regex not match",
440args: args{
441fields: common.ARFields{
442Operation: v1beta1.Create,
443Namespace: "kblt",
444},
445match: v1alpha1.Match{
446ExcludedNamespaces: v1alpha1.Namespace{
447Regex: []string{"kbl.*"},
448},
449},
450},
451want: false,
452want1: "excluded namespace regex",
453},
454{
455name: "empty namespace admission review",
456args: args{
457fields: common.ARFields{
458Operation: v1beta1.Create,
459},
460match: v1alpha1.Match{
461ExcludedNamespaces: v1alpha1.Namespace{
462Regex: []string{"kbl.*"},
463},
464},
465},
466want: true,
467want1: "",
468},
469}
470for _, tt := range tests {
471t.Run(tt.name, func(t *testing.T) {
472lib.ZapLogger = zap.NewNop()
473m := Matcher{}
474got, got1 := m.doesIncludeExcludeNssMatch(context.Background(), tt.args.fields, tt.args.match)
475if got != tt.want {
476t.Errorf("doesIncludeExcludeNssMatch() got = %v, want %v", got, tt.want)
477}
478if got1 != tt.want1 {
479t.Errorf("doesIncludeExcludeNssMatch() got1 = %v, want %v", got1, tt.want1)
480}
481})
482}
483}
484
485func Test_doesKindsMatches(t *testing.T) {
486type args struct {
487fields common.ARFields
488match v1alpha1.Match
489}
490tests := []struct {
491name string
492args args
493wantMatches bool
494wantReason string
495}{
496{
497name: "empty match kind",
498args: args{
499fields: common.ARFields{
500Kind: v1.GroupVersionKind{
501Group: "",
502Version: "v1",
503Kind: "Pod",
504},
505Operation: v1beta1.Create,
506},
507match: v1alpha1.Match{
508Kinds: []v1alpha1.Kind{},
509},
510},
511wantMatches: false,
512wantReason: "request.kind.group",
513},
514{
515name: "match kind and version",
516args: args{
517fields: common.ARFields{
518Kind: v1.GroupVersionKind{
519Group: "",
520Version: "v1",
521Kind: "Pod",
522},
523Operation: v1beta1.Create,
524},
525match: v1alpha1.Match{
526Kinds: []v1alpha1.Kind{
527{
528Kind: []string{"Pod"},
529ApiGroups: []string{""},
530},
531},
532},
533},
534wantMatches: true,
535wantReason: "",
536},
537{
538name: "match kind and not match version",
539args: args{
540fields: common.ARFields{
541Kind: v1.GroupVersionKind{
542Group: "2",
543Version: "v1",
544Kind: "Pod",
545},
546Operation: v1beta1.Create,
547},
548match: v1alpha1.Match{
549Kinds: []v1alpha1.Kind{
550{
551Kind: []string{"Pod"},
552ApiGroups: []string{"3"},
553},
554},
555},
556},
557wantMatches: false,
558wantReason: "request.kind.group",
559},
560{
561name: "match version and not match kind",
562args: args{
563fields: common.ARFields{
564Kind: v1.GroupVersionKind{
565Group: "3",
566Version: "v1",
567Kind: "Deployment",
568},
569Operation: v1beta1.Create,
570},
571match: v1alpha1.Match{
572Kinds: []v1alpha1.Kind{
573{
574Kind: []string{"Pod"},
575ApiGroups: []string{"3"},
576},
577},
578},
579},
580wantMatches: false,
581wantReason: "request.kind.kind",
582},
583}
584for _, tt := range tests {
585t.Run(tt.name, func(t *testing.T) {
586m := Matcher{}
587gotMatches, gotReason := m.doesKindsMatches(context.Background(), tt.args.fields, tt.args.match)
588if gotMatches != tt.wantMatches {
589t.Errorf("doesKindsMatches() gotMatches = %v, want %v", gotMatches, tt.wantMatches)
590}
591if gotReason != tt.wantReason {
592t.Errorf("doesKindsMatches() gotReason = %v, want %v", gotReason, tt.wantReason)
593}
594})
595}
596}
597
598func Test_doesLabelSelectorMatches(t *testing.T) {
599type args struct {
600fields common.ARFields
601match v1alpha1.Match
602}
603tests := []struct {
604name string
605args args
606wantMatches bool
607wantReason string
608}{
609{
610name: "empty match.labelSelector",
611args: args{
612fields: common.ARFields{
613Operation: v1beta1.Create,
614Object: map[string]interface{}{
615"metadata": map[string]interface{}{
616"name": "name-obj",
617"generateName": "generateName-obj",
618},
619},
620},
621match: v1alpha1.Match{
622LabelSelector: v1alpha1.LabelSelector{},
623},
624},
625wantMatches: true,
626wantReason: "",
627},
628{
629name: "wrong labels format",
630args: args{
631fields: common.ARFields{
632Operation: v1beta1.Create,
633Object: map[string]interface{}{
634"metadata": map[string]interface{}{
635"name": "name-obj",
636"generateName": "generateName-obj",
637"labels": map[bool]interface{}{
638true: map[string]interface{}{
639"test": map[string]interface{}{
640"test": "test",
641},
642},
643},
644},
645},
646},
647match: v1alpha1.Match{
648LabelSelector: v1alpha1.LabelSelector{
649MatchExpressions: []v1alpha1.MatchExpression{
650{
651Key: "key",
652Operator: "In",
653Values: []string{"value"},
654},
655},
656},
657},
658},
659wantMatches: false,
660wantReason: "wrong metadata.labels format",
661},
662{
663name: "match labels",
664args: args{
665fields: common.ARFields{
666Operation: v1beta1.Create,
667Object: map[string]interface{}{
668"metadata": map[string]interface{}{
669"name": "name-obj",
670"generateName": "generateName-obj",
671"labels": map[string]interface{}{
672"key": "value",
673},
674},
675},
676},
677match: v1alpha1.Match{
678LabelSelector: v1alpha1.LabelSelector{
679MatchExpressions: []v1alpha1.MatchExpression{
680{
681Key: "key",
682Operator: "In",
683Values: []string{"value", "not-value"},
684},
685},
686},
687},
688},
689wantMatches: true,
690wantReason: "metadata.labels",
691},
692{
693name: "not matched labels",
694args: args{
695fields: common.ARFields{
696Operation: v1beta1.Create,
697Object: map[string]interface{}{
698"metadata": map[string]interface{}{
699"name": "name-obj",
700"generateName": "generateName-obj",
701"labels": map[string]interface{}{
702"key": "value",
703},
704},
705},
706},
707match: v1alpha1.Match{
708LabelSelector: v1alpha1.LabelSelector{
709MatchExpressions: []v1alpha1.MatchExpression{
710{
711Key: "key",
712Operator: "NotIn",
713Values: []string{"value", "not-value"},
714},
715},
716},
717},
718},
719wantMatches: false,
720wantReason: "metadata.labels",
721},
722}
723for _, tt := range tests {
724t.Run(tt.name, func(t *testing.T) {
725lib.ZapLogger = zap.NewNop()
726m := Matcher{}
727gotMatches, gotReason := m.doesLabelSelectorMatches(context.Background(), tt.args.fields, tt.args.match)
728if gotMatches != tt.wantMatches {
729t.Errorf("doesLabelSelectorMatches() gotMatches = %v, want %v", gotMatches, tt.wantMatches)
730}
731if gotReason != tt.wantReason {
732t.Errorf("doesLabelSelectorMatches() gotReason = %v, want %v", gotReason, tt.wantReason)
733}
734})
735}
736}
737
738func Test_doesMatchConditionsMatches(t *testing.T) {
739type args struct {
740fields common.ARFields
741match v1alpha1.Match
742}
743tests := []struct {
744name string
745args args
746want bool
747want1 string
748}{
749// Create
750{
751name: "empty match section",
752args: args{
753fields: common.ARFields{
754Operation: v1beta1.Create,
755Object: map[string]interface{}{
756"metadata": map[string]interface{}{
757"name": "name-obj",
758"generateName": "generateName-obj",
759},
760},
761},
762match: v1alpha1.Match{
763MatchConditions: v1alpha1.MatchConditions{},
764},
765},
766want: true,
767want1: "",
768},
769{
770name: "object mus be matched mustExist",
771args: args{
772fields: common.ARFields{
773Operation: v1beta1.Create,
774Object: map[string]interface{}{
775"metadata": map[string]interface{}{
776"name": "name-obj",
777"generateName": "generateName-obj",
778},
779},
780},
781match: v1alpha1.Match{
782MatchConditions: v1alpha1.MatchConditions{
783Object: []v1alpha1.Obj{{
784Path: "metadata.name",
785Condition: mustExist,
786}},
787},
788},
789},
790want: true,
791want1: "",
792},
793{
794name: "object mus be matched mustNotExist",
795args: args{
796fields: common.ARFields{
797Operation: v1beta1.Create,
798Object: map[string]interface{}{
799"metadata": map[string]interface{}{
800"name": "name-obj",
801"generateName": "generateName-obj",
802},
803},
804},
805match: v1alpha1.Match{
806MatchConditions: v1alpha1.MatchConditions{
807Object: []v1alpha1.Obj{{
808Path: "metadata.annotations",
809Condition: mustNotExist,
810}},
811},
812},
813},
814want: true,
815want1: "",
816},
817{
818name: "object mus be not matched mustNotExist",
819args: args{
820fields: common.ARFields{
821Operation: v1beta1.Create,
822Object: map[string]interface{}{
823"metadata": map[string]interface{}{
824"name": "name-obj",
825"generateName": "generateName-obj",
826},
827},
828},
829match: v1alpha1.Match{
830MatchConditions: v1alpha1.MatchConditions{
831Object: []v1alpha1.Obj{{
832Path: "metadata.annotations",
833Condition: mustExist,
834}},
835},
836},
837},
838want: false,
839want1: "match conditions",
840},
841{
842name: "object mus be not matched mustExist",
843args: args{
844fields: common.ARFields{
845Operation: v1beta1.Create,
846Object: map[string]interface{}{
847"metadata": map[string]interface{}{
848"name": "name-obj",
849"generateName": "generateName-obj",
850},
851},
852},
853match: v1alpha1.Match{
854MatchConditions: v1alpha1.MatchConditions{
855Object: []v1alpha1.Obj{{
856Path: "metadata.name",
857Condition: mustNotExist,
858}},
859},
860},
861},
862want: false,
863want1: "match conditions",
864},
865// Delete
866{
867name: "OldObject mus be matched mustNotExist",
868args: args{
869fields: common.ARFields{
870Operation: v1beta1.Delete,
871OldObject: map[string]interface{}{
872"metadata": map[string]interface{}{
873"name": "name-obj",
874"generateName": "generateName-obj",
875},
876},
877},
878match: v1alpha1.Match{
879MatchConditions: v1alpha1.MatchConditions{
880OldObject: []v1alpha1.Obj{{
881Path: "metadata.annotations",
882Condition: mustNotExist,
883}},
884},
885},
886},
887want: true,
888want1: "",
889},
890{
891name: "OldObject mus be matched mustExist",
892args: args{
893fields: common.ARFields{
894Operation: v1beta1.Delete,
895OldObject: map[string]interface{}{
896"metadata": map[string]interface{}{
897"name": "name-obj",
898"generateName": "generateName-obj",
899},
900},
901},
902match: v1alpha1.Match{
903MatchConditions: v1alpha1.MatchConditions{
904OldObject: []v1alpha1.Obj{{
905Path: "metadata.name",
906Condition: mustExist,
907}},
908},
909},
910},
911want: true,
912want1: "",
913},
914{
915name: "OldObject mus be not matched mustNotExist",
916args: args{
917fields: common.ARFields{
918Operation: v1beta1.Delete,
919OldObject: map[string]interface{}{
920"metadata": map[string]interface{}{
921"name": "name-obj",
922"generateName": "generateName-obj",
923},
924},
925},
926match: v1alpha1.Match{
927MatchConditions: v1alpha1.MatchConditions{
928OldObject: []v1alpha1.Obj{{
929Path: "metadata.name",
930Condition: mustNotExist,
931}},
932},
933},
934},
935want: false,
936want1: "match conditions",
937},
938{
939name: "OldObject mus be not matched mustExist",
940args: args{
941fields: common.ARFields{
942Operation: v1beta1.Delete,
943OldObject: map[string]interface{}{
944"metadata": map[string]interface{}{
945"name": "name-obj",
946"generateName": "generateName-obj",
947},
948},
949},
950match: v1alpha1.Match{
951MatchConditions: v1alpha1.MatchConditions{
952OldObject: []v1alpha1.Obj{{
953Path: "metadata.annotations",
954Condition: mustExist,
955}},
956},
957},
958},
959want: false,
960want1: "match conditions",
961},
962// Update
963{
964name: "both must be matched mustExist",
965args: args{
966fields: common.ARFields{
967Operation: v1beta1.Update,
968OldObject: map[string]interface{}{
969"metadata": map[string]interface{}{
970"name": "name-obj",
971"generateName": "generateName-obj",
972},
973},
974Object: map[string]interface{}{
975"metadata": map[string]interface{}{
976"name": "name-obj",
977"generateName": "generateName-obj",
978},
979},
980},
981match: v1alpha1.Match{
982MatchConditions: v1alpha1.MatchConditions{
983OldObject: []v1alpha1.Obj{{
984Path: "metadata.name",
985Condition: mustExist,
986}},
987Object: []v1alpha1.Obj{{
988Path: "metadata.name",
989Condition: mustExist,
990}},
991},
992},
993},
994want: true,
995want1: "",
996},
997{
998name: "both: Object must be not matched mustExist",
999args: args{
1000fields: common.ARFields{
1001Operation: v1beta1.Update,
1002OldObject: map[string]interface{}{
1003"metadata": map[string]interface{}{
1004"name": "name-obj",
1005"generateName": "generateName-obj",
1006},
1007},
1008Object: map[string]interface{}{
1009"metadata": map[string]interface{}{
1010"name": "name-obj",
1011"generateName": "generateName-obj",
1012},
1013},
1014},
1015match: v1alpha1.Match{
1016MatchConditions: v1alpha1.MatchConditions{
1017OldObject: []v1alpha1.Obj{{
1018Path: "metadata.name",
1019Condition: mustExist,
1020}},
1021Object: []v1alpha1.Obj{{
1022Path: "metadata.annotations",
1023Condition: mustExist,
1024}},
1025},
1026},
1027},
1028want: false,
1029want1: "match conditions",
1030},
1031{
1032name: "both: OldObject must be not matched mustExist",
1033args: args{
1034fields: common.ARFields{
1035Operation: v1beta1.Update,
1036OldObject: map[string]interface{}{
1037"metadata": map[string]interface{}{
1038"name": "name-obj",
1039"generateName": "generateName-obj",
1040},
1041},
1042Object: map[string]interface{}{
1043"metadata": map[string]interface{}{
1044"name": "name-obj",
1045"generateName": "generateName-obj",
1046},
1047},
1048},
1049match: v1alpha1.Match{
1050MatchConditions: v1alpha1.MatchConditions{
1051OldObject: []v1alpha1.Obj{{
1052Path: "metadata.annotations",
1053Condition: mustExist,
1054}},
1055Object: []v1alpha1.Obj{{
1056Path: "metadata.name",
1057Condition: mustExist,
1058}},
1059},
1060},
1061},
1062want: false,
1063want1: "match conditions",
1064},
1065}
1066for _, tt := range tests {
1067t.Run(tt.name, func(t *testing.T) {
1068m := Matcher{}
1069got, got1 := m.doesMatchConditionsMatches(context.Background(), tt.args.fields, tt.args.match)
1070if got != tt.want {
1071t.Errorf("doesMatchConditionsMatches() got = %v, want %v", got, tt.want)
1072}
1073if got1 != tt.want1 {
1074t.Errorf("doesMatchConditionsMatches() got1 = %v, want %v", got1, tt.want1)
1075}
1076})
1077}
1078}
1079
1080func Test_doesNameMatches(t *testing.T) {
1081type args struct {
1082fields common.ARFields
1083match v1alpha1.Match
1084}
1085tests := []struct {
1086name string
1087args args
1088wantMatches bool
1089wantReason string
1090}{
1091{
1092name: "without metadata.name",
1093args: args{
1094fields: common.ARFields{
1095Operation: v1beta1.Create,
1096Object: map[string]interface{}{
1097"metadata": map[string]interface{}{
1098"namespace": "incl_ns",
1099"annotations": map[string]interface{}{"annotNS/annotTr": Enabled},
1100"labels": map[string]interface{}{"key": "val"},
1101},
1102},
1103},
1104match: v1alpha1.Match{
1105Name: v1alpha1.Name{
1106Value: "some_name",
1107},
1108},
1109},
1110wantMatches: false,
1111wantReason: "request.oldObject.metadata.name",
1112},
1113{
1114name: "empty match name",
1115args: args{
1116fields: common.ARFields{
1117Operation: v1beta1.Create,
1118Object: map[string]interface{}{
1119"metadata": map[string]interface{}{
1120"namespace": "incl_ns",
1121"name": "incl_ns",
1122},
1123},
1124},
1125match: v1alpha1.Match{
1126Name: v1alpha1.Name{
1127Value: "",
1128Regex: "",
1129},
1130},
1131},
1132wantMatches: true,
1133wantReason: "",
1134},
1135{
1136name: "match name value",
1137args: args{
1138fields: common.ARFields{
1139Operation: v1beta1.Create,
1140Object: map[string]interface{}{
1141"metadata": map[string]interface{}{
1142"name": "test-nane-value",
1143},
1144},
1145},
1146match: v1alpha1.Match{
1147Name: v1alpha1.Name{
1148Value: "test-nane-value",
1149},
1150},
1151},
1152wantMatches: true,
1153wantReason: "",
1154},
1155{
1156name: "match name regex",
1157args: args{
1158fields: common.ARFields{
1159Operation: v1beta1.Create,
1160Object: map[string]interface{}{
1161"metadata": map[string]interface{}{
1162"name": "test-name-value",
1163},
1164},
1165},
1166match: v1alpha1.Match{
1167Name: v1alpha1.Name{
1168Regex: ".*-name-.*",
1169},
1170},
1171},
1172wantMatches: true,
1173wantReason: "request.oldObject.metadata.name",
1174},
1175{
1176name: "not matched name regex",
1177args: args{
1178fields: common.ARFields{
1179Operation: v1beta1.Create,
1180Object: map[string]interface{}{
1181"metadata": map[string]interface{}{
1182"name": "test-name-value",
1183},
1184},
1185},
1186match: v1alpha1.Match{
1187Name: v1alpha1.Name{
1188Regex: ".*-nane-.*",
1189},
1190},
1191},
1192wantMatches: false,
1193wantReason: "request.oldObject.metadata.name",
1194},
1195{
1196name: "wrong name regex",
1197args: args{
1198fields: common.ARFields{
1199Operation: v1beta1.Create,
1200Object: map[string]interface{}{
1201"metadata": map[string]interface{}{
1202"name": "test-name-value",
1203},
1204},
1205},
1206match: v1alpha1.Match{
1207Name: v1alpha1.Name{
1208Regex: `a(b`,
1209},
1210},
1211},
1212wantMatches: false,
1213wantReason: "wrong match.name.regex: error parsing regexp: missing closing ): `a(b`",
1214},
1215}
1216for _, tt := range tests {
1217t.Run(tt.name, func(t *testing.T) {
1218m := Matcher{}
1219gotMatches, gotReason := m.doesNameMatches(context.Background(), tt.args.fields, tt.args.match)
1220assert.Equalf(t, tt.wantMatches, gotMatches, "doesNameMatches(%v, %v)", tt.args.fields, tt.args.match)
1221assert.Equalf(t, tt.wantReason, gotReason, "doesNameMatches(%v, %v)", tt.args.fields, tt.args.match)
1222})
1223}
1224}
1225
1226func Test_doesNamespaceSelectorMatches(t *testing.T) {
1227type args struct {
1228fields common.ARFields
1229match v1alpha1.Match
1230}
1231tests := []struct {
1232name string
1233args args
1234want bool
1235want1 string
1236}{
1237{
1238name: "empty match section",
1239args: args{
1240fields: common.ARFields{
1241Operation: v1beta1.Update,
1242OldObject: map[string]interface{}{
1243"metadata": map[string]interface{}{
1244"name": "name-obj",
1245"generateName": "generateName-obj",
1246},
1247},
1248Object: map[string]interface{}{
1249"metadata": map[string]interface{}{
1250"name": "name-obj",
1251"generateName": "generateName-obj",
1252},
1253},
1254},
1255match: v1alpha1.Match{
1256NamespaceSelector: v1alpha1.NamespaceSelector{},
1257},
1258},
1259want: true,
1260want1: "namespace selector",
1261},
1262{
1263name: "cluster objet",
1264args: args{
1265fields: common.ARFields{
1266Namespace: "",
1267Operation: v1beta1.Create,
1268Object: map[string]interface{}{
1269"metadata": map[string]interface{}{
1270"name": "name-obj",
1271"generateName": "generateName-obj",
1272},
1273},
1274},
1275match: v1alpha1.Match{
1276NamespaceSelector: v1alpha1.NamespaceSelector{
1277MatchExpressions: []v1alpha1.MatchExpression{
1278{
1279Key: "matchingKey",
1280Operator: "In",
1281Values: []string{"matchingVal"},
1282},
1283},
1284},
1285},
1286},
1287want: true,
1288want1: "namespace selector",
1289},
1290{
1291name: "match namespace",
1292args: args{
1293fields: common.ARFields{
1294Namespace: "ns-test",
1295Operation: v1beta1.Create,
1296Object: map[string]interface{}{
1297"metadata": map[string]interface{}{
1298"name": "name-obj",
1299"generateName": "generateName-obj",
1300},
1301},
1302},
1303match: v1alpha1.Match{
1304NamespaceSelector: v1alpha1.NamespaceSelector{
1305MatchExpressions: []v1alpha1.MatchExpression{
1306{
1307Key: "different-ns",
1308Operator: "In",
1309Values: []string{"matchingVal"},
1310},
1311},
1312},
1313},
1314},
1315want: false,
1316want1: "namespace selector",
1317},
1318}
1319for _, tt := range tests {
1320t.Run(tt.name, func(t *testing.T) {
1321lib.ZapLogger = zap.NewNop()
1322storage.Storage = &storage.StorageController{}
1323storage.Storage.Start(false, false)
1324storage.Storage.UpdateNamespace(corev1.Namespace{
1325TypeMeta: v1.TypeMeta{},
1326ObjectMeta: v1.ObjectMeta{
1327Namespace: "incl_ns",
1328Name: "incl_ns",
1329Labels: map[string]string{"matchingKey": "matchingVal"},
1330},
1331Spec: corev1.NamespaceSpec{},
1332Status: corev1.NamespaceStatus{},
1333})
1334m := Matcher{}
1335got, got1 := m.doesNamespaceSelectorMatches(context.Background(), tt.args.fields, tt.args.match)
1336if got != tt.want {
1337t.Errorf("doesNamespaceSelectorMatches() got = %v, want %v", got, tt.want)
1338}
1339if got1 != tt.want1 {
1340t.Errorf("doesNamespaceSelectorMatches() got1 = %v, want %v", got1, tt.want1)
1341}
1342})
1343}
1344}
1345
1346func Test_doesNsNamesMatch(t *testing.T) {
1347type args struct {
1348matchNs v1alpha1.Namespace
1349ns string
1350include bool
1351}
1352tests := []struct {
1353name string
1354args args
1355want bool
1356want1 string
1357}{
1358{
1359name: "include namespace value must be matched",
1360args: args{
1361matchNs: v1alpha1.Namespace{
1362Values: []string{"kblt-test"},
1363},
1364ns: "kblt-test",
1365include: true,
1366},
1367want: true,
1368want1: "included namespace value",
1369},
1370{
1371name: "include namespace value must be not matched",
1372args: args{
1373matchNs: v1alpha1.Namespace{
1374Values: []string{"test"},
1375},
1376ns: "kblt-test",
1377include: true,
1378},
1379want: false,
1380want1: "included namespace value",
1381},
1382{
1383name: "exclude namespace value must be matched",
1384args: args{
1385matchNs: v1alpha1.Namespace{
1386Values: []string{"test"},
1387},
1388ns: "kblt-test",
1389include: false,
1390},
1391want: true,
1392want1: "excluded namespace value",
1393},
1394{
1395name: "exclude namespace value must be not matched",
1396args: args{
1397matchNs: v1alpha1.Namespace{
1398Values: []string{"kblt-test"},
1399},
1400ns: "kblt-test",
1401include: false,
1402},
1403want: false,
1404want1: "excluded namespace value",
1405},
1406{
1407name: "exclude namespace regex must be not matched",
1408args: args{
1409matchNs: v1alpha1.Namespace{
1410Regex: []string{"kblt-.*"},
1411},
1412ns: "kblt-test",
1413include: false,
1414},
1415want: false,
1416want1: "excluded namespace regex",
1417},
1418{
1419name: "exclude namespace value must be not matched",
1420args: args{
1421matchNs: v1alpha1.Namespace{
1422Regex: []string{".*-test"},
1423},
1424ns: "kblt",
1425include: false,
1426},
1427want: true,
1428want1: "excluded namespace regex",
1429},
1430{
1431name: "exclude namespace invalid regex",
1432args: args{
1433matchNs: v1alpha1.Namespace{
1434Regex: []string{"a(b"},
1435},
1436ns: "kblt",
1437include: false,
1438},
1439want: false,
1440want1: "namespace invalid regex",
1441},
1442}
1443for _, tt := range tests {
1444t.Run(tt.name, func(t *testing.T) {
1445lib.ZapLogger = zap.NewNop()
1446m := Matcher{}
1447got, got1 := m.doesNsNamesMatch(tt.args.matchNs, tt.args.ns, tt.args.include)
1448if got != tt.want {
1449t.Errorf("doesNsNamesMatch() got = %v, want %v", got, tt.want)
1450}
1451if got1 != tt.want1 {
1452t.Errorf("doesNsNamesMatch() got1 = %v, want %v", got1, tt.want1)
1453}
1454})
1455}
1456}
1457
1458func Test_doesObjectSectionMatches(t *testing.T) {
1459type args struct {
1460obj map[string]interface{}
1461matchObjs []v1alpha1.Obj
1462}
1463tests := []struct {
1464name string
1465args args
1466want bool
1467want1 string
1468}{
1469{
1470name: "Empty Match",
1471args: args{
1472obj: map[string]interface{}{
1473"metadata": map[string]interface{}{
1474"name": "name-obj",
1475"generateName": "generateName-obj",
1476},
1477},
1478matchObjs: nil,
1479},
1480want: false,
1481want1: "match conditions doesn't have enough of arguments",
1482},
1483{
1484name: "MustExist Exist",
1485args: args{
1486obj: map[string]interface{}{
1487"metadata": map[string]interface{}{
1488"name": "name-obj",
1489"generateName": "generateName-obj",
1490},
1491},
1492matchObjs: []v1alpha1.Obj{
1493{
1494Path: "metadata",
1495Condition: mustExist,
1496},
1497},
1498},
1499want: true,
1500want1: "",
1501},
1502{
1503name: "MustExist NotExist",
1504args: args{
1505obj: map[string]interface{}{
1506"metadata": map[string]interface{}{
1507"name": "name-obj",
1508"generateName": "generateName-obj",
1509},
1510},
1511matchObjs: []v1alpha1.Obj{
1512{
1513Path: "test",
1514Condition: mustExist,
1515},
1516},
1517},
1518want: false,
1519want1: "match conditions",
1520},
1521{
1522name: "MustNotExist NotExist",
1523args: args{
1524obj: map[string]interface{}{
1525"metadata": map[string]interface{}{
1526"name": "name-obj",
1527"generateName": "generateName-obj",
1528},
1529},
1530matchObjs: []v1alpha1.Obj{
1531{
1532Path: "test",
1533Condition: mustNotExist,
1534},
1535},
1536},
1537want: true,
1538want1: "",
1539},
1540{
1541name: "MustNotExist Exist",
1542args: args{
1543obj: map[string]interface{}{
1544"metadata": map[string]interface{}{
1545"name": "name-obj",
1546"generateName": "generateName-obj",
1547},
1548},
1549matchObjs: []v1alpha1.Obj{
1550{
1551Path: "metadata",
1552Condition: mustNotExist,
1553},
1554},
1555},
1556want: false,
1557want1: "match conditions",
1558},
1559{
1560name: "Wrong path",
1561args: args{
1562obj: map[string]interface{}{
1563"metadata": map[string]interface{}{
1564"name": "name-obj",
1565"generateName": "generateName-obj",
1566},
1567"spec": map[string]interface{}{
1568"containers": []map[string]string{
1569{
1570"name": "istio-proxy",
1571"value": "val",
1572},
1573},
1574"generateName": "generateName-obj",
1575},
1576},
1577matchObjs: []v1alpha1.Obj{
1578{
1579Path: "spec.containers[?@name == `istio-proxy`]",
1580Condition: mustExist,
1581},
1582},
1583},
1584want: false,
1585want1: "match conditions jmespath processing error",
1586},
1587{
1588name: "slice matched",
1589args: args{
1590obj: map[string]interface{}{
1591"metadata": map[string]interface{}{
1592"name": "name-obj",
1593"generateName": "generateName-obj",
1594},
1595"spec": map[string]interface{}{
1596"containers": []map[string]string{
1597{
1598"name": "istio-proxy",
1599"value": "match",
1600"test": "val",
1601},
1602{
1603"name": "test3",
1604"value": "val",
1605"match": "test",
1606},
1607},
1608},
1609},
1610matchObjs: []v1alpha1.Obj{
1611{
1612Path: "spec.containers[? @.name == 'test1']",
1613Condition: mustExist,
1614},
1615},
1616},
1617want: false,
1618want1: "match conditions",
1619},
1620{
1621name: "slice not matched",
1622args: args{
1623obj: map[string]interface{}{
1624"metadata": map[string]interface{}{
1625"name": "name-obj",
1626"generateName": "generateName-obj",
1627},
1628"spec": map[string]interface{}{
1629"containers": []map[string]string{
1630{
1631"name": "istio-proxy",
1632"value": "match",
1633"test": "val",
1634},
1635{
1636"name": "test3",
1637"value": "val",
1638"match": "test",
1639},
1640},
1641},
1642},
1643matchObjs: []v1alpha1.Obj{
1644{
1645Path: "spec.containers[? @.name == 'test1']",
1646Condition: mustNotExist,
1647},
1648},
1649},
1650want: true,
1651want1: "",
1652},
1653{
1654name: "boolean result",
1655args: args{
1656obj: map[string]interface{}{
1657"metadata": map[string]interface{}{
1658"name": "name-obj",
1659"generateName": "generateName-obj",
1660},
1661"spec": map[string]interface{}{
1662"containers": []map[string]interface{}{ //[]map[string]string - wrong type
1663{
1664"name": "istio-proxy",
1665"value": "match",
1666"test": "val",
1667},
1668{
1669"name": "test3",
1670"value": "val",
1671"match": "test3",
1672"image": "val",
1673},
1674},
1675},
1676},
1677matchObjs: []v1alpha1.Obj{
1678{
1679Path: "contains(spec.containers[? @.name==`test3`].image, `val`)",
1680Condition: mustExist,
1681},
1682},
1683},
1684want: true,
1685want1: "",
1686},
1687{
1688name: "boolean result not matched",
1689args: args{
1690obj: map[string]interface{}{
1691"metadata": map[string]interface{}{
1692"name": "name-obj",
1693"generateName": "generateName-obj",
1694},
1695"spec": map[string]interface{}{
1696"containers": []map[string]interface{}{ //[]map[string]string - wrong type
1697{
1698"name": "istio-proxy",
1699"value": "match",
1700"test": "val",
1701},
1702{
1703"name": "test3",
1704"value": "val",
1705"match": "test3",
1706"image": "val",
1707},
1708},
1709},
1710},
1711matchObjs: []v1alpha1.Obj{
1712{
1713Path: "contains(spec.containers[? @.name==`test3`].image, `not mathced`)",
1714Condition: mustExist,
1715},
1716},
1717},
1718want: false,
1719want1: "match conditions",
1720},
1721{
1722name: "boolean result not exist true",
1723args: args{
1724obj: map[string]interface{}{
1725"metadata": map[string]interface{}{
1726"name": "name-obj",
1727"generateName": "generateName-obj",
1728},
1729"spec": map[string]interface{}{
1730"containers": []map[string]interface{}{ //[]map[string]string - wrong type
1731{
1732"name": "istio-proxy",
1733"value": "match",
1734"test": "val",
1735},
1736{
1737"name": "test3",
1738"value": "val",
1739"match": "test3",
1740"image": "val",
1741},
1742},
1743},
1744},
1745matchObjs: []v1alpha1.Obj{
1746{
1747Path: "contains(spec.containers[? @.name==`test3`].image, `not matched`)",
1748Condition: mustNotExist,
1749},
1750},
1751},
1752want: true,
1753want1: "",
1754},
1755{
1756name: "boolean result not exist true",
1757args: args{
1758obj: map[string]interface{}{
1759"metadata": map[string]interface{}{
1760"name": "name-obj",
1761"generateName": "generateName-obj",
1762},
1763"spec": map[string]interface{}{
1764"containers": []map[string]interface{}{ //[]map[string]string - wrong type
1765{
1766"name": "istio-proxy",
1767"value": "match",
1768"test": "val",
1769},
1770{
1771"name": "test3",
1772"value": "val",
1773"match": "test3",
1774"image": "val",
1775},
1776},
1777},
1778},
1779matchObjs: []v1alpha1.Obj{
1780{
1781Path: "contains(spec.containers[? @.name==`test3`].image, `val`)",
1782Condition: mustNotExist,
1783},
1784},
1785},
1786want: false,
1787want1: "match conditions",
1788},
1789{
1790name: "matched result is a number",
1791args: args{
1792obj: map[string]interface{}{
1793"metadata": map[string]interface{}{
1794"name": "name-obj",
1795"generateName": "generateName-obj",
1796"value": 3.14,
1797},
1798"spec": map[string]interface{}{
1799"containers": []map[string]interface{}{ //[]map[string]string - wrong type
1800{
1801"name": "istio-proxy",
1802"value": "3.14",
1803"test": "val",
1804},
1805{
1806"name": "test3",
1807"value": "val",
1808"match": "test3",
1809"image": "val",
1810},
1811},
1812},
1813},
1814matchObjs: []v1alpha1.Obj{
1815{
1816Path: "metadata.value",
1817Condition: mustExist,
1818},
1819},
1820},
1821want: true,
1822want1: "",
1823},
1824{
1825name: "matched result is a string",
1826args: args{
1827obj: map[string]interface{}{
1828"metadata": map[string]interface{}{
1829"name": "name-obj",
1830"generateName": "generateName-obj",
1831"value": 3.14,
1832},
1833"spec": map[string]interface{}{
1834"containers": []map[string]interface{}{ //[]map[string]string - wrong type
1835{
1836"name": "istio-proxy",
1837"value": "3.14",
1838"test": "val",
1839},
1840{
1841"name": "test3",
1842"value": "val",
1843"match": "test3",
1844"image": "val",
1845},
1846},
1847},
1848},
1849matchObjs: []v1alpha1.Obj{
1850{
1851Path: "metadata.name",
1852Condition: mustExist,
1853},
1854},
1855},
1856want: true,
1857want1: "",
1858},
1859{
1860name: "matched result is a map",
1861args: args{
1862obj: map[string]interface{}{
1863"metadata": map[string]interface{}{
1864"name": "name-obj",
1865"generateName": "generateName-obj",
1866"value": 3.14,
1867},
1868},
1869matchObjs: []v1alpha1.Obj{
1870{
1871Path: "metadata",
1872Condition: mustExist,
1873},
1874},
1875},
1876want: true,
1877want1: "",
1878},
1879}
1880for _, tt := range tests {
1881t.Run(tt.name, func(t *testing.T) {
1882lib.ZapLogger = zap.NewNop()
1883m := Matcher{}
1884got, got1 := m.doesObjectSectionMatches(tt.args.obj, tt.args.matchObjs)
1885if got != tt.want {
1886t.Errorf("doesObjectSectionMatches() got = %v, want %v", got, tt.want)
1887}
1888if got1 != tt.want1 {
1889t.Errorf("doesObjectSectionMatches() got1 = %v, want %v", got1, tt.want1)
1890}
1891})
1892}
1893}
1894
1895func Test_doesOperationsMatches(t *testing.T) {
1896type args struct {
1897fields common.ARFields
1898match v1alpha1.Match
1899}
1900tests := []struct {
1901name string
1902args args
1903wantMatches bool
1904wantReason string
1905}{
1906{
1907name: "Empty match section",
1908args: args{
1909fields: common.ARFields{
1910Operation: v1beta1.Create,
1911},
1912match: v1alpha1.Match{},
1913},
1914wantMatches: true,
1915wantReason: "",
1916},
1917{
1918name: "Must be Matched",
1919args: args{
1920fields: common.ARFields{
1921Operation: v1beta1.Create,
1922},
1923match: v1alpha1.Match{
1924Operations: []string{"CREATE"},
1925},
1926},
1927wantMatches: true,
1928wantReason: "",
1929},
1930{
1931name: "Must be not Matched",
1932args: args{
1933fields: common.ARFields{
1934Operation: v1beta1.Delete,
1935},
1936match: v1alpha1.Match{
1937Operations: []string{"CREATE"},
1938},
1939},
1940wantMatches: false,
1941wantReason: "request.operation",
1942},
1943}
1944for _, tt := range tests {
1945t.Run(tt.name, func(t *testing.T) {
1946m := Matcher{}
1947gotMatches, gotReason := m.doesOperationsMatches(context.Background(), tt.args.fields, tt.args.match)
1948if gotMatches != tt.wantMatches {
1949t.Errorf("doesOperationsMatches() gotMatches = %v, want %v", gotMatches, tt.wantMatches)
1950}
1951if gotReason != tt.wantReason {
1952t.Errorf("doesOperationsMatches() gotReason = %v, want %v", gotReason, tt.wantReason)
1953}
1954})
1955}
1956}
1957
1958func Test_doesScopeMatches(t *testing.T) {
1959type args struct {
1960fields common.ARFields
1961match v1alpha1.Match
1962}
1963tests := []struct {
1964name string
1965args args
1966wantMatches bool
1967wantReason string
1968}{
1969{
1970name: "Namespaced match",
1971args: args{
1972fields: common.ARFields{
1973Namespace: "kblt",
1974},
1975match: v1alpha1.Match{
1976Scope: scopeNamespaced,
1977},
1978},
1979wantMatches: true,
1980wantReason: "",
1981},
1982{
1983name: "Namespaced not match",
1984args: args{
1985fields: common.ARFields{},
1986match: v1alpha1.Match{
1987Scope: scopeNamespaced,
1988},
1989},
1990wantMatches: false,
1991wantReason: "request.namespace",
1992},
1993{
1994name: "Cluster match",
1995args: args{
1996fields: common.ARFields{},
1997match: v1alpha1.Match{
1998Scope: scopeCluster,
1999},
2000},
2001wantMatches: true,
2002wantReason: "",
2003},
2004{
2005name: "Cluster not match",
2006args: args{
2007fields: common.ARFields{
2008Namespace: "kblt",
2009},
2010match: v1alpha1.Match{
2011Scope: scopeCluster,
2012},
2013},
2014wantMatches: false,
2015wantReason: "request.namespace",
2016},
2017{
2018name: "Any match",
2019args: args{
2020fields: common.ARFields{},
2021match: v1alpha1.Match{
2022Scope: scopeAny,
2023},
2024},
2025wantMatches: true,
2026wantReason: "",
2027},
2028{
2029name: "Empty match section",
2030args: args{
2031fields: common.ARFields{
2032Namespace: "kblt",
2033},
2034match: v1alpha1.Match{},
2035},
2036wantMatches: true,
2037wantReason: "",
2038},
2039}
2040for _, tt := range tests {
2041t.Run(tt.name, func(t *testing.T) {
2042m := Matcher{}
2043gotMatches, gotReason := m.doesScopeMatches(context.Background(), tt.args.fields, tt.args.match)
2044if gotMatches != tt.wantMatches {
2045t.Errorf("doesScopeMatches() gotMatches = %v, want %v", gotMatches, tt.wantMatches)
2046}
2047if gotReason != tt.wantReason {
2048t.Errorf("doesScopeMatches() gotReason = %v, want %v", gotReason, tt.wantReason)
2049}
2050})
2051}
2052}
2053
2054func Test_doesUserInfoMatches(t *testing.T) {
2055type args struct {
2056fields common.ARFields
2057match v1alpha1.Match
2058}
2059tests := []struct {
2060name string
2061args args
2062wantMatches bool
2063wantReason string
2064}{
2065{
2066name: "Exist user value",
2067args: args{
2068fields: common.ARFields{
2069Namespace: "kblt",
2070UserInfo: common.ARUserInfo{
2071Username: "user-for-test",
2072},
2073Operation: "CREATE",
2074},
2075match: v1alpha1.Match{
2076UserInfo: v1alpha1.UserInfo{
2077Username: "user-for-test",
2078},
2079},
2080},
2081wantMatches: true,
2082wantReason: "",
2083},
2084{
2085name: "NotExist user value",
2086args: args{
2087fields: common.ARFields{
2088Namespace: "kblt",
2089UserInfo: common.ARUserInfo{
2090Username: "user-for-test",
2091},
2092Operation: "CREATE",
2093},
2094match: v1alpha1.Match{
2095UserInfo: v1alpha1.UserInfo{
2096Username: "test-user",
2097},
2098},
2099},
2100wantMatches: false,
2101wantReason: "request.userInfo.username",
2102},
2103{
2104name: "Exist user regex",
2105args: args{
2106fields: common.ARFields{
2107Namespace: "kblt",
2108UserInfo: common.ARUserInfo{
2109Username: "user-for-test",
2110},
2111Operation: "CREATE",
2112},
2113match: v1alpha1.Match{
2114UserInfo: v1alpha1.UserInfo{
2115UsernameRegex: ".*-for-.*",
2116},
2117},
2118},
2119wantMatches: true,
2120wantReason: "",
2121},
2122{
2123name: "NotExist user regex",
2124args: args{
2125fields: common.ARFields{
2126Namespace: "kblt",
2127UserInfo: common.ARUserInfo{
2128Username: "user-for-test",
2129},
2130Operation: "CREATE",
2131},
2132match: v1alpha1.Match{
2133UserInfo: v1alpha1.UserInfo{
2134UsernameRegex: "ololol-.*",
2135},
2136},
2137},
2138wantMatches: false,
2139wantReason: "request.userInfo.username",
2140},
2141{
2142name: "Wrong user regex",
2143args: args{
2144fields: common.ARFields{
2145Namespace: "kblt",
2146UserInfo: common.ARUserInfo{
2147Username: "user-for-test",
2148},
2149Operation: "CREATE",
2150},
2151match: v1alpha1.Match{
2152UserInfo: v1alpha1.UserInfo{
2153UsernameRegex: `a(b`,
2154},
2155},
2156},
2157wantMatches: false,
2158wantReason: "wrong match.userInfo.usernameRegex: error parsing regexp: missing closing ): `a(b`",
2159},
2160{
2161name: "Empty Match section",
2162args: args{
2163fields: common.ARFields{
2164Namespace: "kblt",
2165UserInfo: common.ARUserInfo{
2166Username: "user-for-test",
2167},
2168Operation: "CREATE",
2169},
2170match: v1alpha1.Match{
2171UserInfo: v1alpha1.UserInfo{
2172Username: "",
2173UsernameRegex: "",
2174},
2175},
2176},
2177wantMatches: true,
2178wantReason: "",
2179},
2180{
2181name: "Empty Match section",
2182args: args{
2183fields: common.ARFields{
2184Namespace: "kblt",
2185UserInfo: common.ARUserInfo{
2186Username: "user-for-test",
2187},
2188Operation: "CREATE",
2189},
2190match: v1alpha1.Match{},
2191},
2192wantMatches: true,
2193wantReason: "",
2194},
2195}
2196for _, tt := range tests {
2197t.Run(tt.name, func(t *testing.T) {
2198m := Matcher{}
2199gotMatches, gotReason := m.doesUserInfoMatches(context.Background(), tt.args.fields, tt.args.match)
2200if gotMatches != tt.wantMatches {
2201t.Errorf("doesUserInfoMatches() gotMatches = %v, want %v", gotMatches, tt.wantMatches)
2202}
2203if gotReason != tt.wantReason {
2204t.Errorf("doesUserInfoMatches() gotReason = %v, want %v", gotReason, tt.wantReason)
2205}
2206})
2207}
2208}
2209
2210func Test_findNonRegexNsMatch(t *testing.T) {
2211type args struct {
2212ns string
2213matchVal []string
2214}
2215tests := []struct {
2216name string
2217args args
2218want bool
2219want1 string
2220}{
2221{
2222name: "Exist value",
2223args: args{
2224ns: "kblt",
2225matchVal: []string{"kblt", "test"},
2226},
2227want: true,
2228want1: "namespace value",
2229},
2230{
2231name: "NotExist value",
2232args: args{
2233ns: "kblt",
2234matchVal: []string{"test"},
2235},
2236want: false,
2237want1: "namespace value",
2238},
2239}
2240for _, tt := range tests {
2241t.Run(tt.name, func(t *testing.T) {
2242got, got1 := findNonRegexNsMatch(tt.args.ns, tt.args.matchVal)
2243if got != tt.want {
2244t.Errorf("findNonRegexNsMatch() got = %v, want %v", got, tt.want)
2245}
2246if got1 != tt.want1 {
2247t.Errorf("findNonRegexNsMatch() got1 = %v, want %v", got1, tt.want1)
2248}
2249})
2250}
2251}
2252
2253func Test_findRegexNsMatch(t *testing.T) {
2254type args struct {
2255ns string
2256matchVal []string
2257}
2258tests := []struct {
2259name string
2260args args
2261want bool
2262want1 string
2263}{
2264{
2265name: "Exist value",
2266args: args{
2267ns: "kblt",
2268matchVal: []string{".*blt"},
2269},
2270want: true,
2271want1: "namespace regex",
2272},
2273{
2274name: "NotExist value",
2275args: args{
2276ns: "kblt",
2277matchVal: []string{".*-test"},
2278},
2279want: false,
2280want1: "namespace regex",
2281},
2282{
2283name: "Wrong regex",
2284args: args{
2285ns: "kblt",
2286matchVal: []string{`a(b`},
2287},
2288want: false,
2289want1: "namespace invalid regex",
2290},
2291}
2292for _, tt := range tests {
2293t.Run(tt.name, func(t *testing.T) {
2294lib.ZapLogger = zap.NewNop()
2295got, got1 := findRegexNsMatch(tt.args.ns, tt.args.matchVal)
2296if got != tt.want {
2297t.Errorf("findRegexNsMatch() got = %v, want %v", got, tt.want)
2298}
2299if got1 != tt.want1 {
2300t.Errorf("findRegexNsMatch() got1 = %v, want %v", got1, tt.want1)
2301}
2302})
2303}
2304}
2305
2306func Test_getAdmissionReviewResourceName(t *testing.T) {
2307type args struct {
2308obj map[string]interface{}
2309}
2310tests := []struct {
2311name string
2312args args
2313wantName string
2314}{
2315{
2316name: "name",
2317args: args{
2318obj: map[string]interface{}{
2319"metadata": map[string]interface{}{
2320"name": "name-obj",
2321"generateName": "generateName-obj",
2322},
2323},
2324},
2325wantName: "name-obj",
2326},
2327{
2328name: "generateName",
2329args: args{
2330obj: map[string]interface{}{
2331"metadata": map[string]interface{}{
2332"generateName": "generateName-obj",
2333},
2334},
2335},
2336wantName: "generateName-obj",
2337},
2338{
2339name: "empty name",
2340args: args{
2341obj: map[string]interface{}{
2342"metadata": map[string]interface{}{
2343"whatsYourName": "zhoskiy",
2344},
2345},
2346},
2347wantName: "config_name_was_not_found",
2348},
2349}
2350for _, tt := range tests {
2351t.Run(tt.name, func(t *testing.T) {
2352if gotName := getAdmissionReviewResourceName(tt.args.obj); gotName != tt.wantName {
2353t.Errorf("getAdmissionReviewResourceName() = %v, want %v", gotName, tt.wantName)
2354}
2355})
2356}
2357}
2358
2359func Test_getObjectToValidate(t *testing.T) {
2360type args struct {
2361data common.ARFields
2362}
2363tests := []struct {
2364name string
2365args args
2366want map[string]interface{}
2367}{
2368{
2369name: "Create",
2370args: args{data: common.ARFields{
2371Operation: v1beta1.Create,
2372OldObject: map[string]interface{}{"old": -1},
2373Object: map[string]interface{}{"new": 1},
2374}},
2375want: map[string]interface{}{"new": 1},
2376},
2377{
2378name: "Update",
2379args: args{data: common.ARFields{
2380Operation: v1beta1.Update,
2381OldObject: map[string]interface{}{"old": -1},
2382Object: map[string]interface{}{"new": 1},
2383}},
2384want: map[string]interface{}{"new": 1},
2385},
2386{
2387name: "Delete",
2388args: args{data: common.ARFields{
2389Operation: v1beta1.Delete,
2390OldObject: map[string]interface{}{"old": -1},
2391Object: map[string]interface{}{"new": 1},
2392}},
2393want: map[string]interface{}{"old": -1},
2394},
2395{
2396name: "Wrong",
2397args: args{data: common.ARFields{
2398Operation: v1beta1.Operation("wrong"),
2399OldObject: map[string]interface{}{"old": -1},
2400Object: map[string]interface{}{"new": 1},
2401}},
2402want: nil,
2403},
2404}
2405for _, tt := range tests {
2406t.Run(tt.name, func(t *testing.T) {
2407lib.ZapLogger = zap.NewNop()
2408assert.Equalf(t, tt.want, getObjectToValidate(context.Background(), tt.args.data), "getObjectToValidate(%v)", tt.args.data)
2409})
2410}
2411}
2412