You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by zh...@apache.org on 2022/11/19 09:48:46 UTC
[apisix-ingress-controller] branch master updated: feat: support variable in ApisixRoute exprs scope (#1466)
This is an automated email from the ASF dual-hosted git repository.
zhangjintao 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 e6eb3bf2 feat: support variable in ApisixRoute exprs scope (#1466)
e6eb3bf2 is described below
commit e6eb3bf2aed4c39e91271e4f74b61ff6fe97ad16
Author: Xin Rong <al...@gmail.com>
AuthorDate: Sat Nov 19 17:48:41 2022 +0800
feat: support variable in ApisixRoute exprs scope (#1466)
Co-authored-by: Jintao Zhang <zh...@gmail.com>
---
pkg/kube/apisix/const/const.go | 2 +
pkg/providers/apisix/translation/apisix_route.go | 16 +-
samples/deploy/crd/v1/ApisixRoute.yaml | 3 +
test/e2e/scaffold/scaffold.go | 4 +
test/e2e/suite-features/route_match_exprs.go | 299 +++++++++++++++++++++++
5 files changed, 314 insertions(+), 10 deletions(-)
diff --git a/pkg/kube/apisix/const/const.go b/pkg/kube/apisix/const/const.go
index f972267b..19666c40 100644
--- a/pkg/kube/apisix/const/const.go
+++ b/pkg/kube/apisix/const/const.go
@@ -49,4 +49,6 @@ const (
ScopePath = "Path"
// ScopeCookie means the route match expression subject is in cookie.
ScopeCookie = "Cookie"
+ // ScopeVariable means the route match expression subject is in variable.
+ ScopeVariable = "Variable"
)
diff --git a/pkg/providers/apisix/translation/apisix_route.go b/pkg/providers/apisix/translation/apisix_route.go
index 2fd8681a..f49fab4d 100644
--- a/pkg/providers/apisix/translation/apisix_route.go
+++ b/pkg/providers/apisix/translation/apisix_route.go
@@ -489,6 +489,8 @@ func (t *translator) TranslateRouteMatchExprs(nginxVars []configv2.ApisixRouteHT
subj = "cookie_" + expr.Subject.Name
case _const.ScopePath:
subj = "uri"
+ case _const.ScopeVariable:
+ subj = expr.Subject.Name
default:
return nil, errors.New("bad subject name")
}
@@ -504,20 +506,14 @@ func (t *translator) TranslateRouteMatchExprs(nginxVars []configv2.ApisixRouteHT
op = "=="
case _const.OpGreaterThan:
op = ">"
- // TODO Implement "<=", ">=" operators after the
- // lua-resty-expr supports it. See
- // https://github.com/api7/lua-resty-expr/issues/28
- // for details.
- //case configv2alpha1.OpGreaterThanEqual:
- // invert = true
- // op = "<"
+ case _const.OpGreaterThanEqual:
+ op = ">="
case _const.OpIn:
op = "in"
case _const.OpLessThan:
op = "<"
- //case configv2alpha1.OpLessThanEqual:
- // invert = true
- // op = ">"
+ case _const.OpLessThanEqual:
+ op = "<="
case _const.OpNotEqual:
op = "~="
case _const.OpNotIn:
diff --git a/samples/deploy/crd/v1/ApisixRoute.yaml b/samples/deploy/crd/v1/ApisixRoute.yaml
index 8ca97dc9..89dac1de 100644
--- a/samples/deploy/crd/v1/ApisixRoute.yaml
+++ b/samples/deploy/crd/v1/ApisixRoute.yaml
@@ -420,6 +420,7 @@ spec:
- "Header"
- "Path"
- "Query"
+ - "Variable"
name:
type: string
minLength: 1
@@ -431,7 +432,9 @@ spec:
- Equal
- NotEqual
- GreaterThan
+ - GreaterThanEqual
- LessThan
+ - LessThanEqual
- In
- NotIn
- RegexMatch
diff --git a/test/e2e/scaffold/scaffold.go b/test/e2e/scaffold/scaffold.go
index c3c83262..1db6e8e2 100644
--- a/test/e2e/scaffold/scaffold.go
+++ b/test/e2e/scaffold/scaffold.go
@@ -653,6 +653,10 @@ func (s *Scaffold) CreateVersionedApisixResourceWithNamespace(yml, namespace str
return fmt.Errorf("the resource %s does not support", kindValue)
}
+func (s *Scaffold) ApisixResourceVersion() string {
+ return s.opts.ApisixResourceVersion
+}
+
func ApisixResourceVersion() *apisixResourceVersionInfo {
return apisixResourceVersion
}
diff --git a/test/e2e/suite-features/route_match_exprs.go b/test/e2e/suite-features/route_match_exprs.go
index c04003b7..da59e60d 100644
--- a/test/e2e/suite-features/route_match_exprs.go
+++ b/test/e2e/suite-features/route_match_exprs.go
@@ -187,6 +187,75 @@ spec:
assert.Contains(ginkgo.GinkgoT(), msg, "404 Route Not Found")
})
+ ginkgo.It("operator is GreaterThanEqual", func() {
+ if s.ApisixResourceVersion() == scaffold.ApisixResourceVersion().V2beta3 {
+ ginkgo.Skip("Not support ApisixRoute v2beta3")
+ }
+
+ backendSvc, backendPorts := s.DefaultHTTPBackend()
+
+ ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+ match:
+ hosts:
+ - httpbin.org
+ paths:
+ - /ip
+ exprs:
+ - subject:
+ scope: Query
+ name: id
+ op: GreaterThanEqual
+ value: "13"
+ backends:
+ - serviceName: %s
+ servicePort: %d
+`, backendSvc, backendPorts[0])
+
+ assert.Nil(ginkgo.GinkgoT(), s.CreateVersionedApisixResource(ar))
+
+ time.Sleep(6 * time.Second)
+ err := s.EnsureNumApisixRoutesCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes")
+ err = s.EnsureNumApisixUpstreamsCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams")
+
+ _ = s.NewAPISIXClient().GET("/ip").
+ WithHeader("Host", "httpbin.org").
+ WithQuery("id", 100).
+ Expect().
+ Status(http.StatusOK)
+
+ _ = s.NewAPISIXClient().GET("/ip").
+ WithHeader("Host", "httpbin.org").
+ WithQuery("id", 13).
+ Expect().
+ Status(http.StatusOK)
+
+ msg := s.NewAPISIXClient().GET("/ip").
+ WithHeader("Host", "httpbin.org").
+ WithQuery("id", 10).
+ Expect().
+ Status(http.StatusNotFound).
+ Body().
+ Raw()
+ assert.Contains(ginkgo.GinkgoT(), msg, "404 Route Not Found")
+
+ msg = s.NewAPISIXClient().GET("/ip").
+ WithHeader("Host", "httpbin.org").
+ Expect().
+ Status(http.StatusNotFound).
+ Body().
+ Raw()
+ assert.Contains(ginkgo.GinkgoT(), msg, "404 Route Not Found")
+ })
+
ginkgo.It("operator is less_than", func() {
backendSvc, backendPorts := s.DefaultHTTPBackend()
@@ -246,6 +315,75 @@ spec:
assert.Contains(ginkgo.GinkgoT(), msg, "404 Route Not Found")
})
+ ginkgo.It("operator is LessThanEqual", func() {
+ if s.ApisixResourceVersion() == scaffold.ApisixResourceVersion().V2beta3 {
+ ginkgo.Skip("Not support ApisixRoute v2beta3")
+ }
+
+ backendSvc, backendPorts := s.DefaultHTTPBackend()
+
+ ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+ match:
+ hosts:
+ - httpbin.org
+ paths:
+ - /ip
+ exprs:
+ - subject:
+ scope: Query
+ name: ID
+ op: LessThanEqual
+ value: "13"
+ backends:
+ - serviceName: %s
+ servicePort: %d
+`, backendSvc, backendPorts[0])
+
+ assert.Nil(ginkgo.GinkgoT(), s.CreateVersionedApisixResource(ar))
+
+ time.Sleep(6 * time.Second)
+ err := s.EnsureNumApisixRoutesCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes")
+ err = s.EnsureNumApisixUpstreamsCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams")
+
+ _ = s.NewAPISIXClient().GET("/ip").
+ WithHeader("Host", "httpbin.org").
+ WithQuery("ID", 12).
+ Expect().
+ Status(http.StatusOK)
+
+ _ = s.NewAPISIXClient().GET("/ip").
+ WithHeader("Host", "httpbin.org").
+ WithQuery("ID", 13).
+ Expect().
+ Status(http.StatusOK)
+
+ msg := s.NewAPISIXClient().GET("/ip").
+ WithHeader("Host", "httpbin.org").
+ WithQuery("ID", 14).
+ Expect().
+ Status(http.StatusNotFound).
+ Body().
+ Raw()
+ assert.Contains(ginkgo.GinkgoT(), msg, "404 Route Not Found")
+
+ msg = s.NewAPISIXClient().GET("/ip").
+ WithHeader("Host", "httpbin.org").
+ Expect().
+ Status(http.StatusNotFound).
+ Body().
+ Raw()
+ assert.Contains(ginkgo.GinkgoT(), msg, "404 Route Not Found")
+ })
+
ginkgo.It("operator is in", func() {
backendSvc, backendPorts := s.DefaultHTTPBackend()
@@ -683,3 +821,164 @@ spec:
suites(scaffold.NewDefaultV2Scaffold)
})
})
+
+var _ = ginkgo.Describe("suite-features: route match exprs with variable", func() {
+ s := scaffold.NewDefaultScaffold()
+ ginkgo.It("exprs with request_method variable", func() {
+ backendSvc, backendPorts := s.DefaultHTTPBackend()
+
+ ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+ match:
+ hosts:
+ - httpbin.org
+ paths:
+ - /get
+ - /post
+ - /put
+ exprs:
+ - subject:
+ scope: Variable
+ name: request_method
+ op: In
+ set:
+ - GET
+ - POST
+ backends:
+ - serviceName: %s
+ servicePort: %d
+`, backendSvc, backendPorts[0])
+
+ assert.Nil(ginkgo.GinkgoT(), s.CreateVersionedApisixResource(ar), "creating route")
+ time.Sleep(6 * time.Second)
+ assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixRoutesCreated(1), "Checking number of routes")
+
+ _ = s.NewAPISIXClient().GET("/get").
+ WithHeader("Host", "httpbin.org").
+ Expect().
+ Status(http.StatusOK)
+
+ _ = s.NewAPISIXClient().POST("/post").
+ WithHeader("Host", "httpbin.org").
+ Expect().
+ Status(http.StatusOK)
+
+ _ = s.NewAPISIXClient().PUT("/put").
+ WithHeader("Host", "httpbin.org").
+ Expect().
+ Status(http.StatusNotFound)
+ })
+
+ ginkgo.It("exprs with host variable", func() {
+ backendSvc, backendPorts := s.DefaultHTTPBackend()
+
+ ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+ match:
+ paths:
+ - /ip
+ exprs:
+ - subject:
+ scope: Variable
+ name: host
+ op: In
+ set:
+ - httpbin.net
+ - httpbin.org
+ - httpbin.com
+ backends:
+ - serviceName: %s
+ servicePort: %d
+`, backendSvc, backendPorts[0])
+
+ assert.Nil(ginkgo.GinkgoT(), s.CreateVersionedApisixResource(ar), "creating route")
+ time.Sleep(6 * time.Second)
+ assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixRoutesCreated(1), "Checking number of routes")
+
+ _ = s.NewAPISIXClient().GET("/ip").
+ WithHeader("Host", "httpbin.net").
+ Expect().
+ Status(http.StatusOK)
+
+ _ = s.NewAPISIXClient().GET("/ip").
+ WithHeader("Host", "httpbin.org").
+ Expect().
+ Status(http.StatusOK)
+
+ _ = s.NewAPISIXClient().GET("/ip").
+ WithHeader("Host", "httpbin.com").
+ Expect().
+ Status(http.StatusOK)
+ })
+
+ ginkgo.It("exprs request_method and host variable", func() {
+ backendSvc, backendPorts := s.DefaultHTTPBackend()
+
+ ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+ match:
+ paths:
+ - /*
+ exprs:
+ - subject:
+ scope: Variable
+ name: request_method
+ op: In
+ set:
+ - GET
+ - PUT
+ - subject:
+ scope: Variable
+ name: host
+ op: In
+ set:
+ - httpbin.org
+ - httpbin.com
+ backends:
+ - serviceName: %s
+ servicePort: %d
+`, backendSvc, backendPorts[0])
+
+ assert.Nil(ginkgo.GinkgoT(), s.CreateVersionedApisixResource(ar), "creating route")
+ time.Sleep(6 * time.Second)
+ assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixRoutesCreated(1), "Checking number of routes")
+
+ _ = s.NewAPISIXClient().GET("/get").
+ WithHeader("Host", "httpbin.net").
+ Expect().
+ Status(http.StatusNotFound)
+
+ _ = s.NewAPISIXClient().GET("/get").
+ WithHeader("Host", "httpbin.org").
+ Expect().
+ Status(http.StatusOK)
+
+ _ = s.NewAPISIXClient().POST("/post").
+ WithHeader("Host", "httpbin.org").
+ Expect().
+ Status(http.StatusNotFound)
+
+ _ = s.NewAPISIXClient().PUT("/put").
+ WithHeader("Host", "httpbin.com").
+ Expect().
+ Status(http.StatusOK)
+ })
+})