Skip to content

Commit ce1cd37

Browse files
committed
Validate no duplicate targetRefs
1 parent 046f2d3 commit ce1cd37

31 files changed

+2108
-488
lines changed

apis/v1alpha1/observabilitypolicy_types.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import (
77

88
// +genclient
99
// +kubebuilder:object:root=true
10-
// +kubebuilder:storageversion
10+
// +kubebuilder:deprecatedversion:warning="The 'v1alpha1' version of ObservabilityPolicy API is deprecated, please migrate to 'v1alpha2'."
1111
// +kubebuilder:subresource:status
1212
// +kubebuilder:resource:categories=nginx-gateway-fabric,scope=Namespaced
1313
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
1414
// +kubebuilder:metadata:labels="gateway.networking.k8s.io/policy=direct"
15+
//nolint:lll
1516

1617
// ObservabilityPolicy is a Direct Attached Policy. It provides a way to configure observability settings for
1718
// the NGINX Gateway Fabric data plane. Used in conjunction with the NginxProxy CRD that is attached to the
@@ -50,7 +51,7 @@ type ObservabilityPolicySpec struct {
5051
// +kubebuilder:validation:MinItems=1
5152
// +kubebuilder:validation:MaxItems=16
5253
// +kubebuilder:validation:XValidation:message="TargetRef Kind must be: HTTPRoute or GRPCRoute",rule="(self.exists(t, t.kind=='HTTPRoute') || self.exists(t, t.kind=='GRPCRoute'))"
53-
// +kubebuilder:validation:XValidation:message="TargetRef Group must be gateway.networking.k8s.io.",rule="self.all(t, t.group=='gateway.networking.k8s.io')"
54+
// +kubebuilder:validation:XValidation:message="TargetRef Group must be gateway.networking.k8s.io",rule="self.all(t, t.group=='gateway.networking.k8s.io')"
5455
//nolint:lll
5556
TargetRefs []gatewayv1alpha2.LocalPolicyTargetReference `json:"targetRefs"`
5657
}

apis/v1alpha1/upstreamsettingspolicy_types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,13 @@ type UpstreamSettingsPolicySpec struct {
5555
// Objects must be in the same namespace as the policy.
5656
// Support: Service
5757
//
58+
// TargetRefs must be _distinct_. The `name` field must be unique for all targetRef entries in the UpstreamSettingsPolicy.
59+
//
5860
// +kubebuilder:validation:MinItems=1
5961
// +kubebuilder:validation:MaxItems=16
6062
// +kubebuilder:validation:XValidation:message="TargetRefs Kind must be: Service",rule="self.all(t, t.kind=='Service')"
6163
// +kubebuilder:validation:XValidation:message="TargetRefs Group must be core",rule="self.exists(t, t.group=='') || self.exists(t, t.group=='core')"
64+
// +kubebuilder:validation:XValidation:message="TargetRef Name must be unique",rule="self.all(p1, self.exists_one(p2, p1.name == p2.name))"
6265
//nolint:lll
6366
TargetRefs []gatewayv1alpha2.LocalPolicyTargetReference `json:"targetRefs"`
6467
}

apis/v1alpha2/doc.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Package v1alpha2 contains API Schema definitions for the
2+
// gateway.nginx.org API group.
3+
//
4+
// +kubebuilder:object:generate=true
5+
// +groupName=gateway.nginx.org
6+
package v1alpha2
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
package v1alpha2
2+
3+
import (
4+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
5+
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
6+
7+
ngfAPIv1alpha1 "github.com/nginx/nginx-gateway-fabric/apis/v1alpha1"
8+
)
9+
10+
// +genclient
11+
// +kubebuilder:object:root=true
12+
// +kubebuilder:storageversion
13+
// +kubebuilder:subresource:status
14+
// +kubebuilder:resource:categories=nginx-gateway-fabric,scope=Namespaced
15+
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
16+
// +kubebuilder:metadata:labels="gateway.networking.k8s.io/policy=direct"
17+
18+
// ObservabilityPolicy is a Direct Attached Policy. It provides a way to configure observability settings for
19+
// the NGINX Gateway Fabric data plane. Used in conjunction with the NginxProxy CRD that is attached to the
20+
// GatewayClass parametersRef.
21+
type ObservabilityPolicy struct {
22+
metav1.TypeMeta `json:",inline"`
23+
metav1.ObjectMeta `json:"metadata,omitempty"`
24+
25+
// Spec defines the desired state of the ObservabilityPolicy.
26+
Spec ObservabilityPolicySpec `json:"spec"`
27+
28+
// Status defines the state of the ObservabilityPolicy.
29+
Status gatewayv1alpha2.PolicyStatus `json:"status,omitempty"`
30+
}
31+
32+
// +kubebuilder:object:root=true
33+
34+
// ObservabilityPolicyList contains a list of ObservabilityPolicies.
35+
type ObservabilityPolicyList struct {
36+
metav1.TypeMeta `json:",inline"`
37+
metav1.ListMeta `json:"metadata,omitempty"`
38+
Items []ObservabilityPolicy `json:"items"`
39+
}
40+
41+
// ObservabilityPolicySpec defines the desired state of the ObservabilityPolicy.
42+
type ObservabilityPolicySpec struct {
43+
// Tracing allows for enabling and configuring tracing.
44+
//
45+
// +optional
46+
Tracing *Tracing `json:"tracing,omitempty"`
47+
48+
// TargetRefs identifies the API object(s) to apply the policy to.
49+
// Objects must be in the same namespace as the policy.
50+
// Support: HTTPRoute, GRPCRoute.
51+
//
52+
// TargetRefs must be _distinct_. This means that the multi-part key defined by `kind` and `name` must
53+
// be unique across all targetRef entries in the ObservabilityPolicy.
54+
//
55+
// +kubebuilder:validation:MinItems=1
56+
// +kubebuilder:validation:MaxItems=16
57+
// +kubebuilder:validation:XValidation:message="TargetRef Kind must be: HTTPRoute or GRPCRoute",rule="(self.exists(t, t.kind=='HTTPRoute') || self.exists(t, t.kind=='GRPCRoute'))"
58+
// +kubebuilder:validation:XValidation:message="TargetRef Group must be gateway.networking.k8s.io",rule="self.all(t, t.group=='gateway.networking.k8s.io')"
59+
// +kubebuilder:validation:XValidation:message="TargetRef Kind and Name combination must be unique",rule="self.all(p1, self.exists_one(p2, (p1.name == p2.name) && (p1.kind == p2.kind)))"
60+
//nolint:lll
61+
TargetRefs []gatewayv1alpha2.LocalPolicyTargetReference `json:"targetRefs"`
62+
}
63+
64+
// Tracing allows for enabling and configuring OpenTelemetry tracing.
65+
//
66+
// +kubebuilder:validation:XValidation:message="ratio can only be specified if strategy is of type ratio",rule="!(has(self.ratio) && self.strategy != 'ratio')"
67+
//
68+
//nolint:lll
69+
type Tracing struct {
70+
// Strategy defines if tracing is ratio-based or parent-based.
71+
Strategy TraceStrategy `json:"strategy"`
72+
73+
// Ratio is the percentage of traffic that should be sampled. Integer from 0 to 100.
74+
// By default, 100% of http requests are traced. Not applicable for parent-based tracing.
75+
// If ratio is set to 0, tracing is disabled.
76+
//
77+
// +optional
78+
// +kubebuilder:validation:Minimum=0
79+
// +kubebuilder:validation:Maximum=100
80+
Ratio *int32 `json:"ratio,omitempty"`
81+
82+
// Context specifies how to propagate traceparent/tracestate headers.
83+
// Default: https://nginx.org/en/docs/ngx_otel_module.html#otel_trace_context
84+
//
85+
// +optional
86+
Context *TraceContext `json:"context,omitempty"`
87+
88+
// SpanName defines the name of the Otel span. By default is the name of the location for a request.
89+
// If specified, applies to all locations that are created for a route.
90+
// Format: must have all '"' escaped and must not contain any '$' or end with an unescaped '\'
91+
// Examples of invalid names: some-$value, quoted-"value"-name, unescaped\
92+
//
93+
// +optional
94+
// +kubebuilder:validation:MinLength=1
95+
// +kubebuilder:validation:MaxLength=255
96+
// +kubebuilder:validation:Pattern=`^([^"$\\]|\\[^$])*$`
97+
SpanName *string `json:"spanName,omitempty"`
98+
99+
// SpanAttributes are custom key/value attributes that are added to each span.
100+
//
101+
// +optional
102+
// +listType=map
103+
// +listMapKey=key
104+
// +kubebuilder:validation:MaxItems=64
105+
SpanAttributes []ngfAPIv1alpha1.SpanAttribute `json:"spanAttributes,omitempty"`
106+
}
107+
108+
// TraceStrategy defines the tracing strategy.
109+
//
110+
// +kubebuilder:validation:Enum=ratio;parent
111+
type TraceStrategy string
112+
113+
const (
114+
// TraceStrategyRatio enables ratio-based tracing, defaulting to 100% sampling rate.
115+
TraceStrategyRatio TraceStrategy = "ratio"
116+
117+
// TraceStrategyParent enables tracing and only records spans if the parent span was sampled.
118+
TraceStrategyParent TraceStrategy = "parent"
119+
)
120+
121+
// TraceContext specifies how to propagate traceparent/tracestate headers.
122+
//
123+
// +kubebuilder:validation:Enum=extract;inject;propagate;ignore
124+
type TraceContext string
125+
126+
const (
127+
// TraceContextExtract uses an existing trace context from the request, so that the identifiers
128+
// of a trace and the parent span are inherited from the incoming request.
129+
TraceContextExtract TraceContext = "extract"
130+
131+
// TraceContextInject adds a new context to the request, overwriting existing headers, if any.
132+
TraceContextInject TraceContext = "inject"
133+
134+
// TraceContextPropagate updates the existing context (combines extract and inject).
135+
TraceContextPropagate TraceContext = "propagate"
136+
137+
// TraceContextIgnore skips context headers processing.
138+
TraceContextIgnore TraceContext = "ignore"
139+
)

apis/v1alpha2/policy_methods.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package v1alpha2
2+
3+
import (
4+
"sigs.k8s.io/gateway-api/apis/v1alpha2"
5+
)
6+
7+
// FIXME(kate-osborn): https://github.com/nginxinc/nginx-gateway-fabric/issues/1939.
8+
// Figure out a way to generate these methods for all our policies.
9+
// These methods implement the policies.Policy interface which extends client.Object to add the following methods.
10+
11+
func (p *ObservabilityPolicy) GetTargetRefs() []v1alpha2.LocalPolicyTargetReference {
12+
return p.Spec.TargetRefs
13+
}
14+
15+
func (p *ObservabilityPolicy) GetPolicyStatus() v1alpha2.PolicyStatus {
16+
return p.Status
17+
}
18+
19+
func (p *ObservabilityPolicy) SetPolicyStatus(status v1alpha2.PolicyStatus) {
20+
p.Status = status
21+
}

apis/v1alpha2/register.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package v1alpha2
2+
3+
import (
4+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
5+
"k8s.io/apimachinery/pkg/runtime"
6+
"k8s.io/apimachinery/pkg/runtime/schema"
7+
)
8+
9+
// GroupName specifies the group name used to register the objects.
10+
const GroupName = "gateway.nginx.org"
11+
12+
// SchemeGroupVersion is group version used to register these objects.
13+
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
14+
15+
// Resource takes an unqualified resource and returns a Group qualified GroupResource.
16+
func Resource(resource string) schema.GroupResource {
17+
return SchemeGroupVersion.WithResource(resource).GroupResource()
18+
}
19+
20+
var (
21+
// SchemeBuilder collects functions that add things to a scheme. It's to allow
22+
// code to compile without explicitly referencing generated types. You should
23+
// declare one in each package that will have generated deep copy or conversion
24+
// functions.
25+
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
26+
27+
// AddToScheme applies all the stored functions to the scheme. A non-nil error
28+
// indicates that one function failed and the attempt was abandoned.
29+
AddToScheme = SchemeBuilder.AddToScheme
30+
)
31+
32+
// Adds the list of known types to Scheme.
33+
func addKnownTypes(scheme *runtime.Scheme) error {
34+
scheme.AddKnownTypes(SchemeGroupVersion,
35+
&ObservabilityPolicy{},
36+
&ObservabilityPolicyList{},
37+
)
38+
// AddToGroupVersion allows the serialization of client types like ListOptions.
39+
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
40+
41+
return nil
42+
}

apis/v1alpha2/zz_generated.deepcopy.go

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

0 commit comments

Comments
 (0)