Skip to content

Commit 8022ef1

Browse files
committed
fix: support patch multiple resources in EPP
Signed-off-by: zirain <zirain2009@gmail.com>
1 parent 8e813bd commit 8022ef1

44 files changed

Lines changed: 1424 additions & 224 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

api/v1alpha1/envoypatchpolicy_types.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,20 @@ const (
7878
)
7979

8080
// EnvoyJSONPatchConfig defines the configuration for patching a Envoy xDS Resource
81-
// using JSONPatch semantic
81+
// using JSONPatch semantics.
82+
//
83+
// +kubebuilder:validation:XValidation:rule="!(has(self.name) && has(self.nameSelector))",message="only one of name and nameSelector can be specified"
8284
type EnvoyJSONPatchConfig struct {
8385
// Type is the typed URL of the Envoy xDS Resource
8486
Type EnvoyResourceType `json:"type"`
85-
// Name is the name of the resource
86-
Name string `json:"name"`
87+
// Name is the name of the resource.
88+
//
89+
// +optional
90+
Name *string `json:"name,omitempty"`
91+
// NameSelector is a StringMatch that is used to select the resources to patch based on their name.
92+
//
93+
// +optional
94+
NameSelector *StringMatch `json:"nameSelector,omitempty"`
8795
// Patch defines the JSON Patch Operation
8896
Operation JSONPatchOperation `json:"operation"`
8997
}

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,33 @@ spec:
6161
items:
6262
description: |-
6363
EnvoyJSONPatchConfig defines the configuration for patching a Envoy xDS Resource
64-
using JSONPatch semantic
64+
using JSONPatch semantics.
6565
properties:
6666
name:
67-
description: Name is the name of the resource
67+
description: Name is the name of the resource.
6868
type: string
69+
nameSelector:
70+
description: NameSelector is a StringMatch that is used to select
71+
the resources to patch based on their name.
72+
properties:
73+
type:
74+
default: Exact
75+
description: Type specifies how to match against a string.
76+
enum:
77+
- Exact
78+
- Prefix
79+
- Suffix
80+
- RegularExpression
81+
type: string
82+
value:
83+
description: Value specifies the string value that the match
84+
must have.
85+
maxLength: 1024
86+
minLength: 1
87+
type: string
88+
required:
89+
- value
90+
type: object
6991
operation:
7092
description: Patch defines the JSON Patch Operation
7193
properties:
@@ -117,10 +139,12 @@ spec:
117139
- type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret
118140
type: string
119141
required:
120-
- name
121142
- operation
122143
- type
123144
type: object
145+
x-kubernetes-validations:
146+
- message: only one of name and nameSelector can be specified
147+
rule: '!(has(self.name) && has(self.nameSelector))'
124148
type: array
125149
priority:
126150
description: |-

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

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,33 @@ spec:
6060
items:
6161
description: |-
6262
EnvoyJSONPatchConfig defines the configuration for patching a Envoy xDS Resource
63-
using JSONPatch semantic
63+
using JSONPatch semantics.
6464
properties:
6565
name:
66-
description: Name is the name of the resource
66+
description: Name is the name of the resource.
6767
type: string
68+
nameSelector:
69+
description: NameSelector is a StringMatch that is used to select
70+
the resources to patch based on their name.
71+
properties:
72+
type:
73+
default: Exact
74+
description: Type specifies how to match against a string.
75+
enum:
76+
- Exact
77+
- Prefix
78+
- Suffix
79+
- RegularExpression
80+
type: string
81+
value:
82+
description: Value specifies the string value that the match
83+
must have.
84+
maxLength: 1024
85+
minLength: 1
86+
type: string
87+
required:
88+
- value
89+
type: object
6890
operation:
6991
description: Patch defines the JSON Patch Operation
7092
properties:
@@ -116,10 +138,12 @@ spec:
116138
- type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret
117139
type: string
118140
required:
119-
- name
120141
- operation
121142
- type
122143
type: object
144+
x-kubernetes-validations:
145+
- message: only one of name and nameSelector can be specified
146+
rule: '!(has(self.name) && has(self.nameSelector))'
123147
type: array
124148
priority:
125149
description: |-

internal/gatewayapi/envoypatchpolicy.go

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ package gatewayapi
77

