Skip to content

Commit

Permalink
impl: custom error response (#4415)
Browse files Browse the repository at this point in the history
* gateway api translation

Signed-off-by: Huabing Zhao <[email protected]>

* add tests for gateway api translation

Signed-off-by: Huabing Zhao <[email protected]>

* xds translation

Signed-off-by: Huabing Zhao <[email protected]>

* test for xds translation

Signed-off-by: Huabing Zhao <[email protected]>

* fix lint

Signed-off-by: Huabing Zhao <[email protected]>

* fix lint

Signed-off-by: Huabing Zhao <[email protected]>

* e2e test

Signed-off-by: Huabing Zhao <[email protected]>

* add cel validation

Signed-off-by: Huabing Zhao <[email protected]>

* fix test

Signed-off-by: Huabing Zhao <[email protected]>

* fix test

Signed-off-by: Huabing Zhao <[email protected]>

* fix test

Signed-off-by: Huabing Zhao <[email protected]>

* fix lint

Signed-off-by: Huabing Zhao <[email protected]>

* address comment

Signed-off-by: Huabing Zhao <[email protected]>

* address comment

Signed-off-by: Huabing Zhao <[email protected]>

* fix lint

Signed-off-by: Huabing Zhao <[email protected]>

* make Body required

Signed-off-by: Huabing Zhao <[email protected]>

* fix e2e

Signed-off-by: Huabing Zhao <[email protected]>

---------

Signed-off-by: Huabing Zhao <[email protected]>
  • Loading branch information
zhaohuabing authored Oct 22, 2024
1 parent 33ac6ca commit 04fc944
Show file tree
Hide file tree
Showing 31 changed files with 2,712 additions and 83 deletions.
1 change: 0 additions & 1 deletion api/v1alpha1/backendtrafficpolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ type BackendTrafficPolicySpec struct {
// If multiple configurations are specified, the first one to match wins.
//
// +optional
// +notImplementedHide
ResponseOverride []*ResponseOverride `json:"responseOverride,omitempty"`
}

Expand Down
7 changes: 6 additions & 1 deletion api/v1alpha1/envoyproxy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ type EnvoyProxySpec struct {
//
// - envoy.filters.http.ratelimit
//
// - envoy.filters.http.custom_response
//
// - envoy.filters.http.router
//
// Note: "envoy.filters.http.router" cannot be reordered, it's always the last filter in the chain.
Expand Down Expand Up @@ -174,7 +176,7 @@ type FilterPosition struct {
}

// EnvoyFilter defines the type of Envoy HTTP filter.
// +kubebuilder:validation:Enum=envoy.filters.http.health_check;envoy.filters.http.fault;envoy.filters.http.cors;envoy.filters.http.ext_authz;envoy.filters.http.basic_auth;envoy.filters.http.oauth2;envoy.filters.http.jwt_authn;envoy.filters.http.stateful_session;envoy.filters.http.ext_proc;envoy.filters.http.wasm;envoy.filters.http.rbac;envoy.filters.http.local_ratelimit;envoy.filters.http.ratelimit
// +kubebuilder:validation:Enum=envoy.filters.http.health_check;envoy.filters.http.fault;envoy.filters.http.cors;envoy.filters.http.ext_authz;envoy.filters.http.basic_auth;envoy.filters.http.oauth2;envoy.filters.http.jwt_authn;envoy.filters.http.stateful_session;envoy.filters.http.ext_proc;envoy.filters.http.wasm;envoy.filters.http.rbac;envoy.filters.http.local_ratelimit;envoy.filters.http.ratelimit;envoy.filters.http.custom_response
type EnvoyFilter string

const (
Expand Down Expand Up @@ -217,6 +219,9 @@ const (
// EnvoyFilterRateLimit defines the Envoy HTTP rate limit filter.
EnvoyFilterRateLimit EnvoyFilter = "envoy.filters.http.ratelimit"

// EnvoyFilterCustomResponse defines the Envoy HTTP custom response filter.
EnvoyFilterCustomResponse EnvoyFilter = "envoy.filters.http.custom_response"

// EnvoyFilterRouter defines the Envoy HTTP router filter.
EnvoyFilterRouter EnvoyFilter = "envoy.filters.http.router"
)
Expand Down
47 changes: 39 additions & 8 deletions api/v1alpha1/shared_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -627,33 +627,48 @@ type ResponseOverride struct {
// CustomResponseMatch defines the configuration for matching a user response to return a custom one.
type CustomResponseMatch struct {
// Status code to match on. The match evaluates to true if any of the matches are successful.
StatusCode []StatusCodeMatch `json:"statusCode"`
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=50
StatusCodes []StatusCodeMatch `json:"statusCodes"`
}

// StatusCodeValueType defines the types of values for the status code match supported by Envoy Gateway.
// +kubebuilder:validation:Enum=Value;Range
type StatusCodeValueType string

const (
// StatusCodeValueTypeValue defines the "Value" status code match type.
StatusCodeValueTypeValue StatusCodeValueType = "Value"

// StatusCodeValueTypeRange defines the "Range" status code match type.
StatusCodeValueTypeRange StatusCodeValueType = "Range"
)

// StatusCodeMatch defines the configuration for matching a status code.
// +kubebuilder:validation:XValidation:message="value must be set for type Value",rule="(!has(self.type) || self.type == 'Value')? has(self.value) : true"
// +kubebuilder:validation:XValidation:message="range must be set for type Range",rule="(has(self.type) && self.type == 'Range')? has(self.range) : true"
type StatusCodeMatch struct {
// Type is the type of value.
// Valid values are Value and Range, default is Value.
//
// +kubebuilder:default=Value
// +kubebuilder:validation:Enum=Value;Range
// +unionDiscriminator
Type *StatusCodeValueType `json:"type"`

// Value contains the value of the status code.
//
// +optional
Value *string `json:"value,omitempty"`
// ValueRef contains the contents of the body
// specified as a local object reference.
// Only a reference to ConfigMap is supported.
Value *int `json:"value,omitempty"`

// Range contains the range of status codes.
//
// +optional
Range *StatusCodeRange `json:"range,omitempty"`
}

// StatusCodeRange defines the configuration for define a range of status codes.
// +kubebuilder:validation:XValidation: message="end must be greater than start",rule="self.end > self.start"
type StatusCodeRange struct {
// Start of the range, including the start value.
Start int `json:"start"`
Expand All @@ -669,30 +684,46 @@ type CustomResponse struct {
ContentType *string `json:"contentType,omitempty"`

// Body of the Custom Response
//
// +optional
Body *CustomResponseBody `json:"body,omitempty"`
Body CustomResponseBody `json:"body"`
}

// ResponseValueType defines the types of values for the response body supported by Envoy Gateway.
// +kubebuilder:validation:Enum=Inline;ValueRef
type ResponseValueType string

const (
// ResponseValueTypeInline defines the "Inline" response body type.
ResponseValueTypeInline ResponseValueType = "Inline"

// ResponseValueTypeValueRef defines the "ValueRef" response body type.
ResponseValueTypeValueRef ResponseValueType = "ValueRef"
)

// CustomResponseBody
// +kubebuilder:validation:XValidation:message="inline must be set for type Inline",rule="(!has(self.type) || self.type == 'Inline')? has(self.inline) : true"
// +kubebuilder:validation:XValidation:message="valueRef must be set for type ValueRef",rule="(has(self.type) && self.type == 'ValueRef')? has(self.valueRef) : true"
// +kubebuilder:validation:XValidation:message="only ConfigMap is supported for ValueRef",rule="has(self.valueRef) ? self.valueRef.kind == 'ConfigMap' : true"
type CustomResponseBody struct {
// Type is the type of method to use to read the body value.
// Valid values are Inline and ValueRef, default is Inline.
//
// +kubebuilder:default=Inline
// +kubebuilder:validation:Enum=Inline;ValueRef
// +unionDiscriminator
Type *ResponseValueType `json:"type"`

// Inline contains the value as an inline string.
//
// +optional
Inline *string `json:"inline,omitempty"`

// ValueRef contains the contents of the body
// specified as a local object reference.
// Only a reference to ConfigMap is supported.
//
// The value of key `response.body` in the ConfigMap will be used as the response body.
// If the key is not found, the first value in the ConfigMap will be used.
//
// +optional
ValueRef *gwapiv1.LocalObjectReference `json:"valueRef,omitempty"`
}
12 changes: 4 additions & 8 deletions api/v1alpha1/zz_generated.deepcopy.go

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

Original file line number Diff line number Diff line change
Expand Up @@ -940,16 +940,15 @@ spec:
match:
description: Match configuration.
properties:
statusCode:
statusCodes:
description: Status code to match on. The match evaluates
to true if any of the matches are successful.
items:
description: StatusCodeMatch defines the configuration
for matching a status code.
properties:
range:
description: |-
ValueRef contains the contents of the body
specified as a local object reference.
Only a reference to ConfigMap is supported.
description: Range contains the range of status codes.
properties:
end:
description: End of the range, including the end
Expand All @@ -963,23 +962,41 @@ spec:
- end
- start
type: object
x-kubernetes-validations:
- message: end must be greater than start
rule: self.end > self.start
type:
allOf:
- enum:
- Value
- Range
- enum:
- Value
- Range
default: Value
description: Type is the type of value.
enum:
- Value
- Range
description: |-
Type is the type of value.
Valid values are Value and Range, default is Value.
type: string
value:
description: Value contains the value of the status
code.
type: string
type: integer
required:
- type
type: object
x-kubernetes-validations:
- message: value must be set for type Value
rule: '(!has(self.type) || self.type == ''Value'')?
has(self.value) : true'
- message: range must be set for type Range
rule: '(has(self.type) && self.type == ''Range'')? has(self.range)
: true'
maxItems: 50
minItems: 1
type: array
required:
- statusCode
- statusCodes
type: object
response:
description: Response configuration.
Expand All @@ -992,17 +1009,26 @@ spec:
string.
type: string
type:
description: Type is the type of method to use to read
the body value.
enum:
- Inline
- ValueRef
allOf:
- enum:
- Inline
- ValueRef
- enum:
- Inline
- ValueRef
default: Inline
description: |-
Type is the type of method to use to read the body value.
Valid values are Inline and ValueRef, default is Inline.
type: string
valueRef:
description: |-
ValueRef contains the contents of the body
specified as a local object reference.
Only a reference to ConfigMap is supported.
The value of key `response.body` in the ConfigMap will be used as the response body.
If the key is not found, the first value in the ConfigMap will be used.
properties:
group:
description: |-
Expand Down Expand Up @@ -1031,10 +1057,22 @@ spec:
required:
- type
type: object
x-kubernetes-validations:
- message: inline must be set for type Inline
rule: '(!has(self.type) || self.type == ''Inline'')? has(self.inline)
: true'
- message: valueRef must be set for type ValueRef
rule: '(has(self.type) && self.type == ''ValueRef'')?
has(self.valueRef) : true'
- message: only ConfigMap is supported for ValueRef
rule: 'has(self.valueRef) ? self.valueRef.kind == ''ConfigMap''
: true'
contentType:
description: Content Type of the response. This will be
set in the Content-Type header.
type: string
required:
- body
type: object
required:
- match
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ spec:

- envoy.filters.http.ratelimit

- envoy.filters.http.custom_response

- envoy.filters.http.router

Note: "envoy.filters.http.router" cannot be reordered, it's always the last filter in the chain.
Expand All @@ -330,6 +332,7 @@ spec:
- envoy.filters.http.rbac
- envoy.filters.http.local_ratelimit
- envoy.filters.http.ratelimit
- envoy.filters.http.custom_response
type: string
before:
description: |-
Expand All @@ -349,6 +352,7 @@ spec:
- envoy.filters.http.rbac
- envoy.filters.http.local_ratelimit
- envoy.filters.http.ratelimit
- envoy.filters.http.custom_response
type: string
name:
description: Name of the filter.
Expand All @@ -366,6 +370,7 @@ spec:
- envoy.filters.http.rbac
- envoy.filters.http.local_ratelimit
- envoy.filters.http.ratelimit
- envoy.filters.http.custom_response
type: string
required:
- name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,26 @@ spec:
description: Inline contains the value as an inline string.
type: string
type:
description: Type is the type of method to use to read the
body value.
enum:
- Inline
- ValueRef
allOf:
- enum:
- Inline
- ValueRef
- enum:
- Inline
- ValueRef
default: Inline
description: |-
Type is the type of method to use to read the body value.
Valid values are Inline and ValueRef, default is Inline.
type: string
valueRef:
description: |-
ValueRef contains the contents of the body
specified as a local object reference.
Only a reference to ConfigMap is supported.
The value of key `response.body` in the ConfigMap will be used as the response body.
If the key is not found, the first value in the ConfigMap will be used.
properties:
group:
description: |-
Expand Down Expand Up @@ -99,6 +108,16 @@ spec:
required:
- type
type: object
x-kubernetes-validations:
- message: inline must be set for type Inline
rule: '(!has(self.type) || self.type == ''Inline'')? has(self.inline)
: true'
- message: valueRef must be set for type ValueRef
rule: '(has(self.type) && self.type == ''ValueRef'')? has(self.valueRef)
: true'
- message: only ConfigMap is supported for ValueRef
rule: 'has(self.valueRef) ? self.valueRef.kind == ''ConfigMap''
: true'
contentType:
description: Content Type of the response. This will be set in
the Content-Type header.
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ require (
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.24.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9
google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
Expand Down
Loading

0 comments on commit 04fc944

Please sign in to comment.