From b18c4965e1943b4fadd93309874b3ffdebab1a8a Mon Sep 17 00:00:00 2001
From: Kate Osborn <50597707+kate-osborn@users.noreply.github.com>
Date: Tue, 28 Jan 2025 12:24:18 -0700
Subject: [PATCH] Support NginxProxy at the Gateway level (#3058)
Problem: When the control plane and data planes are split, the user will need the ability to specify data plane settings on a per-Gateway basis. To allow this, we need to support NginxProxy at the Gateway level in addition the the GatewayClass level. In practice, this means a user can reference an NginxProxy resource via the
spec.infrastructure.parametersRef field on the Gateway resource. We still want to support referencing an NginxProxy at the GatewayClass level. If a Gateway and its GatewayClass reference distinct NginxProxy resources, the settings must be merged. Settings specified on a Gateway NginxProxy must override those set on the GatewayClass NginxProxy.
Solution: To support NginxProxy at the Gateway level several changes were made to the API.
As a result, the API is now at version v1alpha2.
Breaking Changes:
* Change the scope of the CRD to Namespaced. The parametersRef.namespace field on the GatewayClass is now required.
* Make DisableHTTP2 and Telemetry.Exporter.Endpoint optional.
New fields:
* Telemetry.DisabledFeatures: allows users to explicitly disable telemetry features. It is a list with one supported entry: DisableTracing. More features may be added in future releases.
Other changes:
* Remove the listType=Map kubebuilder annotation from the RewriteClientIP.TrustedAddresses field. This listType is incorrect since TrustedAddresses can have duplicate keys.
The graph now stores NginxProxies that are referenced by the winning GatewayClass and Gateway. This will need to be updated once we support multiple Gateways. The graph is also responsible for merging the NginxProxies when necessary. The result of this is stored on the graph's Gateway object in the field EffectiveNginxProxy. The EffectiveNginxProxy on the Gateway is used to build the NGINX configuration.
---
apis/v1alpha1/register.go | 2 -
apis/v1alpha1/zz_generated.deepcopy.go | 258 ---
.../nginxproxy_types.go | 48 +-
apis/v1alpha2/register.go | 3 +-
apis/v1alpha2/zz_generated.deepcopy.go | 273 +++
.../templates/gatewayclass.yaml | 1 +
.../templates/nginxproxy.yaml | 3 +-
.../nginx-gateway-fabric/values.schema.json | 11 +
charts/nginx-gateway-fabric/values.yaml | 6 +
.../bases/gateway.nginx.org_nginxproxies.yaml | 30 +-
deploy/aws-nlb/deploy.yaml | 6 +-
deploy/azure/deploy.yaml | 6 +-
deploy/crds.yaml | 30 +-
deploy/default/deploy.yaml | 6 +-
deploy/experimental-nginx-plus/deploy.yaml | 4 +-
deploy/experimental/deploy.yaml | 6 +-
deploy/nginx-plus/deploy.yaml | 4 +-
deploy/nodeport/deploy.yaml | 6 +-
deploy/openshift/deploy.yaml | 6 +-
.../snippets-filters-nginx-plus/deploy.yaml | 4 +-
deploy/snippets-filters/deploy.yaml | 6 +-
internal/mode/static/manager.go | 4 +-
internal/mode/static/manager_test.go | 10 +-
.../mode/static/state/change_processor.go | 4 +-
.../static/state/change_processor_test.go | 173 +-
.../static/state/conditions/conditions.go | 81 +-
.../static/state/dataplane/configuration.go | 92 +-
.../state/dataplane/configuration_test.go | 505 ++---
.../mode/static/state/graph/backend_refs.go | 51 +-
.../static/state/graph/backend_refs_test.go | 51 +-
internal/mode/static/state/graph/gateway.go | 101 +-
.../mode/static/state/graph/gateway_test.go | 356 +++-
.../mode/static/state/graph/gatewayclass.go | 106 +-
.../static/state/graph/gatewayclass_test.go | 136 +-
internal/mode/static/state/graph/graph.go | 78 +-
.../mode/static/state/graph/graph_test.go | 183 +-
.../mode/static/state/graph/grpcroute_test.go | 34 +-
.../mode/static/state/graph/nginxproxy.go | 230 +-
.../static/state/graph/nginxproxy_test.go | 1018 ++++++---
.../mode/static/state/graph/route_common.go | 15 +-
internal/mode/static/state/graph/tlsroute.go | 4 +-
.../mode/static/state/graph/tlsroute_test.go | 11 +-
.../mode/static/status/prepare_requests.go | 2 +
.../static/status/prepare_requests_test.go | 111 +
internal/mode/static/telemetry/collector.go | 5 +-
.../mode/static/telemetry/collector_test.go | 15 +-
.../how-to/data-plane-configuration.md | 6 +-
site/content/reference/api.md | 1898 +++++++++--------
tests/suite/manifests/tracing/nginxproxy.yaml | 2 +-
49 files changed, 3764 insertions(+), 2237 deletions(-)
rename apis/{v1alpha1 => v1alpha2}/nginxproxy_types.go (87%)
diff --git a/apis/v1alpha1/register.go b/apis/v1alpha1/register.go
index 0d18c29eaa..7deb5bfb5c 100644
--- a/apis/v1alpha1/register.go
+++ b/apis/v1alpha1/register.go
@@ -34,8 +34,6 @@ func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&NginxGateway{},
&NginxGatewayList{},
- &NginxProxy{},
- &NginxProxyList{},
&ObservabilityPolicy{},
&ObservabilityPolicyList{},
&ClientSettingsPolicy{},
diff --git a/apis/v1alpha1/zz_generated.deepcopy.go b/apis/v1alpha1/zz_generated.deepcopy.go
index 96100bed3f..65b3b76c30 100644
--- a/apis/v1alpha1/zz_generated.deepcopy.go
+++ b/apis/v1alpha1/zz_generated.deepcopy.go
@@ -318,159 +318,6 @@ func (in *NginxGatewayStatus) DeepCopy() *NginxGatewayStatus {
return out
}
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *NginxLogging) DeepCopyInto(out *NginxLogging) {
- *out = *in
- if in.ErrorLevel != nil {
- in, out := &in.ErrorLevel, &out.ErrorLevel
- *out = new(NginxErrorLogLevel)
- **out = **in
- }
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NginxLogging.
-func (in *NginxLogging) DeepCopy() *NginxLogging {
- if in == nil {
- return nil
- }
- out := new(NginxLogging)
- in.DeepCopyInto(out)
- return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *NginxPlus) DeepCopyInto(out *NginxPlus) {
- *out = *in
- if in.AllowedAddresses != nil {
- in, out := &in.AllowedAddresses, &out.AllowedAddresses
- *out = make([]NginxPlusAllowAddress, len(*in))
- copy(*out, *in)
- }
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NginxPlus.
-func (in *NginxPlus) DeepCopy() *NginxPlus {
- if in == nil {
- return nil
- }
- out := new(NginxPlus)
- in.DeepCopyInto(out)
- return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *NginxPlusAllowAddress) DeepCopyInto(out *NginxPlusAllowAddress) {
- *out = *in
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NginxPlusAllowAddress.
-func (in *NginxPlusAllowAddress) DeepCopy() *NginxPlusAllowAddress {
- if in == nil {
- return nil
- }
- out := new(NginxPlusAllowAddress)
- in.DeepCopyInto(out)
- return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *NginxProxy) DeepCopyInto(out *NginxProxy) {
- *out = *in
- out.TypeMeta = in.TypeMeta
- in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
- in.Spec.DeepCopyInto(&out.Spec)
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NginxProxy.
-func (in *NginxProxy) DeepCopy() *NginxProxy {
- if in == nil {
- return nil
- }
- out := new(NginxProxy)
- in.DeepCopyInto(out)
- return out
-}
-
-// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
-func (in *NginxProxy) DeepCopyObject() runtime.Object {
- if c := in.DeepCopy(); c != nil {
- return c
- }
- return nil
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *NginxProxyList) DeepCopyInto(out *NginxProxyList) {
- *out = *in
- out.TypeMeta = in.TypeMeta
- in.ListMeta.DeepCopyInto(&out.ListMeta)
- if in.Items != nil {
- in, out := &in.Items, &out.Items
- *out = make([]NginxProxy, len(*in))
- for i := range *in {
- (*in)[i].DeepCopyInto(&(*out)[i])
- }
- }
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NginxProxyList.
-func (in *NginxProxyList) DeepCopy() *NginxProxyList {
- if in == nil {
- return nil
- }
- out := new(NginxProxyList)
- in.DeepCopyInto(out)
- return out
-}
-
-// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
-func (in *NginxProxyList) DeepCopyObject() runtime.Object {
- if c := in.DeepCopy(); c != nil {
- return c
- }
- return nil
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *NginxProxySpec) DeepCopyInto(out *NginxProxySpec) {
- *out = *in
- if in.IPFamily != nil {
- in, out := &in.IPFamily, &out.IPFamily
- *out = new(IPFamilyType)
- **out = **in
- }
- if in.Telemetry != nil {
- in, out := &in.Telemetry, &out.Telemetry
- *out = new(Telemetry)
- (*in).DeepCopyInto(*out)
- }
- if in.RewriteClientIP != nil {
- in, out := &in.RewriteClientIP, &out.RewriteClientIP
- *out = new(RewriteClientIP)
- (*in).DeepCopyInto(*out)
- }
- if in.Logging != nil {
- in, out := &in.Logging, &out.Logging
- *out = new(NginxLogging)
- (*in).DeepCopyInto(*out)
- }
- if in.NginxPlus != nil {
- in, out := &in.NginxPlus, &out.NginxPlus
- *out = new(NginxPlus)
- (*in).DeepCopyInto(*out)
- }
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NginxProxySpec.
-func (in *NginxProxySpec) DeepCopy() *NginxProxySpec {
- if in == nil {
- return nil
- }
- out := new(NginxProxySpec)
- in.DeepCopyInto(out)
- return out
-}
-
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ObservabilityPolicy) DeepCopyInto(out *ObservabilityPolicy) {
*out = *in
@@ -557,51 +404,6 @@ func (in *ObservabilityPolicySpec) DeepCopy() *ObservabilityPolicySpec {
return out
}
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *RewriteClientIP) DeepCopyInto(out *RewriteClientIP) {
- *out = *in
- if in.Mode != nil {
- in, out := &in.Mode, &out.Mode
- *out = new(RewriteClientIPModeType)
- **out = **in
- }
- if in.SetIPRecursively != nil {
- in, out := &in.SetIPRecursively, &out.SetIPRecursively
- *out = new(bool)
- **out = **in
- }
- if in.TrustedAddresses != nil {
- in, out := &in.TrustedAddresses, &out.TrustedAddresses
- *out = make([]RewriteClientIPAddress, len(*in))
- copy(*out, *in)
- }
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RewriteClientIP.
-func (in *RewriteClientIP) DeepCopy() *RewriteClientIP {
- if in == nil {
- return nil
- }
- out := new(RewriteClientIP)
- in.DeepCopyInto(out)
- return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *RewriteClientIPAddress) DeepCopyInto(out *RewriteClientIPAddress) {
- *out = *in
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RewriteClientIPAddress.
-func (in *RewriteClientIPAddress) DeepCopy() *RewriteClientIPAddress {
- if in == nil {
- return nil
- }
- out := new(RewriteClientIPAddress)
- in.DeepCopyInto(out)
- return out
-}
-
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Snippet) DeepCopyInto(out *Snippet) {
*out = *in
@@ -733,66 +535,6 @@ func (in *SpanAttribute) DeepCopy() *SpanAttribute {
return out
}
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *Telemetry) DeepCopyInto(out *Telemetry) {
- *out = *in
- if in.Exporter != nil {
- in, out := &in.Exporter, &out.Exporter
- *out = new(TelemetryExporter)
- (*in).DeepCopyInto(*out)
- }
- if in.ServiceName != nil {
- in, out := &in.ServiceName, &out.ServiceName
- *out = new(string)
- **out = **in
- }
- if in.SpanAttributes != nil {
- in, out := &in.SpanAttributes, &out.SpanAttributes
- *out = make([]SpanAttribute, len(*in))
- copy(*out, *in)
- }
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Telemetry.
-func (in *Telemetry) DeepCopy() *Telemetry {
- if in == nil {
- return nil
- }
- out := new(Telemetry)
- in.DeepCopyInto(out)
- return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *TelemetryExporter) DeepCopyInto(out *TelemetryExporter) {
- *out = *in
- if in.Interval != nil {
- in, out := &in.Interval, &out.Interval
- *out = new(Duration)
- **out = **in
- }
- if in.BatchSize != nil {
- in, out := &in.BatchSize, &out.BatchSize
- *out = new(int32)
- **out = **in
- }
- if in.BatchCount != nil {
- in, out := &in.BatchCount, &out.BatchCount
- *out = new(int32)
- **out = **in
- }
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TelemetryExporter.
-func (in *TelemetryExporter) DeepCopy() *TelemetryExporter {
- if in == nil {
- return nil
- }
- out := new(TelemetryExporter)
- in.DeepCopyInto(out)
- return out
-}
-
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Tracing) DeepCopyInto(out *Tracing) {
*out = *in
diff --git a/apis/v1alpha1/nginxproxy_types.go b/apis/v1alpha2/nginxproxy_types.go
similarity index 87%
rename from apis/v1alpha1/nginxproxy_types.go
rename to apis/v1alpha2/nginxproxy_types.go
index ed4ea9ed3d..7c10bd9f3c 100644
--- a/apis/v1alpha1/nginxproxy_types.go
+++ b/apis/v1alpha2/nginxproxy_types.go
@@ -1,15 +1,23 @@
-package v1alpha1
+package v1alpha2
-import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+ "github.com/nginx/nginx-gateway-fabric/apis/v1alpha1"
+)
// +genclient
// +kubebuilder:object:root=true
// +kubebuilder:storageversion
-// +kubebuilder:resource:categories=nginx-gateway-fabric,scope=Cluster
+// +kubebuilder:resource:categories=nginx-gateway-fabric,scope=Namespaced
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
-// NginxProxy is a configuration object that is attached to a GatewayClass parametersRef. It provides a way
-// to configure global settings for all Gateways defined from the GatewayClass.
+// NginxProxy is a configuration object that can be referenced from a GatewayClass parametersRef
+// or a Gateway infrastructure.parametersRef. It provides a way to configure data plane settings.
+// If referenced from a GatewayClass, the settings apply to all Gateways attached to the GatewayClass.
+// If referenced from a Gateway, the settings apply to that Gateway alone. If both a Gateway and its GatewayClass
+// reference an NginxProxy, the settings are merged. Settings specified on the Gateway NginxProxy override those
+// set on the GatewayClass NginxProxy.
type NginxProxy struct { //nolint:govet // standard field alignment, don't change it
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
@@ -54,8 +62,10 @@ type NginxProxySpec struct {
// +optional
NginxPlus *NginxPlus `json:"nginxPlus,omitempty"`
// DisableHTTP2 defines if http2 should be disabled for all servers.
- // Default is false, meaning http2 will be enabled for all servers.
- DisableHTTP2 bool `json:"disableHTTP2,omitempty"`
+ // If not specified, or set to false, http2 will be enabled for all servers.
+ //
+ // +optional
+ DisableHTTP2 *bool `json:"disableHTTP2,omitempty"`
}
// NginxPlus specifies NGINX Plus additional settings. These will only be applied if NGINX Plus is being used.
@@ -68,6 +78,10 @@ type NginxPlus struct {
// Telemetry specifies the OpenTelemetry configuration.
type Telemetry struct {
+ // DisabledFeatures specifies OpenTelemetry features to be disabled.
+ //
+ // +optional
+ DisabledFeatures []DisableTelemetryFeature `json:"disabledFeatures,omitempty"`
// Exporter specifies OpenTelemetry export parameters.
//
// +optional
@@ -88,7 +102,7 @@ type Telemetry struct {
// +listType=map
// +listMapKey=key
// +kubebuilder:validation:MaxItems=64
- SpanAttributes []SpanAttribute `json:"spanAttributes,omitempty"`
+ SpanAttributes []v1alpha1.SpanAttribute `json:"spanAttributes,omitempty"`
}
// TelemetryExporter specifies OpenTelemetry export parameters.
@@ -97,7 +111,7 @@ type TelemetryExporter struct {
// Default: https://nginx.org/en/docs/ngx_otel_module.html#otel_exporter
//
// +optional
- Interval *Duration `json:"interval,omitempty"`
+ Interval *v1alpha1.Duration `json:"interval,omitempty"`
// BatchSize is the maximum number of spans to be sent in one batch per worker.
// Default: https://nginx.org/en/docs/ngx_otel_module.html#otel_exporter
@@ -117,8 +131,9 @@ type TelemetryExporter struct {
// Format: alphanumeric hostname with optional http scheme and optional port.
//
//nolint:lll
+ // +optional
// +kubebuilder:validation:Pattern=`^(?:http?:\/\/)?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*(?::\d{1,5})?$`
- Endpoint string `json:"endpoint"`
+ Endpoint *string `json:"endpoint,omitempty"`
}
// RewriteClientIP specifies the configuration for rewriting the client's IP address.
@@ -149,15 +164,12 @@ type RewriteClientIP struct {
// If a request comes from a trusted address, NGINX will rewrite the client IP information,
// and forward it to the backend in the X-Forwarded-For* and X-Real-IP headers.
// If the request does not come from a trusted address, NGINX will not rewrite the client IP information.
- // TrustedAddresses only supports CIDR blocks: 192.33.21.1/24, fe80::1/64.
// To trust all addresses (not recommended for production), set to 0.0.0.0/0.
// If no addresses are provided, NGINX will not rewrite the client IP information.
// Sets NGINX directive set_real_ip_from: https://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from
// This field is required if mode is set.
//
// +optional
- // +listType=map
- // +listMapKey=type
// +kubebuilder:validation:MaxItems=16
TrustedAddresses []RewriteClientIPAddress `json:"trustedAddresses,omitempty"`
}
@@ -280,3 +292,13 @@ const (
// NginxLogLevelEmerg is the emerg level for NGINX error logs.
NginxLogLevelEmerg NginxErrorLogLevel = "emerg"
)
+
+// DisableTelemetryFeature is a telemetry feature that can be disabled.
+//
+// +kubebuilder:validation:Enum=DisableTracing
+type DisableTelemetryFeature string
+
+const (
+ // DisableTracing disables the OpenTelemetry tracing feature.
+ DisableTracing DisableTelemetryFeature = "DisableTracing"
+)
diff --git a/apis/v1alpha2/register.go b/apis/v1alpha2/register.go
index 23601e280e..8615a5a3b0 100644
--- a/apis/v1alpha2/register.go
+++ b/apis/v1alpha2/register.go
@@ -32,11 +32,12 @@ var (
// Adds the list of known types to Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
+ &NginxProxy{},
+ &NginxProxyList{},
&ObservabilityPolicy{},
&ObservabilityPolicyList{},
)
// AddToGroupVersion allows the serialization of client types like ListOptions.
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
-
return nil
}
diff --git a/apis/v1alpha2/zz_generated.deepcopy.go b/apis/v1alpha2/zz_generated.deepcopy.go
index 77cf20bb07..6e0856a220 100644
--- a/apis/v1alpha2/zz_generated.deepcopy.go
+++ b/apis/v1alpha2/zz_generated.deepcopy.go
@@ -10,6 +10,164 @@ import (
apisv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
)
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *NginxLogging) DeepCopyInto(out *NginxLogging) {
+ *out = *in
+ if in.ErrorLevel != nil {
+ in, out := &in.ErrorLevel, &out.ErrorLevel
+ *out = new(NginxErrorLogLevel)
+ **out = **in
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NginxLogging.
+func (in *NginxLogging) DeepCopy() *NginxLogging {
+ if in == nil {
+ return nil
+ }
+ out := new(NginxLogging)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *NginxPlus) DeepCopyInto(out *NginxPlus) {
+ *out = *in
+ if in.AllowedAddresses != nil {
+ in, out := &in.AllowedAddresses, &out.AllowedAddresses
+ *out = make([]NginxPlusAllowAddress, len(*in))
+ copy(*out, *in)
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NginxPlus.
+func (in *NginxPlus) DeepCopy() *NginxPlus {
+ if in == nil {
+ return nil
+ }
+ out := new(NginxPlus)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *NginxPlusAllowAddress) DeepCopyInto(out *NginxPlusAllowAddress) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NginxPlusAllowAddress.
+func (in *NginxPlusAllowAddress) DeepCopy() *NginxPlusAllowAddress {
+ if in == nil {
+ return nil
+ }
+ out := new(NginxPlusAllowAddress)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *NginxProxy) DeepCopyInto(out *NginxProxy) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+ in.Spec.DeepCopyInto(&out.Spec)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NginxProxy.
+func (in *NginxProxy) DeepCopy() *NginxProxy {
+ if in == nil {
+ return nil
+ }
+ out := new(NginxProxy)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *NginxProxy) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *NginxProxyList) DeepCopyInto(out *NginxProxyList) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.ListMeta)
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]NginxProxy, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NginxProxyList.
+func (in *NginxProxyList) DeepCopy() *NginxProxyList {
+ if in == nil {
+ return nil
+ }
+ out := new(NginxProxyList)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *NginxProxyList) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *NginxProxySpec) DeepCopyInto(out *NginxProxySpec) {
+ *out = *in
+ if in.IPFamily != nil {
+ in, out := &in.IPFamily, &out.IPFamily
+ *out = new(IPFamilyType)
+ **out = **in
+ }
+ if in.Telemetry != nil {
+ in, out := &in.Telemetry, &out.Telemetry
+ *out = new(Telemetry)
+ (*in).DeepCopyInto(*out)
+ }
+ if in.RewriteClientIP != nil {
+ in, out := &in.RewriteClientIP, &out.RewriteClientIP
+ *out = new(RewriteClientIP)
+ (*in).DeepCopyInto(*out)
+ }
+ if in.Logging != nil {
+ in, out := &in.Logging, &out.Logging
+ *out = new(NginxLogging)
+ (*in).DeepCopyInto(*out)
+ }
+ if in.NginxPlus != nil {
+ in, out := &in.NginxPlus, &out.NginxPlus
+ *out = new(NginxPlus)
+ (*in).DeepCopyInto(*out)
+ }
+ if in.DisableHTTP2 != nil {
+ in, out := &in.DisableHTTP2, &out.DisableHTTP2
+ *out = new(bool)
+ **out = **in
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NginxProxySpec.
+func (in *NginxProxySpec) DeepCopy() *NginxProxySpec {
+ if in == nil {
+ return nil
+ }
+ out := new(NginxProxySpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ObservabilityPolicy) DeepCopyInto(out *ObservabilityPolicy) {
*out = *in
@@ -96,6 +254,121 @@ func (in *ObservabilityPolicySpec) DeepCopy() *ObservabilityPolicySpec {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *RewriteClientIP) DeepCopyInto(out *RewriteClientIP) {
+ *out = *in
+ if in.Mode != nil {
+ in, out := &in.Mode, &out.Mode
+ *out = new(RewriteClientIPModeType)
+ **out = **in
+ }
+ if in.SetIPRecursively != nil {
+ in, out := &in.SetIPRecursively, &out.SetIPRecursively
+ *out = new(bool)
+ **out = **in
+ }
+ if in.TrustedAddresses != nil {
+ in, out := &in.TrustedAddresses, &out.TrustedAddresses
+ *out = make([]RewriteClientIPAddress, len(*in))
+ copy(*out, *in)
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RewriteClientIP.
+func (in *RewriteClientIP) DeepCopy() *RewriteClientIP {
+ if in == nil {
+ return nil
+ }
+ out := new(RewriteClientIP)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *RewriteClientIPAddress) DeepCopyInto(out *RewriteClientIPAddress) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RewriteClientIPAddress.
+func (in *RewriteClientIPAddress) DeepCopy() *RewriteClientIPAddress {
+ if in == nil {
+ return nil
+ }
+ out := new(RewriteClientIPAddress)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Telemetry) DeepCopyInto(out *Telemetry) {
+ *out = *in
+ if in.DisabledFeatures != nil {
+ in, out := &in.DisabledFeatures, &out.DisabledFeatures
+ *out = make([]DisableTelemetryFeature, len(*in))
+ copy(*out, *in)
+ }
+ if in.Exporter != nil {
+ in, out := &in.Exporter, &out.Exporter
+ *out = new(TelemetryExporter)
+ (*in).DeepCopyInto(*out)
+ }
+ if in.ServiceName != nil {
+ in, out := &in.ServiceName, &out.ServiceName
+ *out = new(string)
+ **out = **in
+ }
+ if in.SpanAttributes != nil {
+ in, out := &in.SpanAttributes, &out.SpanAttributes
+ *out = make([]v1alpha1.SpanAttribute, len(*in))
+ copy(*out, *in)
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Telemetry.
+func (in *Telemetry) DeepCopy() *Telemetry {
+ if in == nil {
+ return nil
+ }
+ out := new(Telemetry)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *TelemetryExporter) DeepCopyInto(out *TelemetryExporter) {
+ *out = *in
+ if in.Interval != nil {
+ in, out := &in.Interval, &out.Interval
+ *out = new(v1alpha1.Duration)
+ **out = **in
+ }
+ if in.BatchSize != nil {
+ in, out := &in.BatchSize, &out.BatchSize
+ *out = new(int32)
+ **out = **in
+ }
+ if in.BatchCount != nil {
+ in, out := &in.BatchCount, &out.BatchCount
+ *out = new(int32)
+ **out = **in
+ }
+ if in.Endpoint != nil {
+ in, out := &in.Endpoint, &out.Endpoint
+ *out = new(string)
+ **out = **in
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TelemetryExporter.
+func (in *TelemetryExporter) DeepCopy() *TelemetryExporter {
+ if in == nil {
+ return nil
+ }
+ out := new(TelemetryExporter)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Tracing) DeepCopyInto(out *Tracing) {
*out = *in
diff --git a/charts/nginx-gateway-fabric/templates/gatewayclass.yaml b/charts/nginx-gateway-fabric/templates/gatewayclass.yaml
index ee08e1a726..aecd54e8ad 100644
--- a/charts/nginx-gateway-fabric/templates/gatewayclass.yaml
+++ b/charts/nginx-gateway-fabric/templates/gatewayclass.yaml
@@ -17,4 +17,5 @@ spec:
group: gateway.nginx.org
kind: NginxProxy
name: {{ include "nginx-gateway.proxy-config-name" . }}
+ namespace: {{ .Release.Namespace }}
{{- end }}
diff --git a/charts/nginx-gateway-fabric/templates/nginxproxy.yaml b/charts/nginx-gateway-fabric/templates/nginxproxy.yaml
index 4214158b75..bc4105ee37 100644
--- a/charts/nginx-gateway-fabric/templates/nginxproxy.yaml
+++ b/charts/nginx-gateway-fabric/templates/nginxproxy.yaml
@@ -1,8 +1,9 @@
{{- if .Values.nginx.config }}
-apiVersion: gateway.nginx.org/v1alpha1
+apiVersion: gateway.nginx.org/v1alpha2
kind: NginxProxy
metadata:
name: {{ include "nginx-gateway.proxy-config-name" . }}
+ namespace: {{ .Release.Namespace }}
labels:
{{- include "nginx-gateway.labels" . | nindent 4 }}
spec:
diff --git a/charts/nginx-gateway-fabric/values.schema.json b/charts/nginx-gateway-fabric/values.schema.json
index e5d9f321ee..d13491b48f 100644
--- a/charts/nginx-gateway-fabric/values.schema.json
+++ b/charts/nginx-gateway-fabric/values.schema.json
@@ -165,6 +165,17 @@
"telemetry": {
"description": "Telemetry specifies the OpenTelemetry configuration.",
"properties": {
+ "disabledFeatures": {
+ "items": {
+ "enum": [
+ "DisableTracing"
+ ],
+ "required": [],
+ "type": "string"
+ },
+ "required": [],
+ "type": "array"
+ },
"exporter": {
"properties": {
"batchCount": {
diff --git a/charts/nginx-gateway-fabric/values.yaml b/charts/nginx-gateway-fabric/values.yaml
index 2647448ba9..5873ba5682 100644
--- a/charts/nginx-gateway-fabric/values.yaml
+++ b/charts/nginx-gateway-fabric/values.yaml
@@ -233,6 +233,12 @@ nginx:
# pattern: ^([^"$\\]|\\[^$])*$
# minLength: 1
# maxLength: 255
+ # disabledFeatures:
+ # type: array
+ # items:
+ # type: string
+ # enum:
+ # - DisableTracing
# logging:
# type: object
# description: Logging defines logging related settings for NGINX.
diff --git a/config/crd/bases/gateway.nginx.org_nginxproxies.yaml b/config/crd/bases/gateway.nginx.org_nginxproxies.yaml
index b842c62214..834ace5c6c 100644
--- a/config/crd/bases/gateway.nginx.org_nginxproxies.yaml
+++ b/config/crd/bases/gateway.nginx.org_nginxproxies.yaml
@@ -14,18 +14,22 @@ spec:
listKind: NginxProxyList
plural: nginxproxies
singular: nginxproxy
- scope: Cluster
+ scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
- name: v1alpha1
+ name: v1alpha2
schema:
openAPIV3Schema:
description: |-
- NginxProxy is a configuration object that is attached to a GatewayClass parametersRef. It provides a way
- to configure global settings for all Gateways defined from the GatewayClass.
+ NginxProxy is a configuration object that can be referenced from a GatewayClass parametersRef
+ or a Gateway infrastructure.parametersRef. It provides a way to configure data plane settings.
+ If referenced from a GatewayClass, the settings apply to all Gateways attached to the GatewayClass.
+ If referenced from a Gateway, the settings apply to that Gateway alone. If both a Gateway and its GatewayClass
+ reference an NginxProxy, the settings are merged. Settings specified on the Gateway NginxProxy override those
+ set on the GatewayClass NginxProxy.
properties:
apiVersion:
description: |-
@@ -50,7 +54,7 @@ spec:
disableHTTP2:
description: |-
DisableHTTP2 defines if http2 should be disabled for all servers.
- Default is false, meaning http2 will be enabled for all servers.
+ If not specified, or set to false, http2 will be enabled for all servers.
type: boolean
ipFamily:
default: dual
@@ -141,7 +145,6 @@ spec:
If a request comes from a trusted address, NGINX will rewrite the client IP information,
and forward it to the backend in the X-Forwarded-For* and X-Real-IP headers.
If the request does not come from a trusted address, NGINX will not rewrite the client IP information.
- TrustedAddresses only supports CIDR blocks: 192.33.21.1/24, fe80::1/64.
To trust all addresses (not recommended for production), set to 0.0.0.0/0.
If no addresses are provided, NGINX will not rewrite the client IP information.
Sets NGINX directive set_real_ip_from: https://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from
@@ -166,9 +169,6 @@ spec:
type: object
maxItems: 16
type: array
- x-kubernetes-list-map-keys:
- - type
- x-kubernetes-list-type: map
type: object
x-kubernetes-validations:
- message: if mode is set, trustedAddresses is a required field
@@ -177,6 +177,16 @@ spec:
telemetry:
description: Telemetry specifies the OpenTelemetry configuration.
properties:
+ disabledFeatures:
+ description: DisabledFeatures specifies OpenTelemetry features
+ to be disabled.
+ items:
+ description: DisableTelemetryFeature is a telemetry feature
+ that can be disabled.
+ enum:
+ - DisableTracing
+ type: string
+ type: array
exporter:
description: Exporter specifies OpenTelemetry export parameters.
properties:
@@ -206,8 +216,6 @@ spec:
Default: https://nginx.org/en/docs/ngx_otel_module.html#otel_exporter
pattern: ^[0-9]{1,4}(ms|s|m|h)?$
type: string
- required:
- - endpoint
type: object
serviceName:
description: |-
diff --git a/deploy/aws-nlb/deploy.yaml b/deploy/aws-nlb/deploy.yaml
index 6bc4dff222..98dddfdc9b 100644
--- a/deploy/aws-nlb/deploy.yaml
+++ b/deploy/aws-nlb/deploy.yaml
@@ -324,7 +324,7 @@ spec:
app.kubernetes.io/name: tmp-nginx-deployment
spec:
containers:
- - image: ghcr.io/nginxinc/nginx-gateway-fabric/nginx:edge
+ - image: ghcr.io/nginx/nginx-gateway-fabric/nginx:edge
imagePullPolicy: Always
name: nginx
ports:
@@ -366,7 +366,7 @@ spec:
- /usr/bin/gateway
- sleep
- --duration=15s
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: sleep
- command:
@@ -381,7 +381,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.uid
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: init
securityContext:
diff --git a/deploy/azure/deploy.yaml b/deploy/azure/deploy.yaml
index 99ee0c2be2..236c62288b 100644
--- a/deploy/azure/deploy.yaml
+++ b/deploy/azure/deploy.yaml
@@ -323,7 +323,7 @@ spec:
app.kubernetes.io/name: tmp-nginx-deployment
spec:
containers:
- - image: ghcr.io/nginxinc/nginx-gateway-fabric/nginx:edge
+ - image: ghcr.io/nginx/nginx-gateway-fabric/nginx:edge
imagePullPolicy: Always
name: nginx
ports:
@@ -365,7 +365,7 @@ spec:
- /usr/bin/gateway
- sleep
- --duration=15s
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: sleep
- command:
@@ -380,7 +380,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.uid
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: init
securityContext:
diff --git a/deploy/crds.yaml b/deploy/crds.yaml
index f0547580f1..a7be218353 100644
--- a/deploy/crds.yaml
+++ b/deploy/crds.yaml
@@ -599,18 +599,22 @@ spec:
listKind: NginxProxyList
plural: nginxproxies
singular: nginxproxy
- scope: Cluster
+ scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
- name: v1alpha1
+ name: v1alpha2
schema:
openAPIV3Schema:
description: |-
- NginxProxy is a configuration object that is attached to a GatewayClass parametersRef. It provides a way
- to configure global settings for all Gateways defined from the GatewayClass.
+ NginxProxy is a configuration object that can be referenced from a GatewayClass parametersRef
+ or a Gateway infrastructure.parametersRef. It provides a way to configure data plane settings.
+ If referenced from a GatewayClass, the settings apply to all Gateways attached to the GatewayClass.
+ If referenced from a Gateway, the settings apply to that Gateway alone. If both a Gateway and its GatewayClass
+ reference an NginxProxy, the settings are merged. Settings specified on the Gateway NginxProxy override those
+ set on the GatewayClass NginxProxy.
properties:
apiVersion:
description: |-
@@ -635,7 +639,7 @@ spec:
disableHTTP2:
description: |-
DisableHTTP2 defines if http2 should be disabled for all servers.
- Default is false, meaning http2 will be enabled for all servers.
+ If not specified, or set to false, http2 will be enabled for all servers.
type: boolean
ipFamily:
default: dual
@@ -726,7 +730,6 @@ spec:
If a request comes from a trusted address, NGINX will rewrite the client IP information,
and forward it to the backend in the X-Forwarded-For* and X-Real-IP headers.
If the request does not come from a trusted address, NGINX will not rewrite the client IP information.
- TrustedAddresses only supports CIDR blocks: 192.33.21.1/24, fe80::1/64.
To trust all addresses (not recommended for production), set to 0.0.0.0/0.
If no addresses are provided, NGINX will not rewrite the client IP information.
Sets NGINX directive set_real_ip_from: https://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from
@@ -751,9 +754,6 @@ spec:
type: object
maxItems: 16
type: array
- x-kubernetes-list-map-keys:
- - type
- x-kubernetes-list-type: map
type: object
x-kubernetes-validations:
- message: if mode is set, trustedAddresses is a required field
@@ -762,6 +762,16 @@ spec:
telemetry:
description: Telemetry specifies the OpenTelemetry configuration.
properties:
+ disabledFeatures:
+ description: DisabledFeatures specifies OpenTelemetry features
+ to be disabled.
+ items:
+ description: DisableTelemetryFeature is a telemetry feature
+ that can be disabled.
+ enum:
+ - DisableTracing
+ type: string
+ type: array
exporter:
description: Exporter specifies OpenTelemetry export parameters.
properties:
@@ -791,8 +801,6 @@ spec:
Default: https://nginx.org/en/docs/ngx_otel_module.html#otel_exporter
pattern: ^[0-9]{1,4}(ms|s|m|h)?$
type: string
- required:
- - endpoint
type: object
serviceName:
description: |-
diff --git a/deploy/default/deploy.yaml b/deploy/default/deploy.yaml
index d9b557e4d7..c066b92710 100644
--- a/deploy/default/deploy.yaml
+++ b/deploy/default/deploy.yaml
@@ -321,7 +321,7 @@ spec:
app.kubernetes.io/name: tmp-nginx-deployment
spec:
containers:
- - image: ghcr.io/nginxinc/nginx-gateway-fabric/nginx:edge
+ - image: ghcr.io/nginx/nginx-gateway-fabric/nginx:edge
imagePullPolicy: Always
name: nginx
ports:
@@ -363,7 +363,7 @@ spec:
- /usr/bin/gateway
- sleep
- --duration=15s
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: sleep
- command:
@@ -378,7 +378,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.uid
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: init
securityContext:
diff --git a/deploy/experimental-nginx-plus/deploy.yaml b/deploy/experimental-nginx-plus/deploy.yaml
index c23de692ed..ae5ca25e93 100644
--- a/deploy/experimental-nginx-plus/deploy.yaml
+++ b/deploy/experimental-nginx-plus/deploy.yaml
@@ -389,7 +389,7 @@ spec:
- /usr/bin/gateway
- sleep
- --duration=15s
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: sleep
- command:
@@ -407,7 +407,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.uid
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: init
securityContext:
diff --git a/deploy/experimental/deploy.yaml b/deploy/experimental/deploy.yaml
index e6cd3b16b4..16c1d7c10f 100644
--- a/deploy/experimental/deploy.yaml
+++ b/deploy/experimental/deploy.yaml
@@ -327,7 +327,7 @@ spec:
app.kubernetes.io/name: tmp-nginx-deployment
spec:
containers:
- - image: ghcr.io/nginxinc/nginx-gateway-fabric/nginx:edge
+ - image: ghcr.io/nginx/nginx-gateway-fabric/nginx:edge
imagePullPolicy: Always
name: nginx
ports:
@@ -369,7 +369,7 @@ spec:
- /usr/bin/gateway
- sleep
- --duration=15s
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: sleep
- command:
@@ -384,7 +384,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.uid
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: init
securityContext:
diff --git a/deploy/nginx-plus/deploy.yaml b/deploy/nginx-plus/deploy.yaml
index 479e20805c..2ab6da27dd 100644
--- a/deploy/nginx-plus/deploy.yaml
+++ b/deploy/nginx-plus/deploy.yaml
@@ -383,7 +383,7 @@ spec:
- /usr/bin/gateway
- sleep
- --duration=15s
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: sleep
- command:
@@ -401,7 +401,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.uid
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: init
securityContext:
diff --git a/deploy/nodeport/deploy.yaml b/deploy/nodeport/deploy.yaml
index c39299e838..a016150ab7 100644
--- a/deploy/nodeport/deploy.yaml
+++ b/deploy/nodeport/deploy.yaml
@@ -321,7 +321,7 @@ spec:
app.kubernetes.io/name: tmp-nginx-deployment
spec:
containers:
- - image: ghcr.io/nginxinc/nginx-gateway-fabric/nginx:edge
+ - image: ghcr.io/nginx/nginx-gateway-fabric/nginx:edge
imagePullPolicy: Always
name: nginx
ports:
@@ -363,7 +363,7 @@ spec:
- /usr/bin/gateway
- sleep
- --duration=15s
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: sleep
- command:
@@ -378,7 +378,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.uid
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: init
securityContext:
diff --git a/deploy/openshift/deploy.yaml b/deploy/openshift/deploy.yaml
index ea1e5f43f9..43ba8df5fb 100644
--- a/deploy/openshift/deploy.yaml
+++ b/deploy/openshift/deploy.yaml
@@ -329,7 +329,7 @@ spec:
app.kubernetes.io/name: tmp-nginx-deployment
spec:
containers:
- - image: ghcr.io/nginxinc/nginx-gateway-fabric/nginx:edge
+ - image: ghcr.io/nginx/nginx-gateway-fabric/nginx:edge
imagePullPolicy: Always
name: nginx
ports:
@@ -371,7 +371,7 @@ spec:
- /usr/bin/gateway
- sleep
- --duration=15s
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: sleep
- command:
@@ -386,7 +386,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.uid
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: init
securityContext:
diff --git a/deploy/snippets-filters-nginx-plus/deploy.yaml b/deploy/snippets-filters-nginx-plus/deploy.yaml
index 435319441e..1206af4707 100644
--- a/deploy/snippets-filters-nginx-plus/deploy.yaml
+++ b/deploy/snippets-filters-nginx-plus/deploy.yaml
@@ -386,7 +386,7 @@ spec:
- /usr/bin/gateway
- sleep
- --duration=15s
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: sleep
- command:
@@ -404,7 +404,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.uid
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: init
securityContext:
diff --git a/deploy/snippets-filters/deploy.yaml b/deploy/snippets-filters/deploy.yaml
index e97a00d98f..98d20a0ea4 100644
--- a/deploy/snippets-filters/deploy.yaml
+++ b/deploy/snippets-filters/deploy.yaml
@@ -324,7 +324,7 @@ spec:
app.kubernetes.io/name: tmp-nginx-deployment
spec:
containers:
- - image: ghcr.io/nginxinc/nginx-gateway-fabric/nginx:edge
+ - image: ghcr.io/nginx/nginx-gateway-fabric/nginx:edge
imagePullPolicy: Always
name: nginx
ports:
@@ -366,7 +366,7 @@ spec:
- /usr/bin/gateway
- sleep
- --duration=15s
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: sleep
- command:
@@ -381,7 +381,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.uid
- image: ghcr.io/nginxinc/nginx-gateway-fabric:edge
+ image: ghcr.io/nginx/nginx-gateway-fabric:edge
imagePullPolicy: Always
name: init
securityContext:
diff --git a/internal/mode/static/manager.go b/internal/mode/static/manager.go
index 459a79b5e4..70413ffe05 100644
--- a/internal/mode/static/manager.go
+++ b/internal/mode/static/manager.go
@@ -447,7 +447,7 @@ func registerControllers(
},
},
{
- objectType: &ngfAPIv1alpha1.NginxProxy{},
+ objectType: &ngfAPIv1alpha2.NginxProxy{},
options: []controller.Option{
controller.WithK8sPredicate(k8spredicate.GenerationChangedPredicate{}),
},
@@ -708,7 +708,7 @@ func prepareFirstEventBatchPreparerArgs(cfg config.Config) ([]client.Object, []c
&discoveryV1.EndpointSliceList{},
&gatewayv1.HTTPRouteList{},
&gatewayv1beta1.ReferenceGrantList{},
- &ngfAPIv1alpha1.NginxProxyList{},
+ &ngfAPIv1alpha2.NginxProxyList{},
&gatewayv1.GRPCRouteList{},
&ngfAPIv1alpha1.ClientSettingsPolicyList{},
&ngfAPIv1alpha2.ObservabilityPolicyList{},
diff --git a/internal/mode/static/manager_test.go b/internal/mode/static/manager_test.go
index 5361be4deb..98a6146905 100644
--- a/internal/mode/static/manager_test.go
+++ b/internal/mode/static/manager_test.go
@@ -63,7 +63,7 @@ func TestPrepareFirstEventBatchPreparerArgs(t *testing.T) {
&gatewayv1.HTTPRouteList{},
&gatewayv1.GatewayList{},
&gatewayv1beta1.ReferenceGrantList{},
- &ngfAPIv1alpha1.NginxProxyList{},
+ &ngfAPIv1alpha2.NginxProxyList{},
&gatewayv1.GRPCRouteList{},
partialObjectMetadataList,
&ngfAPIv1alpha1.ClientSettingsPolicyList{},
@@ -93,7 +93,7 @@ func TestPrepareFirstEventBatchPreparerArgs(t *testing.T) {
&discoveryV1.EndpointSliceList{},
&gatewayv1.HTTPRouteList{},
&gatewayv1beta1.ReferenceGrantList{},
- &ngfAPIv1alpha1.NginxProxyList{},
+ &ngfAPIv1alpha2.NginxProxyList{},
&gatewayv1.GRPCRouteList{},
partialObjectMetadataList,
&ngfAPIv1alpha1.ClientSettingsPolicyList{},
@@ -124,7 +124,7 @@ func TestPrepareFirstEventBatchPreparerArgs(t *testing.T) {
&discoveryV1.EndpointSliceList{},
&gatewayv1.HTTPRouteList{},
&gatewayv1beta1.ReferenceGrantList{},
- &ngfAPIv1alpha1.NginxProxyList{},
+ &ngfAPIv1alpha2.NginxProxyList{},
partialObjectMetadataList,
&gatewayv1alpha3.BackendTLSPolicyList{},
&gatewayv1alpha2.TLSRouteList{},
@@ -156,7 +156,7 @@ func TestPrepareFirstEventBatchPreparerArgs(t *testing.T) {
&discoveryV1.EndpointSliceList{},
&gatewayv1.HTTPRouteList{},
&gatewayv1beta1.ReferenceGrantList{},
- &ngfAPIv1alpha1.NginxProxyList{},
+ &ngfAPIv1alpha2.NginxProxyList{},
partialObjectMetadataList,
&gatewayv1.GRPCRouteList{},
&ngfAPIv1alpha1.ClientSettingsPolicyList{},
@@ -188,7 +188,7 @@ func TestPrepareFirstEventBatchPreparerArgs(t *testing.T) {
&discoveryV1.EndpointSliceList{},
&gatewayv1.HTTPRouteList{},
&gatewayv1beta1.ReferenceGrantList{},
- &ngfAPIv1alpha1.NginxProxyList{},
+ &ngfAPIv1alpha2.NginxProxyList{},
partialObjectMetadataList,
&gatewayv1alpha3.BackendTLSPolicyList{},
&gatewayv1alpha2.TLSRouteList{},
diff --git a/internal/mode/static/state/change_processor.go b/internal/mode/static/state/change_processor.go
index 61d6475d9f..43ac0e73d7 100644
--- a/internal/mode/static/state/change_processor.go
+++ b/internal/mode/static/state/change_processor.go
@@ -109,7 +109,7 @@ func NewChangeProcessorImpl(cfg ChangeProcessorConfig) *ChangeProcessorImpl {
CRDMetadata: make(map[types.NamespacedName]*metav1.PartialObjectMetadata),
BackendTLSPolicies: make(map[types.NamespacedName]*v1alpha3.BackendTLSPolicy),
ConfigMaps: make(map[types.NamespacedName]*apiv1.ConfigMap),
- NginxProxies: make(map[types.NamespacedName]*ngfAPIv1alpha1.NginxProxy),
+ NginxProxies: make(map[types.NamespacedName]*ngfAPIv1alpha2.NginxProxy),
GRPCRoutes: make(map[types.NamespacedName]*v1.GRPCRoute),
TLSRoutes: make(map[types.NamespacedName]*v1alpha2.TLSRoute),
NGFPolicies: make(map[graph.PolicyKey]policies.Policy),
@@ -203,7 +203,7 @@ func NewChangeProcessorImpl(cfg ChangeProcessorConfig) *ChangeProcessorImpl {
predicate: annotationChangedPredicate{annotation: gatewayclass.BundleVersionAnnotation},
},
{
- gvk: cfg.MustExtractGVK(&ngfAPIv1alpha1.NginxProxy{}),
+ gvk: cfg.MustExtractGVK(&ngfAPIv1alpha2.NginxProxy{}),
store: newObjectStoreMapAdapter(clusterStore.NginxProxies),
predicate: funcPredicate{stateChanged: isReferenced},
},
diff --git a/internal/mode/static/state/change_processor_test.go b/internal/mode/static/state/change_processor_test.go
index 7211a5f045..f1768ebb11 100644
--- a/internal/mode/static/state/change_processor_test.go
+++ b/internal/mode/static/state/change_processor_test.go
@@ -2291,56 +2291,135 @@ var _ = Describe("ChangeProcessor", func() {
})
Describe("NginxProxy resource changes", Ordered, func() {
- paramGC := gc.DeepCopy()
- paramGC.Spec.ParametersRef = &v1beta1.ParametersReference{
- Group: ngfAPIv1alpha1.GroupName,
- Kind: kinds.NginxProxy,
- Name: "np",
- }
+ Context("referenced by a GatewayClass", func() {
+ paramGC := gc.DeepCopy()
+ paramGC.Spec.ParametersRef = &v1beta1.ParametersReference{
+ Group: ngfAPIv1alpha1.GroupName,
+ Kind: kinds.NginxProxy,
+ Name: "np",
+ Namespace: helpers.GetPointer[v1.Namespace]("test"),
+ }
- np := &ngfAPIv1alpha1.NginxProxy{
- ObjectMeta: metav1.ObjectMeta{
- Name: "np",
- },
- }
+ np := &ngfAPIv1alpha2.NginxProxy{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "np",
+ Namespace: "test",
+ },
+ }
- npUpdated := &ngfAPIv1alpha1.NginxProxy{
- ObjectMeta: metav1.ObjectMeta{
- Name: "np",
- },
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- Telemetry: &ngfAPIv1alpha1.Telemetry{
- Exporter: &ngfAPIv1alpha1.TelemetryExporter{
- Endpoint: "my-svc:123",
- BatchSize: helpers.GetPointer(int32(512)),
- BatchCount: helpers.GetPointer(int32(4)),
- Interval: helpers.GetPointer(ngfAPIv1alpha1.Duration("5s")),
+ npUpdated := &ngfAPIv1alpha2.NginxProxy{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "np",
+ Namespace: "test",
+ },
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ Exporter: &ngfAPIv1alpha2.TelemetryExporter{
+ Endpoint: helpers.GetPointer("my-svc:123"),
+ BatchSize: helpers.GetPointer(int32(512)),
+ BatchCount: helpers.GetPointer(int32(4)),
+ Interval: helpers.GetPointer(ngfAPIv1alpha1.Duration("5s")),
+ },
},
},
- },
- }
- It("handles upserts for an NginxProxy", func() {
- processor.CaptureUpsertChange(np)
- processor.CaptureUpsertChange(paramGC)
+ }
+ It("handles upserts for an NginxProxy", func() {
+ processor.CaptureUpsertChange(np)
+ processor.CaptureUpsertChange(paramGC)
- changed, graph := processor.Process()
- Expect(changed).To(Equal(state.ClusterStateChange))
- Expect(graph.NginxProxy.Source).To(Equal(np))
- })
- It("captures changes for an NginxProxy", func() {
- processor.CaptureUpsertChange(npUpdated)
- processor.CaptureUpsertChange(paramGC)
+ changed, graph := processor.Process()
+ Expect(changed).To(Equal(state.ClusterStateChange))
+ Expect(graph.GatewayClass.NginxProxy.Source).To(Equal(np))
+ })
+ It("captures changes for an NginxProxy", func() {
+ processor.CaptureUpsertChange(npUpdated)
+ processor.CaptureUpsertChange(paramGC)
- changed, graph := processor.Process()
- Expect(changed).To(Equal(state.ClusterStateChange))
- Expect(graph.NginxProxy.Source).To(Equal(npUpdated))
+ changed, graph := processor.Process()
+ Expect(changed).To(Equal(state.ClusterStateChange))
+ Expect(graph.GatewayClass.NginxProxy.Source).To(Equal(npUpdated))
+ })
+ It("handles deletes for an NginxProxy", func() {
+ processor.CaptureDeleteChange(np, client.ObjectKeyFromObject(np))
+
+ changed, graph := processor.Process()
+ Expect(changed).To(Equal(state.ClusterStateChange))
+ Expect(graph.GatewayClass.NginxProxy).To(BeNil())
+ })
})
- It("handles deletes for an NginxProxy", func() {
- processor.CaptureDeleteChange(np, client.ObjectKeyFromObject(np))
+ Context("referenced by a Gateway", func() {
+ paramGW := &v1.Gateway{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: "test",
+ Name: "param-gw",
+ Generation: 1,
+ },
+ Spec: v1.GatewaySpec{
+ GatewayClassName: gcName,
+ Listeners: []v1.Listener{
+ {
+ Name: httpListenerName,
+ Hostname: nil,
+ Port: 80,
+ Protocol: v1.HTTPProtocolType,
+ },
+ },
+ Infrastructure: &v1.GatewayInfrastructure{
+ ParametersRef: &v1.LocalParametersReference{
+ Group: ngfAPIv1alpha1.GroupName,
+ Kind: kinds.NginxProxy,
+ Name: "np-gw",
+ },
+ },
+ },
+ }
- changed, graph := processor.Process()
- Expect(changed).To(Equal(state.ClusterStateChange))
- Expect(graph.NginxProxy).To(BeNil())
+ np := &ngfAPIv1alpha2.NginxProxy{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "np-gw",
+ Namespace: "test",
+ },
+ }
+
+ npUpdated := &ngfAPIv1alpha2.NginxProxy{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "np-gw",
+ Namespace: "test",
+ },
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ Exporter: &ngfAPIv1alpha2.TelemetryExporter{
+ Endpoint: helpers.GetPointer("my-svc:123"),
+ BatchSize: helpers.GetPointer(int32(512)),
+ BatchCount: helpers.GetPointer(int32(4)),
+ Interval: helpers.GetPointer(ngfAPIv1alpha1.Duration("5s")),
+ },
+ },
+ },
+ }
+ It("handles upserts for an NginxProxy", func() {
+ processor.CaptureUpsertChange(np)
+ processor.CaptureUpsertChange(paramGW)
+
+ changed, graph := processor.Process()
+ Expect(changed).To(Equal(state.ClusterStateChange))
+ Expect(graph.Gateway.NginxProxy.Source).To(Equal(np))
+ })
+ It("captures changes for an NginxProxy", func() {
+ processor.CaptureUpsertChange(npUpdated)
+ processor.CaptureUpsertChange(paramGW)
+
+ changed, graph := processor.Process()
+ Expect(changed).To(Equal(state.ClusterStateChange))
+ Expect(graph.Gateway.NginxProxy.Source).To(Equal(npUpdated))
+ })
+ It("handles deletes for an NginxProxy", func() {
+ processor.CaptureDeleteChange(np, client.ObjectKeyFromObject(np))
+
+ changed, graph := processor.Process()
+ Expect(changed).To(Equal(state.ClusterStateChange))
+ Expect(graph.Gateway.NginxProxy).To(BeNil())
+ })
})
})
@@ -2633,7 +2712,7 @@ var _ = Describe("ChangeProcessor", func() {
secret, secretUpdated, unrelatedSecret, barSecret, barSecretUpdated *apiv1.Secret
cm, cmUpdated, unrelatedCM *apiv1.ConfigMap
btls, btlsUpdated *v1alpha3.BackendTLSPolicy
- np, npUpdated *ngfAPIv1alpha1.NginxProxy
+ np, npUpdated *ngfAPIv1alpha2.NginxProxy
)
BeforeEach(OncePerOrdered, func() {
@@ -2932,12 +3011,12 @@ var _ = Describe("ChangeProcessor", func() {
btlsUpdated = btls.DeepCopy()
npNsName = types.NamespacedName{Name: "np-1"}
- np = &ngfAPIv1alpha1.NginxProxy{
+ np = &ngfAPIv1alpha2.NginxProxy{
ObjectMeta: metav1.ObjectMeta{
Name: npNsName.Name,
},
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- Telemetry: &ngfAPIv1alpha1.Telemetry{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
ServiceName: helpers.GetPointer("my-svc"),
},
},
@@ -3012,7 +3091,7 @@ var _ = Describe("ChangeProcessor", func() {
processor.CaptureDeleteChange(&v1beta1.ReferenceGrant{}, rgNsName)
processor.CaptureDeleteChange(&v1alpha3.BackendTLSPolicy{}, btlsNsName)
processor.CaptureDeleteChange(&apiv1.ConfigMap{}, cmNsName)
- processor.CaptureDeleteChange(&ngfAPIv1alpha1.NginxProxy{}, npNsName)
+ processor.CaptureDeleteChange(&ngfAPIv1alpha2.NginxProxy{}, npNsName)
// these are non-changing changes
processor.CaptureUpsertChange(gw2)
diff --git a/internal/mode/static/state/conditions/conditions.go b/internal/mode/static/state/conditions/conditions.go
index 84ba2d971a..00feac778a 100644
--- a/internal/mode/static/state/conditions/conditions.go
+++ b/internal/mode/static/state/conditions/conditions.go
@@ -87,6 +87,10 @@ const (
// parametersRef resource does not exist.
GatewayClassReasonParamsRefNotFound v1.GatewayClassConditionReason = "ParametersRefNotFound"
+ // GatewayClassReasonParamsRefInvalid is used with the "GatewayClassResolvedRefs" condition when the
+ // parametersRef resource is invalid.
+ GatewayClassReasonParamsRefInvalid v1.GatewayClassConditionReason = "ParametersRefInvalid"
+
// PolicyReasonNginxProxyConfigNotSet is used with the "PolicyAccepted" condition when the
// NginxProxy resource is missing or invalid.
PolicyReasonNginxProxyConfigNotSet v1alpha2.PolicyConditionReason = "NginxProxyConfigNotSet"
@@ -106,6 +110,21 @@ const (
// GatewayIgnoredReason is used with v1.RouteConditionAccepted when the route references a Gateway that is ignored
// by NGF.
GatewayIgnoredReason v1.RouteConditionReason = "GatewayIgnored"
+
+ // GatewayResolvedRefs condition indicates whether the controller was able to resolve the
+ // parametersRef on the Gateway.
+ GatewayResolvedRefs v1.GatewayConditionType = "ResolvedRefs"
+
+ // GatewayReasonResolvedRefs is used with the "GatewayResolvedRefs" condition when the condition is true.
+ GatewayReasonResolvedRefs v1.GatewayConditionReason = "ResolvedRefs"
+
+ // GatewayReasonParamsRefNotFound is used with the "GatewayResolvedRefs" condition when the
+ // parametersRef resource does not exist.
+ GatewayReasonParamsRefNotFound v1.GatewayConditionReason = "ParametersRefNotFound"
+
+ // GatewayReasonParamsRefInvalid is used with the "GatewayResolvedRefs" condition when the
+ // parametersRef resource is invalid.
+ GatewayReasonParamsRefInvalid v1.GatewayConditionReason = "ParametersRefInvalid"
)
// NewRouteNotAcceptedGatewayIgnored returns a Condition that indicates that the Route is not accepted by the Gateway
@@ -514,7 +533,7 @@ func NewGatewayClassResolvedRefs() conditions.Condition {
Type: string(GatewayClassResolvedRefs),
Status: metav1.ConditionTrue,
Reason: string(GatewayClassReasonResolvedRefs),
- Message: "parametersRef resource is resolved",
+ Message: "ParametersRef resource is resolved",
}
}
@@ -525,7 +544,18 @@ func NewGatewayClassRefNotFound() conditions.Condition {
Type: string(GatewayClassResolvedRefs),
Status: metav1.ConditionFalse,
Reason: string(GatewayClassReasonParamsRefNotFound),
- Message: "parametersRef resource could not be found",
+ Message: "ParametersRef resource could not be found",
+ }
+}
+
+// NewGatewayClassRefInvalid returns a Condition that indicates that the parametersRef
+// on the GatewayClass could not be resolved because the resource it references is invalid.
+func NewGatewayClassRefInvalid(msg string) conditions.Condition {
+ return conditions.Condition{
+ Type: string(GatewayClassResolvedRefs),
+ Status: metav1.ConditionFalse,
+ Reason: string(GatewayClassReasonParamsRefInvalid),
+ Message: msg,
}
}
@@ -537,7 +567,7 @@ func NewGatewayClassInvalidParameters(msg string) conditions.Condition {
Type: string(v1.GatewayClassConditionStatusAccepted),
Status: metav1.ConditionTrue,
Reason: string(v1.GatewayClassReasonInvalidParameters),
- Message: fmt.Sprintf("GatewayClass is accepted, but parametersRef is ignored due to an error: %s", msg),
+ Message: fmt.Sprintf("GatewayClass is accepted, but ParametersRef is ignored due to an error: %s", msg),
}
}
@@ -684,6 +714,51 @@ func NewNginxGatewayInvalid(msg string) conditions.Condition {
}
}
+// NewGatewayResolvedRefs returns a Condition that indicates that the parametersRef
+// on the Gateway is resolved.
+func NewGatewayResolvedRefs() conditions.Condition {
+ return conditions.Condition{
+ Type: string(GatewayResolvedRefs),
+ Status: metav1.ConditionTrue,
+ Reason: string(GatewayReasonResolvedRefs),
+ Message: "ParametersRef resource is resolved",
+ }
+}
+
+// NewGatewayRefNotFound returns a Condition that indicates that the parametersRef
+// on the Gateway could not be resolved.
+func NewGatewayRefNotFound() conditions.Condition {
+ return conditions.Condition{
+ Type: string(GatewayResolvedRefs),
+ Status: metav1.ConditionFalse,
+ Reason: string(GatewayReasonParamsRefNotFound),
+ Message: "ParametersRef resource could not be found",
+ }
+}
+
+// NewGatewayRefInvalid returns a Condition that indicates that the parametersRef
+// on the Gateway could not be resolved because the referenced resource is invalid.
+func NewGatewayRefInvalid(msg string) conditions.Condition {
+ return conditions.Condition{
+ Type: string(GatewayResolvedRefs),
+ Status: metav1.ConditionFalse,
+ Reason: string(GatewayReasonParamsRefInvalid),
+ Message: msg,
+ }
+}
+
+// NewGatewayInvalidParameters returns a Condition that indicates that the Gateway has invalid parameters.
+// We are allowing Accepted to still be true to prevent nullifying the entire Gateway config if a parametersRef
+// is updated to something invalid.
+func NewGatewayInvalidParameters(msg string) conditions.Condition {
+ return conditions.Condition{
+ Type: string(v1.GatewayConditionAccepted),
+ Status: metav1.ConditionTrue,
+ Reason: string(v1.GatewayReasonInvalidParameters),
+ Message: fmt.Sprintf("Gateway is accepted, but ParametersRef is ignored due to an error: %s", msg),
+ }
+}
+
// NewPolicyAccepted returns a Condition that indicates that the Policy is accepted.
func NewPolicyAccepted() conditions.Condition {
return conditions.Condition{
diff --git a/internal/mode/static/state/dataplane/configuration.go b/internal/mode/static/state/dataplane/configuration.go
index 3b4760d331..2b74d10a8c 100644
--- a/internal/mode/static/state/dataplane/configuration.go
+++ b/internal/mode/static/state/dataplane/configuration.go
@@ -4,6 +4,7 @@ import (
"context"
"encoding/base64"
"fmt"
+ "slices"
"sort"
apiv1 "k8s.io/api/core/v1"
@@ -786,22 +787,42 @@ func generateCertBundleID(configMap types.NamespacedName) CertBundleID {
return CertBundleID(fmt.Sprintf("cert_bundle_%s_%s", configMap.Namespace, configMap.Name))
}
+func telemetryEnabled(gw *graph.Gateway) bool {
+ if gw == nil {
+ return false
+ }
+
+ if gw.EffectiveNginxProxy == nil || gw.EffectiveNginxProxy.Telemetry == nil {
+ return false
+ }
+
+ tel := gw.EffectiveNginxProxy.Telemetry
+
+ if slices.Contains(tel.DisabledFeatures, ngfAPIv1alpha2.DisableTracing) {
+ return false
+ }
+
+ if tel.Exporter == nil || tel.Exporter.Endpoint == nil {
+ return false
+ }
+
+ return true
+}
+
// buildTelemetry generates the Otel configuration.
func buildTelemetry(g *graph.Graph) Telemetry {
- if g.NginxProxy == nil || !g.NginxProxy.Valid ||
- g.NginxProxy.Source.Spec.Telemetry == nil ||
- g.NginxProxy.Source.Spec.Telemetry.Exporter == nil {
+ if !telemetryEnabled(g.Gateway) {
return Telemetry{}
}
serviceName := fmt.Sprintf("ngf:%s:%s", g.Gateway.Source.Namespace, g.Gateway.Source.Name)
- telemetry := g.NginxProxy.Source.Spec.Telemetry
+ telemetry := g.Gateway.EffectiveNginxProxy.Telemetry
if telemetry.ServiceName != nil {
serviceName = serviceName + ":" + *telemetry.ServiceName
}
tel := Telemetry{
- Endpoint: telemetry.Exporter.Endpoint,
+ Endpoint: *telemetry.Exporter.Endpoint, // safe to deref here since we verified that telemetry is enabled
ServiceName: serviceName,
}
@@ -865,41 +886,44 @@ func buildBaseHTTPConfig(g *graph.Graph) BaseHTTPConfig {
IPFamily: Dual,
Snippets: buildSnippetsForContext(g.SnippetsFilters, ngfAPIv1alpha1.NginxContextHTTP),
}
- if g.NginxProxy == nil || !g.NginxProxy.Valid {
+
+ // safe to access EffectiveNginxProxy since we only call this function when the Gateway is not nil.
+ np := g.Gateway.EffectiveNginxProxy
+ if np == nil {
return baseConfig
}
- if g.NginxProxy.Source.Spec.DisableHTTP2 {
+ if np.DisableHTTP2 != nil && *np.DisableHTTP2 {
baseConfig.HTTP2 = false
}
- if g.NginxProxy.Source.Spec.IPFamily != nil {
- switch *g.NginxProxy.Source.Spec.IPFamily {
- case ngfAPIv1alpha1.IPv4:
+ if np.IPFamily != nil {
+ switch *np.IPFamily {
+ case ngfAPIv1alpha2.IPv4:
baseConfig.IPFamily = IPv4
- case ngfAPIv1alpha1.IPv6:
+ case ngfAPIv1alpha2.IPv6:
baseConfig.IPFamily = IPv6
}
}
- if g.NginxProxy.Source.Spec.RewriteClientIP != nil {
- if g.NginxProxy.Source.Spec.RewriteClientIP.Mode != nil {
- switch *g.NginxProxy.Source.Spec.RewriteClientIP.Mode {
- case ngfAPIv1alpha1.RewriteClientIPModeProxyProtocol:
+ if np.RewriteClientIP != nil {
+ if np.RewriteClientIP.Mode != nil {
+ switch *np.RewriteClientIP.Mode {
+ case ngfAPIv1alpha2.RewriteClientIPModeProxyProtocol:
baseConfig.RewriteClientIPSettings.Mode = RewriteIPModeProxyProtocol
- case ngfAPIv1alpha1.RewriteClientIPModeXForwardedFor:
+ case ngfAPIv1alpha2.RewriteClientIPModeXForwardedFor:
baseConfig.RewriteClientIPSettings.Mode = RewriteIPModeXForwardedFor
}
}
- if len(g.NginxProxy.Source.Spec.RewriteClientIP.TrustedAddresses) > 0 {
+ if len(np.RewriteClientIP.TrustedAddresses) > 0 {
baseConfig.RewriteClientIPSettings.TrustedAddresses = convertAddresses(
- g.NginxProxy.Source.Spec.RewriteClientIP.TrustedAddresses,
+ np.RewriteClientIP.TrustedAddresses,
)
}
- if g.NginxProxy.Source.Spec.RewriteClientIP.SetIPRecursively != nil {
- baseConfig.RewriteClientIPSettings.IPRecursive = *g.NginxProxy.Source.Spec.RewriteClientIP.SetIPRecursively
+ if np.RewriteClientIP.SetIPRecursively != nil {
+ baseConfig.RewriteClientIPSettings.IPRecursive = *np.RewriteClientIP.SetIPRecursively
}
}
@@ -963,7 +987,7 @@ func buildPolicies(graphPolicies []*graph.Policy) []policies.Policy {
return finalPolicies
}
-func convertAddresses(addresses []ngfAPIv1alpha1.RewriteClientIPAddress) []string {
+func convertAddresses(addresses []ngfAPIv1alpha2.RewriteClientIPAddress) []string {
trustedAddresses := make([]string, len(addresses))
for i, addr := range addresses {
trustedAddresses[i] = addr.Value
@@ -974,10 +998,14 @@ func convertAddresses(addresses []ngfAPIv1alpha1.RewriteClientIPAddress) []strin
func buildLogging(g *graph.Graph) Logging {
logSettings := Logging{ErrorLevel: defaultErrorLogLevel}
- ngfProxy := g.NginxProxy
- if ngfProxy != nil && ngfProxy.Source.Spec.Logging != nil {
- if ngfProxy.Source.Spec.Logging.ErrorLevel != nil {
- logSettings.ErrorLevel = string(*ngfProxy.Source.Spec.Logging.ErrorLevel)
+ if g.Gateway == nil || g.Gateway.EffectiveNginxProxy == nil {
+ return logSettings
+ }
+
+ ngfProxy := g.Gateway.EffectiveNginxProxy
+ if ngfProxy.Logging != nil {
+ if ngfProxy.Logging.ErrorLevel != nil {
+ logSettings.ErrorLevel = string(*ngfProxy.Logging.ErrorLevel)
}
}
@@ -1001,11 +1029,15 @@ func buildAuxiliarySecrets(
func buildNginxPlus(g *graph.Graph) NginxPlus {
nginxPlusSettings := NginxPlus{AllowedAddresses: []string{"127.0.0.1"}}
- ngfProxy := g.NginxProxy
- if ngfProxy != nil && ngfProxy.Source.Spec.NginxPlus != nil {
- if ngfProxy.Source.Spec.NginxPlus.AllowedAddresses != nil {
- addresses := make([]string, 0, len(ngfProxy.Source.Spec.NginxPlus.AllowedAddresses))
- for _, addr := range ngfProxy.Source.Spec.NginxPlus.AllowedAddresses {
+ if g.Gateway == nil || g.Gateway.EffectiveNginxProxy == nil {
+ return nginxPlusSettings
+ }
+
+ ngfProxy := g.Gateway.EffectiveNginxProxy
+ if ngfProxy.NginxPlus != nil {
+ if ngfProxy.NginxPlus.AllowedAddresses != nil {
+ addresses := make([]string, 0, len(ngfProxy.NginxPlus.AllowedAddresses))
+ for _, addr := range ngfProxy.NginxPlus.AllowedAddresses {
addresses = append(addresses, addr.Value)
}
diff --git a/internal/mode/static/state/dataplane/configuration_test.go b/internal/mode/static/state/dataplane/configuration_test.go
index 0117afecdd..db1f59e175 100644
--- a/internal/mode/static/state/dataplane/configuration_test.go
+++ b/internal/mode/static/state/dataplane/configuration_test.go
@@ -827,43 +827,26 @@ func TestBuildConfiguration(t *testing.T) {
},
}
- nginxProxy := &graph.NginxProxy{
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- Telemetry: &ngfAPIv1alpha1.Telemetry{
- Exporter: &ngfAPIv1alpha1.TelemetryExporter{
- Endpoint: "my-otel.svc:4563",
- BatchSize: helpers.GetPointer(int32(512)),
- BatchCount: helpers.GetPointer(int32(4)),
- Interval: helpers.GetPointer(ngfAPIv1alpha1.Duration("5s")),
- },
- ServiceName: helpers.GetPointer("my-svc"),
- },
- DisableHTTP2: true,
- IPFamily: helpers.GetPointer(ngfAPIv1alpha1.Dual),
+ nginxProxy := &graph.EffectiveNginxProxy{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ Exporter: &ngfAPIv1alpha2.TelemetryExporter{
+ Endpoint: helpers.GetPointer("my-otel.svc:4563"),
+ BatchSize: helpers.GetPointer(int32(512)),
+ BatchCount: helpers.GetPointer(int32(4)),
+ Interval: helpers.GetPointer(ngfAPIv1alpha1.Duration("5s")),
},
+ ServiceName: helpers.GetPointer("my-svc"),
},
- Valid: true,
+ DisableHTTP2: helpers.GetPointer(true),
+ IPFamily: helpers.GetPointer(ngfAPIv1alpha2.Dual),
}
- nginxProxyIPv4 := &graph.NginxProxy{
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- Telemetry: &ngfAPIv1alpha1.Telemetry{},
- IPFamily: helpers.GetPointer(ngfAPIv1alpha1.IPv4),
- },
- },
- Valid: true,
+ nginxProxyIPv4 := &graph.EffectiveNginxProxy{
+ IPFamily: helpers.GetPointer(ngfAPIv1alpha2.IPv4),
}
- nginxProxyIPv6 := &graph.NginxProxy{
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- Telemetry: &ngfAPIv1alpha1.Telemetry{},
- IPFamily: helpers.GetPointer(ngfAPIv1alpha1.IPv6),
- },
- },
- Valid: true,
+ nginxProxyIPv6 := &graph.EffectiveNginxProxy{
+ IPFamily: helpers.GetPointer(ngfAPIv1alpha2.IPv6),
}
defaultConfig := Configuration{
@@ -2041,7 +2024,7 @@ func TestBuildConfiguration(t *testing.T) {
Valid: true,
Routes: map[graph.RouteKey]*graph.L7Route{},
})
- g.NginxProxy = nginxProxy
+ g.Gateway.EffectiveNginxProxy = nginxProxy
return g
}),
expConf: getModifiedExpectedConfiguration(func(conf Configuration) Configuration {
@@ -2059,42 +2042,7 @@ func TestBuildConfiguration(t *testing.T) {
conf.BaseHTTPConfig = BaseHTTPConfig{HTTP2: false, IPFamily: Dual}
return conf
}),
- msg: "NginxProxy with tracing config and http2 disabled",
- },
- {
- graph: getModifiedGraph(func(g *graph.Graph) *graph.Graph {
- g.Gateway.Source.ObjectMeta = metav1.ObjectMeta{
- Name: "gw",
- Namespace: "ns",
- }
- g.Gateway.Listeners = append(g.Gateway.Listeners, &graph.Listener{
- Name: "listener-80-1",
- Source: listener80,
- Valid: true,
- Routes: map[graph.RouteKey]*graph.L7Route{},
- })
- g.NginxProxy = &graph.NginxProxy{
- Valid: false,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- DisableHTTP2: true,
- IPFamily: helpers.GetPointer(ngfAPIv1alpha1.Dual),
- Telemetry: &ngfAPIv1alpha1.Telemetry{
- Exporter: &ngfAPIv1alpha1.TelemetryExporter{
- Endpoint: "some-endpoint",
- },
- },
- },
- },
- }
- return g
- }),
- expConf: getModifiedExpectedConfiguration(func(conf Configuration) Configuration {
- conf.SSLServers = []VirtualServer{}
- conf.SSLKeyPairs = map[SSLKeyPairID]SSLKeyPair{}
- return conf
- }),
- msg: "invalid NginxProxy",
+ msg: "EffectiveNginxProxy with tracing config and http2 disabled",
},
{
graph: getModifiedGraph(func(g *graph.Graph) *graph.Graph {
@@ -2203,7 +2151,7 @@ func TestBuildConfiguration(t *testing.T) {
Valid: true,
Routes: map[graph.RouteKey]*graph.L7Route{},
})
- g.NginxProxy = nginxProxyIPv4
+ g.Gateway.EffectiveNginxProxy = nginxProxyIPv4
return g
}),
expConf: getModifiedExpectedConfiguration(func(conf Configuration) Configuration {
@@ -2212,7 +2160,7 @@ func TestBuildConfiguration(t *testing.T) {
conf.BaseHTTPConfig = BaseHTTPConfig{HTTP2: true, IPFamily: IPv4}
return conf
}),
- msg: "NginxProxy with IPv4 IPFamily and no routes",
+ msg: "GatewayClass has NginxProxy with IPv4 IPFamily and no routes",
},
{
graph: getModifiedGraph(func(g *graph.Graph) *graph.Graph {
@@ -2226,7 +2174,7 @@ func TestBuildConfiguration(t *testing.T) {
Valid: true,
Routes: map[graph.RouteKey]*graph.L7Route{},
})
- g.NginxProxy = nginxProxyIPv6
+ g.Gateway.EffectiveNginxProxy = nginxProxyIPv6
return g
}),
expConf: getModifiedExpectedConfiguration(func(conf Configuration) Configuration {
@@ -2235,7 +2183,7 @@ func TestBuildConfiguration(t *testing.T) {
conf.BaseHTTPConfig = BaseHTTPConfig{HTTP2: true, IPFamily: IPv6}
return conf
}),
- msg: "NginxProxy with IPv6 IPFamily and no routes",
+ msg: "GatewayClass has NginxProxy with IPv6 IPFamily and no routes",
},
{
graph: getModifiedGraph(func(g *graph.Graph) *graph.Graph {
@@ -2249,21 +2197,16 @@ func TestBuildConfiguration(t *testing.T) {
Valid: true,
Routes: map[graph.RouteKey]*graph.L7Route{},
})
- g.NginxProxy = &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- RewriteClientIP: &ngfAPIv1alpha1.RewriteClientIP{
- SetIPRecursively: helpers.GetPointer(true),
- TrustedAddresses: []ngfAPIv1alpha1.RewriteClientIPAddress{
- {
- Type: ngfAPIv1alpha1.RewriteClientIPCIDRAddressType,
- Value: "1.1.1.1/32",
- },
- },
- Mode: helpers.GetPointer(ngfAPIv1alpha1.RewriteClientIPModeProxyProtocol),
+ g.Gateway.EffectiveNginxProxy = &graph.EffectiveNginxProxy{
+ RewriteClientIP: &ngfAPIv1alpha2.RewriteClientIP{
+ SetIPRecursively: helpers.GetPointer(true),
+ TrustedAddresses: []ngfAPIv1alpha2.RewriteClientIPAddress{
+ {
+ Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType,
+ Value: "1.1.1.1/32",
},
},
+ Mode: helpers.GetPointer(ngfAPIv1alpha2.RewriteClientIPModeProxyProtocol),
},
}
return g
@@ -2282,7 +2225,7 @@ func TestBuildConfiguration(t *testing.T) {
}
return conf
}),
- msg: "NginxProxy with rewriteClientIP details set",
+ msg: "GatewayClass has NginxProxy with rewriteClientIP details set",
},
{
graph: getModifiedGraph(func(g *graph.Graph) *graph.Graph {
@@ -2296,12 +2239,9 @@ func TestBuildConfiguration(t *testing.T) {
Valid: true,
Routes: map[graph.RouteKey]*graph.L7Route{},
})
- g.NginxProxy = &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- Logging: &ngfAPIv1alpha1.NginxLogging{ErrorLevel: helpers.GetPointer(ngfAPIv1alpha1.NginxLogLevelDebug)},
- },
+ g.Gateway.EffectiveNginxProxy = &graph.EffectiveNginxProxy{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelDebug),
},
}
return g
@@ -2312,7 +2252,7 @@ func TestBuildConfiguration(t *testing.T) {
conf.Logging = Logging{ErrorLevel: "debug"}
return conf
}),
- msg: "NginxProxy with error log level set to debug",
+ msg: "GatewayClass has NginxProxy with error log level set to debug",
},
{
graph: getModifiedGraph(func(g *graph.Graph) *graph.Graph {
@@ -2362,16 +2302,11 @@ func TestBuildConfiguration(t *testing.T) {
Valid: true,
Routes: map[graph.RouteKey]*graph.L7Route{},
})
- g.NginxProxy = &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- NginxPlus: &ngfAPIv1alpha1.NginxPlus{
- AllowedAddresses: []ngfAPIv1alpha1.NginxPlusAllowAddress{
- {Type: ngfAPIv1alpha1.NginxPlusAllowIPAddressType, Value: "127.0.0.3"},
- {Type: ngfAPIv1alpha1.NginxPlusAllowIPAddressType, Value: "25.0.0.3"},
- },
- },
+ g.Gateway.EffectiveNginxProxy = &graph.EffectiveNginxProxy{
+ NginxPlus: &ngfAPIv1alpha2.NginxPlus{
+ AllowedAddresses: []ngfAPIv1alpha2.NginxPlusAllowAddress{
+ {Type: ngfAPIv1alpha2.NginxPlusAllowIPAddressType, Value: "127.0.0.3"},
+ {Type: ngfAPIv1alpha2.NginxPlusAllowIPAddressType, Value: "25.0.0.3"},
},
},
}
@@ -2456,16 +2391,11 @@ func TestBuildConfiguration_Plus(t *testing.T) {
Valid: true,
Routes: map[graph.RouteKey]*graph.L7Route{},
})
- g.NginxProxy = &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- NginxPlus: &ngfAPIv1alpha1.NginxPlus{
- AllowedAddresses: []ngfAPIv1alpha1.NginxPlusAllowAddress{
- {Type: ngfAPIv1alpha1.NginxPlusAllowIPAddressType, Value: "127.0.0.3"},
- {Type: ngfAPIv1alpha1.NginxPlusAllowIPAddressType, Value: "25.0.0.3"},
- },
- },
+ g.Gateway.EffectiveNginxProxy = &graph.EffectiveNginxProxy{
+ NginxPlus: &ngfAPIv1alpha2.NginxPlus{
+ AllowedAddresses: []ngfAPIv1alpha2.NginxPlusAllowAddress{
+ {Type: ngfAPIv1alpha2.NginxPlusAllowIPAddressType, Value: "127.0.0.3"},
+ {Type: ngfAPIv1alpha2.NginxPlusAllowIPAddressType, Value: "25.0.0.3"},
},
},
}
@@ -3417,24 +3347,19 @@ func TestConvertBackendTLS(t *testing.T) {
func TestBuildTelemetry(t *testing.T) {
t.Parallel()
- telemetryConfigured := &graph.NginxProxy{
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- Telemetry: &ngfAPIv1alpha1.Telemetry{
- Exporter: &ngfAPIv1alpha1.TelemetryExporter{
- Endpoint: "my-otel.svc:4563",
- BatchSize: helpers.GetPointer(int32(512)),
- BatchCount: helpers.GetPointer(int32(4)),
- Interval: helpers.GetPointer(ngfAPIv1alpha1.Duration("5s")),
- },
- ServiceName: helpers.GetPointer("my-svc"),
- SpanAttributes: []ngfAPIv1alpha1.SpanAttribute{
- {Key: "key", Value: "value"},
- },
- },
+ telemetryConfigured := &graph.EffectiveNginxProxy{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ Exporter: &ngfAPIv1alpha2.TelemetryExporter{
+ Endpoint: helpers.GetPointer("my-otel.svc:4563"),
+ BatchSize: helpers.GetPointer(int32(512)),
+ BatchCount: helpers.GetPointer(int32(4)),
+ Interval: helpers.GetPointer(ngfAPIv1alpha1.Duration("5s")),
+ },
+ ServiceName: helpers.GetPointer("my-svc"),
+ SpanAttributes: []ngfAPIv1alpha1.SpanAttribute{
+ {Key: "key", Value: "value"},
},
},
- Valid: true,
}
createTelemetry := func() Telemetry {
@@ -3460,10 +3385,24 @@ func TestBuildTelemetry(t *testing.T) {
msg string
expTelemetry Telemetry
}{
+ {
+ g: &graph.Graph{},
+ expTelemetry: Telemetry{},
+ msg: "nil Gateway",
+ },
+ {
+ g: &graph.Graph{
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: nil,
+ },
+ },
+ expTelemetry: Telemetry{},
+ msg: "nil effective NginxProxy",
+ },
{
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Source: &ngfAPIv1alpha1.NginxProxy{},
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{},
},
},
expTelemetry: Telemetry{},
@@ -3471,19 +3410,49 @@ func TestBuildTelemetry(t *testing.T) {
},
{
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- Telemetry: &ngfAPIv1alpha1.Telemetry{
- Exporter: &ngfAPIv1alpha1.TelemetryExporter{},
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ Exporter: &ngfAPIv1alpha2.TelemetryExporter{
+ Endpoint: helpers.GetPointer("my-otel.svc:4563"),
+ },
+ DisabledFeatures: []ngfAPIv1alpha2.DisableTelemetryFeature{
+ ngfAPIv1alpha2.DisableTracing,
+ },
+ },
+ },
+ },
+ },
+ expTelemetry: Telemetry{},
+ msg: "Telemetry disabled explicitly",
+ },
+ {
+ g: &graph.Graph{
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ Exporter: nil,
+ },
+ },
+ },
+ },
+ expTelemetry: Telemetry{},
+ msg: "Telemetry disabled implicitly (nil exporter)",
+ },
+ {
+ g: &graph.Graph{
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ Exporter: &ngfAPIv1alpha2.TelemetryExporter{
+ Endpoint: nil,
},
},
},
- Valid: false,
},
},
expTelemetry: Telemetry{},
- msg: "Invalid NginxProxy configured",
+ msg: "Telemetry disabled implicitly (nil exporter endpoint)",
},
{
g: &graph.Graph{
@@ -3494,8 +3463,8 @@ func TestBuildTelemetry(t *testing.T) {
Namespace: "ns",
},
},
+ EffectiveNginxProxy: telemetryConfigured,
},
- NginxProxy: telemetryConfigured,
},
expTelemetry: createTelemetry(),
msg: "Telemetry configured",
@@ -3509,8 +3478,8 @@ func TestBuildTelemetry(t *testing.T) {
Namespace: "ns",
},
},
+ EffectiveNginxProxy: telemetryConfigured,
},
- NginxProxy: telemetryConfigured,
NGFPolicies: map[graph.PolicyKey]*graph.Policy{
{NsName: types.NamespacedName{Name: "obsPolicy"}}: {
Source: &ngfAPIv1alpha2.ObservabilityPolicy{
@@ -3544,8 +3513,8 @@ func TestBuildTelemetry(t *testing.T) {
Namespace: "ns",
},
},
+ EffectiveNginxProxy: telemetryConfigured,
},
- NginxProxy: telemetryConfigured,
NGFPolicies: map[graph.PolicyKey]*graph.Policy{
{NsName: types.NamespacedName{Name: "obsPolicy"}}: {
Source: &ngfAPIv1alpha2.ObservabilityPolicy{
@@ -3614,8 +3583,8 @@ func TestBuildTelemetry(t *testing.T) {
Namespace: "ns",
},
},
+ EffectiveNginxProxy: telemetryConfigured,
},
- NginxProxy: telemetryConfigured,
NGFPolicies: map[graph.PolicyKey]*graph.Policy{
{NsName: types.NamespacedName{Name: "obsPolicy"}}: {
Source: &ngfAPIv1alpha2.ObservabilityPolicy{
@@ -4051,9 +4020,8 @@ func TestBuildRewriteIPSettings(t *testing.T) {
{
msg: "no rewrite IP settings configured",
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{},
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{},
},
},
expRewriteIPSettings: RewriteClientIPSettings{},
@@ -4061,20 +4029,17 @@ func TestBuildRewriteIPSettings(t *testing.T) {
{
msg: "rewrite IP settings configured with proxyProtocol",
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- RewriteClientIP: &ngfAPIv1alpha1.RewriteClientIP{
- Mode: helpers.GetPointer(ngfAPIv1alpha1.RewriteClientIPModeProxyProtocol),
- TrustedAddresses: []ngfAPIv1alpha1.RewriteClientIPAddress{
- {
- Type: ngfAPIv1alpha1.RewriteClientIPCIDRAddressType,
- Value: "10.9.9.4/32",
- },
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ RewriteClientIP: &ngfAPIv1alpha2.RewriteClientIP{
+ Mode: helpers.GetPointer(ngfAPIv1alpha2.RewriteClientIPModeProxyProtocol),
+ TrustedAddresses: []ngfAPIv1alpha2.RewriteClientIPAddress{
+ {
+ Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType,
+ Value: "10.9.9.4/32",
},
- SetIPRecursively: helpers.GetPointer(true),
},
+ SetIPRecursively: helpers.GetPointer(true),
},
},
},
@@ -4088,20 +4053,17 @@ func TestBuildRewriteIPSettings(t *testing.T) {
{
msg: "rewrite IP settings configured with xForwardedFor",
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- RewriteClientIP: &ngfAPIv1alpha1.RewriteClientIP{
- Mode: helpers.GetPointer(ngfAPIv1alpha1.RewriteClientIPModeXForwardedFor),
- TrustedAddresses: []ngfAPIv1alpha1.RewriteClientIPAddress{
- {
- Type: ngfAPIv1alpha1.RewriteClientIPCIDRAddressType,
- Value: "76.89.90.11/24",
- },
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ RewriteClientIP: &ngfAPIv1alpha2.RewriteClientIP{
+ Mode: helpers.GetPointer(ngfAPIv1alpha2.RewriteClientIPModeXForwardedFor),
+ TrustedAddresses: []ngfAPIv1alpha2.RewriteClientIPAddress{
+ {
+ Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType,
+ Value: "76.89.90.11/24",
},
- SetIPRecursively: helpers.GetPointer(true),
},
+ SetIPRecursively: helpers.GetPointer(true),
},
},
},
@@ -4115,32 +4077,29 @@ func TestBuildRewriteIPSettings(t *testing.T) {
{
msg: "rewrite IP settings configured with recursive set to false and multiple trusted addresses",
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- RewriteClientIP: &ngfAPIv1alpha1.RewriteClientIP{
- Mode: helpers.GetPointer(ngfAPIv1alpha1.RewriteClientIPModeXForwardedFor),
- TrustedAddresses: []ngfAPIv1alpha1.RewriteClientIPAddress{
- {
- Type: ngfAPIv1alpha1.RewriteClientIPCIDRAddressType,
- Value: "5.5.5.5/12",
- },
- {
- Type: ngfAPIv1alpha1.RewriteClientIPCIDRAddressType,
- Value: "1.1.1.1/26",
- },
- {
- Type: ngfAPIv1alpha1.RewriteClientIPCIDRAddressType,
- Value: "2.2.2.2/32",
- },
- {
- Type: ngfAPIv1alpha1.RewriteClientIPCIDRAddressType,
- Value: "3.3.3.3/24",
- },
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ RewriteClientIP: &ngfAPIv1alpha2.RewriteClientIP{
+ Mode: helpers.GetPointer(ngfAPIv1alpha2.RewriteClientIPModeXForwardedFor),
+ TrustedAddresses: []ngfAPIv1alpha2.RewriteClientIPAddress{
+ {
+ Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType,
+ Value: "5.5.5.5/12",
+ },
+ {
+ Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType,
+ Value: "1.1.1.1/26",
+ },
+ {
+ Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType,
+ Value: "2.2.2.2/32",
+ },
+ {
+ Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType,
+ Value: "3.3.3.3/24",
},
- SetIPRecursively: helpers.GetPointer(false),
},
+ SetIPRecursively: helpers.GetPointer(false),
},
},
},
@@ -4173,30 +4132,39 @@ func TestBuildLogging(t *testing.T) {
expLoggingSettings Logging
}{
{
- msg: "NginxProxy is nil",
- g: &graph.Graph{},
+ msg: "Gateway is nil",
+ g: &graph.Graph{
+ Gateway: nil,
+ },
+ expLoggingSettings: defaultLogging,
+ },
+ {
+ msg: "Gateway has no effective NginxProxy",
+ g: &graph.Graph{
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: nil,
+ },
+ },
expLoggingSettings: defaultLogging,
},
{
- msg: "NginxProxy does not specify log level",
+ msg: "Effective NginxProxy does not specify log level",
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{},
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ IPFamily: helpers.GetPointer(ngfAPIv1alpha2.Dual),
},
},
},
expLoggingSettings: defaultLogging,
},
{
- msg: "NginxProxy log level set to debug",
+ msg: "Effective NginxProxy log level set to debug",
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- Logging: &ngfAPIv1alpha1.NginxLogging{ErrorLevel: helpers.GetPointer(ngfAPIv1alpha1.NginxLogLevelDebug)},
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelDebug),
},
},
},
@@ -4204,13 +4172,12 @@ func TestBuildLogging(t *testing.T) {
expLoggingSettings: Logging{ErrorLevel: "debug"},
},
{
- msg: "NginxProxy log level set to info",
+ msg: "Effective NginxProxy log level set to info",
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- Logging: &ngfAPIv1alpha1.NginxLogging{ErrorLevel: helpers.GetPointer(ngfAPIv1alpha1.NginxLogLevelInfo)},
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelInfo),
},
},
},
@@ -4218,13 +4185,12 @@ func TestBuildLogging(t *testing.T) {
expLoggingSettings: Logging{ErrorLevel: defaultErrorLogLevel},
},
{
- msg: "NginxProxy log level set to notice",
+ msg: "Effective NginxProxy log level set to notice",
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- Logging: &ngfAPIv1alpha1.NginxLogging{ErrorLevel: helpers.GetPointer(ngfAPIv1alpha1.NginxLogLevelNotice)},
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelNotice),
},
},
},
@@ -4232,13 +4198,12 @@ func TestBuildLogging(t *testing.T) {
expLoggingSettings: Logging{ErrorLevel: "notice"},
},
{
- msg: "NginxProxy log level set to warn",
+ msg: "Effective NginxProxy log level set to warn",
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- Logging: &ngfAPIv1alpha1.NginxLogging{ErrorLevel: helpers.GetPointer(ngfAPIv1alpha1.NginxLogLevelWarn)},
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelWarn),
},
},
},
@@ -4246,13 +4211,12 @@ func TestBuildLogging(t *testing.T) {
expLoggingSettings: Logging{ErrorLevel: "warn"},
},
{
- msg: "NginxProxy log level set to error",
+ msg: "Effective NginxProxy log level set to error",
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- Logging: &ngfAPIv1alpha1.NginxLogging{ErrorLevel: helpers.GetPointer(ngfAPIv1alpha1.NginxLogLevelError)},
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelError),
},
},
},
@@ -4260,13 +4224,12 @@ func TestBuildLogging(t *testing.T) {
expLoggingSettings: Logging{ErrorLevel: "error"},
},
{
- msg: "NginxProxy log level set to crit",
+ msg: "Effective NginxProxy log level set to crit",
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- Logging: &ngfAPIv1alpha1.NginxLogging{ErrorLevel: helpers.GetPointer(ngfAPIv1alpha1.NginxLogLevelCrit)},
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelCrit),
},
},
},
@@ -4274,13 +4237,12 @@ func TestBuildLogging(t *testing.T) {
expLoggingSettings: Logging{ErrorLevel: "crit"},
},
{
- msg: "NginxProxy log level set to alert",
+ msg: "Effective NginxProxy log level set to alert",
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- Logging: &ngfAPIv1alpha1.NginxLogging{ErrorLevel: helpers.GetPointer(ngfAPIv1alpha1.NginxLogLevelAlert)},
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelAlert),
},
},
},
@@ -4288,13 +4250,12 @@ func TestBuildLogging(t *testing.T) {
expLoggingSettings: Logging{ErrorLevel: "alert"},
},
{
- msg: "NginxProxy log level set to emerg",
+ msg: "Effective NginxProxy log level set to emerg",
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- Logging: &ngfAPIv1alpha1.NginxLogging{ErrorLevel: helpers.GetPointer(ngfAPIv1alpha1.NginxLogLevelEmerg)},
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelEmerg),
},
},
},
@@ -4540,11 +4501,8 @@ func TestBuildNginxPlus(t *testing.T) {
{
msg: "NginxPlus default values are used when NginxProxy doesn't specify NginxPlus settings",
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{},
- },
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{},
},
},
expNginxPlus: defaultNginxPlus,
@@ -4552,14 +4510,11 @@ func TestBuildNginxPlus(t *testing.T) {
{
msg: "NginxProxy specifies one allowed address",
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- NginxPlus: &ngfAPIv1alpha1.NginxPlus{
- AllowedAddresses: []ngfAPIv1alpha1.NginxPlusAllowAddress{
- {Type: ngfAPIv1alpha1.NginxPlusAllowIPAddressType, Value: "127.0.0.3"},
- },
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ NginxPlus: &ngfAPIv1alpha2.NginxPlus{
+ AllowedAddresses: []ngfAPIv1alpha2.NginxPlusAllowAddress{
+ {Type: ngfAPIv1alpha2.NginxPlusAllowIPAddressType, Value: "127.0.0.3"},
},
},
},
@@ -4570,15 +4525,12 @@ func TestBuildNginxPlus(t *testing.T) {
{
msg: "NginxProxy specifies multiple allowed addresses",
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- NginxPlus: &ngfAPIv1alpha1.NginxPlus{
- AllowedAddresses: []ngfAPIv1alpha1.NginxPlusAllowAddress{
- {Type: ngfAPIv1alpha1.NginxPlusAllowIPAddressType, Value: "127.0.0.3"},
- {Type: ngfAPIv1alpha1.NginxPlusAllowIPAddressType, Value: "25.0.0.3"},
- },
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ NginxPlus: &ngfAPIv1alpha2.NginxPlus{
+ AllowedAddresses: []ngfAPIv1alpha2.NginxPlusAllowAddress{
+ {Type: ngfAPIv1alpha2.NginxPlusAllowIPAddressType, Value: "127.0.0.3"},
+ {Type: ngfAPIv1alpha2.NginxPlusAllowIPAddressType, Value: "25.0.0.3"},
},
},
},
@@ -4589,14 +4541,11 @@ func TestBuildNginxPlus(t *testing.T) {
{
msg: "NginxProxy specifies 127.0.0.1 as allowed address",
g: &graph.Graph{
- NginxProxy: &graph.NginxProxy{
- Valid: true,
- Source: &ngfAPIv1alpha1.NginxProxy{
- Spec: ngfAPIv1alpha1.NginxProxySpec{
- NginxPlus: &ngfAPIv1alpha1.NginxPlus{
- AllowedAddresses: []ngfAPIv1alpha1.NginxPlusAllowAddress{
- {Type: ngfAPIv1alpha1.NginxPlusAllowIPAddressType, Value: "127.0.0.1"},
- },
+ Gateway: &graph.Gateway{
+ EffectiveNginxProxy: &graph.EffectiveNginxProxy{
+ NginxPlus: &ngfAPIv1alpha2.NginxPlus{
+ AllowedAddresses: []ngfAPIv1alpha2.NginxPlusAllowAddress{
+ {Type: ngfAPIv1alpha2.NginxPlusAllowIPAddressType, Value: "127.0.0.1"},
},
},
},
diff --git a/internal/mode/static/state/graph/backend_refs.go b/internal/mode/static/state/graph/backend_refs.go
index 3852e900e6..cd25073da1 100644
--- a/internal/mode/static/state/graph/backend_refs.go
+++ b/internal/mode/static/state/graph/backend_refs.go
@@ -11,8 +11,7 @@ import (
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
"sigs.k8s.io/gateway-api/apis/v1alpha3"
- ngfAPI "github.com/nginx/nginx-gateway-fabric/apis/v1alpha1"
-
+ ngfAPIv1alpha2 "github.com/nginx/nginx-gateway-fabric/apis/v1alpha2"
"github.com/nginx/nginx-gateway-fabric/internal/framework/conditions"
"github.com/nginx/nginx-gateway-fabric/internal/framework/helpers"
"github.com/nginx/nginx-gateway-fabric/internal/mode/static/sort"
@@ -47,7 +46,7 @@ func addBackendRefsToRouteRules(
refGrantResolver *referenceGrantResolver,
services map[types.NamespacedName]*v1.Service,
backendTLSPolicies map[types.NamespacedName]*BackendTLSPolicy,
- npCfg *NginxProxy,
+ npCfg *EffectiveNginxProxy,
) {
for _, r := range routes {
addBackendRefsToRules(r, refGrantResolver, services, backendTLSPolicies, npCfg)
@@ -61,7 +60,7 @@ func addBackendRefsToRules(
refGrantResolver *referenceGrantResolver,
services map[types.NamespacedName]*v1.Service,
backendTLSPolicies map[types.NamespacedName]*BackendTLSPolicy,
- npCfg *NginxProxy,
+ npCfg *EffectiveNginxProxy,
) {
if !route.Valid {
return
@@ -123,7 +122,7 @@ func createBackendRef(
services map[types.NamespacedName]*v1.Service,
refPath *field.Path,
backendTLSPolicies map[types.NamespacedName]*BackendTLSPolicy,
- npCfg *NginxProxy,
+ npCfg *EffectiveNginxProxy,
) (BackendRef, *conditions.Condition) {
// Data plane will handle invalid ref by responding with 500.
// Because of that, we always need to add a BackendRef to group.Backends, even if the ref is invalid.
@@ -316,30 +315,32 @@ func getIPFamilyAndPortFromRef(
return svc.Spec.IPFamilies, svcPort, nil
}
-func verifyIPFamily(npCfg *NginxProxy, svcIPFamily []v1.IPFamily) error {
- if npCfg == nil || npCfg.Source == nil || !npCfg.Valid {
+func verifyIPFamily(npCfg *EffectiveNginxProxy, svcIPFamily []v1.IPFamily) error {
+ if npCfg == nil {
return nil
}
- // we can access this field since we have already validated that ipFamily is not nil in validateNginxProxy.
- npIPFamily := npCfg.Source.Spec.IPFamily
- if *npIPFamily == ngfAPI.IPv4 {
- if slices.Contains(svcIPFamily, v1.IPv6Protocol) {
- // capitalizing error message to match the rest of the error messages associated with a condition
- //nolint: stylecheck
- return errors.New(
- "Service configured with IPv6 family but NginxProxy is configured with IPv4",
- )
- }
+ containsIPv6 := slices.Contains(svcIPFamily, v1.IPv6Protocol)
+ containsIPv4 := slices.Contains(svcIPFamily, v1.IPv4Protocol)
+
+ //nolint: stylecheck // used in status condition which is normally capitalized
+ errIPv6Mismatch := errors.New("Service configured with IPv6 family but NginxProxy is configured with IPv4")
+ //nolint: stylecheck // used in status condition which is normally capitalized
+ errIPv4Mismatch := errors.New("Service configured with IPv4 family but NginxProxy is configured with IPv6")
+
+ npIPFamily := npCfg.IPFamily
+
+ if npIPFamily == nil {
+ // default is dual so we don't need to check the service IPFamily.
+ return nil
}
- if *npIPFamily == ngfAPI.IPv6 {
- if slices.Contains(svcIPFamily, v1.IPv4Protocol) {
- // capitalizing error message to match the rest of the error messages associated with a condition
- //nolint: stylecheck
- return errors.New(
- "Service configured with IPv4 family but NginxProxy is configured with IPv6",
- )
- }
+
+ if *npIPFamily == ngfAPIv1alpha2.IPv4 && containsIPv6 {
+ return errIPv6Mismatch
+ }
+
+ if *npIPFamily == ngfAPIv1alpha2.IPv6 && containsIPv4 {
+ return errIPv4Mismatch
}
return nil
diff --git a/internal/mode/static/state/graph/backend_refs_test.go b/internal/mode/static/state/graph/backend_refs_test.go
index 6b4e27f041..bb6ebf0b0f 100644
--- a/internal/mode/static/state/graph/backend_refs_test.go
+++ b/internal/mode/static/state/graph/backend_refs_test.go
@@ -14,7 +14,7 @@ import (
"sigs.k8s.io/gateway-api/apis/v1alpha2"
"sigs.k8s.io/gateway-api/apis/v1alpha3"
- ngfAPI "github.com/nginx/nginx-gateway-fabric/apis/v1alpha1"
+ ngfAPIv1alpha2 "github.com/nginx/nginx-gateway-fabric/apis/v1alpha2"
"github.com/nginx/nginx-gateway-fabric/internal/framework/conditions"
"github.com/nginx/nginx-gateway-fabric/internal/framework/helpers"
staticConds "github.com/nginx/nginx-gateway-fabric/internal/mode/static/state/conditions"
@@ -324,55 +324,35 @@ func TestVerifyIPFamily(t *testing.T) {
test := []struct {
name string
expErr error
- npCfg *NginxProxy
+ npCfg *EffectiveNginxProxy
svcIPFamily []v1.IPFamily
}{
{
name: "Valid - IPv6 and IPv4 configured for NGINX, service has only IPv4",
- npCfg: &NginxProxy{
- Source: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- IPFamily: helpers.GetPointer(ngfAPI.Dual),
- },
- },
- Valid: true,
+ npCfg: &EffectiveNginxProxy{
+ IPFamily: helpers.GetPointer(ngfAPIv1alpha2.Dual),
},
svcIPFamily: []v1.IPFamily{v1.IPv4Protocol},
},
{
name: "Valid - IPv6 and IPv4 configured for NGINX, service has only IPv6",
- npCfg: &NginxProxy{
- Source: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- IPFamily: helpers.GetPointer(ngfAPI.Dual),
- },
- },
- Valid: true,
+ npCfg: &EffectiveNginxProxy{
+ IPFamily: helpers.GetPointer(ngfAPIv1alpha2.Dual),
},
svcIPFamily: []v1.IPFamily{v1.IPv6Protocol},
},
{
name: "Invalid - IPv4 configured for NGINX, service has only IPv6",
- npCfg: &NginxProxy{
- Source: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- IPFamily: helpers.GetPointer(ngfAPI.IPv4),
- },
- },
- Valid: true,
+ npCfg: &EffectiveNginxProxy{
+ IPFamily: helpers.GetPointer(ngfAPIv1alpha2.IPv4),
},
svcIPFamily: []v1.IPFamily{v1.IPv6Protocol},
expErr: errors.New("Service configured with IPv6 family but NginxProxy is configured with IPv4"),
},
{
name: "Invalid - IPv6 configured for NGINX, service has only IPv4",
- npCfg: &NginxProxy{
- Source: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- IPFamily: helpers.GetPointer(ngfAPI.IPv6),
- },
- },
- Valid: true,
+ npCfg: &EffectiveNginxProxy{
+ IPFamily: helpers.GetPointer(ngfAPIv1alpha2.IPv6),
},
svcIPFamily: []v1.IPFamily{v1.IPv4Protocol},
expErr: errors.New("Service configured with IPv4 family but NginxProxy is configured with IPv6"),
@@ -845,7 +825,7 @@ func TestCreateBackend(t *testing.T) {
tests := []struct {
expectedCondition *conditions.Condition
- nginxProxy *NginxProxy
+ nginxProxySpec *EffectiveNginxProxy
name string
expectedServicePortReference string
ref gatewayv1.HTTPBackendRef
@@ -958,12 +938,7 @@ func TestCreateBackend(t *testing.T) {
Weight: 5,
Valid: false,
},
- nginxProxy: &NginxProxy{
- Source: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{IPFamily: helpers.GetPointer(ngfAPI.IPv6)},
- },
- Valid: true,
- },
+ nginxProxySpec: &EffectiveNginxProxy{IPFamily: helpers.GetPointer(ngfAPIv1alpha2.IPv6)},
expectedCondition: helpers.GetPointer(
staticConds.NewRouteInvalidIPFamily(`Service configured with IPv4 family but NginxProxy is configured with IPv6`),
),
@@ -1042,7 +1017,7 @@ func TestCreateBackend(t *testing.T) {
services,
refPath,
policies,
- test.nginxProxy,
+ test.nginxProxySpec,
)
g.Expect(helpers.Diff(test.expectedBackend, backend)).To(BeEmpty())
diff --git a/internal/mode/static/state/graph/gateway.go b/internal/mode/static/state/graph/gateway.go
index 2ee69b5546..b6cfd49ebe 100644
--- a/internal/mode/static/state/graph/gateway.go
+++ b/internal/mode/static/state/graph/gateway.go
@@ -9,6 +9,7 @@ import (
v1 "sigs.k8s.io/gateway-api/apis/v1"
"github.com/nginx/nginx-gateway-fabric/internal/framework/conditions"
+ "github.com/nginx/nginx-gateway-fabric/internal/framework/kinds"
ngfsort "github.com/nginx/nginx-gateway-fabric/internal/mode/static/sort"
staticConds "github.com/nginx/nginx-gateway-fabric/internal/mode/static/state/conditions"
)
@@ -17,6 +18,12 @@ import (
type Gateway struct {
// Source is the corresponding Gateway resource.
Source *v1.Gateway
+ // NginxProxy is the NginxProxy referenced by this Gateway.
+ NginxProxy *NginxProxy
+ /// EffectiveNginxProxy holds the result of merging the NginxProxySpec on this resource with the NginxProxySpec on
+ // the GatewayClass resource. This is the effective set of config that should be applied to the Gateway.
+ // If non-nil, then this config is valid.
+ EffectiveNginxProxy *EffectiveNginxProxy
// Listeners include the listeners of the Gateway.
Listeners []*Listener
// Conditions holds the conditions for the Gateway.
@@ -98,29 +105,91 @@ func buildGateway(
gc *GatewayClass,
refGrantResolver *referenceGrantResolver,
protectedPorts ProtectedPorts,
+ nps map[types.NamespacedName]*NginxProxy,
) *Gateway {
if gw == nil {
return nil
}
- conds := validateGateway(gw, gc)
+ var np *NginxProxy
+ if gw.Spec.Infrastructure != nil && gw.Spec.Infrastructure.ParametersRef != nil {
+ npName := types.NamespacedName{Namespace: gw.Namespace, Name: gw.Spec.Infrastructure.ParametersRef.Name}
+ np = nps[npName]
+ }
- if len(conds) > 0 {
+ var gcNp *NginxProxy
+ if gc != nil {
+ gcNp = gc.NginxProxy
+ }
+
+ effectiveNginxProxy := buildEffectiveNginxProxy(gcNp, np)
+
+ conds, valid := validateGateway(gw, gc, np)
+
+ if !valid {
return &Gateway{
- Source: gw,
- Valid: false,
- Conditions: conds,
+ Source: gw,
+ Valid: false,
+ NginxProxy: np,
+ EffectiveNginxProxy: effectiveNginxProxy,
+ Conditions: conds,
}
}
return &Gateway{
- Source: gw,
- Listeners: buildListeners(gw, secretResolver, refGrantResolver, protectedPorts),
- Valid: true,
+ Source: gw,
+ Listeners: buildListeners(gw, secretResolver, refGrantResolver, protectedPorts),
+ NginxProxy: np,
+ EffectiveNginxProxy: effectiveNginxProxy,
+ Valid: true,
+ Conditions: conds,
}
}
-func validateGateway(gw *v1.Gateway, gc *GatewayClass) []conditions.Condition {
+func validateGatewayParametersRef(npCfg *NginxProxy, ref v1.LocalParametersReference) []conditions.Condition {
+ var conds []conditions.Condition
+
+ path := field.NewPath("spec.infrastructure.parametersRef")
+
+ if _, ok := supportedParamKinds[string(ref.Kind)]; !ok {
+ err := field.NotSupported(path.Child("kind"), string(ref.Kind), []string{kinds.NginxProxy})
+ conds = append(
+ conds,
+ staticConds.NewGatewayRefInvalid(err.Error()),
+ staticConds.NewGatewayInvalidParameters(err.Error()),
+ )
+
+ return conds
+ }
+
+ if npCfg == nil {
+ conds = append(
+ conds,
+ staticConds.NewGatewayRefNotFound(),
+ staticConds.NewGatewayInvalidParameters(
+ field.NotFound(path.Child("name"), ref.Name).Error(),
+ ),
+ )
+
+ return conds
+ }
+
+ if !npCfg.Valid {
+ msg := npCfg.ErrMsgs.ToAggregate().Error()
+ conds = append(
+ conds,
+ staticConds.NewGatewayRefInvalid(msg),
+ staticConds.NewGatewayInvalidParameters(msg),
+ )
+
+ return conds
+ }
+
+ conds = append(conds, staticConds.NewGatewayResolvedRefs())
+ return conds
+}
+
+func validateGateway(gw *v1.Gateway, gc *GatewayClass, npCfg *NginxProxy) ([]conditions.Condition, bool) {
var conds []conditions.Condition
if gc == nil {
@@ -136,5 +205,17 @@ func validateGateway(gw *v1.Gateway, gc *GatewayClass) []conditions.Condition {
conds = append(conds, staticConds.NewGatewayUnsupportedValue(valErr.Error())...)
}
- return conds
+ valid := true
+ // we evaluate validity before validating parametersRef because an invalid parametersRef/NginxProxy does not
+ // invalidate the entire Gateway.
+ if len(conds) > 0 {
+ valid = false
+ }
+
+ if gw.Spec.Infrastructure != nil && gw.Spec.Infrastructure.ParametersRef != nil {
+ paramConds := validateGatewayParametersRef(npCfg, *gw.Spec.Infrastructure.ParametersRef)
+ conds = append(conds, paramConds...)
+ }
+
+ return conds, valid
}
diff --git a/internal/mode/static/state/graph/gateway_test.go b/internal/mode/static/state/graph/gateway_test.go
index cdf7879a78..7d21f77b7c 100644
--- a/internal/mode/static/state/graph/gateway_test.go
+++ b/internal/mode/static/state/graph/gateway_test.go
@@ -8,10 +8,13 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/types"
+ "k8s.io/apimachinery/pkg/util/validation/field"
"sigs.k8s.io/controller-runtime/pkg/client"
v1 "sigs.k8s.io/gateway-api/apis/v1"
- v1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
+ "sigs.k8s.io/gateway-api/apis/v1beta1"
+ ngfAPIv1alpha2 "github.com/nginx/nginx-gateway-fabric/apis/v1alpha2"
+ "github.com/nginx/nginx-gateway-fabric/internal/framework/conditions"
"github.com/nginx/nginx-gateway-fabric/internal/framework/helpers"
"github.com/nginx/nginx-gateway-fabric/internal/framework/kinds"
staticConds "github.com/nginx/nginx-gateway-fabric/internal/mode/static/state/conditions"
@@ -338,6 +341,7 @@ func TestBuildGateway(t *testing.T) {
)
type gatewayCfg struct {
+ ref *v1.LocalParametersReference
listeners []v1.Listener
addresses []v1.GatewayAddress
}
@@ -354,12 +358,64 @@ func TestBuildGateway(t *testing.T) {
Addresses: cfg.addresses,
},
}
+
+ if cfg.ref != nil {
+ lastCreatedGateway.Spec.Infrastructure = &v1.GatewayInfrastructure{
+ ParametersRef: cfg.ref,
+ }
+ }
return lastCreatedGateway
}
getLastCreatedGateway := func() *v1.Gateway {
return lastCreatedGateway
}
+ validGwNp := &ngfAPIv1alpha2.NginxProxy{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: "test",
+ Name: "valid-gw-np",
+ },
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Logging: &ngfAPIv1alpha2.NginxLogging{ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelError)},
+ },
+ }
+ validGwNpRef := &v1.LocalParametersReference{
+ Group: ngfAPIv1alpha2.GroupName,
+ Kind: kinds.NginxProxy,
+ Name: validGwNp.Name,
+ }
+ invalidGwNp := &ngfAPIv1alpha2.NginxProxy{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: "test",
+ Name: "invalid-gw-np",
+ },
+ }
+ invalidGwNpRef := &v1.LocalParametersReference{
+ Group: ngfAPIv1alpha2.GroupName,
+ Kind: kinds.NginxProxy,
+ Name: invalidGwNp.Name,
+ }
+ invalidKindRef := &v1.LocalParametersReference{
+ Group: ngfAPIv1alpha2.GroupName,
+ Kind: "Invalid",
+ Name: "invalid-kind",
+ }
+ npDoesNotExistRef := &v1.LocalParametersReference{
+ Group: ngfAPIv1alpha2.GroupName,
+ Kind: kinds.NginxProxy,
+ Name: "does-not-exist",
+ }
+
+ validGcNp := &ngfAPIv1alpha2.NginxProxy{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: "test",
+ Name: "valid-gc-np",
+ },
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ IPFamily: helpers.GetPointer(ngfAPIv1alpha2.Dual),
+ },
+ }
+
validGC := &GatewayClass{
Valid: true,
}
@@ -367,6 +423,14 @@ func TestBuildGateway(t *testing.T) {
Valid: false,
}
+ validGCWithNp := &GatewayClass{
+ Valid: true,
+ NginxProxy: &NginxProxy{
+ Source: validGcNp,
+ Valid: true,
+ },
+ }
+
supportedKindsForListeners := []v1.RouteGroupKind{
{Kind: v1.Kind(kinds.HTTPRoute), Group: helpers.GetPointer[v1.Group](v1.GroupName)},
{Kind: v1.Kind(kinds.GRPCRoute), Group: helpers.GetPointer[v1.Group](v1.GroupName)},
@@ -509,6 +573,90 @@ func TestBuildGateway(t *testing.T) {
},
name: "valid https listener with cross-namespace secret; allowed by reference grant",
},
+ {
+ gateway: createGateway(gatewayCfg{listeners: []v1.Listener{foo80Listener1}, ref: validGwNpRef}),
+ gatewayClass: validGC,
+ expected: &Gateway{
+ Source: getLastCreatedGateway(),
+ Listeners: []*Listener{
+ {
+ Name: "foo-80-1",
+ Source: foo80Listener1,
+ Valid: true,
+ Attachable: true,
+ Routes: map[RouteKey]*L7Route{},
+ L4Routes: map[L4RouteKey]*L4Route{},
+ SupportedKinds: supportedKindsForListeners,
+ },
+ },
+ Valid: true,
+ NginxProxy: &NginxProxy{
+ Source: validGwNp,
+ Valid: true,
+ },
+ EffectiveNginxProxy: &EffectiveNginxProxy{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelError),
+ },
+ },
+ Conditions: []conditions.Condition{staticConds.NewGatewayResolvedRefs()},
+ },
+ name: "valid http listener with valid NginxProxy; GatewayClass has no NginxProxy",
+ },
+ {
+ gateway: createGateway(gatewayCfg{listeners: []v1.Listener{foo80Listener1}, ref: validGwNpRef}),
+ gatewayClass: validGCWithNp,
+ expected: &Gateway{
+ Source: getLastCreatedGateway(),
+ Listeners: []*Listener{
+ {
+ Name: "foo-80-1",
+ Source: foo80Listener1,
+ Valid: true,
+ Attachable: true,
+ Routes: map[RouteKey]*L7Route{},
+ L4Routes: map[L4RouteKey]*L4Route{},
+ SupportedKinds: supportedKindsForListeners,
+ },
+ },
+ Valid: true,
+ NginxProxy: &NginxProxy{
+ Source: validGwNp,
+ Valid: true,
+ },
+ EffectiveNginxProxy: &EffectiveNginxProxy{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelError),
+ },
+ IPFamily: helpers.GetPointer(ngfAPIv1alpha2.Dual),
+ },
+ Conditions: []conditions.Condition{staticConds.NewGatewayResolvedRefs()},
+ },
+ name: "valid http listener with valid NginxProxy; GatewayClass has valid NginxProxy too",
+ },
+ {
+ gateway: createGateway(gatewayCfg{listeners: []v1.Listener{foo80Listener1}}),
+ gatewayClass: validGCWithNp,
+ expected: &Gateway{
+ Source: getLastCreatedGateway(),
+ Listeners: []*Listener{
+ {
+ Name: "foo-80-1",
+ Source: foo80Listener1,
+ Valid: true,
+ Attachable: true,
+ Routes: map[RouteKey]*L7Route{},
+ L4Routes: map[L4RouteKey]*L4Route{},
+ SupportedKinds: supportedKindsForListeners,
+ },
+ },
+ Valid: true,
+ EffectiveNginxProxy: &EffectiveNginxProxy{
+ IPFamily: helpers.GetPointer(ngfAPIv1alpha2.Dual),
+ },
+ },
+ name: "valid http listener; GatewayClass has valid NginxProxy",
+ },
{
gateway: createGateway(gatewayCfg{listeners: []v1.Listener{crossNamespaceSecretListener}}),
gatewayClass: validGC,
@@ -1024,6 +1172,116 @@ func TestBuildGateway(t *testing.T) {
},
name: "https listener and tls listener with non overlapping hostnames",
},
+ {
+ gateway: createGateway(gatewayCfg{listeners: []v1.Listener{foo80Listener1}, ref: invalidKindRef}),
+ gatewayClass: validGC,
+ expected: &Gateway{
+ Source: getLastCreatedGateway(),
+ Listeners: []*Listener{
+ {
+ Name: "foo-80-1",
+ Source: foo80Listener1,
+ Valid: true,
+ Attachable: true,
+ Routes: map[RouteKey]*L7Route{},
+ L4Routes: map[L4RouteKey]*L4Route{},
+ SupportedKinds: supportedKindsForListeners,
+ },
+ },
+ Valid: true, // invalid parametersRef does not invalidate Gateway.
+ Conditions: []conditions.Condition{
+ staticConds.NewGatewayRefInvalid(
+ "spec.infrastructure.parametersRef.kind: Unsupported value: \"Invalid\": " +
+ "supported values: \"NginxProxy\"",
+ ),
+ staticConds.NewGatewayInvalidParameters(
+ "spec.infrastructure.parametersRef.kind: Unsupported value: \"Invalid\": " +
+ "supported values: \"NginxProxy\"",
+ ),
+ },
+ },
+ name: "invalid parameters ref kind",
+ },
+ {
+ gateway: createGateway(gatewayCfg{listeners: []v1.Listener{foo80Listener1}, ref: npDoesNotExistRef}),
+ gatewayClass: validGC,
+ expected: &Gateway{
+ Source: getLastCreatedGateway(),
+ Listeners: []*Listener{
+ {
+ Name: "foo-80-1",
+ Source: foo80Listener1,
+ Valid: true,
+ Attachable: true,
+ Routes: map[RouteKey]*L7Route{},
+ L4Routes: map[L4RouteKey]*L4Route{},
+ SupportedKinds: supportedKindsForListeners,
+ },
+ },
+ Valid: true, // invalid parametersRef does not invalidate Gateway.
+ Conditions: []conditions.Condition{
+ staticConds.NewGatewayRefNotFound(),
+ staticConds.NewGatewayInvalidParameters(
+ "spec.infrastructure.parametersRef.name: Not found: \"does-not-exist\"",
+ ),
+ },
+ },
+ name: "referenced NginxProxy doesn't exist",
+ },
+ {
+ gateway: createGateway(gatewayCfg{listeners: []v1.Listener{foo80Listener1}, ref: invalidGwNpRef}),
+ gatewayClass: validGC,
+ expected: &Gateway{
+ Source: getLastCreatedGateway(),
+ Listeners: []*Listener{
+ {
+ Name: "foo-80-1",
+ Source: foo80Listener1,
+ Valid: true,
+ Attachable: true,
+ Routes: map[RouteKey]*L7Route{},
+ L4Routes: map[L4RouteKey]*L4Route{},
+ SupportedKinds: supportedKindsForListeners,
+ },
+ },
+ Valid: true, // invalid NginxProxy does not invalidate Gateway.
+ NginxProxy: &NginxProxy{
+ Source: invalidGwNp,
+ ErrMsgs: field.ErrorList{
+ field.Required(field.NewPath("somePath"), "someField"), // fake error
+ },
+ Valid: false,
+ },
+ Conditions: []conditions.Condition{
+ staticConds.NewGatewayRefInvalid("somePath: Required value: someField"),
+ staticConds.NewGatewayInvalidParameters("somePath: Required value: someField"),
+ },
+ },
+ name: "invalid NginxProxy",
+ },
+ {
+ gateway: createGateway(
+ gatewayCfg{listeners: []v1.Listener{foo80Listener1, invalidProtocolListener}, ref: invalidGwNpRef},
+ ),
+ gatewayClass: invalidGC,
+ expected: &Gateway{
+ Source: getLastCreatedGateway(),
+ Valid: false,
+ NginxProxy: &NginxProxy{
+ Source: invalidGwNp,
+ ErrMsgs: field.ErrorList{
+ field.Required(field.NewPath("somePath"), "someField"), // fake error
+ },
+ Valid: false,
+ },
+ Conditions: append(
+ staticConds.NewGatewayInvalid("GatewayClass is invalid"),
+ staticConds.NewGatewayRefInvalid("somePath: Required value: someField"),
+ staticConds.NewGatewayInvalidParameters("somePath: Required value: someField"),
+ ),
+ },
+ name: "invalid gatewayclass and invalid NginxProxy",
+ },
}
secretResolver := newSecretResolver(
@@ -1032,12 +1290,106 @@ func TestBuildGateway(t *testing.T) {
client.ObjectKeyFromObject(secretDiffNamespace): secretDiffNamespace,
})
+ nginxProxies := map[types.NamespacedName]*NginxProxy{
+ client.ObjectKeyFromObject(validGwNp): {Valid: true, Source: validGwNp},
+ client.ObjectKeyFromObject(validGcNp): {Valid: true, Source: validGcNp},
+ client.ObjectKeyFromObject(invalidGwNp): {
+ Source: invalidGwNp,
+ ErrMsgs: append(field.ErrorList{}, field.Required(field.NewPath("somePath"), "someField")),
+ Valid: false,
+ },
+ }
+
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
g := NewWithT(t)
resolver := newReferenceGrantResolver(test.refGrants)
- result := buildGateway(test.gateway, secretResolver, test.gatewayClass, resolver, protectedPorts)
+ result := buildGateway(test.gateway, secretResolver, test.gatewayClass, resolver, protectedPorts, nginxProxies)
g.Expect(helpers.Diff(test.expected, result)).To(BeEmpty())
})
}
}
+
+func TestValidateGatewayParametersRef(t *testing.T) {
+ t.Parallel()
+
+ tests := []struct {
+ name string
+ np *NginxProxy
+ ref v1.LocalParametersReference
+ expConds []conditions.Condition
+ }{
+ {
+ name: "unsupported parameter ref kind",
+ ref: v1.LocalParametersReference{
+ Kind: "wrong-kind",
+ },
+ expConds: []conditions.Condition{
+ staticConds.NewGatewayRefInvalid(
+ "spec.infrastructure.parametersRef.kind: Unsupported value: \"wrong-kind\": " +
+ "supported values: \"NginxProxy\"",
+ ),
+ staticConds.NewGatewayInvalidParameters(
+ "spec.infrastructure.parametersRef.kind: Unsupported value: \"wrong-kind\": " +
+ "supported values: \"NginxProxy\"",
+ ),
+ },
+ },
+ {
+ name: "nil nginx proxy",
+ ref: v1.LocalParametersReference{
+ Group: ngfAPIv1alpha2.GroupName,
+ Kind: kinds.NginxProxy,
+ Name: "np",
+ },
+ expConds: []conditions.Condition{
+ staticConds.NewGatewayRefNotFound(),
+ staticConds.NewGatewayInvalidParameters("spec.infrastructure.parametersRef.name: Not found: \"np\""),
+ },
+ },
+ {
+ name: "invalid nginx proxy",
+ np: &NginxProxy{
+ Source: &ngfAPIv1alpha2.NginxProxy{},
+ ErrMsgs: field.ErrorList{
+ field.Required(field.NewPath("somePath"), "someField"), // fake error
+ },
+ Valid: false,
+ },
+ ref: v1.LocalParametersReference{
+ Group: ngfAPIv1alpha2.GroupName,
+ Kind: kinds.NginxProxy,
+ Name: "np",
+ },
+ expConds: []conditions.Condition{
+ staticConds.NewGatewayRefInvalid("somePath: Required value: someField"),
+ staticConds.NewGatewayInvalidParameters("somePath: Required value: someField"),
+ },
+ },
+ {
+ name: "valid",
+ np: &NginxProxy{
+ Source: &ngfAPIv1alpha2.NginxProxy{},
+ Valid: true,
+ },
+ ref: v1.LocalParametersReference{
+ Group: ngfAPIv1alpha2.GroupName,
+ Kind: kinds.NginxProxy,
+ Name: "np",
+ },
+ expConds: []conditions.Condition{
+ staticConds.NewGatewayResolvedRefs(),
+ },
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ t.Parallel()
+ g := NewWithT(t)
+
+ conds := validateGatewayParametersRef(test.np, test.ref)
+ g.Expect(conds).To(BeEquivalentTo(test.expConds))
+ })
+ }
+}
diff --git a/internal/mode/static/state/graph/gatewayclass.go b/internal/mode/static/state/graph/gatewayclass.go
index 510fd63f32..db5e3dff77 100644
--- a/internal/mode/static/state/graph/gatewayclass.go
+++ b/internal/mode/static/state/graph/gatewayclass.go
@@ -1,8 +1,6 @@
package graph
import (
- "errors"
-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/validation/field"
@@ -19,6 +17,8 @@ import (
type GatewayClass struct {
// Source is the source resource.
Source *v1.GatewayClass
+ // NginxProxy is the NginxProxy resource referenced by this GatewayClass.
+ NginxProxy *NginxProxy
// Conditions include Conditions for the GatewayClass.
Conditions []conditions.Condition
// Valid shows whether the GatewayClass is valid.
@@ -34,7 +34,7 @@ type processedGatewayClasses struct {
// processGatewayClasses returns the "Winner" GatewayClass, which is defined in
// the command-line argument and references this controller, and a list of "Ignored" GatewayClasses
// that reference this controller, but are not named in the command-line argument.
-// Also returns a boolean that says whether or not the GatewayClass defined
+// Also returns a boolean that says whether the GatewayClass defined
// in the command-line argument exists, regardless of which controller it references.
func processGatewayClasses(
gcs map[types.NamespacedName]*v1.GatewayClass,
@@ -63,22 +63,66 @@ func processGatewayClasses(
func buildGatewayClass(
gc *v1.GatewayClass,
- npCfg *NginxProxy,
+ nps map[types.NamespacedName]*NginxProxy,
crdVersions map[types.NamespacedName]*metav1.PartialObjectMetadata,
) *GatewayClass {
if gc == nil {
return nil
}
- conds, valid := validateGatewayClass(gc, npCfg, crdVersions)
+ var np *NginxProxy
+ if gc.Spec.ParametersRef != nil {
+ np = getNginxProxyForGatewayClass(*gc.Spec.ParametersRef, nps)
+ }
+
+ conds, valid := validateGatewayClass(gc, np, crdVersions)
return &GatewayClass{
Source: gc,
+ NginxProxy: np,
Valid: valid,
Conditions: conds,
}
}
+func getNginxProxyForGatewayClass(
+ ref v1.ParametersReference,
+ nps map[types.NamespacedName]*NginxProxy,
+) *NginxProxy {
+ if ref.Namespace == nil {
+ return nil
+ }
+
+ npName := types.NamespacedName{Name: ref.Name, Namespace: string(*ref.Namespace)}
+
+ return nps[npName]
+}
+
+func validateGatewayClassParametersRef(path *field.Path, ref v1.ParametersReference) []conditions.Condition {
+ var errs field.ErrorList
+
+ if _, ok := supportedParamKinds[string(ref.Kind)]; !ok {
+ errs = append(
+ errs,
+ field.NotSupported(path.Child("kind"), string(ref.Kind), []string{kinds.NginxProxy}),
+ )
+ }
+
+ if ref.Namespace == nil {
+ errs = append(errs, field.Required(path.Child("namespace"), "ParametersRef must specify Namespace"))
+ }
+
+ if len(errs) > 0 {
+ msg := errs.ToAggregate().Error()
+ return []conditions.Condition{
+ staticConds.NewGatewayClassRefInvalid(msg),
+ staticConds.NewGatewayClassInvalidParameters(msg),
+ }
+ }
+
+ return nil
+}
+
func validateGatewayClass(
gc *v1.GatewayClass,
npCfg *NginxProxy,
@@ -86,28 +130,44 @@ func validateGatewayClass(
) ([]conditions.Condition, bool) {
var conds []conditions.Condition
- if gc.Spec.ParametersRef != nil {
- var err error
- path := field.NewPath("spec").Child("parametersRef")
- if _, ok := supportedParamKinds[string(gc.Spec.ParametersRef.Kind)]; !ok {
- err = field.NotSupported(path.Child("kind"), string(gc.Spec.ParametersRef.Kind), []string{kinds.NginxProxy})
- } else if npCfg == nil {
- err = field.NotFound(path.Child("name"), gc.Spec.ParametersRef.Name)
- conds = append(conds, staticConds.NewGatewayClassRefNotFound())
- } else if !npCfg.Valid {
- err = errors.New(npCfg.ErrMsgs.ToAggregate().Error())
- }
+ supportedVersionConds, versionsValid := gatewayclass.ValidateCRDVersions(crdVersions)
+ conds = append(conds, supportedVersionConds...)
- if err != nil {
- conds = append(conds, staticConds.NewGatewayClassInvalidParameters(err.Error()))
- } else {
- conds = append(conds, staticConds.NewGatewayClassResolvedRefs())
- }
+ if gc.Spec.ParametersRef == nil {
+ return conds, versionsValid
}
- supportedVersionConds, versionsValid := gatewayclass.ValidateCRDVersions(crdVersions)
+ path := field.NewPath("spec").Child("parametersRef")
+ refConds := validateGatewayClassParametersRef(path, *gc.Spec.ParametersRef)
+
+ // return early since parametersRef isn't valid
+ if len(refConds) > 0 {
+ conds = append(conds, refConds...)
+ return conds, versionsValid
+ }
+
+ if npCfg == nil {
+ conds = append(
+ conds,
+ staticConds.NewGatewayClassRefNotFound(),
+ staticConds.NewGatewayClassInvalidParameters(
+ field.NotFound(path.Child("name"), gc.Spec.ParametersRef.Name).Error(),
+ ),
+ )
+ return conds, versionsValid
+ }
+
+ if !npCfg.Valid {
+ msg := npCfg.ErrMsgs.ToAggregate().Error()
+ conds = append(
+ conds,
+ staticConds.NewGatewayClassRefInvalid(msg),
+ staticConds.NewGatewayClassInvalidParameters(msg),
+ )
+ return conds, versionsValid
+ }
- return append(conds, supportedVersionConds...), versionsValid
+ return append(conds, staticConds.NewGatewayClassResolvedRefs()), versionsValid
}
var supportedParamKinds = map[string]struct{}{
diff --git a/internal/mode/static/state/graph/gatewayclass_test.go b/internal/mode/static/state/graph/gatewayclass_test.go
index 1f1454e838..3d26b6b1fd 100644
--- a/internal/mode/static/state/graph/gatewayclass_test.go
+++ b/internal/mode/static/state/graph/gatewayclass_test.go
@@ -10,7 +10,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
v1 "sigs.k8s.io/gateway-api/apis/v1"
- ngfAPI "github.com/nginx/nginx-gateway-fabric/apis/v1alpha1"
+ ngfAPIv1alpha2 "github.com/nginx/nginx-gateway-fabric/apis/v1alpha2"
"github.com/nginx/nginx-gateway-fabric/internal/framework/conditions"
"github.com/nginx/nginx-gateway-fabric/internal/framework/gatewayclass"
"github.com/nginx/nginx-gateway-fabric/internal/framework/helpers"
@@ -127,17 +127,32 @@ func TestProcessGatewayClasses(t *testing.T) {
func TestBuildGatewayClass(t *testing.T) {
t.Parallel()
validGC := &v1.GatewayClass{}
+ npNsName := types.NamespacedName{Namespace: "test", Name: "nginx-proxy"}
+
+ np := &ngfAPIv1alpha2.NginxProxy{
+ TypeMeta: metav1.TypeMeta{
+ Kind: kinds.NginxProxy,
+ },
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ ServiceName: helpers.GetPointer("my-svc"),
+ },
+ },
+ }
gcWithParams := &v1.GatewayClass{
Spec: v1.GatewayClassSpec{
ParametersRef: &v1.ParametersReference{
Kind: v1.Kind(kinds.NginxProxy),
- Namespace: helpers.GetPointer(v1.Namespace("test")),
- Name: "nginx-proxy",
+ Namespace: helpers.GetPointer(v1.Namespace(npNsName.Namespace)),
+ Name: npNsName.Name,
},
},
}
+ gcWithParamsNoNamespace := gcWithParams.DeepCopy()
+ gcWithParamsNoNamespace.Spec.ParametersRef.Namespace = nil
+
gcWithInvalidKind := &v1.GatewayClass{
Spec: v1.GatewayClassSpec{
ParametersRef: &v1.ParametersReference{
@@ -168,12 +183,11 @@ func TestBuildGatewayClass(t *testing.T) {
}
tests := []struct {
- gc *v1.GatewayClass
- np *NginxProxy
- crdMetadata map[types.NamespacedName]*metav1.PartialObjectMetadata
- expected *GatewayClass
- name string
- expNPInvalid bool
+ gc *v1.GatewayClass
+ nps map[types.NamespacedName]*NginxProxy
+ crdMetadata map[types.NamespacedName]*metav1.PartialObjectMetadata
+ expected *GatewayClass
+ name string
}{
{
gc: validGC,
@@ -191,46 +205,54 @@ func TestBuildGatewayClass(t *testing.T) {
},
{
gc: gcWithParams,
- np: &NginxProxy{
- Source: &ngfAPI.NginxProxy{
- TypeMeta: metav1.TypeMeta{
- Kind: kinds.NginxProxy,
- },
- Spec: ngfAPI.NginxProxySpec{
- Telemetry: &ngfAPI.Telemetry{
- ServiceName: helpers.GetPointer("my-svc"),
- },
- },
+ nps: map[types.NamespacedName]*NginxProxy{
+ npNsName: {
+ Source: np,
+ Valid: true,
},
- Valid: true,
},
expected: &GatewayClass{
Source: gcWithParams,
Valid: true,
Conditions: []conditions.Condition{staticConds.NewGatewayClassResolvedRefs()},
+ NginxProxy: &NginxProxy{
+ Valid: true,
+ Source: np,
+ },
},
name: "valid gatewayclass with paramsRef",
},
{
- gc: gcWithInvalidKind,
- np: &NginxProxy{
- Source: &ngfAPI.NginxProxy{
- TypeMeta: metav1.TypeMeta{
- Kind: kinds.NginxProxy,
- },
+ gc: gcWithParamsNoNamespace,
+ expected: &GatewayClass{
+ Source: gcWithParamsNoNamespace,
+ Valid: true,
+ Conditions: []conditions.Condition{
+ staticConds.NewGatewayClassRefInvalid(
+ "spec.parametersRef.namespace: Required value: ParametersRef must specify Namespace",
+ ),
+ staticConds.NewGatewayClassInvalidParameters(
+ "spec.parametersRef.namespace: Required value: ParametersRef must specify Namespace",
+ ),
},
- Valid: true,
},
+ name: "valid gatewayclass with paramsRef missing namespace",
+ },
+ {
+ gc: gcWithInvalidKind,
expected: &GatewayClass{
Source: gcWithInvalidKind,
Valid: true,
Conditions: []conditions.Condition{
+ staticConds.NewGatewayClassRefInvalid(
+ "spec.parametersRef.kind: Unsupported value: \"Invalid\": supported values: \"NginxProxy\"",
+ ),
staticConds.NewGatewayClassInvalidParameters(
"spec.parametersRef.kind: Unsupported value: \"Invalid\": supported values: \"NginxProxy\"",
),
},
},
- name: "invalid gatewayclass with unsupported paramsRef Kind",
+ name: "valid gatewayclass with unsupported paramsRef Kind",
},
{
gc: gcWithParams,
@@ -244,38 +266,57 @@ func TestBuildGatewayClass(t *testing.T) {
),
},
},
- expNPInvalid: true,
- name: "invalid gatewayclass with paramsRef resource that doesn't exist",
+ name: "valid gatewayclass with paramsRef resource that doesn't exist",
},
{
gc: gcWithParams,
- np: &NginxProxy{
- Valid: false,
- ErrMsgs: field.ErrorList{
- field.Invalid(
- field.NewPath("spec", "telemetry", "serviceName"),
- "my-svc",
- "error",
- ),
- field.Invalid(
- field.NewPath("spec", "telemetry", "exporter", "endpoint"),
- "my-endpoint",
- "error",
- ),
+ nps: map[types.NamespacedName]*NginxProxy{
+ npNsName: {
+ Valid: false,
+ ErrMsgs: field.ErrorList{
+ field.Invalid(
+ field.NewPath("spec", "telemetry", "serviceName"),
+ "my-svc",
+ "error",
+ ),
+ field.Invalid(
+ field.NewPath("spec", "telemetry", "exporter", "endpoint"),
+ "my-endpoint",
+ "error",
+ ),
+ },
},
},
expected: &GatewayClass{
Source: gcWithParams,
Valid: true,
Conditions: []conditions.Condition{
+ staticConds.NewGatewayClassRefInvalid(
+ "[spec.telemetry.serviceName: Invalid value: \"my-svc\": error" +
+ ", spec.telemetry.exporter.endpoint: Invalid value: \"my-endpoint\": error]",
+ ),
staticConds.NewGatewayClassInvalidParameters(
"[spec.telemetry.serviceName: Invalid value: \"my-svc\": error" +
", spec.telemetry.exporter.endpoint: Invalid value: \"my-endpoint\": error]",
),
},
+ NginxProxy: &NginxProxy{
+ Valid: false,
+ ErrMsgs: field.ErrorList{
+ field.Invalid(
+ field.NewPath("spec", "telemetry", "serviceName"),
+ "my-svc",
+ "error",
+ ),
+ field.Invalid(
+ field.NewPath("spec", "telemetry", "exporter", "endpoint"),
+ "my-endpoint",
+ "error",
+ ),
+ },
+ },
},
- expNPInvalid: true,
- name: "invalid gatewayclass with invalid paramsRef resource",
+ name: "valid gatewayclass with invalid paramsRef resource",
},
{
gc: validGC,
@@ -294,11 +335,8 @@ func TestBuildGatewayClass(t *testing.T) {
t.Parallel()
g := NewWithT(t)
- result := buildGatewayClass(test.gc, test.np, test.crdMetadata)
+ result := buildGatewayClass(test.gc, test.nps, test.crdMetadata)
g.Expect(helpers.Diff(test.expected, result)).To(BeEmpty())
- if test.np != nil {
- g.Expect(test.np.Valid).ToNot(Equal(test.expNPInvalid))
- }
})
}
}
diff --git a/internal/mode/static/state/graph/graph.go b/internal/mode/static/state/graph/graph.go
index 82dc2712d9..62e6e9af3a 100644
--- a/internal/mode/static/state/graph/graph.go
+++ b/internal/mode/static/state/graph/graph.go
@@ -14,7 +14,8 @@ import (
"sigs.k8s.io/gateway-api/apis/v1alpha3"
"sigs.k8s.io/gateway-api/apis/v1beta1"
- ngfAPI "github.com/nginx/nginx-gateway-fabric/apis/v1alpha1"
+ ngfAPIv1alpha1 "github.com/nginx/nginx-gateway-fabric/apis/v1alpha1"
+ ngfAPIv1alpha2 "github.com/nginx/nginx-gateway-fabric/apis/v1alpha2"
"github.com/nginx/nginx-gateway-fabric/internal/framework/controller/index"
"github.com/nginx/nginx-gateway-fabric/internal/framework/kinds"
ngftypes "github.com/nginx/nginx-gateway-fabric/internal/framework/types"
@@ -35,10 +36,10 @@ type ClusterState struct {
CRDMetadata map[types.NamespacedName]*metav1.PartialObjectMetadata
BackendTLSPolicies map[types.NamespacedName]*v1alpha3.BackendTLSPolicy
ConfigMaps map[types.NamespacedName]*v1.ConfigMap
- NginxProxies map[types.NamespacedName]*ngfAPI.NginxProxy
+ NginxProxies map[types.NamespacedName]*ngfAPIv1alpha2.NginxProxy
GRPCRoutes map[types.NamespacedName]*gatewayv1.GRPCRoute
NGFPolicies map[PolicyKey]policies.Policy
- SnippetsFilters map[types.NamespacedName]*ngfAPI.SnippetsFilter
+ SnippetsFilters map[types.NamespacedName]*ngfAPIv1alpha1.SnippetsFilter
}
// Graph is a Graph-like representation of Gateway API resources.
@@ -70,10 +71,10 @@ type Graph struct {
ReferencedServices map[types.NamespacedName]*ReferencedService
// ReferencedCaCertConfigMaps includes ConfigMaps that have been referenced by any BackendTLSPolicies.
ReferencedCaCertConfigMaps map[types.NamespacedName]*CaCertConfigMap
+ // ReferencedNginxProxies includes NginxProxies that have been referenced by a GatewayClass or the winning Gateway.
+ ReferencedNginxProxies map[types.NamespacedName]*NginxProxy
// BackendTLSPolicies holds BackendTLSPolicy resources.
BackendTLSPolicies map[types.NamespacedName]*BackendTLSPolicy
- // NginxProxy holds the NginxProxy config for the GatewayClass.
- NginxProxy *NginxProxy
// NGFPolicies holds all NGF Policies.
NGFPolicies map[PolicyKey]*Policy
// GlobalSettings contains global settings from the current state of the graph that may be
@@ -126,9 +127,10 @@ func (g *Graph) IsReferenced(resourceType ngftypes.ObjectType, nsname types.Name
// Service Namespace should be the same Namespace as the EndpointSlice
_, exists := g.ReferencedServices[types.NamespacedName{Namespace: nsname.Namespace, Name: svcName}]
return exists
- // NginxProxy reference exists if it is linked to a GatewayClass.
- case *ngfAPI.NginxProxy:
- return isNginxProxyReferenced(nsname, g.GatewayClass)
+ // NginxProxy reference exists if the GatewayClass or winning Gateway references it.
+ case *ngfAPIv1alpha2.NginxProxy:
+ _, exists := g.ReferencedNginxProxies[nsname]
+ return exists
default:
return false
}
@@ -200,32 +202,39 @@ func BuildGraph(
validators validation.Validators,
protectedPorts ProtectedPorts,
) *Graph {
- var globalSettings *policies.GlobalSettings
-
processedGwClasses, gcExists := processGatewayClasses(state.GatewayClasses, gcName, controllerName)
if gcExists && processedGwClasses.Winner == nil {
// configured GatewayClass does not reference this controller
return &Graph{}
}
- npCfg := buildNginxProxy(state.NginxProxies, processedGwClasses.Winner, validators.GenericValidator)
- gc := buildGatewayClass(processedGwClasses.Winner, npCfg, state.CRDMetadata)
- if gc != nil && npCfg != nil && npCfg.Source != nil {
- spec := npCfg.Source.Spec
- globalSettings = &policies.GlobalSettings{
- NginxProxyValid: npCfg.Valid,
- TelemetryEnabled: spec.Telemetry != nil && spec.Telemetry.Exporter != nil,
- }
- }
+ processedGws := processGateways(state.Gateways, gcName)
+ processedNginxProxies := processNginxProxies(
+ state.NginxProxies,
+ validators.GenericValidator,
+ processedGwClasses.Winner,
+ processedGws.Winner,
+ )
+
+ gc := buildGatewayClass(
+ processedGwClasses.Winner,
+ processedNginxProxies,
+ state.CRDMetadata,
+ )
secretResolver := newSecretResolver(state.Secrets)
configMapResolver := newConfigMapResolver(state.ConfigMaps)
- processedGws := processGateways(state.Gateways, gcName)
-
refGrantResolver := newReferenceGrantResolver(state.ReferenceGrants)
- gw := buildGateway(processedGws.Winner, secretResolver, gc, refGrantResolver, protectedPorts)
+ gw := buildGateway(
+ processedGws.Winner,
+ secretResolver,
+ gc,
+ refGrantResolver,
+ protectedPorts,
+ processedNginxProxies,
+ )
processedBackendTLSPolicies := processBackendTLSPolicies(
state.BackendTLSPolicies,
@@ -235,13 +244,17 @@ func BuildGraph(
)
processedSnippetsFilters := processSnippetsFilters(state.SnippetsFilters)
+ var effectiveNginxProxy *EffectiveNginxProxy
+ if gw != nil {
+ effectiveNginxProxy = gw.EffectiveNginxProxy
+ }
routes := buildRoutesForGateways(
validators.HTTPFieldsValidator,
state.HTTPRoutes,
state.GRPCRoutes,
processedGws.GetAllNsNames(),
- npCfg,
+ effectiveNginxProxy,
processedSnippetsFilters,
)
@@ -249,17 +262,30 @@ func BuildGraph(
state.TLSRoutes,
processedGws.GetAllNsNames(),
state.Services,
- npCfg,
+ effectiveNginxProxy,
refGrantResolver,
)
bindRoutesToListeners(routes, l4routes, gw, state.Namespaces)
- addBackendRefsToRouteRules(routes, refGrantResolver, state.Services, processedBackendTLSPolicies, npCfg)
+ addBackendRefsToRouteRules(
+ routes,
+ refGrantResolver,
+ state.Services,
+ processedBackendTLSPolicies,
+ effectiveNginxProxy,
+ )
referencedNamespaces := buildReferencedNamespaces(state.Namespaces, gw)
referencedServices := buildReferencedServices(routes, l4routes, gw)
+ var globalSettings *policies.GlobalSettings
+ if gw != nil && gw.EffectiveNginxProxy != nil {
+ globalSettings = &policies.GlobalSettings{
+ NginxProxyValid: true, // for effective nginx proxy to be set, the config must be valid
+ TelemetryEnabled: telemetryEnabledForNginxProxy(gw.EffectiveNginxProxy),
+ }
+ }
// policies must be processed last because they rely on the state of the other resources in the graph
processedPolicies := processPolicies(
state.NGFPolicies,
@@ -283,8 +309,8 @@ func BuildGraph(
ReferencedNamespaces: referencedNamespaces,
ReferencedServices: referencedServices,
ReferencedCaCertConfigMaps: configMapResolver.getResolvedConfigMaps(),
+ ReferencedNginxProxies: processedNginxProxies,
BackendTLSPolicies: processedBackendTLSPolicies,
- NginxProxy: npCfg,
NGFPolicies: processedPolicies,
GlobalSettings: globalSettings,
SnippetsFilters: processedSnippetsFilters,
diff --git a/internal/mode/static/state/graph/graph_test.go b/internal/mode/static/state/graph/graph_test.go
index a9e327662b..0e52442b07 100644
--- a/internal/mode/static/state/graph/graph_test.go
+++ b/internal/mode/static/state/graph/graph_test.go
@@ -17,7 +17,8 @@ import (
"sigs.k8s.io/gateway-api/apis/v1alpha3"
"sigs.k8s.io/gateway-api/apis/v1beta1"
- ngfAPI "github.com/nginx/nginx-gateway-fabric/apis/v1alpha1"
+ ngfAPIv1alpha1 "github.com/nginx/nginx-gateway-fabric/apis/v1alpha1"
+ ngfAPIv1alpha2 "github.com/nginx/nginx-gateway-fabric/apis/v1alpha2"
"github.com/nginx/nginx-gateway-fabric/internal/framework/conditions"
"github.com/nginx/nginx-gateway-fabric/internal/framework/controller/index"
"github.com/nginx/nginx-gateway-fabric/internal/framework/helpers"
@@ -110,35 +111,35 @@ func TestBuildGraph(t *testing.T) {
}
refSnippetsFilterExtensionRef := &gatewayv1.LocalObjectReference{
- Group: ngfAPI.GroupName,
+ Group: ngfAPIv1alpha1.GroupName,
Kind: kinds.SnippetsFilter,
Name: "ref-snippets-filter",
}
- unreferencedSnippetsFilter := &ngfAPI.SnippetsFilter{
+ unreferencedSnippetsFilter := &ngfAPIv1alpha1.SnippetsFilter{
ObjectMeta: metav1.ObjectMeta{
Name: "unref-snippets-filter",
Namespace: testNs,
},
- Spec: ngfAPI.SnippetsFilterSpec{
- Snippets: []ngfAPI.Snippet{
+ Spec: ngfAPIv1alpha1.SnippetsFilterSpec{
+ Snippets: []ngfAPIv1alpha1.Snippet{
{
- Context: ngfAPI.NginxContextMain,
+ Context: ngfAPIv1alpha1.NginxContextMain,
Value: "main snippet",
},
},
},
}
- referencedSnippetsFilter := &ngfAPI.SnippetsFilter{
+ referencedSnippetsFilter := &ngfAPIv1alpha1.SnippetsFilter{
ObjectMeta: metav1.ObjectMeta{
Name: "ref-snippets-filter",
Namespace: testNs,
},
- Spec: ngfAPI.SnippetsFilterSpec{
- Snippets: []ngfAPI.Snippet{
+ Spec: ngfAPIv1alpha1.SnippetsFilterSpec{
+ Snippets: []ngfAPIv1alpha1.Snippet{
{
- Context: ngfAPI.NginxContextHTTPServer,
+ Context: ngfAPIv1alpha1.NginxContextHTTPServer,
Value: "server snippet",
},
},
@@ -149,8 +150,8 @@ func TestBuildGraph(t *testing.T) {
Source: unreferencedSnippetsFilter,
Valid: true,
Referenced: false,
- Snippets: map[ngfAPI.NginxContext]string{
- ngfAPI.NginxContextMain: "main snippet",
+ Snippets: map[ngfAPIv1alpha1.NginxContext]string{
+ ngfAPIv1alpha1.NginxContextMain: "main snippet",
},
}
@@ -158,8 +159,8 @@ func TestBuildGraph(t *testing.T) {
Source: referencedSnippetsFilter,
Valid: true,
Referenced: true,
- Snippets: map[ngfAPI.NginxContext]string{
- ngfAPI.NginxContextHTTPServer: "server snippet",
+ Snippets: map[ngfAPIv1alpha1.NginxContext]string{
+ ngfAPIv1alpha1.NginxContextHTTPServer: "server snippet",
},
}
@@ -368,7 +369,7 @@ func TestBuildGraph(t *testing.T) {
},
}
- createGateway := func(name string) *gatewayv1.Gateway {
+ createGateway := func(name, nginxProxyName string) *gatewayv1.Gateway {
return &gatewayv1.Gateway{
ObjectMeta: metav1.ObjectMeta{
Namespace: testNs,
@@ -376,6 +377,13 @@ func TestBuildGraph(t *testing.T) {
},
Spec: gatewayv1.GatewaySpec{
GatewayClassName: gcName,
+ Infrastructure: &gatewayv1.GatewayInfrastructure{
+ ParametersRef: &gatewayv1.LocalParametersReference{
+ Group: ngfAPIv1alpha2.GroupName,
+ Kind: kinds.NginxProxy,
+ Name: nginxProxyName,
+ },
+ },
Listeners: []gatewayv1.Listener{
{
Name: "listener-80-1",
@@ -434,8 +442,35 @@ func TestBuildGraph(t *testing.T) {
}
}
- gw1 := createGateway("gateway-1")
- gw2 := createGateway("gateway-2")
+ gw1 := createGateway("gateway-1", "np-1")
+ gw2 := createGateway("gateway-2", "np-2")
+
+ // np1 is referenced by gw1 and sets the nginx error log to error.
+ // Since gw1 is the winning gateway, we expect this nginx proxy to be configured and merged with the gateway class
+ // nginx proxy configuration.
+ np1 := &ngfAPIv1alpha2.NginxProxy{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "np-1",
+ Namespace: testNs,
+ },
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelError),
+ },
+ },
+ }
+
+ // np2 is referenced by gw2 and sets the IPFamily to IPv6.
+ // Since gw2 is not the winning gateway, we do not expect this nginx proxy to be configured.
+ np2 := &ngfAPIv1alpha2.NginxProxy{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "np-2",
+ Namespace: testNs,
+ },
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ IPFamily: helpers.GetPointer(ngfAPIv1alpha2.IPv6),
+ },
+ }
svc := &v1.Service{
ObjectMeta: metav1.ObjectMeta{
@@ -526,20 +561,22 @@ func TestBuildGraph(t *testing.T) {
},
}
- proxy := &ngfAPI.NginxProxy{
+ // npGlobal is referenced by the gateway class, and we expect it to be configured and merged with np1.
+ npGlobal := &ngfAPIv1alpha2.NginxProxy{
ObjectMeta: metav1.ObjectMeta{
- Name: "nginx-proxy",
+ Name: "np-global",
+ Namespace: testNs,
},
- Spec: ngfAPI.NginxProxySpec{
- Telemetry: &ngfAPI.Telemetry{
- Exporter: &ngfAPI.TelemetryExporter{
- Endpoint: "1.2.3.4:123",
- Interval: helpers.GetPointer(ngfAPI.Duration("5s")),
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ Exporter: &ngfAPIv1alpha2.TelemetryExporter{
+ Endpoint: helpers.GetPointer("1.2.3.4:123"),
+ Interval: helpers.GetPointer(ngfAPIv1alpha1.Duration("5s")),
BatchSize: helpers.GetPointer(int32(512)),
BatchCount: helpers.GetPointer(int32(4)),
},
ServiceName: helpers.GetPointer("my-svc"),
- SpanAttributes: []ngfAPI.SpanAttribute{
+ SpanAttributes: []ngfAPIv1alpha1.SpanAttribute{
{Key: "key", Value: "value"},
},
},
@@ -553,13 +590,13 @@ func TestBuildGraph(t *testing.T) {
// Testing one type of policy per attachment point should suffice.
polGVK := schema.GroupVersionKind{Kind: kinds.ClientSettingsPolicy}
hrPolicyKey := PolicyKey{GVK: polGVK, NsName: types.NamespacedName{Namespace: testNs, Name: "hrPolicy"}}
- hrPolicy := &ngfAPI.ClientSettingsPolicy{
+ hrPolicy := &ngfAPIv1alpha1.ClientSettingsPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "hrPolicy",
Namespace: testNs,
},
TypeMeta: metav1.TypeMeta{Kind: kinds.ClientSettingsPolicy},
- Spec: ngfAPI.ClientSettingsPolicySpec{
+ Spec: ngfAPIv1alpha1.ClientSettingsPolicySpec{
TargetRef: createTestRef(kinds.HTTPRoute, gatewayv1.GroupName, "hr-1"),
},
}
@@ -586,13 +623,13 @@ func TestBuildGraph(t *testing.T) {
}
gwPolicyKey := PolicyKey{GVK: polGVK, NsName: types.NamespacedName{Namespace: testNs, Name: "gwPolicy"}}
- gwPolicy := &ngfAPI.ClientSettingsPolicy{
+ gwPolicy := &ngfAPIv1alpha1.ClientSettingsPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "gwPolicy",
Namespace: testNs,
},
TypeMeta: metav1.TypeMeta{Kind: kinds.ClientSettingsPolicy},
- Spec: ngfAPI.ClientSettingsPolicySpec{
+ Spec: ngfAPIv1alpha1.ClientSettingsPolicySpec{
TargetRef: createTestRef(kinds.Gateway, gatewayv1.GroupName, "gateway-1"),
},
}
@@ -661,14 +698,16 @@ func TestBuildGraph(t *testing.T) {
ConfigMaps: map[types.NamespacedName]*v1.ConfigMap{
client.ObjectKeyFromObject(cm): cm,
},
- NginxProxies: map[types.NamespacedName]*ngfAPI.NginxProxy{
- client.ObjectKeyFromObject(proxy): proxy,
+ NginxProxies: map[types.NamespacedName]*ngfAPIv1alpha2.NginxProxy{
+ client.ObjectKeyFromObject(npGlobal): npGlobal,
+ client.ObjectKeyFromObject(np1): np1,
+ client.ObjectKeyFromObject(np2): np2,
},
NGFPolicies: map[PolicyKey]policies.Policy{
hrPolicyKey: hrPolicy,
gwPolicyKey: gwPolicy,
},
- SnippetsFilters: map[types.NamespacedName]*ngfAPI.SnippetsFilter{
+ SnippetsFilters: map[types.NamespacedName]*ngfAPIv1alpha1.SnippetsFilter{
client.ObjectKeyFromObject(unreferencedSnippetsFilter): unreferencedSnippetsFilter,
client.ObjectKeyFromObject(referencedSnippetsFilter): referencedSnippetsFilter,
},
@@ -820,6 +859,10 @@ func TestBuildGraph(t *testing.T) {
Source: gc,
Valid: true,
Conditions: []conditions.Condition{staticConds.NewGatewayClassResolvedRefs()},
+ NginxProxy: &NginxProxy{
+ Source: npGlobal,
+ Valid: true,
+ },
},
Gateway: &Gateway{
Source: gw1,
@@ -872,6 +915,28 @@ func TestBuildGraph(t *testing.T) {
},
Valid: true,
Policies: []*Policy{processedGwPolicy},
+ NginxProxy: &NginxProxy{
+ Source: np1,
+ Valid: true,
+ },
+ EffectiveNginxProxy: &EffectiveNginxProxy{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ Exporter: &ngfAPIv1alpha2.TelemetryExporter{
+ Endpoint: helpers.GetPointer("1.2.3.4:123"),
+ Interval: helpers.GetPointer(ngfAPIv1alpha1.Duration("5s")),
+ BatchSize: helpers.GetPointer(int32(512)),
+ BatchCount: helpers.GetPointer(int32(4)),
+ },
+ ServiceName: helpers.GetPointer("my-svc"),
+ SpanAttributes: []ngfAPIv1alpha1.SpanAttribute{
+ {Key: "key", Value: "value"},
+ },
+ },
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelError),
+ },
+ },
+ Conditions: []conditions.Condition{staticConds.NewGatewayResolvedRefs()},
},
IgnoredGateways: map[types.NamespacedName]*gatewayv1.Gateway{
{Namespace: testNs, Name: "gateway-2"}: gw2,
@@ -906,9 +971,15 @@ func TestBuildGraph(t *testing.T) {
BackendTLSPolicies: map[types.NamespacedName]*BackendTLSPolicy{
client.ObjectKeyFromObject(btp.Source): &btp,
},
- NginxProxy: &NginxProxy{
- Source: proxy,
- Valid: true,
+ ReferencedNginxProxies: map[types.NamespacedName]*NginxProxy{
+ client.ObjectKeyFromObject(npGlobal): {
+ Source: npGlobal,
+ Valid: true,
+ },
+ client.ObjectKeyFromObject(np1): {
+ Source: np1,
+ Valid: true,
+ },
},
NGFPolicies: map[PolicyKey]*Policy{
hrPolicyKey: processedRoutePolicy,
@@ -941,9 +1012,10 @@ func TestBuildGraph(t *testing.T) {
Spec: gatewayv1.GatewayClassSpec{
ControllerName: controllerName,
ParametersRef: &gatewayv1.ParametersReference{
- Group: gatewayv1.Group("gateway.nginx.org"),
- Kind: gatewayv1.Kind(kinds.NginxProxy),
- Name: "nginx-proxy",
+ Group: gatewayv1.Group("gateway.nginx.org"),
+ Kind: gatewayv1.Kind(kinds.NginxProxy),
+ Name: "np-global",
+ Namespace: helpers.GetPointer(gatewayv1.Namespace(testNs)),
},
},
}
@@ -1122,27 +1194,15 @@ func TestIsReferenced(t *testing.T) {
},
}
- gcWithNginxProxy := &GatewayClass{
- Source: &gatewayv1.GatewayClass{
- Spec: gatewayv1.GatewayClassSpec{
- ParametersRef: &gatewayv1.ParametersReference{
- Group: ngfAPI.GroupName,
- Kind: gatewayv1.Kind(kinds.NginxProxy),
- Name: "nginx-proxy-in-gc",
- },
- },
- },
- }
-
- npNotInGatewayClass := &ngfAPI.NginxProxy{
+ npNotReferenced := &ngfAPIv1alpha2.NginxProxy{
ObjectMeta: metav1.ObjectMeta{
- Name: "nginx-proxy",
+ Name: "nginx-proxy-not-ref",
},
}
- npInGatewayClass := &ngfAPI.NginxProxy{
+ npReferenced := &ngfAPIv1alpha2.NginxProxy{
ObjectMeta: metav1.ObjectMeta{
- Name: "nginx-proxy-in-gc",
+ Name: "nginx-proxy-ref",
},
}
@@ -1165,6 +1225,11 @@ func TestIsReferenced(t *testing.T) {
CACert: []byte(caBlock),
},
},
+ ReferencedNginxProxies: map[types.NamespacedName]*NginxProxy{
+ client.ObjectKeyFromObject(npReferenced): {
+ Source: npReferenced,
+ },
+ },
}
tests := []struct {
@@ -1295,16 +1360,14 @@ func TestIsReferenced(t *testing.T) {
// NginxProxy tests
{
- name: "NginxProxy is referenced in GatewayClass",
- resource: npInGatewayClass,
- gc: gcWithNginxProxy,
+ name: "NginxProxy is referenced",
+ resource: npReferenced,
graph: graph,
expected: true,
},
{
- name: "NginxProxy is not referenced in GatewayClass",
- resource: npNotInGatewayClass,
- gc: gcWithNginxProxy,
+ name: "NginxProxy is not referenced",
+ resource: npNotReferenced,
graph: graph,
expected: false,
},
diff --git a/internal/mode/static/state/graph/grpcroute_test.go b/internal/mode/static/state/graph/grpcroute_test.go
index 0e3edde7be..910e49b898 100644
--- a/internal/mode/static/state/graph/grpcroute_test.go
+++ b/internal/mode/static/state/graph/grpcroute_test.go
@@ -10,7 +10,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
v1 "sigs.k8s.io/gateway-api/apis/v1"
- ngfAPI "github.com/nginx/nginx-gateway-fabric/apis/v1alpha1"
+ ngfAPIv1alpha1 "github.com/nginx/nginx-gateway-fabric/apis/v1alpha1"
"github.com/nginx/nginx-gateway-fabric/internal/framework/conditions"
"github.com/nginx/nginx-gateway-fabric/internal/framework/helpers"
"github.com/nginx/nginx-gateway-fabric/internal/framework/kinds"
@@ -88,7 +88,7 @@ func TestBuildGRPCRoutes(t *testing.T) {
ExtensionRef: &v1.LocalObjectReference{
Name: "sf",
Kind: kinds.SnippetsFilter,
- Group: ngfAPI.GroupName,
+ Group: ngfAPIv1alpha1.GroupName,
},
}
@@ -110,15 +110,15 @@ func TestBuildGRPCRoutes(t *testing.T) {
client.ObjectKeyFromObject(grWrongGateway): grWrongGateway,
}
- sf := &ngfAPI.SnippetsFilter{
+ sf := &ngfAPIv1alpha1.SnippetsFilter{
ObjectMeta: metav1.ObjectMeta{
Namespace: "test",
Name: "sf",
},
- Spec: ngfAPI.SnippetsFilterSpec{
- Snippets: []ngfAPI.Snippet{
+ Spec: ngfAPIv1alpha1.SnippetsFilterSpec{
+ Snippets: []ngfAPIv1alpha1.Snippet{
{
- Context: ngfAPI.NginxContextHTTP,
+ Context: ngfAPIv1alpha1.NginxContextHTTP,
Value: "http snippet",
},
},
@@ -158,8 +158,8 @@ func TestBuildGRPCRoutes(t *testing.T) {
ResolvedExtensionRef: &ExtensionRefFilter{
SnippetsFilter: &SnippetsFilter{
Source: sf,
- Snippets: map[ngfAPI.NginxContext]string{
- ngfAPI.NginxContextHTTP: "http snippet",
+ Snippets: map[ngfAPIv1alpha1.NginxContext]string{
+ ngfAPIv1alpha1.NginxContextHTTP: "http snippet",
},
Valid: true,
Referenced: true,
@@ -194,12 +194,8 @@ func TestBuildGRPCRoutes(t *testing.T) {
validator := &validationfakes.FakeHTTPFieldsValidator{}
- npCfg := &NginxProxy{
- Source: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- DisableHTTP2: false,
- },
- },
+ npCfg := &EffectiveNginxProxy{
+ DisableHTTP2: helpers.GetPointer(false),
}
for _, test := range tests {
@@ -211,8 +207,8 @@ func TestBuildGRPCRoutes(t *testing.T) {
client.ObjectKeyFromObject(sf): {
Source: sf,
Valid: true,
- Snippets: map[ngfAPI.NginxContext]string{
- ngfAPI.NginxContextHTTP: "http snippet",
+ Snippets: map[ngfAPIv1alpha1.NginxContext]string{
+ ngfAPIv1alpha1.NginxContextHTTP: "http snippet",
},
},
}
@@ -351,7 +347,7 @@ func TestBuildGRPCRoute(t *testing.T) {
grValidFilterRule := createGRPCMethodMatch("myService", "myMethod", "Exact")
validSnippetsFilterRef := &v1.LocalObjectReference{
- Group: ngfAPI.GroupName,
+ Group: ngfAPIv1alpha1.GroupName,
Kind: kinds.SnippetsFilter,
Name: "sf",
}
@@ -409,7 +405,7 @@ func TestBuildGRPCRoute(t *testing.T) {
{
Type: v1.GRPCRouteFilterExtensionRef,
ExtensionRef: &v1.LocalObjectReference{
- Group: ngfAPI.GroupName,
+ Group: ngfAPIv1alpha1.GroupName,
Kind: kinds.SnippetsFilter,
Name: "does-not-exist",
},
@@ -428,7 +424,7 @@ func TestBuildGRPCRoute(t *testing.T) {
{
Type: v1.GRPCRouteFilterExtensionRef,
ExtensionRef: &v1.LocalObjectReference{
- Group: ngfAPI.GroupName,
+ Group: ngfAPIv1alpha1.GroupName,
Kind: kinds.SnippetsFilter,
Name: "does-not-exist",
},
diff --git a/internal/mode/static/state/graph/nginxproxy.go b/internal/mode/static/state/graph/nginxproxy.go
index 831a205120..3b013b8f39 100644
--- a/internal/mode/static/state/graph/nginxproxy.go
+++ b/internal/mode/static/state/graph/nginxproxy.go
@@ -1,15 +1,18 @@
package graph
import (
+ "encoding/json"
+ "fmt"
"slices"
"k8s.io/apimachinery/pkg/types"
k8svalidation "k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
+ "sigs.k8s.io/controller-runtime/pkg/client"
v1 "sigs.k8s.io/gateway-api/apis/v1"
- ngfAPI "github.com/nginx/nginx-gateway-fabric/apis/v1alpha1"
- "github.com/nginx/nginx-gateway-fabric/internal/framework/helpers"
+ ngfAPIv1alpha1 "github.com/nginx/nginx-gateway-fabric/apis/v1alpha1"
+ ngfAPIv1alpha2 "github.com/nginx/nginx-gateway-fabric/apis/v1alpha2"
"github.com/nginx/nginx-gateway-fabric/internal/framework/kinds"
"github.com/nginx/nginx-gateway-fabric/internal/mode/static/state/validation"
)
@@ -17,45 +20,169 @@ import (
// NginxProxy represents the NginxProxy resource.
type NginxProxy struct {
// Source is the source resource.
- Source *ngfAPI.NginxProxy
+ Source *ngfAPIv1alpha2.NginxProxy
// ErrMsgs contains the validation errors if they exist, to be included in the GatewayClass condition.
ErrMsgs field.ErrorList
// Valid shows whether the NginxProxy is valid.
Valid bool
}
-// buildNginxProxy validates and returns the NginxProxy associated with the GatewayClass (if it exists).
-func buildNginxProxy(
- nps map[types.NamespacedName]*ngfAPI.NginxProxy,
- gc *v1.GatewayClass,
+// EffectiveNginxProxy holds the result of merging the NginxProxySpec on this resource with the NginxProxySpec on the
+// GatewayClass resource. This is the effective set of config that should be applied to the Gateway.
+type EffectiveNginxProxy ngfAPIv1alpha2.NginxProxySpec
+
+// buildEffectiveNginxProxy builds the effective NginxProxy for the Gateway by merging the GatewayClass and Gateway
+// NginxProxy resources. Fields specified on the Gateway NginxProxy override those set on the GatewayClass NginxProxy.
+func buildEffectiveNginxProxy(gatewayClassNp, gatewayNp *NginxProxy) *EffectiveNginxProxy {
+ gcNpValid, gwNpValid := nginxProxyValid(gatewayClassNp), nginxProxyValid(gatewayNp)
+ if !gcNpValid && !gwNpValid {
+ return nil
+ }
+
+ if !gcNpValid {
+ enp := EffectiveNginxProxy(*gatewayNp.Source.Spec.DeepCopy())
+ return &enp
+ }
+
+ if !gwNpValid {
+ enp := EffectiveNginxProxy(*gatewayClassNp.Source.Spec.DeepCopy())
+ return &enp
+ }
+
+ global := EffectiveNginxProxy(*gatewayClassNp.Source.Spec.DeepCopy())
+ local := EffectiveNginxProxy(*gatewayNp.Source.Spec.DeepCopy())
+
+ // by marshaling the local config and then unmarshaling on top of the global config,
+ // we ensure that any unset local values are set with the global values
+ localBytes, err := json.Marshal(local)
+ if err != nil {
+ panic(
+ fmt.Sprintf(
+ "could not marshal NginxProxy resource referenced by Gateway %s",
+ client.ObjectKeyFromObject(gatewayNp.Source),
+ ),
+ )
+ }
+
+ err = json.Unmarshal(localBytes, &global)
+ if err != nil {
+ panic(
+ fmt.Sprintf(
+ "could not unmarshal NginxProxy resource referenced by GatewayClass %s",
+ client.ObjectKeyFromObject(gatewayClassNp.Source),
+ ),
+ )
+ }
+
+ // this json trick doesn't work for unsetting slices, so we need to do that manually.
+ if local.Telemetry != nil {
+ if local.Telemetry.DisabledFeatures != nil && len(local.Telemetry.DisabledFeatures) == 0 {
+ global.Telemetry.DisabledFeatures = []ngfAPIv1alpha2.DisableTelemetryFeature{}
+ }
+
+ if local.Telemetry.SpanAttributes != nil && len(local.Telemetry.SpanAttributes) == 0 {
+ global.Telemetry.SpanAttributes = []ngfAPIv1alpha1.SpanAttribute{}
+ }
+ }
+
+ if local.RewriteClientIP != nil {
+ if local.RewriteClientIP.TrustedAddresses != nil && len(local.RewriteClientIP.TrustedAddresses) == 0 {
+ global.RewriteClientIP.TrustedAddresses = []ngfAPIv1alpha2.RewriteClientIPAddress{}
+ }
+ }
+
+ return &global
+}
+
+func nginxProxyValid(np *NginxProxy) bool {
+ return np != nil && np.Source != nil && np.Valid
+}
+
+func telemetryEnabledForNginxProxy(np *EffectiveNginxProxy) bool {
+ if np.Telemetry == nil || np.Telemetry.Exporter == nil || np.Telemetry.Exporter.Endpoint == nil {
+ return false
+ }
+
+ if slices.Contains(np.Telemetry.DisabledFeatures, ngfAPIv1alpha2.DisableTracing) {
+ return false
+ }
+
+ return true
+}
+
+func processNginxProxies(
+ nps map[types.NamespacedName]*ngfAPIv1alpha2.NginxProxy,
validator validation.GenericValidator,
-) *NginxProxy {
+ gc *v1.GatewayClass,
+ winningGateway *v1.Gateway,
+) map[types.NamespacedName]*NginxProxy {
+ referencedNginxProxies := make(map[types.NamespacedName]*NginxProxy)
+
if gcReferencesAnyNginxProxy(gc) {
- npCfg := nps[types.NamespacedName{Name: gc.Spec.ParametersRef.Name}]
- if npCfg != nil {
- errs := validateNginxProxy(validator, npCfg)
-
- return &NginxProxy{
- Source: npCfg,
- Valid: len(errs) == 0,
- ErrMsgs: errs,
+ // we will ignore references without namespaces
+ // the gateway class status will contain an error message about the missing namespace
+ if gc.Spec.ParametersRef.Namespace != nil {
+ refNp := types.NamespacedName{
+ Name: gc.Spec.ParametersRef.Name,
+ Namespace: string(*gc.Spec.ParametersRef.Namespace),
+ }
+
+ if np, ok := nps[refNp]; ok {
+ referencedNginxProxies[refNp] = buildNginxProxy(np, validator)
}
}
}
- return nil
+ if gwReferencesAnyNginxProxy(winningGateway) {
+ refNp := types.NamespacedName{
+ Name: winningGateway.Spec.Infrastructure.ParametersRef.Name,
+ Namespace: winningGateway.Namespace,
+ }
+
+ if np, ok := nps[refNp]; ok {
+ referencedNginxProxies[refNp] = buildNginxProxy(np, validator)
+ }
+ }
+
+ if len(referencedNginxProxies) == 0 {
+ return nil
+ }
+
+ return referencedNginxProxies
}
-// isNginxProxyReferenced returns whether or not a specific NginxProxy is referenced in the GatewayClass.
-func isNginxProxyReferenced(npNSName types.NamespacedName, gc *GatewayClass) bool {
- return gc != nil && gcReferencesAnyNginxProxy(gc.Source) && gc.Source.Spec.ParametersRef.Name == npNSName.Name
+// buildNginxProxy validates and returns the NginxProxy associated with the GatewayClass (if it exists).
+func buildNginxProxy(
+ np *ngfAPIv1alpha2.NginxProxy,
+ validator validation.GenericValidator,
+) *NginxProxy {
+ if np != nil {
+ errs := validateNginxProxy(validator, np)
+
+ return &NginxProxy{
+ Source: np,
+ Valid: len(errs) == 0,
+ ErrMsgs: errs,
+ }
+ }
+
+ return nil
}
// gcReferencesNginxProxy returns whether a GatewayClass references any NginxProxy resource.
func gcReferencesAnyNginxProxy(gc *v1.GatewayClass) bool {
if gc != nil {
ref := gc.Spec.ParametersRef
- return ref != nil && ref.Group == ngfAPI.GroupName && ref.Kind == v1.Kind(kinds.NginxProxy)
+ return ref != nil && ref.Group == ngfAPIv1alpha2.GroupName && ref.Kind == kinds.NginxProxy
+ }
+
+ return false
+}
+
+func gwReferencesAnyNginxProxy(gw *v1.Gateway) bool {
+ if gw != nil && gw.Spec.Infrastructure != nil {
+ ref := gw.Spec.Infrastructure.ParametersRef
+ return ref != nil && ref.Group == ngfAPIv1alpha2.GroupName && ref.Kind == kinds.NginxProxy
}
return false
@@ -64,7 +191,7 @@ func gcReferencesAnyNginxProxy(gc *v1.GatewayClass) bool {
// validateNginxProxy performs re-validation on string values in the case of CRD validation failure.
func validateNginxProxy(
validator validation.GenericValidator,
- npCfg *ngfAPI.NginxProxy,
+ npCfg *ngfAPIv1alpha2.NginxProxy,
) field.ErrorList {
var allErrs field.ErrorList
spec := field.NewPath("spec")
@@ -85,8 +212,8 @@ func validateNginxProxy(
exp := telemetry.Exporter
expPath := telPath.Child("exporter")
- if exp.Endpoint != "" {
- if err := validator.ValidateEndpoint(exp.Endpoint); err != nil {
+ if exp.Endpoint != nil {
+ if err := validator.ValidateEndpoint(*exp.Endpoint); err != nil {
allErrs = append(allErrs, field.Invalid(expPath.Child("endpoint"), exp.Endpoint, err.Error()))
}
}
@@ -116,17 +243,15 @@ func validateNginxProxy(
ipFamily := npCfg.Spec.IPFamily
ipFamilyPath := spec.Child("ipFamily")
switch *ipFamily {
- case ngfAPI.Dual, ngfAPI.IPv4, ngfAPI.IPv6:
+ case ngfAPIv1alpha2.Dual, ngfAPIv1alpha2.IPv4, ngfAPIv1alpha2.IPv6:
default:
allErrs = append(
allErrs,
field.NotSupported(
ipFamilyPath,
ipFamily,
- []string{string(ngfAPI.Dual), string(ngfAPI.IPv4), string(ngfAPI.IPv6)}))
+ []string{string(ngfAPIv1alpha2.Dual), string(ngfAPIv1alpha2.IPv4), string(ngfAPIv1alpha2.IPv6)}))
}
- } else {
- npCfg.Spec.IPFamily = helpers.GetPointer[ngfAPI.IPFamilyType](ngfAPI.Dual)
}
allErrs = append(allErrs, validateLogging(npCfg)...)
@@ -138,7 +263,7 @@ func validateNginxProxy(
return allErrs
}
-func validateLogging(npCfg *ngfAPI.NginxProxy) field.ErrorList {
+func validateLogging(npCfg *ngfAPIv1alpha2.NginxProxy) field.ErrorList {
var allErrs field.ErrorList
spec := field.NewPath("spec")
@@ -150,14 +275,14 @@ func validateLogging(npCfg *ngfAPI.NginxProxy) field.ErrorList {
errLevel := string(*logging.ErrorLevel)
validLogLevels := []string{
- string(ngfAPI.NginxLogLevelDebug),
- string(ngfAPI.NginxLogLevelInfo),
- string(ngfAPI.NginxLogLevelNotice),
- string(ngfAPI.NginxLogLevelWarn),
- string(ngfAPI.NginxLogLevelError),
- string(ngfAPI.NginxLogLevelCrit),
- string(ngfAPI.NginxLogLevelAlert),
- string(ngfAPI.NginxLogLevelEmerg),
+ string(ngfAPIv1alpha2.NginxLogLevelDebug),
+ string(ngfAPIv1alpha2.NginxLogLevelInfo),
+ string(ngfAPIv1alpha2.NginxLogLevelNotice),
+ string(ngfAPIv1alpha2.NginxLogLevelWarn),
+ string(ngfAPIv1alpha2.NginxLogLevelError),
+ string(ngfAPIv1alpha2.NginxLogLevelCrit),
+ string(ngfAPIv1alpha2.NginxLogLevelAlert),
+ string(ngfAPIv1alpha2.NginxLogLevelEmerg),
}
if !slices.Contains(validLogLevels, errLevel) {
@@ -175,7 +300,7 @@ func validateLogging(npCfg *ngfAPI.NginxProxy) field.ErrorList {
return allErrs
}
-func validateRewriteClientIP(npCfg *ngfAPI.NginxProxy) field.ErrorList {
+func validateRewriteClientIP(npCfg *ngfAPIv1alpha2.NginxProxy) field.ErrorList {
var allErrs field.ErrorList
spec := field.NewPath("spec")
@@ -194,14 +319,17 @@ func validateRewriteClientIP(npCfg *ngfAPI.NginxProxy) field.ErrorList {
}
switch mode {
- case ngfAPI.RewriteClientIPModeProxyProtocol, ngfAPI.RewriteClientIPModeXForwardedFor:
+ case ngfAPIv1alpha2.RewriteClientIPModeProxyProtocol, ngfAPIv1alpha2.RewriteClientIPModeXForwardedFor:
default:
allErrs = append(
allErrs,
field.NotSupported(
rewriteClientIPPath.Child("mode"),
mode,
- []string{string(ngfAPI.RewriteClientIPModeProxyProtocol), string(ngfAPI.RewriteClientIPModeXForwardedFor)},
+ []string{
+ string(ngfAPIv1alpha2.RewriteClientIPModeProxyProtocol),
+ string(ngfAPIv1alpha2.RewriteClientIPModeXForwardedFor),
+ },
),
)
}
@@ -218,15 +346,15 @@ func validateRewriteClientIP(npCfg *ngfAPI.NginxProxy) field.ErrorList {
valuePath := trustedAddressesPath.Child("value")
switch addr.Type {
- case ngfAPI.RewriteClientIPCIDRAddressType:
+ case ngfAPIv1alpha2.RewriteClientIPCIDRAddressType:
if err := k8svalidation.IsValidCIDR(valuePath, addr.Value); err != nil {
allErrs = append(allErrs, err...)
}
- case ngfAPI.RewriteClientIPIPAddressType:
+ case ngfAPIv1alpha2.RewriteClientIPIPAddressType:
if err := k8svalidation.IsValidIP(valuePath, addr.Value); err != nil {
allErrs = append(allErrs, err...)
}
- case ngfAPI.RewriteClientIPHostnameAddressType:
+ case ngfAPIv1alpha2.RewriteClientIPHostnameAddressType:
if errs := k8svalidation.IsDNS1123Subdomain(addr.Value); len(errs) > 0 {
for _, e := range errs {
allErrs = append(allErrs, field.Invalid(valuePath, addr.Value, e))
@@ -238,9 +366,9 @@ func validateRewriteClientIP(npCfg *ngfAPI.NginxProxy) field.ErrorList {
field.NotSupported(trustedAddressesPath.Child("type"),
addr.Type,
[]string{
- string(ngfAPI.RewriteClientIPCIDRAddressType),
- string(ngfAPI.RewriteClientIPIPAddressType),
- string(ngfAPI.RewriteClientIPHostnameAddressType),
+ string(ngfAPIv1alpha2.RewriteClientIPCIDRAddressType),
+ string(ngfAPIv1alpha2.RewriteClientIPIPAddressType),
+ string(ngfAPIv1alpha2.RewriteClientIPHostnameAddressType),
},
),
)
@@ -251,7 +379,7 @@ func validateRewriteClientIP(npCfg *ngfAPI.NginxProxy) field.ErrorList {
return allErrs
}
-func validateNginxPlus(npCfg *ngfAPI.NginxProxy) field.ErrorList {
+func validateNginxPlus(npCfg *ngfAPIv1alpha2.NginxProxy) field.ErrorList {
var allErrs field.ErrorList
spec := field.NewPath("spec")
@@ -264,11 +392,11 @@ func validateNginxPlus(npCfg *ngfAPI.NginxProxy) field.ErrorList {
valuePath := nginxPlusPath.Child("value")
switch addr.Type {
- case ngfAPI.NginxPlusAllowCIDRAddressType:
+ case ngfAPIv1alpha2.NginxPlusAllowCIDRAddressType:
if err := k8svalidation.IsValidCIDR(valuePath, addr.Value); err != nil {
allErrs = append(allErrs, err...)
}
- case ngfAPI.NginxPlusAllowIPAddressType:
+ case ngfAPIv1alpha2.NginxPlusAllowIPAddressType:
if err := k8svalidation.IsValidIP(valuePath, addr.Value); err != nil {
allErrs = append(allErrs, err...)
}
@@ -278,8 +406,8 @@ func validateNginxPlus(npCfg *ngfAPI.NginxProxy) field.ErrorList {
field.NotSupported(nginxPlusPath.Child("type"),
addr.Type,
[]string{
- string(ngfAPI.NginxPlusAllowCIDRAddressType),
- string(ngfAPI.NginxPlusAllowIPAddressType),
+ string(ngfAPIv1alpha2.NginxPlusAllowCIDRAddressType),
+ string(ngfAPIv1alpha2.NginxPlusAllowIPAddressType),
},
),
)
diff --git a/internal/mode/static/state/graph/nginxproxy_test.go b/internal/mode/static/state/graph/nginxproxy_test.go
index 325a996321..80c7ef6401 100644
--- a/internal/mode/static/state/graph/nginxproxy_test.go
+++ b/internal/mode/static/state/graph/nginxproxy_test.go
@@ -7,78 +7,285 @@ import (
. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
+ "k8s.io/apimachinery/pkg/util/validation/field"
v1 "sigs.k8s.io/gateway-api/apis/v1"
- ngfAPI "github.com/nginx/nginx-gateway-fabric/apis/v1alpha1"
+ ngfAPIv1alpha1 "github.com/nginx/nginx-gateway-fabric/apis/v1alpha1"
+ ngfAPIv1alpha2 "github.com/nginx/nginx-gateway-fabric/apis/v1alpha2"
"github.com/nginx/nginx-gateway-fabric/internal/framework/helpers"
"github.com/nginx/nginx-gateway-fabric/internal/framework/kinds"
+ "github.com/nginx/nginx-gateway-fabric/internal/mode/static/state/validation"
"github.com/nginx/nginx-gateway-fabric/internal/mode/static/state/validation/validationfakes"
)
-func TestGetNginxProxy(t *testing.T) {
+func createValidValidator() *validationfakes.FakeGenericValidator {
+ v := &validationfakes.FakeGenericValidator{}
+ v.ValidateEscapedStringNoVarExpansionReturns(nil)
+ v.ValidateEndpointReturns(nil)
+ v.ValidateServiceNameReturns(nil)
+ v.ValidateNginxDurationReturns(nil)
+
+ return v
+}
+
+func createInvalidValidator() *validationfakes.FakeGenericValidator {
+ v := &validationfakes.FakeGenericValidator{}
+ v.ValidateEscapedStringNoVarExpansionReturns(errors.New("error"))
+ v.ValidateEndpointReturns(errors.New("error"))
+ v.ValidateServiceNameReturns(errors.New("error"))
+ v.ValidateNginxDurationReturns(errors.New("error"))
+
+ return v
+}
+
+func TestBuildEffectiveNginxProxy(t *testing.T) {
t.Parallel()
+
+ newTestNginxProxy := func(
+ ipFam ngfAPIv1alpha2.IPFamilyType,
+ disableFeats []ngfAPIv1alpha2.DisableTelemetryFeature,
+ interval ngfAPIv1alpha1.Duration,
+ batchSize int32,
+ batchCount int32,
+ endpoint string,
+ serviceName string,
+ spanAttr ngfAPIv1alpha1.SpanAttribute,
+ mode ngfAPIv1alpha2.RewriteClientIPModeType,
+ trustedAddr []ngfAPIv1alpha2.RewriteClientIPAddress,
+ logLevel ngfAPIv1alpha2.NginxErrorLogLevel,
+ setIP bool,
+ disableHTTP bool,
+ ) *ngfAPIv1alpha2.NginxProxy {
+ return &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ IPFamily: &ipFam,
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ DisabledFeatures: disableFeats,
+ Exporter: &ngfAPIv1alpha2.TelemetryExporter{
+ Interval: &interval,
+ BatchSize: &batchSize,
+ BatchCount: &batchCount,
+ Endpoint: &endpoint,
+ },
+ ServiceName: &serviceName,
+ SpanAttributes: []ngfAPIv1alpha1.SpanAttribute{spanAttr},
+ },
+ RewriteClientIP: &ngfAPIv1alpha2.RewriteClientIP{
+ Mode: &mode,
+ SetIPRecursively: &setIP,
+ TrustedAddresses: trustedAddr,
+ },
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: &logLevel,
+ },
+ DisableHTTP2: &disableHTTP,
+ },
+ }
+ }
+
+ getNginxProxy := func() *ngfAPIv1alpha2.NginxProxy {
+ return newTestNginxProxy(
+ ngfAPIv1alpha2.Dual,
+ []ngfAPIv1alpha2.DisableTelemetryFeature{ngfAPIv1alpha2.DisableTracing},
+ "10s",
+ 10,
+ 5,
+ "endpoint:1234",
+ "my-service",
+ ngfAPIv1alpha1.SpanAttribute{Key: "key", Value: "val"},
+ ngfAPIv1alpha2.RewriteClientIPModeXForwardedFor,
+ []ngfAPIv1alpha2.RewriteClientIPAddress{
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "10.0.0.1"},
+ },
+ ngfAPIv1alpha2.NginxLogLevelAlert,
+ true,
+ false,
+ )
+ }
+
+ getNginxProxyAllFieldsSetDifferently := func() *ngfAPIv1alpha2.NginxProxy {
+ return newTestNginxProxy(
+ ngfAPIv1alpha2.IPv6,
+ []ngfAPIv1alpha2.DisableTelemetryFeature{},
+ "5s",
+ 8,
+ 2,
+ "diff-endpoint:1234",
+ "diff-service",
+ ngfAPIv1alpha1.SpanAttribute{Key: "diff-key", Value: "diff-val"},
+ ngfAPIv1alpha2.RewriteClientIPModeXForwardedFor,
+ []ngfAPIv1alpha2.RewriteClientIPAddress{
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "10.0.0.1/24"},
+ },
+ ngfAPIv1alpha2.NginxLogLevelError,
+ false,
+ true,
+ )
+ }
+
+ getExpSpec := func() *EffectiveNginxProxy {
+ enp := EffectiveNginxProxy(getNginxProxy().Spec)
+ return &enp
+ }
+
+ getModifiedExpSpec := func(mod func(*ngfAPIv1alpha2.NginxProxy) *ngfAPIv1alpha2.NginxProxy) *EffectiveNginxProxy {
+ enp := EffectiveNginxProxy(mod(getNginxProxy()).Spec)
+ return &enp
+ }
+
tests := []struct {
- nps map[types.NamespacedName]*ngfAPI.NginxProxy
- gc *v1.GatewayClass
- expNP *NginxProxy
- name string
+ gcNp *NginxProxy
+ gwNp *NginxProxy
+ exp *EffectiveNginxProxy
+ name string
}{
{
- nps: map[types.NamespacedName]*ngfAPI.NginxProxy{
- {Name: "np1"}: {},
- },
- gc: nil,
- expNP: nil,
- name: "nil gatewayclass",
+ name: "both gateway class and gateway nginx proxies are nil",
+ gcNp: nil,
+ gwNp: nil,
+ exp: nil,
},
{
- nps: map[types.NamespacedName]*ngfAPI.NginxProxy{},
- gc: &v1.GatewayClass{
- Spec: v1.GatewayClassSpec{
- ParametersRef: &v1.ParametersReference{
- Group: ngfAPI.GroupName,
- Kind: v1.Kind(kinds.NginxProxy),
- Name: "np1",
+ name: "nil gateway class nginx proxy",
+ gcNp: nil,
+ gwNp: &NginxProxy{Valid: true, Source: getNginxProxy()},
+ exp: getExpSpec(),
+ },
+ {
+ name: "nil gateway class nginx proxy; invalid gateway nginx proxy",
+ gcNp: nil,
+ gwNp: &NginxProxy{Valid: false, Source: getNginxProxy()},
+ exp: nil,
+ },
+ {
+ name: "nil gateway class nginx proxy; nil gateway nginx proxy source",
+ gcNp: nil,
+ gwNp: &NginxProxy{Valid: true, Source: nil},
+ exp: nil,
+ },
+ {
+ name: "invalid gateway class nginx proxy",
+ gcNp: &NginxProxy{Valid: false},
+ gwNp: &NginxProxy{Valid: true, Source: getNginxProxy()},
+ exp: getExpSpec(),
+ },
+ {
+ name: "nil gateway class nginx proxy source",
+ gcNp: &NginxProxy{Valid: true, Source: nil},
+ gwNp: &NginxProxy{Valid: true, Source: getNginxProxy()},
+ exp: getExpSpec(),
+ },
+ {
+ name: "nil gateway nginx proxy",
+ gcNp: &NginxProxy{Valid: true, Source: getNginxProxy()},
+ gwNp: nil,
+ exp: getExpSpec(),
+ },
+ {
+ name: "invalid gateway nginx proxy",
+ gcNp: &NginxProxy{Valid: true, Source: getNginxProxy()},
+ gwNp: &NginxProxy{Valid: false},
+ exp: getExpSpec(),
+ },
+ {
+ name: "nil gateway nginx proxy source",
+ gcNp: &NginxProxy{Valid: true, Source: getNginxProxy()},
+ gwNp: &NginxProxy{Valid: true, Source: nil},
+ exp: getExpSpec(),
+ },
+ {
+ name: "both have all fields set; gateway values should win",
+ gcNp: &NginxProxy{Valid: true, Source: getNginxProxy()},
+ gwNp: &NginxProxy{Valid: true, Source: getNginxProxyAllFieldsSetDifferently()},
+ exp: getModifiedExpSpec(func(_ *ngfAPIv1alpha2.NginxProxy) *ngfAPIv1alpha2.NginxProxy {
+ return getNginxProxyAllFieldsSetDifferently()
+ }),
+ },
+ {
+ name: "gateway nginx proxy overrides nginx error log level",
+ gcNp: &NginxProxy{Valid: true, Source: getNginxProxy()},
+ gwNp: &NginxProxy{
+ Valid: true,
+ Source: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelDebug),
+ },
},
},
},
- expNP: nil,
- name: "no nginxproxy resources",
+ exp: getModifiedExpSpec(func(np *ngfAPIv1alpha2.NginxProxy) *ngfAPIv1alpha2.NginxProxy {
+ np.Spec.Logging.ErrorLevel = helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelDebug)
+ return np
+ }),
},
{
- nps: map[types.NamespacedName]*ngfAPI.NginxProxy{
- {Name: "np1"}: {
- ObjectMeta: metav1.ObjectMeta{
- Name: "np1",
- },
- },
- {Name: "np2"}: {
- ObjectMeta: metav1.ObjectMeta{
- Name: "np2",
+ name: "gateway nginx proxy overrides select telemetry values",
+ gcNp: &NginxProxy{Valid: true, Source: getNginxProxy()},
+ gwNp: &NginxProxy{
+ Valid: true,
+ Source: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ ServiceName: helpers.GetPointer("new-service-name"),
+ Exporter: &ngfAPIv1alpha2.TelemetryExporter{
+ BatchSize: helpers.GetPointer[int32](20),
+ Endpoint: helpers.GetPointer("new-endpoint"),
+ },
+ },
},
},
},
- gc: &v1.GatewayClass{
- Spec: v1.GatewayClassSpec{
- ParametersRef: &v1.ParametersReference{
- Group: ngfAPI.GroupName,
- Kind: v1.Kind(kinds.NginxProxy),
- Name: "np2",
+ exp: getModifiedExpSpec(func(np *ngfAPIv1alpha2.NginxProxy) *ngfAPIv1alpha2.NginxProxy {
+ np.Spec.Telemetry.ServiceName = helpers.GetPointer("new-service-name")
+ np.Spec.Telemetry.Exporter.Endpoint = helpers.GetPointer("new-endpoint")
+ np.Spec.Telemetry.Exporter.BatchSize = helpers.GetPointer[int32](20)
+ return np
+ }),
+ },
+ {
+ name: "gateway nginx proxy overrides select rewrite client IP values",
+ gcNp: &NginxProxy{Valid: true, Source: getNginxProxy()},
+ gwNp: &NginxProxy{
+ Valid: true,
+ Source: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ RewriteClientIP: &ngfAPIv1alpha2.RewriteClientIP{
+ Mode: helpers.GetPointer(ngfAPIv1alpha2.RewriteClientIPModeProxyProtocol),
+ SetIPRecursively: helpers.GetPointer(false),
+ },
},
},
},
- expNP: &NginxProxy{
- Source: &ngfAPI.NginxProxy{
- ObjectMeta: metav1.ObjectMeta{
- Name: "np2",
- },
- Spec: ngfAPI.NginxProxySpec{
- IPFamily: helpers.GetPointer(ngfAPI.Dual),
+ exp: getModifiedExpSpec(func(np *ngfAPIv1alpha2.NginxProxy) *ngfAPIv1alpha2.NginxProxy {
+ np.Spec.RewriteClientIP.Mode = helpers.GetPointer(ngfAPIv1alpha2.RewriteClientIPModeProxyProtocol)
+ np.Spec.RewriteClientIP.SetIPRecursively = helpers.GetPointer(false)
+ return np
+ }),
+ },
+ {
+ name: "gateway nginx proxy unsets slices values",
+ gcNp: &NginxProxy{Valid: true, Source: getNginxProxy()},
+ gwNp: &NginxProxy{
+ Valid: true,
+ Source: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ DisabledFeatures: []ngfAPIv1alpha2.DisableTelemetryFeature{},
+ SpanAttributes: []ngfAPIv1alpha1.SpanAttribute{},
+ },
+ RewriteClientIP: &ngfAPIv1alpha2.RewriteClientIP{
+ TrustedAddresses: []ngfAPIv1alpha2.RewriteClientIPAddress{},
+ },
},
},
- Valid: true,
},
- name: "returns correct resource",
+ exp: getModifiedExpSpec(func(np *ngfAPIv1alpha2.NginxProxy) *ngfAPIv1alpha2.NginxProxy {
+ np.Spec.RewriteClientIP.TrustedAddresses = []ngfAPIv1alpha2.RewriteClientIPAddress{}
+ np.Spec.Telemetry.DisabledFeatures = []ngfAPIv1alpha2.DisableTelemetryFeature{}
+ np.Spec.Telemetry.SpanAttributes = []ngfAPIv1alpha1.SpanAttribute{}
+ return np
+ }),
},
}
@@ -87,64 +294,71 @@ func TestGetNginxProxy(t *testing.T) {
t.Parallel()
g := NewWithT(t)
- g.Expect(buildNginxProxy(test.nps, test.gc, &validationfakes.FakeGenericValidator{})).To(Equal(test.expNP))
+ enp := buildEffectiveNginxProxy(test.gcNp, test.gwNp)
+ g.Expect(enp).To(Equal(test.exp))
})
}
}
-func TestIsNginxProxyReferenced(t *testing.T) {
+func TestTelemetryEnabledForNginxProxy(t *testing.T) {
t.Parallel()
+
tests := []struct {
- gc *GatewayClass
- npName types.NamespacedName
- name string
- expRes bool
+ ep *EffectiveNginxProxy
+ name string
+ enabled bool
}{
{
- gc: &GatewayClass{
- Source: &v1.GatewayClass{
- Spec: v1.GatewayClassSpec{
- ParametersRef: &v1.ParametersReference{
- Group: ngfAPI.GroupName,
- Kind: v1.Kind(kinds.NginxProxy),
- Name: "nginx-proxy",
- },
- },
+ name: "telemetry struct is nil",
+ ep: &EffectiveNginxProxy{
+ Telemetry: nil,
+ },
+ enabled: false,
+ },
+ {
+ name: "telemetry exporter is nil",
+ ep: &EffectiveNginxProxy{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ Exporter: nil,
},
},
- npName: types.NamespacedName{},
- expRes: false,
- name: "nil nginxproxy",
+ enabled: false,
},
{
- gc: nil,
- npName: types.NamespacedName{Name: "nginx-proxy"},
- expRes: false,
- name: "nil gatewayclass",
+ name: "tracing is disabled",
+ ep: &EffectiveNginxProxy{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ DisabledFeatures: []ngfAPIv1alpha2.DisableTelemetryFeature{
+ ngfAPIv1alpha2.DisableTracing,
+ },
+ Exporter: &ngfAPIv1alpha2.TelemetryExporter{
+ Endpoint: helpers.GetPointer("new-endpoint"),
+ },
+ },
+ },
+ enabled: false,
},
{
- gc: &GatewayClass{
- Source: nil,
+ name: "exporter endpoint is nil",
+ ep: &EffectiveNginxProxy{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ Exporter: &ngfAPIv1alpha2.TelemetryExporter{
+ Endpoint: nil,
+ },
+ },
},
- npName: types.NamespacedName{Name: "nginx-proxy"},
- expRes: false,
- name: "nil gatewayclass source",
+ enabled: false,
},
{
- gc: &GatewayClass{
- Source: &v1.GatewayClass{
- Spec: v1.GatewayClassSpec{
- ParametersRef: &v1.ParametersReference{
- Group: ngfAPI.GroupName,
- Kind: v1.Kind(kinds.NginxProxy),
- Name: "nginx-proxy",
- },
+ name: "normal case; enabled",
+ ep: &EffectiveNginxProxy{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ Exporter: &ngfAPIv1alpha2.TelemetryExporter{
+ Endpoint: helpers.GetPointer("new-endpoint"),
},
},
},
- npName: types.NamespacedName{Name: "nginx-proxy"},
- expRes: true,
- name: "references the NginxProxy",
+ enabled: true,
},
}
@@ -153,7 +367,162 @@ func TestIsNginxProxyReferenced(t *testing.T) {
t.Parallel()
g := NewWithT(t)
- g.Expect(isNginxProxyReferenced(test.npName, test.gc)).To(Equal(test.expRes))
+ enabled := telemetryEnabledForNginxProxy(test.ep)
+ g.Expect(enabled).To(Equal(test.enabled))
+ })
+ }
+}
+
+func TestProcessNginxProxies(t *testing.T) {
+ t.Parallel()
+
+ gatewayClassNpName := types.NamespacedName{Namespace: "gc-ns", Name: "gc-np"}
+ gatewayNpName := types.NamespacedName{Namespace: "gw-ns", Name: "gw-np"}
+ unreferencedNpName := types.NamespacedName{Namespace: "test", Name: "unref"}
+
+ getTestNp := func(nsname types.NamespacedName) *ngfAPIv1alpha2.NginxProxy {
+ return &ngfAPIv1alpha2.NginxProxy{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: nsname.Namespace,
+ Name: nsname.Name,
+ },
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ ServiceName: helpers.GetPointer("service-name"),
+ },
+ },
+ }
+ }
+
+ gateway := &v1.Gateway{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: "gw-ns",
+ },
+ Spec: v1.GatewaySpec{
+ Infrastructure: &v1.GatewayInfrastructure{
+ ParametersRef: &v1.LocalParametersReference{
+ Group: ngfAPIv1alpha2.GroupName,
+ Kind: kinds.NginxProxy,
+ Name: gatewayNpName.Name,
+ },
+ },
+ },
+ }
+
+ gatewayClass := &v1.GatewayClass{
+ Spec: v1.GatewayClassSpec{
+ ParametersRef: &v1.ParametersReference{
+ Group: ngfAPIv1alpha2.GroupName,
+ Kind: kinds.NginxProxy,
+ Name: gatewayClassNpName.Name,
+ Namespace: helpers.GetPointer[v1.Namespace]("gc-ns"),
+ },
+ },
+ }
+
+ gatewayClassRefMissingNs := &v1.GatewayClass{
+ Spec: v1.GatewayClassSpec{
+ ParametersRef: &v1.ParametersReference{
+ Group: ngfAPIv1alpha2.GroupName,
+ Kind: kinds.NginxProxy,
+ Name: gatewayClassNpName.Name,
+ },
+ },
+ }
+
+ getNpMap := func() map[types.NamespacedName]*ngfAPIv1alpha2.NginxProxy {
+ return map[types.NamespacedName]*ngfAPIv1alpha2.NginxProxy{
+ gatewayClassNpName: getTestNp(gatewayClassNpName),
+ gatewayNpName: getTestNp(gatewayNpName),
+ unreferencedNpName: getTestNp(unreferencedNpName),
+ }
+ }
+
+ getExpResult := func(valid bool) map[types.NamespacedName]*NginxProxy {
+ var errMsgs field.ErrorList
+ if !valid {
+ errMsgs = field.ErrorList{
+ field.Invalid(field.NewPath("spec.telemetry.serviceName"), "service-name", "error"),
+ }
+ }
+
+ return map[types.NamespacedName]*NginxProxy{
+ gatewayNpName: {
+ Valid: valid,
+ ErrMsgs: errMsgs,
+ Source: getTestNp(gatewayNpName),
+ },
+ gatewayClassNpName: {
+ Valid: valid,
+ ErrMsgs: errMsgs,
+ Source: getTestNp(gatewayClassNpName),
+ },
+ }
+ }
+
+ tests := []struct {
+ validator validation.GenericValidator
+ nps map[types.NamespacedName]*ngfAPIv1alpha2.NginxProxy
+ gc *v1.GatewayClass
+ gw *v1.Gateway
+ expResult map[types.NamespacedName]*NginxProxy
+ name string
+ }{
+ {
+ name: "no nginx proxies",
+ nps: nil,
+ gc: gatewayClass,
+ gw: gateway,
+ validator: createValidValidator(),
+ expResult: nil,
+ },
+ {
+ name: "gateway class param ref is missing namespace",
+ nps: map[types.NamespacedName]*ngfAPIv1alpha2.NginxProxy{
+ gatewayClassNpName: getTestNp(gatewayClassNpName),
+ gatewayNpName: getTestNp(gatewayNpName),
+ },
+ gc: gatewayClassRefMissingNs,
+ gw: gateway,
+ validator: createValidValidator(),
+ expResult: map[types.NamespacedName]*NginxProxy{
+ gatewayNpName: {
+ Valid: true,
+ Source: getTestNp(gatewayNpName),
+ },
+ },
+ },
+ {
+ name: "normal case; both nginx proxies are valid",
+ nps: getNpMap(),
+ gc: gatewayClass,
+ gw: gateway,
+ validator: createValidValidator(),
+ expResult: getExpResult(true),
+ },
+ {
+ name: "normal case; both nginx proxies are invalid",
+ nps: getNpMap(),
+ gc: gatewayClass,
+ gw: gateway,
+ validator: createInvalidValidator(),
+ expResult: getExpResult(false),
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ t.Parallel()
+ g := NewWithT(t)
+
+ result := processNginxProxies(
+ test.nps,
+ test.validator,
+ test.gc,
+ test.gw,
+ )
+
+ g.Expect(helpers.Diff(test.expResult, result)).To(BeEmpty())
})
}
}
@@ -194,7 +563,7 @@ func TestGCReferencesAnyNginxProxy(t *testing.T) {
gc: &v1.GatewayClass{
Spec: v1.GatewayClassSpec{
ParametersRef: &v1.ParametersReference{
- Group: ngfAPI.GroupName,
+ Group: ngfAPIv1alpha2.GroupName,
Kind: v1.Kind("WrongKind"),
Name: "wrong-kind",
},
@@ -207,7 +576,7 @@ func TestGCReferencesAnyNginxProxy(t *testing.T) {
gc: &v1.GatewayClass{
Spec: v1.GatewayClassSpec{
ParametersRef: &v1.ParametersReference{
- Group: ngfAPI.GroupName,
+ Group: ngfAPIv1alpha2.GroupName,
Kind: v1.Kind(kinds.NginxProxy),
Name: "nginx-proxy",
},
@@ -228,30 +597,95 @@ func TestGCReferencesAnyNginxProxy(t *testing.T) {
}
}
-func createValidValidator() *validationfakes.FakeGenericValidator {
- v := &validationfakes.FakeGenericValidator{}
- v.ValidateEscapedStringNoVarExpansionReturns(nil)
- v.ValidateEndpointReturns(nil)
- v.ValidateServiceNameReturns(nil)
- v.ValidateNginxDurationReturns(nil)
-
- return v
-}
+func TestGWReferencesAnyNginxProxy(t *testing.T) {
+ t.Parallel()
+ tests := []struct {
+ gw *v1.Gateway
+ name string
+ expRes bool
+ }{
+ {
+ gw: nil,
+ expRes: false,
+ name: "nil gateway",
+ },
+ {
+ gw: &v1.Gateway{
+ Spec: v1.GatewaySpec{},
+ },
+ expRes: false,
+ name: "nil infrastructure",
+ },
+ {
+ gw: &v1.Gateway{
+ Spec: v1.GatewaySpec{
+ Infrastructure: &v1.GatewayInfrastructure{},
+ },
+ },
+ expRes: false,
+ name: "nil parametersRef",
+ },
+ {
+ gw: &v1.Gateway{
+ Spec: v1.GatewaySpec{
+ Infrastructure: &v1.GatewayInfrastructure{
+ ParametersRef: &v1.LocalParametersReference{
+ Group: v1.Group("wrong-group"),
+ Kind: v1.Kind(kinds.NginxProxy),
+ Name: "wrong-group",
+ },
+ },
+ },
+ },
+ expRes: false,
+ name: "wrong group name",
+ },
+ {
+ gw: &v1.Gateway{
+ Spec: v1.GatewaySpec{
+ Infrastructure: &v1.GatewayInfrastructure{
+ ParametersRef: &v1.LocalParametersReference{
+ Group: v1.Group(ngfAPIv1alpha2.GroupName),
+ Kind: v1.Kind("wrong-kind"),
+ Name: "wrong-kind",
+ },
+ },
+ },
+ },
+ expRes: false,
+ name: "wrong kind",
+ },
+ {
+ gw: &v1.Gateway{
+ Spec: v1.GatewaySpec{
+ Infrastructure: &v1.GatewayInfrastructure{
+ ParametersRef: &v1.LocalParametersReference{
+ Group: v1.Group(ngfAPIv1alpha2.GroupName),
+ Kind: v1.Kind(kinds.NginxProxy),
+ Name: "normal",
+ },
+ },
+ },
+ },
+ expRes: true,
+ name: "references an NginxProxy",
+ },
+ }
-func createInvalidValidator() *validationfakes.FakeGenericValidator {
- v := &validationfakes.FakeGenericValidator{}
- v.ValidateEscapedStringNoVarExpansionReturns(errors.New("error"))
- v.ValidateEndpointReturns(errors.New("error"))
- v.ValidateServiceNameReturns(errors.New("error"))
- v.ValidateNginxDurationReturns(errors.New("error"))
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ t.Parallel()
+ g := NewWithT(t)
- return v
+ g.Expect(gwReferencesAnyNginxProxy(test.gw)).To(Equal(test.expRes))
+ })
+ }
}
func TestValidateNginxProxy(t *testing.T) {
t.Parallel()
tests := []struct {
- np *ngfAPI.NginxProxy
+ np *ngfAPIv1alpha2.NginxProxy
validator *validationfakes.FakeGenericValidator
name string
expErrSubstring string
@@ -260,36 +694,36 @@ func TestValidateNginxProxy(t *testing.T) {
{
name: "valid nginxproxy",
validator: createValidValidator(),
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- Telemetry: &ngfAPI.Telemetry{
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
ServiceName: helpers.GetPointer("my-svc"),
- Exporter: &ngfAPI.TelemetryExporter{
- Interval: helpers.GetPointer[ngfAPI.Duration]("5ms"),
- Endpoint: "my-endpoint",
+ Exporter: &ngfAPIv1alpha2.TelemetryExporter{
+ Interval: helpers.GetPointer[ngfAPIv1alpha1.Duration]("5ms"),
+ Endpoint: helpers.GetPointer("my-endpoint"),
},
- SpanAttributes: []ngfAPI.SpanAttribute{
+ SpanAttributes: []ngfAPIv1alpha1.SpanAttribute{
{Key: "key", Value: "value"},
},
},
- IPFamily: helpers.GetPointer[ngfAPI.IPFamilyType](ngfAPI.Dual),
- RewriteClientIP: &ngfAPI.RewriteClientIP{
+ IPFamily: helpers.GetPointer[ngfAPIv1alpha2.IPFamilyType](ngfAPIv1alpha2.Dual),
+ RewriteClientIP: &ngfAPIv1alpha2.RewriteClientIP{
SetIPRecursively: helpers.GetPointer(true),
- TrustedAddresses: []ngfAPI.RewriteClientIPAddress{
+ TrustedAddresses: []ngfAPIv1alpha2.RewriteClientIPAddress{
{
- Type: ngfAPI.RewriteClientIPCIDRAddressType,
+ Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType,
Value: "2001:db8:a0b:12f0::1/32",
},
{
- Type: ngfAPI.RewriteClientIPIPAddressType,
+ Type: ngfAPIv1alpha2.RewriteClientIPIPAddressType,
Value: "1.1.1.1",
},
{
- Type: ngfAPI.RewriteClientIPHostnameAddressType,
+ Type: ngfAPIv1alpha2.RewriteClientIPHostnameAddressType,
Value: "example.com",
},
},
- Mode: helpers.GetPointer(ngfAPI.RewriteClientIPModeProxyProtocol),
+ Mode: helpers.GetPointer(ngfAPIv1alpha2.RewriteClientIPModeProxyProtocol),
},
},
},
@@ -298,9 +732,9 @@ func TestValidateNginxProxy(t *testing.T) {
{
name: "invalid serviceName",
validator: createInvalidValidator(),
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- Telemetry: &ngfAPI.Telemetry{
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
ServiceName: helpers.GetPointer("my-svc"), // any value is invalid by the validator
},
},
@@ -311,11 +745,11 @@ func TestValidateNginxProxy(t *testing.T) {
{
name: "invalid endpoint",
validator: createInvalidValidator(),
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- Telemetry: &ngfAPI.Telemetry{
- Exporter: &ngfAPI.TelemetryExporter{
- Endpoint: "my-endpoint", // any value is invalid by the validator
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ Exporter: &ngfAPIv1alpha2.TelemetryExporter{
+ Endpoint: helpers.GetPointer("my-endpoint"), // any value is invalid by the validator
},
},
},
@@ -326,11 +760,11 @@ func TestValidateNginxProxy(t *testing.T) {
{
name: "invalid interval",
validator: createInvalidValidator(),
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- Telemetry: &ngfAPI.Telemetry{
- Exporter: &ngfAPI.TelemetryExporter{
- Interval: helpers.GetPointer[ngfAPI.Duration](
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ Exporter: &ngfAPIv1alpha2.TelemetryExporter{
+ Interval: helpers.GetPointer[ngfAPIv1alpha1.Duration](
"my-interval",
), // any value is invalid by the validator
},
@@ -343,10 +777,10 @@ func TestValidateNginxProxy(t *testing.T) {
{
name: "invalid spanAttributes",
validator: createInvalidValidator(),
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- Telemetry: &ngfAPI.Telemetry{
- SpanAttributes: []ngfAPI.SpanAttribute{
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{
+ SpanAttributes: []ngfAPIv1alpha1.SpanAttribute{
{Key: "my-key", Value: "my-value"}, // any value is invalid by the validator
},
},
@@ -358,10 +792,10 @@ func TestValidateNginxProxy(t *testing.T) {
{
name: "invalid ipFamily type",
validator: createInvalidValidator(),
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- Telemetry: &ngfAPI.Telemetry{},
- IPFamily: helpers.GetPointer[ngfAPI.IPFamilyType]("invalid"),
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Telemetry: &ngfAPIv1alpha2.Telemetry{},
+ IPFamily: helpers.GetPointer[ngfAPIv1alpha2.IPFamilyType]("invalid"),
},
},
expErrSubstring: "spec.ipFamily",
@@ -386,7 +820,7 @@ func TestValidateNginxProxy(t *testing.T) {
func TestValidateRewriteClientIP(t *testing.T) {
t.Parallel()
tests := []struct {
- np *ngfAPI.NginxProxy
+ np *ngfAPIv1alpha2.NginxProxy
validator *validationfakes.FakeGenericValidator
name string
errorString string
@@ -395,33 +829,33 @@ func TestValidateRewriteClientIP(t *testing.T) {
{
name: "valid rewriteClientIP",
validator: createValidValidator(),
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- RewriteClientIP: &ngfAPI.RewriteClientIP{
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ RewriteClientIP: &ngfAPIv1alpha2.RewriteClientIP{
SetIPRecursively: helpers.GetPointer(true),
- TrustedAddresses: []ngfAPI.RewriteClientIPAddress{
+ TrustedAddresses: []ngfAPIv1alpha2.RewriteClientIPAddress{
{
- Type: ngfAPI.RewriteClientIPCIDRAddressType,
+ Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType,
Value: "2001:db8:a0b:12f0::1/32",
},
{
- Type: ngfAPI.RewriteClientIPCIDRAddressType,
+ Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType,
Value: "10.56.32.11/32",
},
{
- Type: ngfAPI.RewriteClientIPIPAddressType,
+ Type: ngfAPIv1alpha2.RewriteClientIPIPAddressType,
Value: "1.1.1.1",
},
{
- Type: ngfAPI.RewriteClientIPIPAddressType,
+ Type: ngfAPIv1alpha2.RewriteClientIPIPAddressType,
Value: "2001:db8:a0b:12f0::1",
},
{
- Type: ngfAPI.RewriteClientIPHostnameAddressType,
+ Type: ngfAPIv1alpha2.RewriteClientIPHostnameAddressType,
Value: "example.com",
},
},
- Mode: helpers.GetPointer(ngfAPI.RewriteClientIPModeProxyProtocol),
+ Mode: helpers.GetPointer(ngfAPIv1alpha2.RewriteClientIPModeProxyProtocol),
},
},
},
@@ -430,21 +864,21 @@ func TestValidateRewriteClientIP(t *testing.T) {
{
name: "invalid CIDR in trustedAddresses",
validator: createInvalidValidator(),
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- RewriteClientIP: &ngfAPI.RewriteClientIP{
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ RewriteClientIP: &ngfAPIv1alpha2.RewriteClientIP{
SetIPRecursively: helpers.GetPointer(true),
- TrustedAddresses: []ngfAPI.RewriteClientIPAddress{
+ TrustedAddresses: []ngfAPIv1alpha2.RewriteClientIPAddress{
{
- Type: ngfAPI.RewriteClientIPCIDRAddressType,
+ Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType,
Value: "2001:db8::/129",
},
{
- Type: ngfAPI.RewriteClientIPCIDRAddressType,
+ Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType,
Value: "10.0.0.1/32",
},
},
- Mode: helpers.GetPointer(ngfAPI.RewriteClientIPModeProxyProtocol),
+ Mode: helpers.GetPointer(ngfAPIv1alpha2.RewriteClientIPModeProxyProtocol),
},
},
},
@@ -455,21 +889,21 @@ func TestValidateRewriteClientIP(t *testing.T) {
{
name: "invalid IP address in trustedAddresses",
validator: createInvalidValidator(),
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- RewriteClientIP: &ngfAPI.RewriteClientIP{
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ RewriteClientIP: &ngfAPIv1alpha2.RewriteClientIP{
SetIPRecursively: helpers.GetPointer(true),
- TrustedAddresses: []ngfAPI.RewriteClientIPAddress{
+ TrustedAddresses: []ngfAPIv1alpha2.RewriteClientIPAddress{
{
- Type: ngfAPI.RewriteClientIPIPAddressType,
+ Type: ngfAPIv1alpha2.RewriteClientIPIPAddressType,
Value: "1.2.3.4.5",
},
{
- Type: ngfAPI.RewriteClientIPIPAddressType,
+ Type: ngfAPIv1alpha2.RewriteClientIPIPAddressType,
Value: "10.0.0.1",
},
},
- Mode: helpers.GetPointer(ngfAPI.RewriteClientIPModeProxyProtocol),
+ Mode: helpers.GetPointer(ngfAPIv1alpha2.RewriteClientIPModeProxyProtocol),
},
},
},
@@ -480,21 +914,21 @@ func TestValidateRewriteClientIP(t *testing.T) {
{
name: "invalid hostname in trustedAddresses",
validator: createInvalidValidator(),
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- RewriteClientIP: &ngfAPI.RewriteClientIP{
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ RewriteClientIP: &ngfAPIv1alpha2.RewriteClientIP{
SetIPRecursively: helpers.GetPointer(true),
- TrustedAddresses: []ngfAPI.RewriteClientIPAddress{
+ TrustedAddresses: []ngfAPIv1alpha2.RewriteClientIPAddress{
{
- Type: ngfAPI.RewriteClientIPHostnameAddressType,
+ Type: ngfAPIv1alpha2.RewriteClientIPHostnameAddressType,
Value: "bad-host$%^",
},
{
- Type: ngfAPI.RewriteClientIPHostnameAddressType,
+ Type: ngfAPIv1alpha2.RewriteClientIPHostnameAddressType,
Value: "example.com",
},
},
- Mode: helpers.GetPointer(ngfAPI.RewriteClientIPModeProxyProtocol),
+ Mode: helpers.GetPointer(ngfAPIv1alpha2.RewriteClientIPModeProxyProtocol),
},
},
},
@@ -507,10 +941,10 @@ func TestValidateRewriteClientIP(t *testing.T) {
{
name: "invalid when mode is set and trustedAddresses is empty",
validator: createInvalidValidator(),
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- RewriteClientIP: &ngfAPI.RewriteClientIP{
- Mode: helpers.GetPointer(ngfAPI.RewriteClientIPModeProxyProtocol),
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ RewriteClientIP: &ngfAPIv1alpha2.RewriteClientIP{
+ Mode: helpers.GetPointer(ngfAPIv1alpha2.RewriteClientIPModeProxyProtocol),
},
},
},
@@ -520,32 +954,32 @@ func TestValidateRewriteClientIP(t *testing.T) {
{
name: "invalid when trustedAddresses is greater in length than 16",
validator: createInvalidValidator(),
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- RewriteClientIP: &ngfAPI.RewriteClientIP{
- Mode: helpers.GetPointer(ngfAPI.RewriteClientIPModeProxyProtocol),
- TrustedAddresses: []ngfAPI.RewriteClientIPAddress{
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ RewriteClientIP: &ngfAPIv1alpha2.RewriteClientIP{
+ Mode: helpers.GetPointer(ngfAPIv1alpha2.RewriteClientIPModeProxyProtocol),
+ TrustedAddresses: []ngfAPIv1alpha2.RewriteClientIPAddress{
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
},
},
},
@@ -556,17 +990,17 @@ func TestValidateRewriteClientIP(t *testing.T) {
{
name: "invalid when mode is not proxyProtocol or XForwardedFor",
validator: createInvalidValidator(),
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- RewriteClientIP: &ngfAPI.RewriteClientIP{
- Mode: helpers.GetPointer(ngfAPI.RewriteClientIPModeType("invalid")),
- TrustedAddresses: []ngfAPI.RewriteClientIPAddress{
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ RewriteClientIP: &ngfAPIv1alpha2.RewriteClientIP{
+ Mode: helpers.GetPointer(ngfAPIv1alpha2.RewriteClientIPModeType("invalid")),
+ TrustedAddresses: []ngfAPIv1alpha2.RewriteClientIPAddress{
{
- Type: ngfAPI.RewriteClientIPCIDRAddressType,
+ Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType,
Value: "2001:db8:a0b:12f0::1/32",
},
{
- Type: ngfAPI.RewriteClientIPCIDRAddressType,
+ Type: ngfAPIv1alpha2.RewriteClientIPCIDRAddressType,
Value: "10.0.0.1/32",
},
},
@@ -580,10 +1014,10 @@ func TestValidateRewriteClientIP(t *testing.T) {
{
name: "invalid when mode is not proxyProtocol or XForwardedFor and trustedAddresses is empty",
validator: createInvalidValidator(),
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- RewriteClientIP: &ngfAPI.RewriteClientIP{
- Mode: helpers.GetPointer(ngfAPI.RewriteClientIPModeType("invalid")),
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ RewriteClientIP: &ngfAPIv1alpha2.RewriteClientIP{
+ Mode: helpers.GetPointer(ngfAPIv1alpha2.RewriteClientIPModeType("invalid")),
},
},
},
@@ -595,17 +1029,17 @@ func TestValidateRewriteClientIP(t *testing.T) {
{
name: "invalid address type in trustedAddresses",
validator: createInvalidValidator(),
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- RewriteClientIP: &ngfAPI.RewriteClientIP{
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ RewriteClientIP: &ngfAPIv1alpha2.RewriteClientIP{
SetIPRecursively: helpers.GetPointer(true),
- TrustedAddresses: []ngfAPI.RewriteClientIPAddress{
+ TrustedAddresses: []ngfAPIv1alpha2.RewriteClientIPAddress{
{
- Type: ngfAPI.RewriteClientIPAddressType("invalid"),
+ Type: ngfAPIv1alpha2.RewriteClientIPAddressType("invalid"),
Value: "2001:db8::/129",
},
},
- Mode: helpers.GetPointer(ngfAPI.RewriteClientIPModeProxyProtocol),
+ Mode: helpers.GetPointer(ngfAPIv1alpha2.RewriteClientIPModeProxyProtocol),
},
},
},
@@ -631,19 +1065,19 @@ func TestValidateRewriteClientIP(t *testing.T) {
func TestValidateLogging(t *testing.T) {
t.Parallel()
- invalidLogLevel := ngfAPI.NginxErrorLogLevel("invalid-log-level")
+ invalidLogLevel := ngfAPIv1alpha2.NginxErrorLogLevel("invalid-log-level")
tests := []struct {
- np *ngfAPI.NginxProxy
+ np *ngfAPIv1alpha2.NginxProxy
name string
errorString string
expectErrCount int
}{
{
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- Logging: &ngfAPI.NginxLogging{
- ErrorLevel: helpers.GetPointer(ngfAPI.NginxLogLevelDebug),
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelDebug),
},
},
},
@@ -652,10 +1086,10 @@ func TestValidateLogging(t *testing.T) {
expectErrCount: 0,
},
{
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- Logging: &ngfAPI.NginxLogging{
- ErrorLevel: helpers.GetPointer(ngfAPI.NginxLogLevelInfo),
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelInfo),
},
},
},
@@ -664,10 +1098,10 @@ func TestValidateLogging(t *testing.T) {
expectErrCount: 0,
},
{
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- Logging: &ngfAPI.NginxLogging{
- ErrorLevel: helpers.GetPointer(ngfAPI.NginxLogLevelNotice),
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelNotice),
},
},
},
@@ -676,10 +1110,10 @@ func TestValidateLogging(t *testing.T) {
expectErrCount: 0,
},
{
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- Logging: &ngfAPI.NginxLogging{
- ErrorLevel: helpers.GetPointer(ngfAPI.NginxLogLevelWarn),
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelWarn),
},
},
},
@@ -688,10 +1122,10 @@ func TestValidateLogging(t *testing.T) {
expectErrCount: 0,
},
{
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- Logging: &ngfAPI.NginxLogging{
- ErrorLevel: helpers.GetPointer(ngfAPI.NginxLogLevelError),
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelError),
},
},
},
@@ -700,10 +1134,10 @@ func TestValidateLogging(t *testing.T) {
expectErrCount: 0,
},
{
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- Logging: &ngfAPI.NginxLogging{
- ErrorLevel: helpers.GetPointer(ngfAPI.NginxLogLevelCrit),
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelCrit),
},
},
},
@@ -712,10 +1146,10 @@ func TestValidateLogging(t *testing.T) {
expectErrCount: 0,
},
{
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- Logging: &ngfAPI.NginxLogging{
- ErrorLevel: helpers.GetPointer(ngfAPI.NginxLogLevelAlert),
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelAlert),
},
},
},
@@ -724,10 +1158,10 @@ func TestValidateLogging(t *testing.T) {
expectErrCount: 0,
},
{
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- Logging: &ngfAPI.NginxLogging{
- ErrorLevel: helpers.GetPointer(ngfAPI.NginxLogLevelEmerg),
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
+ ErrorLevel: helpers.GetPointer(ngfAPIv1alpha2.NginxLogLevelEmerg),
},
},
},
@@ -736,9 +1170,9 @@ func TestValidateLogging(t *testing.T) {
expectErrCount: 0,
},
{
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- Logging: &ngfAPI.NginxLogging{
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Logging: &ngfAPIv1alpha2.NginxLogging{
ErrorLevel: &invalidLogLevel,
},
},
@@ -749,9 +1183,9 @@ func TestValidateLogging(t *testing.T) {
expectErrCount: 1,
},
{
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- Logging: &ngfAPI.NginxLogging{},
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ Logging: &ngfAPIv1alpha2.NginxLogging{},
},
},
name: "empty log level",
@@ -778,20 +1212,20 @@ func TestValidateNginxPlus(t *testing.T) {
t.Parallel()
tests := []struct {
- np *ngfAPI.NginxProxy
+ np *ngfAPIv1alpha2.NginxProxy
name string
errorString string
expectErrCount int
}{
{
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- NginxPlus: &ngfAPI.NginxPlus{
- AllowedAddresses: []ngfAPI.NginxPlusAllowAddress{
- {Type: ngfAPI.NginxPlusAllowIPAddressType, Value: "2001:db8:a0b:12f0::1"},
- {Type: ngfAPI.NginxPlusAllowCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.NginxPlusAllowIPAddressType, Value: "127.0.0.3"},
- {Type: ngfAPI.NginxPlusAllowCIDRAddressType, Value: "127.0.0.3/32"},
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ NginxPlus: &ngfAPIv1alpha2.NginxPlus{
+ AllowedAddresses: []ngfAPIv1alpha2.NginxPlusAllowAddress{
+ {Type: ngfAPIv1alpha2.NginxPlusAllowIPAddressType, Value: "2001:db8:a0b:12f0::1"},
+ {Type: ngfAPIv1alpha2.NginxPlusAllowCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.NginxPlusAllowIPAddressType, Value: "127.0.0.3"},
+ {Type: ngfAPIv1alpha2.NginxPlusAllowCIDRAddressType, Value: "127.0.0.3/32"},
},
},
},
@@ -801,12 +1235,12 @@ func TestValidateNginxPlus(t *testing.T) {
expectErrCount: 0,
},
{
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- NginxPlus: &ngfAPI.NginxPlus{
- AllowedAddresses: []ngfAPI.NginxPlusAllowAddress{
- {Type: ngfAPI.NginxPlusAllowCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
- {Type: ngfAPI.NginxPlusAllowCIDRAddressType, Value: "127.0.0.3/37"},
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ NginxPlus: &ngfAPIv1alpha2.NginxPlus{
+ AllowedAddresses: []ngfAPIv1alpha2.NginxPlusAllowAddress{
+ {Type: ngfAPIv1alpha2.NginxPlusAllowCIDRAddressType, Value: "2001:db8:a0b:12f0::1/32"},
+ {Type: ngfAPIv1alpha2.NginxPlusAllowCIDRAddressType, Value: "127.0.0.3/37"},
},
},
},
@@ -817,12 +1251,12 @@ func TestValidateNginxPlus(t *testing.T) {
expectErrCount: 1,
},
{
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- NginxPlus: &ngfAPI.NginxPlus{
- AllowedAddresses: []ngfAPI.NginxPlusAllowAddress{
- {Type: ngfAPI.NginxPlusAllowIPAddressType, Value: "127.0.0.3"},
- {Type: ngfAPI.NginxPlusAllowIPAddressType, Value: "127.0.0.3.5/32"},
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ NginxPlus: &ngfAPIv1alpha2.NginxPlus{
+ AllowedAddresses: []ngfAPIv1alpha2.NginxPlusAllowAddress{
+ {Type: ngfAPIv1alpha2.NginxPlusAllowIPAddressType, Value: "127.0.0.3"},
+ {Type: ngfAPIv1alpha2.NginxPlusAllowIPAddressType, Value: "127.0.0.3.5/32"},
},
},
},
@@ -833,11 +1267,11 @@ func TestValidateNginxPlus(t *testing.T) {
expectErrCount: 1,
},
{
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- NginxPlus: &ngfAPI.NginxPlus{
- AllowedAddresses: []ngfAPI.NginxPlusAllowAddress{
- {Type: ngfAPI.NginxPlusAllowAddressType("Hostname"), Value: "example.com"},
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ NginxPlus: &ngfAPIv1alpha2.NginxPlus{
+ AllowedAddresses: []ngfAPIv1alpha2.NginxPlusAllowAddress{
+ {Type: ngfAPIv1alpha2.NginxPlusAllowAddressType("Hostname"), Value: "example.com"},
},
},
},
@@ -848,11 +1282,11 @@ func TestValidateNginxPlus(t *testing.T) {
expectErrCount: 1,
},
{
- np: &ngfAPI.NginxProxy{
- Spec: ngfAPI.NginxProxySpec{
- NginxPlus: &ngfAPI.NginxPlus{
- AllowedAddresses: []ngfAPI.NginxPlusAllowAddress{
- {Type: ngfAPI.NginxPlusAllowAddressType("invalid"), Value: "example.com"},
+ np: &ngfAPIv1alpha2.NginxProxy{
+ Spec: ngfAPIv1alpha2.NginxProxySpec{
+ NginxPlus: &ngfAPIv1alpha2.NginxPlus{
+ AllowedAddresses: []ngfAPIv1alpha2.NginxPlusAllowAddress{
+ {Type: ngfAPIv1alpha2.NginxPlusAllowAddressType("invalid"), Value: "example.com"},
},
},
},
@@ -877,3 +1311,11 @@ func TestValidateNginxPlus(t *testing.T) {
})
}
}
+
+func TestValidateNginxProxy_NilCase(t *testing.T) {
+ t.Parallel()
+ g := NewWithT(t)
+
+ // Just testing the nil case for coverage reasons. The rest of the function is covered by other tests.
+ g.Expect(buildNginxProxy(nil, &validationfakes.FakeGenericValidator{})).To(BeNil())
+}
diff --git a/internal/mode/static/state/graph/route_common.go b/internal/mode/static/state/graph/route_common.go
index 31a7c1528f..0db03e12e4 100644
--- a/internal/mode/static/state/graph/route_common.go
+++ b/internal/mode/static/state/graph/route_common.go
@@ -187,7 +187,7 @@ func buildL4RoutesForGateways(
tlsRoutes map[types.NamespacedName]*v1alpha.TLSRoute,
gatewayNsNames []types.NamespacedName,
services map[types.NamespacedName]*apiv1.Service,
- npCfg *NginxProxy,
+ npCfg *EffectiveNginxProxy,
resolver *referenceGrantResolver,
) map[L4RouteKey]*L4Route {
if len(gatewayNsNames) == 0 {
@@ -216,7 +216,7 @@ func buildRoutesForGateways(
httpRoutes map[types.NamespacedName]*v1.HTTPRoute,
grpcRoutes map[types.NamespacedName]*v1.GRPCRoute,
gatewayNsNames []types.NamespacedName,
- npCfg *NginxProxy,
+ effectiveNginxProxy *EffectiveNginxProxy,
snippetsFilters map[types.NamespacedName]*SnippetsFilter,
) map[RouteKey]*L7Route {
if len(gatewayNsNames) == 0 {
@@ -225,7 +225,7 @@ func buildRoutesForGateways(
routes := make(map[RouteKey]*L7Route)
- http2disabled := isHTTP2Disabled(npCfg)
+ http2disabled := isHTTP2Disabled(effectiveNginxProxy)
for _, route := range httpRoutes {
r := buildHTTPRoute(validator, route, gatewayNsNames, snippetsFilters)
@@ -244,11 +244,16 @@ func buildRoutesForGateways(
return routes
}
-func isHTTP2Disabled(npCfg *NginxProxy) bool {
+func isHTTP2Disabled(npCfg *EffectiveNginxProxy) bool {
if npCfg == nil {
return false
}
- return npCfg.Source.Spec.DisableHTTP2
+
+ if npCfg.DisableHTTP2 == nil {
+ return false
+ }
+
+ return *npCfg.DisableHTTP2
}
func buildSectionNameRefs(
diff --git a/internal/mode/static/state/graph/tlsroute.go b/internal/mode/static/state/graph/tlsroute.go
index 0acf1cadd7..da0749f9ce 100644
--- a/internal/mode/static/state/graph/tlsroute.go
+++ b/internal/mode/static/state/graph/tlsroute.go
@@ -15,7 +15,7 @@ func buildTLSRoute(
gtr *v1alpha2.TLSRoute,
gatewayNsNames []types.NamespacedName,
services map[types.NamespacedName]*apiv1.Service,
- npCfg *NginxProxy,
+ npCfg *EffectiveNginxProxy,
refGrantResolver func(resource toResource) bool,
) *L4Route {
r := &L4Route{
@@ -69,7 +69,7 @@ func buildTLSRoute(
func validateBackendRefTLSRoute(gtr *v1alpha2.TLSRoute,
services map[types.NamespacedName]*apiv1.Service,
- npCfg *NginxProxy,
+ npCfg *EffectiveNginxProxy,
refGrantResolver func(resource toResource) bool,
) (BackendRef, *conditions.Condition) {
// Length of BackendRefs and Rules is guaranteed to be one due to earlier check in buildTLSRoute
diff --git a/internal/mode/static/state/graph/tlsroute_test.go b/internal/mode/static/state/graph/tlsroute_test.go
index 12d9beb872..9bd57f6ac2 100644
--- a/internal/mode/static/state/graph/tlsroute_test.go
+++ b/internal/mode/static/state/graph/tlsroute_test.go
@@ -10,7 +10,7 @@ import (
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
"sigs.k8s.io/gateway-api/apis/v1alpha2"
- ngfAPI "github.com/nginx/nginx-gateway-fabric/apis/v1alpha1"
+ ngfAPI "github.com/nginx/nginx-gateway-fabric/apis/v1alpha2"
"github.com/nginx/nginx-gateway-fabric/internal/framework/conditions"
"github.com/nginx/nginx-gateway-fabric/internal/framework/helpers"
staticConds "github.com/nginx/nginx-gateway-fabric/internal/mode/static/state/conditions"
@@ -271,9 +271,9 @@ func TestBuildTLSRoute(t *testing.T) {
gtr *v1alpha2.TLSRoute
services map[types.NamespacedName]*apiv1.Service
resolver func(resource toResource) bool
+ npCfg *EffectiveNginxProxy
name string
gatewayNsNames []types.NamespacedName
- npCfg NginxProxy
}{
{
gtr: duplicateParentRefsGtr,
@@ -491,10 +491,7 @@ func TestBuildTLSRoute(t *testing.T) {
services: map[types.NamespacedName]*apiv1.Service{
svcNsName: ipv4Svc,
},
- npCfg: NginxProxy{
- Source: &ngfAPI.NginxProxy{Spec: ngfAPI.NginxProxySpec{IPFamily: helpers.GetPointer(ngfAPI.IPv6)}},
- Valid: true,
- },
+ npCfg: &EffectiveNginxProxy{IPFamily: helpers.GetPointer(ngfAPI.IPv6)},
resolver: alwaysTrueRefGrantResolver,
name: "service and npcfg ip family mismatch",
},
@@ -559,7 +556,7 @@ func TestBuildTLSRoute(t *testing.T) {
test.gtr,
test.gatewayNsNames,
test.services,
- &test.npCfg,
+ test.npCfg,
test.resolver,
)
g.Expect(helpers.Diff(test.expected, r)).To(BeEmpty())
diff --git a/internal/mode/static/status/prepare_requests.go b/internal/mode/static/status/prepare_requests.go
index 818445d8d7..46e150a8cb 100644
--- a/internal/mode/static/status/prepare_requests.go
+++ b/internal/mode/static/status/prepare_requests.go
@@ -293,6 +293,8 @@ func prepareGatewayRequest(
}
gwConds := staticConds.NewDefaultGatewayConditions()
+ gwConds = append(gwConds, gateway.Conditions...)
+
if validListenerCount == 0 {
gwConds = append(gwConds, staticConds.NewGatewayNotAcceptedListenersNotValid()...)
} else if validListenerCount < len(gateway.Listeners) {
diff --git a/internal/mode/static/status/prepare_requests_test.go b/internal/mode/static/status/prepare_requests_test.go
index 702cbe9827..f4ad7e1fe0 100644
--- a/internal/mode/static/status/prepare_requests_test.go
+++ b/internal/mode/static/status/prepare_requests_test.go
@@ -1134,6 +1134,117 @@ func TestBuildGatewayStatuses(t *testing.T) {
},
nginxReloadRes: NginxReloadResult{Error: errors.New("test error")},
},
+ {
+ name: "valid gateway with valid parametersRef; all valid listeners",
+ gateway: &graph.Gateway{
+ Source: createGateway(),
+ Listeners: []*graph.Listener{
+ {
+ Name: "listener-valid-1",
+ Valid: true,
+ Routes: map[graph.RouteKey]*graph.L7Route{routeKey: {}},
+ },
+ },
+ Valid: true,
+ Conditions: []conditions.Condition{
+ staticConds.NewGatewayResolvedRefs(),
+ },
+ },
+ expected: map[types.NamespacedName]v1.GatewayStatus{
+ {Namespace: "test", Name: "gateway"}: {
+ Addresses: addr,
+ Conditions: []metav1.Condition{
+ {
+ Type: string(v1.GatewayConditionAccepted),
+ Status: metav1.ConditionTrue,
+ ObservedGeneration: 2,
+ LastTransitionTime: transitionTime,
+ Reason: string(v1.GatewayReasonAccepted),
+ Message: "Gateway is accepted",
+ },
+ {
+ Type: string(v1.GatewayConditionProgrammed),
+ Status: metav1.ConditionTrue,
+ ObservedGeneration: 2,
+ LastTransitionTime: transitionTime,
+ Reason: string(v1.GatewayReasonProgrammed),
+ Message: "Gateway is programmed",
+ },
+ {
+ Type: string(staticConds.GatewayResolvedRefs),
+ Status: metav1.ConditionTrue,
+ ObservedGeneration: 2,
+ LastTransitionTime: transitionTime,
+ Reason: string(staticConds.GatewayReasonResolvedRefs),
+ Message: "ParametersRef resource is resolved",
+ },
+ },
+ Listeners: []v1.ListenerStatus{
+ {
+ Name: "listener-valid-1",
+ AttachedRoutes: 1,
+ Conditions: validListenerConditions,
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "valid gateway with invalid parametersRef; all valid listeners",
+ gateway: &graph.Gateway{
+ Source: createGateway(),
+ Listeners: []*graph.Listener{
+ {
+ Name: "listener-valid-1",
+ Valid: true,
+ Routes: map[graph.RouteKey]*graph.L7Route{routeKey: {}},
+ },
+ },
+ Valid: true,
+ Conditions: []conditions.Condition{
+ staticConds.NewGatewayRefNotFound(),
+ staticConds.NewGatewayInvalidParameters("ParametersRef not found"),
+ },
+ },
+ expected: map[types.NamespacedName]v1.GatewayStatus{
+ {Namespace: "test", Name: "gateway"}: {
+ Addresses: addr,
+ Conditions: []metav1.Condition{
+ {
+ Type: string(v1.GatewayConditionProgrammed),
+ Status: metav1.ConditionTrue,
+ ObservedGeneration: 2,
+ LastTransitionTime: transitionTime,
+ Reason: string(v1.GatewayReasonProgrammed),
+ Message: "Gateway is programmed",
+ },
+ {
+ Type: string(staticConds.GatewayResolvedRefs),
+ Status: metav1.ConditionFalse,
+ ObservedGeneration: 2,
+ LastTransitionTime: transitionTime,
+ Reason: string(staticConds.GatewayReasonParamsRefNotFound),
+ Message: "ParametersRef resource could not be found",
+ },
+ {
+ Type: string(v1.GatewayConditionAccepted),
+ Status: metav1.ConditionTrue,
+ ObservedGeneration: 2,
+ LastTransitionTime: transitionTime,
+ Reason: string(v1.GatewayReasonInvalidParameters),
+ Message: "Gateway is accepted, but ParametersRef is ignored due to an error: ParametersRef not found",
+ },
+ },
+ Listeners: []v1.ListenerStatus{
+ {
+ Name: "listener-valid-1",
+ AttachedRoutes: 1,
+ Conditions: validListenerConditions,
+ },
+ },
+ },
+ },
+ },
}
for _, test := range tests {
diff --git a/internal/mode/static/telemetry/collector.go b/internal/mode/static/telemetry/collector.go
index a349475a36..facc7dc56a 100644
--- a/internal/mode/static/telemetry/collector.go
+++ b/internal/mode/static/telemetry/collector.go
@@ -246,10 +246,7 @@ func collectGraphResourceCount(
}
}
- if g.NginxProxy != nil {
- ngfResourceCounts.NginxProxyCount = 1
- }
-
+ ngfResourceCounts.NginxProxyCount = int64(len(g.ReferencedNginxProxies))
ngfResourceCounts.SnippetsFilterCount = int64(len(g.SnippetsFilters))
return ngfResourceCounts, nil
diff --git a/internal/mode/static/telemetry/collector_test.go b/internal/mode/static/telemetry/collector_test.go
index 24f6e4e973..9935920d4f 100644
--- a/internal/mode/static/telemetry/collector_test.go
+++ b/internal/mode/static/telemetry/collector_test.go
@@ -334,8 +334,10 @@ var _ = Describe("Collector", Ordered, func() {
GVK: schema.GroupVersionKind{Kind: kinds.UpstreamSettingsPolicy},
}: {},
},
- NginxProxy: &graph.NginxProxy{},
- SnippetsFilters: map[types.NamespacedName]*graph.SnippetsFilter{
+ ReferencedNginxProxies: map[types.NamespacedName]*graph.NginxProxy{
+ {Namespace: "test", Name: "NginxProxy-1"}: {},
+ {Namespace: "test", Name: "NginxProxy-2"}: {},
+ }, SnippetsFilters: map[types.NamespacedName]*graph.SnippetsFilter{
{Namespace: "test", Name: "sf-1"}: {
Snippets: map[ngfAPI.NginxContext]string{
ngfAPI.NginxContextMain: "worker_priority 0;",
@@ -414,7 +416,7 @@ var _ = Describe("Collector", Ordered, func() {
GatewayAttachedClientSettingsPolicyCount: 1,
RouteAttachedClientSettingsPolicyCount: 2,
ObservabilityPolicyCount: 1,
- NginxProxyCount: 1,
+ NginxProxyCount: 2,
SnippetsFilterCount: 3,
UpstreamSettingsPolicyCount: 1,
}
@@ -613,7 +615,10 @@ var _ = Describe("Collector", Ordered, func() {
GVK: schema.GroupVersionKind{Kind: kinds.UpstreamSettingsPolicy},
}: {},
},
- NginxProxy: &graph.NginxProxy{},
+ ReferencedNginxProxies: map[types.NamespacedName]*graph.NginxProxy{
+ {Namespace: "test", Name: "NginxProxy-1"}: {},
+ {Namespace: "test", Name: "NginxProxy-2"}: {},
+ },
SnippetsFilters: map[types.NamespacedName]*graph.SnippetsFilter{
{Namespace: "test", Name: "sf-1"}: {},
},
@@ -689,7 +694,7 @@ var _ = Describe("Collector", Ordered, func() {
GatewayAttachedClientSettingsPolicyCount: 1,
RouteAttachedClientSettingsPolicyCount: 1,
ObservabilityPolicyCount: 1,
- NginxProxyCount: 1,
+ NginxProxyCount: 2,
SnippetsFilterCount: 1,
UpstreamSettingsPolicyCount: 1,
}
diff --git a/site/content/how-to/data-plane-configuration.md b/site/content/how-to/data-plane-configuration.md
index d12fa03fa7..1f1e7d0713 100644
--- a/site/content/how-to/data-plane-configuration.md
+++ b/site/content/how-to/data-plane-configuration.md
@@ -71,7 +71,7 @@ The following command creates a basic `NginxProxy` configuration that sets the I
```yaml
kubectl apply -f - <
- NginxProxy is a configuration object that is attached to a GatewayClass parametersRef. It provides a way
-to configure global settings for all Gateways defined from the GatewayClass.NginxProxy
-¶
-
-
Field | -Description | -||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
-apiVersion -string |
-
-
-gateway.nginx.org/v1alpha1
-
- |
-||||||||||||
-kind -string - |
-NginxProxy |
-||||||||||||
-metadata - - -Kubernetes meta/v1.ObjectMeta - - - |
-
-Refer to the Kubernetes API documentation for the fields of the
-metadata field.
- |
-||||||||||||
-spec - - -NginxProxySpec - - - |
-
- Spec defines the desired state of the NginxProxy. -- -
|
-
Duration is a string value representing a duration in time. @@ -1055,34 +905,6 @@ Duration can be specified in milliseconds (ms), seconds (s), minutes (m), hours A value without a suffix is seconds. Examples: 120s, 50ms, 5m, 1h.
-string
alias)¶
--(Appears on: -NginxProxySpec) -
--
IPFamilyType specifies the IP family to be used by NGINX.
- -Value | -Description | -
---|---|
"dual" |
-Dual specifies that NGINX will use both IPv4 and IPv6. - |
-
"ipv4" |
-IPv4 specifies that NGINX will use only IPv4. - |
-
"ipv6" |
-IPv6 specifies that NGINX will use only IPv6. - |
-
string
alias)¶
--(Appears on: -NginxLogging) -
--
NginxErrorLogLevel type defines the log level of error logs for NGINX.
- -Value | -Description | -
---|---|
"alert" |
-NginxLogLevelAlert is the alert level for NGINX error logs. - |
-
"crit" |
-NginxLogLevelCrit is the crit level for NGINX error logs. - |
-
"debug" |
-NginxLogLevelDebug is the debug level for NGINX error logs. - |
-
"emerg" |
-NginxLogLevelEmerg is the emerg level for NGINX error logs. - |
-
"error" |
-NginxLogLevelError is the error level for NGINX error logs. - |
-
"info" |
-NginxLogLevelInfo is the info level for NGINX error logs. - |
-
"notice" |
-NginxLogLevelNotice is the notice level for NGINX error logs. - |
-
"warn" |
-NginxLogLevelWarn is the warn level for NGINX error logs. - |
-
string
alias)¶
(Appears on: -NginxProxySpec) +ObservabilityPolicy)
-
NginxLogging defines logging related settings for NGINX.
+ObservabilityPolicySpec defines the desired state of the ObservabilityPolicy.
-errorLevel + tracing - -NginxErrorLogLevel + +Tracing |
(Optional)
- ErrorLevel defines the error log level. Possible log levels listed in order of increasing severity are -debug, info, notice, warn, error, crit, alert, and emerg. Setting a certain log level will cause all messages -of the specified and more severe log levels to be logged. For example, the log level ‘error’ will cause error, -crit, alert, and emerg messages to be logged. https://nginx.org/en/docs/ngx_core_module.html#error_log +Tracing allows for enabling and configuring tracing. + |
+
+targetRefs + + +[]sigs.k8s.io/gateway-api/apis/v1alpha2.LocalPolicyTargetReference + + + |
+
+ TargetRefs identifies the API object(s) to apply the policy to. +Objects must be in the same namespace as the policy. +Support: HTTPRoute, GRPCRoute. |
string
alias)¶
(Appears on: -NginxProxySpec) +ClientBody, +UpstreamSettingsPolicySpec)
-
NginxPlus specifies NGINX Plus additional settings. These will only be applied if NGINX Plus is being used.
+Size is a string value representing a size. Size can be specified in bytes, kilobytes (k), megabytes (m), +or gigabytes (g). +Examples: 1024, 8k, 1m.
+ ++(Appears on: +SnippetsFilterSpec) +
++
Snippet represents an NGINX configuration snippet.
-(Optional)
- AllowedAddresses specifies IPAddresses or CIDR blocks to the allow list for accessing the NGINX Plus API. - |
-
-
-
-(Appears on: -NginxPlus) -
--
NginxPlusAllowAddress specifies the address type and value for an NginxPlus allow address.
- -Field | -Description | -
---|---|
-type - - -NginxPlusAllowAddressType - - - |
-
- Type specifies the type of address. +Context is the NGINX context to insert the snippet into. |
- Value specifies the address value. +Value is the NGINX configuration snippet. |
string
alias)¶
+string
alias)¶
-(Appears on: -NginxPlusAllowAddress) +
SnippetsFilterConditionReason is a reason for a SnippetsFilter condition type.
+Value | +Description | +
---|---|
"Accepted" |
+SnippetsFilterConditionReasonAccepted is used with the Accepted condition type when +the condition is true. + |
+
"Invalid" |
+SnippetsFilterConditionReasonInvalid is used with the Accepted condition type when +SnippetsFilter is invalid. + |
+
string
alias)¶
+-
NginxPlusAllowAddressType specifies the type of address.
+SnippetsFilterConditionType is a type of condition associated with SnippetsFilter.
Description | -|
---|---|
"CIDR" |
-NginxPlusAllowCIDRAddressType specifies that the address is a CIDR block. - |
-
"IPAddress" |
-NginxPlusAllowIPAddressType specifies that the address is an IP address. + |
"Accepted" |
+SnippetsFilterConditionTypeAccepted indicates that the SnippetsFilter is accepted. +Possible reasons for this condition to be True: +
Possible reasons for this condition to be False: +
|
(Appears on: -NginxProxy) +SnippetsFilter)
-
NginxProxySpec defines the desired state of the NginxProxy.
+SnippetsFilterSpec defines the desired state of the SnippetsFilter.
-ipFamily - - -IPFamilyType - - - |
-
-(Optional)
- IPFamily specifies the IP family to be used by the NGINX. -Default is “dual”, meaning the server will use both IPv4 and IPv6. - |
-
-telemetry - - -Telemetry - - - |
-
-(Optional)
- Telemetry specifies the OpenTelemetry configuration. - |
-
-rewriteClientIP - - -RewriteClientIP - - - |
-
-(Optional)
- RewriteClientIP defines configuration for rewriting the client IP to the original client’s IP. - |
-
-logging - - -NginxLogging - - - |
-
-(Optional)
- Logging defines logging related settings for NGINX. - |
-
-nginxPlus + snippets - -NginxPlus + +[]Snippet |
-(Optional)
- NginxPlus specifies NGINX Plus additional settings. - |
-
-disableHTTP2 - -bool - - |
-
- DisableHTTP2 defines if http2 should be disabled for all servers. -Default is false, meaning http2 will be enabled for all servers. +Snippets is a list of NGINX configuration snippets. +There can only be one snippet per context. +Allowed contexts: main, http, http.server, http.server.location. |
(Appears on: -ObservabilityPolicy) +SnippetsFilter)
-
ObservabilityPolicySpec defines the desired state of the ObservabilityPolicy.
+SnippetsFilterStatus defines the state of SnippetsFilter.
-tracing - - -Tracing - - - |
-
-(Optional)
- Tracing allows for enabling and configuring tracing. - |
-
-targetRefs + controllers - -[]sigs.k8s.io/gateway-api/apis/v1alpha2.LocalPolicyTargetReference + +[]ControllerStatus |
- TargetRefs identifies the API object(s) to apply the policy to. -Objects must be in the same namespace as the policy. -Support: HTTPRoute, GRPCRoute. +Controllers is a list of Gateway API controllers that processed the SnippetsFilter +and the status of the SnippetsFilter with respect to each controller. |
(Appears on: -NginxProxySpec) +Tracing, +Telemetry, +Tracing)
-
RewriteClientIP specifies the configuration for rewriting the client’s IP address.
+SpanAttribute is a key value pair to be added to a tracing span.
-mode - - -RewriteClientIPModeType - - - |
-
-(Optional)
- Mode defines how NGINX will rewrite the client’s IP address. -There are two possible modes: -- ProxyProtocol: NGINX will rewrite the client’s IP using the PROXY protocol header. -- XForwardedFor: NGINX will rewrite the client’s IP using the X-Forwarded-For header. -Sets NGINX directive real_ip_header: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header - |
-
-setIPRecursively + key -bool +string |
-(Optional)
- SetIPRecursively configures whether recursive search is used when selecting the client’s address from -the X-Forwarded-For header. It is used in conjunction with TrustedAddresses. -If enabled, NGINX will recurse on the values in X-Forwarded-Header from the end of array -to start of array and select the first untrusted IP. -For example, if X-Forwarded-For is [11.11.11.11, 22.22.22.22, 55.55.55.1], -and TrustedAddresses is set to 55.55.55.1⁄32, NGINX will rewrite the client IP to 22.22.22.22. -If disabled, NGINX will select the IP at the end of the array. -In the previous example, 55.55.55.1 would be selected. -Sets NGINX directive real_ip_recursive: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_recursive +Key is the key for a span attribute. +Format: must have all ‘“’ escaped and must not contain any ‘$’ or end with an unescaped ‘\’ |
-trustedAddresses + value - -[]RewriteClientIPAddress - +string |
-(Optional)
- TrustedAddresses specifies the addresses that are trusted to send correct client IP information. -If a request comes from a trusted address, NGINX will rewrite the client IP information, -and forward it to the backend in the X-Forwarded-For* and X-Real-IP headers. -If the request does not come from a trusted address, NGINX will not rewrite the client IP information. -TrustedAddresses only supports CIDR blocks: 192.33.21.1⁄24, fe80::1⁄64. -To trust all addresses (not recommended for production), set to 0.0.0.0/0. -If no addresses are provided, NGINX will not rewrite the client IP information. -Sets NGINX directive set_real_ip_from: https://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from -This field is required if mode is set. +Value is the value for a span attribute. +Format: must have all ‘“’ escaped and must not contain any ‘$’ or end with an unescaped ‘\’ |
string
alias)¶
(Appears on: -RewriteClientIP) +Tracing)
-
RewriteClientIPAddress specifies the address type and value for a RewriteClientIP address.
+TraceContext specifies how to propagate traceparent/tracestate headers.
Field | +Value | Description |
---|---|---|
-type - - -RewriteClientIPAddressType - - - |
-
- Type specifies the type of address. - |
-|
-value - -string - - |
-
- Value specifies the address value. + | |
"extract" |
+TraceContextExtract uses an existing trace context from the request, so that the identifiers +of a trace and the parent span are inherited from the incoming request. |
-
string
alias)¶
--(Appears on: -RewriteClientIPAddress) -
--
RewriteClientIPAddressType specifies the type of address.
- -Value | -Description | -
---|---|
"CIDR" |
-RewriteClientIPCIDRAddressType specifies that the address is a CIDR block. + |
"ignore" |
+TraceContextIgnore skips context headers processing. |
-
"Hostname" |
-RewriteClientIPHostnameAddressType specifies that the address is a Hostname. + |
"inject" |
+TraceContextInject adds a new context to the request, overwriting existing headers, if any. |
-
"IPAddress" |
-RewriteClientIPIPAddressType specifies that the address is an IP address. + |
"propagate" |
+TraceContextPropagate updates the existing context (combines extract and inject). |
string
alias)¶
+string
alias)¶
(Appears on: -RewriteClientIP) +Tracing)
-
RewriteClientIPModeType defines how NGINX Gateway Fabric will determine the client’s original IP address.
+TraceStrategy defines the tracing strategy.
Description | -|
---|---|
"ProxyProtocol" |
-RewriteClientIPModeProxyProtocol configures NGINX to accept PROXY protocol and -set the client’s IP address to the IP address in the PROXY protocol header. -Sets the proxy_protocol parameter on the listen directive of all servers and sets real_ip_header -to proxy_protocol: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header. + |
"parent" |
+TraceStrategyParent enables tracing and only records spans if the parent span was sampled. |
-
"XForwardedFor" |
-RewriteClientIPModeXForwardedFor configures NGINX to set the client’s IP address to the -IP address in the X-Forwarded-For HTTP header. -https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header. + |
"ratio" |
+TraceStrategyRatio enables ratio-based tracing, defaulting to 100% sampling rate. |
string
alias)¶
--(Appears on: -ClientBody, -UpstreamSettingsPolicySpec) -
--
Size is a string value representing a size. Size can be specified in bytes, kilobytes (k), megabytes (m), -or gigabytes (g). -Examples: 1024, 8k, 1m.
- -(Appears on: -SnippetsFilterSpec) +ObservabilityPolicySpec)
-
Snippet represents an NGINX configuration snippet.
+Tracing allows for enabling and configuring OpenTelemetry tracing.
-context + strategy - -NginxContext + +TraceStrategy |
- Context is the NGINX context to insert the snippet into. +Strategy defines if tracing is ratio-based or parent-based. |
-value + ratio -string +int32 |
- Value is the NGINX configuration snippet. +(Optional) +Ratio is the percentage of traffic that should be sampled. Integer from 0 to 100. +By default, 100% of http requests are traced. Not applicable for parent-based tracing. +If ratio is set to 0, tracing is disabled. |
string
alias)¶
--
SnippetsFilterConditionReason is a reason for a SnippetsFilter condition type.
- -Value | -Description | -|
---|---|---|
"Accepted" |
-SnippetsFilterConditionReasonAccepted is used with the Accepted condition type when -the condition is true. - |
-|
"Invalid" |
-SnippetsFilterConditionReasonInvalid is used with the Accepted condition type when -SnippetsFilter is invalid. + |
+context + + +TraceContext + + |
-
string
alias)¶
--
SnippetsFilterConditionType is a type of condition associated with SnippetsFilter.
- -Value | -Description | -|
---|---|---|
"Accepted" |
-SnippetsFilterConditionTypeAccepted indicates that the SnippetsFilter is accepted. -Possible reasons for this condition to be True: -
Possible reasons for this condition to be False: -
|
+(Optional)
+ Context specifies how to propagate traceparent/tracestate headers. +Default: https://nginx.org/en/docs/ngx_otel_module.html#otel_trace_context |
-
-(Appears on: -SnippetsFilter) -
--
SnippetsFilterSpec defines the desired state of the SnippetsFilter.
- -Field | -Description |
---|---|
-snippets + spanName - -[]Snippet - +string |
- Snippets is a list of NGINX configuration snippets. -There can only be one snippet per context. -Allowed contexts: main, http, http.server, http.server.location. +(Optional) +SpanName defines the name of the Otel span. By default is the name of the location for a request. +If specified, applies to all locations that are created for a route. +Format: must have all ‘“’ escaped and must not contain any ‘$’ or end with an unescaped ‘\’ +Examples of invalid names: some-$value, quoted-“value”-name, unescaped |
-(Appears on: -SnippetsFilter) -
--
SnippetsFilterStatus defines the state of SnippetsFilter.
- -Field | -Description | -
---|---|
-controllers + spanAttributes - -[]ControllerStatus + +[]SpanAttribute |
- Controllers is a list of Gateway API controllers that processed the SnippetsFilter -and the status of the SnippetsFilter with respect to each controller. +(Optional) +SpanAttributes are custom key/value attributes that are added to each span. |
(Appears on: -Telemetry, -Tracing, -Tracing) +UpstreamSettingsPolicySpec)
-
SpanAttribute is a key value pair to be added to a tracing span.
+UpstreamKeepAlive defines the keep-alive settings for upstreams.
-key + connections -string +int32 |
- Key is the key for a span attribute. -Format: must have all ‘“’ escaped and must not contain any ‘$’ or end with an unescaped ‘\’ +(Optional) +Connections sets the maximum number of idle keep-alive connections to upstream servers that are preserved +in the cache of each nginx worker process. When this number is exceeded, the least recently used +connections are closed. +Directive: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive |
-value + requests -string +int32 |
- Value is the value for a span attribute. -Format: must have all ‘“’ escaped and must not contain any ‘$’ or end with an unescaped ‘\’ +(Optional) +Requests sets the maximum number of requests that can be served through one keep-alive connection. +After the maximum number of requests are made, the connection is closed. +Directive: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive_requests + |
+
+time + + +Duration + + + |
+
+(Optional)
+ Time defines the maximum time during which requests can be processed through one keep-alive connection. +After this time is reached, the connection is closed following the subsequent request processing. +Directive: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive_time + |
+
+timeout + + +Duration + + + |
+
+(Optional)
+ Timeout defines the keep-alive timeout for upstreams. +Directive: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive_timeout + |
+
+(Appears on: +UpstreamSettingsPolicy) +
++
UpstreamSettingsPolicySpec defines the desired state of the UpstreamSettingsPolicy.
+ +Field | +Description | +
---|---|
+zoneSize + + +Size + + + |
+
+(Optional)
+ ZoneSize is the size of the shared memory zone used by the upstream. This memory zone is used to share +the upstream configuration between nginx worker processes. The more servers that an upstream has, +the larger memory zone is required. +Default: OSS: 512k, Plus: 1m. +Directive: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#zone + |
+
+keepAlive + + +UpstreamKeepAlive + + + |
+
+(Optional)
+ KeepAlive defines the keep-alive settings. + |
+
+targetRefs + + +[]sigs.k8s.io/gateway-api/apis/v1alpha2.LocalPolicyTargetReference + + + |
+
+ TargetRefs identifies API object(s) to apply the policy to. +Objects must be in the same namespace as the policy. +Support: Service +TargetRefs must be distinct. The |
+
+
Package v1alpha2 contains API Schema definitions for the +gateway.nginx.org API group.
+ +Resource Types: + ++
NginxProxy is a configuration object that can be referenced from a GatewayClass parametersRef +or a Gateway infrastructure.parametersRef. It provides a way to configure data plane settings. +If referenced from a GatewayClass, the settings apply to all Gateways attached to the GatewayClass. +If referenced from a Gateway, the settings apply to that Gateway alone. If both a Gateway and its GatewayClass +reference an NginxProxy, the settings are merged. Settings specified on the Gateway NginxProxy override those +set on the GatewayClass NginxProxy.
+ +Field | +Description | +||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+apiVersion +string |
+
+
+gateway.nginx.org/v1alpha2
+
+ |
+||||||||||||
+kind +string + |
+NginxProxy |
+||||||||||||
+metadata + + +Kubernetes meta/v1.ObjectMeta + + + |
+
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+||||||||||||
+spec + + +NginxProxySpec + + + |
+
+ Spec defines the desired state of the NginxProxy. ++ +
|
+
+
ObservabilityPolicy is a Direct Attached Policy. It provides a way to configure observability settings for +the NGINX Gateway Fabric data plane. Used in conjunction with the NginxProxy CRD that is attached to the +GatewayClass parametersRef.
+ +Field | +Description | +||||
---|---|---|---|---|---|
+apiVersion +string |
+
+
+gateway.nginx.org/v1alpha2
+
+ |
+||||
+kind +string + |
+ObservabilityPolicy |
+||||
+metadata + + +Kubernetes meta/v1.ObjectMeta + + + |
+
+Refer to the Kubernetes API documentation for the fields of the
+metadata field.
+ |
+||||
+spec + + +ObservabilityPolicySpec + + + |
+
+ Spec defines the desired state of the ObservabilityPolicy. ++ +
|
+||||
+status + + +sigs.k8s.io/gateway-api/apis/v1alpha2.PolicyStatus + + + |
+
+ Status defines the state of the ObservabilityPolicy. + |
+
string
alias)¶
++(Appears on: +Telemetry) +
++
DisableTelemetryFeature is a telemetry feature that can be disabled.
+ +Value | +Description | +
---|---|
"DisableTracing" |
+DisableTracing disables the OpenTelemetry tracing feature. + |
+
string
alias)¶
++(Appears on: +NginxProxySpec) +
++
IPFamilyType specifies the IP family to be used by NGINX.
+ +Value | +Description | +
---|---|
"dual" |
+Dual specifies that NGINX will use both IPv4 and IPv6. + |
+
"ipv4" |
+IPv4 specifies that NGINX will use only IPv4. + |
+
"ipv6" |
+IPv6 specifies that NGINX will use only IPv6. + |
+
string
alias)¶
++(Appears on: +NginxLogging) +
++
NginxErrorLogLevel type defines the log level of error logs for NGINX.
+ +Value | +Description | +
---|---|
"alert" |
+NginxLogLevelAlert is the alert level for NGINX error logs. + |
+
"crit" |
+NginxLogLevelCrit is the crit level for NGINX error logs. + |
+
"debug" |
+NginxLogLevelDebug is the debug level for NGINX error logs. + |
+
"emerg" |
+NginxLogLevelEmerg is the emerg level for NGINX error logs. + |
+
"error" |
+NginxLogLevelError is the error level for NGINX error logs. + |
+
"info" |
+NginxLogLevelInfo is the info level for NGINX error logs. + |
+
"notice" |
+NginxLogLevelNotice is the notice level for NGINX error logs. + |
+
"warn" |
+NginxLogLevelWarn is the warn level for NGINX error logs. + |
+
+(Appears on: +NginxProxySpec) +
++
NginxLogging defines logging related settings for NGINX.
+ +Field | +Description | +
---|---|
+errorLevel + + +NginxErrorLogLevel + + + |
+
+(Optional)
+ ErrorLevel defines the error log level. Possible log levels listed in order of increasing severity are +debug, info, notice, warn, error, crit, alert, and emerg. Setting a certain log level will cause all messages +of the specified and more severe log levels to be logged. For example, the log level ‘error’ will cause error, +crit, alert, and emerg messages to be logged. https://nginx.org/en/docs/ngx_core_module.html#error_log |
(Appears on: -NginxProxySpec) +NginxProxySpec)
-
Telemetry specifies the OpenTelemetry configuration.
+NginxPlus specifies NGINX Plus additional settings. These will only be applied if NGINX Plus is being used.
-exporter - - -TelemetryExporter - - - |
-
-(Optional)
- Exporter specifies OpenTelemetry export parameters. - |
-
-serviceName - -string - - |
-
-(Optional)
- ServiceName is the “service.name” attribute of the OpenTelemetry resource.
-Default is ‘ngf: |
-
-spanAttributes + allowedAddresses - -[]SpanAttribute + +[]NginxPlusAllowAddress |
(Optional)
- SpanAttributes are custom key/value attributes that are added to each span. +AllowedAddresses specifies IPAddresses or CIDR blocks to the allow list for accessing the NGINX Plus API. |
(Appears on: -Telemetry) +NginxPlus)
-
TelemetryExporter specifies OpenTelemetry export parameters.
+NginxPlusAllowAddress specifies the address type and value for an NginxPlus allow address.
-interval + type - -Duration + +NginxPlusAllowAddressType |
-(Optional)
- Interval is the maximum interval between two exports. -Default: https://nginx.org/en/docs/ngx_otel_module.html#otel_exporter - |
-
-batchSize - -int32 - - |
-
-(Optional)
- BatchSize is the maximum number of spans to be sent in one batch per worker. -Default: https://nginx.org/en/docs/ngx_otel_module.html#otel_exporter - |
-
-batchCount - -int32 - - |
-
-(Optional)
- BatchCount is the number of pending batches per worker, spans exceeding the limit are dropped. -Default: https://nginx.org/en/docs/ngx_otel_module.html#otel_exporter +Type specifies the type of address. |
-endpoint + value string |
- Endpoint is the address of OTLP/gRPC endpoint that will accept telemetry data. -Format: alphanumeric hostname with optional http scheme and optional port. +Value specifies the address value. |
string
alias)¶
--(Appears on: -Tracing) -
--
TraceContext specifies how to propagate traceparent/tracestate headers.
- -Value | -Description | -
---|---|
"extract" |
-TraceContextExtract uses an existing trace context from the request, so that the identifiers -of a trace and the parent span are inherited from the incoming request. - |
-
"ignore" |
-TraceContextIgnore skips context headers processing. - |
-
"inject" |
-TraceContextInject adds a new context to the request, overwriting existing headers, if any. - |
-
"propagate" |
-TraceContextPropagate updates the existing context (combines extract and inject). - |
-
string
alias)¶
+string
alias)¶
(Appears on: -Tracing) +NginxPlusAllowAddress)
-
TraceStrategy defines the tracing strategy.
+NginxPlusAllowAddressType specifies the type of address.
Description | -|
---|---|
"parent" |
-TraceStrategyParent enables tracing and only records spans if the parent span was sampled. + |
"CIDR" |
+NginxPlusAllowCIDRAddressType specifies that the address is a CIDR block. |
-
"ratio" |
-TraceStrategyRatio enables ratio-based tracing, defaulting to 100% sampling rate. + |
"IPAddress" |
+NginxPlusAllowIPAddressType specifies that the address is an IP address. |
(Appears on: -ObservabilityPolicySpec) +NginxProxy)
-
Tracing allows for enabling and configuring OpenTelemetry tracing.
+NginxProxySpec defines the desired state of the NginxProxy.
-strategy + ipFamily - -TraceStrategy + +IPFamilyType |
- Strategy defines if tracing is ratio-based or parent-based. +(Optional) +IPFamily specifies the IP family to be used by the NGINX. +Default is “dual”, meaning the server will use both IPv4 and IPv6. |
-ratio + telemetry -int32 + +Telemetry + |
(Optional)
- Ratio is the percentage of traffic that should be sampled. Integer from 0 to 100. -By default, 100% of http requests are traced. Not applicable for parent-based tracing. -If ratio is set to 0, tracing is disabled. +Telemetry specifies the OpenTelemetry configuration. |
-context + rewriteClientIP - -TraceContext + +RewriteClientIP |
(Optional)
- Context specifies how to propagate traceparent/tracestate headers. -Default: https://nginx.org/en/docs/ngx_otel_module.html#otel_trace_context +RewriteClientIP defines configuration for rewriting the client IP to the original client’s IP. |
-spanName + logging -string + +NginxLogging + |
(Optional)
- SpanName defines the name of the Otel span. By default is the name of the location for a request. -If specified, applies to all locations that are created for a route. -Format: must have all ‘“’ escaped and must not contain any ‘$’ or end with an unescaped ‘\’ -Examples of invalid names: some-$value, quoted-“value”-name, unescaped +Logging defines logging related settings for NGINX. |
-spanAttributes + nginxPlus - -[]SpanAttribute + +NginxPlus |
(Optional)
- SpanAttributes are custom key/value attributes that are added to each span. +NginxPlus specifies NGINX Plus additional settings. + |
+
+disableHTTP2 + +bool + + |
+
+(Optional)
+ DisableHTTP2 defines if http2 should be disabled for all servers. +If not specified, or set to false, http2 will be enabled for all servers. |
(Appears on: -UpstreamSettingsPolicySpec) +ObservabilityPolicy)
-
UpstreamKeepAlive defines the keep-alive settings for upstreams.
+ObservabilityPolicySpec defines the desired state of the ObservabilityPolicy.
-connections + tracing -int32 + +Tracing + |
(Optional)
- Connections sets the maximum number of idle keep-alive connections to upstream servers that are preserved -in the cache of each nginx worker process. When this number is exceeded, the least recently used -connections are closed. -Directive: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive +Tracing allows for enabling and configuring tracing. |
-requests + targetRefs -int32 + +[]sigs.k8s.io/gateway-api/apis/v1alpha2.LocalPolicyTargetReference + |
-(Optional)
- Requests sets the maximum number of requests that can be served through one keep-alive connection. -After the maximum number of requests are made, the connection is closed. -Directive: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive_requests +TargetRefs identifies the API object(s) to apply the policy to. +Objects must be in the same namespace as the policy. +Support: HTTPRoute, GRPCRoute. +TargetRefs must be distinct. This means that the multi-part key defined by |
+(Appears on: +NginxProxySpec) +
++
RewriteClientIP specifies the configuration for rewriting the client’s IP address.
+ +Field | +Description | +
---|---|
-time + mode - -Duration + +RewriteClientIPModeType |
(Optional)
- Time defines the maximum time during which requests can be processed through one keep-alive connection. -After this time is reached, the connection is closed following the subsequent request processing. -Directive: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive_time +Mode defines how NGINX will rewrite the client’s IP address. +There are two possible modes: +- ProxyProtocol: NGINX will rewrite the client’s IP using the PROXY protocol header. +- XForwardedFor: NGINX will rewrite the client’s IP using the X-Forwarded-For header. +Sets NGINX directive real_ip_header: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header + |
+
+setIPRecursively + +bool + + |
+
+(Optional)
+ SetIPRecursively configures whether recursive search is used when selecting the client’s address from +the X-Forwarded-For header. It is used in conjunction with TrustedAddresses. +If enabled, NGINX will recurse on the values in X-Forwarded-Header from the end of array +to start of array and select the first untrusted IP. +For example, if X-Forwarded-For is [11.11.11.11, 22.22.22.22, 55.55.55.1], +and TrustedAddresses is set to 55.55.55.1⁄32, NGINX will rewrite the client IP to 22.22.22.22. +If disabled, NGINX will select the IP at the end of the array. +In the previous example, 55.55.55.1 would be selected. +Sets NGINX directive real_ip_recursive: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_recursive |
-timeout + trustedAddresses - -Duration + +[]RewriteClientIPAddress |
(Optional)
- Timeout defines the keep-alive timeout for upstreams. -Directive: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive_timeout +TrustedAddresses specifies the addresses that are trusted to send correct client IP information. +If a request comes from a trusted address, NGINX will rewrite the client IP information, +and forward it to the backend in the X-Forwarded-For* and X-Real-IP headers. +If the request does not come from a trusted address, NGINX will not rewrite the client IP information. +To trust all addresses (not recommended for production), set to 0.0.0.0/0. +If no addresses are provided, NGINX will not rewrite the client IP information. +Sets NGINX directive set_real_ip_from: https://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from +This field is required if mode is set. |
(Appears on: -UpstreamSettingsPolicy) +RewriteClientIP)
-
UpstreamSettingsPolicySpec defines the desired state of the UpstreamSettingsPolicy.
+RewriteClientIPAddress specifies the address type and value for a RewriteClientIP address.
-(Optional)
- ZoneSize is the size of the shared memory zone used by the upstream. This memory zone is used to share -the upstream configuration between nginx worker processes. The more servers that an upstream has, -the larger memory zone is required. -Default: OSS: 512k, Plus: 1m. -Directive: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#zone +Type specifies the type of address. |
|
-keepAlive + value - -UpstreamKeepAlive - +string |
-(Optional)
- KeepAlive defines the keep-alive settings. +Value specifies the address value. |
string
alias)¶
++(Appears on: +RewriteClientIPAddress) +
++
RewriteClientIPAddressType specifies the type of address.
+ +
-targetRefs - - -[]sigs.k8s.io/gateway-api/apis/v1alpha2.LocalPolicyTargetReference - - + | Value | +Description | +
---|---|---|
"CIDR" |
+RewriteClientIPCIDRAddressType specifies that the address is a CIDR block. |
-
- TargetRefs identifies API object(s) to apply the policy to. -Objects must be in the same namespace as the policy. -Support: Service -TargetRefs must be distinct. The |
"Hostname" |
+RewriteClientIPHostnameAddressType specifies that the address is a Hostname. |
-|
"IPAddress" |
+RewriteClientIPIPAddressType specifies that the address is an IP address. + |
+
string
alias)¶
+-
Package v1alpha2 contains API Schema definitions for the -gateway.nginx.org API group.
+(Appears on: +RewriteClientIP) -Resource Types: - --
ObservabilityPolicy is a Direct Attached Policy. It provides a way to configure observability settings for -the NGINX Gateway Fabric data plane. Used in conjunction with the NginxProxy CRD that is attached to the -GatewayClass parametersRef.
+RewriteClientIPModeType defines how NGINX Gateway Fabric will determine the client’s original IP address.
Field | +Value | Description |
---|---|---|
-apiVersion -string |
-
-
-gateway.nginx.org/v1alpha2
-
+ | |
"ProxyProtocol" |
+RewriteClientIPModeProxyProtocol configures NGINX to accept PROXY protocol and +set the client’s IP address to the IP address in the PROXY protocol header. +Sets the proxy_protocol parameter on the listen directive of all servers and sets real_ip_header +to proxy_protocol: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header. |
-|
-kind -string + | ||
"XForwardedFor" |
+RewriteClientIPModeXForwardedFor configures NGINX to set the client’s IP address to the +IP address in the X-Forwarded-For HTTP header. +https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header. |
-ObservabilityPolicy |
+
+(Appears on: +NginxProxySpec) +
++
Telemetry specifies the OpenTelemetry configuration.
+ +Field | +Description | ||||
---|---|---|---|---|---|
-metadata + disabledFeatures - -Kubernetes meta/v1.ObjectMeta + +[]DisableTelemetryFeature |
-Refer to the Kubernetes API documentation for the fields of the
-metadata field.
+(Optional)
+DisabledFeatures specifies OpenTelemetry features to be disabled. |
||||
-spec - - -ObservabilityPolicySpec - - - |
-
- Spec defines the desired state of the ObservabilityPolicy. -- -
ServiceName is the “service.name” attribute of the OpenTelemetry resource.
+Default is ‘ngf: |
||||
-status + spanAttributes - -sigs.k8s.io/gateway-api/apis/v1alpha2.PolicyStatus + +[]SpanAttribute |
- Status defines the state of the ObservabilityPolicy. +(Optional) +SpanAttributes are custom key/value attributes that are added to each span. |
(Appears on: -ObservabilityPolicy) +Telemetry)
-
ObservabilityPolicySpec defines the desired state of the ObservabilityPolicy.
+TelemetryExporter specifies OpenTelemetry export parameters.
-tracing + interval - -Tracing + +Duration |
(Optional)
- Tracing allows for enabling and configuring tracing. +Interval is the maximum interval between two exports. +Default: https://nginx.org/en/docs/ngx_otel_module.html#otel_exporter |
-targetRefs + batchSize - -[]sigs.k8s.io/gateway-api/apis/v1alpha2.LocalPolicyTargetReference - +int32 |
- TargetRefs identifies the API object(s) to apply the policy to. -Objects must be in the same namespace as the policy. -Support: HTTPRoute, GRPCRoute. -TargetRefs must be distinct. This means that the multi-part key defined by BatchSize is the maximum number of spans to be sent in one batch per worker. +Default: https://nginx.org/en/docs/ngx_otel_module.html#otel_exporter + |
+
+batchCount + +int32 + + |
+
+(Optional)
+ BatchCount is the number of pending batches per worker, spans exceeding the limit are dropped. +Default: https://nginx.org/en/docs/ngx_otel_module.html#otel_exporter + |
+
+endpoint + +string + + |
+
+(Optional)
+ Endpoint is the address of OTLP/gRPC endpoint that will accept telemetry data. +Format: alphanumeric hostname with optional http scheme and optional port. |