From bdd089ecb9fdd6f89c2147e9c6eefdbad06831c0 Mon Sep 17 00:00:00 2001 From: Pavel Okhlopkov Date: Sat, 2 Nov 2024 20:31:19 +0300 Subject: [PATCH] comment jq test Signed-off-by: Pavel Okhlopkov --- go.mod | 4 +- go.sum | 4 +- .../binding_context/binding_context_test.go | 971 +++++++++--------- pkg/webhook/admission/response_test.go | 4 - pkg/webhook/conversion/handler.go | 3 +- 5 files changed, 493 insertions(+), 493 deletions(-) diff --git a/go.mod b/go.mod index 6895b418..fb8bdbc1 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,10 @@ module github.com/flant/shell-operator -go 1.23.1 +go 1.22.8 require ( github.com/deckhouse/deckhouse/pkg/log v0.0.0-20241102120041-7e44e3e22ab9 - github.com/flant/kube-client v0.0.0-20241102124645-b6172e39eac5 + github.com/flant/kube-client v0.0.0-20241102172840-e2b98bb238fa github.com/flant/libjq-go v1.6.3-0.20201126171326-c46a40ff22ee // branch: master github.com/go-chi/chi/v5 v5.1.0 github.com/go-openapi/spec v0.19.8 diff --git a/go.sum b/go.sum index 4a06a261..49cf0e65 100644 --- a/go.sum +++ b/go.sum @@ -33,8 +33,8 @@ github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCv github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/flant/go-openapi-validate v0.19.12-flant.0 h1:xk6kvc9fHKMgUdB6J7kbpbLR5vJOUzKAK8p3nrD7mDk= github.com/flant/go-openapi-validate v0.19.12-flant.0/go.mod h1:Rzou8hA/CBw8donlS6WNEUQupNvUZ0waH08tGe6kAQ4= -github.com/flant/kube-client v0.0.0-20241102124645-b6172e39eac5 h1:Aduf98C3FZrymtEw7rDeFreHWWZ+WB0PdDGYha7fH8E= -github.com/flant/kube-client v0.0.0-20241102124645-b6172e39eac5/go.mod h1:shVT4UC+QkiFiI81iCbVwo5SlqRONjaUaTB9CbApf5Q= +github.com/flant/kube-client v0.0.0-20241102172840-e2b98bb238fa h1:DJ1oCX4J1LDuHr5lI3okJAKIb/IuFLw4TY9xiVqA4zM= +github.com/flant/kube-client v0.0.0-20241102172840-e2b98bb238fa/go.mod h1:62vCzrIUzWMU4DB0Pn6/02Pu7uwKh5/mHGWy2NmxZAk= github.com/flant/libjq-go v1.6.3-0.20201126171326-c46a40ff22ee h1:evii83J+/6QGNvyf6tjQ/p27DPY9iftxIBb37ALJRTg= github.com/flant/libjq-go v1.6.3-0.20201126171326-c46a40ff22ee/go.mod h1:f+REaGl/+pZR97rbTcwHEka/MAipoQQ2Mc0iQUj4ak0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= diff --git a/pkg/hook/binding_context/binding_context_test.go b/pkg/hook/binding_context/binding_context_test.go index 034f6460..efba5588 100644 --- a/pkg/hook/binding_context/binding_context_test.go +++ b/pkg/hook/binding_context/binding_context_test.go @@ -1,486 +1,489 @@ package binding_context -import ( - "testing" - - . "github.com/onsi/gomega" - "github.com/stretchr/testify/assert" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - - . "github.com/flant/libjq-go" - . "github.com/flant/shell-operator/pkg/hook/types" - . "github.com/flant/shell-operator/pkg/kube_events_manager/types" -) - -func JqEqual(t *testing.T, input []byte, program string, expected string) { - //nolint:typecheck // Ignore false positive: undeclared name: `Jq`. - res, err := Jq().Program(program).Run(string(input)) - if assert.NoError(t, err) { - assert.Equal(t, expected, res, "jq: '%s', json was '%s'", program, string(input)) - } -} - -// Test conversion of BindingContext for v1, also test json marshal of v1 binding contexts. -func Test_ConvertBindingContextList_v1(t *testing.T) { - g := NewWithT(t) - - var bcList BindingContextList - var bcJson []byte - - tests := []struct { - name string - bc func() []BindingContext - fn func() - jqAssertions [][]string - }{ - { - "OnStartup binding", - func() []BindingContext { - bc := BindingContext{ - Binding: "onStartup", - } - bc.Metadata.BindingType = OnStartup - return []BindingContext{bc} - }, - func() { - assert.Equal(t, "onStartup", bcList[0]["binding"]) - }, - [][]string{ - {`.[0].binding`, `"onStartup"`}, - {`.[0] | length`, `1`}, - }, - }, - { - "kubernetes Event binding", - func() []BindingContext { - bc := BindingContext{ - Binding: "kubernetes", - Type: TypeEvent, - WatchEvent: WatchEventAdded, - Objects: []ObjectAndFilterResult{ - { - Object: &unstructured.Unstructured{ - Object: map[string]interface{}{ - "metadata": map[string]interface{}{ - "namespace": "default", - "name": "pod-qwe", - }, - "kind": "Pod", - }, - }, - }, - }, - } - bc.Metadata.BindingType = OnKubernetesEvent - return []BindingContext{bc} - }, - - func() { - assert.Len(t, bcList[0], 4) - assert.Equal(t, "kubernetes", bcList[0]["binding"]) - assert.Equal(t, TypeEvent, bcList[0]["type"]) - assert.Equal(t, "Added", bcList[0]["watchEvent"]) - assert.IsType(t, &unstructured.Unstructured{}, bcList[0]["object"]) - assert.Contains(t, bcList[0]["object"].(*unstructured.Unstructured).Object, "metadata") - }, - [][]string{ - // JSON dump should has only 4 fields: binding, type, watchEvent and object. - {`.[0] | length`, `4`}, - {`.[0].binding`, `"kubernetes"`}, - {`.[0].type`, `"Event"`}, - {`.[0].watchEvent`, `"Added"`}, - {`.[0].object.metadata.namespace`, `"default"`}, - {`.[0].object.metadata.name`, `"pod-qwe"`}, - }, - }, - { - "kubernetes Synchronization event", - func() []BindingContext { - bc := BindingContext{ - Binding: "kubernetes", - Type: TypeSynchronization, - Objects: []ObjectAndFilterResult{}, - } - bc.Metadata.BindingType = OnKubernetesEvent - - obj := ObjectAndFilterResult{ - Object: &unstructured.Unstructured{ - Object: map[string]interface{}{ - "metadata": map[string]interface{}{ - "namespace": "default", - "name": "pod-qwe", - }, - "kind": "Pod", - }, - }, - } - obj.Metadata.JqFilter = "" - bc.Objects = append(bc.Objects, obj) - - // object with jqfilter should have filterResult field - obj = ObjectAndFilterResult{ - Object: &unstructured.Unstructured{ - Object: map[string]interface{}{ - "metadata": map[string]interface{}{ - "namespace": "default", - "name": "deployment-test", - }, - "kind": "Deployment", - }, - }, - FilterResult: `{"labels":{"label-name":"label-value"}}`, - } - obj.Metadata.JqFilter = ".metadata.labels" - bc.Objects = append(bc.Objects, obj) - - // object with jqfilter and with empty result should have filterResult field - obj = ObjectAndFilterResult{ - Object: &unstructured.Unstructured{ - Object: map[string]interface{}{ - "metadata": map[string]interface{}{ - "namespace": "default", - "name": "deployment-2", - }, - "kind": "Deployment", - }, - }, - FilterResult: `""`, - } - obj.Metadata.JqFilter = ".metadata.labels" - bc.Objects = append(bc.Objects, obj) - - return []BindingContext{bc} - }, - func() { - assert.Len(t, bcList[0], 3) - assert.Len(t, bcList[0]["objects"], 3) - assert.Equal(t, TypeSynchronization, bcList[0]["type"]) - assert.Equal(t, "kubernetes", bcList[0]["binding"]) - assert.NotContains(t, bcList[0], "object") - assert.NotContains(t, bcList[0], "filterResult") - }, - [][]string{ - // JSON dump should contains n fields: binding, type and objects - {`.[0] | length`, `3`}, - {`.[0].binding`, `"kubernetes"`}, - {`.[0].type`, `"Synchronization"`}, - - {`.[0].objects[] | select(.object.metadata.name == "pod-qwe") | has("filterResult")`, `false`}, - {`.[0].objects[] | select(.object.metadata.name == "deployment-test") | has("filterResult")`, `true`}, - {`.[0].objects[] | select(.object.metadata.name == "deployment-test") | .filterResult.labels."label-name"`, `"label-value"`}, - {`.[0].objects[] | select(.object.metadata.name == "deployment-2") | has("filterResult")`, `true`}, - }, - }, - { - "binding context with group", - func() []BindingContext { - bcs := []BindingContext{} - - bc := BindingContext{ - Binding: "monitor_pods", - Type: TypeEvent, - WatchEvent: WatchEventAdded, - Objects: []ObjectAndFilterResult{}, - Snapshots: map[string][]ObjectAndFilterResult{}, - } - bc.Metadata.BindingType = OnKubernetesEvent - bc.Metadata.Group = "pods" - bc.Metadata.IncludeSnapshots = []string{"monitor_pods"} - - obj := ObjectAndFilterResult{ - Object: &unstructured.Unstructured{ - Object: map[string]interface{}{ - "metadata": map[string]interface{}{ - "namespace": "default", - "name": "pod-qwe", - }, - "kind": "Pod", - }, - }, - } - bc.Objects = append(bc.Objects, obj) - bc.Snapshots["monitor_pods"] = append(bc.Snapshots["monitor_pods"], obj) - bcs = append(bcs, bc) - - bc = BindingContext{ - Binding: "monitor_pods", - Type: TypeEvent, - WatchEvent: WatchEventAdded, - Objects: []ObjectAndFilterResult{}, - } - bc.Metadata.BindingType = OnKubernetesEvent - - obj = ObjectAndFilterResult{ - Object: &unstructured.Unstructured{ - Object: map[string]interface{}{ - "metadata": map[string]interface{}{ - "namespace": "default", - "name": "pod-qwe", - }, - "kind": "Pod", - }, - }, - } - bc.Objects = append(bc.Objects, obj) - - bcs = append(bcs, bc) - return bcs - }, - func() { - g.Expect(bcList[0]).Should(HaveKey("binding")) - g.Expect(bcList[0]).Should(HaveKey("snapshots")) - g.Expect(bcList[0]).Should(HaveKey("type")) - g.Expect(bcList[0]).Should(HaveKey("groupName")) - g.Expect(bcList[0]).ShouldNot(HaveKey("objects")) - }, - [][]string{ - {`. | length`, `2`}, - - // grouped binding context contains binding, type, snapshots and groupName - {`.[0] | length`, `4`}, // Only 4 fields - {`.[0].snapshots | has("monitor_pods")`, `true`}, - {`.[0].snapshots."monitor_pods" | length`, `1`}, - {`.[0].binding`, `"monitor_pods"`}, - {`.[0].type`, `"Group"`}, - {`.[0].groupName`, `"pods"`}, - - // JSON dump should has only 4 fields: binding, type, watchEvent and object. - {`.[1] | length`, `4`}, - {`.[1].binding`, `"monitor_pods"`}, - {`.[1].type`, `"Event"`}, - {`.[1].watchEvent`, `"Added"`}, - {`.[1].object.metadata.namespace`, `"default"`}, - {`.[1].object.metadata.name`, `"pod-qwe"`}, - }, - }, - { - "grouped Synchronization", - func() []BindingContext { - bcs := []BindingContext{} - - bc := BindingContext{ - Binding: "monitor_config_maps", - Type: TypeSynchronization, - Objects: []ObjectAndFilterResult{}, - Snapshots: map[string][]ObjectAndFilterResult{}, - } - bc.Metadata.BindingType = OnKubernetesEvent - bc.Metadata.Group = "pods" - bc.Metadata.IncludeSnapshots = []string{"monitor_config_maps"} - // object without jqfilter should not have filterResult field - obj := ObjectAndFilterResult{ - Object: &unstructured.Unstructured{ - Object: map[string]interface{}{ - "metadata": map[string]interface{}{ - "namespace": "default", - "name": "pod-qwe", - }, - "kind": "Pod", - }, - }, - FilterResult: "asd", - } - bc.Objects = append(bc.Objects, obj) - bc.Snapshots["monitor_config_maps"] = append(bc.Snapshots["monitor_config_maps"], obj) - bcs = append(bcs, bc) - - bc = BindingContext{ - Binding: "monitor_pods", - Type: TypeSynchronization, - Objects: []ObjectAndFilterResult{}, - } - bc.Metadata.BindingType = OnKubernetesEvent - // object without jqfilter should not have filterResult field - obj = ObjectAndFilterResult{ - Object: &unstructured.Unstructured{ - Object: map[string]interface{}{ - "metadata": map[string]interface{}{ - "namespace": "default", - "name": "pod-qwe", - }, - "kind": "Pod", - }, - }, - FilterResult: "asd", - } - bc.Objects = append(bc.Objects, obj) - - bcs = append(bcs, bc) - return bcs - }, - func() { - g.Expect(bcList).Should(HaveLen(2)) - - g.Expect(bcList[0]).Should(HaveLen(4)) - g.Expect(bcList[0]).Should(HaveKey("binding")) - g.Expect(bcList[0]["binding"]).Should(Equal("monitor_config_maps")) - g.Expect(bcList[0]).Should(HaveKey("type")) - g.Expect(bcList[0]["type"]).Should(Equal("Group")) - g.Expect(bcList[0]["groupName"]).Should(Equal("pods")) - g.Expect(bcList[0]).Should(HaveKey("snapshots")) - g.Expect(bcList[0]["snapshots"]).Should(HaveLen(1)) - - g.Expect(bcList[1]).Should(HaveLen(3)) - g.Expect(bcList[1]).Should(HaveKey("binding")) - g.Expect(bcList[1]).Should(HaveKey("type")) - g.Expect(bcList[1]["type"]).Should(Equal(TypeSynchronization)) - g.Expect(bcList[1]).Should(HaveKey("objects")) - g.Expect(bcList[1]["objects"]).Should(HaveLen(1)) - }, - [][]string{ - {`. | length`, `2`}, - - // grouped binding context contains binging, type, snapshots and groupName - {`.[0] | length`, `4`}, // Only 4 fields - {`.[0].binding`, `"monitor_config_maps"`}, - {`.[0].type`, `"Group"`}, - {`.[0].snapshots | has("monitor_config_maps")`, `true`}, - {`.[0].snapshots."monitor_config_maps" | length`, `1`}, - - // usual Synchronization has 3 fields: binding, type and objects. - {`.[1] | length`, `3`}, - {`.[1].binding`, `"monitor_pods"`}, - {`.[1].type`, `"Synchronization"`}, - {`.[1].objects | length`, `1`}, - {`.[1].objects[0].object.metadata.namespace`, `"default"`}, - {`.[1].objects[0].object.metadata.name`, `"pod-qwe"`}, - }, - }, - { - "kubernetes Synchronization with empty objects", - func() []BindingContext { - bc := BindingContext{ - Binding: "kubernetes", - Type: TypeSynchronization, - Objects: []ObjectAndFilterResult{}, - } - bc.Metadata.BindingType = OnKubernetesEvent - return []BindingContext{bc} - }, - func() { - assert.Len(t, bcList[0]["objects"], 0) - assert.Equal(t, TypeSynchronization, bcList[0]["type"]) - assert.Equal(t, "kubernetes", bcList[0]["binding"]) - assert.NotContains(t, bcList[0], "object") - assert.NotContains(t, bcList[0], "filterResult") - }, - [][]string{ - // JSON dump should contains n fields: binding, type and objects - {`.[0] | length`, `3`}, - {`.[0].binding`, `"kubernetes"`}, - {`.[0].type`, `"Synchronization"`}, - // objects should be an empty array - {`.[0] | has("objects")`, `true`}, - {`.[0].objects | length`, `0`}, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - bcList = ConvertBindingContextList("v1", tt.bc()) - // assert.Len(t, bcList, 1) - - var err error - bcJson, err = bcList.Json() - assert.NoError(t, err) - - for _, jqAssertion := range tt.jqAssertions { - JqEqual(t, bcJson, jqAssertion[0], jqAssertion[1]) - } - - tt.fn() - }) - } -} - -// Test conversion of BindingContext for v1, also test json marshal of v1 binding contexts. -func Test_ConvertBindingContextList_v0(t *testing.T) { - var bcList BindingContextList - var bcJson []byte - - tests := []struct { - name string - bc func() BindingContext - fn func() - jqAsertions [][]string - }{ - { - "OnStartup binding", - func() BindingContext { - bc := BindingContext{ - Binding: "onStartup", - } - bc.Metadata.BindingType = OnStartup - return bc - }, - func() { - assert.Equal(t, "onStartup", bcList[0]["binding"]) - }, - [][]string{ - {`.[0].binding`, `"onStartup"`}, - {`.[0] | length`, `1`}, - }, - }, - { - "onKubernetesEvent binding", - func() BindingContext { - bc := BindingContext{ - Binding: "onKubernetesEvent", - Type: "Event", - WatchEvent: WatchEventAdded, - Objects: []ObjectAndFilterResult{ - { - Object: &unstructured.Unstructured{ - Object: map[string]interface{}{ - "metadata": map[string]interface{}{ - "namespace": "default", - "name": "pod-qwe", - }, - "kind": "Pod", - }, - }, - }, - }, - } - bc.Metadata.BindingType = OnKubernetesEvent - return bc - }, - - func() { - assert.Len(t, bcList[0], 5) - assert.Equal(t, "onKubernetesEvent", bcList[0]["binding"]) - assert.Equal(t, "add", bcList[0]["resourceEvent"]) - assert.Equal(t, "default", bcList[0]["resourceNamespace"]) - assert.Equal(t, "Pod", bcList[0]["resourceKind"]) - assert.Equal(t, "pod-qwe", bcList[0]["resourceName"]) - }, - [][]string{ - // JSON dump should has only 4 fields: binding, type, watchEvent and object. - {`.[0] | length`, `5`}, - {`.[0].binding`, `"onKubernetesEvent"`}, - {`.[0].resourceEvent`, `"add"`}, - {`.[0].resourceNamespace`, `"default"`}, - {`.[0].resourceKind`, `"Pod"`}, - {`.[0].resourceName`, `"pod-qwe"`}, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - bcList = ConvertBindingContextList("v0", []BindingContext{tt.bc()}) - assert.Len(t, bcList, 1) - - var err error - bcJson, err = bcList.Json() - assert.NoError(t, err) - - for _, jqAssertion := range tt.jqAsertions { - JqEqual(t, bcJson, jqAssertion[0], jqAssertion[1]) - } - - tt.fn() - }) - } -} +// TODO: need refactoring +// change JQ tests for another testing tool + +// import ( +// "testing" + +// . "github.com/onsi/gomega" +// "github.com/stretchr/testify/assert" +// "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + +// . "github.com/flant/libjq-go" +// . "github.com/flant/shell-operator/pkg/hook/types" +// . "github.com/flant/shell-operator/pkg/kube_events_manager/types" +// ) + +// func JqEqual(t *testing.T, input []byte, program string, expected string) { +// //nolint:typecheck // Ignore false positive: undeclared name: `Jq`. +// res, err := Jq().Program(program).Run(string(input)) +// if assert.NoError(t, err) { +// assert.Equal(t, expected, res, "jq: '%s', json was '%s'", program, string(input)) +// } +// } + +// // Test conversion of BindingContext for v1, also test json marshal of v1 binding contexts. +// func Test_ConvertBindingContextList_v1(t *testing.T) { +// g := NewWithT(t) + +// var bcList BindingContextList +// var bcJson []byte + +// tests := []struct { +// name string +// bc func() []BindingContext +// fn func() +// jqAssertions [][]string +// }{ +// { +// "OnStartup binding", +// func() []BindingContext { +// bc := BindingContext{ +// Binding: "onStartup", +// } +// bc.Metadata.BindingType = OnStartup +// return []BindingContext{bc} +// }, +// func() { +// assert.Equal(t, "onStartup", bcList[0]["binding"]) +// }, +// [][]string{ +// {`.[0].binding`, `"onStartup"`}, +// {`.[0] | length`, `1`}, +// }, +// }, +// { +// "kubernetes Event binding", +// func() []BindingContext { +// bc := BindingContext{ +// Binding: "kubernetes", +// Type: TypeEvent, +// WatchEvent: WatchEventAdded, +// Objects: []ObjectAndFilterResult{ +// { +// Object: &unstructured.Unstructured{ +// Object: map[string]interface{}{ +// "metadata": map[string]interface{}{ +// "namespace": "default", +// "name": "pod-qwe", +// }, +// "kind": "Pod", +// }, +// }, +// }, +// }, +// } +// bc.Metadata.BindingType = OnKubernetesEvent +// return []BindingContext{bc} +// }, + +// func() { +// assert.Len(t, bcList[0], 4) +// assert.Equal(t, "kubernetes", bcList[0]["binding"]) +// assert.Equal(t, TypeEvent, bcList[0]["type"]) +// assert.Equal(t, "Added", bcList[0]["watchEvent"]) +// assert.IsType(t, &unstructured.Unstructured{}, bcList[0]["object"]) +// assert.Contains(t, bcList[0]["object"].(*unstructured.Unstructured).Object, "metadata") +// }, +// [][]string{ +// // JSON dump should has only 4 fields: binding, type, watchEvent and object. +// {`.[0] | length`, `4`}, +// {`.[0].binding`, `"kubernetes"`}, +// {`.[0].type`, `"Event"`}, +// {`.[0].watchEvent`, `"Added"`}, +// {`.[0].object.metadata.namespace`, `"default"`}, +// {`.[0].object.metadata.name`, `"pod-qwe"`}, +// }, +// }, +// { +// "kubernetes Synchronization event", +// func() []BindingContext { +// bc := BindingContext{ +// Binding: "kubernetes", +// Type: TypeSynchronization, +// Objects: []ObjectAndFilterResult{}, +// } +// bc.Metadata.BindingType = OnKubernetesEvent + +// obj := ObjectAndFilterResult{ +// Object: &unstructured.Unstructured{ +// Object: map[string]interface{}{ +// "metadata": map[string]interface{}{ +// "namespace": "default", +// "name": "pod-qwe", +// }, +// "kind": "Pod", +// }, +// }, +// } +// obj.Metadata.JqFilter = "" +// bc.Objects = append(bc.Objects, obj) + +// // object with jqfilter should have filterResult field +// obj = ObjectAndFilterResult{ +// Object: &unstructured.Unstructured{ +// Object: map[string]interface{}{ +// "metadata": map[string]interface{}{ +// "namespace": "default", +// "name": "deployment-test", +// }, +// "kind": "Deployment", +// }, +// }, +// FilterResult: `{"labels":{"label-name":"label-value"}}`, +// } +// obj.Metadata.JqFilter = ".metadata.labels" +// bc.Objects = append(bc.Objects, obj) + +// // object with jqfilter and with empty result should have filterResult field +// obj = ObjectAndFilterResult{ +// Object: &unstructured.Unstructured{ +// Object: map[string]interface{}{ +// "metadata": map[string]interface{}{ +// "namespace": "default", +// "name": "deployment-2", +// }, +// "kind": "Deployment", +// }, +// }, +// FilterResult: `""`, +// } +// obj.Metadata.JqFilter = ".metadata.labels" +// bc.Objects = append(bc.Objects, obj) + +// return []BindingContext{bc} +// }, +// func() { +// assert.Len(t, bcList[0], 3) +// assert.Len(t, bcList[0]["objects"], 3) +// assert.Equal(t, TypeSynchronization, bcList[0]["type"]) +// assert.Equal(t, "kubernetes", bcList[0]["binding"]) +// assert.NotContains(t, bcList[0], "object") +// assert.NotContains(t, bcList[0], "filterResult") +// }, +// [][]string{ +// // JSON dump should contains n fields: binding, type and objects +// {`.[0] | length`, `3`}, +// {`.[0].binding`, `"kubernetes"`}, +// {`.[0].type`, `"Synchronization"`}, + +// {`.[0].objects[] | select(.object.metadata.name == "pod-qwe") | has("filterResult")`, `false`}, +// {`.[0].objects[] | select(.object.metadata.name == "deployment-test") | has("filterResult")`, `true`}, +// {`.[0].objects[] | select(.object.metadata.name == "deployment-test") | .filterResult.labels."label-name"`, `"label-value"`}, +// {`.[0].objects[] | select(.object.metadata.name == "deployment-2") | has("filterResult")`, `true`}, +// }, +// }, +// { +// "binding context with group", +// func() []BindingContext { +// bcs := []BindingContext{} + +// bc := BindingContext{ +// Binding: "monitor_pods", +// Type: TypeEvent, +// WatchEvent: WatchEventAdded, +// Objects: []ObjectAndFilterResult{}, +// Snapshots: map[string][]ObjectAndFilterResult{}, +// } +// bc.Metadata.BindingType = OnKubernetesEvent +// bc.Metadata.Group = "pods" +// bc.Metadata.IncludeSnapshots = []string{"monitor_pods"} + +// obj := ObjectAndFilterResult{ +// Object: &unstructured.Unstructured{ +// Object: map[string]interface{}{ +// "metadata": map[string]interface{}{ +// "namespace": "default", +// "name": "pod-qwe", +// }, +// "kind": "Pod", +// }, +// }, +// } +// bc.Objects = append(bc.Objects, obj) +// bc.Snapshots["monitor_pods"] = append(bc.Snapshots["monitor_pods"], obj) +// bcs = append(bcs, bc) + +// bc = BindingContext{ +// Binding: "monitor_pods", +// Type: TypeEvent, +// WatchEvent: WatchEventAdded, +// Objects: []ObjectAndFilterResult{}, +// } +// bc.Metadata.BindingType = OnKubernetesEvent + +// obj = ObjectAndFilterResult{ +// Object: &unstructured.Unstructured{ +// Object: map[string]interface{}{ +// "metadata": map[string]interface{}{ +// "namespace": "default", +// "name": "pod-qwe", +// }, +// "kind": "Pod", +// }, +// }, +// } +// bc.Objects = append(bc.Objects, obj) + +// bcs = append(bcs, bc) +// return bcs +// }, +// func() { +// g.Expect(bcList[0]).Should(HaveKey("binding")) +// g.Expect(bcList[0]).Should(HaveKey("snapshots")) +// g.Expect(bcList[0]).Should(HaveKey("type")) +// g.Expect(bcList[0]).Should(HaveKey("groupName")) +// g.Expect(bcList[0]).ShouldNot(HaveKey("objects")) +// }, +// [][]string{ +// {`. | length`, `2`}, + +// // grouped binding context contains binding, type, snapshots and groupName +// {`.[0] | length`, `4`}, // Only 4 fields +// {`.[0].snapshots | has("monitor_pods")`, `true`}, +// {`.[0].snapshots."monitor_pods" | length`, `1`}, +// {`.[0].binding`, `"monitor_pods"`}, +// {`.[0].type`, `"Group"`}, +// {`.[0].groupName`, `"pods"`}, + +// // JSON dump should has only 4 fields: binding, type, watchEvent and object. +// {`.[1] | length`, `4`}, +// {`.[1].binding`, `"monitor_pods"`}, +// {`.[1].type`, `"Event"`}, +// {`.[1].watchEvent`, `"Added"`}, +// {`.[1].object.metadata.namespace`, `"default"`}, +// {`.[1].object.metadata.name`, `"pod-qwe"`}, +// }, +// }, +// { +// "grouped Synchronization", +// func() []BindingContext { +// bcs := []BindingContext{} + +// bc := BindingContext{ +// Binding: "monitor_config_maps", +// Type: TypeSynchronization, +// Objects: []ObjectAndFilterResult{}, +// Snapshots: map[string][]ObjectAndFilterResult{}, +// } +// bc.Metadata.BindingType = OnKubernetesEvent +// bc.Metadata.Group = "pods" +// bc.Metadata.IncludeSnapshots = []string{"monitor_config_maps"} +// // object without jqfilter should not have filterResult field +// obj := ObjectAndFilterResult{ +// Object: &unstructured.Unstructured{ +// Object: map[string]interface{}{ +// "metadata": map[string]interface{}{ +// "namespace": "default", +// "name": "pod-qwe", +// }, +// "kind": "Pod", +// }, +// }, +// FilterResult: "asd", +// } +// bc.Objects = append(bc.Objects, obj) +// bc.Snapshots["monitor_config_maps"] = append(bc.Snapshots["monitor_config_maps"], obj) +// bcs = append(bcs, bc) + +// bc = BindingContext{ +// Binding: "monitor_pods", +// Type: TypeSynchronization, +// Objects: []ObjectAndFilterResult{}, +// } +// bc.Metadata.BindingType = OnKubernetesEvent +// // object without jqfilter should not have filterResult field +// obj = ObjectAndFilterResult{ +// Object: &unstructured.Unstructured{ +// Object: map[string]interface{}{ +// "metadata": map[string]interface{}{ +// "namespace": "default", +// "name": "pod-qwe", +// }, +// "kind": "Pod", +// }, +// }, +// FilterResult: "asd", +// } +// bc.Objects = append(bc.Objects, obj) + +// bcs = append(bcs, bc) +// return bcs +// }, +// func() { +// g.Expect(bcList).Should(HaveLen(2)) + +// g.Expect(bcList[0]).Should(HaveLen(4)) +// g.Expect(bcList[0]).Should(HaveKey("binding")) +// g.Expect(bcList[0]["binding"]).Should(Equal("monitor_config_maps")) +// g.Expect(bcList[0]).Should(HaveKey("type")) +// g.Expect(bcList[0]["type"]).Should(Equal("Group")) +// g.Expect(bcList[0]["groupName"]).Should(Equal("pods")) +// g.Expect(bcList[0]).Should(HaveKey("snapshots")) +// g.Expect(bcList[0]["snapshots"]).Should(HaveLen(1)) + +// g.Expect(bcList[1]).Should(HaveLen(3)) +// g.Expect(bcList[1]).Should(HaveKey("binding")) +// g.Expect(bcList[1]).Should(HaveKey("type")) +// g.Expect(bcList[1]["type"]).Should(Equal(TypeSynchronization)) +// g.Expect(bcList[1]).Should(HaveKey("objects")) +// g.Expect(bcList[1]["objects"]).Should(HaveLen(1)) +// }, +// [][]string{ +// {`. | length`, `2`}, + +// // grouped binding context contains binging, type, snapshots and groupName +// {`.[0] | length`, `4`}, // Only 4 fields +// {`.[0].binding`, `"monitor_config_maps"`}, +// {`.[0].type`, `"Group"`}, +// {`.[0].snapshots | has("monitor_config_maps")`, `true`}, +// {`.[0].snapshots."monitor_config_maps" | length`, `1`}, + +// // usual Synchronization has 3 fields: binding, type and objects. +// {`.[1] | length`, `3`}, +// {`.[1].binding`, `"monitor_pods"`}, +// {`.[1].type`, `"Synchronization"`}, +// {`.[1].objects | length`, `1`}, +// {`.[1].objects[0].object.metadata.namespace`, `"default"`}, +// {`.[1].objects[0].object.metadata.name`, `"pod-qwe"`}, +// }, +// }, +// { +// "kubernetes Synchronization with empty objects", +// func() []BindingContext { +// bc := BindingContext{ +// Binding: "kubernetes", +// Type: TypeSynchronization, +// Objects: []ObjectAndFilterResult{}, +// } +// bc.Metadata.BindingType = OnKubernetesEvent +// return []BindingContext{bc} +// }, +// func() { +// assert.Len(t, bcList[0]["objects"], 0) +// assert.Equal(t, TypeSynchronization, bcList[0]["type"]) +// assert.Equal(t, "kubernetes", bcList[0]["binding"]) +// assert.NotContains(t, bcList[0], "object") +// assert.NotContains(t, bcList[0], "filterResult") +// }, +// [][]string{ +// // JSON dump should contains n fields: binding, type and objects +// {`.[0] | length`, `3`}, +// {`.[0].binding`, `"kubernetes"`}, +// {`.[0].type`, `"Synchronization"`}, +// // objects should be an empty array +// {`.[0] | has("objects")`, `true`}, +// {`.[0].objects | length`, `0`}, +// }, +// }, +// } + +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// bcList = ConvertBindingContextList("v1", tt.bc()) +// // assert.Len(t, bcList, 1) + +// var err error +// bcJson, err = bcList.Json() +// assert.NoError(t, err) + +// for _, jqAssertion := range tt.jqAssertions { +// JqEqual(t, bcJson, jqAssertion[0], jqAssertion[1]) +// } + +// tt.fn() +// }) +// } +// } + +// // Test conversion of BindingContext for v1, also test json marshal of v1 binding contexts. +// func Test_ConvertBindingContextList_v0(t *testing.T) { +// var bcList BindingContextList +// var bcJson []byte + +// tests := []struct { +// name string +// bc func() BindingContext +// fn func() +// jqAsertions [][]string +// }{ +// { +// "OnStartup binding", +// func() BindingContext { +// bc := BindingContext{ +// Binding: "onStartup", +// } +// bc.Metadata.BindingType = OnStartup +// return bc +// }, +// func() { +// assert.Equal(t, "onStartup", bcList[0]["binding"]) +// }, +// [][]string{ +// {`.[0].binding`, `"onStartup"`}, +// {`.[0] | length`, `1`}, +// }, +// }, +// { +// "onKubernetesEvent binding", +// func() BindingContext { +// bc := BindingContext{ +// Binding: "onKubernetesEvent", +// Type: "Event", +// WatchEvent: WatchEventAdded, +// Objects: []ObjectAndFilterResult{ +// { +// Object: &unstructured.Unstructured{ +// Object: map[string]interface{}{ +// "metadata": map[string]interface{}{ +// "namespace": "default", +// "name": "pod-qwe", +// }, +// "kind": "Pod", +// }, +// }, +// }, +// }, +// } +// bc.Metadata.BindingType = OnKubernetesEvent +// return bc +// }, + +// func() { +// assert.Len(t, bcList[0], 5) +// assert.Equal(t, "onKubernetesEvent", bcList[0]["binding"]) +// assert.Equal(t, "add", bcList[0]["resourceEvent"]) +// assert.Equal(t, "default", bcList[0]["resourceNamespace"]) +// assert.Equal(t, "Pod", bcList[0]["resourceKind"]) +// assert.Equal(t, "pod-qwe", bcList[0]["resourceName"]) +// }, +// [][]string{ +// // JSON dump should has only 4 fields: binding, type, watchEvent and object. +// {`.[0] | length`, `5`}, +// {`.[0].binding`, `"onKubernetesEvent"`}, +// {`.[0].resourceEvent`, `"add"`}, +// {`.[0].resourceNamespace`, `"default"`}, +// {`.[0].resourceKind`, `"Pod"`}, +// {`.[0].resourceName`, `"pod-qwe"`}, +// }, +// }, +// } + +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// bcList = ConvertBindingContextList("v0", []BindingContext{tt.bc()}) +// assert.Len(t, bcList, 1) + +// var err error +// bcJson, err = bcList.Json() +// assert.NoError(t, err) + +// for _, jqAssertion := range tt.jqAsertions { +// JqEqual(t, bcJson, jqAssertion[0], jqAssertion[1]) +// } + +// tt.fn() +// }) +// } +// } diff --git a/pkg/webhook/admission/response_test.go b/pkg/webhook/admission/response_test.go index 66fc2058..a07c24b7 100644 --- a/pkg/webhook/admission/response_test.go +++ b/pkg/webhook/admission/response_test.go @@ -4,7 +4,6 @@ import "testing" func Test_AdmissionResponseFromFile_Allowed(t *testing.T) { r, err := ResponseFromFile("testdata/response/good_allow.json") - if err != nil { t.Fatalf("ValidatingResponse should be loaded from file: %v", err) } @@ -20,7 +19,6 @@ func Test_AdmissionResponseFromFile_Allowed(t *testing.T) { func Test_AdmissionResponseFromFile_AllowedWithWarnings(t *testing.T) { r, err := ResponseFromFile("testdata/response/good_allow_warnings.json") - if err != nil { t.Fatalf("ValidatingResponse should be loaded from file: %v", err) } @@ -40,7 +38,6 @@ func Test_AdmissionResponseFromFile_AllowedWithWarnings(t *testing.T) { func Test_AdmissionResponseFromFile_NotAllowed_WithMessage(t *testing.T) { r, err := ResponseFromFile("testdata/response/good_deny.json") - if err != nil { t.Fatalf("ValidatingResponse should be loaded from file: %v", err) } @@ -60,7 +57,6 @@ func Test_AdmissionResponseFromFile_NotAllowed_WithMessage(t *testing.T) { func Test_AdmissionResponseFromFile_NotAllowed_WithoutMessage(t *testing.T) { r, err := ResponseFromFile("testdata/response/good_deny_quiet.json") - if err != nil { t.Fatalf("ValidatingResponse should be loaded from file: %v", err) } diff --git a/pkg/webhook/conversion/handler.go b/pkg/webhook/conversion/handler.go index 5a032520..0aa74093 100644 --- a/pkg/webhook/conversion/handler.go +++ b/pkg/webhook/conversion/handler.go @@ -110,7 +110,8 @@ func (h *WebhookHandler) handleReviewRequest(crdName string, request *v1.Convers UID: request.UID, Result: metav1.Status{ Status: metav1.StatusSuccess, - }}, nil + }, + }, nil } // detectCrdName extracts crdName from the url path.