kubelatte-ce
Форк от sbertech/kubelatte-ce
615 строк · 28.6 Кб
1package mutation
2
3import (
4"context"
5"fmt"
6"github.com/InVisionApp/conjungo"
7"github.com/Masterminds/sprig/v3"
8"github.com/wI2L/jsondiff"
9"gitverse.ru/synapse/kubelatte/pkg/api/common"
10"gitverse.ru/synapse/kubelatte/pkg/api/v1alpha1"
11"gitverse.ru/synapse/kubelatte/pkg/observability/logger/lib"
12"gitverse.ru/synapse/kubelatte/pkg/storage"
13"gitverse.ru/synapse/kubelatte/pkg/util"
14"gitverse.ru/synapse/kubelatte/pkg/util/env"
15baseMatch "gitverse.ru/synapse/kubelatte/pkg/util/match"
16"gitverse.ru/synapse/kubelatte/pkg/util/templates"
17"go.uber.org/zap"
18"html/template"
19metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
20"k8s.io/apimachinery/pkg/util/yaml"
21"log"
22"os"
23"reflect"
24"strings"
25"testing"
26)
27
28func TestMutateController_CheckMatchSelector(t *testing.T) {
29type args struct {
30config *v1alpha1.MutationConfig
31obj ObjInfo
32}
33tests := []struct {
34name string
35args args
36want bool
37}{
38{
39name: "wrong operator",
40args: args{
41config: &v1alpha1.MutationConfig{
42LabelSelector: metav1.LabelSelector{
43MatchExpressions: []metav1.LabelSelectorRequirement{{Key: "", Values: []string{}, Operator: "s0m3 wr0n9 0p3rat0r"}}},
44},
45obj: ObjInfo{
46labels: map[string]string{"str": "str"},
47},
48},
49want: false,
50},
51{
52name: "matching",
53args: args{
54obj: ObjInfo{
55Kind: "pod",
56name: "name",
57labels: map[string]string{"str": "str"},
58},
59config: &v1alpha1.MutationConfig{
60ObjectSelector: v1alpha1.ObjectSelector{Kind: "pod", Name: "name"},
61LabelSelector: metav1.LabelSelector{
62MatchExpressions: []metav1.LabelSelectorRequirement{{Key: "", Values: []string{}, Operator: "s0m3 wr0n9 0p3rat0r"}}},
63},
64},
65want: true,
66},
67}
68for _, tt := range tests {
69t.Run(tt.name, func(t *testing.T) {
70lib.ZapLogger = zap.NewNop()
71
72r := &MutRenderer{}
73if got := r.checkMatchSelector(context.Background(), tt.args.config, tt.args.obj); got != tt.want {
74t.Errorf("checkMatchSelector() = %v, want %v", got, tt.want)
75}
76})
77}
78}
79
80func TestMutateController_GetRenders(t *testing.T) {
81tests := []struct {
82name string
83obj map[string]interface{}
84trigger v1alpha1.Trigger
85template v1alpha1.Template
86want []util.RenderItem
87}{
88{
89name: "merge",
90obj: map[string]interface{}{
91"metadata": map[string]interface{}{
92"annotations": map[string]interface{}{
93"ns/annotK": "enabled",
94},
95"labels": map[string]interface{}{
96"labK": "labV",
97},
98},
99},
100trigger: v1alpha1.Trigger{
101TypeMeta: metav1.TypeMeta{},
102ObjectMeta: metav1.ObjectMeta{},
103Spec: v1alpha1.TriggerSpec{
104MutationConfigs: []v1alpha1.MutationConfig{{
105UpdateStrategy: "",
106AnnotationNamespace: "ns",
107AnnotationTrigger: "annotK",
108TemplateRefs: []string{"templNs/templName"},
109LabelSelector: metav1.LabelSelector{
110MatchLabels: nil,
111MatchExpressions: []metav1.LabelSelectorRequirement{
112{
113Key: "labK",
114Operator: "Exists",
115Values: nil,
116},
117},
118},
119}}},
120Status: v1alpha1.TriggerStatus{},
121},
122template: v1alpha1.Template{
123TypeMeta: metav1.TypeMeta{},
124ObjectMeta: metav1.ObjectMeta{
125Namespace: "templNs",
126Name: "templName",
127},
128Spec: v1alpha1.TemplateSpec{},
129Status: v1alpha1.TemplateStatus{},
130},
131want: []util.RenderItem{{
132Template: v1alpha1.Template{
133TypeMeta: metav1.TypeMeta{},
134ObjectMeta: metav1.ObjectMeta{
135Namespace: "templNs",
136Name: "templName",
137},
138Spec: v1alpha1.TemplateSpec{},
139Status: v1alpha1.TemplateStatus{},
140},
141Render: "",
142Action: "",
143},
144},
145},
146{
147name: "replace",
148obj: map[string]interface{}{
149"metadata": map[string]interface{}{
150"annotations": map[string]interface{}{
151"ns/annotK": "enabled",
152},
153"labels": map[string]interface{}{
154"labK": "labV",
155},
156},
157},
158trigger: v1alpha1.Trigger{
159TypeMeta: metav1.TypeMeta{},
160ObjectMeta: metav1.ObjectMeta{},
161Spec: v1alpha1.TriggerSpec{
162MutationConfigs: []v1alpha1.MutationConfig{{
163Name: "",
164UpdateStrategy: "replace",
165AnnotationNamespace: "ns",
166AnnotationTrigger: "annotK",
167TemplateRefs: []string{"templNs/templName"},
168LabelSelector: metav1.LabelSelector{
169MatchLabels: nil,
170MatchExpressions: []metav1.LabelSelectorRequirement{
171{
172Key: "labK",
173Operator: "Exists",
174Values: nil,
175},
176},
177},
178}}},
179Status: v1alpha1.TriggerStatus{},
180},
181template: v1alpha1.Template{
182TypeMeta: metav1.TypeMeta{},
183ObjectMeta: metav1.ObjectMeta{
184Namespace: "templNs",
185Name: "templName",
186},
187Spec: v1alpha1.TemplateSpec{},
188Status: v1alpha1.TemplateStatus{},
189},
190want: []util.RenderItem{{
191Template: v1alpha1.Template{
192TypeMeta: metav1.TypeMeta{},
193ObjectMeta: metav1.ObjectMeta{
194Namespace: "templNs",
195Name: "templName",
196},
197Spec: v1alpha1.TemplateSpec{},
198Status: v1alpha1.TemplateStatus{},
199},
200Render: "",
201Action: "replace",
202},
203},
204},
205}
206for _, tt := range tests {
207t.Run(tt.name, func(t *testing.T) {
208lib.ZapLogger = zap.NewNop()
209matcher := baseMatch.NewMatcher()
210renderer := NewMutRenderer(matcher, nil)
211r := Mutator{renderer}
212storage.Storage = &storage.StorageController{}
213storage.Storage.Start(false, false)
214storage.Storage.UpdateTrigger(&tt.trigger)
215storage.Storage.UpdateTemplate(&tt.template)
216
217if got := r.renderer.GetRenders(context.Background(), &common.ARFields{Object: tt.obj}); !reflect.DeepEqual(got, tt.want) {
218t.Errorf("getRenders() = %v, want %v", got, tt.want)
219}
220})
221}
222}
223
224func TestMutateController_Mutate(t *testing.T) {
225type args struct {
226obj map[string]interface{}
227raw []byte
228}
229tests := []struct {
230name string
231trigger v1alpha1.Trigger
232template v1alpha1.Template
233args args
234want []jsondiff.Operation
235}{
236{
237name: "ok",
238want: []jsondiff.Operation{
239{
240Value: nil,
241OldValue: "annotV",
242Type: "remove",
243From: "",
244Path: "/metadata/annotations/annotK",
245},
246{
247Value: "annotVal",
248OldValue: nil,
249Type: "add",
250From: "",
251Path: "/metadata/annotations/annotKey",
252},
253{
254Value: nil,
255OldValue: map[string]interface{}{"labK": "labV"},
256Type: "remove",
257From: "",
258Path: "/metadata/labels",
259},
260},
261args: args{
262obj: map[string]interface{}{
263"metadata": map[string]interface{}{
264"annotations": map[string]interface{}{
265"annotK": "annotV",
266},
267"labels": map[string]interface{}{
268"labK": "labV",
269},
270},
271},
272raw: []byte("{\n \"metadata\": {\n \"annotations\": {\n \"annotKey\": \"annotVal\"\n }\n }\n}"),
273},
274trigger: v1alpha1.Trigger{
275TypeMeta: metav1.TypeMeta{},
276ObjectMeta: metav1.ObjectMeta{},
277Spec: v1alpha1.TriggerSpec{
278MutationConfigs: []v1alpha1.MutationConfig{{
279Name: "",
280UpdateStrategy: "",
281TemplateRefs: []string{"templNs/templName"},
282LabelSelector: metav1.LabelSelector{
283MatchLabels: nil,
284MatchExpressions: []metav1.LabelSelectorRequirement{
285{
286Key: "labK",
287Operator: "Exists",
288Values: nil,
289},
290},
291},
292}}},
293Status: v1alpha1.TriggerStatus{},
294},
295template: v1alpha1.Template{
296TypeMeta: metav1.TypeMeta{},
297ObjectMeta: metav1.ObjectMeta{
298Namespace: "templNs",
299Name: "templName",
300},
301Spec: v1alpha1.TemplateSpec{},
302Status: v1alpha1.TemplateStatus{},
303},
304},
305{
306name: "ok2",
307args: args{
308obj: map[string]interface{}{
309"kind": "Pod",
310"metadata": map[string]interface{}{
311"annotations": map[string]interface{}{
312"ann_ns/ann_trig": "enabled",
313},
314},
315},
316raw: []byte("{\"spec\": {\"containers\": [{\"name\": \"cont1\",\"image\": \"noimage\"}]}}")},
317trigger: v1alpha1.Trigger{
318Spec: v1alpha1.TriggerSpec{
319MutationConfigs: []v1alpha1.MutationConfig{
320{
321AnnotationNamespace: "ann_ns",
322AnnotationTrigger: "ann_trig",
323Name: "mutation cfg",
324UpdateStrategy: string(MergeStrategy),
325Containers: []string{"some-ns/some-templ/container_mutated"}},
326},
327},
328},
329
330template: v1alpha1.Template{
331ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "some-templ"},
332Spec: v1alpha1.TemplateSpec{Data: `spec:
333containers:
334- name: container_mutated
335image: imagemut`,
336},
337},
338want: []jsondiff.Operation{
339{Type: "remove", Path: "/kind", OldValue: "Pod"},
340{Type: "remove", Path: "/metadata/annotations", OldValue: map[string]interface{}{"ann_ns/ann_trig": "enabled"}},
341{Value: map[string]interface{}{env.ServiceAnnotationPrefix + "mutation.resource": "true"}, Type: "add", Path: "/metadata/labels"},
342{Value: map[string]interface{}{
343"containers": []interface{}{
344map[string]interface{}{"image": "noimage", "name": "cont1"},
345map[string]interface{}{"image": "imagemut", "name": "container_mutated"},
346},
347}, Type: "add", Path: "/spec"},
348},
349},
350{
351name: "location",
352args: args{obj: map[string]interface{}{
353"Kind": "Deployment",
354"metadata": map[string]interface{}{
355"annotations": map[string]interface{}{
356"ann_ns/ann_trig": "enabled",
357},
358},
359},
360raw: []byte("{\n \"apiVersion\": \"apps/v1\",\n \"Kind\": \"Deployment\",\n \"metadata\": {\n \"name\": \"scope-volume-deployment\",\n \"namespace\": \"kblt-dev\",\n \"labels\": {\n \"kblt.dev\": \"test\",\n \"kblt.testname\": \"scope_volume_aft\",\n \"app\": \"to-test-latte\"\n },\n \"annotations\": {\n \"kblt.annotations/merge\": \"enabled\"\n }\n },\n \"spec\": {\n \"strategy\": {\n \"type\": \"Recreate\"\n },\n \"replicas\": 1,\n \"selector\": {\n \"matchLabels\": {\n \"app\": \"to-test-latte\"\n }\n },\n \"template\": {\n \"metadata\": {\n \"labels\": {\n \"kblt.dev\": \"test\",\n \"kblt.testname\": \"scope_volume_aft\",\n \"app\": \"to-test-latte\",\n \"find-pod\": \"scope-volume-aft\",\n \"sidecar.istio.io/inject\": \"false\"\n },\n \"annotations\": {\n \"kblt.annotations/merge\": \"enabled\"\n }\n },\n \"spec\": {\n \"securityContext\": {\n \"seccompProfile\": {\n \"type\": \"RuntimeDefault\"\n },\n \"runAsNonRoot\": true\n },\n \"containers\": [\n {\n \"name\": \"to-test-latte-2\",\n \"image\": \"dzo.sw.sbc.space/sbt/ci90000221_fedmesh/federation-demo@sha256:548cc416011c86bb1e2c6d06289aab0771a0f749c044656deaac5fc86d891fea\",\n \"securityContext\": {\n \"capabilities\": {\n \"drop\": [\n \"ALL\"\n ]\n },\n \"allowPrivilegeEscalation\": false\n },\n \"resources\": {\n \"limits\": {\n \"cpu\": \"100m\",\n \"memory\": \"100Mi\"\n },\n \"requests\": {\n \"cpu\": \"100m\",\n \"memory\": \"100Mi\"\n }\n }\n },\n {\n \"name\": \"to-test-latte-1\",\n \"image\": \"dzo.sw.sbc.space/sbt/ci90000221_fedmesh/federation-demo@sha256:548cc416011c86bb1e2c6d06289aab0771a0f749c044656deaac5fc86d891fea\",\n \"securityContext\": {\n \"capabilities\": {\n \"drop\": [\n \"ALL\"\n ]\n },\n \"allowPrivilegeEscalation\": false\n },\n \"resources\": {\n \"limits\": {\n \"cpu\": \"100m\",\n \"memory\": \"100Mi\"\n },\n \"requests\": {\n \"cpu\": \"100m\",\n \"memory\": \"100Mi\"\n }\n }\n }\n ],\n \"volumes\": [\n {\n \"name\": \"test-volume-1\",\n \"emptyDir\": {\n \"sizeLimit\": \"49Mi\"\n }\n }\n ]\n }\n }\n }\n}")},
361trigger: v1alpha1.Trigger{
362Spec: v1alpha1.TriggerSpec{
363MutationConfigs: []v1alpha1.MutationConfig{
364{
365AnnotationNamespace: "ann_ns",
366AnnotationTrigger: "ann_trig",
367Name: "mutation cfg",
368UpdateStrategy: string(ReplaceStrategy),
369TemplateRefs: []string{"some-ns/some-templ"}},
370},
371},
372},
373
374template: v1alpha1.Template{
375ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "some-templ"},
376Spec: v1alpha1.TemplateSpec{Data: `
377
378name: container_mutated
379image: imagemut
380`,
381Location: "spec.template.spec.containers[@.name==`to-test-latte-2`]",
382},
383},
384want: []jsondiff.Operation{
385{
386Value: "apps/v1",
387Path: "/apiVersion",
388Type: "add",
389},
390{
391Type: "remove",
392Path: "/metadata/annotations/ann_ns~1ann_trig",
393OldValue: "enabled",
394},
395{
396Value: "enabled",
397Type: "add",
398Path: "/metadata/annotations/kblt.annotations~1merge",
399},
400{
401Value: map[string]interface{}{"app": "to-test-latte", "kblt.dev": "test", env.ServiceAnnotationPrefix + "mutation.resource": "true", "kblt.testname": "scope_volume_aft"},
402Type: "add",
403Path: "/metadata/labels",
404},
405{
406Value: "scope-volume-deployment",
407Type: "add",
408Path: "/metadata/name",
409},
410{
411Value: "kblt-dev",
412OldValue: nil,
413Type: "add",
414From: "",
415Path: "/metadata/namespace",
416},
417{
418Value: map[string]interface{}{"replicas": float64(1),
419"selector": map[string]interface{}{"matchLabels": map[string]interface{}{"app": "to-test-latte"}},
420"strategy": map[string]interface{}{"type": "Recreate"},
421"template": map[string]interface{}{"metadata": map[string]interface{}{"annotations": map[string]interface{}{"kblt.annotations/merge": "enabled"},
422"labels": map[string]interface{}{"app": "to-test-latte", "find-pod": "scope-volume-aft", "kblt.dev": "test", "kblt.testname": "scope_volume_aft", "sidecar.istio.io/inject": "false"}},
423"spec": map[string]interface{}{"containers": []interface{}{map[string]interface{}{"image": "imagemut", "name": "container_mutated"}, map[string]interface{}{"image": "dzo.sw.sbc.space/sbt/ci90000221_fedmesh/federation-demo@sha256:548cc416011c86bb1e2c6d06289aab0771a0f749c044656deaac5fc86d891fea", "name": "to-test-latte-1", "resources": map[string]interface{}{"limits": map[string]interface{}{"cpu": "100m", "memory": "100Mi"}, "requests": map[string]interface{}{"cpu": "100m", "memory": "100Mi"}}, "securityContext": map[string]interface{}{"allowPrivilegeEscalation": false, "capabilities": map[string]interface{}{"drop": []interface{}{"ALL"}}}}},
424"securityContext": map[string]interface{}{"runAsNonRoot": true, "seccompProfile": map[string]interface{}{"type": "RuntimeDefault"}}, "volumes": []interface{}{map[string]interface{}{"emptyDir": map[string]interface{}{"sizeLimit": "49Mi"}, "name": "test-volume-1"}}},
425}},
426Type: "add",
427Path: "/spec",
428},
429},
430},
431}
432for _, tt := range tests {
433t.Run(tt.name, func(t *testing.T) {
434lib.ZapLogger = zap.NewNop()
435matcher := baseMatch.NewMatcher()
436renderer := NewMutRenderer(matcher, nil)
437r := NewMutator(renderer)
438storage.Storage = &storage.StorageController{}
439storage.Storage.Start(false, false)
440storage.Storage.UpdateTrigger(&tt.trigger)
441storage.Storage.UpdateTemplate(&tt.template)
442
443if got, _ := r.ApplyMutation(context.Background(), &common.ARFields{Object: tt.args.obj}, tt.args.raw); !reflect.DeepEqual(got, tt.want) {
444t.Errorf("ApplyMutation() = %v, want %v\n", got, tt.want)
445for i := 0; i < len(got); i++ {
446fmt.Printf("%v: result: %+v\n", i, got[i])
447fmt.Printf("%v: want : %+v\n", i, tt.want[i])
448}
449}
450})
451}
452}
453
454func TestMergeFunc(t *testing.T) {
455ym1 := "containers: \n - name: test\n image: aaaaaa\n testdt:\n - asda\n - adad\n - cvbcvb\n - name: test1\n image: bbbbbb\n - name: test2\n image: cccccc "
456ym2 := "containers: \n - name: test\n image: ssssss\n testdt:\n - xxx\n - yyy\n - zzz\n - name: test2\n image: zzzzzz "
457var obj1 map[string]interface{}
458var obj2 map[string]interface{}
459yaml.Unmarshal([]byte(ym1), &obj1)
460yaml.Unmarshal([]byte(ym2), &obj2)
461opts := conjungo.NewOptions()
462opts.SetKindMergeFunc(
463reflect.Slice,
464
465func(t, s reflect.Value, o *conjungo.Options) (reflect.Value, error) {
466aT, _ := t.Interface().([]interface{})
467aS, _ := s.Interface().([]interface{})
468
469aT = util.MergeSlice(aT, aS)
470
471return reflect.ValueOf(aT), nil
472},
473)
474opts.Overwrite = false
475err := conjungo.Merge(&obj1, obj2, opts)
476if err != nil {
477fmt.Printf("%s", err)
478}
479fmt.Printf("Data %v\n", obj1)
480}
481
482func TestRangeTemplate(t *testing.T) {
483data := "spec:\n template:\n spec:\n containers:\n {{% range .spec.template.spec.containers %}}\n - name: {{% .name %}}\n securityContext:\n privileged: false\n runAsUser: 10000\n runAsGroup: 5000\n readOnlyRootFilesystem: true\n allowPrivilegeEscalation: false\n capabilities:\n drop:\n - ALL \n {{% end %}}"
484templateEngine := template.New("common").
485Delims("{{%", "%}}").
486Funcs(template.FuncMap{
487"fromYaml": templates.FromYAML,
488}).
489Funcs(sprig.TxtFuncMap())
490temp, err := templateEngine.New("test").Parse(data)
491if err != nil {
492log.Fatalf("Failed parse %s", err)
493}
494
495var inputObj interface{}
496input := "apiVersion: apps/v1\nKind: Deployment\nmetadata:\n name: test-igeg\n namespace: synapse-metrics-system\n annotations:\n kblt.synapse/deploymentigeg: enabled\n kblt.synapse/deployment-all: enabled\n labels:\n secman-injector: enabled\n user-label: 'true'\nspec:\n replicas: 1\n selector:\n matchLabels:\n app: egw-syn-metrics-synapse-metrics-system\n istio: egw-syn-metrics-synapse-metrics-system\n template:\n metadata:\n labels:\n app: egw-syn-metrics-synapse-metrics-system\n istio: egw-syn-metrics-synapse-metrics-system\n annotations:\n openshift.io/scc: restricted\n sidecar.istio.io/inject: 'false'\n spec:\n volumes:\n - configMap:\n defaultMode: 256\n name: istio-basic\n optional: true\n name: config-volume\n - name: istiod-ca-cert\n configMap:\n name: istio-ca-root-cert\n defaultMode: 256\n - name: podinfo\n downwardAPI:\n items:\n - path: labels\n fieldRef:\n apiVersion: v1\n fieldPath: metadata.labels\n - path: annotations\n fieldRef:\n apiVersion: v1\n fieldPath: metadata.annotations\n defaultMode: 256\n - name: istio-envoy\n emptyDir: {}\n - name: istio-data\n emptyDir: {}\n - name: istio-token\n projected:\n sources:\n - serviceAccountToken:\n audience: istio-ca\n expirationSeconds: 43200\n path: istio-token\n defaultMode: 256\n containers:\n - name: istio-proxy\n image: image\n args:\n - proxy\n - router\n - '--domain'\n - $(POD_NAMESPACE).svc.cluster.local\n - '--proxyLogLevel=warning'\n - '--proxyComponentLogLevel=misc:error'\n - '--log_output_level=default:info'\n - '--serviceCluster'\n - $(POD_NAMESPACE)\n - '--trust-domain=cluster.local'\n ports:\n - name: status-port\n containerPort: 15021\n protocol: TCP\n - name: https-kubeapi\n containerPort: 4443\n protocol: TCP\n env:\n - name: JWT_POLICY\n value: first-party-jwt\n - name: TRUST_DOMAIN\n value: cluster.local\n - name: ISTIO_META_UNPRIVILEGED_POD\n value: 'true'\n - name: PILOT_CERT_PROVIDER\n value: istiod\n - name: CA_ADDR\n value: blabla.ci00000-cp.svc:15012\n - name: NODE_NAME\n valueFrom:\n fieldRef:\n apiVersion: v1\n fieldPath: spec.nodeName\n - name: POD_NAME\n valueFrom:\n fieldRef:\n apiVersion: v1\n fieldPath: metadata.name\n - name: POD_NAMESPACE\n valueFrom:\n fieldRef:\n apiVersion: v1\n fieldPath: metadata.namespace\n - name: INSTANCE_IP\n valueFrom:\n fieldRef:\n apiVersion: v1\n fieldPath: status.podIP\n - name: HOST_IP\n valueFrom:\n fieldRef:\n apiVersion: v1\n fieldPath: status.hostIP\n - name: SERVICE_ACCOUNT\n valueFrom:\n fieldRef:\n apiVersion: v1\n fieldPath: spec.serviceAccountName\n - name: CANONICAL_SERVICE\n valueFrom:\n fieldRef:\n apiVersion: v1\n fieldPath: metadata.labels['service.istio.io/canonical-name']\n - name: CANONICAL_REVISION\n valueFrom:\n fieldRef:\n apiVersion: v1\n fieldPath: metadata.labels['service.istio.io/canonical-revision']\n - name: ISTIO_META_WORKLOAD_NAME\n value: egressgateway-synapse-metrics\n - name: ISTIO_META_OWNER\n value: >-\n kubernetes://apis/apps/v1/namespaces/synapse-metrics-system/deployments/egw-syn-metrics-synapse-metrics-system\n - name: ISTIO_META_MESH_ID\n value: cluster.local\n - name: ISTIO_META_ROUTER_MODE\n value: sni-dnat\n - name: ISTIO_META_CLUSTER_ID\n value: Kubernetes\n resources:\n limits:\n cpu: 300m\n ephemeral-storage: 500Mi\n memory: 500Mi\n requests:\n cpu: 300m\n ephemeral-storage: 500Mi\n memory: 500Mi\n volumeMounts:\n - mountPath: /etc/istio/config\n name: config-volume\n - name: istio-envoy\n mountPath: /etc/istio/proxy\n - name: istiod-ca-cert\n mountPath: /var/run/secrets/istio\n - name: podinfo\n mountPath: /etc/istio/pod\n - name: istio-token\n readOnly: true\n mountPath: /var/run/secrets/tokens\n - name: istio-data\n mountPath: /var/lib/istio/data\n readinessProbe:\n httpGet:\n path: /healthz/ready\n port: 15021\n scheme: HTTP\n initialDelaySeconds: 1\n timeoutSeconds: 1\n periodSeconds: 2\n successThreshold: 1\n failureThreshold: 30\n terminationMessagePath: /dev/termination-log\n terminationMessagePolicy: File\n imagePullPolicy: Always\n securityContext:\n readOnlyRootFilesystem: true\n restartPolicy: Always\n terminationGracePeriodSeconds: 30\n dnsPolicy: ClusterFirst\n affinity:\n nodeAffinity:\n requiredDuringSchedulingIgnoredDuringExecution:\n nodeSelectorTerms:\n - matchExpressions:\n - key: kubernetes.io/arch\n operator: In\n values:\n - amd64\n - ppc64le\n - s390x\n preferredDuringSchedulingIgnoredDuringExecution:\n - weight: 2\n preference:\n matchExpressions:\n - key: kubernetes.io/arch\n operator: In\n values:\n - amd64\n - weight: 2\n preference:\n matchExpressions:\n - key: kubernetes.io/arch\n operator: In\n values:\n - ppc64le\n - weight: 2\n preference:\n matchExpressions:\n - key: kubernetes.io/arch\n operator: In\n values:\n - s390x\n schedulerName: default-scheduler\n strategy:\n type: RollingUpdate\n rollingUpdate:\n maxUnavailable: 25%\n maxSurge: 100%\n revisionHistoryLimit: 10\n progressDeadlineSeconds: 600"
497err = yaml.Unmarshal([]byte(input), &inputObj)
498if err != nil {
499log.Fatalf("Failed Unmarshal %s", err)
500}
501
502var tempBuffer strings.Builder
503err = temp.Execute(&tempBuffer, inputObj)
504if err != nil {
505log.Fatalf("Failed Execute %s", err)
506}
507
508log.Printf("%s", tempBuffer.String())
509}
510
511func TestGetSelector(t *testing.T) {
512os.Setenv("CONFIGS_PATH", "./configs")
513os.Setenv("LOGS_PATH", "./logs")
514os.Setenv("TMPDIR", "./logs")
515os.Setenv("KBLT_PORT_MAIN", "9998")
516os.Setenv("KBLT_PORT_LOG", "9999")
517os.Setenv("KBLT_ENABLED_TRIGGER_PREFIX", "true")
518
519//noexception
520getSelectorKey("simple-key", []string{"value"})
521//exception
522os.Setenv("KBLT_PREFIX_EXCEPTION", "true")
523env.InitEnvWebhookServer()
524getSelectorKey("simple-key", []string{"value"})
525//istio
526os.Setenv("KBLT_PREFIX_EXCEPTION", "true")
527env.InitEnvWebhookServer()
528getSelectorKey("app", []string{"istiod"})
529}
530
531func TestGetNewEmtyObject(t *testing.T) {
532lib.ZapLogger = zap.NewNop()
533
534ctrl := Mutator{}
535obj := ctrl.getNewObject(context.Background(), util.RenderItem{}, nil)
536
537if obj != nil {
538t.Errorf("should be nil object")
539}
540}
541
542func TestGetNewBrokenObject(t *testing.T) {
543lib.ZapLogger = zap.NewNop()
544
545ctrl := Mutator{}
546obj := ctrl.getNewObject(context.Background(), util.RenderItem{}, []byte("1"))
547
548if obj != nil {
549t.Errorf("should be nil object")
550}
551}
552
553func TestController_getNewObject(t *testing.T) {
554lib.ZapLogger = zap.NewNop()
555
556type args struct {
557templateRender util.RenderItem
558raw []byte
559}
560tests := []struct {
561name string
562args args
563wantMap bool
564}{
565{
566name: "templateRender.Template.Spec.Location != ''",
567args: args{
568templateRender: util.RenderItem{
569Template: v1alpha1.Template{
570Spec: v1alpha1.TemplateSpec{
571Location: "location",
572},
573},
574},
575raw: []byte("{\"key\": \"value\"}"),
576},
577wantMap: true,
578},
579{
580name: "error when Unmarshal",
581args: args{
582templateRender: util.RenderItem{
583Render: "1",
584},
585raw: []byte("{\"key\": \"value\"}"),
586},
587wantMap: false,
588},
589{
590name: "error when Unmarshal with location",
591args: args{
592templateRender: util.RenderItem{
593Render: "1",
594Template: v1alpha1.Template{
595Spec: v1alpha1.TemplateSpec{
596Location: "location",
597},
598},
599},
600raw: []byte("{\"key\": \"value\"}"),
601},
602wantMap: true,
603},
604}
605for _, tt := range tests {
606t.Run(tt.name, func(t *testing.T) {
607r := &Mutator{}
608got := r.getNewObject(context.Background(), tt.args.templateRender, tt.args.raw)
609
610if (got != nil) != tt.wantMap {
611t.Errorf("return map required")
612}
613})
614}
615}
616