Skip to content

Commit 9e4e35b

Browse files
authored
feat: support translate BackendTrafficPolicy CRD (#92)
1 parent 497da5f commit 9e4e35b

File tree

15 files changed

+416
-53
lines changed

15 files changed

+416
-53
lines changed

api/v1alpha1/backendtrafficpolicy_types.go

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package v1alpha1
22

33
import (
44
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
5-
6-
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
75
)
86

97
// +kubebuilder:object:root=true
@@ -12,22 +10,18 @@ type BackendTrafficPolicy struct {
1210
metav1.TypeMeta `json:",inline"`
1311
metav1.ObjectMeta `json:"metadata,omitempty"`
1412

15-
Spec BackendTrafficPolicySpec `json:"spec,omitempty"`
16-
Status gatewayv1alpha2.PolicyStatus `json:"status,omitempty"`
13+
Spec BackendTrafficPolicySpec `json:"spec,omitempty"`
14+
Status PolicyStatus `json:"status,omitempty"`
1715
}
1816

1917
type BackendTrafficPolicySpec struct {
2018
// TargetRef identifies an API object to apply policy to.
2119
// Currently, Backends (i.e. Service, ServiceImport, or any
2220
// implementation-specific backendRef) are the only valid API
2321
// target references.
24-
// +listType=map
25-
// +listMapKey=group
26-
// +listMapKey=kind
27-
// +listMapKey=name
2822
// +kubebuilder:validation:MinItems=1
2923
// +kubebuilder:validation:MaxItems=16
30-
TargetRefs []gatewayv1alpha2.LocalPolicyTargetReferenceWithSectionName `json:"targetRefs"`
24+
TargetRefs []BackendPolicyTargetReferenceWithSectionName `json:"targetRefs"`
3125
// LoadBalancer represents the load balancer configuration for Kubernetes Service.
3226
// The default strategy is round robin.
3327
LoadBalancer *LoadBalancer `json:"loadbalancer,omitempty" yaml:"loadbalancer,omitempty"`
@@ -74,9 +68,12 @@ type LoadBalancer struct {
7468
}
7569

7670
type Timeout struct {
71+
// +kubebuilder:default="60s"
7772
Connect metav1.Duration `json:"connect,omitempty" yaml:"connect,omitempty"`
78-
Send metav1.Duration `json:"send,omitempty" yaml:"send,omitempty"`
79-
Read metav1.Duration `json:"read,omitempty" yaml:"read,omitempty"`
73+
// +kubebuilder:default="60s"
74+
Send metav1.Duration `json:"send,omitempty" yaml:"send,omitempty"`
75+
// +kubebuilder:default="60s"
76+
Read metav1.Duration `json:"read,omitempty" yaml:"read,omitempty"`
8077
}
8178

8279
// +kubebuilder:object:root=true

api/v1alpha1/policies_type.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package v1alpha1
2+
3+
import gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
4+
5+
type PolicyStatus gatewayv1alpha2.PolicyStatus
6+
7+
// +kubebuilder:validation:XValidation:rule="self.kind == 'Service' && self.group == \"\""
8+
type BackendPolicyTargetReferenceWithSectionName gatewayv1alpha2.LocalPolicyTargetReferenceWithSectionName

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 45 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/gateway.apisix.io_backendtrafficpolicies.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,23 +153,23 @@ spec:
153153
- kind
154154
- name
155155
type: object
156+
x-kubernetes-validations:
157+
- rule: self.kind == 'Service' && self.group == ""
156158
maxItems: 16
157159
minItems: 1
158160
type: array
159-
x-kubernetes-list-map-keys:
160-
- group
161-
- kind
162-
- name
163-
x-kubernetes-list-type: map
164161
timeout:
165162
description: Timeout settings for the read, send and connect to the
166163
upstream.
167164
properties:
168165
connect:
166+
default: 60s
169167
type: string
170168
read:
169+
default: 60s
171170
type: string
172171
send:
172+
default: 60s
173173
type: string
174174
type: object
175175
upstream_host:

internal/controller/consumer_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ func (r *ConsumerReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
136136
}
137137

138138
var statusErr error
139-
tctx := provider.NewDefaultTranslateContext()
139+
tctx := provider.NewDefaultTranslateContext(ctx)
140140

141141
if err := r.processSpec(ctx, tctx, consumer); err != nil {
142142
r.Log.Error(err, "failed to process consumer spec", "consumer", consumer)

internal/controller/httproute_controller.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func (r *HTTPRouteReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
112112
return ctrl.Result{}, nil
113113
}
114114

115-
tctx := provider.NewDefaultTranslateContext()
115+
tctx := provider.NewDefaultTranslateContext(ctx)
116116

117117
if err := r.processHTTPRoute(tctx, hr); err != nil {
118118
acceptStatus.status = false
@@ -249,7 +249,7 @@ func (r *HTTPRouteReconciler) processHTTPRouteBackendRefs(tctx *provider.Transla
249249
}
250250

251251
var service corev1.Service
252-
if err := r.Get(context.TODO(), client.ObjectKey{
252+
if err := r.Get(tctx, client.ObjectKey{
253253
Namespace: namespace,
254254
Name: name,
255255
}, &service); err != nil {
@@ -268,9 +268,13 @@ func (r *HTTPRouteReconciler) processHTTPRouteBackendRefs(tctx *provider.Transla
268268
terr = fmt.Errorf("port %d not found in service %s", *backend.Port, name)
269269
continue
270270
}
271+
tctx.Services[client.ObjectKey{
272+
Namespace: namespace,
273+
Name: name,
274+
}] = &service
271275

272276
endpointSliceList := new(discoveryv1.EndpointSliceList)
273-
if err := r.List(context.TODO(), endpointSliceList,
277+
if err := r.List(tctx, endpointSliceList,
274278
client.InNamespace(namespace),
275279
client.MatchingLabels{
276280
discoveryv1.LabelServiceName: name,

internal/controller/indexer/indexer.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55

66
"github.com/api7/api7-ingress-controller/api/v1alpha1"
77
networkingv1 "k8s.io/api/networking/v1"
8+
"k8s.io/apimachinery/pkg/runtime/schema"
9+
"k8s.io/apimachinery/pkg/types"
810
ctrl "sigs.k8s.io/controller-runtime"
911
"sigs.k8s.io/controller-runtime/pkg/client"
1012
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
@@ -19,6 +21,7 @@ const (
1921
SecretIndexRef = "secretRefs"
2022
IngressClassRef = "ingressClassRef"
2123
ConsumerGatewayRef = "consumerGatewayRef"
24+
PolicyTargetRefs = "targetRefs"
2225
)
2326

2427
func SetupIndexer(mgr ctrl.Manager) error {
@@ -34,6 +37,11 @@ func SetupIndexer(mgr ctrl.Manager) error {
3437
if err := setupConsumerIndexer(mgr); err != nil {
3538
return err
3639
}
40+
/*
41+
if err := setupBackendTrafficPolicyIndexer(mgr); err != nil {
42+
return err
43+
}
44+
*/
3745
return nil
3846
}
3947

@@ -175,6 +183,18 @@ func setupIngressIndexer(mgr ctrl.Manager) error {
175183
return nil
176184
}
177185

186+
func SetupBackendTrafficPolicyIndexer(mgr ctrl.Manager) error {
187+
if err := mgr.GetFieldIndexer().IndexField(
188+
context.Background(),
189+
&v1alpha1.BackendTrafficPolicy{},
190+
PolicyTargetRefs,
191+
BackendTrafficPolicyIndexFunc,
192+
); err != nil {
193+
return err
194+
}
195+
return nil
196+
}
197+
178198
func IngressClassIndexFunc(rawObj client.Object) []string {
179199
ingressClass := rawObj.(*networkingv1.IngressClass)
180200
if ingressClass.Spec.Controller == "" {
@@ -227,6 +247,18 @@ func IngressSecretIndexFunc(rawObj client.Object) []string {
227247
return secrets
228248
}
229249

250+
func GenIndexKeyWithGK(group, kind, namespace, name string) string {
251+
gvk := schema.GroupKind{
252+
Group: group,
253+
Kind: kind,
254+
}
255+
nsName := types.NamespacedName{
256+
Namespace: namespace,
257+
Name: name,
258+
}
259+
return gvk.String() + "/" + nsName.String()
260+
}
261+
230262
func GenIndexKey(namespace, name string) string {
231263
return client.ObjectKey{
232264
Namespace: namespace,
@@ -292,3 +324,19 @@ func GatewayParametersRefIndexFunc(rawObj client.Object) []string {
292324
}
293325
return nil
294326
}
327+
328+
func BackendTrafficPolicyIndexFunc(rawObj client.Object) []string {
329+
btp := rawObj.(*v1alpha1.BackendTrafficPolicy)
330+
keys := make([]string, 0, len(btp.Spec.TargetRefs))
331+
for _, ref := range btp.Spec.TargetRefs {
332+
keys = append(keys,
333+
GenIndexKeyWithGK(
334+
string(ref.Group),
335+
string(ref.Kind),
336+
btp.GetNamespace(),
337+
string(ref.Name),
338+
),
339+
)
340+
}
341+
return keys
342+
}

internal/controller/ingress_controller.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -93,16 +93,16 @@ func (r *IngressReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
9393
r.Log.Info("reconciling ingress", "ingress", ingress.Name)
9494

9595
// create a translate context
96-
tctx := provider.NewDefaultTranslateContext()
96+
tctx := provider.NewDefaultTranslateContext(ctx)
9797

9898
// process TLS configuration
99-
if err := r.processTLS(ctx, tctx, ingress); err != nil {
99+
if err := r.processTLS(tctx, ingress); err != nil {
100100
r.Log.Error(err, "failed to process TLS configuration", "ingress", ingress.Name)
101101
return ctrl.Result{}, err
102102
}
103103

104104
// process backend services
105-
if err := r.processBackends(ctx, tctx, ingress); err != nil {
105+
if err := r.processBackends(tctx, ingress); err != nil {
106106
r.Log.Error(err, "failed to process backend services", "ingress", ingress.Name)
107107
return ctrl.Result{}, err
108108
}
@@ -295,14 +295,14 @@ func (r *IngressReconciler) listIngressesBySecret(ctx context.Context, obj clien
295295
}
296296

297297
// processTLS process the TLS configuration of the ingress
298-
func (r *IngressReconciler) processTLS(ctx context.Context, tctx *provider.TranslateContext, ingress *networkingv1.Ingress) error {
298+
func (r *IngressReconciler) processTLS(tctx *provider.TranslateContext, ingress *networkingv1.Ingress) error {
299299
for _, tls := range ingress.Spec.TLS {
300300
if tls.SecretName == "" {
301301
continue
302302
}
303303

304304
secret := corev1.Secret{}
305-
if err := r.Get(ctx, client.ObjectKey{
305+
if err := r.Get(tctx, client.ObjectKey{
306306
Namespace: ingress.Namespace,
307307
Name: tls.SecretName,
308308
}, &secret); err != nil {
@@ -323,7 +323,7 @@ func (r *IngressReconciler) processTLS(ctx context.Context, tctx *provider.Trans
323323
}
324324

325325
// processBackends process the backend services of the ingress
326-
func (r *IngressReconciler) processBackends(ctx context.Context, tctx *provider.TranslateContext, ingress *networkingv1.Ingress) error {
326+
func (r *IngressReconciler) processBackends(tctx *provider.TranslateContext, ingress *networkingv1.Ingress) error {
327327
var terr error
328328

329329
// process all the backend services in the rules
@@ -336,7 +336,7 @@ func (r *IngressReconciler) processBackends(ctx context.Context, tctx *provider.
336336
continue
337337
}
338338
service := path.Backend.Service
339-
if err := r.processBackendService(ctx, tctx, ingress.Namespace, service); err != nil {
339+
if err := r.processBackendService(tctx, ingress.Namespace, service); err != nil {
340340
terr = err
341341
}
342342
}
@@ -345,10 +345,10 @@ func (r *IngressReconciler) processBackends(ctx context.Context, tctx *provider.
345345
}
346346

347347
// processBackendService process a single backend service
348-
func (r *IngressReconciler) processBackendService(ctx context.Context, tctx *provider.TranslateContext, namespace string, backendService *networkingv1.IngressServiceBackend) error {
348+
func (r *IngressReconciler) processBackendService(tctx *provider.TranslateContext, namespace string, backendService *networkingv1.IngressServiceBackend) error {
349349
// get the service
350350
var service corev1.Service
351-
if err := r.Get(ctx, client.ObjectKey{
351+
if err := r.Get(tctx, client.ObjectKey{
352352
Namespace: namespace,
353353
Name: backendService.Name,
354354
}, &service); err != nil {
@@ -385,7 +385,7 @@ func (r *IngressReconciler) processBackendService(ctx context.Context, tctx *pro
385385

386386
// get the endpoint slices
387387
endpointSliceList := &discoveryv1.EndpointSliceList{}
388-
if err := r.List(ctx, endpointSliceList,
388+
if err := r.List(tctx, endpointSliceList,
389389
client.InNamespace(namespace),
390390
client.MatchingLabels{
391391
discoveryv1.LabelServiceName: backendService.Name,

0 commit comments

Comments
 (0)