Skip to content

Commit a7784c5

Browse files
authored
e2e & misc fixes for EnvoyPatchPolicy (envoyproxy#1738)
* Add E2E for EnvoyPatchPolicy * Use LocalReplyConfig to return a custom status code `406` when there is no valid route match Signed-off-by: Arko Dasgupta <arko@tetrate.io>
1 parent b4d4e2f commit a7784c5

8 files changed

Lines changed: 140 additions & 24 deletions

File tree

api/v1alpha1/envoypatchpolicy_types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ type EnvoyPatchPolicySpec struct {
5959
// the priority i.e. int32.min has the highest priority and
6060
// int32.max has the lowest priority.
6161
// Defaults to 0.
62-
Priority int32 `json:"priority"`
62+
Priority int32 `json:"priority,omitempty"`
6363
}
6464

6565
// EnvoyPatchType specifies the types of Envoy patching mechanisms.

charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoypatchpolicies.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@ spec:
142142
- JSONPatch
143143
type: string
144144
required:
145-
- priority
146145
- targetRef
147146
- type
148147
type: object

docs/latest/user/envoy-patch-policy.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -86,19 +86,19 @@ spec:
8686
name: default/eg/http
8787
operation:
8888
op: add
89-
path: "/default_filter_chain/filters/0/typed_config"
89+
path: "/default_filter_chain/filters/0/typed_config/local_reply_config"
9090
value:
91-
local_reply_config:
92-
mappers:
93-
- filter:
94-
status_code_filter:
95-
comparison:
96-
op: EQ
97-
value:
98-
default_value: 404
99-
runtime_key: key_b
100-
body:
101-
inline_string: "could not find what you are looking for"
91+
mappers:
92+
- filter:
93+
status_code_filter:
94+
comparison:
95+
op: EQ
96+
value:
97+
default_value: 404
98+
runtime_key: key_b
99+
status_code: 406
100+
body:
101+
inline_string: "could not find what you are looking for"
102102
EOF
103103
```
104104

examples/redis/redis.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ data:
6262
type: Kubernetes
6363
gateway:
6464
controllerName: gateway.envoyproxy.io/gatewayclass-controller
65+
extensionApis:
66+
enableEnvoyPatchPolicy: true
6567
rateLimit:
6668
backend:
6769
type: Redis

internal/provider/kubernetes/controller.go

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -240,16 +240,19 @@ func (r *gatewayAPIReconciler) Reconcile(ctx context.Context, request reconcile.
240240
}
241241

242242
// Add all EnvoyPatchPolicies
243-
envoyPatchPolicies := egv1a1.EnvoyPatchPolicyList{}
244-
if err := r.client.List(ctx, &envoyPatchPolicies); err != nil {
245-
return reconcile.Result{}, fmt.Errorf("error listing envoypatchpolicies: %v", err)
246-
}
247-
for _, policy := range envoyPatchPolicies.Items {
248-
policy := policy
249-
// Discard Status to reduce memory consumption in watchable
250-
// It will be recomputed by the gateway-api layer
251-
policy.Status = egv1a1.EnvoyPatchPolicyStatus{}
252-
resourceTree.EnvoyPatchPolicies = append(resourceTree.EnvoyPatchPolicies, &policy)
243+
if r.envoyGateway.ExtensionAPIs != nil && r.envoyGateway.ExtensionAPIs.EnableEnvoyPatchPolicy {
244+
envoyPatchPolicies := egv1a1.EnvoyPatchPolicyList{}
245+
if err := r.client.List(ctx, &envoyPatchPolicies); err != nil {
246+
return reconcile.Result{}, fmt.Errorf("error listing envoypatchpolicies: %v", err)
247+
}
248+
249+
for _, policy := range envoyPatchPolicies.Items {
250+
policy := policy
251+
// Discard Status to reduce memory consumption in watchable
252+
// It will be recomputed by the gateway-api layer
253+
policy.Status = egv1a1.EnvoyPatchPolicyStatus{}
254+
resourceTree.EnvoyPatchPolicies = append(resourceTree.EnvoyPatchPolicies, &policy)
255+
}
253256
}
254257

255258
// For this particular Gateway, and all associated objects, check whether the

internal/status/envoypatchpolicy.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ func SetEnvoyPatchPolicyProgrammedIfUnset(s *egv1a1.EnvoyPatchPolicyStatus, mess
2525
if c.Type == string(egv1a1.PolicyConditionProgrammed) {
2626
return
2727
}
28+
if c.Type == string(gwv1a2.PolicyConditionAccepted) && c.Status == metav1.ConditionFalse {
29+
return
30+
}
2831
}
2932

3033
cond := newCondition(string(egv1a1.PolicyConditionProgrammed), metav1.ConditionTrue, string(egv1a1.PolicyReasonProgrammed), message, time.Now(), 0)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
apiVersion: gateway.networking.k8s.io/v1beta1
3+
kind: HTTPRoute
4+
metadata:
5+
name: http-envoy-patch-policy
6+
namespace: gateway-conformance-infra
7+
spec:
8+
parentRefs:
9+
- name: same-namespace
10+
rules:
11+
- backendRefs:
12+
- name: infra-backend-v1
13+
port: 8080
14+
matches:
15+
- path:
16+
type: PathPrefix
17+
value: /foo
18+
---
19+
apiVersion: gateway.envoyproxy.io/v1alpha1
20+
kind: EnvoyPatchPolicy
21+
metadata:
22+
name: custom-response-patch-policy
23+
namespace: gateway-conformance-infra
24+
spec:
25+
targetRef:
26+
group: gateway.networking.k8s.io
27+
kind: Gateway
28+
name: same-namespace
29+
namespace: gateway-conformance-infra
30+
type: JSONPatch
31+
jsonPatches:
32+
- type: "type.googleapis.com/envoy.config.listener.v3.Listener"
33+
name: "gateway-conformance-infra/same-namespace/http"
34+
operation:
35+
op: add
36+
path: "/default_filter_chain/filters/0/typed_config/local_reply_config"
37+
value:
38+
mappers:
39+
- filter:
40+
status_code_filter:
41+
comparison:
42+
op: EQ
43+
value:
44+
default_value: 404
45+
runtime_key: key_b
46+
status_code: 406
47+
body:
48+
inline_string: "not acceptable"
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright Envoy Gateway Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
// The full text of the Apache license is available in the LICENSE file at
4+
// the root of the repo.
5+
6+
//go:build e2e
7+
// +build e2e
8+
9+
package tests
10+
11+
import (
12+
"testing"
13+
14+
"k8s.io/apimachinery/pkg/types"
15+
"sigs.k8s.io/gateway-api/conformance/utils/http"
16+
"sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
17+
"sigs.k8s.io/gateway-api/conformance/utils/suite"
18+
)
19+
20+
func init() {
21+
ConformanceTests = append(ConformanceTests, EnvoyPatchPolicyTest)
22+
}
23+
24+
var EnvoyPatchPolicyTest = suite.ConformanceTest{
25+
ShortName: "EnvoyPatchPolicy",
26+
Description: "update xds using EnvoyPatchPolicy",
27+
Manifests: []string{"testdata/envoy-patch-policy.yaml"},
28+
Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
29+
t.Run("envoy patch policy", func(t *testing.T) {
30+
ns := "gateway-conformance-infra"
31+
routeNN := types.NamespacedName{Name: "http-envoy-patch-policy", Namespace: ns}
32+
gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns}
33+
gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
34+
OkResp := http.ExpectedResponse{
35+
Request: http.Request{
36+
Path: "/foo",
37+
},
38+
Response: http.Response{
39+
StatusCode: 200,
40+
},
41+
Namespace: ns,
42+
}
43+
44+
// Send a request to an valid path and expect a successful response
45+
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, OkResp)
46+
47+
customResp := http.ExpectedResponse{
48+
Request: http.Request{
49+
Path: "/bar",
50+
},
51+
Response: http.Response{
52+
StatusCode: 406,
53+
},
54+
Namespace: ns,
55+
}
56+
57+
// Send a request to an invalid path and expect a custom response
58+
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, customResp)
59+
})
60+
},
61+
}

0 commit comments

Comments
 (0)