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 632d5c12 feat: support HTTPRequestMirrorFilter in HTTPRoute (#1461)
632d5c12 is described below

commit 632d5c1291bc0775d6280a58536ca9902676541f
Author: Xin Rong <[email protected]>
AuthorDate: Thu Nov 17 21:12:46 2022 +0800

    feat: support HTTPRequestMirrorFilter in HTTPRoute (#1461)
---
 .../gateway/translation/gateway_httproute.go       | 32 +++++++-
 pkg/types/apisix/v1/plugin_types.go                |  6 ++
 pkg/types/apisix/v1/zz_generated.deepcopy.go       | 16 ++++
 test/e2e/suite-gateway/gateway_httproute.go        | 93 +++++++++++++++++++---
 4 files changed, 135 insertions(+), 12 deletions(-)

diff --git a/pkg/providers/gateway/translation/gateway_httproute.go 
b/pkg/providers/gateway/translation/gateway_httproute.go
index 4b2d0eb2..cc2dd42a 100644
--- a/pkg/providers/gateway/translation/gateway_httproute.go
+++ b/pkg/providers/gateway/translation/gateway_httproute.go
@@ -32,7 +32,7 @@ import (
        apisixv1 
"github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
 )
 
-func (t *translator) generatePluginsFromHTTPRouteFilter(filters 
[]gatewayv1beta1.HTTPRouteFilter) apisixv1.Plugins {
+func (t *translator) generatePluginsFromHTTPRouteFilter(namespace string, 
filters []gatewayv1beta1.HTTPRouteFilter) apisixv1.Plugins {
        plugins := apisixv1.Plugins{}
        for _, filter := range filters {
                switch filter.Type {
@@ -41,7 +41,9 @@ func (t *translator) 
generatePluginsFromHTTPRouteFilter(filters []gatewayv1beta1
                case gatewayv1beta1.HTTPRouteFilterRequestRedirect:
                        t.generatePluginFromHTTPRequestRedirectFilter(plugins, 
filter.RequestRedirect)
                case gatewayv1beta1.HTTPRouteFilterRequestMirror:
-                       // to do
+                       t.generatePluginFromHTTPRequestMirrorFilter(namespace, 
plugins, filter.RequestMirror)
+               case gatewayv1beta1.HTTPRouteFilterURLRewrite:
+                       // TODO: It is not yet supported by v1beta1 CRDs.
                }
        }
        return plugins
@@ -68,6 +70,30 @@ func (t *translator) 
generatePluginFromHTTPRequestHeaderFilter(plugins apisixv1.
        }
 }
 
+func (t *translator) generatePluginFromHTTPRequestMirrorFilter(namespace 
string, plugins apisixv1.Plugins, reqMirror 
*gatewayv1beta1.HTTPRequestMirrorFilter) {
+       if reqMirror == nil {
+               return
+       }
+
+       var (
+               port int    = 80
+               ns   string = namespace
+       )
+       if reqMirror.BackendRef.Port != nil {
+               port = int(*reqMirror.BackendRef.Port)
+       }
+       if reqMirror.BackendRef.Namespace != nil {
+               ns = string(*reqMirror.BackendRef.Namespace)
+       }
+       // TODO 1: Need to support https.
+       // TODO 2: https://github.com/apache/apisix/issues/8351 APISIX 3.0 
support {service.namespace} and {service.namespace.svc}, but APISIX <= 2.15 
version is not supported.
+       host := fmt.Sprintf("http://%s.%s.svc.cluster.local:%d";, 
reqMirror.BackendRef.Name, ns, port)
+
+       plugins["proxy-mirror"] = apisixv1.RequestMirror{
+               Host: host,
+       }
+}
+
 func (t *translator) generatePluginFromHTTPRequestRedirectFilter(plugins 
apisixv1.Plugins, reqRedirect *gatewayv1beta1.HTTPRequestRedirectFilter) {
        if reqRedirect == nil {
                return
@@ -210,7 +236,7 @@ func (t *translator) 
TranslateGatewayHTTPRouteV1beta1(httpRoute *gatewayv1beta1.
                                },
                        }
                }
-               plugins := t.generatePluginsFromHTTPRouteFilter(rule.Filters)
+               plugins := 
t.generatePluginsFromHTTPRouteFilter(httpRoute.Namespace, rule.Filters)
 
                for j, match := range matches {
                        route, err := t.translateGatewayHTTPRouteMatch(&match)
diff --git a/pkg/types/apisix/v1/plugin_types.go 
b/pkg/types/apisix/v1/plugin_types.go
index 8958d285..37e74b0b 100644
--- a/pkg/types/apisix/v1/plugin_types.go
+++ b/pkg/types/apisix/v1/plugin_types.go
@@ -156,6 +156,12 @@ type BasicAuthConfig struct {
 type KeyAuthConfig struct {
 }
 
+// RequestMirror is the rule config for proxy-mirror plugin.
+// +k8s:deepcopy-gen=true
+type RequestMirror struct {
+       Host string `json:"host"`
+}
+
 type Headers map[string]any
 
 func (p *Headers) DeepCopyInto(out *Headers) {
diff --git a/pkg/types/apisix/v1/zz_generated.deepcopy.go 
b/pkg/types/apisix/v1/zz_generated.deepcopy.go
index 205436eb..f09f3097 100644
--- a/pkg/types/apisix/v1/zz_generated.deepcopy.go
+++ b/pkg/types/apisix/v1/zz_generated.deepcopy.go
@@ -340,6 +340,22 @@ func (in *RedirectConfig) DeepCopy() *RedirectConfig {
        return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *RequestMirror) DeepCopyInto(out *RequestMirror) {
+       *out = *in
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new RequestMirror.
+func (in *RequestMirror) DeepCopy() *RequestMirror {
+       if in == nil {
+               return nil
+       }
+       out := new(RequestMirror)
+       in.DeepCopyInto(out)
+       return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
 func (in *RewriteConfig) DeepCopyInto(out *RewriteConfig) {
        *out = *in
diff --git a/test/e2e/suite-gateway/gateway_httproute.go 
b/test/e2e/suite-gateway/gateway_httproute.go
index bc809407..29d27399 100644
--- a/test/e2e/suite-gateway/gateway_httproute.go
+++ b/test/e2e/suite-gateway/gateway_httproute.go
@@ -34,7 +34,7 @@ var _ = ginkgo.Describe("suite-gateway: HTTPRoute", func() {
                backendSvc, backendPorts := s.DefaultHTTPBackend()
                time.Sleep(time.Second * 15)
                route := fmt.Sprintf(`
-apiVersion: gateway.networking.k8s.io/v1alpha2
+apiVersion: gateway.networking.k8s.io/v1beta1
 kind: HTTPRoute
 metadata:
   name: basic-http-route
@@ -69,7 +69,7 @@ spec:
                backendSvc, backendPorts := s.DefaultHTTPBackend()
                time.Sleep(time.Second * 15)
                route := fmt.Sprintf(`
-apiVersion: gateway.networking.k8s.io/v1alpha2
+apiVersion: gateway.networking.k8s.io/v1beta1
 kind: HTTPRoute
 metadata:
   name: basic-http-route
@@ -107,7 +107,7 @@ spec:
        ginkgo.It("Basic HTTPRoute with 1 Hosts 1 Rule 2 Match 1 BackendRef", 
func() {
                backendSvc, backendPorts := s.DefaultHTTPBackend()
                route := fmt.Sprintf(`
-apiVersion: gateway.networking.k8s.io/v1alpha2
+apiVersion: gateway.networking.k8s.io/v1beta1
 kind: HTTPRoute
 metadata:
   name: basic-http-route
@@ -148,7 +148,7 @@ spec:
        ginkgo.It("Update HTTPRoute", func() {
                backendSvc, backendPorts := s.DefaultHTTPBackend()
                route := fmt.Sprintf(`
-apiVersion: gateway.networking.k8s.io/v1alpha2
+apiVersion: gateway.networking.k8s.io/v1beta1
 kind: HTTPRoute
 metadata:
   name: basic-http-route
@@ -169,7 +169,7 @@ spec:
                assert.Nil(ginkgo.GinkgoT(), 
s.EnsureNumApisixUpstreamsCreated(1), "Checking number of upstreams")
 
                route = fmt.Sprintf(`
-apiVersion: gateway.networking.k8s.io/v1alpha2
+apiVersion: gateway.networking.k8s.io/v1beta1
 kind: HTTPRoute
 metadata:
   name: basic-http-route
@@ -202,7 +202,7 @@ spec:
        ginkgo.It("Delete HTTPRoute", func() {
                backendSvc, backendPorts := s.DefaultHTTPBackend()
                route := fmt.Sprintf(`
-apiVersion: gateway.networking.k8s.io/v1alpha2
+apiVersion: gateway.networking.k8s.io/v1beta1
 kind: HTTPRoute
 metadata:
   name: basic-http-route
@@ -243,7 +243,7 @@ var _ = ginkgo.Describe("suite-gateway: HTTPRoute with 
filter", func() {
                backendSvc, backendPorts := s.DefaultHTTPBackend()
                time.Sleep(time.Second * 15)
                httproute := fmt.Sprintf(`
-apiVersion: gateway.networking.k8s.io/v1alpha2
+apiVersion: gateway.networking.k8s.io/v1beta1
 kind: HTTPRoute
 metadata:
   name: http-route
@@ -295,7 +295,7 @@ spec:
                backendSvc, backendPorts := s.DefaultHTTPBackend()
 
                httproute := fmt.Sprintf(`
-apiVersion: gateway.networking.k8s.io/v1alpha2
+apiVersion: gateway.networking.k8s.io/v1beta1
 kind: HTTPRoute
 metadata:
   name: http-route
@@ -327,7 +327,7 @@ spec:
                        
Header("Location").Equal("https://httpbin.org:9443/headers";)
 
                httproute2 := fmt.Sprintf(`
-apiVersion: gateway.networking.k8s.io/v1alpha2
+apiVersion: gateway.networking.k8s.io/v1beta1
 kind: HTTPRoute
 metadata:
   name: http-route2
@@ -358,4 +358,79 @@ spec:
                        Status(http.StatusMovedPermanently).
                        Header("Location").Equal("http://httpbin.org/ip";)
        })
+
+       ginkgo.It("HTTPRoute with RequestMirror", func() {
+               backendSvc, backendPorts := s.DefaultHTTPBackend()
+
+               echo := `
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: echo
+spec:
+  selector:
+    matchLabels:
+      app: echo
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: echo
+    spec:
+      containers:
+      - name: echo
+        image: localhost:5000/jmalloc/echo-server:dev
+        ports:
+        - containerPort: 8080
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: echo-service
+spec:
+  selector:
+    app: echo
+  ports:
+  - name: http
+    port: 80
+    protocol: TCP
+    targetPort: 8080
+`
+               assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(echo), 
"creating echo server")
+
+               httproute := fmt.Sprintf(`
+apiVersion: gateway.networking.k8s.io/v1beta1
+kind: HTTPRoute
+metadata:
+  name: http-route
+spec:
+  hostnames: ["httpbin.org"]
+  rules:
+  - matches:
+    - path:
+        type: PathPrefix
+        value: /headers
+    filters:
+    - type: RequestMirror
+      requestMirror:
+        backendRef:
+          name: echo-service
+          port: 80
+    backendRefs:
+    - name: %s
+      port: %d
+`, backendSvc, backendPorts[0])
+
+               assert.Nil(ginkgo.GinkgoT(), 
s.CreateResourceFromString(httproute), "creating HTTPRoute")
+               time.Sleep(time.Second * 6)
+               assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixRoutesCreated(1), 
"Checking number of routes")
+
+               _ = s.NewAPISIXClient().GET("/headers").
+                       WithHeader("Host", "httpbin.org").
+                       Expect().
+                       Status(http.StatusOK)
+
+               echoLogs := s.GetDeploymentLogs("echo")
+               assert.Contains(ginkgo.GinkgoT(), echoLogs, "GET /headers")
+       })
 })

Reply via email to