kubelatte-ce
Форк от sbertech/kubelatte-ce
915 строк · 39.4 Кб
1package sideeffect
2
3import (
4"context"
5"errors"
6"github.com/stretchr/testify/mock"
7"gitverse.ru/synapse/kubelatte/pkg/api/v1alpha1"
8"gitverse.ru/synapse/kubelatte/pkg/kubeapi"
9"gitverse.ru/synapse/kubelatte/pkg/observability/logger/lib"
10"gitverse.ru/synapse/kubelatte/pkg/operator/controllers/clientset"
11mocks2 "gitverse.ru/synapse/kubelatte/pkg/operator/controllers/clientset/mocks"
12semodles "gitverse.ru/synapse/kubelatte/pkg/sideeffect"
13"gitverse.ru/synapse/kubelatte/pkg/storage"
14"gitverse.ru/synapse/kubelatte/pkg/util/env"
15"go.uber.org/zap"
16errors2 "k8s.io/apimachinery/pkg/api/errors"
17metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
18"k8s.io/apimachinery/pkg/runtime/schema"
19"k8s.io/client-go/kubernetes"
20"k8s.io/client-go/rest"
21"os"
22"sync"
23"testing"
24"time"
25)
26
27func TestMain(m *testing.M) {
28kubeapi.GetKBLTClient = func() (*clientset.V1Alpha1Client, error) {
29return nil, nil
30}
31kubeapi.GetResourceMeta = func(client *kubernetes.Clientset, kind string, version string) *kubeapi.ResourceMeta {
32return &kubeapi.ResourceMeta{Name: "sth"}
33}
34kubeapi.GetResource = func(ctx context.Context, resourceMeta *kubeapi.ResourceMeta, resourceName string, namespace string) ([]byte, error) {
35return []byte("{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"name\":\"pod-se-plus-mutation\",\"resourceVersion\": \"verse1\",\"uid\": \"31ce6848-bee4-40fb-be85-7f796dd11685\",\"namespace\":\"kate-kblt-dev\",\"labels\":{\"sidecar.istio.io/inject\":\"false\",\"side-effect-plus-mutation\":\"enabled\"},\"annotations\":{\"kblt.annot-ns/merge\":\"enabled\", \"kblt.sideEffect.resource/tag\": \"5\"}},\"spec\":{\"hostNetwork\":false,\"serviceAccount\":\"default\",\"serviceAccountName\":\"default\",\"restartPolicy\":\"Never\",\"automountServiceAccountToken\":false,\"securityContext\":{\"runAsNonRoot\":true,\"seccompProfile\":{\"type\":\"RuntimeDefault\"}},\"containers\":[{\"image\":\"dzo.sw.sbc.space/sbt_dev/ci90000221_fedmesh_dev/federation-demo@sha256:548cc416011c86bb1e2c6d06289aab0771a0f749c044656deaac5fc86d891fea\",\"name\":\"test\",\"imagePullPolicy\":\"Always\",\"securityContext\":{\"allowPrivilegeEscalation\":false,\"capabilities\":{\"drop\":[\"ALL\"]},\"runAsNonRoot\":true,\"privileged\":false}}]}}"), nil
36}
37kubeapi.GetClient = func() *kubernetes.Clientset {
38return nil
39}
40kubeapi.InvalidateCacheAndTryGetResourceMeta = func(client *kubernetes.Clientset, kind string, version string) *kubeapi.ResourceMeta {
41return nil
42}
43kubeapi.CheckResourceMeta = func(client *kubernetes.Clientset, kind string, version string) *kubeapi.ResourceMeta {
44return nil
45}
46kubeapi.GetRawResourceFromKubeApi = func(ctx context.Context, client rest.Interface, resourceMeta *kubeapi.ResourceMeta, resourceName string, namespaceName string) ([]byte, error) {
47return []byte{}, nil
48}
49
50kubeapi.CreateResourceInKubeApi = func(ctx context.Context, client rest.Interface, resourceMeta *kubeapi.ResourceMeta, jsBody []byte, namespaceName string) ([]byte, error, error) {
51return nil, nil, nil
52}
53lib.ZapLogger = zap.NewNop()
54code := m.Run()
55os.Exit(code)
56}
57
58// hashes should be different only if one of ControlFields have diffs (ann, labels, spec or data)
59func TestController_getObjControlFieldsHash_SimilarHashes(t *testing.T) {
60type args struct {
61obj map[string]any
62}
63env.PrefixSideEffectRecreate = "kblt/"
64tests := []struct {
65name string
66args1 args
67args2 args
68args3 args
69want string
70wantErr bool
71}{
72{
73name: "equal hashes annots + labels",
74args1: args{obj: map[string]any{
75"metadata": map[string]any{
76"name": "some_name1",
77"namespace": "incl_ns1",
78"annotations": map[string]any{*prefix + ".annotNS/annotTr": "Enabled"},
79"labels": map[string]any{
80*prefix + ".key1": "val1",
81*prefix + ".key2": "val2",
82*prefix + ".key3": "val3"},
83},
84}},
85args2: args{obj: map[string]any{
86"metadata": map[string]any{
87"name": "some_name2",
88"field": "incl_ns2",
89"annotations": map[string]any{*prefix + ".annotNS/annotTr": "Enabled"},
90"labels": map[string]any{
91"key_without_pref333333": "val",
92*prefix + ".key1": "val1",
93*prefix + ".key2": "val2",
94*prefix + ".key3": "val3"}},
95}},
96args3: args{obj: map[string]any{
97"metadata": map[string]any{
98"name": "some_name3",
99"namespace": "incl_ns3",
100"annotations": map[string]any{*prefix + ".annotNS/annotTr": "Enabled"},
101"labels": map[string]any{
102"key_without_pref1": "val",
103"key_without_pref2": "val",
104"key_without_pref3": "val",
105"key_without_pref4": "val",
106"key_without_pref5": "val",
107"key_without_pref6": "val",
108*prefix + ".key1": "val1",
109"key_without_pref7": "val",
110"key_without_pref8": "val",
111*prefix + ".key2": "val2",
112"key_without_pref9": "val",
113*prefix + ".key3": "val3"}},
114}},
115want: "2708313859359176490",
116wantErr: false,
117},
118{
119name: "equal hashes spec + data",
120args1: args{obj: map[string]any{
121"metadata": map[string]any{
122"name": "some_name1",
123"namespace": "incl_ns1",
124"spec": map[string]any{"img": "image]"},
125"data": map[string]any{"key1": "val1", "key2": "val2", "key3": "val3"},
126},
127}},
128args2: args{obj: map[string]any{
129"metadata": map[string]any{
130"name": "some_name2",
131"field": "incl_ns2",
132"spec": map[string]any{"img": "image]"},
133"data": map[string]any{"key1": "val1", "key2": "val2", "key3": "val3"},
134},
135}},
136args3: args{obj: map[string]any{
137"metadata": map[string]any{
138"name": "some_name3",
139"namespace": "incl_ns3",
140"spec": map[string]any{"img": "image]"},
141"data": map[string]any{"key1": "val1", "key2": "val2", "key3": "val3"},
142},
143}},
144want: "10562426954055529816",
145wantErr: false,
146},
147{
148name: "equal hashes annots + labels + spec + data",
149args1: args{obj: map[string]any{
150"metadata": map[string]any{
151"name": "some_name1",
152"namespace": "incl_ns1",
153"spec": map[string]any{"img": "image]"},
154"data": map[string]any{"key1": "val1", "key2": "val2", "key3": "val3"},
155"annotations": map[string]any{*prefix + ".annotNS/annotTr": "Enabled"},
156"labels": map[string]any{
157"key_without_pref1": "val",
158"key_without_pref2": "val",
159"key_without_pref3": "val",
160"key_without_pref4": "val",
161"key_without_pref5": "val",
162"key_without_pref6": "val",
163*prefix + ".key1": "val1",
164"key_without_pref7": "val",
165"key_without_pref8": "val",
166*prefix + ".key2": "val2",
167"key_without_pref9": "val",
168*prefix + ".key3": "val3"}},
169},
170},
171args2: args{obj: map[string]any{
172"metadata": map[string]any{
173"name": "some_name2",
174"field": "incl_ns2",
175"spec": map[string]any{"img": "image]"},
176"data": map[string]any{"key1": "val1", "key2": "val2", "key3": "val3"},
177"annotations": map[string]any{*prefix + ".annotNS/annotTr": "Enabled"},
178"labels": map[string]any{
179"key_without_pref333333": "val",
180*prefix + ".key2": "val2",
181*prefix + ".key1": "val1",
182*prefix + ".key3": "val3"},
183},
184}},
185args3: args{obj: map[string]any{
186"metadata": map[string]any{
187"name": "some_name3",
188"namespace": "incl_ns3",
189"spec": map[string]any{"img": "image]"},
190"data": map[string]any{"key1": "val1", "key2": "val2", "key3": "val3"},
191"annotations": map[string]any{*prefix + ".annotNS/annotTr": "Enabled"},
192"labels": map[string]any{
193*prefix + ".key1": "val1",
194*prefix + ".key2": "val2",
195*prefix + ".key3": "val3"},
196},
197}},
198want: "2708313859359176490",
199wantErr: false,
200},
201}
202for _, tt := range tests {
203t.Run(tt.name, func(t *testing.T) {
204c := &Executor{}
205
206got1, err1 := c.getObjControlFieldsHash(context.Background(), tt.args1.obj)
207got2, err2 := c.getObjControlFieldsHash(context.Background(), tt.args2.obj)
208got3, err3 := c.getObjControlFieldsHash(context.Background(), tt.args3.obj)
209
210if (err1 != nil) != tt.wantErr || (err2 != nil) != tt.wantErr || (err3 != nil) != tt.wantErr {
211t.Errorf("getObjControlFieldsHash() errors: %v, %v, %v, wantErr %v", err1.Error(), err2.Error(), err3.Error(), tt.wantErr)
212return
213}
214
215if got1 != tt.want {
216t.Errorf("getObjControlFieldsHash() got = %v, want %v", got1, tt.want)
217}
218if got2 != tt.want {
219t.Errorf("getObjControlFieldsHash() got = %v, want %v", got2, tt.want)
220}
221if got3 != tt.want {
222t.Errorf("getObjControlFieldsHash() got = %v, want %v", got3, tt.want)
223}
224
225if got1 != got2 || got2 != got3 {
226t.Errorf("results are not equal to each ther: \n1: %v, \n2: %v, \n3: %v", got1, got2, got3)
227}
228})
229}
230}
231
232func TestController_getObjControlFieldsHash_DiffHashes(t *testing.T) {
233type args struct {
234obj map[string]any
235}
236env.PrefixSideEffectRecreate = "kblt/"
237tests := []struct {
238name string
239args1 args
240args2 args
241want string
242wantErr bool
243}{
244{
245name: "equal hashes annots + labels",
246args1: args{obj: map[string]any{
247"metadata": map[string]any{
248"name": "some_name1",
249"namespace": "incl_ns1",
250"annotations": map[string]any{*prefix + ".annotNS/annotTr": "Enabled"},
251"labels": map[string]any{
252*prefix + ".key1": "val1",
253*prefix + ".key2": "val2",
254*prefix + ".key3": "val3"},
255},
256}},
257args2: args{obj: map[string]any{
258"metadata": map[string]any{
259"name": "some_name2",
260"field": "incl_ns2",
261"annotations": map[string]any{*prefix + ".annotNS/annotTr": "Enabled"},
262"labels": map[string]any{
263"key_without_pref333333": "val",
264*prefix + ".key1": "val1",
265*prefix + ".key2": "val2",
266*prefix + ".key3": "val3"}},
267}},
268want: "2708313859359176490",
269wantErr: false,
270},
271{
272name: "equal hashes spec + data",
273args1: args{obj: map[string]any{
274"metadata": map[string]any{
275"name": "some_name1",
276"namespace": "incl_ns1",
277"spec": map[string]any{"img": "image]"},
278"data": map[string]any{"key1": "val1", "key2": "val2", "key3": "val3"},
279},
280}},
281args2: args{obj: map[string]any{
282"metadata": map[string]any{
283"name": "some_name2",
284"field": "incl_ns2",
285"spec": map[string]any{"img": "image]"},
286"data": map[string]any{"key1": "val1", "key2": "val2", "key3": "val3"},
287},
288}},
289want: "10562426954055529816",
290wantErr: false,
291},
292{
293name: "equal hashes annots + labels + spec + data",
294args1: args{obj: map[string]any{
295"metadata": map[string]any{
296"name": "some_name1",
297"namespace": "incl_ns1",
298"spec": map[string]any{"img": "image]"},
299"data": map[string]any{"key1": "val1", "key2": "val2", "key3": "val3"},
300"labels": map[string]any{
301"key_without_pref1": "val",
302"key_without_pref2": "val",
303"key_without_pref3": "val",
304"key_without_pref4": "val",
305"key_without_pref5": "val",
306"key_without_pref6": "val",
307*prefix + ".key1": "val1",
308"key_without_pref7": "val",
309"key_without_pref8": "val",
310*prefix + ".key2": "val2",
311"key_without_pref9": "val",
312*prefix + ".key3": "val3"}},
313},
314},
315args2: args{obj: map[string]any{
316"metadata": map[string]any{
317"name": "some_name2",
318"field": "incl_ns2",
319"spec": map[string]any{"img": "image]"},
320"data": map[string]any{"key1": "val1", "key2": "val2", "key3": "val3"},
321"annotations": map[string]any{*prefix + ".annotNS/annotTr": "Enabled"},
322"labels": map[string]any{
323"key_without_pref333333": "val",
324*prefix + ".key1": "val1",
325*prefix + ".key2": "val2",
326*prefix + ".key3": "val3"},
327},
328}},
329want: "18154908706307353440",
330wantErr: false,
331},
332}
333for _, tt := range tests {
334t.Run(tt.name, func(t *testing.T) {
335c := &Executor{}
336
337got1, err1 := c.getObjControlFieldsHash(context.Background(), tt.args1.obj)
338got2, err2 := c.getObjControlFieldsHash(context.Background(), tt.args1.obj)
339got3, err3 := c.getObjControlFieldsHash(context.Background(), tt.args1.obj)
340
341if (err1 != nil) != tt.wantErr || (err2 != nil) != tt.wantErr || (err3 != nil) != tt.wantErr {
342t.Errorf("getObjControlFieldsHash() errors: %v, %v, %v, wantErr %v", err1.Error(), err2.Error(), err3.Error(), tt.wantErr)
343return
344}
345
346if got1 != tt.want {
347t.Errorf("getObjControlFieldsHash() got = %v, want %v", got1, tt.want)
348}
349if got2 != tt.want {
350t.Errorf("getObjControlFieldsHash() got = %v, want %v", got1, tt.want)
351}
352if got3 != tt.want {
353t.Errorf("getObjControlFieldsHash() got = %v, want %v", got1, tt.want)
354}
355
356if got1 != got2 || got2 != got3 {
357t.Errorf("results are not equal to each ther: \n1: %v, \n2: %v, \n3: %v", got1, got2, got3)
358}
359})
360}
361}
362
363func TestController_applySideEffectRecreate(t *testing.T) {
364type args struct {
365info *semodles.SE
366}
367tests := []struct {
368name string
369setVars func()
370template v1alpha1.Template
371trigger v1alpha1.Trigger
372args args
373ti v1alpha1.TriggerInstance
374}{
375{
376name: "success recreation",
377ti: v1alpha1.TriggerInstance{
378TypeMeta: metav1.TypeMeta{
379Kind: "",
380APIVersion: "",
381},
382ObjectMeta: metav1.ObjectMeta{
383Name: "",
384Labels: nil,
385Annotations: map[string]string{
386env.AnnotSideEffConfigName: "SideEffConfigName",
387env.AnnotTriggerNamespace: "TriggerNamespace",
388env.AnnotTriggerName: "TriggerName",
389env.AnnotParentHash: "12345677",
390},
391},
392Spec: v1alpha1.TriggerInstanceSpec{},
393Status: v1alpha1.TriggerInstanceStatus{},
394},
395setVars: func() {
396kubeapi.GetResourceMeta = func(client *kubernetes.Clientset, kind string, version string) *kubeapi.ResourceMeta {
397return &kubeapi.ResourceMeta{
398Name: "Pod",
399Plural: "pods",
400Path: "api",
401Namespaced: true,
402GroupVersion: "v1",
403}
404}
405env.TimeoutSideEffectParentPublicationWaiting = 2 * time.Second
406kubeapi.GetResource = func(ctx context.Context, resourceMeta *kubeapi.ResourceMeta, resourceName string, namespaceName string) ([]byte, error) {
407return []byte("{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"name\":\"pod-se-plus-mutation\",\"resourceVersion\": \"verse1\",\"uid\": \"31ce6848-bee4-40fb-be85-7f796dd11685\",\"namespace\":\"kate-kblt-dev\",\"labels\":{\"sidecar.istio.io/inject\":\"false\",\"side-effect-plus-mutation\":\"enabled\"},\"annotations\":{\"kblt.annot-ns/merge\":\"enabled\", \"kblt.sideEffect.resource/tag\": \"5\"}},\"spec\":{\"hostNetwork\":false,\"serviceAccount\":\"default\",\"serviceAccountName\":\"default\",\"restartPolicy\":\"Never\",\"automountServiceAccountToken\":false,\"securityContext\":{\"runAsNonRoot\":true,\"seccompProfile\":{\"type\":\"RuntimeDefault\"}},\"containers\":[{\"image\":\"dzo.sw.sbc.space/sbt_dev/ci90000221_fedmesh_dev/federation-demo@sha256:548cc416011c86bb1e2c6d06289aab0771a0f749c044656deaac5fc86d891fea\",\"name\":\"test\",\"imagePullPolicy\":\"Always\",\"securityContext\":{\"allowPrivilegeEscalation\":false,\"capabilities\":{\"drop\":[\"ALL\"]},\"runAsNonRoot\":true,\"privileged\":false}}]}}"), nil
408}
409},
410trigger: v1alpha1.Trigger{
411ObjectMeta: metav1.ObjectMeta{Name: "TriggerName", Namespace: "TriggerNamespace"},
412Spec: v1alpha1.TriggerSpec{
413SideEffectConfigs: []v1alpha1.SideEffectConfig{{
414Name: "SideEffConfigName",
415TemplateRefs: []string{"templNs/templName"},
416}}},
417},
418template: v1alpha1.Template{
419ObjectMeta: metav1.ObjectMeta{
420Namespace: "templNs",
421Name: "templName",
422},
423Spec: v1alpha1.TemplateSpec{
424Data: "---\nkind: TriggerInstance\napiVersion: kubelatte.synapse.sber/v1alpha1\nmetadata:\n name: trigger-instance-se-plus-mutation\n annotations:\n kblt/side-effect-plus-mutation: enabled\nspec:\n data: data\n",
425},
426},
427args: args{
428info: &semodles.SE{
429SeMode: int32(semodles.Recreation),
430Configs: semodles.Configs{
431Kind: "Pod",
432ApiVersion: "v1",
433Metadata: semodles.Metadata{
434Namespace: "kblt-dev",
435Name: "podik :D ! XD",
436},
437ParentTag: 5,
438TemplateRefs: []string{"templNs/templName"},
439TriggerRef: semodles.TriggerRef{
440Name: "TriggerName",
441Namespace: "TriggerNamespace",
442SideEffectConfig: "SideEffConfigName",
443},
444},
445}},
446},
447{
448name: "no parent hash",
449ti: v1alpha1.TriggerInstance{
450TypeMeta: metav1.TypeMeta{
451Kind: "",
452APIVersion: "",
453},
454ObjectMeta: metav1.ObjectMeta{
455Name: "",
456Labels: nil,
457Annotations: map[string]string{
458env.AnnotSideEffConfigName: "SideEffConfigName",
459env.AnnotTriggerNamespace: "TriggerNamespace",
460env.AnnotTriggerName: "TriggerName",
461env.AnnotParentHash: "",
462},
463},
464Spec: v1alpha1.TriggerInstanceSpec{},
465Status: v1alpha1.TriggerInstanceStatus{},
466},
467setVars: func() {
468kubeapi.GetResourceMeta = func(client *kubernetes.Clientset, kind string, version string) *kubeapi.ResourceMeta {
469return &kubeapi.ResourceMeta{
470Name: "Pod",
471Plural: "pods",
472Path: "api",
473Namespaced: true,
474GroupVersion: "v1",
475}
476}
477env.TimeoutSideEffectParentPublicationWaiting = 2 * time.Second
478kubeapi.GetResource = func(ctx context.Context, resourceMeta *kubeapi.ResourceMeta, resourceName string, namespaceName string) ([]byte, error) {
479return []byte("{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"name\":\"pod-se-plus-mutation\",\"resourceVersion\": \"verse1\",\"uid\": \"31ce6848-bee4-40fb-be85-7f796dd11685\",\"namespace\":\"kate-kblt-dev\",\"labels\":{\"sidecar.istio.io/inject\":\"false\",\"side-effect-plus-mutation\":\"enabled\"},\"annotations\":{\"kblt.annot-ns/merge\":\"enabled\", \"kblt.sideEffect.resource/tag\": \"5\"}},\"spec\":{\"hostNetwork\":false,\"serviceAccount\":\"default\",\"serviceAccountName\":\"default\",\"restartPolicy\":\"Never\",\"automountServiceAccountToken\":false,\"securityContext\":{\"runAsNonRoot\":true,\"seccompProfile\":{\"type\":\"RuntimeDefault\"}},\"containers\":[{\"image\":\"dzo.sw.sbc.space/sbt_dev/ci90000221_fedmesh_dev/federation-demo@sha256:548cc416011c86bb1e2c6d06289aab0771a0f749c044656deaac5fc86d891fea\",\"name\":\"test\",\"imagePullPolicy\":\"Always\",\"securityContext\":{\"allowPrivilegeEscalation\":false,\"capabilities\":{\"drop\":[\"ALL\"]},\"runAsNonRoot\":true,\"privileged\":false}}]}}"), nil
480}
481},
482trigger: v1alpha1.Trigger{
483ObjectMeta: metav1.ObjectMeta{Name: "TriggerName", Namespace: "TriggerNamespace"},
484Spec: v1alpha1.TriggerSpec{
485SideEffectConfigs: []v1alpha1.SideEffectConfig{{
486Name: "SideEffConfigName",
487TemplateRefs: []string{"templNs/templName"},
488}}},
489},
490template: v1alpha1.Template{
491ObjectMeta: metav1.ObjectMeta{
492Namespace: "templNs",
493Name: "templName",
494},
495Spec: v1alpha1.TemplateSpec{
496Data: "---\nkind: TriggerInstance\napiVersion: kubelatte.synapse.sber/v1alpha1\nmetadata:\n name: trigger-instance-se-plus-mutation\n annotations:\n kblt/side-effect-plus-mutation: enabled\nspec:\n data: data\n",
497},
498},
499args: args{
500info: &semodles.SE{
501SeMode: int32(semodles.Recreation),
502Configs: semodles.Configs{
503Kind: "Pod",
504ApiVersion: "v1",
505Metadata: semodles.Metadata{
506Namespace: "kblt-dev",
507Name: "podik :D ! XD",
508},
509ParentTag: 5,
510TemplateRefs: []string{"templNs/templName"},
511TriggerRef: semodles.TriggerRef{
512Name: "TriggerName",
513Namespace: "TriggerNamespace",
514SideEffectConfig: "SideEffConfigName",
515},
516},
517}},
518},
519{
520name: "empty timeout",
521ti: v1alpha1.TriggerInstance{
522TypeMeta: metav1.TypeMeta{
523Kind: "",
524APIVersion: "",
525},
526ObjectMeta: metav1.ObjectMeta{
527Name: "",
528Labels: nil,
529Annotations: map[string]string{
530env.AnnotSideEffConfigName: "SideEffConfigName",
531env.AnnotTriggerNamespace: "TriggerNamespace",
532env.AnnotTriggerName: "TriggerName",
533env.AnnotParentHash: "12345677",
534},
535},
536Spec: v1alpha1.TriggerInstanceSpec{},
537Status: v1alpha1.TriggerInstanceStatus{},
538},
539setVars: func() {
540kubeapi.GetResourceMeta = func(client *kubernetes.Clientset, kind string, version string) *kubeapi.ResourceMeta {
541return &kubeapi.ResourceMeta{
542Name: "Pod",
543Plural: "pods",
544Path: "api",
545Namespaced: true,
546GroupVersion: "v1",
547}
548}
549kubeapi.GetResource = func(ctx context.Context, resourceMeta *kubeapi.ResourceMeta, resourceName string, namespaceName string) ([]byte, error) {
550return []byte("{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"name\":\"pod-se-plus-mutation\",\"resourceVersion\": \"verse1\",\"uid\": \"31ce6848-bee4-40fb-be85-7f796dd11685\",\"namespace\":\"kate-kblt-dev\",\"labels\":{\"sidecar.istio.io/inject\":\"false\",\"side-effect-plus-mutation\":\"enabled\"},\"annotations\":{\"kblt.annot-ns/merge\":\"enabled\", \"kblt.sideEffect.resource/tag\": \"5\"}},\"spec\":{\"hostNetwork\":false,\"serviceAccount\":\"default\",\"serviceAccountName\":\"default\",\"restartPolicy\":\"Never\",\"automountServiceAccountToken\":false,\"securityContext\":{\"runAsNonRoot\":true,\"seccompProfile\":{\"type\":\"RuntimeDefault\"}},\"containers\":[{\"image\":\"dzo.sw.sbc.space/sbt_dev/ci90000221_fedmesh_dev/federation-demo@sha256:548cc416011c86bb1e2c6d06289aab0771a0f749c044656deaac5fc86d891fea\",\"name\":\"test\",\"imagePullPolicy\":\"Always\",\"securityContext\":{\"allowPrivilegeEscalation\":false,\"capabilities\":{\"drop\":[\"ALL\"]},\"runAsNonRoot\":true,\"privileged\":false}}]}}"), nil
551}
552},
553trigger: v1alpha1.Trigger{
554ObjectMeta: metav1.ObjectMeta{Name: "TriggerName", Namespace: "TriggerNamespace"},
555Spec: v1alpha1.TriggerSpec{
556SideEffectConfigs: []v1alpha1.SideEffectConfig{{
557Name: "SideEffConfigName",
558TemplateRefs: []string{"templNs/templName"},
559}}},
560},
561template: v1alpha1.Template{
562ObjectMeta: metav1.ObjectMeta{
563Namespace: "templNs",
564Name: "templName",
565},
566Spec: v1alpha1.TemplateSpec{
567Data: "---\nkind: TriggerInstance\napiVersion: kubelatte.synapse.sber/v1alpha1\nmetadata:\n name: trigger-instance-se-plus-mutation\n annotations:\n kblt/side-effect-plus-mutation: enabled\nspec:\n data: data\n",
568},
569},
570args: args{
571info: &semodles.SE{
572SeMode: int32(semodles.Recreation),
573Configs: semodles.Configs{
574Kind: "Pod",
575ApiVersion: "v1",
576Metadata: semodles.Metadata{
577Namespace: "kblt-dev",
578Name: "podik :D ! XD",
579},
580ParentTag: 5,
581TemplateRefs: []string{"templNs/templName"},
582TriggerRef: semodles.TriggerRef{
583Name: "TriggerName",
584Namespace: "TriggerNamespace",
585SideEffectConfig: "SideEffConfigName",
586},
587},
588}},
589},
590{
591name: "gettimg parent error",
592ti: v1alpha1.TriggerInstance{
593TypeMeta: metav1.TypeMeta{
594Kind: "",
595APIVersion: "",
596},
597ObjectMeta: metav1.ObjectMeta{
598Name: "",
599Labels: nil,
600Annotations: map[string]string{
601env.AnnotSideEffConfigName: "SideEffConfigName",
602env.AnnotTriggerNamespace: "TriggerNamespace",
603env.AnnotTriggerName: "TriggerName",
604env.AnnotParentHash: "12345677",
605},
606},
607Spec: v1alpha1.TriggerInstanceSpec{},
608Status: v1alpha1.TriggerInstanceStatus{},
609},
610setVars: func() {
611kubeapi.GetResourceMeta = func(client *kubernetes.Clientset, kind string, version string) *kubeapi.ResourceMeta {
612return &kubeapi.ResourceMeta{
613Name: "Pod",
614Plural: "pods",
615Path: "api",
616Namespaced: true,
617GroupVersion: "v1",
618}
619}
620env.TimeoutSideEffectParentPublicationWaiting = 2 * time.Second
621kubeapi.GetResource = func(ctx context.Context, resourceMeta *kubeapi.ResourceMeta, resourceName string, namespaceName string) ([]byte, error) {
622return []byte("{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"name\":\"pod-se-plus-mutation\",\"resourceVersion\": \"verse1\",\"uid\": \"31ce6848-bee4-40fb-be85-7f796dd11685\",\"namespace\":\"kate-kblt-dev\",\"labels\":{\"sidecar.istio.io/inject\":\"false\",\"side-effect-plus-mutation\":\"enabled\"},\"annotations\":{\"kblt.annot-ns/merge\":\"enabled\", \"kblt.sideEffect.resource/tag\": \"5\"}},\"spec\":{\"hostNetwork\":false,\"serviceAccount\":\"default\",\"serviceAccountName\":\"default\",\"restartPolicy\":\"Never\",\"automountServiceAccountToken\":false,\"securityContext\":{\"runAsNonRoot\":true,\"seccompProfile\":{\"type\":\"RuntimeDefault\"}},\"containers\":[{\"image\":\"dzo.sw.sbc.space/sbt_dev/ci90000221_fedmesh_dev/federation-demo@sha256:548cc416011c86bb1e2c6d06289aab0771a0f749c044656deaac5fc86d891fea\",\"name\":\"test\",\"imagePullPolicy\":\"Always\",\"securityContext\":{\"allowPrivilegeEscalation\":false,\"capabilities\":{\"drop\":[\"ALL\"]},\"runAsNonRoot\":true,\"privileged\":false}}]}}"), errors.New("")
623}
624},
625trigger: v1alpha1.Trigger{
626ObjectMeta: metav1.ObjectMeta{Name: "TriggerName", Namespace: "TriggerNamespace"},
627Spec: v1alpha1.TriggerSpec{
628SideEffectConfigs: []v1alpha1.SideEffectConfig{{
629Name: "SideEffConfigName",
630TemplateRefs: []string{"templNs/templName"},
631}}},
632},
633template: v1alpha1.Template{
634ObjectMeta: metav1.ObjectMeta{
635Namespace: "templNs",
636Name: "templName",
637},
638Spec: v1alpha1.TemplateSpec{
639Data: "---\nkind: TriggerInstance\napiVersion: kubelatte.synapse.sber/v1alpha1\nmetadata:\n name: trigger-instance-se-plus-mutation\n annotations:\n kblt/side-effect-plus-mutation: enabled\nspec:\n data: data\n",
640},
641},
642args: args{
643info: &semodles.SE{
644SeMode: int32(semodles.Recreation),
645Configs: semodles.Configs{
646Kind: "Pod",
647ApiVersion: "v1",
648Metadata: semodles.Metadata{
649Namespace: "kblt-dev",
650Name: "podik :D ! XD",
651},
652ParentTag: 5,
653TemplateRefs: []string{"templNs/templName"},
654TriggerRef: semodles.TriggerRef{
655Name: "TriggerName",
656Namespace: "TriggerNamespace",
657SideEffectConfig: "SideEffConfigName",
658},
659},
660}},
661},
662{
663name: "no templates",
664ti: v1alpha1.TriggerInstance{
665TypeMeta: metav1.TypeMeta{
666Kind: "",
667APIVersion: "",
668},
669ObjectMeta: metav1.ObjectMeta{
670Name: "",
671Labels: nil,
672Annotations: map[string]string{
673env.AnnotSideEffConfigName: "SideEffConfigName",
674env.AnnotTriggerNamespace: "TriggerNamespace",
675env.AnnotTriggerName: "TriggerName",
676env.AnnotParentHash: "12345677",
677},
678},
679Spec: v1alpha1.TriggerInstanceSpec{},
680Status: v1alpha1.TriggerInstanceStatus{},
681},
682setVars: func() {
683kubeapi.GetResourceMeta = func(client *kubernetes.Clientset, kind string, version string) *kubeapi.ResourceMeta {
684return &kubeapi.ResourceMeta{
685Name: "Pod",
686Plural: "pods",
687Path: "api",
688Namespaced: true,
689GroupVersion: "v1",
690}
691}
692env.TimeoutSideEffectParentPublicationWaiting = 2 * time.Second
693kubeapi.GetResource = func(ctx context.Context, resourceMeta *kubeapi.ResourceMeta, resourceName string, namespaceName string) ([]byte, error) {
694return []byte("{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"name\":\"pod-se-plus-mutation\",\"resourceVersion\": \"verse1\",\"uid\": \"31ce6848-bee4-40fb-be85-7f796dd11685\",\"namespace\":\"kate-kblt-dev\",\"labels\":{\"sidecar.istio.io/inject\":\"false\",\"side-effect-plus-mutation\":\"enabled\"},\"annotations\":{\"kblt.annot-ns/merge\":\"enabled\", \"kblt.sideEffect.resource/tag\": \"5\"}},\"spec\":{\"hostNetwork\":false,\"serviceAccount\":\"default\",\"serviceAccountName\":\"default\",\"restartPolicy\":\"Never\",\"automountServiceAccountToken\":false,\"securityContext\":{\"runAsNonRoot\":true,\"seccompProfile\":{\"type\":\"RuntimeDefault\"}},\"containers\":[{\"image\":\"dzo.sw.sbc.space/sbt_dev/ci90000221_fedmesh_dev/federation-demo@sha256:548cc416011c86bb1e2c6d06289aab0771a0f749c044656deaac5fc86d891fea\",\"name\":\"test\",\"imagePullPolicy\":\"Always\",\"securityContext\":{\"allowPrivilegeEscalation\":false,\"capabilities\":{\"drop\":[\"ALL\"]},\"runAsNonRoot\":true,\"privileged\":false}}]}}"), errors.New("")
695}
696},
697trigger: v1alpha1.Trigger{
698ObjectMeta: metav1.ObjectMeta{Name: "TriggerName", Namespace: "TriggerNamespace"},
699Spec: v1alpha1.TriggerSpec{
700SideEffectConfigs: []v1alpha1.SideEffectConfig{{
701Name: "SideEffConfigName",
702TemplateRefs: []string{"templNs/templName"},
703}}},
704},
705template: v1alpha1.Template{
706ObjectMeta: metav1.ObjectMeta{
707Namespace: "templNs",
708Name: "templName",
709},
710Spec: v1alpha1.TemplateSpec{
711Data: "---\nkind: TriggerInstance\napiVersion: kubelatte.synapse.sber/v1alpha1\nmetadata:\n name: trigger-instance-se-plus-mutation\n annotations:\n kblt/side-effect-plus-mutation: enabled\nspec:\n data: data\n",
712},
713},
714args: args{
715info: &semodles.SE{
716SeMode: int32(semodles.Recreation),
717Configs: semodles.Configs{
718Kind: "Pod",
719ApiVersion: "v1",
720Metadata: semodles.Metadata{
721Namespace: "kblt-dev",
722Name: "podik :D ! XD",
723},
724ParentTag: 5,
725TemplateRefs: []string{"templNs/templName"},
726TriggerRef: semodles.TriggerRef{
727Name: "TriggerName",
728Namespace: "TriggerNamespace",
729SideEffectConfig: "SideEffConfigName",
730},
731},
732}},
733},
734}
735for _, tt := range tests {
736t.Run(tt.name, func(t *testing.T) {
737tt.setVars()
738
739triggerInstanceClient := mocks2.NewTriggerInstanceInterface(t)
740triggerInstanceClient.On("Get", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errors2.NewNotFound(schema.GroupResource{}, "ti")).Maybe()
741triggerInstanceClient.On("Create", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil).Maybe()
742triggerInstanceClient.On("Delete", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe()
743triggerInstanceClient.On("List", mock.Anything, mock.Anything, mock.Anything).Return(&v1alpha1.TriggerInstanceList{
744Items: []v1alpha1.TriggerInstance{tt.ti},
745}, nil).Maybe()
746
747kbtlKubeClientMock := mocks2.NewV1Alpha1Interface(t)
748kbtlKubeClientMock.On("TriggerInstance").Return(triggerInstanceClient).Maybe()
749
750storage.Storage = &storage.StorageController{}
751storage.Storage.Start(false, false)
752storage.Storage.UpdateTemplate(&tt.template)
753storage.Storage.UpdateTrigger(&tt.trigger)
754
755c := Executor{kbtlKubeClient: kbtlKubeClientMock, mu: &sync.Mutex{}}
756c.act = &c
757c.ApplySideEffectRecreate(context.Background(), tt.args.info)
758})
759}
760}
761
762func TestExecutor_waitForUpdatedParentPublication(t *testing.T) {
763type fields struct {
764kubeCli *kubernetes.Clientset
765kbtlKubeClient clientset.V1Alpha1Interface
766mu *sync.Mutex
767}
768type args struct {
769ctx context.Context
770oldParentHash string
771info *semodles.SE
772}
773tests := []struct {
774name string
775fields fields
776args args
777setup func()
778want []byte
779wantErr bool
780}{
781{
782name: "parent NotYetUpdated",
783args: args{
784ctx: context.Background(),
785oldParentHash: "hash",
786info: &semodles.SE{
787Configs: semodles.Configs{
788ParentTag: 123,
789},
790SeMode: int32(semodles.Recreation),
791},
792},
793setup: func() {
794env.TimeoutSideEffectParentPublicationWaiting = 2 * time.Second
795kubeapi.GetResourceMeta = func(client *kubernetes.Clientset, kind string, version string) *kubeapi.ResourceMeta {
796return &kubeapi.ResourceMeta{Name: "sth"}
797}
798kubeapi.GetResource = func(ctx context.Context, resourceMeta *kubeapi.ResourceMeta, resourceName string, namespace string) ([]byte, error) {
799return []byte("{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"name\":\"pod-se-plus-mutation\",\"resourceVersion\": \"verse1\",\"uid\": \"31ce6848-bee4-40fb-be85-7f796dd11685\",\"namespace\":\"kate-kblt-dev\",\"labels\":{\"sidecar.istio.io/inject\":\"false\",\"side-effect-plus-mutation\":\"enabled\"},\"annotations\":{\"kblt.annot-ns/merge\":\"enabled\", \"sideEffect.resource/tag\": \"5\"}},\"spec\":{\"hostNetwork\":false,\"serviceAccount\":\"default\",\"serviceAccountName\":\"default\",\"restartPolicy\":\"Never\",\"automountServiceAccountToken\":false,\"securityContext\":{\"runAsNonRoot\":true,\"seccompProfile\":{\"type\":\"RuntimeDefault\"}},\"containers\":[{\"image\":\"dzo.sw.sbc.space/sbt_dev/ci90000221_fedmesh_dev/federation-demo@sha256:548cc416011c86bb1e2c6d06289aab0771a0f749c044656deaac5fc86d891fea\",\"name\":\"test\",\"imagePullPolicy\":\"Always\",\"securityContext\":{\"allowPrivilegeEscalation\":false,\"capabilities\":{\"drop\":[\"ALL\"]},\"runAsNonRoot\":true,\"privileged\":false}}]}}"), nil
800}
801},
802want: nil,
803wantErr: true,
804},
805{
806name: "parent Obtained",
807args: args{
808ctx: context.Background(),
809oldParentHash: "hash",
810info: &semodles.SE{
811Configs: semodles.Configs{
812ParentTag: 0,
813},
814SeMode: int32(semodles.Recreation),
815},
816},
817setup: func() {
818env.TimeoutSideEffectParentPublicationWaiting = 2 * time.Second
819kubeapi.GetResourceMeta = func(client *kubernetes.Clientset, kind string, version string) *kubeapi.ResourceMeta {
820return &kubeapi.ResourceMeta{Name: "sth"}
821}
822kubeapi.GetResource = func(ctx context.Context, resourceMeta *kubeapi.ResourceMeta, resourceName string, namespace string) ([]byte, error) {
823return []byte("{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"name\":\"pod-se-plus-mutation\",\"resourceVersion\": \"verse1\",\"uid\": \"31ce6848-bee4-40fb-be85-7f796dd11685\",\"namespace\":\"kate-kblt-dev\",\"labels\":{\"sidecar.istio.io/inject\":\"false\",\"side-effect-plus-mutation\":\"enabled\"},\"annotations\":{\"kblt.annot-ns/merge\":\"enabled\", \"sideEffect.resource/tag\": \"5\"}},\"spec\":{\"hostNetwork\":false,\"serviceAccount\":\"default\",\"serviceAccountName\":\"default\",\"restartPolicy\":\"Never\",\"automountServiceAccountToken\":false,\"securityContext\":{\"runAsNonRoot\":true,\"seccompProfile\":{\"type\":\"RuntimeDefault\"}},\"containers\":[{\"image\":\"dzo.sw.sbc.space/sbt_dev/ci90000221_fedmesh_dev/federation-demo@sha256:548cc416011c86bb1e2c6d06289aab0771a0f749c044656deaac5fc86d891fea\",\"name\":\"test\",\"imagePullPolicy\":\"Always\",\"securityContext\":{\"allowPrivilegeEscalation\":false,\"capabilities\":{\"drop\":[\"ALL\"]},\"runAsNonRoot\":true,\"privileged\":false}}]}}"), nil
824}
825},
826want: nil,
827wantErr: true,
828},
829{
830name: "parent PublishedHashChanged",
831args: args{
832ctx: context.Background(),
833oldParentHash: "хеш",
834info: &semodles.SE{
835Configs: semodles.Configs{
836ParentTag: 5,
837},
838SeMode: int32(semodles.Recreation),
839},
840},
841setup: func() {
842env.TimeoutSideEffectParentPublicationWaiting = 2 * time.Second
843kubeapi.GetResourceMeta = func(client *kubernetes.Clientset, kind string, version string) *kubeapi.ResourceMeta {
844return &kubeapi.ResourceMeta{Name: "sth"}
845}
846kubeapi.GetResource = func(ctx context.Context, resourceMeta *kubeapi.ResourceMeta, resourceName string, namespace string) ([]byte, error) {
847return []byte("{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"name\":\"pod-se-plus-mutation\",\"resourceVersion\": \"verse1\",\"uid\": \"31ce6848-bee4-40fb-be85-7f796dd11685\",\"namespace\":\"kate-kblt-dev\",\"labels\":{\"sidecar.istio.io/inject\":\"false\",\"side-effect-plus-mutation\":\"enabled\"},\"annotations\":{\"kblt.annot-ns/merge\":\"enabled\", \"sideEffect.resource/tag\": \"5\"}},\"spec\":{\"hostNetwork\":false,\"serviceAccount\":\"default\",\"serviceAccountName\":\"default\",\"restartPolicy\":\"Never\",\"automountServiceAccountToken\":false,\"securityContext\":{\"runAsNonRoot\":true,\"seccompProfile\":{\"type\":\"RuntimeDefault\"}},\"containers\":[{\"image\":\"dzo.sw.sbc.space/sbt_dev/ci90000221_fedmesh_dev/federation-demo@sha256:548cc416011c86bb1e2c6d06289aab0771a0f749c044656deaac5fc86d891fea\",\"name\":\"test\",\"imagePullPolicy\":\"Always\",\"securityContext\":{\"allowPrivilegeEscalation\":false,\"capabilities\":{\"drop\":[\"ALL\"]},\"runAsNonRoot\":true,\"privileged\":false}}]}}"), nil
848}
849},
850wantErr: false,
851},
852{
853name: "parent PublishedHashNotChanged",
854args: args{
855ctx: context.Background(),
856oldParentHash: "9079847633250741385",
857info: &semodles.SE{
858Configs: semodles.Configs{
859ParentTag: 5,
860},
861SeMode: int32(semodles.Recreation),
862},
863},
864setup: func() {
865env.TimeoutSideEffectParentPublicationWaiting = 2 * time.Second
866kubeapi.GetKBLTClient = func() (*clientset.V1Alpha1Client, error) {
867return nil, nil
868}
869kubeapi.GetResourceMeta = func(client *kubernetes.Clientset, kind string, version string) *kubeapi.ResourceMeta {
870return &kubeapi.ResourceMeta{Name: "sth"}
871}
872kubeapi.GetResource = func(ctx context.Context, resourceMeta *kubeapi.ResourceMeta, resourceName string, namespace string) ([]byte, error) {
873return []byte("{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"name\":\"pod-se-plus-mutation\",\"resourceVersion\": \"verse1\",\"uid\": \"31ce6848-bee4-40fb-be85-7f796dd11685\",\"namespace\":\"kate-kblt-dev\",\"labels\":{\"sidecar.istio.io/inject\":\"false\",\"side-effect-plus-mutation\":\"enabled\"},\"annotations\":{\"kblt.annot-ns/merge\":\"enabled\", \"sideEffect.resource/tag\": \"5\"}},\"spec\":{\"hostNetwork\":false,\"serviceAccount\":\"default\",\"serviceAccountName\":\"default\",\"restartPolicy\":\"Never\",\"automountServiceAccountToken\":false,\"securityContext\":{\"runAsNonRoot\":true,\"seccompProfile\":{\"type\":\"RuntimeDefault\"}},\"containers\":[{\"image\":\"dzo.sw.sbc.space/sbt_dev/ci90000221_fedmesh_dev/federation-demo@sha256:548cc416011c86bb1e2c6d06289aab0771a0f749c044656deaac5fc86d891fea\",\"name\":\"test\",\"imagePullPolicy\":\"Always\",\"securityContext\":{\"allowPrivilegeEscalation\":false,\"capabilities\":{\"drop\":[\"ALL\"]},\"runAsNonRoot\":true,\"privileged\":false}}]}}"), nil
874}
875},
876wantErr: false,
877},
878}
879for _, tt := range tests {
880t.Run(tt.name, func(t *testing.T) {
881tt.setup()
882e := &Executor{}
883e.act = e
884_, err := e.waitForUpdatedParentPublication(tt.args.ctx, tt.args.oldParentHash, tt.args.info)
885if (err != nil) != tt.wantErr {
886t.Errorf("waitForUpdatedParentPublication() error = %v, wantErr %v", err, tt.wantErr)
887return
888}
889})
890}
891}
892
893func TestExecutor_deleteTIs(t *testing.T) {
894t.Run("ok", func(t *testing.T) {
895kbltKubeClientMock := mocks2.NewV1Alpha1Interface(t)
896timock := mocks2.NewTriggerInstanceInterface(t)
897timock.On("Delete", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
898kbltKubeClientMock.On("TriggerInstance").Return(timock)
899e := &Executor{
900kbtlKubeClient: kbltKubeClientMock,
901}
902e.deleteTIs(context.Background(), []*v1alpha1.TriggerInstance{{}}, "")
903})
904
905t.Run("error", func(t *testing.T) {
906kbltKubeClientMock := mocks2.NewV1Alpha1Interface(t)
907timock := mocks2.NewTriggerInstanceInterface(t)
908timock.On("Delete", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(errors.New("err"))
909kbltKubeClientMock.On("TriggerInstance").Return(timock)
910e := &Executor{
911kbtlKubeClient: kbltKubeClientMock,
912}
913e.deleteTIs(context.Background(), []*v1alpha1.TriggerInstance{{}}, "")
914})
915}
916