diff --git a/api/v1alpha1/ext_proc_types.go b/api/v1alpha1/ext_proc_types.go
index 085e0f86ea..2d6fb1ea69 100644
--- a/api/v1alpha1/ext_proc_types.go
+++ b/api/v1alpha1/ext_proc_types.go
@@ -69,6 +69,7 @@ type ExtProcProcessingMode struct {
// +kubebuilder:validation:XValidation:message="BackendRefs only supports Service, ServiceImport, and Backend kind.",rule="has(self.backendRefs) ? self.backendRefs.all(f, f.kind == 'Service' || f.kind == 'ServiceImport' || f.kind == 'Backend') : true"
// +kubebuilder:validation:XValidation:message="BackendRefs only supports Core, multicluster.x-k8s.io, and gateway.envoyproxy.io groups.",rule="has(self.backendRefs) ? (self.backendRefs.all(f, f.group == \"\" || f.group == 'multicluster.x-k8s.io' || f.group == 'gateway.envoyproxy.io')) : true"
// +kubebuilder:validation:XValidation:message="If FullDuplexStreamed body processing mode is used, FailOpen must be false.",rule="!(has(self.failOpen) && self.failOpen == true && has(self.processingMode) && ((has(self.processingMode.request) && has(self.processingMode.request.body) && self.processingMode.request.body == 'FullDuplexStreamed') || (has(self.processingMode.response) && has(self.processingMode.response.body) && self.processingMode.response.body == 'FullDuplexStreamed')))"
+// +kubebuilder:validation:XValidation:message="If shadowMode is enabled, body processing mode must be Streamed or unset.",rule="!(has(self.shadowMode) && self.shadowMode == true && has(self.processingMode) && ((has(self.processingMode.request) && has(self.processingMode.request.body) && self.processingMode.request.body != 'Streamed') || (has(self.processingMode.response) && has(self.processingMode.response.body) && self.processingMode.response.body != 'Streamed')))"
type ExtProc struct {
BackendCluster `json:",inline"`
@@ -97,6 +98,15 @@ type ExtProc struct {
// +optional
ProcessingMode *ExtProcProcessingMode `json:"processingMode,omitempty"`
+ // ShadowMode sets if envoy gateway should treat this external processor as "send and go".
+ // When enabled, Envoy forwards request/response data to the external processor but does
+ // not wait for or apply any response from it. This maps to Envoy's `observability_mode`
+ // on the ext_proc filter.
+ // Defaults to false.
+ //
+ // +optional
+ ShadowMode *bool `json:"shadowMode,omitempty"`
+
// Metadata defines options related to the sending and receiving of dynamic metadata.
// These options define which metadata namespaces would be sent to the processor and which dynamic metadata
// namespaces the processor would be permitted to emit metadata to.
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 2195616a06..70fa5a1495 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -3430,6 +3430,11 @@ func (in *ExtProc) DeepCopyInto(out *ExtProc) {
*out = new(ExtProcProcessingMode)
(*in).DeepCopyInto(*out)
}
+ if in.ShadowMode != nil {
+ in, out := &in.ShadowMode, &out.ShadowMode
+ *out = new(bool)
+ **out = **in
+ }
if in.Metadata != nil {
in, out := &in.Metadata, &out.Metadata
*out = new(ExtProcMetadata)
diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
index 0091f64054..ced0356581 100644
--- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
+++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
@@ -1609,6 +1609,14 @@ spec:
type: string
type: object
type: object
+ shadowMode:
+ description: |-
+ ShadowMode sets if envoy gateway should treat this external processor as "send and go".
+ When enabled, Envoy forwards request/response data to the external processor but does
+ not wait for or apply any response from it. This maps to Envoy's `observability_mode`
+ on the ext_proc filter.
+ Defaults to false.
+ type: boolean
statusOnError:
description: |-
Sets the HTTP status that is returned to the client when the external processor returns an error
@@ -1675,6 +1683,13 @@ spec:
&& self.processingMode.request.body == ''FullDuplexStreamed'')
|| (has(self.processingMode.response) && has(self.processingMode.response.body)
&& self.processingMode.response.body == ''FullDuplexStreamed'')))'
+ - message: If shadowMode is enabled, body processing mode must be
+ Streamed or unset.
+ rule: '!(has(self.shadowMode) && self.shadowMode == true && has(self.processingMode)
+ && ((has(self.processingMode.request) && has(self.processingMode.request.body)
+ && self.processingMode.request.body != ''Streamed'') || (has(self.processingMode.response)
+ && has(self.processingMode.response.body) && self.processingMode.response.body
+ != ''Streamed'')))'
maxItems: 16
type: array
lua:
diff --git a/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
index e774cc60af..af2b874a7b 100644
--- a/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
+++ b/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
@@ -1608,6 +1608,14 @@ spec:
type: string
type: object
type: object
+ shadowMode:
+ description: |-
+ ShadowMode sets if envoy gateway should treat this external processor as "send and go".
+ When enabled, Envoy forwards request/response data to the external processor but does
+ not wait for or apply any response from it. This maps to Envoy's `observability_mode`
+ on the ext_proc filter.
+ Defaults to false.
+ type: boolean
statusOnError:
description: |-
Sets the HTTP status that is returned to the client when the external processor returns an error
@@ -1674,6 +1682,13 @@ spec:
&& self.processingMode.request.body == ''FullDuplexStreamed'')
|| (has(self.processingMode.response) && has(self.processingMode.response.body)
&& self.processingMode.response.body == ''FullDuplexStreamed'')))'
+ - message: If shadowMode is enabled, body processing mode must be
+ Streamed or unset.
+ rule: '!(has(self.shadowMode) && self.shadowMode == true && has(self.processingMode)
+ && ((has(self.processingMode.request) && has(self.processingMode.request.body)
+ && self.processingMode.request.body != ''Streamed'') || (has(self.processingMode.response)
+ && has(self.processingMode.response.body) && self.processingMode.response.body
+ != ''Streamed'')))'
maxItems: 16
type: array
lua:
diff --git a/internal/gatewayapi/envoyextensionpolicy.go b/internal/gatewayapi/envoyextensionpolicy.go
index 341252f8ed..e3793b3f9b 100644
--- a/internal/gatewayapi/envoyextensionpolicy.go
+++ b/internal/gatewayapi/envoyextensionpolicy.go
@@ -890,6 +890,10 @@ func (t *Translator) buildExtProc(
extProcIR.MessageTimeout = ir.MetaV1DurationPtr(d)
}
+ if extProc.ShadowMode != nil {
+ extProcIR.ShadowMode = extProc.ShadowMode
+ }
+
if extProc.FailOpen != nil {
extProcIR.FailOpen = extProc.FailOpen
}
diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-shadowmode.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-shadowmode.in.yaml
new file mode 100644
index 0000000000..c736ce6ec1
--- /dev/null
+++ b/internal/gatewayapi/testdata/envoyextensionpolicy-shadowmode.in.yaml
@@ -0,0 +1,85 @@
+gateways:
+- apiVersion: gateway.networking.k8s.io/v1
+ kind: Gateway
+ metadata:
+ namespace: default
+ name: gateway-1
+ spec:
+ gatewayClassName: envoy-gateway-class
+ listeners:
+ - name: http
+ protocol: HTTP
+ port: 80
+ allowedRoutes:
+ namespaces:
+ from: All
+httpRoutes:
+- apiVersion: gateway.networking.k8s.io/v1
+ kind: HTTPRoute
+ metadata:
+ namespace: default
+ name: httproute-1
+ spec:
+ hostnames:
+ - www.foo.com
+ parentRefs:
+ - namespace: default
+ name: gateway-1
+ sectionName: http
+ rules:
+ - matches:
+ - path:
+ value: /foo
+ backendRefs:
+ - name: service-1
+ port: 8080
+services:
+- apiVersion: v1
+ kind: Service
+ metadata:
+ namespace: default
+ name: grpc-backend
+ spec:
+ ports:
+ - port: 9000
+ name: grpc
+ protocol: TCP
+endpointSlices:
+- apiVersion: discovery.k8s.io/v1
+ kind: EndpointSlice
+ metadata:
+ name: endpointslice-grpc-backend
+ namespace: default
+ labels:
+ kubernetes.io/service-name: grpc-backend
+ addressType: IPv4
+ ports:
+ - name: grpc
+ protocol: TCP
+ port: 9000
+ endpoints:
+ - addresses:
+ - 8.8.8.8
+ conditions:
+ ready: true
+envoyExtensionPolicies:
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: EnvoyExtensionPolicy
+ metadata:
+ namespace: default
+ name: policy-for-http-route
+ spec:
+ targetRef:
+ group: gateway.networking.k8s.io
+ kind: HTTPRoute
+ name: httproute-1
+ extProc:
+ - backendRefs:
+ - Name: grpc-backend
+ Port: 9000
+ shadowMode: true
+ processingMode:
+ request:
+ body: Streamed
+ response:
+ body: Streamed
diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-shadowmode.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-shadowmode.out.yaml
new file mode 100644
index 0000000000..5286446657
--- /dev/null
+++ b/internal/gatewayapi/testdata/envoyextensionpolicy-shadowmode.out.yaml
@@ -0,0 +1,243 @@
+envoyExtensionPolicies:
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+ kind: EnvoyExtensionPolicy
+ metadata:
+ name: policy-for-http-route
+ namespace: default
+ spec:
+ extProc:
+ - backendRefs:
+ - name: grpc-backend
+ port: 9000
+ processingMode:
+ request:
+ body: Streamed
+ response:
+ body: Streamed
+ shadowMode: true
+ targetRef:
+ group: gateway.networking.k8s.io
+ kind: HTTPRoute
+ name: httproute-1
+ status:
+ ancestors:
+ - ancestorRef:
+ group: gateway.networking.k8s.io
+ kind: Gateway
+ name: gateway-1
+ namespace: default
+ sectionName: http
+ conditions:
+ - lastTransitionTime: null
+ message: Policy has been accepted.
+ reason: Accepted
+ status: "True"
+ type: Accepted
+ - lastTransitionTime: null
+ message: spec.targetRef is deprecated, use spec.targetRefs instead
+ reason: DeprecatedField
+ status: "True"
+ type: Warning
+ controllerName: gateway.envoyproxy.io/gatewayclass-controller
+gateways:
+- apiVersion: gateway.networking.k8s.io/v1
+ kind: Gateway
+ metadata:
+ name: gateway-1
+ namespace: default
+ spec:
+ gatewayClassName: envoy-gateway-class
+ listeners:
+ - allowedRoutes:
+ namespaces:
+ from: All
+ name: http
+ port: 80
+ protocol: HTTP
+ status:
+ listeners:
+ - attachedRoutes: 1
+ conditions:
+ - lastTransitionTime: null
+ message: Sending translated listener configuration to the data plane
+ reason: Programmed
+ status: "True"
+ type: Programmed
+ - lastTransitionTime: null
+ message: Listener has been successfully translated
+ reason: Accepted
+ status: "True"
+ type: Accepted
+ - lastTransitionTime: null
+ message: Listener references have been resolved
+ reason: ResolvedRefs
+ status: "True"
+ type: ResolvedRefs
+ name: http
+ supportedKinds:
+ - group: gateway.networking.k8s.io
+ kind: HTTPRoute
+ - group: gateway.networking.k8s.io
+ kind: GRPCRoute
+httpRoutes:
+- apiVersion: gateway.networking.k8s.io/v1
+ kind: HTTPRoute
+ metadata:
+ name: httproute-1
+ namespace: default
+ spec:
+ hostnames:
+ - www.foo.com
+ parentRefs:
+ - name: gateway-1
+ namespace: default
+ sectionName: http
+ rules:
+ - backendRefs:
+ - name: service-1
+ port: 8080
+ matches:
+ - path:
+ value: /foo
+ status:
+ parents:
+ - conditions:
+ - lastTransitionTime: null
+ message: Route is accepted
+ reason: Accepted
+ status: "True"
+ type: Accepted
+ - lastTransitionTime: null
+ message: Resolved all the Object references for the Route
+ reason: ResolvedRefs
+ status: "True"
+ type: ResolvedRefs
+ controllerName: gateway.envoyproxy.io/gatewayclass-controller
+ parentRef:
+ name: gateway-1
+ namespace: default
+ sectionName: http
+infraIR:
+ default/gateway-1:
+ proxy:
+ listeners:
+ - name: default/gateway-1/http
+ ports:
+ - containerPort: 10080
+ name: http-80
+ protocol: HTTP
+ servicePort: 80
+ metadata:
+ labels:
+ gateway.envoyproxy.io/owning-gateway-name: gateway-1
+ gateway.envoyproxy.io/owning-gateway-namespace: default
+ ownerReference:
+ kind: GatewayClass
+ name: envoy-gateway-class
+ name: default/gateway-1
+ namespace: envoy-gateway-system
+xdsIR:
+ default/gateway-1:
+ accessLog:
+ json:
+ - path: /dev/stdout
+ globalResources:
+ proxyServiceCluster:
+ metadata:
+ kind: Service
+ name: envoy-default-gateway-1-bfd08ef4
+ namespace: envoy-gateway-system
+ sectionName: "8080"
+ name: default/gateway-1
+ settings:
+ - addressType: IP
+ endpoints:
+ - host: 7.6.5.4
+ port: 8080
+ zone: zone1
+ metadata:
+ kind: Service
+ name: envoy-default-gateway-1-bfd08ef4
+ namespace: envoy-gateway-system
+ sectionName: "8080"
+ name: default/gateway-1
+ protocol: TCP
+ http:
+ - address: 0.0.0.0
+ externalPort: 80
+ hostnames:
+ - '*'
+ metadata:
+ kind: Gateway
+ name: gateway-1
+ namespace: default
+ sectionName: http
+ name: default/gateway-1/http
+ path:
+ escapedSlashesAction: UnescapeAndRedirect
+ mergeSlashes: true
+ port: 10080
+ routes:
+ - destination:
+ metadata:
+ kind: HTTPRoute
+ name: httproute-1
+ namespace: default
+ name: httproute/default/httproute-1/rule/0
+ settings:
+ - addressType: IP
+ endpoints:
+ - host: 7.7.7.7
+ port: 8080
+ metadata:
+ kind: Service
+ name: service-1
+ namespace: default
+ sectionName: "8080"
+ name: httproute/default/httproute-1/rule/0/backend/0
+ protocol: HTTP
+ weight: 1
+ envoyExtensions:
+ extProcs:
+ - authority: grpc-backend.default:9000
+ destination:
+ metadata:
+ kind: EnvoyExtensionPolicy
+ name: policy-for-http-route
+ namespace: default
+ name: envoyextensionpolicy/default/policy-for-http-route/extproc/0
+ settings:
+ - addressType: IP
+ endpoints:
+ - host: 8.8.8.8
+ port: 9000
+ metadata:
+ kind: Service
+ name: grpc-backend
+ namespace: default
+ sectionName: "9000"
+ name: envoyextensionpolicy/default/policy-for-http-route/extproc/0/backend/0
+ protocol: GRPC
+ weight: 1
+ name: envoyextensionpolicy/default/policy-for-http-route/extproc/0
+ requestBodyProcessingMode: Streamed
+ requestHeaderProcessing: true
+ responseBodyProcessingMode: Streamed
+ responseHeaderProcessing: true
+ shadowMode: true
+ hostname: www.foo.com
+ isHTTP2: false
+ metadata:
+ kind: HTTPRoute
+ name: httproute-1
+ namespace: default
+ name: httproute/default/httproute-1/rule/0/match/0/www_foo_com
+ pathMatch:
+ distinct: false
+ name: ""
+ prefix: /foo
+ readyListener:
+ address: 0.0.0.0
+ ipFamily: IPv4
+ path: /ready
+ port: 19003
diff --git a/internal/ir/xds.go b/internal/ir/xds.go
index d8ff851451..6d795bf944 100644
--- a/internal/ir/xds.go
+++ b/internal/ir/xds.go
@@ -3684,6 +3684,10 @@ type ExtProc struct {
// MessageTimeout is the timeout for a response to be returned from the external processor
MessageTimeout *metav1.Duration `json:"messageTimeout,omitempty" yaml:"messageTimeout,omitempty"`
+ // ShadowMode sets if envoy gateway should treat this external processor as "send and go".
+ // Maps to Envoy's `observability_mode` on the ext_proc filter.
+ ShadowMode *bool `json:"shadowMode,omitempty" yaml:"shadowMode,omitempty"`
+
// FailOpen defines if requests or responses that cannot be processed due to connectivity to the
// external processor are terminated or passed-through.
FailOpen *bool `json:"failOpen,omitempty" yaml:"failOpen,omitempty"`
diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go
index f4e3a81b02..151021ad50 100644
--- a/internal/ir/zz_generated.deepcopy.go
+++ b/internal/ir/zz_generated.deepcopy.go
@@ -1634,6 +1634,11 @@ func (in *ExtProc) DeepCopyInto(out *ExtProc) {
*out = new(metav1.Duration)
**out = **in
}
+ if in.ShadowMode != nil {
+ in, out := &in.ShadowMode, &out.ShadowMode
+ *out = new(bool)
+ **out = **in
+ }
if in.FailOpen != nil {
in, out := &in.FailOpen, &out.FailOpen
*out = new(bool)
diff --git a/internal/xds/translator/extproc.go b/internal/xds/translator/extproc.go
index ef03c485fb..846796d76b 100644
--- a/internal/xds/translator/extproc.go
+++ b/internal/xds/translator/extproc.go
@@ -108,6 +108,10 @@ func extProcConfig(extProc *ir.ExtProc) (*extprocv3.ExternalProcessor, error) {
config.ProcessingMode = buildProcessingMode(extProc)
+ if extProc.ShadowMode != nil {
+ config.ObservabilityMode = *extProc.ShadowMode
+ }
+
if extProc.FailOpen != nil {
config.FailureModeAllow = *extProc.FailOpen
}
diff --git a/internal/xds/translator/testdata/in/xds-ir/ext-proc.yaml b/internal/xds/translator/testdata/in/xds-ir/ext-proc.yaml
index ac3e7fe119..915bc8fc6a 100644
--- a/internal/xds/translator/testdata/in/xds-ir/ext-proc.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/ext-proc.yaml
@@ -84,6 +84,7 @@ http:
name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0/grpc-backend-3/backend/0
- name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/extproc/0
failOpen: false
+ shadowMode: true
statusOnError: 503
messageTimeout: 15s
requestAttributes:
diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-proc.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-proc.listeners.yaml
index 940862f64b..47500f8461 100644
--- a/internal/xds/translator/testdata/out/xds-ir/ext-proc.listeners.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/ext-proc.listeners.yaml
@@ -79,6 +79,7 @@
receivingNamespaces:
untyped:
- envoy.filters.http.prc_ext
+ observabilityMode: true
processingMode:
requestHeaderMode: SKIP
requestTrailerMode: SKIP
diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md
index 7d78e634ab..ab0a203321 100644
--- a/site/content/en/latest/api/extension_types.md
+++ b/site/content/en/latest/api/extension_types.md
@@ -2331,6 +2331,7 @@ _Appears in:_
| `messageTimeout` | _[Duration](https://gateway-api.sigs.k8s.io/reference/api-spec/1.5/spec/#duration)_ | false | | MessageTimeout is the timeout for a response to be returned from the external processor
Default: 200ms |
| `failOpen` | _boolean_ | false | false | FailOpen is a switch used to control the behavior when failing to call the external processor.
If FailOpen is set to true, the system bypasses the ExtProc extension and
allows the traffic to pass through. If it is set to false or
not set (defaulting to false), the system blocks the traffic and returns
an HTTP 5xx error.
If set to true, the ExtProc extension will also be bypassed if the configuration is invalid. |
| `processingMode` | _[ExtProcProcessingMode](#extprocprocessingmode)_ | false | | ProcessingMode defines how request and response body is processed
Default: header and body are not sent to the external processor |
+| `shadowMode` | _boolean_ | false | | ShadowMode sets if envoy gateway should treat this external processor as "send and go".
When enabled, Envoy forwards request/response data to the external processor but does
not wait for or apply any response from it. This maps to Envoy's `observability_mode`
on the ext_proc filter.
Defaults to false. |
| `metadata` | _[ExtProcMetadata](#extprocmetadata)_ | false | | Refer to Kubernetes API documentation for fields of `metadata`. |
| `statusOnError` | _integer_ | false | | Sets the HTTP status that is returned to the client when the external processor returns an error
or cannot be reached. Defaults to 500 Internal Server Error.
Only 4xx and 5xx status codes are supported. |
diff --git a/test/cel-validation/envoyextensionpolicy_test.go b/test/cel-validation/envoyextensionpolicy_test.go
index aae14e2cac..d838c0c2d2 100644
--- a/test/cel-validation/envoyextensionpolicy_test.go
+++ b/test/cel-validation/envoyextensionpolicy_test.go
@@ -1332,6 +1332,49 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) {
},
wantErrors: []string{},
},
+ {
+ desc: "invalid ExtProc with FullDuplexStreamed response/request body and invalid body processing mode",
+ mutate: func(sp *egv1a1.EnvoyExtensionPolicy) {
+ sp.Spec = egv1a1.EnvoyExtensionPolicySpec{
+ ExtProc: []egv1a1.ExtProc{
+ {
+ BackendCluster: egv1a1.BackendCluster{
+ BackendRefs: []egv1a1.BackendRef{
+ {
+ BackendObjectReference: gwapiv1.BackendObjectReference{
+ Name: "grpc-proc-service",
+ Port: new(gwapiv1.PortNumber(80)),
+ },
+ },
+ },
+ },
+ ProcessingMode: &egv1a1.ExtProcProcessingMode{
+ Request: &egv1a1.ProcessingModeOptions{
+ Body: new(egv1a1.ExtProcBodyProcessingMode("FullDuplexStreamed")),
+ },
+ Response: &egv1a1.ProcessingModeOptions{
+ Body: new(egv1a1.ExtProcBodyProcessingMode("FullDuplexStreamed")),
+ },
+ },
+ ShadowMode: new(true),
+ },
+ },
+ PolicyTargetReferences: egv1a1.PolicyTargetReferences{
+ TargetRef: &gwapiv1.LocalPolicyTargetReferenceWithSectionName{
+ LocalPolicyTargetReference: gwapiv1.LocalPolicyTargetReference{
+ Group: "gateway.networking.k8s.io",
+ Kind: "Gateway",
+ Name: "eg",
+ },
+ },
+ },
+ }
+ },
+ wantErrors: []string{
+ "spec.extProc[0]: Invalid value:",
+ ": If shadowMode is enabled, body processing mode must be Streamed or unset.",
+ },
+ },
}
for _, tc := range cases {
diff --git a/test/helm/gateway-crds-helm/all.out.yaml b/test/helm/gateway-crds-helm/all.out.yaml
index f0fcbd76a5..61692a7913 100644
--- a/test/helm/gateway-crds-helm/all.out.yaml
+++ b/test/helm/gateway-crds-helm/all.out.yaml
@@ -32134,6 +32134,14 @@ spec:
type: string
type: object
type: object
+ shadowMode:
+ description: |-
+ ShadowMode sets if envoy gateway should treat this external processor as "send and go".
+ When enabled, Envoy forwards request/response data to the external processor but does
+ not wait for or apply any response from it. This maps to Envoy's `observability_mode`
+ on the ext_proc filter.
+ Defaults to false.
+ type: boolean
statusOnError:
description: |-
Sets the HTTP status that is returned to the client when the external processor returns an error
@@ -32200,6 +32208,13 @@ spec:
&& self.processingMode.request.body == ''FullDuplexStreamed'')
|| (has(self.processingMode.response) && has(self.processingMode.response.body)
&& self.processingMode.response.body == ''FullDuplexStreamed'')))'
+ - message: If shadowMode is enabled, body processing mode must be
+ Streamed or unset.
+ rule: '!(has(self.shadowMode) && self.shadowMode == true && has(self.processingMode)
+ && ((has(self.processingMode.request) && has(self.processingMode.request.body)
+ && self.processingMode.request.body != ''Streamed'') || (has(self.processingMode.response)
+ && has(self.processingMode.response.body) && self.processingMode.response.body
+ != ''Streamed'')))'
maxItems: 16
type: array
lua:
diff --git a/test/helm/gateway-crds-helm/e2e.out.yaml b/test/helm/gateway-crds-helm/e2e.out.yaml
index a91c9b9ca8..20e6be1465 100644
--- a/test/helm/gateway-crds-helm/e2e.out.yaml
+++ b/test/helm/gateway-crds-helm/e2e.out.yaml
@@ -8072,6 +8072,14 @@ spec:
type: string
type: object
type: object
+ shadowMode:
+ description: |-
+ ShadowMode sets if envoy gateway should treat this external processor as "send and go".
+ When enabled, Envoy forwards request/response data to the external processor but does
+ not wait for or apply any response from it. This maps to Envoy's `observability_mode`
+ on the ext_proc filter.
+ Defaults to false.
+ type: boolean
statusOnError:
description: |-
Sets the HTTP status that is returned to the client when the external processor returns an error
@@ -8138,6 +8146,13 @@ spec:
&& self.processingMode.request.body == ''FullDuplexStreamed'')
|| (has(self.processingMode.response) && has(self.processingMode.response.body)
&& self.processingMode.response.body == ''FullDuplexStreamed'')))'
+ - message: If shadowMode is enabled, body processing mode must be
+ Streamed or unset.
+ rule: '!(has(self.shadowMode) && self.shadowMode == true && has(self.processingMode)
+ && ((has(self.processingMode.request) && has(self.processingMode.request.body)
+ && self.processingMode.request.body != ''Streamed'') || (has(self.processingMode.response)
+ && has(self.processingMode.response.body) && self.processingMode.response.body
+ != ''Streamed'')))'
maxItems: 16
type: array
lua:
diff --git a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml
index f926f93ec0..624a7c1434 100644
--- a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml
+++ b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml
@@ -8072,6 +8072,14 @@ spec:
type: string
type: object
type: object
+ shadowMode:
+ description: |-
+ ShadowMode sets if envoy gateway should treat this external processor as "send and go".
+ When enabled, Envoy forwards request/response data to the external processor but does
+ not wait for or apply any response from it. This maps to Envoy's `observability_mode`
+ on the ext_proc filter.
+ Defaults to false.
+ type: boolean
statusOnError:
description: |-
Sets the HTTP status that is returned to the client when the external processor returns an error
@@ -8138,6 +8146,13 @@ spec:
&& self.processingMode.request.body == ''FullDuplexStreamed'')
|| (has(self.processingMode.response) && has(self.processingMode.response.body)
&& self.processingMode.response.body == ''FullDuplexStreamed'')))'
+ - message: If shadowMode is enabled, body processing mode must be
+ Streamed or unset.
+ rule: '!(has(self.shadowMode) && self.shadowMode == true && has(self.processingMode)
+ && ((has(self.processingMode.request) && has(self.processingMode.request.body)
+ && self.processingMode.request.body != ''Streamed'') || (has(self.processingMode.response)
+ && has(self.processingMode.response.body) && self.processingMode.response.body
+ != ''Streamed'')))'
maxItems: 16
type: array
lua: