From f64f9f70b6047f5ac183d6e61c8671fdd8be4e68 Mon Sep 17 00:00:00 2001 From: Natalia Sitko <80401180+nataliasitko@users.noreply.github.com> Date: Tue, 9 Jul 2024 11:46:44 +0200 Subject: [PATCH 01/11] Remove blank spaces (#1152) --- docs/user/tutorials/01-20-set-up-tls-gateway.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/tutorials/01-20-set-up-tls-gateway.md b/docs/user/tutorials/01-20-set-up-tls-gateway.md index fc176a0cc..55b744cdf 100644 --- a/docs/user/tutorials/01-20-set-up-tls-gateway.md +++ b/docs/user/tutorials/01-20-set-up-tls-gateway.md @@ -59,7 +59,7 @@ This tutorial shows how to set up a TLS Gateway in simple mode. credentialName: $TLS_SECRET hosts: - "*.$DOMAIN_TO_EXPOSE_WORKLOADS" - EOF + EOF ``` \ No newline at end of file From 73868fa39f6b5b5f26848d8d76382b34e4fcaa8c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 14:20:44 +0200 Subject: [PATCH 02/11] gomod(deps): bump golang.org/x/net from 0.26.0 to 0.27.0 (#1145) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.26.0 to 0.27.0. - [Commits](https://github.com/golang/net/compare/v0.26.0...v0.27.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Bartosz Chwila <103247439+barchw@users.noreply.github.com> Co-authored-by: Tim Riffer --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index c7c53482d..278638016 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/thoas/go-funk v0.9.3 gitlab.com/rodrigoodhin/gocure v0.0.0-20230214115050-efed6aac536a - golang.org/x/net v0.26.0 + golang.org/x/net v0.27.0 golang.org/x/time v0.5.0 google.golang.org/appengine v1.6.8 google.golang.org/protobuf v1.34.2 @@ -69,9 +69,9 @@ require ( github.com/tdewolff/minify/v2 v2.10.0 // indirect github.com/tdewolff/parse/v2 v2.5.27 // indirect go.uber.org/zap v1.26.0 // indirect - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/term v0.21.0 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/term v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect golang.org/x/tools v0.22.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 29142038b..555786184 100644 --- a/go.sum +++ b/go.sum @@ -178,8 +178,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -194,8 +194,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -214,15 +214,15 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= From 515076227a71ab30922ff2a727841bc8cc5bc6ea Mon Sep 17 00:00:00 2001 From: Kamil Kasperski Date: Tue, 9 Jul 2024 15:36:45 +0200 Subject: [PATCH 03/11] feat: more log gathering in int test jobs (#1154) /kind feature /area ci Add some additional log spitting and collection to gather more insights on potential failures only if something is wrong with the jobs. --- .../integration-test-gardener/action.yaml | 16 ++++++++++++++++ .github/actions/integration-tests/action.yaml | 16 ++++++++++++++++ tests/integration/pkg/helpers/api_rule.go | 11 +++++++---- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/.github/actions/integration-test-gardener/action.yaml b/.github/actions/integration-test-gardener/action.yaml index 329933bd3..f8e456644 100644 --- a/.github/actions/integration-test-gardener/action.yaml +++ b/.github/actions/integration-test-gardener/action.yaml @@ -58,6 +58,22 @@ runs: run: | EXPORT_RESULT=true \ ${{ inputs.script }} + - shell: bash + name: gather deployment logs + if: failure() + run: | + mkdir logs + (kubectl logs -n kyma-system deployments/istio-controller-manager || true) > logs/istio-controller-manager.log + (kubectl logs -n kyma-system deployments/api-gateway-controller-manager || true) > logs/api-gateway-controller-manager.log + (kubectl logs -n istio-system deployments/istio-ingressgateway || true) > logs/istio-ingressgateway.log + (kubectl logs -n istio-system deployments/istiod || true) > logs/istiod.log + (kubectl describe --all-namespaces apirules.gateway.kyma-project.io -oyaml) > logs/apirules-dump.yaml + - name: Uploads logs + uses: actions/upload-artifact@v4 + if: failure() + with: + name: logs-${{ github.job }} + path: logs/ - name: Uploads artifacts uses: actions/upload-artifact@v4 with: diff --git a/.github/actions/integration-tests/action.yaml b/.github/actions/integration-tests/action.yaml index 5db5b9092..3ad737721 100644 --- a/.github/actions/integration-tests/action.yaml +++ b/.github/actions/integration-tests/action.yaml @@ -45,8 +45,24 @@ runs: run: | EXPORT_RESULT=true \ make install-istio deploy test-integration + - shell: bash + name: gather deployment logs + if: failure() + run: | + mkdir logs + (kubectl logs -n kyma-system deployments/istio-controller-manager || true) > logs/istio-controller-manager.log + (kubectl logs -n kyma-system deployments/api-gateway-controller-manager || true) > logs/api-gateway-controller-manager.log + (kubectl logs -n istio-system deployments/istio-ingressgateway || true) > logs/istio-ingressgateway.log + (kubectl logs -n istio-system deployments/istiod || true) > logs/istiod.log + (kubectl describe --all-namespaces apirules.gateway.kyma-project.io -oyaml || true) > logs/apirules-dump.yaml - name: Uploads artifacts uses: actions/upload-artifact@v4 with: name: html-reports-${{ github.job }} path: tests/integration/reports/ + - name: Uploads logs + uses: actions/upload-artifact@v4 + if: failure() + with: + name: logs-${{ github.job }} + path: logs/ diff --git a/tests/integration/pkg/helpers/api_rule.go b/tests/integration/pkg/helpers/api_rule.go index dcad9eae9..bbff043cf 100644 --- a/tests/integration/pkg/helpers/api_rule.go +++ b/tests/integration/pkg/helpers/api_rule.go @@ -7,12 +7,14 @@ import ( "github.com/kyma-project/api-gateway/tests/integration/pkg/resource" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/client-go/dynamic" + "log" ) type apiRuleStatus struct { Status struct { APIRuleStatus struct { - Code string `json:"code"` + Code string `json:"code"` + Description string `json:"desc"` } `json:"APIRuleStatus"` } `json:"status"` } @@ -39,7 +41,6 @@ func ApplyApiRule(toExecute RetryableApiRule, onRetry RetryableApiRule, k8sClien if err != nil { return err } - js, err := json.Marshal(res) if err != nil { return err @@ -49,7 +50,8 @@ func ApplyApiRule(toExecute RetryableApiRule, onRetry RetryableApiRule, k8sClien return err } if apiStatus.Status.APIRuleStatus.Code == "ERROR" { - return errors.New("APIRule status not ok") + log.Println("APIRule status not ok: " + apiStatus.Status.APIRuleStatus.Description) + return errors.New("APIRule status not ok: " + apiStatus.Status.APIRuleStatus.Description) } return nil }, retryOpts...) @@ -75,7 +77,8 @@ func UpdateApiRule(resourceManager *resource.Manager, k8sClient dynamic.Interfac return err } if status.Status.APIRuleStatus.Code == "ERROR" || status.Status.APIRuleStatus.Code == "Error" { - return errors.New("APIRule status not ok") + log.Println("APIRule status not ok: " + status.Status.APIRuleStatus.Description) + return errors.New("APIRule status not ok: " + status.Status.APIRuleStatus.Description) } return nil } From 8763e69872c27b759c807eba99ded06518e65a60 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 07:40:28 +0200 Subject: [PATCH 04/11] Bump cypress from 13.12.0 to 13.13.0 in /tests/ui/tests (#1144) Bumps [cypress](https://github.com/cypress-io/cypress) from 13.12.0 to 13.13.0. - [Release notes](https://github.com/cypress-io/cypress/releases) - [Changelog](https://github.com/cypress-io/cypress/blob/develop/CHANGELOG.md) - [Commits](https://github.com/cypress-io/cypress/compare/v13.12.0...v13.13.0) --- updated-dependencies: - dependency-name: cypress dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Tim Riffer --- tests/ui/tests/package-lock.json | 210 +++---------------------------- tests/ui/tests/package.json | 2 +- 2 files changed, 18 insertions(+), 194 deletions(-) diff --git a/tests/ui/tests/package-lock.json b/tests/ui/tests/package-lock.json index a9499e642..b85ec7a2d 100644 --- a/tests/ui/tests/package-lock.json +++ b/tests/ui/tests/package-lock.json @@ -7,7 +7,7 @@ "name": "ui-tests", "devDependencies": { "@kubernetes/client-node": "0.21.0", - "cypress": "13.12.0", + "cypress": "13.13.0", "cypress-file-upload": "5.0.8", "js-yaml": "4.1.0", "typescript": "5.5.3" @@ -556,16 +556,6 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -803,12 +793,6 @@ "node": ">=4.0.0" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -830,9 +814,9 @@ } }, "node_modules/cypress": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.12.0.tgz", - "integrity": "sha512-udzS2JilmI9ApO/UuqurEwOvThclin5ntz7K0BtnHBs+tg2Bl9QShLISXpSEMDv/u8b6mqdoAdyKeZiSqKWL8g==", + "version": "13.13.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.13.0.tgz", + "integrity": "sha512-ou/MQUDq4tcDJI2FsPaod2FZpex4kpIK43JJlcBgWrX8WX7R/05ZxGTuxedOuZBfxjZxja+fbijZGyxiLP6CFA==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -875,7 +859,7 @@ "request-progress": "^3.0.0", "semver": "^7.5.3", "supports-color": "^8.1.1", - "tmp": "~0.2.1", + "tmp": "~0.2.3", "untildify": "^4.0.0", "yauzl": "^2.10.0" }, @@ -1210,12 +1194,6 @@ "node": ">=10" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -1277,26 +1255,6 @@ "assert-plus": "^1.0.0" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/global-dirs": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", @@ -1462,22 +1420,6 @@ "node": ">=8" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, "node_modules/ini": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", @@ -1849,18 +1791,6 @@ "node": ">=6" } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -2088,15 +2018,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -2331,21 +2252,6 @@ "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", "dev": true }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/rxjs": { "version": "7.8.0", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", @@ -2623,15 +2529,12 @@ "dev": true }, "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, "engines": { - "node": ">=8.17.0" + "node": ">=14.14" } }, "node_modules/tough-cookie": { @@ -3283,16 +3186,6 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -3456,12 +3349,6 @@ "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", "dev": true }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -3480,9 +3367,9 @@ } }, "cypress": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.12.0.tgz", - "integrity": "sha512-udzS2JilmI9ApO/UuqurEwOvThclin5ntz7K0BtnHBs+tg2Bl9QShLISXpSEMDv/u8b6mqdoAdyKeZiSqKWL8g==", + "version": "13.13.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.13.0.tgz", + "integrity": "sha512-ou/MQUDq4tcDJI2FsPaod2FZpex4kpIK43JJlcBgWrX8WX7R/05ZxGTuxedOuZBfxjZxja+fbijZGyxiLP6CFA==", "dev": true, "requires": { "@cypress/request": "^3.0.0", @@ -3524,7 +3411,7 @@ "request-progress": "^3.0.0", "semver": "^7.5.3", "supports-color": "^8.1.1", - "tmp": "~0.2.1", + "tmp": "~0.2.3", "untildify": "^4.0.0", "yauzl": "^2.10.0" } @@ -3771,12 +3658,6 @@ "universalify": "^2.0.0" } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, "function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -3823,20 +3704,6 @@ "assert-plus": "^1.0.0" } }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, "global-dirs": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", @@ -3942,22 +3809,6 @@ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, "ini": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", @@ -4226,15 +4077,6 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, "minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -4392,12 +4234,6 @@ "aggregate-error": "^3.0.0" } }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -4588,15 +4424,6 @@ "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", "dev": true }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, "rxjs": { "version": "7.8.0", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", @@ -4798,13 +4625,10 @@ "dev": true }, "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - } + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "dev": true }, "tough-cookie": { "version": "2.5.0", diff --git a/tests/ui/tests/package.json b/tests/ui/tests/package.json index 8d169d22c..9547c9ccd 100644 --- a/tests/ui/tests/package.json +++ b/tests/ui/tests/package.json @@ -9,7 +9,7 @@ "start-k3d": "./scripts/k3d-local-dev.sh" }, "devDependencies": { - "cypress": "13.12.0", + "cypress": "13.13.0", "cypress-file-upload": "5.0.8", "js-yaml": "4.1.0", "typescript": "5.5.3", From 88cd23747bbb2addf05024b31614f85d8758efeb Mon Sep 17 00:00:00 2001 From: Bartosz Chwila <103247439+barchw@users.noreply.github.com> Date: Thu, 11 Jul 2024 12:02:27 +0200 Subject: [PATCH 05/11] Replace all context TODO (#1158) --- .../api_controller_integration_test.go | 230 +++++++++--------- ...rule_controller_status_integration_test.go | 24 +- ..._controller_validation_integration_test.go | 6 +- .../apirule_timeout_integration_test.go | 26 +- controllers/gateway/suite_test.go | 16 +- .../apigateway_controller_integration_test.go | 20 +- .../operator/apigateway_controller_test.go | 10 +- controllers/operator/suite_test.go | 4 +- controllers/status_test.go | 8 +- internal/clusterconfig/clusterconfig_test.go | 6 +- internal/helpers/service_test.go | 10 +- internal/processing/cleaner_test.go | 10 +- .../authorization_policy_processor_test.go | 62 ++--- .../processors/ory/reconciliation_test.go | 4 +- internal/resources/resources_test.go | 14 +- internal/validation/v1beta1/v1beta1_test.go | 52 ++-- tests/integration/pkg/hooks/api-gateway.go | 2 +- tests/integration/pkg/resource/manager.go | 4 +- .../testsuites/custom-domain/testsuite.go | 2 +- 19 files changed, 255 insertions(+), 255 deletions(-) diff --git a/controllers/gateway/api_controller_integration_test.go b/controllers/gateway/api_controller_integration_test.go index c16dede9d..f726aaaef 100644 --- a/controllers/gateway/api_controller_integration_test.go +++ b/controllers/gateway/api_controller_integration_test.go @@ -70,8 +70,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -83,12 +83,12 @@ var _ = Describe("APIRule Controller", Serial, func() { By("Updating APIRule") existingInstance := gatewayv1beta1.APIRule{} - Expect(c.Get(context.TODO(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &existingInstance)).Should(Succeed()) + Expect(c.Get(context.Background(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &existingInstance)).Should(Succeed()) serviceHost = fmt.Sprintf("%s.local.kyma.dev", serviceName) existingInstance.Spec.Host = &serviceHost - Expect(c.Update(context.TODO(), &existingInstance)).Should(Succeed()) + Expect(c.Update(context.Background(), &existingInstance)).Should(Succeed()) By("Verifying APIRule after update") @@ -136,7 +136,7 @@ var _ = Describe("APIRule Controller", Serial, func() { }, } - Expect(c.Create(context.TODO(), &gateway)).Should(Succeed()) + Expect(c.Create(context.Background(), &gateway)).Should(Succeed()) By("Creating APIRule") @@ -150,8 +150,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -194,8 +194,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRulev2alpha1Teardown(apiRule) serviceTeardown(svc) @@ -217,8 +217,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRulev2alpha1Teardown(apiRule) serviceTeardown(svc) @@ -241,8 +241,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRulev2alpha1Teardown(apiRule) serviceTeardown(svc) @@ -264,8 +264,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRulev2alpha1Teardown(apiRule) serviceTeardown(svc) @@ -283,8 +283,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - err := c.Create(context.TODO(), apiRule) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + err := c.Create(context.Background(), apiRule) defer func() { apiRulev2alpha1Teardown(apiRule) serviceTeardown(svc) @@ -306,8 +306,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - err := c.Create(context.TODO(), apiRule) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + err := c.Create(context.Background(), apiRule) defer func() { apiRulev2alpha1Teardown(apiRule) serviceTeardown(svc) @@ -333,8 +333,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - err := c.Create(context.TODO(), apiRule) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + err := c.Create(context.Background(), apiRule) defer func() { apiRulev2alpha1Teardown(apiRule) serviceTeardown(svc) @@ -357,8 +357,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - err := c.Create(context.TODO(), apiRule) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + err := c.Create(context.Background(), apiRule) defer func() { apiRulev2alpha1Teardown(apiRule) serviceTeardown(svc) @@ -393,8 +393,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -418,7 +418,7 @@ var _ = Describe("APIRule Controller", Serial, func() { By("Updating APIRule") existingInstance := gatewayv1beta1.APIRule{} - Expect(c.Get(context.TODO(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &existingInstance)).Should(Succeed()) + Expect(c.Get(context.Background(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &existingInstance)).Should(Succeed()) rule4 := testRule("/rule4", methodsPost, defaultMutators, noConfigHandler("cookie_session")) existingInstance.Spec.Rules = []gatewayv1beta1.Rule{rule1, rule4} @@ -428,12 +428,12 @@ var _ = Describe("APIRule Controller", Serial, func() { existingInstance.Spec.Service.Port = &newServicePort svcNew := testService(newServiceName, testNamespace, newServicePort) - Expect(c.Create(context.TODO(), svcNew)).Should(Succeed()) + Expect(c.Create(context.Background(), svcNew)).Should(Succeed()) defer func() { serviceTeardown(svcNew) }() - Expect(c.Update(context.TODO(), &existingInstance)).Should(Succeed()) + Expect(c.Update(context.Background(), &existingInstance)).Should(Succeed()) By("Verifying APIRule after update") @@ -469,8 +469,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -483,7 +483,7 @@ var _ = Describe("APIRule Controller", Serial, func() { By("Verifying created virtual service") vsList := networkingv1beta1.VirtualServiceList{} Eventually(func(g Gomega) { - g.Expect(c.List(context.TODO(), &vsList, matchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &vsList, matchingLabels)).Should(Succeed()) g.Expect(vsList.Items).To(HaveLen(1)) vs := vsList.Items[0] @@ -572,8 +572,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -586,7 +586,7 @@ var _ = Describe("APIRule Controller", Serial, func() { By("Verifying created virtual service") vsList := networkingv1beta1.VirtualServiceList{} Eventually(func(g Gomega) { - g.Expect(c.List(context.TODO(), &vsList, matchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &vsList, matchingLabels)).Should(Succeed()) g.Expect(vsList.Items).To(HaveLen(1)) vs := vsList.Items[0] @@ -714,8 +714,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -728,7 +728,7 @@ var _ = Describe("APIRule Controller", Serial, func() { By("Verifying virtual service") vsList := networkingv1beta1.VirtualServiceList{} Eventually(func(g Gomega) { - g.Expect(c.List(context.TODO(), &vsList, ApiRuleNameMatchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &vsList, ApiRuleNameMatchingLabels)).Should(Succeed()) g.Expect(vsList.Items).To(HaveLen(1)) vs := vsList.Items[0] @@ -754,7 +754,7 @@ var _ = Describe("APIRule Controller", Serial, func() { By("Verifying request authentication") raList := securityv1beta1.RequestAuthenticationList{} Eventually(func(g Gomega) { - g.Expect(c.List(context.TODO(), &raList, ApiRuleNameMatchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &raList, ApiRuleNameMatchingLabels)).Should(Succeed()) g.Expect(raList.Items).To(HaveLen(1)) ra := raList.Items[0] @@ -776,7 +776,7 @@ var _ = Describe("APIRule Controller", Serial, func() { apList := securityv1beta1.AuthorizationPolicyList{} Eventually(func(g Gomega) { - g.Expect(c.List(context.TODO(), &apList, ApiRuleNameMatchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &apList, ApiRuleNameMatchingLabels)).Should(Succeed()) g.Expect(apList.Items).To(HaveLen(2)) hasAuthorizationPolicyWithOperationPath := func(apList []*securityv1beta1.AuthorizationPolicy, operationPath string, assertWhen func(*securityv1beta1.AuthorizationPolicy)) { @@ -843,8 +843,8 @@ var _ = Describe("APIRule Controller", Serial, func() { By(fmt.Sprintf("Creating APIRule %s", apiRuleName)) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -852,7 +852,7 @@ var _ = Describe("APIRule Controller", Serial, func() { Eventually(func(g Gomega) { createdApiRule := gatewayv1beta1.APIRule{} - g.Expect(c.Get(context.TODO(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &createdApiRule)).Should(Succeed()) + g.Expect(c.Get(context.Background(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &createdApiRule)).Should(Succeed()) g.Expect(createdApiRule.Status.APIRuleStatus).NotTo(BeNil()) g.Expect(createdApiRule.Status.APIRuleStatus.Code).To(Equal(gatewayv1beta1.StatusOK)) g.Expect(createdApiRule.Status.APIRuleStatus.Code).To(Equal(gatewayv1beta1.StatusOK)) @@ -863,7 +863,7 @@ var _ = Describe("APIRule Controller", Serial, func() { // when updatedApiRule := gatewayv1beta1.APIRule{} - Expect(c.Get(context.TODO(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &updatedApiRule)).Should(Succeed()) + Expect(c.Get(context.Background(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &updatedApiRule)).Should(Succeed()) updatedAuthorizations := []*gatewayv1beta1.JwtAuthorization{ { @@ -880,14 +880,14 @@ var _ = Describe("APIRule Controller", Serial, func() { updatedApiRule.Spec.Rules = []gatewayv1beta1.Rule{ruleWithScopes} By(fmt.Sprintf("Updating APIRule %s with new Authorizations for /img path", apiRuleName)) - Expect(c.Update(context.TODO(), &updatedApiRule)).Should(Succeed()) + Expect(c.Update(context.Background(), &updatedApiRule)).Should(Succeed()) // then matchingLabels := matchingLabelsFunc(apiRuleName, testNamespace) Eventually(func(g Gomega) { apList := securityv1beta1.AuthorizationPolicyList{} - g.Expect(c.List(context.TODO(), &apList, matchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &apList, matchingLabels)).Should(Succeed()) g.Expect(apList.Items).To(HaveLen(3)) scopeAScopeCMatcher := getAuthorizationPolicyWhenScopeMatcher("scope-a", "scope-c") @@ -918,8 +918,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc.Spec.Selector["custom"] = serviceName // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -933,7 +933,7 @@ var _ = Describe("APIRule Controller", Serial, func() { raList := securityv1beta1.RequestAuthenticationList{} Eventually(func(g Gomega) { - g.Expect(c.List(context.TODO(), &raList, ApiRuleNameMatchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &raList, ApiRuleNameMatchingLabels)).Should(Succeed()) g.Expect(raList.Items).To(HaveLen(1)) g.Expect(raList.Items[0].Spec.Selector.MatchLabels).To(HaveLen(1)) g.Expect(raList.Items[0].Spec.Selector.MatchLabels).To(HaveKeyWithValue("custom", serviceName)) @@ -943,7 +943,7 @@ var _ = Describe("APIRule Controller", Serial, func() { apList := securityv1beta1.AuthorizationPolicyList{} Eventually(func(g Gomega) { - g.Expect(c.List(context.TODO(), &apList, ApiRuleNameMatchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &apList, ApiRuleNameMatchingLabels)).Should(Succeed()) g.Expect(apList.Items).To(HaveLen(1)) g.Expect(apList.Items[0].Spec.Selector.MatchLabels).To(HaveLen(1)) g.Expect(apList.Items[0].Spec.Selector.MatchLabels).To(HaveKeyWithValue("custom", serviceName)) @@ -965,8 +965,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc.Spec.Selector["second-custom"] = "blah" // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -980,7 +980,7 @@ var _ = Describe("APIRule Controller", Serial, func() { raList := securityv1beta1.RequestAuthenticationList{} Eventually(func(g Gomega) { - g.Expect(c.List(context.TODO(), &raList, ApiRuleNameMatchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &raList, ApiRuleNameMatchingLabels)).Should(Succeed()) g.Expect(raList.Items).To(HaveLen(1)) g.Expect(raList.Items[0].Spec.Selector.MatchLabels).To(HaveLen(2)) g.Expect(raList.Items[0].Spec.Selector.MatchLabels).To(HaveKeyWithValue("custom", serviceName)) @@ -991,7 +991,7 @@ var _ = Describe("APIRule Controller", Serial, func() { apList := securityv1beta1.AuthorizationPolicyList{} Eventually(func(g Gomega) { - g.Expect(c.List(context.TODO(), &apList, ApiRuleNameMatchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &apList, ApiRuleNameMatchingLabels)).Should(Succeed()) g.Expect(apList.Items).To(HaveLen(1)) g.Expect(apList.Items[0].Spec.Selector.MatchLabels).To(HaveLen(2)) g.Expect(apList.Items[0].Spec.Selector.MatchLabels).To(HaveKeyWithValue("custom", serviceName)) @@ -1022,8 +1022,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -1036,7 +1036,7 @@ var _ = Describe("APIRule Controller", Serial, func() { By("Verifying created virtual service") vsList := networkingv1beta1.VirtualServiceList{} Eventually(func(g Gomega) { - g.Expect(c.List(context.TODO(), &vsList, matchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &vsList, matchingLabels)).Should(Succeed()) g.Expect(vsList.Items).To(HaveLen(1)) vs := vsList.Items[0] @@ -1154,8 +1154,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -1168,7 +1168,7 @@ var _ = Describe("APIRule Controller", Serial, func() { By("Verifying created virtual service") vsList := networkingv1beta1.VirtualServiceList{} Eventually(func(g Gomega) { - g.Expect(c.List(context.TODO(), &vsList, matchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &vsList, matchingLabels)).Should(Succeed()) g.Expect(vsList.Items).To(HaveLen(1)) vs := vsList.Items[0] @@ -1227,8 +1227,8 @@ var _ = Describe("APIRule Controller", Serial, func() { By("Creating ApiRule with Rule using Ory JWT handler configuration") // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -1242,7 +1242,7 @@ var _ = Describe("APIRule Controller", Serial, func() { // then Eventually(func(g Gomega) { apiRule := gatewayv1beta1.APIRule{} - g.Expect(c.Get(context.TODO(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &apiRule)).Should(Succeed()) + g.Expect(c.Get(context.Background(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &apiRule)).Should(Succeed()) g.Expect(apiRule.Status.APIRuleStatus.Code).To(Equal(gatewayv1beta1.StatusError)) g.Expect(apiRule.Status.APIRuleStatus.Description).To(ContainSubstring("Multiple validation errors")) @@ -1264,8 +1264,8 @@ var _ = Describe("APIRule Controller", Serial, func() { By("Creating ApiRule with Rule using Ory JWT handler") // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -1280,9 +1280,9 @@ var _ = Describe("APIRule Controller", Serial, func() { istioJwtRule := testRule("/img", methodsGet, nil, testIstioJWTHandler(testIssuer, testJwksUri)) Eventually(func(g Gomega) { updatedApiRule := gatewayv1beta1.APIRule{} - g.Expect(c.Get(context.TODO(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &updatedApiRule)).Should(Succeed()) + g.Expect(c.Get(context.Background(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &updatedApiRule)).Should(Succeed()) updatedApiRule.Spec.Rules = []gatewayv1beta1.Rule{istioJwtRule} - g.Expect(c.Update(context.TODO(), &updatedApiRule)).Should(Succeed()) + g.Expect(c.Update(context.Background(), &updatedApiRule)).Should(Succeed()) }, eventuallyTimeout).Should(Succeed()) // then @@ -1314,8 +1314,8 @@ var _ = Describe("APIRule Controller", Serial, func() { By("Creating ApiRule with Rule using Istio JWT handler configuration") // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -1330,7 +1330,7 @@ var _ = Describe("APIRule Controller", Serial, func() { // then Eventually(func(g Gomega) { apiRule := gatewayv1beta1.APIRule{} - g.Expect(c.Get(context.TODO(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &apiRule)).Should(Succeed()) + g.Expect(c.Get(context.Background(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &apiRule)).Should(Succeed()) g.Expect(apiRule.Status.APIRuleStatus.Code).To(Equal(gatewayv1beta1.StatusError)) g.Expect(apiRule.Status.APIRuleStatus.Description).To(ContainSubstring("Validation error")) @@ -1353,8 +1353,8 @@ var _ = Describe("APIRule Controller", Serial, func() { By("Creating ApiRule with Rule using JWT handler configuration") // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -1367,7 +1367,7 @@ var _ = Describe("APIRule Controller", Serial, func() { By("Waiting until reconciliation of API Rule has finished") Eventually(func(g Gomega) { apiRule := gatewayv1beta1.APIRule{} - g.Expect(c.Get(context.TODO(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &apiRule)).Should(Succeed()) + g.Expect(c.Get(context.Background(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &apiRule)).Should(Succeed()) g.Expect(apiRule.Status.APIRuleStatus).NotTo(BeNil()) g.Expect(apiRule.Status.APIRuleStatus.Code).To(Equal(gatewayv1beta1.StatusError)) }, eventuallyTimeout).Should(Succeed()) @@ -1377,9 +1377,9 @@ var _ = Describe("APIRule Controller", Serial, func() { Eventually(func(g Gomega) { oryJwtRule := testRule("/img", methodsGet, nil, testOryJWTHandler(testIssuer, defaultScopes)) updatedApiRule := gatewayv1beta1.APIRule{} - Expect(c.Get(context.TODO(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &updatedApiRule)).Should(Succeed()) + Expect(c.Get(context.Background(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &updatedApiRule)).Should(Succeed()) updatedApiRule.Spec.Rules = []gatewayv1beta1.Rule{oryJwtRule} - Expect(c.Update(context.TODO(), &updatedApiRule)).Should(Succeed()) + Expect(c.Update(context.Background(), &updatedApiRule)).Should(Succeed()) }, eventuallyTimeout).Should(Succeed()) // then @@ -1406,13 +1406,13 @@ var _ = Describe("APIRule Controller", Serial, func() { By(fmt.Sprintf("Creating virtual service for host %s", serviceHost)) vs := virtualService(vsName, serviceHost) - Expect(c.Create(context.TODO(), vs)).Should(Succeed()) + Expect(c.Create(context.Background(), vs)).Should(Succeed()) defer func() { By(fmt.Sprintf("Deleting VirtualService %s as part of teardown", vs.Name)) Eventually(func(g Gomega) { - _ = c.Delete(context.TODO(), vs) + _ = c.Delete(context.Background(), vs) v := networkingv1beta1.VirtualService{} - err := c.Get(context.TODO(), client.ObjectKey{Name: vs.Name, Namespace: testNamespace}, &v) + err := c.Get(context.Background(), client.ObjectKey{Name: vs.Name, Namespace: testNamespace}, &v) g.Expect(errors.IsNotFound(err)).To(BeTrue()) }, eventuallyTimeout).Should(Succeed()) }() @@ -1420,7 +1420,7 @@ var _ = Describe("APIRule Controller", Serial, func() { By("Verifying virtual service has been created") Eventually(func(g Gomega) { createdVs := networkingv1beta1.VirtualService{} - g.Expect(c.Get(context.TODO(), client.ObjectKey{Name: vsName, Namespace: testNamespace}, &createdVs)).Should(Succeed()) + g.Expect(c.Get(context.Background(), client.ObjectKey{Name: vsName, Namespace: testNamespace}, &createdVs)).Should(Succeed()) }, eventuallyTimeout).Should(Succeed()) apiRuleLabelMatcher := matchingLabelsFunc(apiRuleName, testNamespace) @@ -1431,8 +1431,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -1468,8 +1468,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -1479,13 +1479,13 @@ var _ = Describe("APIRule Controller", Serial, func() { By(fmt.Sprintf("Creating virtual service for host %s", serviceHost)) vs := virtualService(vsName, serviceHost) - Expect(c.Create(context.TODO(), vs)).Should(Succeed()) + Expect(c.Create(context.Background(), vs)).Should(Succeed()) defer func() { By(fmt.Sprintf("Deleting VirtualService %s as part of teardown", vs.Name)) Eventually(func(g Gomega) { - _ = c.Delete(context.TODO(), vs) + _ = c.Delete(context.Background(), vs) v := networkingv1beta1.VirtualService{} - err := c.Get(context.TODO(), client.ObjectKey{Name: vs.Name, Namespace: testNamespace}, &v) + err := c.Get(context.Background(), client.ObjectKey{Name: vs.Name, Namespace: testNamespace}, &v) g.Expect(errors.IsNotFound(err)).To(BeTrue()) }, eventuallyTimeout).Should(Succeed()) }() @@ -1493,7 +1493,7 @@ var _ = Describe("APIRule Controller", Serial, func() { By("Verifying virtual service has been created") Eventually(func(g Gomega) { createdVs := networkingv1beta1.VirtualService{} - g.Expect(c.Get(context.TODO(), client.ObjectKey{Name: vsName, Namespace: testNamespace}, &createdVs)).Should(Succeed()) + g.Expect(c.Get(context.Background(), client.ObjectKey{Name: vsName, Namespace: testNamespace}, &createdVs)).Should(Succeed()) }, eventuallyTimeout).Should(Succeed()) By("Waiting until APIRule is reconciled after error") @@ -1502,7 +1502,7 @@ var _ = Describe("APIRule Controller", Serial, func() { By("Verifying APIRule status description") Eventually(func(g Gomega) { expectedApiRule := gatewayv1beta1.APIRule{} - g.Expect(c.Get(context.TODO(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &expectedApiRule)).Should(Succeed()) + g.Expect(c.Get(context.Background(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &expectedApiRule)).Should(Succeed()) g.Expect(expectedApiRule.Status.APIRuleStatus).NotTo(BeNil()) g.Expect(expectedApiRule.Status.APIRuleStatus.Description).To(ContainSubstring("This host is occupied by another Virtual Service")) }, eventuallyTimeout).Should(Succeed()) @@ -1520,8 +1520,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -1539,22 +1539,22 @@ var _ = Describe("APIRule Controller", Serial, func() { By("Deleting Virtual Service") Eventually(func(g Gomega) { vsList := networkingv1beta1.VirtualServiceList{} - g.Expect(c.List(context.TODO(), &vsList, apiRuleNameMatchingLabels)).Should(Succeed()) - g.Expect(c.Delete(context.TODO(), vsList.Items[0])).Should(Succeed()) + g.Expect(c.List(context.Background(), &vsList, apiRuleNameMatchingLabels)).Should(Succeed()) + g.Expect(c.Delete(context.Background(), vsList.Items[0])).Should(Succeed()) }, eventuallyTimeout).Should(Succeed()) By("Deleting Request Authentication") raList := securityv1beta1.RequestAuthenticationList{} Eventually(func(g Gomega) { - g.Expect(c.List(context.TODO(), &raList, apiRuleNameMatchingLabels)).Should(Succeed()) - g.Expect(c.Delete(context.TODO(), raList.Items[0])).Should(Succeed()) + g.Expect(c.List(context.Background(), &raList, apiRuleNameMatchingLabels)).Should(Succeed()) + g.Expect(c.Delete(context.Background(), raList.Items[0])).Should(Succeed()) }, eventuallyTimeout).Should(Succeed()) By("Deleting Authorization Policy") apList := securityv1beta1.AuthorizationPolicyList{} Eventually(func(g Gomega) { - g.Expect(c.List(context.TODO(), &apList, apiRuleNameMatchingLabels)).Should(Succeed()) - g.Expect(c.Delete(context.TODO(), apList.Items[0])).Should(Succeed()) + g.Expect(c.List(context.Background(), &apList, apiRuleNameMatchingLabels)).Should(Succeed()) + g.Expect(c.Delete(context.Background(), apList.Items[0])).Should(Succeed()) }, eventuallyTimeout).Should(Succeed()) By("Verifying deleted resources are recreated") @@ -1575,8 +1575,8 @@ var _ = Describe("APIRule Controller", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -1602,7 +1602,7 @@ func verifyVirtualServiceCount(c client.Client, option client.ListOption, count By(fmt.Sprintf("Verifying %d Virtual Service exist", count)) Eventually(func(g Gomega) { vsList := networkingv1beta1.VirtualServiceList{} - g.Expect(c.List(context.TODO(), &vsList, option)).Should(Succeed()) + g.Expect(c.List(context.Background(), &vsList, option)).Should(Succeed()) g.Expect(vsList.Items).To(HaveLen(count)) }, eventuallyTimeout).Should(Succeed()) } @@ -1611,7 +1611,7 @@ func verifyRequestAuthenticationCount(c client.Client, option client.ListOption, By(fmt.Sprintf("Verifying %d Request Authentication exist", count)) Eventually(func(g Gomega) { raList := securityv1beta1.RequestAuthenticationList{} - g.Expect(c.List(context.TODO(), &raList, option)).Should(Succeed()) + g.Expect(c.List(context.Background(), &raList, option)).Should(Succeed()) g.Expect(raList.Items).To(HaveLen(count)) }, eventuallyTimeout).Should(Succeed()) } @@ -1620,7 +1620,7 @@ func verifyAuthorizationPolicyCount(c client.Client, option client.ListOption, c By(fmt.Sprintf("Verifying %d Authorization Policy exist", count)) Eventually(func(g Gomega) { apList := securityv1beta1.AuthorizationPolicyList{} - g.Expect(c.List(context.TODO(), &apList, option)).Should(Succeed()) + g.Expect(c.List(context.Background(), &apList, option)).Should(Succeed()) g.Expect(apList.Items).To(HaveLen(count)) }, eventuallyTimeout).Should(Succeed()) } @@ -1853,7 +1853,7 @@ func generateTestName(name string, length int) string { func getRuleList(g Gomega, matchingLabels client.ListOption) []rulev1alpha1.Rule { res := rulev1alpha1.RuleList{} - g.Expect(c.List(context.TODO(), &res, matchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &res, matchingLabels)).Should(Succeed()) return res.Items } @@ -1912,18 +1912,18 @@ func matchingLabelsFunc(apiRuleName, namespace string) client.ListOption { func updateJwtHandlerTo(jwtHandler string) { cm := &corev1.ConfigMap{} - Expect(c.Get(context.TODO(), client.ObjectKey{Name: helpers.CM_NAME, Namespace: helpers.CM_NS}, cm)).Should(Succeed()) + Expect(c.Get(context.Background(), client.ObjectKey{Name: helpers.CM_NAME, Namespace: helpers.CM_NS}, cm)).Should(Succeed()) if !strings.Contains(cm.Data[helpers.CM_KEY], jwtHandler) { By(fmt.Sprintf("Updating JWT handler config map to %s", jwtHandler)) cm.Data = map[string]string{ helpers.CM_KEY: fmt.Sprintf("jwtHandler: %s", jwtHandler), } - Expect(c.Update(context.TODO(), cm)).To(Succeed()) + Expect(c.Update(context.Background(), cm)).To(Succeed()) By("Waiting until config map is updated") Eventually(func(g Gomega) { - g.Expect(c.Get(context.TODO(), client.ObjectKey{Name: cm.Name, Namespace: cm.Namespace}, cm)).Should(Succeed()) + g.Expect(c.Get(context.Background(), client.ObjectKey{Name: cm.Name, Namespace: cm.Namespace}, cm)).Should(Succeed()) g.Expect(cm.Data).To(HaveKeyWithValue(helpers.CM_KEY, fmt.Sprintf("jwtHandler: %s", jwtHandler))) }, eventuallyTimeout).Should(Succeed()) } @@ -1958,17 +1958,17 @@ func getAuthorizationPolicyWhenScopeMatcher(firstScope, secondScope string) gome func deleteApiRule(apiRule *gatewayv1beta1.APIRule) { By(fmt.Sprintf("Deleting ApiRule %s", apiRule.Name)) - Expect(c.Delete(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Delete(context.Background(), apiRule)).Should(Succeed()) Eventually(func(g Gomega) { a := gatewayv1beta1.APIRule{} - err := c.Get(context.TODO(), client.ObjectKey{Name: apiRule.Name, Namespace: testNamespace}, &a) + err := c.Get(context.Background(), client.ObjectKey{Name: apiRule.Name, Namespace: testNamespace}, &a) g.Expect(errors.IsNotFound(err)).To(BeTrue()) }, eventuallyTimeout).Should(Succeed()) } func apiRuleTeardown(apiRule *gatewayv1beta1.APIRule) { By(fmt.Sprintf("Deleting ApiRule %s as part of teardown", apiRule.Name)) - err := c.Delete(context.TODO(), apiRule) + err := c.Delete(context.Background(), apiRule) if err != nil { Expect(errors.IsNotFound(err)).To(BeTrue()) @@ -1976,14 +1976,14 @@ func apiRuleTeardown(apiRule *gatewayv1beta1.APIRule) { Eventually(func(g Gomega) { a := gatewayv1beta1.APIRule{} - err := c.Get(context.TODO(), client.ObjectKey{Name: apiRule.Name, Namespace: testNamespace}, &a) + err := c.Get(context.Background(), client.ObjectKey{Name: apiRule.Name, Namespace: testNamespace}, &a) g.Expect(errors.IsNotFound(err)).To(BeTrue()) }, eventuallyTimeout).Should(Succeed()) } func apiRulev2alpha1Teardown(apiRule *gatewayv2alpha1.APIRule) { By(fmt.Sprintf("Deleting ApiRule %s as part of teardown", apiRule.Name)) - err := c.Delete(context.TODO(), apiRule) + err := c.Delete(context.Background(), apiRule) if err != nil { Expect(errors.IsNotFound(err)).To(BeTrue()) @@ -1991,14 +1991,14 @@ func apiRulev2alpha1Teardown(apiRule *gatewayv2alpha1.APIRule) { Eventually(func(g Gomega) { a := gatewayv2alpha1.APIRule{} - err := c.Get(context.TODO(), client.ObjectKey{Name: apiRule.Name, Namespace: testNamespace}, &a) + err := c.Get(context.Background(), client.ObjectKey{Name: apiRule.Name, Namespace: testNamespace}, &a) g.Expect(errors.IsNotFound(err)).To(BeTrue()) }, eventuallyTimeout).Should(Succeed()) } func serviceTeardown(svc *corev1.Service) { By(fmt.Sprintf("Deleting Service %s as part of teardown", svc.Name)) - err := c.Delete(context.TODO(), svc) + err := c.Delete(context.Background(), svc) if err != nil { Expect(errors.IsNotFound(err)).To(BeTrue()) @@ -2006,7 +2006,7 @@ func serviceTeardown(svc *corev1.Service) { Eventually(func(g Gomega) { a := corev1.Service{} - err := c.Get(context.TODO(), client.ObjectKey{Name: svc.Name, Namespace: testNamespace}, &a) + err := c.Get(context.Background(), client.ObjectKey{Name: svc.Name, Namespace: testNamespace}, &a) g.Expect(errors.IsNotFound(err)).To(BeTrue()) }, eventuallyTimeout).Should(Succeed()) } @@ -2015,7 +2015,7 @@ func expectApiRuleStatus(apiRuleName string, statusCode gatewayv1beta1.StatusCod By(fmt.Sprintf("Verifying that ApiRule %s has status %s", apiRuleName, statusCode)) Eventually(func(g Gomega) { expectedApiRule := gatewayv1beta1.APIRule{} - g.Expect(c.Get(context.TODO(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &expectedApiRule)).Should(Succeed()) + g.Expect(c.Get(context.Background(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &expectedApiRule)).Should(Succeed()) g.Expect(expectedApiRule.Status.APIRuleStatus).NotTo(BeNil()) g.Expect(expectedApiRule.Status.APIRuleStatus.Code).To(Equal(statusCode)) }, eventuallyTimeout).Should(Succeed()) @@ -2023,10 +2023,10 @@ func expectApiRuleStatus(apiRuleName string, statusCode gatewayv1beta1.StatusCod func deleteVirtualService(vs *networkingv1beta1.VirtualService) { By(fmt.Sprintf("Deleting virtual service %s", vs.Name)) - Expect(c.Delete(context.TODO(), vs)).Should(Succeed()) + Expect(c.Delete(context.Background(), vs)).Should(Succeed()) Eventually(func(g Gomega) { v := networkingv1beta1.VirtualService{} - err := c.Get(context.TODO(), client.ObjectKey{Name: vs.Name, Namespace: testNamespace}, &v) + err := c.Get(context.Background(), client.ObjectKey{Name: vs.Name, Namespace: testNamespace}, &v) g.Expect(errors.IsNotFound(err)).To(BeTrue()) }, eventuallyTimeout).Should(Succeed()) } diff --git a/controllers/gateway/apirule_controller_status_integration_test.go b/controllers/gateway/apirule_controller_status_integration_test.go index ed03c60fc..3169b2dbc 100644 --- a/controllers/gateway/apirule_controller_status_integration_test.go +++ b/controllers/gateway/apirule_controller_status_integration_test.go @@ -38,8 +38,8 @@ var _ = Describe("Resource status", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), instance)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), instance)).Should(Succeed()) defer func() { apiRuleTeardown(instance) serviceTeardown(svc) @@ -48,7 +48,7 @@ var _ = Describe("Resource status", Serial, func() { // then Eventually(func(g Gomega) { created := gatewayv1beta1.APIRule{} - g.Expect(c.Get(context.TODO(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &created)).Should(Succeed()) + g.Expect(c.Get(context.Background(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &created)).Should(Succeed()) g.Expect(created.Status.APIRuleStatus).NotTo(BeNil()) g.Expect(created.Status.APIRuleStatus.Code).To(Equal(gatewayv1beta1.StatusOK)) g.Expect(created.Status.VirtualServiceStatus.Code).To(Equal(gatewayv1beta1.StatusOK)) @@ -77,8 +77,8 @@ var _ = Describe("Resource status", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), instance)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), instance)).Should(Succeed()) defer func() { apiRuleTeardown(instance) serviceTeardown(svc) @@ -87,7 +87,7 @@ var _ = Describe("Resource status", Serial, func() { // then Eventually(func(g Gomega) { created := gatewayv1beta1.APIRule{} - Expect(c.Get(context.TODO(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &created)).Should(Succeed()) + Expect(c.Get(context.Background(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &created)).Should(Succeed()) g.Expect(created.Status.APIRuleStatus).NotTo(BeNil()) g.Expect(created.Status.APIRuleStatus.Code).To(Equal(gatewayv1beta1.StatusError)) @@ -123,8 +123,8 @@ var _ = Describe("Resource status", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), instance)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), instance)).Should(Succeed()) defer func() { apiRuleTeardown(instance) serviceTeardown(svc) @@ -133,7 +133,7 @@ var _ = Describe("Resource status", Serial, func() { // then Eventually(func(g Gomega) { created := gatewayv1beta1.APIRule{} - Expect(c.Get(context.TODO(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &created)).Should(Succeed()) + Expect(c.Get(context.Background(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &created)).Should(Succeed()) g.Expect(created.Status.APIRuleStatus).NotTo(BeNil()) g.Expect(created.Status.APIRuleStatus.Code).To(Equal(gatewayv1beta1.StatusOK)) g.Expect(created.Status.VirtualServiceStatus.Code).To(Equal(gatewayv1beta1.StatusOK)) @@ -161,8 +161,8 @@ var _ = Describe("Resource status", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), instance)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), instance)).Should(Succeed()) defer func() { apiRuleTeardown(instance) serviceTeardown(svc) @@ -171,7 +171,7 @@ var _ = Describe("Resource status", Serial, func() { // then Eventually(func(g Gomega) { created := gatewayv1beta1.APIRule{} - Expect(c.Get(context.TODO(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &created)).Should(Succeed()) + Expect(c.Get(context.Background(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &created)).Should(Succeed()) g.Expect(created.Status.APIRuleStatus).NotTo(BeNil()) g.Expect(created.Status.APIRuleStatus.Code).To(Equal(gatewayv1beta1.StatusError)) g.Expect(created.Status.APIRuleStatus.Description).To(ContainSubstring("Multiple validation errors:")) diff --git a/controllers/gateway/apirule_controller_validation_integration_test.go b/controllers/gateway/apirule_controller_validation_integration_test.go index 3700af02d..6395abf4e 100644 --- a/controllers/gateway/apirule_controller_validation_integration_test.go +++ b/controllers/gateway/apirule_controller_validation_integration_test.go @@ -352,8 +352,8 @@ func testConfigWithServiceAndHost(serviceName string, host string, accessStrateg svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), instance)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), instance)).Should(Succeed()) defer func() { apiRuleTeardown(instance) serviceTeardown(svc) @@ -362,7 +362,7 @@ func testConfigWithServiceAndHost(serviceName string, host string, accessStrateg // then Eventually(func(g Gomega) { created := gatewayv1beta1.APIRule{} - g.Expect(c.Get(context.TODO(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &created)).Should(Succeed()) + g.Expect(c.Get(context.Background(), client.ObjectKey{Name: apiRuleName, Namespace: testNamespace}, &created)).Should(Succeed()) g.Expect(created.Status.APIRuleStatus).NotTo(BeNil()) g.Expect(created.Status.APIRuleStatus.Code).To(Equal(expectedStatusCode)) for _, expected := range expectedValidationErrors { diff --git a/controllers/gateway/apirule_timeout_integration_test.go b/controllers/gateway/apirule_timeout_integration_test.go index 657995bfa..11c660a33 100644 --- a/controllers/gateway/apirule_timeout_integration_test.go +++ b/controllers/gateway/apirule_timeout_integration_test.go @@ -45,8 +45,8 @@ var _ = Describe("APIRule timeout", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -59,7 +59,7 @@ var _ = Describe("APIRule timeout", Serial, func() { By("Verifying created virtual service") vsList := networkingv1beta1.VirtualServiceList{} Eventually(func(g Gomega) { - g.Expect(c.List(context.TODO(), &vsList, matchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &vsList, matchingLabels)).Should(Succeed()) g.Expect(vsList.Items).To(HaveLen(1)) vs := vsList.Items[0] @@ -103,8 +103,8 @@ var _ = Describe("APIRule timeout", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -117,7 +117,7 @@ var _ = Describe("APIRule timeout", Serial, func() { By("Verifying created virtual service") vsList := networkingv1beta1.VirtualServiceList{} Eventually(func(g Gomega) { - g.Expect(c.List(context.TODO(), &vsList, matchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &vsList, matchingLabels)).Should(Succeed()) g.Expect(vsList.Items).To(HaveLen(1)) vs := vsList.Items[0] @@ -136,8 +136,8 @@ var _ = Describe("APIRule timeout", Serial, func() { svc := testService(serviceName, testNamespace, testServicePort) // when - Expect(c.Create(context.TODO(), svc)).Should(Succeed()) - Expect(c.Create(context.TODO(), apiRule)).Should(Succeed()) + Expect(c.Create(context.Background(), svc)).Should(Succeed()) + Expect(c.Create(context.Background(), apiRule)).Should(Succeed()) defer func() { apiRuleTeardown(apiRule) serviceTeardown(svc) @@ -150,7 +150,7 @@ var _ = Describe("APIRule timeout", Serial, func() { By("Verifying created virtual service") vsList := networkingv1beta1.VirtualServiceList{} Eventually(func(g Gomega) { - g.Expect(c.List(context.TODO(), &vsList, matchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &vsList, matchingLabels)).Should(Succeed()) g.Expect(vsList.Items).To(HaveLen(1)) vs := vsList.Items[0] @@ -212,7 +212,7 @@ var _ = Describe("APIRule timeout", Serial, func() { apiRule.Spec.Timeout = &timeout // when - err := c.Create(context.TODO(), apiRule) + err := c.Create(context.Background(), apiRule) // then Expect(err).Should(HaveOccurred()) @@ -228,7 +228,7 @@ var _ = Describe("APIRule timeout", Serial, func() { apiRule := testApiRule(apiRuleName, testNamespace, serviceName, testNamespace, serviceHost, testServicePort, []gatewayv1beta1.Rule{rule}) // when - err := c.Create(context.TODO(), apiRule) + err := c.Create(context.Background(), apiRule) // then Expect(err).Should(HaveOccurred()) @@ -289,7 +289,7 @@ var _ = Describe("APIRule timeout", Serial, func() { apiRule.Spec.Timeout = &timeout // when - err := c.Create(context.TODO(), apiRule) + err := c.Create(context.Background(), apiRule) // then Expect(err).Should(HaveOccurred()) @@ -305,7 +305,7 @@ var _ = Describe("APIRule timeout", Serial, func() { apiRule := testApiRule(apiRuleName, testNamespace, serviceName, testNamespace, serviceHost, testServicePort, []gatewayv1beta1.Rule{rule}) // when - err := c.Create(context.TODO(), apiRule) + err := c.Create(context.Background(), apiRule) // then Expect(err).Should(HaveOccurred()) diff --git a/controllers/gateway/suite_test.go b/controllers/gateway/suite_test.go index 6cddb78be..925ff56b8 100644 --- a/controllers/gateway/suite_test.go +++ b/controllers/gateway/suite_test.go @@ -84,7 +84,7 @@ func TestAPIs(t *testing.T) { var _ = BeforeSuite(func(specCtx SpecContext) { logf.SetLogger(zap.New(zap.UseDevMode(true), zap.WriteTo(GinkgoWriter))) - ctx, cancel = context.WithCancel(context.TODO()) + ctx, cancel = context.WithCancel(context.Background()) By("Bootstrapping test environment") testEnv = &envtest.Environment{ @@ -121,13 +121,13 @@ var _ = BeforeSuite(func(specCtx SpecContext) { ObjectMeta: metav1.ObjectMeta{Name: testNamespace}, Spec: corev1.NamespaceSpec{}, } - Expect(c.Create(context.TODO(), ns)).Should(Succeed()) + Expect(c.Create(context.Background(), ns)).Should(Succeed()) nsKyma := &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{Name: helpers.CM_NS}, Spec: corev1.NamespaceSpec{}, } - Expect(c.Create(context.TODO(), nsKyma)).Should(Succeed()) + Expect(c.Create(context.Background(), nsKyma)).Should(Succeed()) cm := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ @@ -138,7 +138,7 @@ var _ = BeforeSuite(func(specCtx SpecContext) { helpers.CM_KEY: fmt.Sprintf("jwtHandler: %s", helpers.JWT_HANDLER_ORY), }, } - Expect(c.Create(context.TODO(), cm)).Should(Succeed()) + Expect(c.Create(context.Background(), cm)).Should(Succeed()) reconcilerConfig := gateway.ApiRuleReconcilerConfiguration{ OathkeeperSvcAddr: testOathkeeperSvcURL, @@ -214,7 +214,7 @@ var _ = ReportAfterSuite("custom reporter", func(report types.Report) { func shouldHaveVirtualServices(g Gomega, apiRuleName, testNamespace string, len int) { matchingLabels := matchingLabelsFunc(apiRuleName, testNamespace) list := securityv1beta1.RequestAuthenticationList{} - g.Expect(c.List(context.TODO(), &list, matchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &list, matchingLabels)).Should(Succeed()) g.Expect(list.Items).To(HaveLen(len)) } @@ -222,7 +222,7 @@ func shouldHaveVirtualServices(g Gomega, apiRuleName, testNamespace string, len func shouldHaveRequestAuthentications(g Gomega, apiRuleName, testNamespace string, len int) { matchingLabels := matchingLabelsFunc(apiRuleName, testNamespace) list := securityv1beta1.RequestAuthenticationList{} - g.Expect(c.List(context.TODO(), &list, matchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &list, matchingLabels)).Should(Succeed()) g.Expect(list.Items).To(HaveLen(len)) } @@ -230,7 +230,7 @@ func shouldHaveRequestAuthentications(g Gomega, apiRuleName, testNamespace strin func shouldHaveAuthorizationPolicies(g Gomega, apiRuleName, testNamespace string, len int) { matchingLabels := matchingLabelsFunc(apiRuleName, testNamespace) list := securityv1beta1.AuthorizationPolicyList{} - g.Expect(c.List(context.TODO(), &list, matchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &list, matchingLabels)).Should(Succeed()) g.Expect(list.Items).To(HaveLen(len)) } @@ -238,6 +238,6 @@ func shouldHaveAuthorizationPolicies(g Gomega, apiRuleName, testNamespace string func shouldHaveRules(g Gomega, apiRuleName, testNamespace string, len int) { matchingLabels := matchingLabelsFunc(apiRuleName, testNamespace) list := rulev1alpha1.RuleList{} - g.Expect(c.List(context.TODO(), &list, matchingLabels)).Should(Succeed()) + g.Expect(c.List(context.Background(), &list, matchingLabels)).Should(Succeed()) g.Expect(list.Items).To(HaveLen(len)) } diff --git a/controllers/operator/apigateway_controller_integration_test.go b/controllers/operator/apigateway_controller_integration_test.go index 81e23642a..9208dac21 100644 --- a/controllers/operator/apigateway_controller_integration_test.go +++ b/controllers/operator/apigateway_controller_integration_test.go @@ -423,7 +423,7 @@ func deleteApiGateways() { Eventually(func(g Gomega) { By("Checking if APIGateway exists as part of teardown") list := v1alpha1.APIGatewayList{} - Expect(k8sClient.List(context.TODO(), &list)).Should(Succeed()) + Expect(k8sClient.List(context.Background(), &list)).Should(Succeed()) for _, item := range list.Items { apiGatewayTeardown(&item) @@ -434,14 +434,14 @@ func deleteApiGateways() { func apiGatewayTeardown(apiGateway *v1alpha1.APIGateway) { By(fmt.Sprintf("Deleting APIGateway %s as part of teardown", apiGateway.Name)) Eventually(func(g Gomega) { - err := k8sClient.Delete(context.TODO(), apiGateway) + err := k8sClient.Delete(context.Background(), apiGateway) if err != nil { Expect(errors.IsNotFound(err)).To(BeTrue()) } a := v1alpha1.APIGateway{} - err = k8sClient.Get(context.TODO(), client.ObjectKey{Name: apiGateway.Name}, &a) + err = k8sClient.Get(context.Background(), client.ObjectKey{Name: apiGateway.Name}, &a) g.Expect(errors.IsNotFound(err)).To(BeTrue()) }, eventuallyTimeout).Should(Succeed()) } @@ -450,7 +450,7 @@ func deleteApiRules() { Eventually(func(g Gomega) { By("Checking if APIRules exists as part of teardown") list := v1beta1.APIRuleList{} - Expect(k8sClient.List(context.TODO(), &list)).Should(Succeed()) + Expect(k8sClient.List(context.Background(), &list)).Should(Succeed()) for _, item := range list.Items { apiRuleTeardown(&item) @@ -462,7 +462,7 @@ func fetchLatestApiGateway(apiGateway v1alpha1.APIGateway) v1alpha1.APIGateway { a := v1alpha1.APIGateway{} Eventually(func(g Gomega) { - err := k8sClient.Get(context.TODO(), client.ObjectKey{Name: apiGateway.Name}, &a) + err := k8sClient.Get(context.Background(), client.ObjectKey{Name: apiGateway.Name}, &a) g.Expect(err).To(Not(HaveOccurred())) }, eventuallyTimeout).Should(Succeed()) @@ -472,21 +472,21 @@ func fetchLatestApiGateway(apiGateway v1alpha1.APIGateway) v1alpha1.APIGateway { func virtualServiceTeardown(vs *networkingv1beta1.VirtualService) { By(fmt.Sprintf("Deleting Virtual Service %s as part of teardown", vs.Name)) Eventually(func(g Gomega) { - err := k8sClient.Delete(context.TODO(), vs) + err := k8sClient.Delete(context.Background(), vs) if err != nil { Expect(errors.IsNotFound(err)).To(BeTrue()) } v := networkingv1beta1.VirtualService{} - err = k8sClient.Get(context.TODO(), client.ObjectKey{Name: vs.Name, Namespace: vs.Namespace}, &v) + err = k8sClient.Get(context.Background(), client.ObjectKey{Name: vs.Name, Namespace: vs.Namespace}, &v) g.Expect(errors.IsNotFound(err)).To(BeTrue()) }, eventuallyTimeout).Should(Succeed()) } func apiRuleTeardown(apiRule *v1beta1.APIRule) { By(fmt.Sprintf("Deleting APIRule %s as part of teardown", apiRule.Name)) - err := k8sClient.Delete(context.TODO(), apiRule) + err := k8sClient.Delete(context.Background(), apiRule) if err != nil { Expect(errors.IsNotFound(err)).To(BeTrue()) @@ -494,7 +494,7 @@ func apiRuleTeardown(apiRule *v1beta1.APIRule) { Eventually(func(g Gomega) { a := v1beta1.APIRule{} - err := k8sClient.Get(context.TODO(), client.ObjectKey{Name: apiRule.Name, Namespace: apiRule.Namespace}, &a) + err := k8sClient.Get(context.Background(), client.ObjectKey{Name: apiRule.Name, Namespace: apiRule.Namespace}, &a) g.Expect(errors.IsNotFound(err)).To(BeTrue()) }, eventuallyTimeout).Should(Succeed()) } @@ -554,7 +554,7 @@ func deleteVirtualServices() { Eventually(func(g Gomega) { By("Checking if VirtualServices exists as part of teardown") list := networkingv1beta1.VirtualServiceList{} - Expect(k8sClient.List(context.TODO(), &list)).Should(Succeed()) + Expect(k8sClient.List(context.Background(), &list)).Should(Succeed()) for _, item := range list.Items { virtualServiceTeardown(item) diff --git a/controllers/operator/apigateway_controller_test.go b/controllers/operator/apigateway_controller_test.go index 72f7fac20..f4ef76d1b 100644 --- a/controllers/operator/apigateway_controller_test.go +++ b/controllers/operator/apigateway_controller_test.go @@ -66,7 +66,7 @@ var _ = Describe("API-Gateway Controller", func() { Expect(err).ShouldNot(HaveOccurred()) Expect(result).Should(Equal(reconcile.Result{})) - Expect(c.Get(context.TODO(), client.ObjectKeyFromObject(apiGatewayCR), apiGatewayCR)).Should(Succeed()) + Expect(c.Get(context.Background(), client.ObjectKeyFromObject(apiGatewayCR), apiGatewayCR)).Should(Succeed()) Expect(apiGatewayCR.GetObjectMeta().GetFinalizers()).To(ContainElement(ApiGatewayFinalizer)) }) @@ -95,7 +95,7 @@ var _ = Describe("API-Gateway Controller", func() { Expect(err).ShouldNot(HaveOccurred()) Expect(result).Should(Equal(reconcile.Result{})) - Expect(c.Get(context.TODO(), client.ObjectKeyFromObject(apiGatewayCR), apiGatewayCR)).Should(Succeed()) + Expect(c.Get(context.Background(), client.ObjectKeyFromObject(apiGatewayCR), apiGatewayCR)).Should(Succeed()) Expect(apiGatewayCR.Status.State).Should(Equal(operatorv1alpha1.Ready)) Expect(apiGatewayCR.Status.Conditions).To(ContainElement(MatchFields(IgnoreExtras, Fields{ "Type": Equal(conditions.ReconcileSucceeded.Condition().Type), @@ -252,7 +252,7 @@ var _ = Describe("API-Gateway Controller", func() { Expect(err).ShouldNot(HaveOccurred()) Expect(result).Should(Equal(reconcile.Result{})) - Expect(errors.IsNotFound(c.Get(context.TODO(), client.ObjectKeyFromObject(apiGatewayCR), apiGatewayCR))).To(BeTrue()) + Expect(errors.IsNotFound(c.Get(context.Background(), client.ObjectKeyFromObject(apiGatewayCR), apiGatewayCR))).To(BeTrue()) }) It("Should not delete API-Gateway CR if there are any APIRules on cluster", func() { @@ -295,7 +295,7 @@ var _ = Describe("API-Gateway Controller", func() { Expect(err.Error()).To(Equal("could not delete API-Gateway CR since there are APIRule(s) that block its deletion")) Expect(result).Should(Equal(reconcile.Result{})) - Expect(c.Get(context.TODO(), client.ObjectKeyFromObject(apiGatewayCR), apiGatewayCR)).Should(Succeed()) + Expect(c.Get(context.Background(), client.ObjectKeyFromObject(apiGatewayCR), apiGatewayCR)).Should(Succeed()) Expect(apiGatewayCR.Status.State).To(Equal(operatorv1alpha1.Warning)) Expect(apiGatewayCR.Status.Description).To(Equal("There are APIRule(s) that block the deletion of API-Gateway CR. Please take a look at kyma-system/api-gateway-controller-manager logs to see more information about the warning")) Expect(apiGatewayCR.GetObjectMeta().GetFinalizers()).To(ContainElement(ApiGatewayFinalizer)) @@ -346,7 +346,7 @@ var _ = Describe("API-Gateway Controller", func() { Expect(err.Error()).To(Equal("could not delete API-Gateway CR since there are ORY Oathkeeper Rule(s) that block its deletion")) Expect(result).Should(Equal(reconcile.Result{})) - Expect(c.Get(context.TODO(), client.ObjectKeyFromObject(apiGatewayCR), apiGatewayCR)).Should(Succeed()) + Expect(c.Get(context.Background(), client.ObjectKeyFromObject(apiGatewayCR), apiGatewayCR)).Should(Succeed()) Expect(apiGatewayCR.Status.State).To(Equal(operatorv1alpha1.Warning)) Expect(apiGatewayCR.Status.Description).To(Equal("There are ORY Oathkeeper Rule(s) that block the deletion of API-Gateway CR. Please take a look at kyma-system/api-gateway-controller-manager logs to see more information about the warning")) Expect(apiGatewayCR.GetObjectMeta().GetFinalizers()).To(ContainElement(ApiGatewayFinalizer)) diff --git a/controllers/operator/suite_test.go b/controllers/operator/suite_test.go index 6bb30abe0..b3b818ae7 100644 --- a/controllers/operator/suite_test.go +++ b/controllers/operator/suite_test.go @@ -188,13 +188,13 @@ func createCommonTestResources(k8sClient client.Client) { ObjectMeta: metav1.ObjectMeta{Name: testNamespace}, Spec: corev1.NamespaceSpec{}, } - Expect(k8sClient.Create(context.TODO(), kymaSystemNs)).Should(Succeed()) + Expect(k8sClient.Create(context.Background(), kymaSystemNs)).Should(Succeed()) istioSystemNs := &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{Name: "istio-system"}, Spec: corev1.NamespaceSpec{}, } - Expect(k8sClient.Create(context.TODO(), istioSystemNs)).Should(Succeed()) + Expect(k8sClient.Create(context.Background(), istioSystemNs)).Should(Succeed()) } func createFakeClient(objects ...client.Object) client.Client { diff --git a/controllers/status_test.go b/controllers/status_test.go index 080063a70..05395add1 100644 --- a/controllers/status_test.go +++ b/controllers/status_test.go @@ -25,11 +25,11 @@ var _ = Describe("status", func() { newStatus := ErrorStatus(fmt.Errorf("test error"), "test description", nil) k8sClient := createFakeClient(&cr) // when - err := UpdateApiGatewayStatus(context.TODO(), k8sClient, &cr, newStatus) + err := UpdateApiGatewayStatus(context.Background(), k8sClient, &cr, newStatus) // then Expect(err).ToNot(HaveOccurred()) - Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: "test"}, &cr)).To(Succeed()) + Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: "test"}, &cr)).To(Succeed()) Expect(cr.Status.State).To(Equal(operatorv1alpha1.Error)) Expect(cr.Status.Description).To(Equal("test description")) }) @@ -43,7 +43,7 @@ var _ = Describe("status", func() { newStatus := ReadyStatus(nil) k8sClient := fake.NewClientBuilder().Build() // when - err := UpdateApiGatewayStatus(context.TODO(), k8sClient, &cr, newStatus) + err := UpdateApiGatewayStatus(context.Background(), k8sClient, &cr, newStatus) // then Expect(err).To(HaveOccurred()) @@ -60,7 +60,7 @@ var _ = Describe("status", func() { k8sClient := createFakeClient(&cr) // when - err := UpdateApiGatewayStatus(context.TODO(), k8sClient, &cr, status) + err := UpdateApiGatewayStatus(context.Background(), k8sClient, &cr, status) result := status.Condition() ok := reflect.DeepEqual(result, expected) diff --git a/internal/clusterconfig/clusterconfig_test.go b/internal/clusterconfig/clusterconfig_test.go index df8b80dbb..04b3fa784 100644 --- a/internal/clusterconfig/clusterconfig_test.go +++ b/internal/clusterconfig/clusterconfig_test.go @@ -35,7 +35,7 @@ var _ = Describe("EvaluateClusterSize", func() { client := createFakeClient(&k3dNode) //when - size, err := clusterconfig.EvaluateClusterSize(context.TODO(), client) + size, err := clusterconfig.EvaluateClusterSize(context.Background(), client) //then Expect(err).To(Not(HaveOccurred())) @@ -59,7 +59,7 @@ var _ = Describe("EvaluateClusterSize", func() { client := createFakeClient(&k3dNode) //when - size, err := clusterconfig.EvaluateClusterSize(context.TODO(), client) + size, err := clusterconfig.EvaluateClusterSize(context.Background(), client) //then Expect(err).To(Not(HaveOccurred())) @@ -95,7 +95,7 @@ var _ = Describe("EvaluateClusterSize", func() { client := createFakeClient(&k3dNode, &k3dNode2) //when - size, err := clusterconfig.EvaluateClusterSize(context.TODO(), client) + size, err := clusterconfig.EvaluateClusterSize(context.Background(), client) //then Expect(err).To(Not(HaveOccurred())) diff --git a/internal/helpers/service_test.go b/internal/helpers/service_test.go index 46cf35930..9a3474067 100644 --- a/internal/helpers/service_test.go +++ b/internal/helpers/service_test.go @@ -86,7 +86,7 @@ var _ = Describe("GetLabelSelectorFromService", func() { } apiRule := gatewayv1beta1.APIRule{} rule := gatewayv1beta1.Rule{} - workloadSelector, err := GetLabelSelectorFromService(context.TODO(), k8sClient, &service, &apiRule, &rule) + workloadSelector, err := GetLabelSelectorFromService(context.Background(), k8sClient, &service, &apiRule, &rule) Expect(err).ToNot(HaveOccurred()) Expect(workloadSelector.MatchLabels).To(HaveKeyWithValue("selectorKey", "selectorValue")) }) @@ -99,7 +99,7 @@ var _ = Describe("GetLabelSelectorFromService", func() { } apiRule := gatewayv1beta1.APIRule{} rule := gatewayv1beta1.Rule{} - workloadSelector, err := GetLabelSelectorFromService(context.TODO(), k8sClient, &service, &apiRule, &rule) + workloadSelector, err := GetLabelSelectorFromService(context.Background(), k8sClient, &service, &apiRule, &rule) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("service name is required but missing")) Expect(workloadSelector.MatchLabels).To(BeNil()) @@ -127,7 +127,7 @@ var _ = Describe("GetLabelSelectorFromService", func() { }, } rule := gatewayv1beta1.Rule{} - workloadSelector, err := GetLabelSelectorFromService(context.TODO(), k8sClient, &service, &apiRule, &rule) + workloadSelector, err := GetLabelSelectorFromService(context.Background(), k8sClient, &service, &apiRule, &rule) Expect(err).ToNot(HaveOccurred()) Expect(workloadSelector.MatchLabels).To(HaveKeyWithValue("selectorKey", "selectorValue")) }) @@ -148,7 +148,7 @@ var _ = Describe("GetLabelSelectorFromService", func() { } apiRule := gatewayv1beta1.APIRule{} rule := gatewayv1beta1.Rule{} - workloadSelector, err := GetLabelSelectorFromService(context.TODO(), k8sClient, &service, &apiRule, &rule) + workloadSelector, err := GetLabelSelectorFromService(context.Background(), k8sClient, &service, &apiRule, &rule) Expect(err).ToNot(HaveOccurred()) Expect(workloadSelector.MatchLabels).To(HaveKeyWithValue("selectorKey", "selectorValue")) }) @@ -167,7 +167,7 @@ var _ = Describe("GetLabelSelectorFromService", func() { } apiRule := gatewayv1beta1.APIRule{} rule := gatewayv1beta1.Rule{} - workloadSelector, err := GetLabelSelectorFromService(context.TODO(), k8sClient, &service, &apiRule, &rule) + workloadSelector, err := GetLabelSelectorFromService(context.Background(), k8sClient, &service, &apiRule, &rule) Expect(err).ToNot(HaveOccurred()) Expect(workloadSelector).To(BeNil()) }) diff --git a/internal/processing/cleaner_test.go b/internal/processing/cleaner_test.go index bf56cc70d..a858687ee 100644 --- a/internal/processing/cleaner_test.go +++ b/internal/processing/cleaner_test.go @@ -87,33 +87,33 @@ var _ = Describe("APIRule subresources deletion", func() { client := testUtils.GetFakeClient(&apiRuleVS, &otherVS, &apiRuleRule, &otherRule, &apiRuleAP, &otherAP, &apiRuleRA, &otherRA) // when - err := processing.DeleteAPIRuleSubresources(client, context.TODO(), *apiRule) + err := processing.DeleteAPIRuleSubresources(client, context.Background(), *apiRule) Expect(err).ShouldNot(HaveOccurred()) // then vsList := networkingv1beta1.VirtualServiceList{} - err = client.List(context.TODO(), &vsList) + err = client.List(context.Background(), &vsList) Expect(err).ShouldNot(HaveOccurred()) Expect(vsList.Items).To(HaveLen(1)) Expect(vsList.Items[0].Name).To(Equal("test-other-apirule")) ruleList := rulev1alpha1.RuleList{} - err = client.List(context.TODO(), &ruleList) + err = client.List(context.Background(), &ruleList) Expect(err).ShouldNot(HaveOccurred()) Expect(ruleList.Items).To(HaveLen(1)) Expect(ruleList.Items[0].Name).To(Equal("test-other-apirule")) apList := securityv1beta1.AuthorizationPolicyList{} - err = client.List(context.TODO(), &apList) + err = client.List(context.Background(), &apList) Expect(err).ShouldNot(HaveOccurred()) Expect(apList.Items).To(HaveLen(1)) Expect(apList.Items[0].Name).To(Equal("test-other-apirule")) raList := securityv1beta1.RequestAuthenticationList{} - err = client.List(context.TODO(), &raList) + err = client.List(context.Background(), &raList) Expect(err).ShouldNot(HaveOccurred()) Expect(raList.Items).To(HaveLen(1)) diff --git a/internal/processing/processors/istio/authorization_policy_processor_test.go b/internal/processing/processors/istio/authorization_policy_processor_test.go index b2b0742fb..c54b68142 100644 --- a/internal/processing/processors/istio/authorization_policy_processor_test.go +++ b/internal/processing/processors/istio/authorization_policy_processor_test.go @@ -185,7 +185,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), client) + result, err := processor.EvaluateReconciliation(context.Background(), client) Expect(err).To(BeNil()) Expect(result).To(HaveLen(1)) @@ -212,7 +212,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), client) + result, err := processor.EvaluateReconciliation(context.Background(), client) // then Expect(err).To(BeNil()) @@ -286,7 +286,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), client) + result, err := processor.EvaluateReconciliation(context.Background(), client) // then Expect(err).To(BeNil()) @@ -350,7 +350,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), client) + result, err := processor.EvaluateReconciliation(context.Background(), client) // then Expect(err).To(BeNil()) @@ -379,7 +379,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), client) + result, err := processor.EvaluateReconciliation(context.Background(), client) // then Expect(err).To(BeNil()) @@ -409,7 +409,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), client) + result, err := processor.EvaluateReconciliation(context.Background(), client) // then Expect(err).To(BeNil()) @@ -450,7 +450,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), client) + result, err := processor.EvaluateReconciliation(context.Background(), client) // then Expect(err).To(BeNil()) @@ -519,7 +519,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), client) + result, err := processor.EvaluateReconciliation(context.Background(), client) // then Expect(err).To(BeNil()) @@ -558,7 +558,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), client) + result, err := processor.EvaluateReconciliation(context.Background(), client) // then Expect(err).To(BeNil()) @@ -595,7 +595,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - results, err := processor.EvaluateReconciliation(context.TODO(), client) + results, err := processor.EvaluateReconciliation(context.Background(), client) // then Expect(err).To(BeNil()) @@ -660,7 +660,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - results, err := processor.EvaluateReconciliation(context.TODO(), client) + results, err := processor.EvaluateReconciliation(context.Background(), client) // then Expect(err).To(BeNil()) @@ -715,7 +715,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), client) + result, err := processor.EvaluateReconciliation(context.Background(), client) // then Expect(err).To(BeNil()) @@ -741,7 +741,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), client) + result, err := processor.EvaluateReconciliation(context.Background(), client) // then Expect(err).To(BeNil()) @@ -785,7 +785,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), ctrlClient) + result, err := processor.EvaluateReconciliation(context.Background(), ctrlClient) // then Expect(err).To(BeNil()) @@ -809,7 +809,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), ctrlClient) + result, err := processor.EvaluateReconciliation(context.Background(), ctrlClient) // then Expect(err).To(BeNil()) @@ -836,7 +836,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), ctrlClient) + result, err := processor.EvaluateReconciliation(context.Background(), ctrlClient) // then Expect(err).To(BeNil()) @@ -863,7 +863,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), ctrlClient) + result, err := processor.EvaluateReconciliation(context.Background(), ctrlClient) // then Expect(err).To(BeNil()) @@ -889,7 +889,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), ctrlClient) + result, err := processor.EvaluateReconciliation(context.Background(), ctrlClient) // then Expect(err).To(BeNil()) @@ -917,7 +917,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), ctrlClient) + result, err := processor.EvaluateReconciliation(context.Background(), ctrlClient) // then Expect(err).To(BeNil()) @@ -947,7 +947,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), ctrlClient) + result, err := processor.EvaluateReconciliation(context.Background(), ctrlClient) // then Expect(err).To(BeNil()) @@ -978,7 +978,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), ctrlClient) + result, err := processor.EvaluateReconciliation(context.Background(), ctrlClient) // then Expect(err).To(BeNil()) @@ -1003,7 +1003,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), ctrlClient) + result, err := processor.EvaluateReconciliation(context.Background(), ctrlClient) // then Expect(err).To(BeNil()) @@ -1033,7 +1033,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), ctrlClient) + result, err := processor.EvaluateReconciliation(context.Background(), ctrlClient) // then Expect(err).To(BeNil()) @@ -1098,7 +1098,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), ctrlClient) + result, err := processor.EvaluateReconciliation(context.Background(), ctrlClient) // then Expect(err).To(BeNil()) @@ -1164,7 +1164,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), ctrlClient) + result, err := processor.EvaluateReconciliation(context.Background(), ctrlClient) // then Expect(err).To(BeNil()) @@ -1229,7 +1229,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), ctrlClient) + result, err := processor.EvaluateReconciliation(context.Background(), ctrlClient) // then Expect(err).To(BeNil()) @@ -1306,7 +1306,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), ctrlClient) + result, err := processor.EvaluateReconciliation(context.Background(), ctrlClient) // then Expect(err).To(BeNil()) @@ -1339,7 +1339,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), client) + result, err := processor.EvaluateReconciliation(context.Background(), client) // then Expect(err).To(BeNil()) @@ -1370,7 +1370,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), client) + result, err := processor.EvaluateReconciliation(context.Background(), client) // then Expect(err).To(BeNil()) @@ -1400,7 +1400,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), client) + result, err := processor.EvaluateReconciliation(context.Background(), client) // then Expect(err).To(BeNil()) @@ -1462,7 +1462,7 @@ var _ = Describe("JwtAuthorization Policy Processor", func() { processor := istio.Newv1beta1AuthorizationPolicyProcessor(GetTestConfig(), &testLogger, apiRule) // when - result, err := processor.EvaluateReconciliation(context.TODO(), ctrlClient) + result, err := processor.EvaluateReconciliation(context.Background(), ctrlClient) // then Expect(err).To(BeNil()) diff --git a/internal/processing/processors/ory/reconciliation_test.go b/internal/processing/processors/ory/reconciliation_test.go index bed70541e..ca7de8107 100644 --- a/internal/processing/processors/ory/reconciliation_test.go +++ b/internal/processing/processors/ory/reconciliation_test.go @@ -57,7 +57,7 @@ var _ = Describe("Reconciliation", func() { var createdObjects []client.Object reconciliation := ory.NewOryReconciliation(apiRule, GetTestConfig(), &testLogger) for _, processor := range reconciliation.GetProcessors() { - results, err := processor.EvaluateReconciliation(context.TODO(), faceClient) + results, err := processor.EvaluateReconciliation(context.Background(), faceClient) Expect(err).To(BeNil()) for _, result := range results { @@ -119,7 +119,7 @@ var _ = Describe("Reconciliation", func() { var createdObjects []client.Object reconciliation := ory.NewOryReconciliation(apiRule, GetTestConfig(), &testLogger) for _, processor := range reconciliation.GetProcessors() { - results, err := processor.EvaluateReconciliation(context.TODO(), faceClient) + results, err := processor.EvaluateReconciliation(context.Background(), faceClient) Expect(err).To(BeNil()) for _, result := range results { diff --git a/internal/resources/resources_test.go b/internal/resources/resources_test.go index ebc0f41bc..26d70b520 100644 --- a/internal/resources/resources_test.go +++ b/internal/resources/resources_test.go @@ -36,7 +36,7 @@ var _ = Describe("Resources", func() { Expect(err != nil).To(Equal(wantErr)) Expect(got).To(BeEquivalentTo(want)) }, - Entry("Should get nothing if there are only managed API-Gateway resources present", context.TODO(), + Entry("Should get nothing if there are only managed API-Gateway resources present", context.Background(), logr.Discard(), fake.NewClientBuilder().WithScheme(sc).WithObjects(&v1beta1.APIRule{ ObjectMeta: metav1.ObjectMeta{ @@ -63,7 +63,7 @@ var _ = Describe("Resources", func() { true, nil, false, - ), Entry("Should get resource if there is a customer resource present", context.TODO(), + ), Entry("Should get resource if there is a customer resource present", context.Background(), logr.Discard(), fake.NewClientBuilder().WithScheme(sc).WithObjects(&v1beta1.APIRule{ ObjectMeta: metav1.ObjectMeta{ @@ -106,7 +106,7 @@ var _ = Describe("Resources", func() { }, }, false, - ), Entry("Should get resource if there is a customer resource present in a specific version only", context.TODO(), + ), Entry("Should get resource if there is a customer resource present in a specific version only", context.Background(), logr.Discard(), fake.NewClientBuilder().WithScheme(sc).WithObjects(&networkingv1beta1.VirtualService{ ObjectMeta: metav1.ObjectMeta{ @@ -145,7 +145,7 @@ var _ = Describe("Resources", func() { }, }, false, - ), Entry("Should not get resource if there is a customer resource present but condition check returns false", context.TODO(), + ), Entry("Should not get resource if there is a customer resource present but condition check returns false", context.Background(), logr.Discard(), fake.NewClientBuilder().WithScheme(sc).WithObjects(&v1beta1.APIRule{ ObjectMeta: metav1.ObjectMeta{ @@ -171,10 +171,10 @@ var _ = Describe("Resources", func() { var _ = Describe("NewResourcesFinderFromConfigYaml", func() { It("Should read configuration from yaml", func() { - config, err := NewResourcesFinderFromConfigYaml(context.TODO(), nil, logr.Logger{}, "test_assets/test_resources_list.yaml") + config, err := NewResourcesFinderFromConfigYaml(context.Background(), nil, logr.Logger{}, "test_assets/test_resources_list.yaml") Expect(err).ToNot(HaveOccurred()) Expect(config).To(BeEquivalentTo(&ResourcesFinder{ - ctx: context.TODO(), + ctx: context.Background(), logger: logr.Logger{}, client: nil, configuration: resourceFinderConfiguration{ @@ -199,7 +199,7 @@ var _ = Describe("NewResourcesFinderFromConfigYaml", func() { }) It("Should fail if the configuration contains invalid regex", func() { - _, err := NewResourcesFinderFromConfigYaml(context.TODO(), nil, logr.Logger{}, "test_assets/test_wrong_resources_list.yaml") + _, err := NewResourcesFinderFromConfigYaml(context.Background(), nil, logr.Logger{}, "test_assets/test_wrong_resources_list.yaml") Expect(err).To(HaveOccurred()) }) }) diff --git a/internal/validation/v1beta1/v1beta1_test.go b/internal/validation/v1beta1/v1beta1_test.go index 293893de6..6dbfdd347 100644 --- a/internal/validation/v1beta1/v1beta1_test.go +++ b/internal/validation/v1beta1/v1beta1_test.go @@ -54,7 +54,7 @@ var _ = Describe("Validate function", func() { HandlerValidator: handlerValidatorMock, AccessStrategiesValidator: asValidatorMock, DomainAllowList: testAllowList, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(1)) @@ -96,7 +96,7 @@ var _ = Describe("Validate function", func() { AccessStrategiesValidator: asValidatorMock, ServiceBlockList: testBlockList, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(1)) @@ -139,7 +139,7 @@ var _ = Describe("Validate function", func() { AccessStrategiesValidator: asValidatorMock, ServiceBlockList: testBlockList, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(1)) @@ -177,7 +177,7 @@ var _ = Describe("Validate function", func() { AccessStrategiesValidator: asValidatorMock, ServiceBlockList: testBlockList, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(1)) @@ -219,7 +219,7 @@ var _ = Describe("Validate function", func() { DomainAllowList: testDomainAllowlist, HostBlockList: testHostBlockList, DefaultDomainName: testDefaultDomain, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(1)) @@ -263,7 +263,7 @@ var _ = Describe("Validate function", func() { DomainAllowList: testDomainAllowlist, HostBlockList: testHostBlockList, DefaultDomainName: testDefaultDomain, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(0)) @@ -299,7 +299,7 @@ var _ = Describe("Validate function", func() { AccessStrategiesValidator: asValidatorMock, ServiceBlockList: testBlockList, DomainAllowList: []string{}, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(0)) @@ -335,7 +335,7 @@ var _ = Describe("Validate function", func() { AccessStrategiesValidator: asValidatorMock, ServiceBlockList: testBlockList, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(1)) @@ -373,7 +373,7 @@ var _ = Describe("Validate function", func() { AccessStrategiesValidator: asValidatorMock, ServiceBlockList: testBlockList, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(1)) @@ -412,7 +412,7 @@ var _ = Describe("Validate function", func() { ServiceBlockList: testBlockList, DomainAllowList: testDomainAllowlist, DefaultDomainName: testDefaultDomain, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(0)) @@ -448,7 +448,7 @@ var _ = Describe("Validate function", func() { AccessStrategiesValidator: asValidatorMock, ServiceBlockList: testBlockList, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(1)) @@ -489,7 +489,7 @@ var _ = Describe("Validate function", func() { HandlerValidator: handlerValidatorMock, AccessStrategiesValidator: asValidatorMock, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{Items: []*networkingv1beta1.VirtualService{&existingVS}}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{Items: []*networkingv1beta1.VirtualService{&existingVS}}) Expect(problems).To(HaveLen(1)) Expect(problems[0].AttributePath).To(Equal(".spec.host")) @@ -531,7 +531,7 @@ var _ = Describe("Validate function", func() { HandlerValidator: handlerValidatorMock, AccessStrategiesValidator: asValidatorMock, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{Items: []*networkingv1beta1.VirtualService{&existingVS}}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{Items: []*networkingv1beta1.VirtualService{&existingVS}}) Expect(problems).To(HaveLen(0)) }) @@ -560,7 +560,7 @@ var _ = Describe("Validate function", func() { ApiRule: apiRule, AccessStrategiesValidator: asValidatorMock, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(1)) @@ -611,7 +611,7 @@ var _ = Describe("Validate function", func() { AccessStrategiesValidator: asValidatorMock, ServiceBlockList: testBlockList, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(1)) @@ -663,7 +663,7 @@ var _ = Describe("Validate function", func() { AccessStrategiesValidator: asValidatorMock, ServiceBlockList: testBlockList, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(1)) @@ -712,7 +712,7 @@ var _ = Describe("Validate function", func() { ApiRule: apiRule, AccessStrategiesValidator: asValidatorMock, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(5)) @@ -766,7 +766,7 @@ var _ = Describe("Validate function", func() { ApiRule: apiRule, AccessStrategiesValidator: asValidatorMock, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(1)) @@ -828,7 +828,7 @@ var _ = Describe("Validate function", func() { HandlerValidator: handlerValidatorMock, AccessStrategiesValidator: asValidatorMock, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{Items: []*networkingv1beta1.VirtualService{&existingVS}}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{Items: []*networkingv1beta1.VirtualService{&existingVS}}) //then Expect(problems).To(HaveLen(0)) @@ -876,7 +876,7 @@ var _ = Describe("Validate function", func() { HandlerValidator: handlerValidatorMock, AccessStrategiesValidator: asValidatorMock, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{Items: []*networkingv1beta1.VirtualService{&existingVS}}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{Items: []*networkingv1beta1.VirtualService{&existingVS}}) //then Expect(problems).To(HaveLen(0)) @@ -910,7 +910,7 @@ var _ = Describe("Validate function", func() { HandlerValidator: handlerValidatorMock, AccessStrategiesValidator: asValidatorMock, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) // then Expect(problems).To(HaveLen(1)) @@ -946,7 +946,7 @@ var _ = Describe("Validate function", func() { HandlerValidator: handlerValidatorMock, AccessStrategiesValidator: asValidatorMock, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) // then Expect(problems).To(HaveLen(1)) @@ -982,7 +982,7 @@ var _ = Describe("Validate function", func() { HandlerValidator: handlerValidatorMock, AccessStrategiesValidator: asValidatorMock, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(0)) @@ -1016,7 +1016,7 @@ var _ = Describe("Validate function", func() { HandlerValidator: handlerValidatorMock, AccessStrategiesValidator: asValidatorMock, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(0)) @@ -1049,7 +1049,7 @@ var _ = Describe("Validate function", func() { HandlerValidator: handlerValidatorMock, AccessStrategiesValidator: asValidatorMock, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(0)) @@ -1082,7 +1082,7 @@ var _ = Describe("Validate function", func() { HandlerValidator: handlerValidatorMock, AccessStrategiesValidator: asValidatorMock, DomainAllowList: testDomainAllowlist, - }).Validate(context.TODO(), fakeClient, networkingv1beta1.VirtualServiceList{}) + }).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) //then Expect(problems).To(HaveLen(0)) diff --git a/tests/integration/pkg/hooks/api-gateway.go b/tests/integration/pkg/hooks/api-gateway.go index 0cdb8dad8..f6e22033c 100644 --- a/tests/integration/pkg/hooks/api-gateway.go +++ b/tests/integration/pkg/hooks/api-gateway.go @@ -195,7 +195,7 @@ func removeObjectFromCluster(ctx context.Context, object client.Object) error { return err } - err = k8sClient.Delete(context.TODO(), object, &client.DeleteOptions{}) + err = k8sClient.Delete(context.Background(), object, &client.DeleteOptions{}) if err != nil && !k8serrors.IsNotFound(err) { return err } diff --git a/tests/integration/pkg/resource/manager.go b/tests/integration/pkg/resource/manager.go index 0da8878f3..ab0a52ff8 100644 --- a/tests/integration/pkg/resource/manager.go +++ b/tests/integration/pkg/resource/manager.go @@ -195,11 +195,11 @@ func (m *Manager) CreateOrUpdateResourcesGVR(client dynamic.Interface, resources if err != nil { return nil, err } - _, err = client.Resource(*gvr).Namespace(res.GetNamespace()).Get(context.TODO(), res.GetName(), metav1.GetOptions{}) + _, err = client.Resource(*gvr).Namespace(res.GetNamespace()).Get(context.Background(), res.GetName(), metav1.GetOptions{}) if err != nil { if apierrors.IsNotFound(err) { - _, err := client.Resource(*gvr).Namespace(res.GetNamespace()).Create(context.TODO(), &res, metav1.CreateOptions{}) + _, err := client.Resource(*gvr).Namespace(res.GetNamespace()).Create(context.Background(), &res, metav1.CreateOptions{}) if err != nil { return nil, err } diff --git a/tests/integration/testsuites/custom-domain/testsuite.go b/tests/integration/testsuites/custom-domain/testsuite.go index af40ed041..1b6542ccb 100644 --- a/tests/integration/testsuites/custom-domain/testsuite.go +++ b/tests/integration/testsuites/custom-domain/testsuite.go @@ -114,7 +114,7 @@ func (t *testsuite) Setup() error { func (t *testsuite) TearDown() { //Remove certificate res := schema.GroupVersionResource{Group: "cert.gardener.cloud", Version: "v1alpha1", Resource: "certificates"} - err := t.k8sClient.Resource(res).Namespace("istio-system").DeleteCollection(context.TODO(), v1.DeleteOptions{}, v1.ListOptions{LabelSelector: "owner=custom-domain-test"}) + err := t.k8sClient.Resource(res).Namespace("istio-system").DeleteCollection(context.Background(), v1.DeleteOptions{}, v1.ListOptions{LabelSelector: "owner=custom-domain-test"}) if err != nil { log.Print(err.Error()) } From 107530a7afd08bd8701ae5b1e2644147a5da26a5 Mon Sep 17 00:00:00 2001 From: Kamil Kasperski Date: Thu, 11 Jul 2024 13:35:59 +0200 Subject: [PATCH 06/11] bug: increase retry attempts for ory scenarios (#1160) /kind bug /area ci * increase retry count in ory scenario to 60 * fix getting apirules * add getting apigateways --- .github/actions/integration-test-gardener/action.yaml | 3 ++- .github/actions/integration-tests/action.yaml | 3 ++- tests/integration/pkg/testcontext/config.go | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/actions/integration-test-gardener/action.yaml b/.github/actions/integration-test-gardener/action.yaml index f8e456644..bca7ed8e9 100644 --- a/.github/actions/integration-test-gardener/action.yaml +++ b/.github/actions/integration-test-gardener/action.yaml @@ -67,7 +67,8 @@ runs: (kubectl logs -n kyma-system deployments/api-gateway-controller-manager || true) > logs/api-gateway-controller-manager.log (kubectl logs -n istio-system deployments/istio-ingressgateway || true) > logs/istio-ingressgateway.log (kubectl logs -n istio-system deployments/istiod || true) > logs/istiod.log - (kubectl describe --all-namespaces apirules.gateway.kyma-project.io -oyaml) > logs/apirules-dump.yaml + (kubectl get --all-namespaces apirules.gateway.kyma-project.io -oyaml || true) > logs/apirules-dump.yaml + (kubectl get --all-namespaces apigateways.operator.kyma-project.io -oyaml || true) > logs/gateway-dump.yaml - name: Uploads logs uses: actions/upload-artifact@v4 if: failure() diff --git a/.github/actions/integration-tests/action.yaml b/.github/actions/integration-tests/action.yaml index 3ad737721..fdbcdfb3f 100644 --- a/.github/actions/integration-tests/action.yaml +++ b/.github/actions/integration-tests/action.yaml @@ -54,7 +54,8 @@ runs: (kubectl logs -n kyma-system deployments/api-gateway-controller-manager || true) > logs/api-gateway-controller-manager.log (kubectl logs -n istio-system deployments/istio-ingressgateway || true) > logs/istio-ingressgateway.log (kubectl logs -n istio-system deployments/istiod || true) > logs/istiod.log - (kubectl describe --all-namespaces apirules.gateway.kyma-project.io -oyaml || true) > logs/apirules-dump.yaml + (kubectl get --all-namespaces apirules.gateway.kyma-project.io -oyaml || true) > logs/apirules-dump.yaml + (kubectl get --all-namespaces apigateways.operator.kyma-project.io -oyaml || true) > logs/gateway-dump.yaml - name: Uploads artifacts uses: actions/upload-artifact@v4 with: diff --git a/tests/integration/pkg/testcontext/config.go b/tests/integration/pkg/testcontext/config.go index 33168b087..113f681cd 100644 --- a/tests/integration/pkg/testcontext/config.go +++ b/tests/integration/pkg/testcontext/config.go @@ -52,7 +52,7 @@ func GetRetryOpts() []retry.Option { retryOpts = []retry.Option{ retry.Delay(time.Duration(config.ReqDelay) * time.Second), - retry.Attempts(config.ReqTimeout / config.ReqDelay), + retry.Attempts(60), retry.DelayType(retry.FixedDelay), } } From 646815ce82efb39cc98bc7cffd4c91a424d65bf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ko=C5=82odziejczak?= <69915024+kolodziejczak@users.noreply.github.com> Date: Mon, 15 Jul 2024 08:43:35 +0200 Subject: [PATCH 07/11] Update security scanner config (#1163) --- sec-scanners-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sec-scanners-config.yaml b/sec-scanners-config.yaml index 57b0299e3..92eb7de63 100644 --- a/sec-scanners-config.yaml +++ b/sec-scanners-config.yaml @@ -1,6 +1,6 @@ module-name: api-gateway protecode: - - europe-docker.pkg.dev/kyma-project/prod/api-gateway-manager:v20240701-d2e5878b + - europe-docker.pkg.dev/kyma-project/prod/api-gateway-manager:v20240711-107530a7 - europe-docker.pkg.dev/kyma-project/prod/external/oryd/oathkeeper:v0.38.25-beta.1 - europe-docker.pkg.dev/kyma-project/prod/external/oryd/oathkeeper-maester:v0.1.5 whitesource: From c3e6fe9ff583fdfd2be9afb9e4493c165f84af85 Mon Sep 17 00:00:00 2001 From: Tim Riffer Date: Mon, 15 Jul 2024 11:01:35 +0200 Subject: [PATCH 08/11] Add rules validation for v2alpha1 (#1156) * Fix problem of reconciling creation of v2alpha1 APIRule after deletion * Add rules validation for v2alpha1 * Add JWT validation tests * Add tests for rules validation * Add tests for rules validation * Remove named returns * Don't leak attribute path to callers. * Review remarks * Add tests for sidecar injection selector logic and simplify code --- controllers/gateway/config_map.go | 3 +- internal/validation/injection.go | 4 +- internal/validation/injection_test.go | 133 ++++++ .../v1beta1/istio/jwt_validator_test.go | 124 ------ internal/validation/v2alpha1/jwt.go | 203 +++++++++ .../v2alpha1/jwt_authentications_test.go | 252 +++++++++++ .../v2alpha1/jwt_authorizations_test.go | 272 ++++++++++++ internal/validation/v2alpha1/jwt_test.go | 207 +++++++++ internal/validation/v2alpha1/rules.go | 75 ++++ internal/validation/v2alpha1/rules_test.go | 313 ++++++++++++++ .../validation/v2alpha1/sidecar_injection.go | 83 ++++ .../v2alpha1/sidecar_injection_test.go | 408 ++++++++++++++++++ internal/validation/v2alpha1/suite_test.go | 119 +++++ internal/validation/v2alpha1/v2alpha1.go | 49 +-- internal/validation/v2alpha1/v2alpha1_test.go | 67 +++ main.go | 6 + 16 files changed, 2151 insertions(+), 167 deletions(-) create mode 100644 internal/validation/injection_test.go create mode 100644 internal/validation/v2alpha1/jwt.go create mode 100644 internal/validation/v2alpha1/jwt_authentications_test.go create mode 100644 internal/validation/v2alpha1/jwt_authorizations_test.go create mode 100644 internal/validation/v2alpha1/jwt_test.go create mode 100644 internal/validation/v2alpha1/rules.go create mode 100644 internal/validation/v2alpha1/rules_test.go create mode 100644 internal/validation/v2alpha1/sidecar_injection.go create mode 100644 internal/validation/v2alpha1/sidecar_injection_test.go create mode 100644 internal/validation/v2alpha1/suite_test.go create mode 100644 internal/validation/v2alpha1/v2alpha1_test.go diff --git a/controllers/gateway/config_map.go b/controllers/gateway/config_map.go index a51e6f20f..b85d05cc2 100644 --- a/controllers/gateway/config_map.go +++ b/controllers/gateway/config_map.go @@ -14,7 +14,6 @@ const ( ) func (r *APIRuleReconciler) reconcileConfigMap(ctx context.Context, isCMReconcile bool) (finishReconciliation bool) { - r.Log.Info("Starting ConfigMap reconciliation") err := r.Config.ReadFromConfigMap(ctx, r.Client) if err != nil { if apierrs.IsNotFound(err) { @@ -25,7 +24,9 @@ func (r *APIRuleReconciler) reconcileConfigMap(ctx context.Context, isCMReconcil r.Config.Reset() } } + if isCMReconcile { + r.Log.Info("Starting ConfigMap reconciliation") configValidationFailures := validation.ValidateConfig(r.Config) r.Log.Info("ConfigMap changed", "config", r.Config) if len(configValidationFailures) > 0 { diff --git a/internal/validation/injection.go b/internal/validation/injection.go index a213e0304..4a19ffad8 100644 --- a/internal/validation/injection.go +++ b/internal/validation/injection.go @@ -19,7 +19,7 @@ func NewInjectionValidator(ctx context.Context, client client.Client) *Injection return &InjectionValidator{Ctx: ctx, Client: client} } -func (v *InjectionValidator) Validate(attributePath string, selector *apiv1beta1.WorkloadSelector, namespace string) (problems []Failure, err error) { +func (v *InjectionValidator) Validate(attributePath string, selector *apiv1beta1.WorkloadSelector, workloadNamespace string) (problems []Failure, err error) { if selector == nil { problems = append(problems, Failure{ AttributePath: attributePath + ".injection", @@ -30,7 +30,7 @@ func (v *InjectionValidator) Validate(attributePath string, selector *apiv1beta1 } var podList corev1.PodList - err = v.Client.List(v.Ctx, &podList, client.InNamespace(namespace), client.MatchingLabels(selector.MatchLabels)) + err = v.Client.List(v.Ctx, &podList, client.InNamespace(workloadNamespace), client.MatchingLabels(selector.MatchLabels)) if err != nil { return nil, err } diff --git a/internal/validation/injection_test.go b/internal/validation/injection_test.go new file mode 100644 index 000000000..1b5ca0a6d --- /dev/null +++ b/internal/validation/injection_test.go @@ -0,0 +1,133 @@ +package validation_test + +import ( + "context" + gatewayv1beta1 "github.com/kyma-project/api-gateway/apis/gateway/v1beta1" + "github.com/kyma-project/api-gateway/internal/validation" + + "istio.io/api/type/v1beta1" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +var _ = Describe("Istio injection validation", func() { + + scheme := runtime.NewScheme() + err := gatewayv1beta1.AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) + var k8sFakeClient client.WithWatch + + BeforeEach(func() { + k8sFakeClient = fake.NewClientBuilder().Build() + }) + + It("Should not fail when the Pod for which the service is specified is in different ns", func() { + //given + err := k8sFakeClient.Create(context.Background(), &corev1.Pod{ + ObjectMeta: v1.ObjectMeta{ + Name: "test-pod", + Namespace: "test", + Labels: map[string]string{ + "app": "test", + }, + }, + }) + Expect(err).NotTo(HaveOccurred()) + + //when + problems, err := (&validation.InjectionValidator{Ctx: context.Background(), Client: k8sFakeClient}).Validate("some.attribute", &v1beta1.WorkloadSelector{MatchLabels: map[string]string{"app": "test"}}, "default") + Expect(err).NotTo(HaveOccurred()) + + //then + Expect(problems).To(HaveLen(0)) + }) + + It("Should fail when the workload selector is nil", func() { + //when + problems, err := (&validation.InjectionValidator{Ctx: context.Background(), Client: k8sFakeClient}).Validate("some.attribute", nil, "default") + Expect(err).NotTo(HaveOccurred()) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal("some.attribute.injection")) + Expect(problems[0].Message).To(Equal("Service cannot have empty label selectors when the API Rule strategy is JWT")) + }) + + It("Should fail when the Pod for which the service is specified is not istio injected and in the same not default namespace", func() { + //given + err := k8sFakeClient.Create(context.Background(), &corev1.Pod{ + ObjectMeta: v1.ObjectMeta{ + Name: "test-pod", + Namespace: "test", + Labels: map[string]string{ + "app": "test", + }, + }, + }) + Expect(err).NotTo(HaveOccurred()) + + //when + problems, err := (&validation.InjectionValidator{Ctx: context.Background(), Client: k8sFakeClient}).Validate("some.attribute", &v1beta1.WorkloadSelector{MatchLabels: map[string]string{"app": "test"}}, "test") + Expect(err).NotTo(HaveOccurred()) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal("some.attribute")) + Expect(problems[0].Message).To(Equal("Pod test/test-pod does not have an injected istio sidecar")) + }) + + It("Should fail when the Pod for which the service is specified is not istio injected", func() { + //given + err := k8sFakeClient.Create(context.Background(), &corev1.Pod{ + ObjectMeta: v1.ObjectMeta{ + Name: "test-pod", + Namespace: "default", + Labels: map[string]string{ + "app": "test", + }, + }, + }) + Expect(err).NotTo(HaveOccurred()) + + //when + problems, err := (&validation.InjectionValidator{Ctx: context.Background(), Client: k8sFakeClient}).Validate("some.attribute", &v1beta1.WorkloadSelector{MatchLabels: map[string]string{"app": "test"}}, "default") + Expect(err).NotTo(HaveOccurred()) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal("some.attribute")) + Expect(problems[0].Message).To(Equal("Pod default/test-pod does not have an injected istio sidecar")) + }) + + It("Should not fail when the Pod for which the service is specified is istio injected", func() { + //given + err := k8sFakeClient.Create(context.Background(), &corev1.Pod{ + ObjectMeta: v1.ObjectMeta{ + Name: "test-pod-injected", + Namespace: "default", + Labels: map[string]string{ + "app": "test-injected", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + {Name: "istio-proxy"}, + }, + }, + }) + Expect(err).NotTo(HaveOccurred()) + + //when + problems, err := (&validation.InjectionValidator{Ctx: context.Background(), Client: k8sFakeClient}).Validate("some.attribute", &v1beta1.WorkloadSelector{MatchLabels: map[string]string{"app": "test-injected"}}, "default") + Expect(err).NotTo(HaveOccurred()) + + //then + Expect(problems).To(HaveLen(0)) + }) +}) diff --git a/internal/validation/v1beta1/istio/jwt_validator_test.go b/internal/validation/v1beta1/istio/jwt_validator_test.go index 712168b51..676ff87eb 100644 --- a/internal/validation/v1beta1/istio/jwt_validator_test.go +++ b/internal/validation/v1beta1/istio/jwt_validator_test.go @@ -1,141 +1,17 @@ package istio import ( - "context" "encoding/json" gatewayv1beta1 "github.com/kyma-project/api-gateway/apis/gateway/v1beta1" - "github.com/kyma-project/api-gateway/internal/validation" - processingtest "github.com/kyma-project/api-gateway/internal/processing/processing_test" - "istio.io/api/type/v1beta1" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - "github.com/kyma-project/api-gateway/internal/types/ory" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - corev1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/controller-runtime/pkg/client" ) var _ = Describe("JWT Handler validation", func() { - Context("Istio injection validation", func() { - scheme := runtime.NewScheme() - err := gatewayv1beta1.AddToScheme(scheme) - Expect(err).NotTo(HaveOccurred()) - var k8sfakeClient client.WithWatch - - BeforeEach(func() { - k8sfakeClient = fake.NewClientBuilder().Build() - }) - - It("Should not fail when the Pod for which the service is specified is in different ns", func() { - //given - err := k8sfakeClient.Create(context.Background(), &corev1.Pod{ - ObjectMeta: v1.ObjectMeta{ - Name: "test-pod", - Namespace: "test", - Labels: map[string]string{ - "app": "test", - }, - }, - }) - Expect(err).NotTo(HaveOccurred()) - - //when - problems, err := (&validation.InjectionValidator{Ctx: context.Background(), Client: k8sfakeClient}).Validate("some.attribute", &v1beta1.WorkloadSelector{MatchLabels: map[string]string{"app": "test"}}, "default") - Expect(err).NotTo(HaveOccurred()) - - //then - Expect(problems).To(HaveLen(0)) - }) - - It("Should fail when the workload selector is nil", func() { - //when - problems, err := (&validation.InjectionValidator{Ctx: context.Background(), Client: k8sfakeClient}).Validate("some.attribute", nil, "default") - Expect(err).NotTo(HaveOccurred()) - - //then - Expect(problems).To(HaveLen(1)) - Expect(problems[0].AttributePath).To(Equal("some.attribute.injection")) - Expect(problems[0].Message).To(Equal("Service cannot have empty label selectors when the API Rule strategy is JWT")) - }) - - It("Should fail when the Pod for which the service is specified is not istio injected and in the same not default namespace", func() { - //given - err := k8sfakeClient.Create(context.Background(), &corev1.Pod{ - ObjectMeta: v1.ObjectMeta{ - Name: "test-pod", - Namespace: "test", - Labels: map[string]string{ - "app": "test", - }, - }, - }) - Expect(err).NotTo(HaveOccurred()) - - //when - problems, err := (&validation.InjectionValidator{Ctx: context.Background(), Client: k8sfakeClient}).Validate("some.attribute", &v1beta1.WorkloadSelector{MatchLabels: map[string]string{"app": "test"}}, "test") - Expect(err).NotTo(HaveOccurred()) - - //then - Expect(problems).To(HaveLen(1)) - Expect(problems[0].AttributePath).To(Equal("some.attribute")) - Expect(problems[0].Message).To(Equal("Pod test/test-pod does not have an injected istio sidecar")) - }) - - It("Should fail when the Pod for which the service is specified is not istio injected", func() { - //given - err := k8sfakeClient.Create(context.Background(), &corev1.Pod{ - ObjectMeta: v1.ObjectMeta{ - Name: "test-pod", - Namespace: "default", - Labels: map[string]string{ - "app": "test", - }, - }, - }) - Expect(err).NotTo(HaveOccurred()) - - //when - problems, err := (&validation.InjectionValidator{Ctx: context.Background(), Client: k8sfakeClient}).Validate("some.attribute", &v1beta1.WorkloadSelector{MatchLabels: map[string]string{"app": "test"}}, "default") - Expect(err).NotTo(HaveOccurred()) - - //then - Expect(problems).To(HaveLen(1)) - Expect(problems[0].AttributePath).To(Equal("some.attribute")) - Expect(problems[0].Message).To(Equal("Pod default/test-pod does not have an injected istio sidecar")) - }) - - It("Should not fail when the Pod for which the service is specified is istio injected", func() { - //given - err := k8sfakeClient.Create(context.Background(), &corev1.Pod{ - ObjectMeta: v1.ObjectMeta{ - Name: "test-pod-injected", - Namespace: "default", - Labels: map[string]string{ - "app": "test-injected", - }, - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - {Name: "istio-proxy"}, - }, - }, - }) - Expect(err).NotTo(HaveOccurred()) - - //when - problems, err := (&validation.InjectionValidator{Ctx: context.Background(), Client: k8sfakeClient}).Validate("some.attribute", &v1beta1.WorkloadSelector{MatchLabels: map[string]string{"app": "test-injected"}}, "default") - Expect(err).NotTo(HaveOccurred()) - - //then - Expect(problems).To(HaveLen(0)) - }) - }) - It("Should fail with empty config", func() { //given handler := &gatewayv1beta1.Handler{Name: "jwt", Config: emptyJWTIstioConfig()} diff --git a/internal/validation/v2alpha1/jwt.go b/internal/validation/v2alpha1/jwt.go new file mode 100644 index 000000000..16581787e --- /dev/null +++ b/internal/validation/v2alpha1/jwt.go @@ -0,0 +1,203 @@ +package v2alpha1 + +import ( + "errors" + "fmt" + gatewayv2alpha1 "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" + "strings" + + "github.com/kyma-project/api-gateway/internal/validation" +) + +func validateJwt(parentAttributePath string, rule *gatewayv2alpha1.Rule) []validation.Failure { + var failures []validation.Failure + + if rule.Jwt == nil { + return nil + } + + jwtAttributePath := parentAttributePath + ".jwt" + + failures = append(failures, hasInvalidAuthorizations(jwtAttributePath, rule.Jwt.Authorizations)...) + failures = append(failures, hasInvalidAuthentications(jwtAttributePath, rule.Jwt.Authentications)...) + + return failures +} + +func hasInvalidRequiredScopes(authorization gatewayv2alpha1.JwtAuthorization) error { + if authorization.RequiredScopes == nil { + return nil + } + if len(authorization.RequiredScopes) == 0 { + return errors.New("value is empty") + } + for _, scope := range authorization.RequiredScopes { + if scope == "" { + return errors.New("scope value is empty") + } + } + return nil +} + +func hasInvalidAudiences(authorization gatewayv2alpha1.JwtAuthorization) error { + if authorization.Audiences == nil { + return nil + } + if len(authorization.Audiences) == 0 { + return errors.New("value is empty") + } + for _, audience := range authorization.Audiences { + if audience == "" { + return errors.New("audience value is empty") + } + } + return nil +} + +func hasInvalidAuthentications(parentAttributePath string, authentications []*gatewayv2alpha1.JwtAuthentication) []validation.Failure { + var failures []validation.Failure + authenticationsAttrPath := parentAttributePath + ".authentications" + + hasFromHeaders, hasFromParams := false, false + if len(authentications) == 0 { + return []validation.Failure{ + { + AttributePath: authenticationsAttrPath, + Message: "A JWT config must have at least one authentication", + }, + } + } + for i, authentication := range authentications { + issuerErr := validateJwtIssuer(authentication.Issuer) + if issuerErr != nil { + attrPath := fmt.Sprintf("%s[%d]%s", authenticationsAttrPath, i, ".issuer") + failures = append(failures, validation.Failure{AttributePath: attrPath, Message: fmt.Sprintf("value is empty or not a valid uri err=%s", issuerErr)}) + } + + invalidJwksUri, err := validation.IsInvalidURL(authentication.JwksUri) + if invalidJwksUri { + attrPath := fmt.Sprintf("%s[%d]%s", authenticationsAttrPath, i, ".jwksUri") + failures = append(failures, validation.Failure{AttributePath: attrPath, Message: fmt.Sprintf("value is empty or not a valid uri err=%s", err)}) + } + if len(authentication.FromHeaders) > 0 { + if hasFromParams { + attrPath := fmt.Sprintf("%s[%d]%s", authenticationsAttrPath, i, ".fromHeaders") + failures = append(failures, validation.Failure{AttributePath: attrPath, Message: "mixture of multiple fromHeaders and fromParams is not supported"}) + } + hasFromHeaders = true + } + if len(authentication.FromParams) > 0 { + if hasFromHeaders { + attrPath := fmt.Sprintf("%s[%d]%s", authenticationsAttrPath, i, ".fromParams") + failures = append(failures, validation.Failure{AttributePath: attrPath, Message: "mixture of multiple fromHeaders and fromParams is not supported"}) + } + hasFromParams = true + } + if len(authentication.FromHeaders) > 1 { + attrPath := fmt.Sprintf("%s[%d]%s", authenticationsAttrPath, i, ".fromHeaders") + failures = append(failures, validation.Failure{AttributePath: attrPath, Message: "multiple fromHeaders are not supported"}) + } + if len(authentication.FromParams) > 1 { + attrPath := fmt.Sprintf("%s[%d]%s", authenticationsAttrPath, i, ".fromParams") + failures = append(failures, validation.Failure{AttributePath: attrPath, Message: "multiple fromParams are not supported"}) + } + } + return failures +} + +func hasInvalidAuthorizations(parentAttributePath string, authorizations []*gatewayv2alpha1.JwtAuthorization) []validation.Failure { + var failures []validation.Failure + authorizationsAttrPath := parentAttributePath + ".authorizations" + + if authorizations == nil { + return nil + } + if len(authorizations) == 0 { + return append(failures, validation.Failure{AttributePath: authorizationsAttrPath, Message: "authorizations defined, but no configuration exists"}) + } + + for i, authorization := range authorizations { + if authorization == nil { + attrPath := fmt.Sprintf("%s[%d]", authorizationsAttrPath, i) + failures = append(failures, validation.Failure{AttributePath: attrPath, Message: "authorization is empty"}) + continue + } + + err := hasInvalidRequiredScopes(*authorization) + if err != nil { + attrPath := fmt.Sprintf("%s[%d]%s", authorizationsAttrPath, i, ".requiredScopes") + failures = append(failures, validation.Failure{AttributePath: attrPath, Message: err.Error()}) + } + + err = hasInvalidAudiences(*authorization) + if err != nil { + attrPath := fmt.Sprintf("%s[%d]%s", authorizationsAttrPath, i, ".audiences") + failures = append(failures, validation.Failure{AttributePath: attrPath, Message: err.Error()}) + } + } + + return failures +} + +// validateJwtAuthenticationEquality validates that all JWT authorizations with the same issuer and JWKS URI have the same configuration +func validateJwtAuthenticationEquality(parentAttributePath string, rules []gatewayv2alpha1.Rule) []validation.Failure { + var failures []validation.Failure + jwtAuths := map[string]*gatewayv2alpha1.JwtAuthentication{} + + for ruleIndex, rule := range rules { + + if rule.Jwt == nil { + continue + } + + for authenticationIndex, authentication := range rule.Jwt.Authentications { + authAttributePath := fmt.Sprintf("%s[%d].jwt.authentications[%d]", parentAttributePath, ruleIndex, authenticationIndex) + + jwtAuthKey := authentication.Issuer + authentication.JwksUri + if jwtAuths[jwtAuthKey] != nil && !jwtAuthenticationsEqual(authentication, jwtAuths[jwtAuthKey]) { + failures = append(failures, validation.Failure{AttributePath: authAttributePath, Message: "multiple jwt configurations that differ for the same issuer"}) + } else { + jwtAuths[jwtAuthKey] = authentication + } + } + } + return failures +} + +func jwtAuthenticationsEqual(auth1 *gatewayv2alpha1.JwtAuthentication, auth2 *gatewayv2alpha1.JwtAuthentication) bool { + if auth1.Issuer != auth2.Issuer || auth1.JwksUri != auth2.JwksUri { + return false + } + if len(auth1.FromHeaders) != len(auth2.FromHeaders) { + return false + } + for i, auth1FromHeader := range auth1.FromHeaders { + if auth1FromHeader.Name != auth2.FromHeaders[i].Name || auth1FromHeader.Prefix != auth2.FromHeaders[i].Prefix { + return false + } + } + if len(auth1.FromParams) != len(auth2.FromParams) { + return false + } + for i, auth1FromParam := range auth1.FromParams { + if auth1FromParam != auth2.FromParams[i] { + return false + } + } + return true +} + +func validateJwtIssuer(issuer string) error { + if issuer == "" { + return errors.New("value is empty") + } + + // If issuer contains ':' it must be a valid URI, see https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1 + if strings.Contains(issuer, ":") { + if isInvalid, err := validation.IsInvalidURL(issuer); isInvalid { + return err + } + } + + return nil +} diff --git a/internal/validation/v2alpha1/jwt_authentications_test.go b/internal/validation/v2alpha1/jwt_authentications_test.go new file mode 100644 index 000000000..4aaa1b8ff --- /dev/null +++ b/internal/validation/v2alpha1/jwt_authentications_test.go @@ -0,0 +1,252 @@ +package v2alpha1 + +import ( + gatewayv2alpha1 "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("JWT authentications validation", func() { + + It("should fail validation when jwksUri is not a URI", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "the_issuer/", + JwksUri: "no_url", + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal("rule.jwt.authentications[0].jwksUri")) + Expect(problems[0].Message).To(ContainSubstring("value is empty or not a valid uri")) + }) + + It("should fail validation when issuer and jwksUri are empty", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "", + JwksUri: "", + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(2)) + Expect(problems[0].AttributePath).To(Equal("rule.jwt.authentications[0].issuer")) + Expect(problems[0].Message).To(ContainSubstring("value is empty or not a valid uri")) + Expect(problems[1].AttributePath).To(Equal("rule.jwt.authentications[0].jwksUri")) + Expect(problems[1].Message).To(ContainSubstring("value is empty or not a valid uri")) + }) + + It("should fail validation when issuer contains ':' but is not a URI", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "://example", + JwksUri: "http://issuer.test/.well-known/jwks.json", + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal("rule.jwt.authentications[0].issuer")) + Expect(problems[0].Message).To(ContainSubstring("value is empty or not a valid uri")) + }) + + It("should pass validation when issuer contains ':' and is a URI", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.example.com", + JwksUri: "http://issuer.test/.well-known/jwks.json", + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(0)) + }) + + It("should pass validation when issuer is not empty has contains no ':'", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "testing@secure.istio.io", + JwksUri: "http://issuer.test/.well-known/jwks.json", + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(0)) + }) + + It("should succeed for config with plain HTTP JWKSUrls and trustedIssuers", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "http://issuer.test", + JwksUri: "http://issuer.test/.well-known/jwks.json", + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(0)) + }) + + It("should succeed for config with file JWKSUrls and HTTPS trustedIssuers", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(0)) + }) + + It("should succeed for config with HTTPS JWKSUrls and trustedIssuers", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test//", + JwksUri: "https://issuer.test/.well-known/jwks.json", + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(0)) + }) + + It("Should fail validation when authentication has more than one fromHeaders", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test//", + JwksUri: "https://issuer.test/.well-known/jwks.json", + FromHeaders: []*gatewayv2alpha1.JwtHeader{{Name: "header1"}, {Name: "header2"}}, + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal("rule.jwt.authentications[0].fromHeaders")) + Expect(problems[0].Message).To(Equal("multiple fromHeaders are not supported")) + }) + + It("should fail validation when authentication has more than one fromParams", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test//", + JwksUri: "https://issuer.test/.well-known/jwks.json", + FromParams: []string{"param1", "param2"}, + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal("rule.jwt.authentications[0].fromParams")) + Expect(problems[0].Message).To(Equal("multiple fromParams are not supported")) + }) + + It("should fail validation when multiple authentications have mixture of fromHeaders and fromParams", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test//", + JwksUri: "file://.well-known/jwks.json", + FromParams: []string{"param1"}, + }, + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + FromHeaders: []*gatewayv2alpha1.JwtHeader{{Name: "header1"}}, + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal("rule.jwt.authentications[1].fromHeaders")) + Expect(problems[0].Message).To(Equal("mixture of multiple fromHeaders and fromParams is not supported")) + }) +}) diff --git a/internal/validation/v2alpha1/jwt_authorizations_test.go b/internal/validation/v2alpha1/jwt_authorizations_test.go new file mode 100644 index 000000000..e9354e9f5 --- /dev/null +++ b/internal/validation/v2alpha1/jwt_authorizations_test.go @@ -0,0 +1,272 @@ +package v2alpha1 + +import ( + gatewayv2alpha1 "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("JWT authorizations validation", func() { + + It("should fail validation when authorizations is defined, but empty", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + }, + }, + Authorizations: []*gatewayv2alpha1.JwtAuthorization{}, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal("rule.jwt.authorizations")) + Expect(problems[0].Message).To(Equal("authorizations defined, but no configuration exists")) + }) + + It("should fail validation when authorization is empty", func() { + //given + var auth *gatewayv2alpha1.JwtAuthorization + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + }, + }, + Authorizations: []*gatewayv2alpha1.JwtAuthorization{ + auth, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal("rule.jwt.authorizations[0]")) + Expect(problems[0].Message).To(Equal("authorization is empty")) + }) + + Context("required scopes", func() { + It("should fail for config with empty required scopes", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + }, + }, + Authorizations: []*gatewayv2alpha1.JwtAuthorization{ + { + RequiredScopes: []string{}, + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal("rule.jwt.authorizations[0].requiredScopes")) + Expect(problems[0].Message).To(Equal("value is empty")) + }) + + It("should fail for config with empty string in required scopes", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + }, + }, + Authorizations: []*gatewayv2alpha1.JwtAuthorization{ + { + RequiredScopes: []string{"scope-a", ""}, + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal("rule.jwt.authorizations[0].requiredScopes")) + Expect(problems[0].Message).To(Equal("scope value is empty")) + }) + + It("should succeed for config with two required scopes", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + }, + }, + Authorizations: []*gatewayv2alpha1.JwtAuthorization{ + { + RequiredScopes: []string{"scope-a", "scope-b"}, + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(0)) + }) + + It("should successful validate config without a required scope", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + }, + }, + Authorizations: []*gatewayv2alpha1.JwtAuthorization{ + { + Audiences: []string{"www.example.com"}, + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(0)) + }) + }) + + Context("audiences", func() { + + It("should fail validation for config with empty audiences", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + }, + }, + Authorizations: []*gatewayv2alpha1.JwtAuthorization{ + { + Audiences: []string{}, + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal("rule.jwt.authorizations[0].audiences")) + Expect(problems[0].Message).To(Equal("value is empty")) + }) + + It("should fail validation for config with empty string in audiences", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + }, + }, + Authorizations: []*gatewayv2alpha1.JwtAuthorization{ + { + Audiences: []string{"www.example.com", ""}, + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal("rule.jwt.authorizations[0].audiences")) + Expect(problems[0].Message).To(Equal("audience value is empty")) + }) + + It("should successful validate config with an audience", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + }, + }, + Authorizations: []*gatewayv2alpha1.JwtAuthorization{ + { + Audiences: []string{"www.example.com"}, + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(0)) + }) + + It("should successful validate config without audiences", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + }, + }, + Authorizations: []*gatewayv2alpha1.JwtAuthorization{ + { + RequiredScopes: []string{"www.example.com"}, + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(0)) + }) + }) +}) diff --git a/internal/validation/v2alpha1/jwt_test.go b/internal/validation/v2alpha1/jwt_test.go new file mode 100644 index 000000000..26a2e69d0 --- /dev/null +++ b/internal/validation/v2alpha1/jwt_test.go @@ -0,0 +1,207 @@ +package v2alpha1 + +import ( + gatewayv2alpha1 "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("validateJwt", func() { + + It("should fail with empty JWT config", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{}, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal("rule.jwt.authentications")) + Expect(problems[0].Message).To(Equal("A JWT config must have at least one authentication")) + }) + + It("should fail when Authorizations are configured, but empty Authentications", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authorizations: []*gatewayv2alpha1.JwtAuthorization{ + { + RequiredScopes: []string{"scope-a", "scope-b"}, + }, + }, + }, + } + + //when + problems := validateJwt("rule", &rule) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal("rule.jwt.authentications")) + Expect(problems[0].Message).To(Equal("A JWT config must have at least one authentication")) + }) +}) + +var _ = Describe("validateJwtAuthenticationEquality", func() { + It("should fail validation when multiple authentications fromHeaders configuration", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + FromHeaders: []*gatewayv2alpha1.JwtHeader{{Name: "header1"}}, + }, + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + FromHeaders: []*gatewayv2alpha1.JwtHeader{{Name: "header2"}}, + }, + }, + }, + } + + //when + problems := validateJwtAuthenticationEquality(".spec.rules", []gatewayv2alpha1.Rule{rule}) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal(".spec.rules[0].jwt.authentications[1]")) + Expect(problems[0].Message).To(Equal("multiple jwt configurations that differ for the same issuer")) + }) + + It("should fail validation when multiple authentications fromParams configuration", func() { + //given + rule := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + FromParams: []string{"param1"}, + }, + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + FromParams: []string{"param2"}, + }, + }, + }, + } + + //when + problems := validateJwtAuthenticationEquality(".spec.rules", []gatewayv2alpha1.Rule{rule}) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal(".spec.rules[0].jwt.authentications[1]")) + Expect(problems[0].Message).To(Equal("multiple jwt configurations that differ for the same issuer")) + }) + + It("should fail when multiple jwt handlers specify different token from types of configurations", func() { + //given + ruleFromHeaders := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + FromHeaders: []*gatewayv2alpha1.JwtHeader{{Name: "header1"}}, + }, + }, + }, + } + + ruleFromParams := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + FromParams: []string{"param1"}, + }, + }, + }, + } + + //when + problems := validateJwtAuthenticationEquality(".spec.rules", []gatewayv2alpha1.Rule{ruleFromHeaders, ruleFromParams}) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal(".spec.rules[1].jwt.authentications[0]")) + Expect(problems[0].Message).To(Equal("multiple jwt configurations that differ for the same issuer")) + }) + + It("should fail when multiple jwt handlers specify different token from headers configuration", func() { + //given + ruleFromHeaders := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + FromHeaders: []*gatewayv2alpha1.JwtHeader{{Name: "header1"}}, + }, + }, + }, + } + + ruleFromHeadersDifferent := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + FromHeaders: []*gatewayv2alpha1.JwtHeader{{Name: "header2"}}, + }, + }, + }, + } + + //when + problems := validateJwtAuthenticationEquality(".spec.rules", []gatewayv2alpha1.Rule{ruleFromHeaders, ruleFromHeadersDifferent}) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal(".spec.rules[1].jwt.authentications[0]")) + Expect(problems[0].Message).To(Equal("multiple jwt configurations that differ for the same issuer")) + }) + + It("should succeed when multiple jwt handlers specify same token from headers configuration", func() { + //given + ruleFromHeaders := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + FromHeaders: []*gatewayv2alpha1.JwtHeader{{Name: "header1"}}, + }, + }, + }, + } + + ruleFromHeadersEqual := gatewayv2alpha1.Rule{ + Jwt: &gatewayv2alpha1.JwtConfig{ + Authentications: []*gatewayv2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.test/", + JwksUri: "file://.well-known/jwks.json", + FromHeaders: []*gatewayv2alpha1.JwtHeader{{Name: "header1"}}, + }, + }, + }, + } + + //when + problems := validateJwtAuthenticationEquality(".spec.rules", []gatewayv2alpha1.Rule{ruleFromHeaders, ruleFromHeadersEqual}) + + //then + Expect(problems).To(HaveLen(0)) + }) +}) diff --git a/internal/validation/v2alpha1/rules.go b/internal/validation/v2alpha1/rules.go new file mode 100644 index 000000000..97c240ff6 --- /dev/null +++ b/internal/validation/v2alpha1/rules.go @@ -0,0 +1,75 @@ +package v2alpha1 + +import ( + "context" + "fmt" + gatewayv2alpha1 "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" + "github.com/kyma-project/api-gateway/internal/validation" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func validateRules(ctx context.Context, client client.Client, parentAttributePath string, apiRule *gatewayv2alpha1.APIRule) []validation.Failure { + var problems []validation.Failure + rulesAttributePath := parentAttributePath + ".rules" + + rules := apiRule.Spec.Rules + if len(rules) == 0 { + problems = append(problems, validation.Failure{AttributePath: rulesAttributePath, Message: "No rules defined"}) + return problems + } + + if hasPathAndMethodDuplicates(rules) { + problems = append(problems, validation.Failure{AttributePath: rulesAttributePath, Message: "multiple rules defined for the same path and method"}) + } + + for i, rule := range rules { + ruleAttributePath := fmt.Sprintf("%s[%d]", rulesAttributePath, i) + + if apiRule.Spec.Service == nil && rule.Service == nil { + problems = append(problems, validation.Failure{AttributePath: ruleAttributePath + ".service", Message: "The rule must define a service, because no service is defined on spec level"}) + } + + if rule.Jwt != nil { + injectionFailures, err := validateSidecarInjection(ctx, client, ruleAttributePath, apiRule, rule) + if err != nil { + problems = append(problems, validation.Failure{AttributePath: ruleAttributePath, Message: fmt.Sprintf("Failed to execute sidecar injection validation, err: %s", err)}) + } + + problems = append(problems, injectionFailures...) + + jwtFailures := validateJwt(ruleAttributePath, &rule) + problems = append(problems, jwtFailures...) + } + + } + + jwtAuthFailures := validateJwtAuthenticationEquality(rulesAttributePath, rules) + problems = append(problems, jwtAuthFailures...) + + return problems +} + +func hasPathAndMethodDuplicates(rules []gatewayv2alpha1.Rule) bool { + duplicates := map[string]bool{} + + if len(rules) > 1 { + for _, rule := range rules { + if len(rule.Methods) > 0 { + for _, method := range rule.Methods { + tmp := fmt.Sprintf("%s:%s", rule.Path, method) + if duplicates[tmp] { + return true + } + duplicates[tmp] = true + } + } else { + if duplicates[rule.Path] { + return true + } + duplicates[rule.Path] = true + } + } + } + + return false +} diff --git a/internal/validation/v2alpha1/rules_test.go b/internal/validation/v2alpha1/rules_test.go new file mode 100644 index 000000000..e7860239d --- /dev/null +++ b/internal/validation/v2alpha1/rules_test.go @@ -0,0 +1,313 @@ +package v2alpha1 + +import ( + "context" + "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + "net/http" +) + +var _ = Describe("Validate rules", func() { + sampleServiceName := "some-service" + host := v2alpha1.Host(sampleServiceName + ".test.dev") + + It("should fail for empty rules", func() { + //given + apiRule := &v2alpha1.APIRule{ + Spec: v2alpha1.APIRuleSpec{ + Rules: nil, + Service: getApiRuleService(sampleServiceName, uint32(8080)), + Hosts: []*v2alpha1.Host{&host}, + }, + } + + service := getService(sampleServiceName) + fakeClient := createFakeClient(service) + + //when + problems := validateRules(context.Background(), fakeClient, ".spec", apiRule) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal(".spec.rules")) + Expect(problems[0].Message).To(Equal("No rules defined")) + }) + + It("should return an error when no service is defined for rule with no service on spec level", func() { + //given + apiRule := &v2alpha1.APIRule{ + Spec: v2alpha1.APIRuleSpec{ + Hosts: []*v2alpha1.Host{&host}, + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + NoAuth: ptr.To(true), + }, + }, + }, + } + + service := getService(sampleServiceName, "default") + fakeClient := createFakeClient(service) + + //when + problems := validateRules(context.Background(), fakeClient, ".spec", apiRule) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal(".spec.rules[0].service")) + Expect(problems[0].Message).To(Equal("The rule must define a service, because no service is defined on spec level")) + }) + + It("should report multiple problem at once", func() { + //given + apiRule := &v2alpha1.APIRule{ + Spec: v2alpha1.APIRuleSpec{ + Service: getApiRuleService(sampleServiceName, uint32(8080)), + Hosts: []*v2alpha1.Host{&host}, + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + Jwt: &v2alpha1.JwtConfig{ + Authentications: []*v2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.example.com", + JwksUri: "https://issuer.test/.well-known/jwks.json", + }, + }, + }, + }, + { + Path: "/abc", + NoAuth: ptr.To(true), + }, + { + Path: "/test", + Jwt: &v2alpha1.JwtConfig{}, + }, + }, + }, + } + + service := getService(sampleServiceName) + fakeClient := createFakeClient(service) + + //when + problems := validateRules(context.Background(), fakeClient, ".spec", apiRule) + + //then + Expect(problems).To(HaveLen(2)) + }) + + It("should fail for the same path and method", func() { + //given + apiRule := &v2alpha1.APIRule{ + Spec: v2alpha1.APIRuleSpec{ + Service: getApiRuleService(sampleServiceName, uint32(8080)), + Hosts: []*v2alpha1.Host{&host}, + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + NoAuth: ptr.To(true), + Methods: []v2alpha1.HttpMethod{http.MethodGet}, + }, + { + Path: "/abc", + NoAuth: ptr.To(true), + Methods: []v2alpha1.HttpMethod{http.MethodGet, http.MethodPost}, + }, + }, + }, + } + + service := getService(sampleServiceName) + fakeClient := createFakeClient(service) + + //when + problems := validateRules(context.Background(), fakeClient, ".spec", apiRule) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal(".spec.rules")) + Expect(problems[0].Message).To(Equal("multiple rules defined for the same path and method")) + }) + + It("should succeed for the same path but different methods", func() { + //given + apiRule := &v2alpha1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + UID: "67890", + }, + Spec: v2alpha1.APIRuleSpec{ + Service: getApiRuleService(sampleServiceName, uint32(8080)), + Hosts: []*v2alpha1.Host{&host}, + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + NoAuth: ptr.To(true), + Methods: []v2alpha1.HttpMethod{http.MethodPost}, + }, + { + Path: "/abc", + NoAuth: ptr.To(true), + Methods: []v2alpha1.HttpMethod{http.MethodGet}, + }, + }, + }, + } + + service := getService(sampleServiceName) + fakeClient := createFakeClient(service) + + //when + problems := validateRules(context.Background(), fakeClient, ".spec", apiRule) + + //then + Expect(problems).To(HaveLen(0)) + }) + + It("should not fail with service without labels selector by when NoAuth is used", func() { + //given + apiRule := &v2alpha1.APIRule{ + Spec: v2alpha1.APIRuleSpec{ + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + NoAuth: ptr.To(true), + Methods: []v2alpha1.HttpMethod{http.MethodPost}, + }, + }, + Service: getApiRuleService(sampleServiceName, uint32(8080)), + Hosts: []*v2alpha1.Host{&host}, + }, + } + + service := getService(sampleServiceName) + service.Spec.Selector = map[string]string{} + fakeClient := createFakeClient(service) + + //when + problems := validateRules(context.Background(), fakeClient, ".spec", apiRule) + + //then + Expect(problems).To(HaveLen(0)) + }) + + It("should not fail with service on path level when NoAuth is used", func() { + //given + apiRule := &v2alpha1.APIRule{ + Spec: v2alpha1.APIRuleSpec{ + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + Service: getApiRuleService(sampleServiceName, uint32(8080)), + NoAuth: ptr.To(true), + Methods: []v2alpha1.HttpMethod{http.MethodPost}, + }, + }, + Hosts: []*v2alpha1.Host{&host}, + }, + } + + service := getService(sampleServiceName) + service.Spec.Selector = map[string]string{} + fakeClient := createFakeClient(service) + + //when + problems := validateRules(context.Background(), fakeClient, ".spec", apiRule) + + //then + Expect(problems).To(HaveLen(0)) + }) + + It("should succeed with service without namespace", func() { + //given + apiRule := &v2alpha1.APIRule{ + Spec: v2alpha1.APIRuleSpec{ + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + NoAuth: ptr.To(true), + Methods: []v2alpha1.HttpMethod{http.MethodPost}, + }, + }, + Service: getApiRuleService(sampleServiceName, uint32(8080)), + Hosts: []*v2alpha1.Host{&host}, + }, + } + + service := getService(sampleServiceName) + fakeClient := createFakeClient(service) + + //when + problems := validateRules(context.Background(), fakeClient, ".spec", apiRule) + + //then + Expect(problems).To(HaveLen(0)) + }) + + It("should succeed with service on path level without namespace", func() { + //given + apiRule := &v2alpha1.APIRule{ + Spec: v2alpha1.APIRuleSpec{ + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + Service: getApiRuleService(sampleServiceName, uint32(8080)), + NoAuth: ptr.To(true), + Methods: []v2alpha1.HttpMethod{http.MethodPost}, + }, + }, + Hosts: []*v2alpha1.Host{&host}, + }, + } + + service := getService(sampleServiceName) + fakeClient := createFakeClient(service) + + //when + problems := validateRules(context.Background(), fakeClient, ".spec", apiRule) + + //then + Expect(problems).To(HaveLen(0)) + }) + + It("should invoke sidecar injection validation", func() { + //given + apiRule := &v2alpha1.APIRule{ + Spec: v2alpha1.APIRuleSpec{ + Service: getApiRuleService(sampleServiceName, uint32(8080)), + Hosts: []*v2alpha1.Host{&host}, + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + NoAuth: ptr.To(true), + Jwt: &v2alpha1.JwtConfig{ + Authentications: []*v2alpha1.JwtAuthentication{ + { + Issuer: "https://issuer.example.com", + JwksUri: "https://issuer.test/.well-known/jwks.json", + }, + }, + }, + }, + }, + }, + } + + service := getService(sampleServiceName) + service.Spec.Selector = map[string]string{} + fakeClient := createFakeClient(service) + + //when + problems := validateRules(context.Background(), fakeClient, ".spec", apiRule) + + // then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal(".spec.rules[0].injection")) + Expect(problems[0].Message).To(Equal("Service cannot have empty label selectors when the API Rule strategy is JWT")) + }) +}) diff --git a/internal/validation/v2alpha1/sidecar_injection.go b/internal/validation/v2alpha1/sidecar_injection.go new file mode 100644 index 000000000..c9c77bc06 --- /dev/null +++ b/internal/validation/v2alpha1/sidecar_injection.go @@ -0,0 +1,83 @@ +package v2alpha1 + +import ( + "context" + "fmt" + gatewayv2alpha1 "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" + "github.com/kyma-project/api-gateway/internal/validation" + apiv1beta1 "istio.io/api/type/v1beta1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func validateSidecarInjection(ctx context.Context, k8sClient client.Client, parentAttributePath string, apiRule *gatewayv2alpha1.APIRule, rule gatewayv2alpha1.Rule) (problems []validation.Failure, err error) { + + podWorkloadSelector, err := getSelectorFromService(ctx, k8sClient, apiRule, rule) + if err != nil { + return nil, err + } + + return validation.NewInjectionValidator(ctx, k8sClient).Validate(parentAttributePath, podWorkloadSelector.selector, podWorkloadSelector.namespace) +} + +func findServiceNamespace(apiRule *gatewayv2alpha1.APIRule, rule gatewayv2alpha1.Rule) string { + // Fallback direction for the upstream service namespace: Rule.Service > Spec.Service > APIRule + if rule.Service != nil && rule.Service.Namespace != nil { + return *rule.Service.Namespace + } + if apiRule != nil && apiRule.Spec.Service != nil && apiRule.Spec.Service.Namespace != nil { + return *apiRule.Spec.Service.Namespace + } + return apiRule.Namespace +} + +type podSelector struct { + selector *apiv1beta1.WorkloadSelector + namespace string +} + +func getSelectorFromService(ctx context.Context, client client.Client, apiRule *gatewayv2alpha1.APIRule, rule gatewayv2alpha1.Rule) (podSelector, error) { + + var service *gatewayv2alpha1.Service + if rule.Service != nil { + service = rule.Service + } else { + service = apiRule.Spec.Service + } + + if service == nil || service.Name == nil { + return podSelector{}, fmt.Errorf("service name is required but missing") + } + serviceNamespacedName := types.NamespacedName{Name: *service.Name} + if service.Namespace != nil { + serviceNamespacedName.Namespace = *service.Namespace + } else { + serviceNamespacedName.Namespace = findServiceNamespace(apiRule, rule) + } + + if serviceNamespacedName.Namespace == "" { + serviceNamespacedName.Namespace = "default" + } + + svc := &corev1.Service{} + err := client.Get(ctx, serviceNamespacedName, svc) + if err != nil { + return podSelector{}, err + } + + if len(svc.Spec.Selector) == 0 { + return podSelector{}, nil + } + + workloadSelector := apiv1beta1.WorkloadSelector{} + workloadSelector.MatchLabels = map[string]string{} + for label, value := range svc.Spec.Selector { + workloadSelector.MatchLabels[label] = value + } + + return podSelector{ + selector: &workloadSelector, + namespace: serviceNamespacedName.Namespace, + }, nil +} diff --git a/internal/validation/v2alpha1/sidecar_injection_test.go b/internal/validation/v2alpha1/sidecar_injection_test.go new file mode 100644 index 000000000..5742872ae --- /dev/null +++ b/internal/validation/v2alpha1/sidecar_injection_test.go @@ -0,0 +1,408 @@ +package v2alpha1 + +import ( + "context" + "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" + "k8s.io/utils/ptr" + "net/http" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +var _ = Describe("Sidecar injection validation", func() { + It("should use service namespace and name from rule for pod selection when it's defined", func() { + //given + apiRule := &v2alpha1.APIRule{ + ObjectMeta: v1.ObjectMeta{ + Name: "api-rule", + Namespace: "api-rule-ns", + }, + Spec: v2alpha1.APIRuleSpec{ + Service: getApiRuleService("spec-level", uint32(8080), ptr.To("spec-level-ns")), + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + Service: getApiRuleService("rule-level", uint32(8080), ptr.To("rule-level-ns")), + NoAuth: ptr.To(true), + Methods: []v2alpha1.HttpMethod{http.MethodPost}, + }, + }, + Hosts: getHosts("test.dev"), + }, + } + + ruleService := getService("rule-level", "rule-level-ns") + specService := getService("spec-level", "spec-level-ns") + ruleLevelNs := getNamespace("rule-level-ns") + specLevelNs := getNamespace("spec-level-ns") + + fakeClient := createFakeClient(ruleService, specService, ruleLevelNs, specLevelNs) + + err := fakeClient.Create(context.Background(), &corev1.Pod{ + ObjectMeta: v1.ObjectMeta{ + Name: "test", + Namespace: "rule-level-ns", + Labels: map[string]string{ + "app": "rule-level", + }, + }, + }) + Expect(err).NotTo(HaveOccurred()) + + //when + problems, err := validateSidecarInjection(context.Background(), fakeClient, "some.attribute", apiRule, apiRule.Spec.Rules[0]) + Expect(err).NotTo(HaveOccurred()) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].Message).To(Equal("Pod rule-level-ns/test does not have an injected istio sidecar")) + }) + + It("should use service namespace from spec and service name from rule for pod selection when no service namespace is defined on rule-level", func() { + //given + apiRule := &v2alpha1.APIRule{ + ObjectMeta: v1.ObjectMeta{ + Name: "api-rule", + Namespace: "api-rule-ns", + }, + Spec: v2alpha1.APIRuleSpec{ + Service: getApiRuleService("spec-level", uint32(8080), ptr.To("spec-level-ns")), + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + Service: getApiRuleService("rule-level", uint32(8080)), + NoAuth: ptr.To(true), + Methods: []v2alpha1.HttpMethod{http.MethodPost}, + }, + }, + Hosts: getHosts("test.dev"), + }, + } + + ruleService := getService("rule-level", "spec-level-ns") + specService := getService("spec-level", "spec-level-ns") + specLevelNs := getNamespace("spec-level-ns") + fakeClient := createFakeClient(ruleService, specService, specLevelNs) + + err := fakeClient.Create(context.Background(), &corev1.Pod{ + ObjectMeta: v1.ObjectMeta{ + Name: "test", + Namespace: "spec-level-ns", + Labels: map[string]string{ + "app": "rule-level", + }, + }, + }) + Expect(err).NotTo(HaveOccurred()) + + //when + problems, err := validateSidecarInjection(context.Background(), fakeClient, "some.attribute", apiRule, apiRule.Spec.Rules[0]) + Expect(err).NotTo(HaveOccurred()) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].Message).To(Equal("Pod spec-level-ns/test does not have an injected istio sidecar")) + }) + + It("should use service namespace and name from spec for pod selection when no service is defined on rule-level", func() { + //given + apiRule := &v2alpha1.APIRule{ + ObjectMeta: v1.ObjectMeta{ + Name: "api-rule", + Namespace: "api-rule-ns", + }, + Spec: v2alpha1.APIRuleSpec{ + Service: getApiRuleService("spec-level", uint32(8080), ptr.To("spec-level-ns")), + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + NoAuth: ptr.To(true), + Methods: []v2alpha1.HttpMethod{http.MethodPost}, + }, + }, + Hosts: getHosts("test.dev"), + }, + } + + specService := getService("spec-level", "spec-level-ns") + specLevelNs := getNamespace("spec-level-ns") + fakeClient := createFakeClient(specService, specLevelNs) + + err := fakeClient.Create(context.Background(), &corev1.Pod{ + ObjectMeta: v1.ObjectMeta{ + Name: "test", + Namespace: "spec-level-ns", + Labels: map[string]string{ + "app": "spec-level", + }, + }, + }) + Expect(err).NotTo(HaveOccurred()) + + //when + problems, err := validateSidecarInjection(context.Background(), fakeClient, "some.attribute", apiRule, apiRule.Spec.Rules[0]) + Expect(err).NotTo(HaveOccurred()) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].Message).To(Equal("Pod spec-level-ns/test does not have an injected istio sidecar")) + }) + + It("should use service namespace from APIRule and service name from rule for pod selection when no service namespace is defined on spec or rule", func() { + //given + apiRule := &v2alpha1.APIRule{ + ObjectMeta: v1.ObjectMeta{ + Name: "api-rule", + Namespace: "api-rule-ns", + }, + Spec: v2alpha1.APIRuleSpec{ + Service: getApiRuleService("spec-level", uint32(8080)), + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + Service: getApiRuleService("rule-level", uint32(8080)), + NoAuth: ptr.To(true), + Methods: []v2alpha1.HttpMethod{http.MethodPost}, + }, + }, + Hosts: getHosts("test.dev"), + }, + } + + ruleService := getService("rule-level", "api-rule-ns") + specService := getService("spec-level", "api-rule-ns") + apiRuleNs := getNamespace("api-rule-ns") + + fakeClient := createFakeClient(ruleService, specService, apiRuleNs) + + err := fakeClient.Create(context.Background(), &corev1.Pod{ + ObjectMeta: v1.ObjectMeta{ + Name: "test", + Namespace: "api-rule-ns", + Labels: map[string]string{ + "app": "rule-level", + }, + }, + }) + Expect(err).NotTo(HaveOccurred()) + + //when + problems, err := validateSidecarInjection(context.Background(), fakeClient, "some.attribute", apiRule, apiRule.Spec.Rules[0]) + Expect(err).NotTo(HaveOccurred()) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].Message).To(Equal("Pod api-rule-ns/test does not have an injected istio sidecar")) + }) + + It("should use service namespace from APIRule and service name from spec for pod selection when no service namespace is defined on spec or rule", func() { + //given + apiRule := &v2alpha1.APIRule{ + ObjectMeta: v1.ObjectMeta{ + Name: "api-rule", + Namespace: "api-rule-ns", + }, + Spec: v2alpha1.APIRuleSpec{ + Service: getApiRuleService("spec-level", uint32(8080)), + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + NoAuth: ptr.To(true), + Methods: []v2alpha1.HttpMethod{http.MethodPost}, + }, + }, + Hosts: getHosts("test.dev"), + }, + } + + specService := getService("spec-level", "api-rule-ns") + apiRuleNs := getNamespace("api-rule-ns") + + fakeClient := createFakeClient(specService, apiRuleNs) + + err := fakeClient.Create(context.Background(), &corev1.Pod{ + ObjectMeta: v1.ObjectMeta{ + Name: "test", + Namespace: "api-rule-ns", + Labels: map[string]string{ + "app": "spec-level", + }, + }, + }) + Expect(err).NotTo(HaveOccurred()) + + //when + problems, err := validateSidecarInjection(context.Background(), fakeClient, "some.attribute", apiRule, apiRule.Spec.Rules[0]) + Expect(err).NotTo(HaveOccurred()) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].Message).To(Equal("Pod api-rule-ns/test does not have an injected istio sidecar")) + }) + + It("should use 'default' as service namespace for pod selection and service name from rule when service namespace contains an empty string", func() { + //given + apiRule := &v2alpha1.APIRule{ + ObjectMeta: v1.ObjectMeta{ + Name: "api-rule", + Namespace: "api-rule-ns", + }, + Spec: v2alpha1.APIRuleSpec{ + Service: getApiRuleService("spec-level", uint32(8080), ptr.To("")), + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + Service: getApiRuleService("rule-level", uint32(8080)), + NoAuth: ptr.To(true), + Methods: []v2alpha1.HttpMethod{http.MethodPost}, + }, + }, + Hosts: getHosts("test.dev"), + }, + } + + ruleService := getService("rule-level", "default") + specService := getService("spec-level", "default") + ruleLevelNs := getNamespace("rule-level-ns") + specLevelNs := getNamespace("spec-level-ns") + defaultNs := getNamespace("default") + fakeClient := createFakeClient(ruleService, specService, ruleLevelNs, specLevelNs, defaultNs) + + err := fakeClient.Create(context.Background(), &corev1.Pod{ + ObjectMeta: v1.ObjectMeta{ + Name: "test", + Namespace: "default", + Labels: map[string]string{ + "app": "rule-level", + }, + }, + }) + Expect(err).NotTo(HaveOccurred()) + + //when + problems, err := validateSidecarInjection(context.Background(), fakeClient, "some.attribute", apiRule, apiRule.Spec.Rules[0]) + Expect(err).NotTo(HaveOccurred()) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].Message).To(Equal("Pod default/test does not have an injected istio sidecar")) + }) + + It("should use 'default' as service namespace for pod selection and service name from spec when service namespace contains an empty string", func() { + //given + apiRule := &v2alpha1.APIRule{ + ObjectMeta: v1.ObjectMeta{ + Name: "api-rule", + Namespace: "api-rule-ns", + }, + Spec: v2alpha1.APIRuleSpec{ + Service: getApiRuleService("spec-level", uint32(8080), ptr.To("")), + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + NoAuth: ptr.To(true), + Methods: []v2alpha1.HttpMethod{http.MethodPost}, + }, + }, + Hosts: getHosts("test.dev"), + }, + } + + specService := getService("spec-level", "default") + specLevelNs := getNamespace("spec-level-ns") + defaultNs := getNamespace("default") + fakeClient := createFakeClient(specService, specLevelNs, defaultNs) + + err := fakeClient.Create(context.Background(), &corev1.Pod{ + ObjectMeta: v1.ObjectMeta{ + Name: "test", + Namespace: "default", + Labels: map[string]string{ + "app": "spec-level", + }, + }, + }) + Expect(err).NotTo(HaveOccurred()) + + //when + problems, err := validateSidecarInjection(context.Background(), fakeClient, "some.attribute", apiRule, apiRule.Spec.Rules[0]) + Expect(err).NotTo(HaveOccurred()) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].Message).To(Equal("Pod default/test does not have an injected istio sidecar")) + }) + + It("should return error when spec.service.name is not defined", func() { + //given + apiRule := &v2alpha1.APIRule{ + ObjectMeta: v1.ObjectMeta{ + Name: "api-rule", + Namespace: "api-rule-ns", + }, + Spec: v2alpha1.APIRuleSpec{ + Service: &v2alpha1.Service{}, + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + NoAuth: ptr.To(true), + Methods: []v2alpha1.HttpMethod{http.MethodPost}, + }, + }, + Hosts: getHosts("test.dev"), + }, + } + + fakeClient := createFakeClient() + + //when + _, err := validateSidecarInjection(context.Background(), fakeClient, "some.attribute", apiRule, apiRule.Spec.Rules[0]) + + //then + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(Equal("service name is required but missing")) + }) + + It("should fail when the service has no selector", func() { + //given + apiRule := &v2alpha1.APIRule{ + ObjectMeta: v1.ObjectMeta{ + Name: "api-rule", + Namespace: "api-rule-ns", + }, + Spec: v2alpha1.APIRuleSpec{ + Service: getApiRuleService("spec-level", uint32(8080), ptr.To("spec-level-ns")), + Rules: []v2alpha1.Rule{ + { + Path: "/abc", + NoAuth: ptr.To(true), + Methods: []v2alpha1.HttpMethod{http.MethodPost}, + }, + }, + Hosts: getHosts("test.dev"), + }, + } + + specService := corev1.Service{ + ObjectMeta: v1.ObjectMeta{ + Name: "spec-level", + Namespace: "spec-level-ns", + }, + } + + specLevelNs := getNamespace("spec-level-ns") + + fakeClient := createFakeClient(&specService, specLevelNs) + + //when + problems, err := validateSidecarInjection(context.Background(), fakeClient, "some.attribute", apiRule, apiRule.Spec.Rules[0]) + Expect(err).NotTo(HaveOccurred()) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].Message).To(Equal("Service cannot have empty label selectors when the API Rule strategy is JWT")) + }) +}) diff --git a/internal/validation/v2alpha1/suite_test.go b/internal/validation/v2alpha1/suite_test.go new file mode 100644 index 000000000..e684cfc88 --- /dev/null +++ b/internal/validation/v2alpha1/suite_test.go @@ -0,0 +1,119 @@ +package v2alpha1 + +import ( + "fmt" + "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" + rulev1alpha1 "github.com/ory/oathkeeper-maester/api/v1alpha1" + networkingv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" + securityv1beta1 "istio.io/client-go/pkg/apis/security/v1beta1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/utils/ptr" + "os" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + "testing" + + . "github.com/onsi/ginkgo/v2" + "github.com/onsi/ginkgo/v2/reporters" + "github.com/onsi/ginkgo/v2/types" + . "github.com/onsi/gomega" + "sigs.k8s.io/controller-runtime/pkg/log/zap" +) + +func Test(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "v2alpha1 validation Suite") +} + +var _ = ReportAfterSuite("custom reporter", func(report types.Report) { + logger := zap.New(zap.UseDevMode(true), zap.WriteTo(GinkgoWriter)) + + if key, ok := os.LookupEnv("ARTIFACTS"); ok { + reportsFilename := fmt.Sprintf("%s/%s", key, "junit-v2alpha1-validation.xml") + logger.Info("Generating reports at", "location", reportsFilename) + err := reporters.GenerateJUnitReport(report, reportsFilename) + + if err != nil { + logger.Error(err, "Junit Report Generation Error") + } + } else { + if err := os.MkdirAll("../../reports", 0755); err != nil { + logger.Error(err, "could not create directory") + } + + reportsFilename := fmt.Sprintf("%s/%s", "../../reports", "junit-v2alpha1-validation.xml") + logger.Info("Generating reports at", "location", reportsFilename) + err := reporters.GenerateJUnitReport(report, reportsFilename) + + if err != nil { + logger.Error(err, "Junit Report Generation Error") + } + } +}) + +func createFakeClient(objs ...client.Object) client.Client { + scheme := runtime.NewScheme() + err := networkingv1beta1.AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) + err = rulev1alpha1.AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) + err = securityv1beta1.AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) + err = v2alpha1.AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) + err = corev1.AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) + + return fake.NewClientBuilder().WithScheme(scheme).WithObjects(objs...).Build() +} + +func getService(name string, namespace ...string) *corev1.Service { + svc := corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Spec: corev1.ServiceSpec{ + Selector: map[string]string{ + "app": name, + }, + }, + } + if len(namespace) > 0 { + svc.ObjectMeta.Namespace = namespace[0] + } + if svc.ObjectMeta.Namespace == "" { + svc.ObjectMeta.Namespace = "default" + } + return &svc +} + +func getApiRuleService(serviceName string, servicePort uint32, namespace ...*string) *v2alpha1.Service { + svc := v2alpha1.Service{ + Name: &serviceName, + Port: &servicePort, + } + if len(namespace) > 0 { + svc.Namespace = namespace[0] + } + return &svc +} + +func getNamespace(name string) *corev1.Namespace { + return &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + } +} + +func getHosts(hosts ...string) []*v2alpha1.Host { + var h []*v2alpha1.Host + for _, host := range hosts { + h = append(h, ptr.To(v2alpha1.Host(host))) + + } + + return h +} diff --git a/internal/validation/v2alpha1/v2alpha1.go b/internal/validation/v2alpha1/v2alpha1.go index 465e78aac..a59418272 100644 --- a/internal/validation/v2alpha1/v2alpha1.go +++ b/internal/validation/v2alpha1/v2alpha1.go @@ -9,50 +9,19 @@ import ( ) type APIRuleValidator struct { - Api *gatewayv2alpha1.APIRule - - // TODO: I don't know if those validators are enough, for now I added some boilerplate code - InjectionValidator *validation.InjectionValidator - RulesValidator rulesValidator - JwtValidator jwtValidator - - DefaultDomainName string -} - -type jwtValidator interface { - Validate(attributePath string, handler *gatewayv2alpha1.JwtConfig) []validation.Failure -} - -type jwtValidatorImpl struct{} - -func (j *jwtValidatorImpl) Validate(attributePath string, jwtConfig *gatewayv2alpha1.JwtConfig) []validation.Failure { - //TODO implement me - return make([]validation.Failure, 0) + ApiRule *gatewayv2alpha1.APIRule } -type rulesValidator interface { - Validate(attributePath string, rules []*gatewayv2alpha1.Rule) []validation.Failure -} - -type rulesValidatorImpl struct{} - -func (r rulesValidatorImpl) Validate(attributePath string, rules []*gatewayv2alpha1.Rule) []validation.Failure { - //TODO implement me - return make([]validation.Failure, 0) -} - -func NewAPIRuleValidator(ctx context.Context, client client.Client, api *gatewayv2alpha1.APIRule, defaultDomainName string) *APIRuleValidator { +func NewAPIRuleValidator(apiRule *gatewayv2alpha1.APIRule) *APIRuleValidator { return &APIRuleValidator{ - Api: api, - InjectionValidator: validation.NewInjectionValidator(ctx, client), - RulesValidator: rulesValidatorImpl{}, - JwtValidator: &jwtValidatorImpl{}, - DefaultDomainName: defaultDomainName, + ApiRule: apiRule, } } -// TODO: Actually Validate -func (*APIRuleValidator) Validate(ctx context.Context, client client.Client, vsList networkingv1beta1.VirtualServiceList) []validation.Failure { - //TODO implement me - return make([]validation.Failure, 0) +func (a *APIRuleValidator) Validate(ctx context.Context, client client.Client, vsList networkingv1beta1.VirtualServiceList) []validation.Failure { + var failures []validation.Failure + + failures = append(failures, validateRules(ctx, client, ".spec", a.ApiRule)...) + + return failures } diff --git a/internal/validation/v2alpha1/v2alpha1_test.go b/internal/validation/v2alpha1/v2alpha1_test.go new file mode 100644 index 000000000..f88a04467 --- /dev/null +++ b/internal/validation/v2alpha1/v2alpha1_test.go @@ -0,0 +1,67 @@ +package v2alpha1_test + +import ( + "context" + gatewayv2alpha1 "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" + "github.com/kyma-project/api-gateway/internal/validation/v2alpha1" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + networkingv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +var _ = Describe("Validate", func() { + + serviceName := "some-service" + host := gatewayv2alpha1.Host(serviceName + ".test.dev") + + It("should invoke rules validation", func() { + //given + apiRule := &gatewayv2alpha1.APIRule{ + Spec: gatewayv2alpha1.APIRuleSpec{ + Rules: nil, + Service: &gatewayv2alpha1.Service{ + Name: ptr.To(serviceName), + Port: ptr.To(uint32(8080)), + }, + Hosts: []*gatewayv2alpha1.Host{&host}, + }, + } + + service := corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: serviceName, + }, + Spec: corev1.ServiceSpec{ + Selector: map[string]string{ + "app": serviceName, + }, + }, + } + fakeClient := createFakeClient(&service) + + //when + problems := (&v2alpha1.APIRuleValidator{ApiRule: apiRule}).Validate(context.Background(), fakeClient, networkingv1beta1.VirtualServiceList{}) + + //then + Expect(problems).To(HaveLen(1)) + Expect(problems[0].AttributePath).To(Equal(".spec.rules")) + Expect(problems[0].Message).To(Equal("No rules defined")) + }) + +}) + +func createFakeClient(objs ...client.Object) client.Client { + scheme := runtime.NewScheme() + err := gatewayv2alpha1.AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) + err = corev1.AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) + + return fake.NewClientBuilder().WithScheme(scheme).WithObjects(objs...).Build() +} diff --git a/main.go b/main.go index 3a14d5767..189a54e07 100644 --- a/main.go +++ b/main.go @@ -163,6 +163,12 @@ func main() { Cache: &client.CacheOptions{ DisableFor: []client.Object{ &rulev1alpha1.Rule{}, + /* + Reading v1beta1 and v2alpha1 APIRules during reconciliation led to an issue that the APIRule could not be read in v2alpha1 after it was deleted. + This would self-heal in the next reconciliation loop.To avoid this confusion with this issue, we disable the cache for v2alpha1 APIRules. + This can probably be enabled again when reconciliation only uses v2alpha1. + */ + &gatewayv2alpha1.APIRule{}, }, }, }, From 3c28467429809aa268cc191d63800520cbb21699 Mon Sep 17 00:00:00 2001 From: Kamil Kasperski Date: Mon, 15 Jul 2024 11:59:34 +0200 Subject: [PATCH 09/11] chore: add oathkeeper log collection (#1164) /kind chore /area ci * add getting logs and deployments for ory oathkeeper --- .github/actions/integration-tests/action.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/actions/integration-tests/action.yaml b/.github/actions/integration-tests/action.yaml index fdbcdfb3f..58602ca61 100644 --- a/.github/actions/integration-tests/action.yaml +++ b/.github/actions/integration-tests/action.yaml @@ -54,8 +54,10 @@ runs: (kubectl logs -n kyma-system deployments/api-gateway-controller-manager || true) > logs/api-gateway-controller-manager.log (kubectl logs -n istio-system deployments/istio-ingressgateway || true) > logs/istio-ingressgateway.log (kubectl logs -n istio-system deployments/istiod || true) > logs/istiod.log + (kubectl logs -n kyma-system deployments/ory-oathkeeper || true) > logs/ory-oathkeeper.log (kubectl get --all-namespaces apirules.gateway.kyma-project.io -oyaml || true) > logs/apirules-dump.yaml (kubectl get --all-namespaces apigateways.operator.kyma-project.io -oyaml || true) > logs/gateway-dump.yaml + (kubectl get -n kyma-system deployment ory-oathkeeper -oyaml || true) > logs/ory-oathkeeper-dump.yaml - name: Uploads artifacts uses: actions/upload-artifact@v4 with: From 946768576a8ed06f6711cc3ec2719b6b40e46c1a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2024 16:13:35 +0200 Subject: [PATCH 10/11] gomod(deps): bump github.com/gardener/external-dns-management (#1162) Bumps [github.com/gardener/external-dns-management](https://github.com/gardener/external-dns-management) from 0.18.7 to 0.19.0. - [Release notes](https://github.com/gardener/external-dns-management/releases) - [Commits](https://github.com/gardener/external-dns-management/compare/v0.18.7...v0.19.0) --- updated-dependencies: - dependency-name: github.com/gardener/external-dns-management dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Bartosz Chwila <103247439+barchw@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 278638016..2d46048df 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/avast/retry-go/v4 v4.6.0 github.com/cucumber/godog v0.14.1 github.com/gardener/cert-management v0.15.0 - github.com/gardener/external-dns-management v0.18.7 + github.com/gardener/external-dns-management v0.19.0 github.com/go-jose/go-jose/v3 v3.0.3 github.com/go-logr/logr v1.4.2 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 555786184..958534678 100644 --- a/go.sum +++ b/go.sum @@ -31,8 +31,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gardener/cert-management v0.15.0 h1:ohm1eWae2rQSkwFGWXTt+lBv4rLBhtJsJgqvaXJBs6o= github.com/gardener/cert-management v0.15.0/go.mod h1:3BK2VEtGwv2ijf3bSziTLMCUvYnPzIQrQ/uPeZzL4m0= -github.com/gardener/external-dns-management v0.18.7 h1:w3giAUwqTyO4Q5YRz9s8E0pIgelcKJueQViw31A+mjk= -github.com/gardener/external-dns-management v0.18.7/go.mod h1:s8O/Weu6s6hBMpNPV99PNId4HebXuwy3Xs7bGWTn9Ts= +github.com/gardener/external-dns-management v0.19.0 h1:R1qUjeqirCS+EV7DF99HL6SWtRLSuVohbMnkhJHmINc= +github.com/gardener/external-dns-management v0.19.0/go.mod h1:s8O/Weu6s6hBMpNPV99PNId4HebXuwy3Xs7bGWTn9Ts= github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= From 34e5a44080e45258577dba4d45a4eae4b6dfb248 Mon Sep 17 00:00:00 2001 From: Bartosz Chwila <103247439+barchw@users.noreply.github.com> Date: Mon, 15 Jul 2024 16:57:34 +0200 Subject: [PATCH 11/11] v2alpha1 CORS and Hosts (#1157) * CORS policy in v2alpha1 * Revert to v1beta1 * Tests * Tests * Add test for multiple hosts * Update API * Revert "Update API" This reverts commit 94e4eb0f1fba8b7154f0ea97ff00ef3b854b19c3. * review changes * Fix unit test * Add unit tests * Adapt the doc * Update docs/user/custom-resources/apirule/v2alpha1/04-10-apirule-custom-resource.md Co-authored-by: Natalia Sitko <80401180+nataliasitko@users.noreply.github.com> --------- Co-authored-by: Tim Riffer Co-authored-by: Natalia Sitko <80401180+nataliasitko@users.noreply.github.com> --- apis/gateway/v2alpha1/rule.go | 9 + .../api_controller_integration_test.go | 10 +- .../v2alpha1/04-10-apirule-custom-resource.md | 64 +++--- internal/builders/virtual_service.go | 48 +++- internal/builders/virtual_service_test.go | 8 +- .../istio/virtual_service_processor.go | 2 +- .../ory/virtual_service_processor.go | 2 +- .../processors/v2alpha1/cors_test.go | 77 +++++++ .../processors/v2alpha1/hosts_test.go | 43 ++++ .../processors/v2alpha1/http_matching_test.go | 51 +++++ .../processors/v2alpha1/reconciliation.go | 16 ++ .../processors/v2alpha1/test_builders_test.go | 209 ++++++++++++++++++ .../processors/v2alpha1/timeout_test.go | 68 ++++++ .../v2alpha1/virtual_service_processor.go | 174 +++++++++++++++ .../virtual_service_processor_test.go | 166 ++++++++++++++ 15 files changed, 903 insertions(+), 44 deletions(-) create mode 100644 internal/processing/processors/v2alpha1/cors_test.go create mode 100644 internal/processing/processors/v2alpha1/hosts_test.go create mode 100644 internal/processing/processors/v2alpha1/http_matching_test.go create mode 100644 internal/processing/processors/v2alpha1/test_builders_test.go create mode 100644 internal/processing/processors/v2alpha1/timeout_test.go create mode 100644 internal/processing/processors/v2alpha1/virtual_service_processor.go create mode 100644 internal/processing/processors/v2alpha1/virtual_service_processor_test.go diff --git a/apis/gateway/v2alpha1/rule.go b/apis/gateway/v2alpha1/rule.go index 2aff62a43..e73adb815 100644 --- a/apis/gateway/v2alpha1/rule.go +++ b/apis/gateway/v2alpha1/rule.go @@ -7,3 +7,12 @@ func (r *Rule) ContainsAccessStrategyJwt() bool { func (r *Rule) ContainsNoAuth() bool { return r.NoAuth != nil } + +func ConvertHttpMethodsToStrings(methods []HttpMethod) []string { + strings := make([]string, len(methods)) + for i, method := range methods { + strings[i] = string(method) + } + + return strings +} diff --git a/controllers/gateway/api_controller_integration_test.go b/controllers/gateway/api_controller_integration_test.go index f726aaaef..c32a464d4 100644 --- a/controllers/gateway/api_controller_integration_test.go +++ b/controllers/gateway/api_controller_integration_test.go @@ -493,7 +493,7 @@ var _ = Describe("APIRule Controller", Serial, func() { g.Expect(len(vs.Name) > len(apiRuleName)).To(BeTrue()) expectedSpec := builders.VirtualServiceSpec(). - Host(serviceHost). + AddHost(serviceHost). Gateway(testGatewayURL). HTTP(builders.HTTPRoute(). Match(builders.MatchRequest().Uri().Regex(testPath)). @@ -591,7 +591,7 @@ var _ = Describe("APIRule Controller", Serial, func() { vs := vsList.Items[0] expectedSpec := builders.VirtualServiceSpec(). - Host(serviceHost). + AddHost(serviceHost). Gateway(testGatewayURL). HTTP(builders.HTTPRoute(). Match(builders.MatchRequest().Uri().Regex("/img")). @@ -733,7 +733,7 @@ var _ = Describe("APIRule Controller", Serial, func() { vs := vsList.Items[0] expectedSpec := builders.VirtualServiceSpec(). - Host(serviceHost). + AddHost(serviceHost). Gateway(testGatewayURL). HTTP(builders.HTTPRoute(). Match(builders.MatchRequest().Uri().Regex("/img").MethodRegEx(http.MethodGet)). @@ -1042,7 +1042,7 @@ var _ = Describe("APIRule Controller", Serial, func() { vs := vsList.Items[0] expectedSpec := builders.VirtualServiceSpec(). - Host(serviceHost). + AddHost(serviceHost). Gateway(testGatewayURL). HTTP(builders.HTTPRoute(). Match(builders.MatchRequest().Uri().Regex("/img")). @@ -1174,7 +1174,7 @@ var _ = Describe("APIRule Controller", Serial, func() { vs := vsList.Items[0] expectedSpec := builders.VirtualServiceSpec(). - Host(serviceHost). + AddHost(serviceHost). Gateway(testGatewayURL). HTTP(builders.HTTPRoute(). Match(builders.MatchRequest().Uri().Regex("/favicon")). diff --git a/docs/user/custom-resources/apirule/v2alpha1/04-10-apirule-custom-resource.md b/docs/user/custom-resources/apirule/v2alpha1/04-10-apirule-custom-resource.md index fb3faff21..6f87d74bc 100644 --- a/docs/user/custom-resources/apirule/v2alpha1/04-10-apirule-custom-resource.md +++ b/docs/user/custom-resources/apirule/v2alpha1/04-10-apirule-custom-resource.md @@ -13,38 +13,38 @@ This table lists all parameters of APIRule `v2alpha1` CRD together with their de **Spec:** -| Field | Required | Description | Validation | -|:-------------------------------------------------|:---------:|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------| -| **gateway** | **YES** | Specifies the Istio Gateway. | None | -| **corsPolicy** | **NO** | Allows configuring CORS headers sent with the response. If **corsPolicy** is not defined, the default values are applied. If **corsPolicy** is configured, only the CORS headers defined in the APIRule are sent with the response. For more information, see the [decision record](https://github.com/kyma-project/api-gateway/issues/752). | None | -| **corsPolicy.allowHeaders** | **NO** | Specifies headers allowed with the **Access-Control-Allow-Headers** CORS header. | None | -| **corsPolicy.allowMethods** | **NO** | Specifies methods allowed with the **Access-Control-Allow-Methods** CORS header. | None | -| **corsPolicy.allowOrigins** | **NO** | Specifies origins allowed with the **Access-Control-Allow-Origins** CORS header. | None | -| **corsPolicy.allowCredentials** | **NO** | Specifies whether credentials are allowed in the **Access-Control-Allow-Credentials** CORS header. | None | -| **corsPolicy.exposeHeaders** | **NO** | Specifies headers exposed with the **Access-Control-Expose-Headers** CORS header. | None | -| **corsPolicy.maxAge** | **NO** | Specifies the maximum age of CORS policy cache. The value is provided in the **Access-Control-Max-Age** CORS header. | None | -| **hosts** | **YES** | Specifies the Service's communication address for inbound external traffic. If only the leftmost label is provided, the default domain name is used. | The full domain name or the leftmost label cannot contain the wildcard character `*`. | -| **service.name** | **NO** | Specifies the name of the exposed Service. | None | -| **service.namespace** | **NO** | Specifies the namespace of the exposed Service. | None | -| **service.port** | **NO** | Specifies the communication port of the exposed Service. | None | -| **timeout** | **NO** | Specifies the timeout for HTTP requests in seconds for all Access Rules. The value can be overridden for each Access Rule.
If no timeout is specified, the default timeout of 180 seconds applies. | The maximum timeout is limited to 3900 seconds (65 minutes). | -| **rules** | **YES** | Specifies the list of Access Rules. | None | -| **rules.service** | **NO** | Services definitions at this level have higher precedence than the Service definition at the **spec.service** level. | None | -| **rules.path** | **YES** | Specifies the path of the exposed Service. If the path specified in an Access Rule overlaps with the path of another Access Rule, both Access Rules are applied. This happens, for example, if one of the Access Rules' configurations contains `*`. | The value can be either an exact path or a wildcard `*`. | -| **rules.methods** | **NO** | Specifies the list of HTTP request methods available for **spec.rules.path**. The list of supported methods is defined in [RFC 9910: HTTP Semantics](https://www.rfc-editor.org/rfc/rfc9110.html) and [RFC 5789: PATCH Method for HTTP](https://www.rfc-editor.org/rfc/rfc5789.html). | None | -| **rules.noAuth** | **NO** | Setting `noAuth` to `true` disables authorization. | When `noAuth` is set to true, it is not allowed to define the `jwt` access strategy on the same path. | -| **rules.jwt** | **NO** | Specifies the Istio JWT access strategy. | None | -| **rules.jwt.authentications** | **YES** | Specifies the list of authentication objects. | None | -| **rules.jwt.authentications.issuer** | **YES** | Identifies the issuer that issued the JWT.
The value must be a URL. Although HTTP is allowed, it is recommended that you use only HTTPS endpoints. | None | -| **rules.jwt.authentications.jwksUri** | **YES** | Contains the URL of the provider’s public key set to validate the signature of the JWT.
The value must be a URL. Although HTTP is allowed, it is recommended that you use only HTTPS endpoints. | None | -| **rules.jwt.authentications.fromHeaders** | **NO** | Specifies the list of headers from which the JWT token is extracted. | None | -| **rules.jwt.authentications.fromHeaders.name** | **YES** | Specifies the name of the header. | None | -| **rules.jwt.authentications.fromHeaders.prefix** | **NO** | Specifies the prefix used before the JWT token. The default is `Bearer`. | None | -| **rules.jwt.authentications.fromParams** | **NO** | Specifies the list of parameters from which the JWT token is extracted. | None | -| **rules.jwt.authorizations** | **NO** | Specifies the list of authorization objects. | None | -| **rules.jwt.authorizations.requiredScopes** | **NO** | Specifies the list of required scope values for the JWT. | None | -| **rules.jwt.authorizations.audiences** | **NO** | Specifies the list of audiences required for the JWT. | None | -| **rules.timeout** | **NO** | Specifies the timeout, in seconds, for HTTP requests made to **spec.rules.path**. Timeout definitions set at this level take precedence over any timeout defined at the **spec.timeout** level. | The maximum timeout is limited to 3900 seconds (65 minutes). | +| Field | Required | Description | Validation | +|:-------------------------------------------------|:---------:|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------| +| **gateway** | **YES** | Specifies the Istio Gateway. | None | +| **corsPolicy** | **NO** | Allows configuring CORS headers sent with the response. If **corsPolicy** is not defined, the CORS headers are enforced to be empty. | None | +| **corsPolicy.allowHeaders** | **NO** | Specifies headers allowed with the **Access-Control-Allow-Headers** CORS header. | None | +| **corsPolicy.allowMethods** | **NO** | Specifies methods allowed with the **Access-Control-Allow-Methods** CORS header. | None | +| **corsPolicy.allowOrigins** | **NO** | Specifies origins allowed with the **Access-Control-Allow-Origins** CORS header. | None | +| **corsPolicy.allowCredentials** | **NO** | Specifies whether credentials are allowed in the **Access-Control-Allow-Credentials** CORS header. | None | +| **corsPolicy.exposeHeaders** | **NO** | Specifies headers exposed with the **Access-Control-Expose-Headers** CORS header. | None | +| **corsPolicy.maxAge** | **NO** | Specifies the maximum age of CORS policy cache. The value is provided in the **Access-Control-Max-Age** CORS header. | None | +| **hosts** | **YES** | Specifies the Service's communication address for inbound external traffic. If only the leftmost label is provided, the default domain name is used. | The full domain name or the leftmost label cannot contain the wildcard character `*`. | +| **service.name** | **NO** | Specifies the name of the exposed Service. | None | +| **service.namespace** | **NO** | Specifies the namespace of the exposed Service. | None | +| **service.port** | **NO** | Specifies the communication port of the exposed Service. | None | +| **timeout** | **NO** | Specifies the timeout for HTTP requests in seconds for all Access Rules. The value can be overridden for each Access Rule.
If no timeout is specified, the default timeout of 180 seconds applies. | The maximum timeout is limited to 3900 seconds (65 minutes). | +| **rules** | **YES** | Specifies the list of Access Rules. | None | +| **rules.service** | **NO** | Services definitions at this level have higher precedence than the Service definition at the **spec.service** level. | None | +| **rules.path** | **YES** | Specifies the path of the exposed Service. If the path specified in an Access Rule overlaps with the path of another Access Rule, both Access Rules are applied. This happens, for example, if one of the Access Rules' configurations contains `*`. | The value can be either an exact path or a wildcard `*`. | +| **rules.methods** | **NO** | Specifies the list of HTTP request methods available for **spec.rules.path**. The list of supported methods is defined in [RFC 9910: HTTP Semantics](https://www.rfc-editor.org/rfc/rfc9110.html) and [RFC 5789: PATCH Method for HTTP](https://www.rfc-editor.org/rfc/rfc5789.html). | None | +| **rules.noAuth** | **NO** | Setting `noAuth` to `true` disables authorization. | When `noAuth` is set to true, it is not allowed to define the `jwt` access strategy on the same path. | +| **rules.jwt** | **NO** | Specifies the Istio JWT access strategy. | None | +| **rules.jwt.authentications** | **YES** | Specifies the list of authentication objects. | None | +| **rules.jwt.authentications.issuer** | **YES** | Identifies the issuer that issued the JWT.
The value must be a URL. Although HTTP is allowed, it is recommended that you use only HTTPS endpoints. | None | +| **rules.jwt.authentications.jwksUri** | **YES** | Contains the URL of the provider’s public key set to validate the signature of the JWT.
The value must be a URL. Although HTTP is allowed, it is recommended that you use only HTTPS endpoints. | None | +| **rules.jwt.authentications.fromHeaders** | **NO** | Specifies the list of headers from which the JWT token is extracted. | None | +| **rules.jwt.authentications.fromHeaders.name** | **YES** | Specifies the name of the header. | None | +| **rules.jwt.authentications.fromHeaders.prefix** | **NO** | Specifies the prefix used before the JWT token. The default is `Bearer`. | None | +| **rules.jwt.authentications.fromParams** | **NO** | Specifies the list of parameters from which the JWT token is extracted. | None | +| **rules.jwt.authorizations** | **NO** | Specifies the list of authorization objects. | None | +| **rules.jwt.authorizations.requiredScopes** | **NO** | Specifies the list of required scope values for the JWT. | None | +| **rules.jwt.authorizations.audiences** | **NO** | Specifies the list of audiences required for the JWT. | None | +| **rules.timeout** | **NO** | Specifies the timeout, in seconds, for HTTP requests made to **spec.rules.path**. Timeout definitions set at this level take precedence over any timeout defined at the **spec.timeout** level. | The maximum timeout is limited to 3900 seconds (65 minutes). | > [!WARNING] > When you use an unsupported `v1beta1` configuration in version `v2alpha1` of the APIRule CR, you get an empty **spec**. See [supported access strategies](04-15-api-rule-access-strategies.md). diff --git a/internal/builders/virtual_service.go b/internal/builders/virtual_service.go index a8fc6828d..b02b5d44a 100644 --- a/internal/builders/virtual_service.go +++ b/internal/builders/virtual_service.go @@ -3,6 +3,7 @@ package builders import ( "fmt" apirulev1beta1 "github.com/kyma-project/api-gateway/apis/gateway/v1beta1" + apirulev2alpha1 "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/wrapperspb" "istio.io/api/networking/v1beta1" @@ -80,7 +81,7 @@ func (vss *virtualServiceSpec) From(val *v1beta1.VirtualService) *virtualService return vss } -func (vss *virtualServiceSpec) Host(val string) *virtualServiceSpec { +func (vss *virtualServiceSpec) AddHost(val string) *virtualServiceSpec { vss.value.Hosts = append(vss.value.Hosts, val) return vss } @@ -155,6 +156,20 @@ func (mr *matchRequest) Uri() *stringMatch { return &stringMatch{mr.value.Uri, func() *matchRequest { return mr }} } +// MethodRegExV2Alpha1 sets the HTTP method regex in the HTTPMatchRequest for the given HTTP methods in the format "^(PUT|POST|GET)$". +func (mr *matchRequest) MethodRegExV2Alpha1(httpMethods ...apirulev2alpha1.HttpMethod) *matchRequest { + methodStrings := apirulev2alpha1.ConvertHttpMethodsToStrings(httpMethods) + methodsWithSeparator := strings.Join(methodStrings, "|") + + mr.value.Method = &v1beta1.StringMatch{ + MatchType: &v1beta1.StringMatch_Regex{ + Regex: fmt.Sprintf("^(%s)$", methodsWithSeparator), + }, + } + + return mr +} + // MethodRegEx sets the HTTP method regex in the HTTPMatchRequest for the given HTTP methods in the format "^(PUT|POST|GET)$". func (mr *matchRequest) MethodRegEx(httpMethods ...apirulev1beta1.HttpMethod) *matchRequest { @@ -257,6 +272,37 @@ func (cp *corsPolicy) AllowOrigins(val ...*v1beta1.StringMatch) *corsPolicy { return cp } +func (cp *corsPolicy) FromV2Alpha1ApiRuleCorsPolicy(corsPolicy apirulev2alpha1.CorsPolicy) *corsPolicy { + if len(corsPolicy.AllowOrigins) == 0 { + cp.value.AllowOrigins = nil + } else { + matchers := corsPolicy.AllowOrigins.ToIstioStringMatchArray() + cp.value.AllowOrigins = append(cp.value.AllowOrigins, matchers...) + } + + if len(corsPolicy.AllowHeaders) > 0 { + cp.value.AllowHeaders = corsPolicy.AllowHeaders + } + + if len(corsPolicy.AllowMethods) > 0 { + cp.value.AllowMethods = corsPolicy.AllowMethods + } + + if len(corsPolicy.ExposeHeaders) > 0 { + cp.value.ExposeHeaders = corsPolicy.ExposeHeaders + } + + if corsPolicy.AllowCredentials != nil { + cp.value.AllowCredentials = &wrapperspb.BoolValue{Value: *corsPolicy.AllowCredentials} + } + + if corsPolicy.MaxAge != nil { + cp.value.MaxAge = durationpb.New(time.Duration(*corsPolicy.MaxAge) * time.Second) + } + + return cp +} + func (cp *corsPolicy) FromApiRuleCorsPolicy(corsPolicy apirulev1beta1.CorsPolicy) *corsPolicy { if len(corsPolicy.AllowOrigins) == 0 { cp.value.AllowOrigins = nil diff --git a/internal/builders/virtual_service_test.go b/internal/builders/virtual_service_test.go index 3a4398a77..69149bffa 100644 --- a/internal/builders/virtual_service_test.go +++ b/internal/builders/virtual_service_test.go @@ -35,7 +35,7 @@ var _ = Describe("Builder for", func() { vs := VirtualService().From(&initialVs).GenerateName(name).Namespace(namespace). Spec( VirtualServiceSpec(). - Host(host). + AddHost(host). Gateway(gateway)). Get() Expect(vs.Name).To(BeEmpty()) @@ -60,8 +60,8 @@ var _ = Describe("Builder for", func() { timeout := time.Second * 60 result := VirtualServiceSpec(). - Host(host). - Host(host2). + AddHost(host). + AddHost(host2). Gateway(gateway). Gateway(gateway2). HTTP(HTTPRoute(). @@ -132,7 +132,7 @@ var _ = Describe("Builder for", func() { } result := VirtualServiceSpec(). - Host(host). + AddHost(host). Gateway(gateway). HTTP(HTTPRoute(). CorsPolicy(CorsPolicy().FromApiRuleCorsPolicy(corsPolicy)). diff --git a/internal/processing/processors/istio/virtual_service_processor.go b/internal/processing/processors/istio/virtual_service_processor.go index 4a82a0f0e..96812346b 100644 --- a/internal/processing/processors/istio/virtual_service_processor.go +++ b/internal/processing/processors/istio/virtual_service_processor.go @@ -36,7 +36,7 @@ func (r virtualServiceCreator) Create(api *gatewayv1beta1.APIRule) (*networkingv virtualServiceNamePrefix := fmt.Sprintf("%s-", api.ObjectMeta.Name) vsSpecBuilder := builders.VirtualServiceSpec() - vsSpecBuilder.Host(default_domain.GetHostWithDomain(*api.Spec.Host, r.defaultDomainName)) + vsSpecBuilder.AddHost(default_domain.GetHostWithDomain(*api.Spec.Host, r.defaultDomainName)) vsSpecBuilder.Gateway(*api.Spec.Gateway) filteredRules := processing.FilterDuplicatePaths(api.Spec.Rules) diff --git a/internal/processing/processors/ory/virtual_service_processor.go b/internal/processing/processors/ory/virtual_service_processor.go index 60cedb671..629f2f570 100644 --- a/internal/processing/processors/ory/virtual_service_processor.go +++ b/internal/processing/processors/ory/virtual_service_processor.go @@ -36,7 +36,7 @@ func (r virtualServiceCreator) Create(api *gatewayv1beta1.APIRule) (*networkingv virtualServiceNamePrefix := fmt.Sprintf("%s-", api.ObjectMeta.Name) vsSpecBuilder := builders.VirtualServiceSpec() - vsSpecBuilder.Host(default_domain.GetHostWithDomain(*api.Spec.Host, r.defaultDomainName)) + vsSpecBuilder.AddHost(default_domain.GetHostWithDomain(*api.Spec.Host, r.defaultDomainName)) vsSpecBuilder.Gateway(*api.Spec.Gateway) filteredRules := processing.FilterDuplicatePaths(api.Spec.Rules) diff --git a/internal/processing/processors/v2alpha1/cors_test.go b/internal/processing/processors/v2alpha1/cors_test.go new file mode 100644 index 000000000..6cf8bf791 --- /dev/null +++ b/internal/processing/processors/v2alpha1/cors_test.go @@ -0,0 +1,77 @@ +package v2alpha1_test + +import ( + gatewayv2alpha1 "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" + "github.com/kyma-project/api-gateway/internal/builders" + processors "github.com/kyma-project/api-gateway/internal/processing/processors/v2alpha1" + istioapiv1beta1 "istio.io/api/networking/v1beta1" + networkingv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" + "sigs.k8s.io/controller-runtime/pkg/client" + + . "github.com/kyma-project/api-gateway/internal/processing/processing_test" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("CORS", func() { + var client client.Client + var processor processors.VirtualServiceProcessor + BeforeEach(func() { + client = GetFakeClient() + }) + + DescribeTable("CORS", + func(apiRule *gatewayv2alpha1.APIRule, verifiers []verifier, expectedActions ...string) { + processor = processors.NewVirtualServiceProcessor(GetTestConfig(), apiRule) + checkVirtualServices(client, processor, verifiers, expectedActions...) + }, + + Entry("should set default empty values in VirtualService CORSPolicy when no CORS configuration is set in APIRule", + newAPIRuleBuilderWithDummyDataWithNoAuthRule().Build(), + []verifier{ + func(vs *networkingv1beta1.VirtualService) { + Expect(vs.Spec.Http[0].CorsPolicy).To(BeNil()) + + Expect(vs.Spec.Http[0].Headers.Response.Remove).To(ConsistOf([]string{ + builders.ExposeHeadersName, + builders.MaxAgeName, + builders.AllowHeadersName, + builders.AllowCredentialsName, + builders.AllowMethodsName, + builders.AllowOriginName, + })) + }, + }, "create"), + + Entry("should apply all CORSPolicy headers correctly", + newAPIRuleBuilderWithDummyDataWithNoAuthRule().WithCORSPolicy( + newCorsPolicyBuilder(). + WithAllowOrigins([]map[string]string{{"exact": "example.com"}}). + WithAllowMethods([]string{"GET", "POST"}). + WithAllowHeaders([]string{"header1", "header2"}). + WithExposeHeaders([]string{"header3", "header4"}). + WithAllowCredentials(true). + WithMaxAge(600). + Build()). + Build(), + []verifier{func(vs *networkingv1beta1.VirtualService) { + Expect(vs.Spec.Http[0].CorsPolicy).NotTo(BeNil()) + Expect(vs.Spec.Http[0].CorsPolicy.AllowOrigins).To(HaveLen(1)) + Expect(vs.Spec.Http[0].CorsPolicy.AllowOrigins[0]).To(Equal(&istioapiv1beta1.StringMatch{MatchType: &istioapiv1beta1.StringMatch_Exact{Exact: "example.com"}})) + Expect(vs.Spec.Http[0].CorsPolicy.AllowMethods).To(ConsistOf("GET", "POST")) + Expect(vs.Spec.Http[0].CorsPolicy.AllowHeaders).To(ConsistOf("header1", "header2")) + Expect(vs.Spec.Http[0].CorsPolicy.ExposeHeaders).To(ConsistOf("header3", "header4")) + Expect(vs.Spec.Http[0].CorsPolicy.AllowCredentials.GetValue()).To(BeTrue()) + Expect(vs.Spec.Http[0].CorsPolicy.MaxAge.Seconds).To(Equal(int64(600))) + + Expect(vs.Spec.Http[0].Headers.Response.Remove).To(ConsistOf([]string{ + builders.ExposeHeadersName, + builders.MaxAgeName, + builders.AllowHeadersName, + builders.AllowCredentialsName, + builders.AllowMethodsName, + builders.AllowOriginName, + })) + }}, "create"), + ) +}) diff --git a/internal/processing/processors/v2alpha1/hosts_test.go b/internal/processing/processors/v2alpha1/hosts_test.go new file mode 100644 index 000000000..7cac36ff5 --- /dev/null +++ b/internal/processing/processors/v2alpha1/hosts_test.go @@ -0,0 +1,43 @@ +package v2alpha1_test + +import ( + gatewayv2alpha1 "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" + processors "github.com/kyma-project/api-gateway/internal/processing/processors/v2alpha1" + networkingv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" + "sigs.k8s.io/controller-runtime/pkg/client" + + . "github.com/kyma-project/api-gateway/internal/processing/processing_test" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("Hosts", func() { + var client client.Client + var processor processors.VirtualServiceProcessor + BeforeEach(func() { + client = GetFakeClient() + }) + + DescribeTable("Hosts", + func(apiRule *gatewayv2alpha1.APIRule, verifiers []verifier, expectedActions ...string) { + processor = processors.NewVirtualServiceProcessor(GetTestConfig(), apiRule) + checkVirtualServices(client, processor, verifiers, expectedActions...) + }, + + Entry("should set the host correctly", + newAPIRuleBuilder().WithGateway("example/example").WithHost("example.com").Build(), + []verifier{ + func(vs *networkingv1beta1.VirtualService) { + Expect(vs.Spec.Hosts).To(ConsistOf("example.com")) + }, + }, "create"), + + Entry("should set multiple hosts correctly", + newAPIRuleBuilder().WithGateway("example/example").WithHosts("example.com", "goat.com").Build(), + []verifier{ + func(vs *networkingv1beta1.VirtualService) { + Expect(vs.Spec.Hosts).To(ConsistOf("example.com", "goat.com")) + }, + }, "create"), + ) +}) diff --git a/internal/processing/processors/v2alpha1/http_matching_test.go b/internal/processing/processors/v2alpha1/http_matching_test.go new file mode 100644 index 000000000..8c2138b9b --- /dev/null +++ b/internal/processing/processors/v2alpha1/http_matching_test.go @@ -0,0 +1,51 @@ +package v2alpha1_test + +import ( + gatewayv2alpha1 "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" + processors "github.com/kyma-project/api-gateway/internal/processing/processors/v2alpha1" + networkingv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" + "net/http" + "sigs.k8s.io/controller-runtime/pkg/client" + + . "github.com/kyma-project/api-gateway/internal/processing/processing_test" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("HTTP matching", func() { + var client client.Client + var processor processors.VirtualServiceProcessor + BeforeEach(func() { + client = GetFakeClient() + }) + var _ = DescribeTable("Different methods on same path", + func(apiRule *gatewayv2alpha1.APIRule, verifiers []verifier, expectedActions ...string) { + processor = processors.NewVirtualServiceProcessor(GetTestConfig(), apiRule) + checkVirtualServices(client, processor, verifiers, expectedActions...) + }, + Entry("from two rules with different methods on the same path should create two HTTP routes with different methods", + newAPIRuleBuilderWithDummyData(). + WithRules(newRuleBuilder().WithMethods(http.MethodGet).WithPath("/").NoAuth().Build(), + newRuleBuilder().WithMethods(http.MethodPut).WithPath("/").WithJWTAuthn("example.com", "https://jwks.example.com", nil, nil).Build()).Build(), + []verifier{ + func(vs *networkingv1beta1.VirtualService) { + Expect(vs.Spec.Http).To(HaveLen(2)) + + Expect(vs.Spec.Http[0].Match[0].Method.GetRegex()).To(Equal("^(GET)$")) + Expect(vs.Spec.Http[1].Match[0].Method.GetRegex()).To(Equal("^(PUT)$")) + }, + }, "create"), + + Entry("from one rule with two methods on the same path should create one HTTP route with regex matching both methods", + newAPIRuleBuilderWithDummyData(). + WithRules(newRuleBuilder().WithMethods(http.MethodGet, http.MethodPut).WithPath("/").NoAuth().Build()). + Build(), + []verifier{ + func(vs *networkingv1beta1.VirtualService) { + Expect(vs.Spec.Http).To(HaveLen(1)) + + Expect(vs.Spec.Http[0].Match[0].Method.GetRegex()).To(Equal("^(GET|PUT)$")) + }, + }, "create"), + ) +}) diff --git a/internal/processing/processors/v2alpha1/reconciliation.go b/internal/processing/processors/v2alpha1/reconciliation.go index 4c26bdb43..176a91cab 100644 --- a/internal/processing/processors/v2alpha1/reconciliation.go +++ b/internal/processing/processors/v2alpha1/reconciliation.go @@ -54,3 +54,19 @@ func NewReconciliation(apiRuleV2alpha1 *gatewayv2alpha1.APIRule, apiRuleV1beta1 config: config, } } + +func findServiceNamespace(api *gatewayv2alpha1.APIRule, rule *gatewayv2alpha1.Rule) string { + // Fallback direction for the upstream service namespace: Rule.Service > Spec.Service > APIRule + if rule != nil && rule.Service != nil && rule.Service.Namespace != nil { + return *rule.Service.Namespace + } + if api != nil && api.Spec.Service != nil && api.Spec.Service.Namespace != nil { + return *api.Spec.Service.Namespace + } + + if api != nil { + return api.Namespace + } else { + return "" + } +} diff --git a/internal/processing/processors/v2alpha1/test_builders_test.go b/internal/processing/processors/v2alpha1/test_builders_test.go new file mode 100644 index 000000000..0b0e49d82 --- /dev/null +++ b/internal/processing/processors/v2alpha1/test_builders_test.go @@ -0,0 +1,209 @@ +package v2alpha1_test + +import ( + gatewayv2alpha1 "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" + "k8s.io/utils/ptr" + "net/http" +) + +type ruleBuilder struct { + rule *gatewayv2alpha1.Rule +} + +func (r *ruleBuilder) WithPath(path string) *ruleBuilder { + r.rule.Path = path + return r +} + +func (r *ruleBuilder) WithTimeout(timeout uint32) *ruleBuilder { + r.rule.Timeout = ptr.To(gatewayv2alpha1.Timeout(timeout)) + return r +} + +func (r *ruleBuilder) WithService(name, namespace string, port uint32) *ruleBuilder { + r.rule.Service = &gatewayv2alpha1.Service{ + Name: &name, + Namespace: &namespace, + Port: &port, + } + return r +} + +func (r *ruleBuilder) WithMethods(methods ...gatewayv2alpha1.HttpMethod) *ruleBuilder { + r.rule.Methods = methods + return r +} + +func (r *ruleBuilder) NoAuth() *ruleBuilder { + r.rule.NoAuth = ptr.To(true) + return r +} + +func (r *ruleBuilder) WithJWTAuthn(issuer, jwksUri string, fromHeaders []*gatewayv2alpha1.JwtHeader, fromParams []string) *ruleBuilder { + if r.rule.Jwt == nil { + r.rule.Jwt = &gatewayv2alpha1.JwtConfig{} + } + r.rule.Jwt.Authentications = append(r.rule.Jwt.Authentications, &gatewayv2alpha1.JwtAuthentication{ + Issuer: issuer, + JwksUri: jwksUri, + FromHeaders: fromHeaders, + FromParams: fromParams, + }) + + return r +} + +func (r *ruleBuilder) WithJWTAuthz(requiredScopes []string, audiences []string) *ruleBuilder { + if r.rule.Jwt == nil { + r.rule.Jwt = &gatewayv2alpha1.JwtConfig{} + } + + r.rule.Jwt.Authorizations = append(r.rule.Jwt.Authorizations, &gatewayv2alpha1.JwtAuthorization{ + RequiredScopes: requiredScopes, + Audiences: audiences, + }) + + return r +} + +func newRuleBuilder() *ruleBuilder { + return &ruleBuilder{ + rule: &gatewayv2alpha1.Rule{}, + } +} + +func (r *ruleBuilder) Build() *gatewayv2alpha1.Rule { + return r.rule +} + +type apiRuleBuilder struct { + apiRule *gatewayv2alpha1.APIRule +} + +func (a *apiRuleBuilder) WithHost(host string) *apiRuleBuilder { + a.apiRule.Spec.Hosts = append(a.apiRule.Spec.Hosts, ptr.To(gatewayv2alpha1.Host(host))) + return a +} + +func (a *apiRuleBuilder) WithHosts(hosts ...string) *apiRuleBuilder { + for _, host := range hosts { + a.WithHost(host) + } + return a +} + +func (a *apiRuleBuilder) WithService(name, namespace string, port uint32) *apiRuleBuilder { + a.apiRule.Spec.Service = &gatewayv2alpha1.Service{ + Name: &name, + Namespace: &namespace, + Port: &port, + } + return a +} + +func (a *apiRuleBuilder) WithGateway(gateway string) *apiRuleBuilder { + a.apiRule.Spec.Gateway = ptr.To(gateway) + return a +} + +func (a *apiRuleBuilder) WithCORSPolicy(policy gatewayv2alpha1.CorsPolicy) *apiRuleBuilder { + a.apiRule.Spec.CorsPolicy = &policy + return a +} + +func (a *apiRuleBuilder) WithTimeout(timeout uint32) *apiRuleBuilder { + a.apiRule.Spec.Timeout = ptr.To(gatewayv2alpha1.Timeout(timeout)) + return a +} + +func (a *apiRuleBuilder) WithRule(rule gatewayv2alpha1.Rule) *apiRuleBuilder { + a.apiRule.Spec.Rules = append(a.apiRule.Spec.Rules, rule) + return a +} + +func (a *apiRuleBuilder) WithRules(rules ...*gatewayv2alpha1.Rule) *apiRuleBuilder { + for _, rule := range rules { + a.WithRule(*rule) + } + return a +} + +func (a *apiRuleBuilder) Build() *gatewayv2alpha1.APIRule { + return a.apiRule +} + +func newAPIRuleBuilder() *apiRuleBuilder { + return &apiRuleBuilder{ + apiRule: &gatewayv2alpha1.APIRule{}, + } +} + +// newAPIRuleBuilderWithDummyDataWithNoAuthRule returns an APIRuleBuilder pre-filled with placeholder data: +// +// Host: example-host.example.com +// +// Gateway: example-namespace/example-gateway +// +// Service: example-namespace/example-service:8080 +// +// Rule: GET / +// +// Strategy: NoAuth +func newAPIRuleBuilderWithDummyDataWithNoAuthRule() *apiRuleBuilder { + return newAPIRuleBuilder(). + WithHost("example-host.example.com"). + WithGateway("example-namespace/example-gateway"). + WithService("example-service", "example-namespace", 8080). + WithRule(*newRuleBuilder().WithMethods(http.MethodGet).WithPath("/").NoAuth().Build()) +} + +func newAPIRuleBuilderWithDummyData() *apiRuleBuilder { + return newAPIRuleBuilder(). + WithHost("example-host.example.com"). + WithGateway("example-namespace/example-gateway"). + WithService("example-service", "example-namespace", 8080) +} + +type corsPolicyBuilder struct { + policy gatewayv2alpha1.CorsPolicy +} + +func (c *corsPolicyBuilder) WithAllowOrigins(origins []map[string]string) *corsPolicyBuilder { + c.policy.AllowOrigins = origins + return c +} + +func (c *corsPolicyBuilder) WithAllowMethods(methods []string) *corsPolicyBuilder { + c.policy.AllowMethods = methods + return c +} + +func (c *corsPolicyBuilder) WithAllowHeaders(headers []string) *corsPolicyBuilder { + c.policy.AllowHeaders = headers + return c +} + +func (c *corsPolicyBuilder) WithExposeHeaders(headers []string) *corsPolicyBuilder { + c.policy.ExposeHeaders = headers + return c +} + +func (c *corsPolicyBuilder) WithMaxAge(maxAge uint64) *corsPolicyBuilder { + c.policy.MaxAge = &maxAge + return c +} + +func (c *corsPolicyBuilder) WithAllowCredentials(allow bool) *corsPolicyBuilder { + c.policy.AllowCredentials = &allow + return c +} + +func newCorsPolicyBuilder() *corsPolicyBuilder { + return &corsPolicyBuilder{ + policy: gatewayv2alpha1.CorsPolicy{}, + } +} + +func (c *corsPolicyBuilder) Build() gatewayv2alpha1.CorsPolicy { + return c.policy +} diff --git a/internal/processing/processors/v2alpha1/timeout_test.go b/internal/processing/processors/v2alpha1/timeout_test.go new file mode 100644 index 000000000..303d88b7f --- /dev/null +++ b/internal/processing/processors/v2alpha1/timeout_test.go @@ -0,0 +1,68 @@ +package v2alpha1_test + +import ( + gatewayv2alpha1 "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" + "k8s.io/utils/ptr" + + processors "github.com/kyma-project/api-gateway/internal/processing/processors/v2alpha1" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("GetVirtualServiceHttpTimeout", func() { + It("should return default of 180s when no timeout is set", func() { + // given + apiRuleSpec := gatewayv2alpha1.APIRuleSpec{} + rule := gatewayv2alpha1.Rule{} + + // when + timeout := processors.GetVirtualServiceHttpTimeout(apiRuleSpec, rule) + + // then + Expect(timeout).To(Equal(uint32(180))) + }) + + It("should return the timeout set in the rule when it is set and APIRule has different value", func() { + // given + apiRuleSpec := gatewayv2alpha1.APIRuleSpec{ + Timeout: ptr.To(gatewayv2alpha1.Timeout(20)), + } + rule := gatewayv2alpha1.Rule{ + Timeout: ptr.To(gatewayv2alpha1.Timeout(10)), + } + + // when + timeout := processors.GetVirtualServiceHttpTimeout(apiRuleSpec, rule) + + // then + Expect(timeout).To(Equal(uint32(10))) + }) + + It("should return the timeout set in the rule when it is set and APIRule timeout is not", func() { + // given + apiRuleSpec := gatewayv2alpha1.APIRuleSpec{} + rule := gatewayv2alpha1.Rule{ + Timeout: ptr.To(gatewayv2alpha1.Timeout(10)), + } + + // when + timeout := processors.GetVirtualServiceHttpTimeout(apiRuleSpec, rule) + + // then + Expect(timeout).To(Equal(uint32(10))) + }) + + It("should return the timeout set in the APIRule it is set and rule timeout is not", func() { + // given + apiRuleSpec := gatewayv2alpha1.APIRuleSpec{ + Timeout: ptr.To(gatewayv2alpha1.Timeout(20)), + } + rule := gatewayv2alpha1.Rule{} + + // when + timeout := processors.GetVirtualServiceHttpTimeout(apiRuleSpec, rule) + + // then + Expect(timeout).To(Equal(uint32(20))) + }) +}) diff --git a/internal/processing/processors/v2alpha1/virtual_service_processor.go b/internal/processing/processors/v2alpha1/virtual_service_processor.go new file mode 100644 index 000000000..41df5c41f --- /dev/null +++ b/internal/processing/processors/v2alpha1/virtual_service_processor.go @@ -0,0 +1,174 @@ +package v2alpha1 + +import ( + "context" + "fmt" + gatewayv2alpha1 "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" + "github.com/kyma-project/api-gateway/internal/builders" + "github.com/kyma-project/api-gateway/internal/processing" + "github.com/kyma-project/api-gateway/internal/processing/default_domain" + networkingv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" + ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" + "time" +) + +const defaultHttpTimeout uint32 = 180 + +func NewVirtualServiceProcessor(config processing.ReconciliationConfig, apiRule *gatewayv2alpha1.APIRule) VirtualServiceProcessor { + return VirtualServiceProcessor{ + ApiRule: apiRule, + Creator: virtualServiceCreator{ + defaultDomainName: config.DefaultDomainName, + }, + } +} + +// VirtualServiceProcessor is the generic processor that handles the Virtual Service in the reconciliation of API Rule. +type VirtualServiceProcessor struct { + ApiRule *gatewayv2alpha1.APIRule + Creator VirtualServiceCreator +} + +// VirtualServiceCreator provides the creation of a Virtual Service using the configuration in the given APIRule. +type VirtualServiceCreator interface { + Create(api *gatewayv2alpha1.APIRule) (*networkingv1beta1.VirtualService, error) +} + +// EvaluateReconciliation evaluates the reconciliation of the Virtual Service for the given API Rule. +func (r VirtualServiceProcessor) EvaluateReconciliation(ctx context.Context, client ctrlclient.Client) ([]*processing.ObjectChange, error) { + desired, err := r.getDesiredState(r.ApiRule) + if err != nil { + return make([]*processing.ObjectChange, 0), err + } + + actual, err := r.getActualState(ctx, client, r.ApiRule) + if err != nil { + return make([]*processing.ObjectChange, 0), err + } + + changes := r.getObjectChanges(desired, actual) + + return []*processing.ObjectChange{changes}, nil +} + +func (r VirtualServiceProcessor) getDesiredState(api *gatewayv2alpha1.APIRule) (*networkingv1beta1.VirtualService, error) { + return r.Creator.Create(api) +} + +func (r VirtualServiceProcessor) getActualState(ctx context.Context, client ctrlclient.Client, api *gatewayv2alpha1.APIRule) (*networkingv1beta1.VirtualService, error) { + labels := getOwnerLabels(api) + + var vsList networkingv1beta1.VirtualServiceList + if err := client.List(ctx, &vsList, ctrlclient.MatchingLabels(labels)); err != nil { + return nil, err + } + + if len(vsList.Items) >= 1 { + return vsList.Items[0], nil + } else { + return nil, nil + } +} + +func (r VirtualServiceProcessor) getObjectChanges(desired *networkingv1beta1.VirtualService, actual *networkingv1beta1.VirtualService) *processing.ObjectChange { + if actual != nil { + actual.Spec = *desired.Spec.DeepCopy() + return processing.NewObjectUpdateAction(actual) + } else { + return processing.NewObjectCreateAction(desired) + } +} + +// The owner labels are still set to the old APIRule version. +// Do not switch the owner labels to the new APIRule version unless absolutely necessary! +// This has been done before, and it caused a lot of confusion and bugs. +// If the change for some reason has to be done, please remove the version from the processing.OwnerLabel constant. +func getOwnerLabels(api *gatewayv2alpha1.APIRule) map[string]string { + return map[string]string{ + processing.OwnerLabel: fmt.Sprintf("%s.%s", api.ObjectMeta.Name, api.ObjectMeta.Namespace), + } +} + +type virtualServiceCreator struct { + defaultDomainName string +} + +// Create returns the Virtual Service using the configuration of the APIRule. +func (r virtualServiceCreator) Create(api *gatewayv2alpha1.APIRule) (*networkingv1beta1.VirtualService, error) { + virtualServiceNamePrefix := fmt.Sprintf("%s-", api.ObjectMeta.Name) + + vsSpecBuilder := builders.VirtualServiceSpec() + for _, host := range api.Spec.Hosts { + vsSpecBuilder.AddHost(default_domain.GetHostWithDomain(string(*host), r.defaultDomainName)) + } + + vsSpecBuilder.Gateway(*api.Spec.Gateway) + + for _, rule := range api.Spec.Rules { + httpRouteBuilder := builders.HTTPRoute() + serviceNamespace := findServiceNamespace(api, &rule) + + var host string + var port uint32 + + // Use rule level service if it exists + if rule.Service != nil { + host = default_domain.GetHostLocalDomain(*rule.Service.Name, serviceNamespace) + port = *rule.Service.Port + } else { + // Otherwise, use service defined on APIRule spec level + host = default_domain.GetHostLocalDomain(*api.Spec.Service.Name, serviceNamespace) + port = *api.Spec.Service.Port + } + + httpRouteBuilder.Route(builders.RouteDestination().Host(host).Port(port)) + + matchBuilder := builders.MatchRequest().MethodRegExV2Alpha1(rule.Methods...) + + if rule.Path == "/*" { + matchBuilder.Uri().Prefix("/") + } else { + matchBuilder.Uri().Regex(rule.Path) + } + + httpRouteBuilder.Match(matchBuilder) + + httpRouteBuilder.Timeout(time.Duration(GetVirtualServiceHttpTimeout(api.Spec, rule)) * time.Second) + + headersBuilder := builders.NewHttpRouteHeadersBuilder(). + // For now, the X-Forwarded-Host header is set to the first host in the APIRule hosts list. + // The status of this header is still under discussion in the following GitHub issue: + // https://github.com/kyma-project/api-gateway/issues/1159 + SetHostHeader(default_domain.GetHostWithDomain(string(*api.Spec.Hosts[0]), r.defaultDomainName)) + + if api.Spec.CorsPolicy != nil { + httpRouteBuilder.CorsPolicy(builders.CorsPolicy().FromV2Alpha1ApiRuleCorsPolicy(*api.Spec.CorsPolicy)) + } + headersBuilder.RemoveUpstreamCORSPolicyHeaders() + + httpRouteBuilder.Headers(headersBuilder.Get()) + + vsSpecBuilder.HTTP(httpRouteBuilder) + + } + + vsBuilder := builders.VirtualService(). + GenerateName(virtualServiceNamePrefix). + Namespace(api.ObjectMeta.Namespace). + Label(processing.OwnerLabel, fmt.Sprintf("%s.%s", api.ObjectMeta.Name, api.ObjectMeta.Namespace)) + + vsBuilder.Spec(vsSpecBuilder) + + return vsBuilder.Get(), nil +} + +func GetVirtualServiceHttpTimeout(apiRuleSpec gatewayv2alpha1.APIRuleSpec, rule gatewayv2alpha1.Rule) uint32 { + if rule.Timeout != nil { + return uint32(*rule.Timeout) + } + + if apiRuleSpec.Timeout != nil { + return uint32(*apiRuleSpec.Timeout) + } + return defaultHttpTimeout +} diff --git a/internal/processing/processors/v2alpha1/virtual_service_processor_test.go b/internal/processing/processors/v2alpha1/virtual_service_processor_test.go new file mode 100644 index 000000000..a288d9d59 --- /dev/null +++ b/internal/processing/processors/v2alpha1/virtual_service_processor_test.go @@ -0,0 +1,166 @@ +package v2alpha1_test + +import ( + "context" + gatewayv2alpha1 "github.com/kyma-project/api-gateway/apis/gateway/v2alpha1" + "github.com/kyma-project/api-gateway/internal/builders" + . "github.com/kyma-project/api-gateway/internal/processing/processing_test" + processors "github.com/kyma-project/api-gateway/internal/processing/processors/v2alpha1" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + istioapiv1beta1 "istio.io/api/networking/v1beta1" + networkingv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +var _ = Describe("ObjectChange", func() { + It("should return create action when there is no VirtualService on cluster", func() { + // given + processor := processors.VirtualServiceProcessor{ + ApiRule: &gatewayv2alpha1.APIRule{}, + Creator: mockVirtualServiceCreator{}, + } + + // when + result, err := processor.EvaluateReconciliation(context.Background(), GetFakeClient()) + + // then + Expect(err).To(BeNil()) + Expect(result).To(HaveLen(1)) + Expect(result[0].Action.String()).To(Equal("create")) + }) + + It("should return update action when there is a matching VirtualService on cluster", func() { + // given + apiRuleBuilder := newAPIRuleBuilderWithDummyData() + processor := processors.NewVirtualServiceProcessor(GetTestConfig(), apiRuleBuilder.Build()) + result, err := processor.EvaluateReconciliation(context.Background(), GetFakeClient()) + + Expect(err).To(BeNil()) + Expect(result).To(HaveLen(1)) + Expect(result[0].Action.String()).To(Equal("create")) + + // when + processor = processors.NewVirtualServiceProcessor(GetTestConfig(), apiRuleBuilder.WithHosts("newHost.com").Build()) + result, err = processor.EvaluateReconciliation(context.Background(), GetFakeClient(result[0].Obj.(*networkingv1beta1.VirtualService))) + + // then + Expect(err).To(BeNil()) + Expect(result).To(HaveLen(1)) + Expect(result[0].Action.String()).To(Equal("update")) + }) +}) + +var _ = Describe("Fully configured APIRule happy path", func() { + It("should create a VirtualService with all the configured values", func() { + apiRule := newAPIRuleBuilder(). + WithGateway("example/example"). + WithHosts("example.com", "goat.com"). + WithService("example-service", "example-namespace", 8080). + WithTimeout(180). + WithCORSPolicy(newCorsPolicyBuilder(). + WithAllowOrigins([]map[string]string{{"exact": "example.com"}}). + WithAllowMethods([]string{"GET", "POST"}). + WithAllowHeaders([]string{"header1", "header2"}). + WithExposeHeaders([]string{"header3", "header4"}). + WithAllowCredentials(true). + WithMaxAge(600). + Build()). + WithRules( + newRuleBuilder(). + WithService("another-service", "another-namespace", 9999). + WithMethods("GET", "POST"). + WithPath("/"). + WithJWTAuthn("example.com", "https://jwks.example.com", nil, nil). + WithTimeout(10).Build(), + + newRuleBuilder(). + WithMethods("PUT"). + WithPath("/*"). + NoAuth().Build(), + ). + Build() + + client := GetFakeClient() + processor := processors.NewVirtualServiceProcessor(GetTestConfig(), apiRule) + checkVirtualServices(client, processor, []verifier{ + func(vs *networkingv1beta1.VirtualService) { + Expect(vs.Spec.Hosts).To(ConsistOf("example.com", "goat.com")) + Expect(vs.Spec.Gateways).To(ConsistOf("example/example")) + Expect(vs.Spec.Http).To(HaveLen(2)) + + Expect(vs.Spec.Http[0].Match[0].Method.GetRegex()).To(Equal("^(GET|POST)$")) + Expect(vs.Spec.Http[0].Match[0].Uri.GetRegex()).To(Equal("/")) + Expect(vs.Spec.Http[0].Route[0].Destination.Host).To(Equal("another-service.another-namespace.svc.cluster.local")) + Expect(vs.Spec.Http[0].Route[0].Destination.Port.Number).To(Equal(uint32(9999))) + + Expect(vs.Spec.Http[0].CorsPolicy).NotTo(BeNil()) + Expect(vs.Spec.Http[0].CorsPolicy.AllowOrigins).To(HaveLen(1)) + Expect(vs.Spec.Http[0].CorsPolicy.AllowOrigins[0]).To(Equal(&istioapiv1beta1.StringMatch{MatchType: &istioapiv1beta1.StringMatch_Exact{Exact: "example.com"}})) + Expect(vs.Spec.Http[0].CorsPolicy.AllowMethods).To(ConsistOf("GET", "POST")) + Expect(vs.Spec.Http[0].CorsPolicy.AllowHeaders).To(ConsistOf("header1", "header2")) + Expect(vs.Spec.Http[0].CorsPolicy.ExposeHeaders).To(ConsistOf("header3", "header4")) + Expect(vs.Spec.Http[0].CorsPolicy.AllowCredentials.GetValue()).To(BeTrue()) + Expect(vs.Spec.Http[0].CorsPolicy.MaxAge.Seconds).To(Equal(int64(600))) + + Expect(vs.Spec.Http[0].Timeout.Seconds).To(Equal(int64(10))) + + Expect(vs.Spec.Http[1].Match[0].Method.GetRegex()).To(Equal("^(PUT)$")) + Expect(vs.Spec.Http[1].Match[0].Uri.GetPrefix()).To(Equal("/")) + Expect(vs.Spec.Http[1].Route[0].Destination.Host).To(Equal("example-service.example-namespace.svc.cluster.local")) + Expect(vs.Spec.Http[1].Route[0].Destination.Port.Number).To(Equal(uint32(8080))) + + Expect(vs.Spec.Http[1].CorsPolicy).NotTo(BeNil()) + Expect(vs.Spec.Http[1].CorsPolicy.AllowOrigins).To(HaveLen(1)) + Expect(vs.Spec.Http[1].CorsPolicy.AllowOrigins[0]).To(Equal(&istioapiv1beta1.StringMatch{MatchType: &istioapiv1beta1.StringMatch_Exact{Exact: "example.com"}})) + Expect(vs.Spec.Http[1].CorsPolicy.AllowMethods).To(ConsistOf("GET", "POST")) + Expect(vs.Spec.Http[1].CorsPolicy.AllowHeaders).To(ConsistOf("header1", "header2")) + Expect(vs.Spec.Http[1].CorsPolicy.ExposeHeaders).To(ConsistOf("header3", "header4")) + Expect(vs.Spec.Http[1].CorsPolicy.AllowCredentials.GetValue()).To(BeTrue()) + Expect(vs.Spec.Http[1].CorsPolicy.MaxAge.Seconds).To(Equal(int64(600))) + + Expect(vs.Spec.Http[1].Timeout.Seconds).To(Equal(int64(180))) + }, + }, "create") + + }) +}) + +var _ = Describe("VirtualServiceProcessor", func() { + It("should create virtual service when no virtual service exists", func() { + // given + processor := processors.VirtualServiceProcessor{ + ApiRule: &gatewayv2alpha1.APIRule{}, + Creator: mockVirtualServiceCreator{}, + } + + // when + result, err := processor.EvaluateReconciliation(context.Background(), GetFakeClient()) + + // then + Expect(err).To(BeNil()) + Expect(result).To(HaveLen(1)) + Expect(result[0].Action.String()).To(Equal("create")) + }) +}) + +func checkVirtualServices(c client.Client, processor processors.VirtualServiceProcessor, verifiers []verifier, expectedActions ...string) { + result, err := processor.EvaluateReconciliation(context.Background(), c) + Expect(err).To(BeNil()) + Expect(result).To(HaveLen(len(expectedActions))) + for i, action := range expectedActions { + Expect(result[i].Action.String()).To(Equal(action)) + } + + for i, v := range verifiers { + v(result[i].Obj.(*networkingv1beta1.VirtualService)) + } +} + +type verifier func(*networkingv1beta1.VirtualService) + +type mockVirtualServiceCreator struct{} + +func (r mockVirtualServiceCreator) Create(_ *gatewayv2alpha1.APIRule) (*networkingv1beta1.VirtualService, error) { + return builders.VirtualService().Get(), nil +}