Skip to content

Commit

Permalink
feat: support HTTPRequestMirrorFilter in HTTPRoute (#1461)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlinsRan committed Nov 17, 2022
1 parent 47906a5 commit 632d5c1
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 12 deletions.
32 changes: 29 additions & 3 deletions pkg/providers/gateway/translation/gateway_httproute.go
Expand Up @@ -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 {
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions pkg/types/apisix/v1/plugin_types.go
Expand Up @@ -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) {
Expand Down
16 changes: 16 additions & 0 deletions pkg/types/apisix/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

93 changes: 84 additions & 9 deletions test/e2e/suite-gateway/gateway_httproute.go
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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")
})
})

0 comments on commit 632d5c1

Please sign in to comment.