From 3cdd93a568de3a8a4b8c882de50970ca828ced99 Mon Sep 17 00:00:00 2001 From: Mustafa Abdelrahman Date: Mon, 31 Jul 2023 15:40:45 +0200 Subject: [PATCH] Refactor & add more validation webhook tests Signed-off-by: Mustafa Abdelrahman --- cmd/webhook/admission/admission_test.go | 119 ++++++++---------- .../admission/testdata/invalid-rg.json | 13 ++ .../rg-with-invalid-eskip-filters.json | 48 +++++++ .../testdata/rg-with-valid-eskip-filters.json | 48 +++++++ cmd/webhook/admission/testdata/valid-rg.json | 26 ++++ 5 files changed, 188 insertions(+), 66 deletions(-) create mode 100644 cmd/webhook/admission/testdata/invalid-rg.json create mode 100644 cmd/webhook/admission/testdata/rg-with-invalid-eskip-filters.json create mode 100644 cmd/webhook/admission/testdata/rg-with-valid-eskip-filters.json create mode 100644 cmd/webhook/admission/testdata/valid-rg.json diff --git a/cmd/webhook/admission/admission_test.go b/cmd/webhook/admission/admission_test.go index 4c382f289d..305a871c53 100644 --- a/cmd/webhook/admission/admission_test.go +++ b/cmd/webhook/admission/admission_test.go @@ -2,15 +2,41 @@ package admission import ( "bytes" + _ "embed" + "fmt" "io" "net/http" "net/http/httptest" + "os" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) +var ( + responseAllowedFmt = `{ + "kind": "AdmissionReview", + "apiVersion": "admission.k8s.io/v1", + "response": { + "uid": "req-uid", + "allowed": true + } + }` + + responseNotAllowedFmt = `{ + "kind": "AdmissionReview", + "apiVersion": "admission.k8s.io/v1", + "response": { + "uid": "req-uid", + "allowed": false, + "status": { + "message": "%s" + } + } + }` +) + type testAdmitter struct { // validate validates & plugs parameters for Admit validate func(response *admissionRequest) (*admissionResponse, error) @@ -60,78 +86,39 @@ func TestUnsupportedContentType(t *testing.T) { func TestRouteGroupAdmitter(t *testing.T) { for _, tc := range []struct { - name string - input string - result string + name string + inputFile string + message string }{ { - name: "allowed", - input: `{ - "request": { - "uid": "req-uid", - "name": "req1", - "namespace": "n1", - "object": { - "metadata": { - "name": "rg1", - "namespace": "n1" - }, - "spec": { - "backends": [ - { - "name": "backend", - "type": "shunt" - } - ], - "defaultBackends": [ - { - "backendName": "backend" - } - ] - } - } - } - }`, - result: `{ - "kind": "AdmissionReview", - "apiVersion": "admission.k8s.io/v1", - "response": { - "uid": "req-uid", - "allowed": true - } - }`, + name: "allowed", + inputFile: "valid-rg.json", }, { - name: "not allowed", - input: `{ - "request": { - "uid": "req-uid", - "name": "req1", - "namespace": "n1", - "object": { - "metadata": { - "name": "rg1", - "namespace": "n1" - } - } - } - }`, - result: `{ - "kind": "AdmissionReview", - "apiVersion": "admission.k8s.io/v1", - "response": { - "uid": "req-uid", - "allowed": false, - "status": { - "message": - "could not validate RouteGroup, error in route group n1/rg1: route group without spec" - } - } - }`, + name: "not allowed", + inputFile: "invalid-rg.json", + message: "could not validate RouteGroup, error in route group n1/rg1: route group without spec", + }, + { + name: "valid eskip filters", + inputFile: "rg-with-valid-eskip-filters.json", + }, + { + name: "invalid eskip filters", // This means that eskip parser failed but doesn't mean filters exist + inputFile: "rg-with-invalid-eskip-filters.json", + message: "could not validate RouteGroup, parse failed after token status, last route id: , position 11: syntax error", }, } { t.Run(tc.name, func(t *testing.T) { - req := httptest.NewRequest("POST", "http://example.com/foo", bytes.NewBuffer([]byte(tc.input))) + result := responseAllowedFmt + if len(tc.message) > 0 { + result = fmt.Sprintf(responseNotAllowedFmt, tc.message) + } + + input, err := os.ReadFile("testdata/" + tc.inputFile) + require.NoError(t, err) + + req := httptest.NewRequest("POST", "http://example.com/foo", bytes.NewBuffer(input)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() @@ -146,7 +133,7 @@ func TestRouteGroupAdmitter(t *testing.T) { require.NoError(t, err) resp.Body.Close() - assert.JSONEq(t, tc.result, string(rb)) + assert.JSONEq(t, result, string(rb)) }) } } diff --git a/cmd/webhook/admission/testdata/invalid-rg.json b/cmd/webhook/admission/testdata/invalid-rg.json new file mode 100644 index 0000000000..8903e04416 --- /dev/null +++ b/cmd/webhook/admission/testdata/invalid-rg.json @@ -0,0 +1,13 @@ +{ + "request": { + "uid": "req-uid", + "name": "req1", + "namespace": "n1", + "object": { + "metadata": { + "name": "rg1", + "namespace": "n1" + } + } + } +} \ No newline at end of file diff --git a/cmd/webhook/admission/testdata/rg-with-invalid-eskip-filters.json b/cmd/webhook/admission/testdata/rg-with-invalid-eskip-filters.json new file mode 100644 index 0000000000..061223b39e --- /dev/null +++ b/cmd/webhook/admission/testdata/rg-with-invalid-eskip-filters.json @@ -0,0 +1,48 @@ +{ + "request": { + "uid": "req-uid", + "name": "req1", + "operation": "create", + "kind": { + "group": "zalando", + "version": "v1", + "kind": "RouteGroup" + }, + "namespace": "n1", + "object": { + "metadata": { + "name": "rg1", + "namespace": "n1" + }, + "spec": { + "backends": [ + { + "name": "backend", + "type": "shunt" + } + ], + "defaultBackends": [ + { + "backendName": "backend" + } + ], + "routes": [ + { + "backends": [ + { + "backendName": "backend" + } + ], + "filters": [ + "status&(201)" + ], + "path": "/", + "predicates": [ + "Method(\"GET\")" + ] + } + ] + } + } + } +} \ No newline at end of file diff --git a/cmd/webhook/admission/testdata/rg-with-valid-eskip-filters.json b/cmd/webhook/admission/testdata/rg-with-valid-eskip-filters.json new file mode 100644 index 0000000000..4e501500e9 --- /dev/null +++ b/cmd/webhook/admission/testdata/rg-with-valid-eskip-filters.json @@ -0,0 +1,48 @@ +{ + "request": { + "uid": "req-uid", + "name": "req1", + "operation": "create", + "kind": { + "group": "zalando", + "version": "v1", + "kind": "RouteGroup" + }, + "namespace": "n1", + "object": { + "metadata": { + "name": "rg1", + "namespace": "n1" + }, + "spec": { + "backends": [ + { + "name": "backend", + "type": "shunt" + } + ], + "defaultBackends": [ + { + "backendName": "backend" + } + ], + "routes": [ + { + "backends": [ + { + "backendName": "backend" + } + ], + "filters": [ + "status(201)" + ], + "path": "/", + "predicates": [ + "Method(\"GET\")" + ] + } + ] + } + } + } +} \ No newline at end of file diff --git a/cmd/webhook/admission/testdata/valid-rg.json b/cmd/webhook/admission/testdata/valid-rg.json new file mode 100644 index 0000000000..93e5e40b2b --- /dev/null +++ b/cmd/webhook/admission/testdata/valid-rg.json @@ -0,0 +1,26 @@ +{ + "request": { + "uid": "req-uid", + "name": "req1", + "namespace": "n1", + "object": { + "metadata": { + "name": "rg1", + "namespace": "n1" + }, + "spec": { + "backends": [ + { + "name": "backend", + "type": "shunt" + } + ], + "defaultBackends": [ + { + "backendName": "backend" + } + ] + } + } + } +} \ No newline at end of file