diff --git a/api/v1alpha1/envoyextensionypolicy_types.go b/api/v1alpha1/envoyextensionypolicy_types.go index cbab194b24e..7fbceda8c1f 100644 --- a/api/v1alpha1/envoyextensionypolicy_types.go +++ b/api/v1alpha1/envoyextensionypolicy_types.go @@ -54,11 +54,19 @@ type EnvoyExtensionPolicySpec struct { Wasm []Wasm `json:"wasm,omitempty"` // ExtProc is an ordered list of external processing filters - // that should added to the envoy filter chain + // that should be added to the envoy filter chain // // +kubebuilder:validation:MaxItems=16 // +optional ExtProc []ExtProc `json:"extProc,omitempty"` + + // LuaFilters is an ordered list of Lua filters + // that should be added to the envoy filter chain + // + // +kubebuilder:validation:MaxItems=16 + // +optional + // +notImplementedHide + LuaFilters []LuaFilter `json:"lua,omitempty"` } //+kubebuilder:object:root=true diff --git a/api/v1alpha1/httproutefilter_types.go b/api/v1alpha1/httproutefilter_types.go index 3259fabc8f4..67e86605c21 100644 --- a/api/v1alpha1/httproutefilter_types.go +++ b/api/v1alpha1/httproutefilter_types.go @@ -35,6 +35,10 @@ type HTTPRouteFilterSpec struct { URLRewrite *HTTPURLRewriteFilter `json:"urlRewrite,omitempty"` // +optional DirectResponse *HTTPDirectResponseFilter `json:"directResponse,omitempty"` + // +kubebuilder:validation:MaxItems=16 + // +optional + // +notImplementedHide + LuaFilters []LuaPerRouteFilter `json:"lua,omitempty"` } // HTTPURLRewriteFilter define rewrites of HTTP URL components such as path and host diff --git a/api/v1alpha1/lua_types.go b/api/v1alpha1/lua_types.go new file mode 100644 index 00000000000..5381be9b1a8 --- /dev/null +++ b/api/v1alpha1/lua_types.go @@ -0,0 +1,67 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package v1alpha1 + +// LuaFilter defines a Lua extension that applies globally +// to all requests passing through the filter chain. +type LuaFilter struct { + // SourceCodes is a map of named LuaSource codes that can be referenced in LuaPerRouteFilter + // + // +kubebuilder:validation:MaxProperties=16 + // +optional + SourceCodes map[string]*LuaSource `json:"sourceCodes"` + // DefaultSourceCode is the default LuaSource that will be executed + // unless overridden by LuaPerRouteFilter configured for the selected route + DefaultSourceCode *LuaSource `json:"defaultSourceCode"` + // StatPrefix is the additional prefix to use when emitting statistics. + // By default, metrics are emitted in .lua. namespace. + // If multiple lua filters are configured in a filter chain, the stats from each filter instance can be emitted + // using custom stat prefix to distinguish emitted statistics. + // + // +optional + StatPrefix *string `json:"statPrefix,omitempty"` +} + +// LuaPerRouteFilter defines a Lua extension that applies to specific routes based on route match. +// Only one of Disabled, Name or OverrideSource must be set. +// +kubebuilder:validation:XValidation:rule="has(self.disabled) ? (!has(self.name) && !has(self.overrideSource)) : (has(self.name) ? !has(self.overrideSource) : has(self.overrideSource))",message="Exactly one of disabled, name, or overrideSource must be set." +type LuaPerRouteFilter struct { + // Disabled is the status of the Lua filter for this particular vhost or route. + // If disabled is specified in multiple per-filter-configs, the most specific one will be used. + // + // +optional + Disabled *bool `json:"disabled,omitempty"` + // Name of a LuaSource code stored in LuaFilter.SourceCodes + // + // +optional + Name *string `json:"name,omitempty"` + // OverrideSource is a LuaSource defined for this specific route + // + // +optional + OverrideSource *LuaSource `json:"overrideSource,omitempty"` +} + +// LuaSource contains source code information for a user defined Lua script +// Only one of FileName, InlineBytes, InlineString or EnvironmentVariable must be set +// +kubebuilder:validation:XValidation:rule="has(self.fileName) ? (!has(self.inlineBytes) && !has(self.inlineString) && !has(self.environmentVariable)) : (has(self.inlineBytes) ? (!has(self.inlineString) && !has(self.environmentVariable)) : has(self.inlineString) ? !has(self.environmentVariable) : has(self.environmentVariable))",message="Exactly one of fileName, inlineBytes, inlineString, or environmentVariable must be set." +type LuaSource struct { + // FileName represents a local filesystem data source. + // + // +optional + FileName *string `json:"fileName,omitempty"` + // InlineBytes represents bytes inlined in the configuration. + // + // +optional + InlineBytes []byte `json:"inlineBytes,omitempty"` + // InlineString represents a string inlined in the configuration. + // + // +optional + InlineString *string `json:"inlineString,omitempty"` + // EnvironmentVariable represents an environment variable data source. + // + // +optional + EnvironmentVariable *string `json:"environmentVariable,omitempty"` +} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index dbc28e6aca2..907c456e9d6 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1380,6 +1380,13 @@ func (in *EnvoyExtensionPolicySpec) DeepCopyInto(out *EnvoyExtensionPolicySpec) (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.LuaFilters != nil { + in, out := &in.LuaFilters, &out.LuaFilters + *out = make([]LuaFilter, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyExtensionPolicySpec. @@ -2880,6 +2887,13 @@ func (in *HTTPRouteFilterSpec) DeepCopyInto(out *HTTPRouteFilterSpec) { *out = new(HTTPDirectResponseFilter) (*in).DeepCopyInto(*out) } + if in.LuaFilters != nil { + in, out := &in.LuaFilters, &out.LuaFilters + *out = make([]LuaPerRouteFilter, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteFilterSpec. @@ -3841,6 +3855,112 @@ func (in *LocalRateLimit) DeepCopy() *LocalRateLimit { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LuaFilter) DeepCopyInto(out *LuaFilter) { + *out = *in + if in.SourceCodes != nil { + in, out := &in.SourceCodes, &out.SourceCodes + *out = make(map[string]*LuaSource, len(*in)) + for key, val := range *in { + var outVal *LuaSource + if val == nil { + (*out)[key] = nil + } else { + inVal := (*in)[key] + in, out := &inVal, &outVal + *out = new(LuaSource) + (*in).DeepCopyInto(*out) + } + (*out)[key] = outVal + } + } + if in.DefaultSourceCode != nil { + in, out := &in.DefaultSourceCode, &out.DefaultSourceCode + *out = new(LuaSource) + (*in).DeepCopyInto(*out) + } + if in.StatPrefix != nil { + in, out := &in.StatPrefix, &out.StatPrefix + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LuaFilter. +func (in *LuaFilter) DeepCopy() *LuaFilter { + if in == nil { + return nil + } + out := new(LuaFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LuaPerRouteFilter) DeepCopyInto(out *LuaPerRouteFilter) { + *out = *in + if in.Disabled != nil { + in, out := &in.Disabled, &out.Disabled + *out = new(bool) + **out = **in + } + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } + if in.OverrideSource != nil { + in, out := &in.OverrideSource, &out.OverrideSource + *out = new(LuaSource) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LuaPerRouteFilter. +func (in *LuaPerRouteFilter) DeepCopy() *LuaPerRouteFilter { + if in == nil { + return nil + } + out := new(LuaPerRouteFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LuaSource) DeepCopyInto(out *LuaSource) { + *out = *in + if in.FileName != nil { + in, out := &in.FileName, &out.FileName + *out = new(string) + **out = **in + } + if in.InlineBytes != nil { + in, out := &in.InlineBytes, &out.InlineBytes + *out = make([]byte, len(*in)) + copy(*out, *in) + } + if in.InlineString != nil { + in, out := &in.InlineString, &out.InlineString + *out = new(string) + **out = **in + } + if in.EnvironmentVariable != nil { + in, out := &in.EnvironmentVariable, &out.EnvironmentVariable + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LuaSource. +func (in *LuaSource) DeepCopy() *LuaSource { + if in == nil { + return nil + } + out := new(LuaSource) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OIDC) DeepCopyInto(out *OIDC) { *out = *in diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index 0fbbcafe94e..98bc241b2fb 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -49,7 +49,7 @@ spec: extProc: description: |- ExtProc is an ordered list of external processing filters - that should added to the envoy filter chain + that should be added to the envoy filter chain items: description: ExtProc defines the configuration for External Processing filter. @@ -973,6 +973,94 @@ spec: == "" || f.group == ''gateway.envoyproxy.io'')) : true' maxItems: 16 type: array + lua: + description: |- + LuaFilters is an ordered list of Lua filters + that should be added to the envoy filter chain + items: + description: |- + LuaFilter defines a Lua extension that applies globally + to all requests passing through the filter chain. + properties: + defaultSourceCode: + description: |- + DefaultSourceCode is the default LuaSource that will be executed + unless overridden by LuaPerRouteFilter configured for the selected route + properties: + environmentVariable: + description: EnvironmentVariable represents an environment + variable data source. + type: string + fileName: + description: FileName represents a local filesystem data + source. + type: string + inlineBytes: + description: InlineBytes represents bytes inlined in the + configuration. + format: byte + type: string + inlineString: + description: InlineString represents a string inlined in + the configuration. + type: string + type: object + x-kubernetes-validations: + - message: Exactly one of fileName, inlineBytes, inlineString, + or environmentVariable must be set. + rule: 'has(self.fileName) ? (!has(self.inlineBytes) && !has(self.inlineString) + && !has(self.environmentVariable)) : (has(self.inlineBytes) + ? (!has(self.inlineString) && !has(self.environmentVariable)) + : has(self.inlineString) ? !has(self.environmentVariable) + : has(self.environmentVariable))' + sourceCodes: + additionalProperties: + description: |- + LuaSource contains source code information for a user defined Lua script + Only one of FileName, InlineBytes, InlineString or EnvironmentVariable must be set + properties: + environmentVariable: + description: EnvironmentVariable represents an environment + variable data source. + type: string + fileName: + description: FileName represents a local filesystem data + source. + type: string + inlineBytes: + description: InlineBytes represents bytes inlined in the + configuration. + format: byte + type: string + inlineString: + description: InlineString represents a string inlined + in the configuration. + type: string + type: object + x-kubernetes-validations: + - message: Exactly one of fileName, inlineBytes, inlineString, + or environmentVariable must be set. + rule: 'has(self.fileName) ? (!has(self.inlineBytes) && !has(self.inlineString) + && !has(self.environmentVariable)) : (has(self.inlineBytes) + ? (!has(self.inlineString) && !has(self.environmentVariable)) + : has(self.inlineString) ? !has(self.environmentVariable) + : has(self.environmentVariable))' + description: SourceCodes is a map of named LuaSource codes that + can be referenced in LuaPerRouteFilter + maxProperties: 16 + type: object + statPrefix: + description: |- + StatPrefix is the additional prefix to use when emitting statistics. + By default, metrics are emitted in .lua. namespace. + If multiple lua filters are configured in a filter chain, the stats from each filter instance can be emitted + using custom stat prefix to distinguish emitted statistics. + type: string + required: + - defaultSourceCode + type: object + maxItems: 16 + type: array targetRef: description: |- TargetRef is the name of the resource this policy is being attached to. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_httproutefilters.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_httproutefilters.yaml index 195bf24ece8..6d54325aed7 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_httproutefilters.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_httproutefilters.yaml @@ -128,6 +128,58 @@ spec: If unset, defaults to 200. type: integer type: object + lua: + items: + description: |- + LuaPerRouteFilter defines a Lua extension that applies to specific routes based on route match. + Only one of Disabled, Name or OverrideSource must be set. + properties: + disabled: + description: |- + Disabled is the status of the Lua filter for this particular vhost or route. + If disabled is specified in multiple per-filter-configs, the most specific one will be used. + type: boolean + name: + description: Name of a LuaSource code stored in LuaFilter.SourceCodes + type: string + overrideSource: + description: OverrideSource is a LuaSource defined for this + specific route + properties: + environmentVariable: + description: EnvironmentVariable represents an environment + variable data source. + type: string + fileName: + description: FileName represents a local filesystem data + source. + type: string + inlineBytes: + description: InlineBytes represents bytes inlined in the + configuration. + format: byte + type: string + inlineString: + description: InlineString represents a string inlined in + the configuration. + type: string + type: object + x-kubernetes-validations: + - message: Exactly one of fileName, inlineBytes, inlineString, + or environmentVariable must be set. + rule: 'has(self.fileName) ? (!has(self.inlineBytes) && !has(self.inlineString) + && !has(self.environmentVariable)) : (has(self.inlineBytes) + ? (!has(self.inlineString) && !has(self.environmentVariable)) + : has(self.inlineString) ? !has(self.environmentVariable) + : has(self.environmentVariable))' + type: object + x-kubernetes-validations: + - message: Exactly one of disabled, name, or overrideSource must + be set. + rule: 'has(self.disabled) ? (!has(self.name) && !has(self.overrideSource)) + : (has(self.name) ? !has(self.overrideSource) : has(self.overrideSource))' + maxItems: 16 + type: array urlRewrite: description: HTTPURLRewriteFilter define rewrites of HTTP URL components such as path and host diff --git a/release-notes/current.yaml b/release-notes/current.yaml index 4d61dd6b19f..157cfcc092d 100644 --- a/release-notes/current.yaml +++ b/release-notes/current.yaml @@ -17,6 +17,7 @@ new features: | Added support for trusted CIDRs in the ClientIPDetectionSettings API Added support for sending attributes to external processor in EnvoyExtensionPolicy API Added support for patching EnvoyProxy.spec.provider.kubernetes.envoyHpa and EnvoyProxy.spec.provider.kubernetes.envoyPDB + Added Lua support in EnvoyExtensionPolicy and HTTPRouteFilter APIs # Fixes for bugs identified in previous versions. bug fixes: | diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 5119d756646..d5697aaed9f 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -980,7 +980,7 @@ _Appears in:_ | `targetRefs` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName) array_ | true | TargetRefs are the names of the Gateway resources this policy
is being attached to. | | `targetSelectors` | _[TargetSelector](#targetselector) array_ | true | TargetSelectors allow targeting resources for this policy based on labels | | `wasm` | _[Wasm](#wasm) array_ | false | Wasm is a list of Wasm extensions to be loaded by the Gateway.
Order matters, as the extensions will be loaded in the order they are
defined in this list. | -| `extProc` | _[ExtProc](#extproc) array_ | false | ExtProc is an ordered list of external processing filters
that should added to the envoy filter chain | +| `extProc` | _[ExtProc](#extproc) array_ | false | ExtProc is an ordered list of external processing filters
that should be added to the envoy filter chain | #### EnvoyFilter @@ -2738,6 +2738,59 @@ _Appears in:_ | `error` | LogLevelError defines the "Error" logging level.
| +#### LuaFilter + + + +LuaFilter defines a Lua extension that applies globally +to all requests passing through the filter chain. + +_Appears in:_ +- [EnvoyExtensionPolicySpec](#envoyextensionpolicyspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `sourceCodes` | _object (keys:string, values:[LuaSource](#luasource))_ | false | SourceCodes is a map of named LuaSource codes that can be referenced in LuaPerRouteFilter | +| `defaultSourceCode` | _[LuaSource](#luasource)_ | true | DefaultSourceCode is the default LuaSource that will be executed
unless overridden by LuaPerRouteFilter configured for the selected route | +| `statPrefix` | _string_ | false | StatPrefix is the additional prefix to use when emitting statistics.
By default, metrics are emitted in .lua. namespace.
If multiple lua filters are configured in a filter chain, the stats from each filter instance can be emitted
using custom stat prefix to distinguish emitted statistics. | + + +#### LuaPerRouteFilter + + + +LuaPerRouteFilter defines a Lua extension that applies to specific routes based on route match. +Only one of Disabled, Name or OverrideSource must be set. + +_Appears in:_ +- [HTTPRouteFilterSpec](#httproutefilterspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `disabled` | _boolean_ | false | Disabled is the status of the Lua filter for this particular vhost or route.
If disabled is specified in multiple per-filter-configs, the most specific one will be used. | +| `name` | _string_ | false | Name of a LuaSource code stored in LuaFilter.SourceCodes | +| `overrideSource` | _[LuaSource](#luasource)_ | false | OverrideSource is a LuaSource defined for this specific route | + + +#### LuaSource + + + +LuaSource contains source code information for a user defined Lua script +Only one of FileName, InlineBytes, InlineString or EnvironmentVariable must be set + +_Appears in:_ +- [LuaFilter](#luafilter) +- [LuaPerRouteFilter](#luaperroutefilter) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `fileName` | _string_ | false | FileName represents a local filesystem data source. | +| `inlineBytes` | _integer array_ | false | InlineBytes represents bytes inlined in the configuration. | +| `inlineString` | _string_ | false | InlineString represents a string inlined in the configuration. | +| `environmentVariable` | _string_ | false | EnvironmentVariable represents an environment variable data source. | + + #### MergeType _Underlying type:_ _string_ diff --git a/site/content/zh/latest/api/extension_types.md b/site/content/zh/latest/api/extension_types.md index 5119d756646..d5697aaed9f 100644 --- a/site/content/zh/latest/api/extension_types.md +++ b/site/content/zh/latest/api/extension_types.md @@ -980,7 +980,7 @@ _Appears in:_ | `targetRefs` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName) array_ | true | TargetRefs are the names of the Gateway resources this policy
is being attached to. | | `targetSelectors` | _[TargetSelector](#targetselector) array_ | true | TargetSelectors allow targeting resources for this policy based on labels | | `wasm` | _[Wasm](#wasm) array_ | false | Wasm is a list of Wasm extensions to be loaded by the Gateway.
Order matters, as the extensions will be loaded in the order they are
defined in this list. | -| `extProc` | _[ExtProc](#extproc) array_ | false | ExtProc is an ordered list of external processing filters
that should added to the envoy filter chain | +| `extProc` | _[ExtProc](#extproc) array_ | false | ExtProc is an ordered list of external processing filters
that should be added to the envoy filter chain | #### EnvoyFilter @@ -2738,6 +2738,59 @@ _Appears in:_ | `error` | LogLevelError defines the "Error" logging level.
| +#### LuaFilter + + + +LuaFilter defines a Lua extension that applies globally +to all requests passing through the filter chain. + +_Appears in:_ +- [EnvoyExtensionPolicySpec](#envoyextensionpolicyspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `sourceCodes` | _object (keys:string, values:[LuaSource](#luasource))_ | false | SourceCodes is a map of named LuaSource codes that can be referenced in LuaPerRouteFilter | +| `defaultSourceCode` | _[LuaSource](#luasource)_ | true | DefaultSourceCode is the default LuaSource that will be executed
unless overridden by LuaPerRouteFilter configured for the selected route | +| `statPrefix` | _string_ | false | StatPrefix is the additional prefix to use when emitting statistics.
By default, metrics are emitted in .lua. namespace.
If multiple lua filters are configured in a filter chain, the stats from each filter instance can be emitted
using custom stat prefix to distinguish emitted statistics. | + + +#### LuaPerRouteFilter + + + +LuaPerRouteFilter defines a Lua extension that applies to specific routes based on route match. +Only one of Disabled, Name or OverrideSource must be set. + +_Appears in:_ +- [HTTPRouteFilterSpec](#httproutefilterspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `disabled` | _boolean_ | false | Disabled is the status of the Lua filter for this particular vhost or route.
If disabled is specified in multiple per-filter-configs, the most specific one will be used. | +| `name` | _string_ | false | Name of a LuaSource code stored in LuaFilter.SourceCodes | +| `overrideSource` | _[LuaSource](#luasource)_ | false | OverrideSource is a LuaSource defined for this specific route | + + +#### LuaSource + + + +LuaSource contains source code information for a user defined Lua script +Only one of FileName, InlineBytes, InlineString or EnvironmentVariable must be set + +_Appears in:_ +- [LuaFilter](#luafilter) +- [LuaPerRouteFilter](#luaperroutefilter) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `fileName` | _string_ | false | FileName represents a local filesystem data source. | +| `inlineBytes` | _integer array_ | false | InlineBytes represents bytes inlined in the configuration. | +| `inlineString` | _string_ | false | InlineString represents a string inlined in the configuration. | +| `environmentVariable` | _string_ | false | EnvironmentVariable represents an environment variable data source. | + + #### MergeType _Underlying type:_ _string_ diff --git a/test/cel-validation/envoyextensionpolicy_test.go b/test/cel-validation/envoyextensionpolicy_test.go index a1d435e55dc..55596d87528 100644 --- a/test/cel-validation/envoyextensionpolicy_test.go +++ b/test/cel-validation/envoyextensionpolicy_test.go @@ -414,6 +414,62 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { "spec.extProc[0].processingMode.request.body: Unsupported value: \"not-a-body-mode\": supported values: \"Streamed\", \"Buffered\", \"BufferedPartial\"", }, }, + { + desc: "Lua filter with nil default source code", + mutate: func(sp *egv1a1.EnvoyExtensionPolicy) { + sp.Spec = egv1a1.EnvoyExtensionPolicySpec{ + LuaFilters: []egv1a1.LuaFilter{ + { + SourceCodes: map[string]*egv1a1.LuaSource{ + "test.lua": { + FileName: ptr.To("/tmp/test.lua"), + }, + }, + DefaultSourceCode: nil, + }, + }, + PolicyTargetReferences: egv1a1.PolicyTargetReferences{ + TargetRef: &gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{ + LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{ + Group: "gateway.networking.k8s.io", + Kind: "Gateway", + Name: "eg", + }, + }, + }, + } + }, + wantErrors: []string{ + "spec.lua[0].defaultSourceCode: Required value, : Invalid value: \"null\": some validation rules were not checked because the object was invalid; correct the existing errors to complete validation", + }, + }, + { + desc: "Lua filter with invalid default source code", + mutate: func(sp *egv1a1.EnvoyExtensionPolicy) { + sp.Spec = egv1a1.EnvoyExtensionPolicySpec{ + LuaFilters: []egv1a1.LuaFilter{ + { + DefaultSourceCode: &egv1a1.LuaSource{ + FileName: ptr.To("/tmp/default.lua"), + InlineString: ptr.To("function envoy_on_response(response_handle) -- Do something -- end"), + }, + }, + }, + PolicyTargetReferences: egv1a1.PolicyTargetReferences{ + TargetRef: &gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{ + LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{ + Group: "gateway.networking.k8s.io", + Kind: "Gateway", + Name: "eg", + }, + }, + }, + } + }, + wantErrors: []string{ + "spec.lua[0].defaultSourceCode: Invalid value: \"object\": Exactly one of fileName, inlineBytes, inlineString, or environmentVariable must be set.", + }, + }, { desc: "target selectors without targetRefs or targetRef", mutate: func(sp *egv1a1.EnvoyExtensionPolicy) { diff --git a/test/cel-validation/httproutefilter_test.go b/test/cel-validation/httproutefilter_test.go index c0b6e1ec817..7ed6442b2bf 100644 --- a/test/cel-validation/httproutefilter_test.go +++ b/test/cel-validation/httproutefilter_test.go @@ -66,6 +66,35 @@ func TestHTTPRouteFilter(t *testing.T) { }, wantErrors: []string{"spec.urlRewrite.path: Invalid value: \"object\": If HTTPPathModifier type is ReplaceRegexMatch, replaceRegexMatch field needs to be set."}, }, + { + desc: "Valid LuaPerRoute filter", + mutate: func(httproutefilter *egv1a1.HTTPRouteFilter) { + httproutefilter.Spec = egv1a1.HTTPRouteFilterSpec{ + LuaFilters: []egv1a1.LuaPerRouteFilter{ + { + Name: ptr.To("hello.lua"), + }, + }, + } + }, + wantErrors: nil, + }, + { + desc: "invalid LuaPerRoute filter", + mutate: func(httproutefilter *egv1a1.HTTPRouteFilter) { + httproutefilter.Spec = egv1a1.HTTPRouteFilterSpec{ + LuaFilters: []egv1a1.LuaPerRouteFilter{ + { + Disabled: ptr.To(true), + Name: ptr.To("hello.lua"), + }, + }, + } + }, + wantErrors: []string{ + "spec.lua[0]: Invalid value: \"object\": Exactly one of disabled, name, or overrideSource must be set.", + }, + }, { desc: "invalid RegexHTTPPathModifier missing pattern and substitution", mutate: func(httproutefilter *egv1a1.HTTPRouteFilter) {