diff --git a/conformance/Makefile b/conformance/Makefile new file mode 100644 index 000000000..0a7239c35 --- /dev/null +++ b/conformance/Makefile @@ -0,0 +1,59 @@ +NKG_TAG = edge +NKG_PREFIX = nginx-kubernetes-gateway +GATEWAY_CLASS = nginx +SUPPORTED_FEATURES = Gateway,HTTPRoute +KIND_KUBE_CONFIG_FOLDER = $${HOME}/.kube/kind +TAG = latest +PREFIX = conformance-test-runner +.DEFAULT_GOAL := help + +.PHONY: help +help: Makefile ## Display this help + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "; printf "Usage:\n\n make \033[36m\033[0m\n\nTargets:\n\n"}; {printf " \033[36m%-30s\033[0m %s\n", $$1, $$2}' + +.PHONY: build-test-runner-image +build-test-runner-image: ## Build conformance test runner image + docker build -t $(PREFIX):$(TAG) -f tests/Dockerfile .. + +.PHONY: create-kind-cluster +create-kind-cluster: ## Create a kind cluster + kind create cluster --image kindest/node:v1.27.1 + kind export kubeconfig --kubeconfig $(KIND_KUBE_CONFIG_FOLDER)/config + +.PHONY: prepare-nkg +prepare-nkg: ## Build and load NKG container on configured kind cluster + cd .. && make PREFIX=$(NKG_PREFIX) TAG=$(NKG_TAG) container + kind load docker-image $(NKG_PREFIX):$(NKG_TAG) + +.PHONY: install-nkg +install-nkg: ## Install NKG with provisioner on configured kind cluster + kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v0.7.0/standard-install.yaml + kubectl wait --for=condition=available --timeout=60s deployment gateway-api-admission-server -n gateway-system + kubectl apply -f ../deploy/manifests/namespace.yaml + kubectl create configmap njs-modules --from-file=../internal/nginx/modules/src/httpmatches.js -n nginx-gateway + kubectl apply -f ../deploy/manifests/nginx-conf.yaml + kubectl apply -f ../deploy/manifests/rbac.yaml + kubectl apply -f ../deploy/manifests/gatewayclass.yaml + kubectl apply -f ../deploy/manifests/service/nodeport.yaml + kubectl apply -f provisioner/provisioner.yaml + +.PHONY: update-test-kind-config +update-test-kind-config: ## Update kind config + sed -ir "s|server:.*|server: https://kind-control-plane:6443|" $(KIND_KUBE_CONFIG_FOLDER)/config + +.PHONY: run-conformance-tests +run-conformance-tests: update-test-kind-config ## Run conformance tests + docker run --network=kind --rm -v $(KIND_KUBE_CONFIG_FOLDER):/root/.kube $(PREFIX):$(TAG) \ + go test -v . -tags conformance -args --gateway-class=$(GATEWAY_CLASS) --supported-features=$(SUPPORTED_FEATURES) + +.PHONY: uninstall-nkg +uninstall-nkg: ## Uninstall NKG on configured kind cluster + kubectl delete -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v0.7.0/standard-install.yaml + kubectl delete -f ../deploy/manifests/rbac.yaml + kubectl delete -f ../deploy/manifests/namespace.yaml + kubectl delete clusterrole nginx-gateway-provisioner + kubectl delete clusterrolebinding nginx-gateway-provisioner + +.PHONY: delete-kind-cluster +delete-kind-cluster: ## Delete kind cluster + kind delete cluster diff --git a/conformance/README.md b/conformance/README.md new file mode 100644 index 000000000..26eaac8fb --- /dev/null +++ b/conformance/README.md @@ -0,0 +1,77 @@ +# Running [Gateway Conformance Tests](https://gateway-api.sigs.k8s.io/concepts/conformance/#3-conformance-tests) in kind + +## Prerequisites: + +* [kind](https://kind.sigs.k8s.io/). +* Docker. +* Golang. + +**Note**: all commands in steps below are executed from the ```conformance``` directory + +List available commands: + +```bash +$ make + +build-test-image Build conformance test image +create-kind-cluster Create a kind cluster +delete-kind-cluster Delete kind cluster +help Display this help +install-nkg Install NKG on configured kind cluster +run-conformance-tests Run conformance tests +uninstall-nkg Uninstall NKG from configured kind cluster +update-test-kind-config Update kind config +``` +### Step 1 - Create a kind Cluster + +```bash +$ make create-kind-cluster +``` + +### Step 2 - Update NKG deployment and provisioner manifests +**Note**: this step is only required when user wants to run conformance tests using locally built image of Nginx Kubernetes Gateway +* Set NKG_PREFIX= NKG_TAG= to preferred values. +* Navigate to `deploy/manifests` and update values in `deployment.yaml` as specified in below code-block. +* Navigate to `conformance/provisioner` and update values in `provisioner.yaml` as specified in below code-block. +* Save the changes. +``` +. +.. +containers: +- image: : + imagePullPolicy: Never +.. +. +``` + +### Step 3 - Build and load Nginx Kubernetes Gateway container to configured kind cluster +**Note**: this step is only required when user wants to run conformance tests using locally built image of Nginx Kubernetes Gateway + +```bash +$ make NKG_PREFIX= NKG_TAG= prepare-nkg + +``` +### Step 4 - Build conformance test runner image +```bash +$ make build-test-runner-image +``` + +### Step 5 - Install Nginx Kubernetes Gateway +```bash +$ make install-nkg +``` + +### Step 6 - Run Gateway conformance tests +```bash +$ make run-conformance-tests +``` + +### Step 7 - Uninstall Nginx Kubernetes Gateway +```bash +$ make uninstall-nkg +``` + +### Step 8 - Delete kind cluster +```bash +$ make delete-kind-cluster +``` diff --git a/conformance/tests/Dockerfile b/conformance/tests/Dockerfile new file mode 100644 index 000000000..672872bbd --- /dev/null +++ b/conformance/tests/Dockerfile @@ -0,0 +1,11 @@ +# syntax=docker/dockerfile:1.5 + +FROM golang:1.20 + +WORKDIR /go/src/github.com/nginxinc/nginx-kubernetes-gateway/conformance/tests/ + +COPY --link go.mod /go/src/github.com/nginxinc/nginx-kubernetes-gateway/ +COPY --link go.sum /go/src/github.com/nginxinc/nginx-kubernetes-gateway/ +RUN go mod download + +COPY --link conformance/tests /go/src/github.com/nginxinc/nginx-kubernetes-gateway/conformance/tests/ diff --git a/conformance/tests/conformance_test.go b/conformance/tests/conformance_test.go new file mode 100644 index 000000000..b75ef2d68 --- /dev/null +++ b/conformance/tests/conformance_test.go @@ -0,0 +1,59 @@ +//go:build conformance + +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package tests + +import ( + "testing" + + . "github.com/onsi/gomega" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/config" + "sigs.k8s.io/gateway-api/apis/v1alpha2" + "sigs.k8s.io/gateway-api/apis/v1beta1" + "sigs.k8s.io/gateway-api/conformance/tests" + "sigs.k8s.io/gateway-api/conformance/utils/flags" + "sigs.k8s.io/gateway-api/conformance/utils/suite" +) + +func TestConformance(t *testing.T) { + g := NewGomegaWithT(t) + cfg, err := config.GetConfig() + g.Expect(err).To(BeNil()) + + client, err := client.New(cfg, client.Options{}) + g.Expect(err).To(BeNil()) + + g.Expect(v1alpha2.AddToScheme(client.Scheme())).To(Succeed()) + g.Expect(v1beta1.AddToScheme(client.Scheme())).To(Succeed()) + + t.Logf(`Running conformance tests with %s GatewayClass\n cleanup: %t\n`+ + `debug: %t\n enable all features: %t \n supported features: [%v]\n exempt features: [%v]`, + *flags.GatewayClassName, *flags.CleanupBaseResources, *flags.ShowDebug, + *flags.EnableAllSupportedFeatures, *flags.SupportedFeatures, *flags.ExemptFeatures) + + cSuite := suite.New(suite.Options{ + Client: client, + GatewayClassName: *flags.GatewayClassName, + Debug: *flags.ShowDebug, + CleanupBaseResources: *flags.CleanupBaseResources, + SupportedFeatures: nil, + EnableAllSupportedFeatures: *flags.EnableAllSupportedFeatures, + }) + cSuite.Setup(t) + cSuite.Run(t, tests.ConformanceTests) +} diff --git a/docs/developer/testing.md b/docs/developer/testing.md index 2de781e6a..8fdbecc2d 100644 --- a/docs/developer/testing.md +++ b/docs/developer/testing.md @@ -83,10 +83,14 @@ Follow the steps below for manual testing: - NGINX proxies traffic successfully (when applicable). - [Examples](/examples) work correctly. This will ensure that your changes have not introduced any regressions. - > **Note** > > Don't limit yourself to happy path testing. Make an effort to cover various scenarios, including edge cases and potential error conditions. By testing a wide range of scenarios, you can uncover hidden issues and ensure the robustness of your changes. Performing manual testing helps guarantee the stability, reliability, and effectiveness of your changes before submitting them for review and integration into the project. + + +## Gateway API Conformance Testing + +To run Gateway API conformance tests, please follow the instructions on [this](/conformance/README.md) page. diff --git a/go.mod b/go.mod index 4bd695b65..9b6bb044e 100644 --- a/go.mod +++ b/go.mod @@ -42,15 +42,18 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/moby/spdystream v0.2.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.15.1 // indirect github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/testify v1.8.2 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.7.0 // indirect go.uber.org/zap v1.24.0 // indirect diff --git a/go.sum b/go.sum index 8121879cf..9b2b1620b 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,6 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -75,6 +76,7 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJY github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= @@ -101,6 +103,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/maxbrunsfeld/counterfeiter/v6 v6.6.1 h1:9XE5ykDiC8eNSqIPkxx0EsV3kMX1oe4kQWRZjIgytUA= github.com/maxbrunsfeld/counterfeiter/v6 v6.6.1/go.mod h1:qbKwBR+qQODzH2WD/s53mdgp/xVcXMlJb59GRFOp6Z4= +github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -145,6 +149,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=