You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by kv...@apache.org on 2021/04/01 03:27:35 UTC
[apisix-ingress-controller] branch master updated: test: add e2e
test cases for redirect, uri-blocker and fault-injection plugins (#320)
This is an automated email from the ASF dual-hosted git repository.
kvn pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-ingress-controller.git
The following commit(s) were added to refs/heads/master by this push:
new 06e2b35 test: add e2e test cases for redirect, uri-blocker and fault-injection plugins (#320)
06e2b35 is described below
commit 06e2b35bccbf62a9d7a1d0e2680eb9a71be78cae
Author: Alex Zhang <to...@apache.org>
AuthorDate: Thu Apr 1 11:27:25 2021 +0800
test: add e2e test cases for redirect, uri-blocker and fault-injection plugins (#320)
* test: add e2e test cases for redirect and fault-injection plugins
* fix
* fix
* test: add test cases for uri-blocker plugin
* fix
---
pkg/kube/apisix/apis/config/v2alpha1/types.go | 2 +-
test/e2e/README.md | 12 +-
test/e2e/e2e.go | 1 +
test/e2e/plugins/fault_injection.go | 175 ++++++++++++++++++++++++++
test/e2e/plugins/redirect.go | 151 ++++++++++++++++++++++
test/e2e/plugins/uri_blocker.go | 150 ++++++++++++++++++++++
test/e2e/scaffold/scaffold.go | 3 +
7 files changed, 492 insertions(+), 2 deletions(-)
diff --git a/pkg/kube/apisix/apis/config/v2alpha1/types.go b/pkg/kube/apisix/apis/config/v2alpha1/types.go
index 303bd04..bc4232b 100644
--- a/pkg/kube/apisix/apis/config/v2alpha1/types.go
+++ b/pkg/kube/apisix/apis/config/v2alpha1/types.go
@@ -174,7 +174,7 @@ type ApisixRouteHTTPPlugin struct {
Enable bool `json:"enable" yaml:"enable"`
// Plugin configuration.
// TODO we may use protobuf to define it.
- Config ApisixRouteHTTPPluginConfig
+ Config ApisixRouteHTTPPluginConfig `json:"config" yaml:"config"`
}
// ApisixRouteHTTPPluginConfig is the configuration for
diff --git a/test/e2e/README.md b/test/e2e/README.md
index 5f508a8..bc35f93 100644
--- a/test/e2e/README.md
+++ b/test/e2e/README.md
@@ -20,7 +20,7 @@
apisix ingress controller e2e test suites
=========================================
-For running e2e test cases, a Kubernetes cluster is needed, [minikube](https://minikube.sigs.k8s.io/docs/start/) is a good choice to build k8s cluster in development environment.
+For running e2e test cases, a Kubernetes cluster is required, [minikube](https://minikube.sigs.k8s.io/docs/start/) is a good choice to build k8s cluster in development environment.
Scaffold
---------
@@ -34,3 +34,13 @@ a e2e test scaffold is prepared to run test cases easily. The source codes are i
* Create a http server with [kennethreitz/httpbin](https://hub.docker.com/r/kennethreitz/httpbin/) as the upstream.
The above mentioned steps are run before each case starts and all resources will be destroyed after the case finishes.
+
+Plugins
+-------
+
+Test cases inside `plugins` directory test the availability about APISIX plugins.
+
+Features
+--------
+
+Test caes inside `features` directory test some features about APISIX, such as traffic-split, health check and so on.
diff --git a/test/e2e/e2e.go b/test/e2e/e2e.go
index 8c5052d..d2ea114 100644
--- a/test/e2e/e2e.go
+++ b/test/e2e/e2e.go
@@ -18,6 +18,7 @@ import (
_ "github.com/apache/apisix-ingress-controller/test/e2e/endpoints"
_ "github.com/apache/apisix-ingress-controller/test/e2e/features"
_ "github.com/apache/apisix-ingress-controller/test/e2e/ingress"
+ _ "github.com/apache/apisix-ingress-controller/test/e2e/plugins"
)
func runE2E() {}
diff --git a/test/e2e/plugins/fault_injection.go b/test/e2e/plugins/fault_injection.go
new file mode 100644
index 0000000..6dd3b52
--- /dev/null
+++ b/test/e2e/plugins/fault_injection.go
@@ -0,0 +1,175 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You 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 plugins
+
+import (
+ "fmt"
+ "net/http"
+ "time"
+
+ "github.com/apache/apisix-ingress-controller/test/e2e/scaffold"
+ "github.com/onsi/ginkgo"
+ "github.com/stretchr/testify/assert"
+)
+
+var _ = ginkgo.Describe("fault-injection plugin", func() {
+ opts := &scaffold.Options{
+ Name: "default",
+ Kubeconfig: scaffold.GetKubeconfig(),
+ APISIXConfigPath: "testdata/apisix-gw-config.yaml",
+ APISIXDefaultConfigPath: "testdata/apisix-gw-config-default.yaml",
+ IngressAPISIXReplicas: 1,
+ HTTPBinServicePort: 80,
+ APISIXRouteVersion: "apisix.apache.org/v2alpha1",
+ }
+ s := scaffold.NewScaffold(opts)
+ ginkgo.It("inject code and body to abort request", func() {
+ backendSvc, backendPorts := s.DefaultHTTPBackend()
+ ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2alpha1
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+ match:
+ hosts:
+ - httpbin.org
+ paths:
+ - /ip
+ backends:
+ - serviceName: %s
+ servicePort: %d
+ weight: 10
+ plugins:
+ - name: fault-injection
+ enable: true
+ config:
+ abort:
+ http_status: 500
+ body: "internal server error"
+ vars:
+ - [ ["http_x_foo", "==", "bar"], ["arg_name", "==", "bob"] ]
+`, backendSvc, backendPorts[0])
+
+ assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ar))
+
+ err := s.EnsureNumApisixUpstreamsCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams")
+ err = s.EnsureNumApisixRoutesCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes")
+
+ // vars unsatisfied
+ resp := s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.org").Expect()
+ resp.Status(http.StatusOK)
+
+ resp = s.NewAPISIXClient().GET("/ip").WithQuery("name", "bob").WithHeader("Host", "httpbin.org").WithHeader("X-Foo", "bar").Expect()
+ resp.Status(http.StatusInternalServerError)
+ resp.Body().Equal("internal server error")
+ })
+
+ ginkgo.It("delay request", func() {
+ backendSvc, backendPorts := s.DefaultHTTPBackend()
+ ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2alpha1
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+ match:
+ hosts:
+ - httpbin.org
+ paths:
+ - /ip
+ backends:
+ - serviceName: %s
+ servicePort: %d
+ weight: 10
+ plugins:
+ - name: fault-injection
+ enable: true
+ config:
+ delay:
+ duration: 3
+ vars:
+ - [ ["http_x_foo", "==", "bar"], ["arg_name", "==", "bob"] ]
+`, backendSvc, backendPorts[0])
+
+ assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ar))
+
+ err := s.EnsureNumApisixUpstreamsCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams")
+ err = s.EnsureNumApisixRoutesCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes")
+
+ // vars unsatisfied
+ resp := s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.org").Expect()
+ resp.Status(http.StatusOK)
+
+ now := time.Now()
+ resp = s.NewAPISIXClient().GET("/ip").WithQuery("name", "bob").WithHeader("Host", "httpbin.org").WithHeader("X-Foo", "bar").Expect()
+ resp.Status(http.StatusOK)
+ assert.Less(ginkgo.GinkgoT(), float64((3 * time.Second).Nanoseconds()), float64(time.Since(now).Nanoseconds()))
+ })
+
+ ginkgo.It("disable plugin", func() {
+ backendSvc, backendPorts := s.DefaultHTTPBackend()
+
+ ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2alpha1
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+ match:
+ hosts:
+ - httpbin.org
+ paths:
+ - /ip
+ backends:
+ - serviceName: %s
+ servicePort: %d
+ weight: 10
+ plugins:
+ - name: fault-injection
+ enable: false
+ config:
+ abort:
+ http_status: 500
+ body: "internal server error"
+ vars:
+ - [ ["http_x_foo", "==", "bar"], ["arg_name", "==", "bob"] ]
+`, backendSvc, backendPorts[0])
+
+ assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ar))
+
+ err := s.EnsureNumApisixUpstreamsCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams")
+ err = s.EnsureNumApisixRoutesCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes")
+
+ // vars unsatisfied
+ resp := s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.org").Expect()
+ resp.Status(http.StatusOK)
+
+ resp = s.NewAPISIXClient().GET("/ip").WithQuery("name", "bob").WithHeader("Host", "httpbin.org").WithHeader("X-Foo", "bar").Expect()
+ resp.Status(http.StatusOK)
+ })
+})
diff --git a/test/e2e/plugins/redirect.go b/test/e2e/plugins/redirect.go
new file mode 100644
index 0000000..cb094d0
--- /dev/null
+++ b/test/e2e/plugins/redirect.go
@@ -0,0 +1,151 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You 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 plugins
+
+import (
+ "fmt"
+ "net/http"
+
+ "github.com/onsi/ginkgo"
+ "github.com/stretchr/testify/assert"
+
+ "github.com/apache/apisix-ingress-controller/test/e2e/scaffold"
+)
+
+var _ = ginkgo.Describe("redirect plugin", func() {
+ opts := &scaffold.Options{
+ Name: "default",
+ Kubeconfig: scaffold.GetKubeconfig(),
+ APISIXConfigPath: "testdata/apisix-gw-config.yaml",
+ APISIXDefaultConfigPath: "testdata/apisix-gw-config-default.yaml",
+ IngressAPISIXReplicas: 1,
+ HTTPBinServicePort: 80,
+ APISIXRouteVersion: "apisix.apache.org/v2alpha1",
+ }
+ s := scaffold.NewScaffold(opts)
+ ginkgo.It("http_to_https", func() {
+ backendSvc, backendPorts := s.DefaultHTTPBackend()
+ ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2alpha1
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+ match:
+ hosts:
+ - httpbin.org
+ paths:
+ - /ip
+ backends:
+ - serviceName: %s
+ servicePort: %d
+ weight: 10
+ plugins:
+ - name: redirect
+ enable: true
+ config:
+ http_to_https: true
+`, backendSvc, backendPorts[0])
+
+ assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ar))
+
+ err := s.EnsureNumApisixUpstreamsCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams")
+ err = s.EnsureNumApisixRoutesCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes")
+
+ resp := s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.org").Expect()
+ resp.Status(http.StatusMovedPermanently)
+ resp.Header("Location").Equal("https://httpbin.org/ip")
+ })
+ ginkgo.It("redirect to specific uri", func() {
+ backendSvc, backendPorts := s.DefaultHTTPBackend()
+ ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2alpha1
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+ match:
+ hosts:
+ - httpbin.org
+ paths:
+ - /ip
+ backends:
+ - serviceName: %s
+ servicePort: %d
+ weight: 10
+ plugins:
+ - name: redirect
+ enable: true
+ config:
+ uri: "$uri/ipip"
+ ret_code: 308
+`, backendSvc, backendPorts[0])
+
+ assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ar))
+
+ err := s.EnsureNumApisixUpstreamsCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams")
+ err = s.EnsureNumApisixRoutesCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes")
+
+ resp := s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.org").Expect()
+ resp.Status(http.StatusPermanentRedirect)
+ resp.Header("Location").Equal("/ip/ipip")
+ })
+ ginkgo.It("disable plugin", func() {
+ backendSvc, backendPorts := s.DefaultHTTPBackend()
+ ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2alpha1
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+ match:
+ hosts:
+ - httpbin.org
+ paths:
+ - /ip
+ backends:
+ - serviceName: %s
+ servicePort: %d
+ weight: 10
+ plugins:
+ - name: redirect
+ enable: false
+ config:
+ http_to_https: true
+ uri: "$uri/ipip"
+ ret_code: 308
+`, backendSvc, backendPorts[0])
+
+ assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ar))
+
+ err := s.EnsureNumApisixUpstreamsCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams")
+ err = s.EnsureNumApisixRoutesCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes")
+
+ resp := s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.org").Expect()
+ resp.Status(http.StatusOK)
+ })
+})
diff --git a/test/e2e/plugins/uri_blocker.go b/test/e2e/plugins/uri_blocker.go
new file mode 100644
index 0000000..8f1c8f9
--- /dev/null
+++ b/test/e2e/plugins/uri_blocker.go
@@ -0,0 +1,150 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You 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 plugins
+
+import (
+ "fmt"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/apache/apisix-ingress-controller/test/e2e/scaffold"
+ "github.com/onsi/ginkgo"
+)
+
+var _ = ginkgo.Describe("uri-blocker plugin", func() {
+ opts := &scaffold.Options{
+ Name: "default",
+ Kubeconfig: scaffold.GetKubeconfig(),
+ APISIXConfigPath: "testdata/apisix-gw-config.yaml",
+ APISIXDefaultConfigPath: "testdata/apisix-gw-config-default.yaml",
+ IngressAPISIXReplicas: 1,
+ HTTPBinServicePort: 80,
+ APISIXRouteVersion: "apisix.apache.org/v2alpha1",
+ }
+ s := scaffold.NewScaffold(opts)
+ ginkgo.It("sanity", func() {
+ backendSvc, backendPorts := s.DefaultHTTPBackend()
+ ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2alpha1
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+ match:
+ hosts:
+ - httpbin.org
+ paths:
+ - /ip
+ - /status/200
+ - /headers
+ backends:
+ - serviceName: %s
+ servicePort: %d
+ weight: 10
+ plugins:
+ - name: uri-blocker
+ enable: true
+ config:
+ rejected_code: 403
+ block_rules:
+ - /status/200
+ - /headers
+`, backendSvc, backendPorts[0])
+
+ assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ar))
+
+ err := s.EnsureNumApisixUpstreamsCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams")
+ err = s.EnsureNumApisixRoutesCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes")
+
+ s.NewAPISIXClient().GET("/status/200").WithHeader("Host", "httpbin.org").
+ Expect().
+ Status(403)
+ s.NewAPISIXClient().GET("/headers").WithHeader("Host", "httpbin.org").
+ Expect().
+ Status(403)
+ s.NewAPISIXClient().GET("/status/206").WithHeader("Host", "httpbin.org").
+ Expect().
+ Status(404).
+ Body().
+ Contains("404 Route Not Found")
+ s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.org").
+ Expect().
+ Status(200).
+ Body().
+ Contains("origin")
+ })
+
+ ginkgo.It("disable plugin", func() {
+ backendSvc, backendPorts := s.DefaultHTTPBackend()
+ ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2alpha1
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+ match:
+ hosts:
+ - httpbin.org
+ paths:
+ - /ip
+ - /status/200
+ - /headers
+ backends:
+ - serviceName: %s
+ servicePort: %d
+ weight: 10
+ plugins:
+ - name: uri-blocker
+ enable: false
+ config:
+ rejected_code: 403
+ block_rules:
+ - /status/200
+ - /headers
+`, backendSvc, backendPorts[0])
+
+ assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ar))
+
+ err := s.EnsureNumApisixUpstreamsCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams")
+ err = s.EnsureNumApisixRoutesCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes")
+
+ s.NewAPISIXClient().GET("/status/200").WithHeader("Host", "httpbin.org").
+ Expect().
+ Status(200)
+ s.NewAPISIXClient().GET("/headers").WithHeader("Host", "httpbin.org").
+ Expect().
+ Status(200).
+ Body().
+ Contains("httpbin.org")
+ s.NewAPISIXClient().GET("/status/206").WithHeader("Host", "httpbin.org").
+ Expect().
+ Status(404).
+ Body().
+ Contains("404 Route Not Found")
+ s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.org").
+ Expect().
+ Status(200).
+ Body().
+ Contains("origin")
+ })
+})
diff --git a/test/e2e/scaffold/scaffold.go b/test/e2e/scaffold/scaffold.go
index ed2979a..7a9da7e 100644
--- a/test/e2e/scaffold/scaffold.go
+++ b/test/e2e/scaffold/scaffold.go
@@ -154,6 +154,9 @@ func (s *Scaffold) NewAPISIXClient() *httpexpect.Expect {
BaseURL: u.String(),
Client: &http.Client{
Transport: &http.Transport{},
+ CheckRedirect: func(req *http.Request, via []*http.Request) error {
+ return http.ErrUseLastResponse
+ },
},
Reporter: httpexpect.NewAssertReporter(
httpexpect.NewAssertReporter(ginkgo.GinkgoT()),