88
import (
99
"fmt"
10+
"regexp"
1011

1112
"k8s.io/apimachinery/pkg/types"
13+
"k8s.io/utils/ptr"
1214
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
1315

1416
egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
@@ -126,7 +128,31 @@ func (t *Translator) ProcessEnvoyPatchPolicies(envoyPatchPolicies []*egv1a1.Envo
126128
for _, patch := range policy.Spec.JSONPatches {
127129
irPatch := ir.JSONPatchConfig{}
128130
irPatch.Type = string(patch.Type)
129-
irPatch.Name = patch.Name
131+
irPatch.Name = ir.StringMatch{
132+
Exact: patch.Name,
133+
}
134+
if patch.NameSelector != nil {
135+
irPatch.Name = *toIRStringMatch(patch.NameSelector)
136+
}
137+
// Validate that regex is valid if it's a regex match
138+
if r := irPatch.Name.SafeRegex; r != nil {
139+
_, err := regexp.Compile(*r)
140+
if err != nil {
141+
message := fmt.Sprintf("invalid regex in NameSelector: %v", err)
142+
resolveErr = &status.PolicyResolveError{
143+
Reason: egv1a1.PolicyReasonInvalid,
144+
Message: message,
145+
}
146+
status.SetResolveErrorForPolicyAncestor(&policy.Status,
147+
&ancestorRef,
148+
t.GatewayControllerName,
149+
policy.Generation,
150+
resolveErr,
151+
)
152+
153+
continue
154+
}
155+
}
130156
irPatch.Operation.Op = ir.JSONPatchOp(patch.Operation.Op)
131157
irPatch.Operation.Path = patch.Operation.Path
132158
irPatch.Operation.JSONPath = patch.Operation.JSONPath
@@ -140,3 +166,30 @@ func (t *Translator) ProcessEnvoyPatchPolicies(envoyPatchPolicies []*egv1a1.Envo
140166
status.SetAcceptedForPolicyAncestor(&policy.Status, &ancestorRef, t.GatewayControllerName, policy.Generation)
141167
}
142168
}
169+
170+
func toIRStringMatch(sm *egv1a1.StringMatch) *ir.StringMatch {
171+
if sm == nil {
172+
return nil
173+
}
174+
175+
switch ptr.Deref(sm.Type, egv1a1.StringMatchExact) {
176+
case egv1a1.StringMatchExact:
177+
return &ir.StringMatch{
178+
Exact: &sm.Value,
179+
}
180+
case egv1a1.StringMatchPrefix:
181+
return &ir.StringMatch{
182+
Prefix: &sm.Value,
183+
}
184+
case egv1a1.StringMatchSuffix:
185+
return &ir.StringMatch{
186+
Suffix: &sm.Value,
187+
}
188+
case egv1a1.StringMatchRegularExpression:
189+
return &ir.StringMatch{
190+
SafeRegex: &sm.Value,
191+
}
192+
default:
193+
return nil
194+
}
195+
}

internal/gatewayapi/testdata/envoypatchpolicy-invalid-merge-gateways.out.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,10 @@ xdsIR:
139139
- path: /dev/stdout
140140
envoyPatchPolicies:
141141
- jsonPatches:
142-
- name: envoy-gateway-gateway-1-http
142+
- name:
143+
distinct: false
144+
exact: envoy-gateway-gateway-1-http
145+
name: ""
143146
operation:
144147
op: replace
145148
path: /ignore_global_conn_limit

internal/gatewayapi/testdata/envoypatchpolicy-invalid-target-name.in.yaml

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ envoyPatchPolicies:
44
metadata:
55
namespace: envoy-gateway
66
name: gateway-not-exists
7-
generation: 10
87
spec:
98
type: "JSONPatch"
109
targetRef:
@@ -23,7 +22,6 @@ envoyPatchPolicies:
2322
metadata:
2423
namespace: envoy-gateway
2524
name: edit-ignore-global-limit
26-
generation: 10
2725
spec:
2826
type: "JSONPatch"
2927
targetRef:
@@ -39,6 +37,26 @@ envoyPatchPolicies:
3937
op: replace
4038
path: "/ignore_global_conn_limit"
4139
value: "true"
40+
- apiVersion: gateway.envoyproxy.io/v1alpha1
41+
kind: EnvoyPatchPolicy
42+
metadata:
43+
namespace: envoy-gateway
44+
name: invalid-regex
45+
spec:
46+
type: "JSONPatch"
47+
targetRef:
48+
group: gateway.networking.k8s.io
49+
kind: Gateway
50+
name: gateway-not-exists
51+
jsonPatches:
52+
- type: "type.googleapis.com/envoy.config.listener.v3.Listener"
53+
nameSelector:
54+
type: RegularExpression
55+
value: "*.illegal.regex"
56+
operation:
57+
op: replace
58+
path: "/per_connection_buffer_limit_bytes"
59+
value: "1024"
4260
gateways:
4361
- apiVersion: gateway.networking.k8s.io/v1
4462
kind: Gateway

internal/gatewayapi/testdata/envoypatchpolicy-invalid-target-name.out.yaml

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ envoyPatchPolicies:
22
- apiVersion: gateway.envoyproxy.io/v1alpha1
33
kind: EnvoyPatchPolicy
44
metadata:
5-
generation: 10
65
name: gateway-not-exists
76
namespace: envoy-gateway
87
spec:
@@ -23,7 +22,6 @@ envoyPatchPolicies:
2322
- apiVersion: gateway.envoyproxy.io/v1alpha1
2423
kind: EnvoyPatchPolicy
2524
metadata:
26-
generation: 10
2725
name: edit-ignore-global-limit
2826
namespace: envoy-gateway
2927
spec:
@@ -50,11 +48,32 @@ envoyPatchPolicies:
5048
conditions:
5149
- lastTransitionTime: null
5250
message: Policy has been accepted.
53-
observedGeneration: 10
5451
reason: Accepted
5552
status: "True"
5653
type: Accepted
5754
controllerName: gateway.envoyproxy.io/gatewayclass-controller
55+
- apiVersion: gateway.envoyproxy.io/v1alpha1
56+
kind: EnvoyPatchPolicy
57+
metadata:
58+
name: invalid-regex
59+
namespace: envoy-gateway
60+
spec:
61+
jsonPatches:
62+
- nameSelector:
63+
type: RegularExpression
64+
value: '*.illegal.regex'
65+
operation:
66+
op: replace
67+
path: /per_connection_buffer_limit_bytes
68+
value: "1024"
69+
type: type.googleapis.com/envoy.config.listener.v3.Listener
70+
targetRef:
71+
group: gateway.networking.k8s.io
72+
kind: Gateway
73+
name: gateway-not-exists
74+
type: JSONPatch
75+
status:
76+
ancestors: null
5877
gateways:
5978
- apiVersion: gateway.networking.k8s.io/v1
6079
kind: Gateway
@@ -120,9 +139,11 @@ xdsIR:
120139
json:
121140
- path: /dev/stdout
122141
envoyPatchPolicies:
123-
- generation: 10
124-
jsonPatches:
125-
- name: envoy-gateway-gateway-1-http
142+
- jsonPatches:
143+
- name:
144+
distinct: false
145+
exact: envoy-gateway-gateway-1-http
146+
name: ""
126147
operation:
127148
op: replace
128149
path: /ignore_global_conn_limit
@@ -140,7 +161,6 @@ xdsIR:
140161
conditions:
141162
- lastTransitionTime: null
142163
message: Policy has been accepted.
143-
observedGeneration: 10
144164
reason: Accepted
145165
status: "True"
146166
type: Accepted

internal/gatewayapi/testdata/envoypatchpolicy-valid-merge-gateways.out.yaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,10 @@ xdsIR:
137137
- path: /dev/stdout
138138
envoyPatchPolicies:
139139
- jsonPatches:
140-
- name: envoy-gateway-gateway-1-http
140+
- name:
141+
distinct: false
142+
exact: envoy-gateway-gateway-1-http
143+
name: ""
141144
operation:
142145
op: replace
143146
path: /per_connection_buffer_limit_bytes
@@ -159,7 +162,10 @@ xdsIR:
159162
type: Accepted
160163
controllerName: gateway.envoyproxy.io/gatewayclass-controller
161164
- jsonPatches:
162-
- name: envoy-gateway-gateway-1-http
165+
- name:
166+
distinct: false
167+
exact: envoy-gateway-gateway-1-http
168+
name: ""
163169
operation:
164170
op: replace
165171
path: /ignore_global_conn_limit

internal/gatewayapi/testdata/envoypatchpolicy-valid.out.yaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,10 @@ xdsIR:
135135
envoyPatchPolicies:
136136
- generation: 10
137137
jsonPatches:
138-
- name: envoy-gateway-gateway-1-http
138+
- name:
139+
distinct: false
140+
exact: envoy-gateway-gateway-1-http
141+
name: ""
139142
operation:
140143
op: replace
141144
path: /per_connection_buffer_limit_bytes
@@ -160,7 +163,10 @@ xdsIR:
160163
controllerName: gateway.envoyproxy.io/gatewayclass-controller
161164
- generation: 10
162165
jsonPatches:
163-
- name: envoy-gateway-gateway-1-http
166+
- name:
167+
distinct: false
168+
exact: envoy-gateway-gateway-1-http
169+
name: ""
164170
operation:
165171
op: replace
166172
path: /ignore_global_conn_limit

0 commit comments

Comments
 (0)