From 845a5ec195d3662cf3b10b3d00c6ddce551e045f Mon Sep 17 00:00:00 2001 From: Karol Szwaj Date: Wed, 12 Jun 2024 19:54:11 +0200 Subject: [PATCH] e2e: basic multiple gc test (#2707) * e2e: multiple gc test Signed-off-by: Karol Szwaj * update multiple gc tests Signed-off-by: Karol Szwaj --- test/config/gatewayclass.yaml | 15 ++++ test/e2e/multiple_gc/multiple_gc_test.go | 110 +++++++++++++++++++++++ test/e2e/testdata/internet-gc.yaml | 74 +++++++++++++++ test/e2e/testdata/private-gc.yaml | 74 +++++++++++++++ test/e2e/tests/multiple-gc.go | 85 ++++++++++++++++++ test/e2e/tests/tests.go | 1 + tools/make/kube.mk | 7 +- 7 files changed, 364 insertions(+), 2 deletions(-) create mode 100644 test/e2e/multiple_gc/multiple_gc_test.go create mode 100644 test/e2e/testdata/internet-gc.yaml create mode 100644 test/e2e/testdata/private-gc.yaml create mode 100644 test/e2e/tests/multiple-gc.go diff --git a/test/config/gatewayclass.yaml b/test/config/gatewayclass.yaml index e4a801b6b8e..ad5ce4fefe4 100644 --- a/test/config/gatewayclass.yaml +++ b/test/config/gatewayclass.yaml @@ -126,3 +126,18 @@ metadata: namespace: envoy-gateway-system spec: mergeGateways: true +--- +kind: GatewayClass +apiVersion: gateway.networking.k8s.io/v1 +metadata: + name: internet +spec: + controllerName: gateway.envoyproxy.io/gatewayclass-controller +--- +kind: GatewayClass +apiVersion: gateway.networking.k8s.io/v1 +metadata: + name: private +spec: + controllerName: gateway.envoyproxy.io/gatewayclass-controller +--- diff --git a/test/e2e/multiple_gc/multiple_gc_test.go b/test/e2e/multiple_gc/multiple_gc_test.go new file mode 100644 index 00000000000..75b642bd16c --- /dev/null +++ b/test/e2e/multiple_gc/multiple_gc_test.go @@ -0,0 +1,110 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +//go:build e2e +// +build e2e + +package multiplegc + +import ( + "flag" + "io/fs" + "testing" + + "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/config" + "sigs.k8s.io/gateway-api/conformance/utils/flags" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" + + "github.com/envoyproxy/gateway/test/e2e" + "github.com/envoyproxy/gateway/test/e2e/tests" +) + +func TestMultipleGC(t *testing.T) { + flag.Parse() + + cfg, err := config.GetConfig() + require.NoError(t, err) + + c, err := client.New(cfg, client.Options{}) + require.NoError(t, err) + + // Install all the scheme to kubernetes client. + e2e.CheckInstallScheme(t, c) + + if flags.RunTest != nil && *flags.RunTest != "" { + t.Logf("Running E2E test %s with %s GatewayClass\n cleanup: %t\n debug: %t", + *flags.RunTest, *flags.GatewayClassName, *flags.CleanupBaseResources, *flags.ShowDebug) + } else { + t.Logf("Running E2E tests with %s GatewayClass\n cleanup: %t\n debug: %t", + *flags.GatewayClassName, *flags.CleanupBaseResources, *flags.ShowDebug) + } + t.Run("Internet GC Test", func(t *testing.T) { + t.Parallel() + internetGatewaySuiteGatewayClassName := "internet" + internetGatewaySuite, err := suite.NewConformanceTestSuite(suite.ConformanceOptions{ + Client: c, + GatewayClassName: internetGatewaySuiteGatewayClassName, + Debug: *flags.ShowDebug, + CleanupBaseResources: *flags.CleanupBaseResources, + RunTest: *flags.RunTest, + // SupportedFeatures cannot be empty, so we set it to SupportGateway + // All e2e tests should leave Features empty. + SupportedFeatures: sets.New[features.SupportedFeature](features.SupportGateway), + SkipTests: []string{}, + }) + if err != nil { + t.Fatalf("Failed to create ConformanceTestSuite: %v", err) + } + + // Setting up the necessary arguments for the suite instead of calling Suite.Setup method again, + // since this test suite reuse the base resources of previous test suite. + internetGatewaySuite.Applier.ManifestFS = []fs.FS{e2e.Manifests} + internetGatewaySuite.Applier.GatewayClass = internetGatewaySuiteGatewayClassName + internetGatewaySuite.ControllerName = kubernetes.GWCMustHaveAcceptedConditionTrue(t, internetGatewaySuite.Client, internetGatewaySuite.TimeoutConfig, internetGatewaySuite.GatewayClassName) + + t.Logf("Running %d MultipleGC tests", len(tests.MultipleGCTests[internetGatewaySuiteGatewayClassName])) + + err = internetGatewaySuite.Run(t, tests.MultipleGCTests[internetGatewaySuiteGatewayClassName]) + if err != nil { + t.Fatalf("Failed to run InternetGC tests: %v", err) + } + }) + + t.Run("Private GC Test", func(t *testing.T) { + t.Parallel() + privateGatewaySuiteGatewayClassName := "private" + privateGatewaySuite, err := suite.NewConformanceTestSuite(suite.ConformanceOptions{ + Client: c, + GatewayClassName: privateGatewaySuiteGatewayClassName, + Debug: *flags.ShowDebug, + CleanupBaseResources: *flags.CleanupBaseResources, + RunTest: *flags.RunTest, + // SupportedFeatures cannot be empty, so we set it to SupportGateway + // All e2e tests should leave Features empty. + SupportedFeatures: sets.New[features.SupportedFeature](features.SupportGateway), + SkipTests: []string{}, + }) + if err != nil { + t.Fatalf("Failed to create ConformanceTestSuite: %v", err) + } + + // Setting up the necessary arguments for the suite instead of calling Suite.Setup method again, + // since this test suite reuse the base resources of previous test suite. + privateGatewaySuite.Applier.ManifestFS = []fs.FS{e2e.Manifests} + privateGatewaySuite.Applier.GatewayClass = privateGatewaySuiteGatewayClassName + privateGatewaySuite.ControllerName = kubernetes.GWCMustHaveAcceptedConditionTrue(t, privateGatewaySuite.Client, privateGatewaySuite.TimeoutConfig, privateGatewaySuite.GatewayClassName) + + t.Logf("Running %d MultipleGC tests", len(tests.MultipleGCTests[privateGatewaySuiteGatewayClassName])) + err = privateGatewaySuite.Run(t, tests.MultipleGCTests[privateGatewaySuiteGatewayClassName]) + if err != nil { + t.Fatalf("Failed to run PrivateGC tests: %v", err) + } + }) +} diff --git a/test/e2e/testdata/internet-gc.yaml b/test/e2e/testdata/internet-gc.yaml new file mode 100644 index 00000000000..91a4b992aa9 --- /dev/null +++ b/test/e2e/testdata/internet-gc.yaml @@ -0,0 +1,74 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: internet-gateway + namespace: gateway-conformance-infra +spec: + gatewayClassName: internet + listeners: + - name: http + port: 80 + protocol: HTTP + allowedRoutes: + namespaces: + from: Same +--- +apiVersion: v1 +kind: Service +metadata: + name: internet-backend + namespace: gateway-conformance-infra +spec: + selector: + app: internet-backend + ports: + - protocol: TCP + port: 8080 + targetPort: 3000 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: internet-backend + namespace: gateway-conformance-infra + labels: + app: internet-backend +spec: + replicas: 2 + selector: + matchLabels: + app: internet-backend + template: + metadata: + labels: + app: internet-backend + spec: + containers: + - name: internet-backend + image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + resources: + requests: + cpu: 10m +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: internet-route + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: internet-gateway + sectionName: http + rules: + - backendRefs: + - name: internet-backend + port: 8080 diff --git a/test/e2e/testdata/private-gc.yaml b/test/e2e/testdata/private-gc.yaml new file mode 100644 index 00000000000..c47e49fc98a --- /dev/null +++ b/test/e2e/testdata/private-gc.yaml @@ -0,0 +1,74 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: private-gateway + namespace: gateway-conformance-infra +spec: + gatewayClassName: private + listeners: + - name: http + port: 80 + protocol: HTTP + allowedRoutes: + namespaces: + from: Same +--- +apiVersion: v1 +kind: Service +metadata: + name: private-backend + namespace: gateway-conformance-infra +spec: + selector: + app: private-backend + ports: + - protocol: TCP + port: 8080 + targetPort: 3000 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: private-backend + namespace: gateway-conformance-infra + labels: + app: private-backend +spec: + replicas: 2 + selector: + matchLabels: + app: private-backend + template: + metadata: + labels: + app: private-backend + spec: + containers: + - name: private-backend + image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + resources: + requests: + cpu: 10m +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: private-route + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: private-gateway + sectionName: http + rules: + - backendRefs: + - name: private-backend + port: 8080 diff --git a/test/e2e/tests/multiple-gc.go b/test/e2e/tests/multiple-gc.go new file mode 100644 index 00000000000..9b56ed1e2e4 --- /dev/null +++ b/test/e2e/tests/multiple-gc.go @@ -0,0 +1,85 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +// This file contains code derived from upstream gateway-api, it will be moved to upstream. + +//go:build e2e +// +build e2e + +package tests + +import ( + "testing" + + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" +) + +var ( + InternetGCTests []suite.ConformanceTest + PrivateGCTests []suite.ConformanceTest +) + +func init() { + MultipleGCTests = make(map[string][]suite.ConformanceTest) + InternetGCTests = append(InternetGCTests, InternetGCTest) + PrivateGCTests = append(PrivateGCTests, PrivateGCTest) + MultipleGCTests["internet"] = InternetGCTests + MultipleGCTests["private"] = PrivateGCTests +} + +var InternetGCTest = suite.ConformanceTest{ + ShortName: "InternetGC", + Description: "Testing multiple GatewayClass with the same controller", + Manifests: []string{"testdata/internet-gc.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + t.Run("internet gc", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "internet-route", Namespace: ns} + gwNN := types.NamespacedName{Name: "internet-gateway", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + OkResp := http.ExpectedResponse{ + Request: http.Request{ + Path: "/", + }, + Response: http.Response{ + StatusCode: 200, + }, + Namespace: ns, + } + + // Send a request to an valid path and expect a successful response + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, OkResp) + }) + }, +} + +var PrivateGCTest = suite.ConformanceTest{ + ShortName: "PrivateGC", + Description: "Testing multiple GatewayClass with the same controller", + Manifests: []string{"testdata/private-gc.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + t.Run("private gc", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "private-route", Namespace: ns} + gwNN := types.NamespacedName{Name: "private-gateway", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + OkResp := http.ExpectedResponse{ + Request: http.Request{ + Path: "/", + }, + Response: http.Response{ + StatusCode: 200, + }, + Namespace: ns, + } + + // Send a request to an valid path and expect a successful response + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, OkResp) + }) + }, +} diff --git a/test/e2e/tests/tests.go b/test/e2e/tests/tests.go index 6888cff3a8c..dc39be7790b 100644 --- a/test/e2e/tests/tests.go +++ b/test/e2e/tests/tests.go @@ -14,4 +14,5 @@ var ( ConformanceTests []suite.ConformanceTest UpgradeTests []suite.ConformanceTest MergeGatewaysTests []suite.ConformanceTest + MultipleGCTests map[string][]suite.ConformanceTest ) diff --git a/tools/make/kube.mk b/tools/make/kube.mk index eec42ea2395..81d63e9cc25 100644 --- a/tools/make/kube.mk +++ b/tools/make/kube.mk @@ -3,7 +3,7 @@ ENVTEST_K8S_VERSION ?= 1.28.0 # Need run cel validation across multiple versions of k8s ENVTEST_K8S_VERSIONS ?= 1.27.1 1.28.0 1.29.0 # GATEWAY_API_VERSION refers to the version of Gateway API CRDs. -# For more details, see https://gateway-api.sigs.k8s.io/guides/getting-started/#installing-gateway-api +# For more details, see https://gateway-api.sigs.k8s.io/guides/getting-started/#installing-gateway-api GATEWAY_API_VERSION ?= $(shell go list -m -f '{{.Version}}' sigs.k8s.io/gateway-api) GATEWAY_RELEASE_URL ?= https://github.com/kubernetes-sigs/gateway-api/releases/download/${GATEWAY_API_VERSION}/experimental-install.yaml @@ -125,6 +125,7 @@ run-e2e: install-e2e-telemetry ifeq ($(E2E_RUN_TEST),) go test -v -tags e2e ./test/e2e --gateway-class=envoy-gateway --debug=true --cleanup-base-resources=false go test -v -tags e2e ./test/e2e/merge_gateways --gateway-class=merge-gateways --debug=true --cleanup-base-resources=false + go test -v -tags e2e ./test/e2e/multiple_gc --debug=true --cleanup-base-resources=false go test -v -tags e2e ./test/e2e/upgrade --gateway-class=upgrade --debug=true --cleanup-base-resources=$(E2E_CLEANUP) else ifeq ($(E2E_RUN_EG_UPGRADE_TESTS),false) @@ -132,6 +133,8 @@ ifeq ($(E2E_RUN_EG_UPGRADE_TESTS),false) --run-test $(E2E_RUN_TEST) go test -v -tags e2e ./test/e2e --gateway-class=envoy-gateway --debug=true --cleanup-base-resources=$(E2E_CLEANUP) \ --run-test $(E2E_RUN_TEST) + go test -v -tags e2e ./test/e2e/multiple_gc --debug=true --cleanup-base-resources=$(E2E_CLEANUP) \ + --run-test $(E2E_RUN_TEST) else go test -v -tags e2e ./test/e2e/upgrade --gateway-class=upgrade --debug=true --cleanup-base-resources=$(E2E_CLEANUP) \ --run-test $(E2E_RUN_TEST) @@ -204,7 +207,7 @@ run-conformance: ## Run Gateway API conformance. kubectl apply -f test/config/gatewayclass.yaml go test -v -tags conformance ./test/conformance --gateway-class=envoy-gateway --debug=true -CONFORMANCE_REPORT_PATH ?= +CONFORMANCE_REPORT_PATH ?= .PHONY: run-experimental-conformance run-experimental-conformance: ## Run Experimental Gateway API conformance.