Skip to content

Commit 2fc258a

Browse files
committed
(WIP) feat: support sync when update gateway proxy
Signed-off-by: ashing <[email protected]>
1 parent 298943b commit 2fc258a

File tree

4 files changed

+178
-41
lines changed

4 files changed

+178
-41
lines changed

internal/controller/consumer_controller.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ func (r *ConsumerReconciler) SetupWithManager(mgr ctrl.Manager) error {
6262
Watches(&corev1.Secret{},
6363
handler.EnqueueRequestsFromMapFunc(r.listConsumersForSecret),
6464
).
65+
Watches(&v1alpha1.GatewayProxy{},
66+
handler.EnqueueRequestsFromMapFunc(r.listConsumersForGatewayProxy),
67+
).
6568
Complete(r)
6669
}
6770

@@ -115,6 +118,49 @@ func (r *ConsumerReconciler) listConsumersForGateway(ctx context.Context, obj cl
115118
return requests
116119
}
117120

121+
func (r *ConsumerReconciler) listConsumersForGatewayProxy(ctx context.Context, obj client.Object) []reconcile.Request {
122+
gatewayProxy, ok := obj.(*v1alpha1.GatewayProxy)
123+
if !ok {
124+
r.Log.Error(nil, "failed to convert to GatewayProxy", "object", obj)
125+
return nil
126+
}
127+
128+
namespace := gatewayProxy.GetNamespace()
129+
name := gatewayProxy.GetName()
130+
131+
// find all gateways that reference this gateway proxy
132+
gatewayList := &gatewayv1.GatewayList{}
133+
if err := r.List(ctx, gatewayList, client.MatchingFields{
134+
indexer.ParametersRef: indexer.GenIndexKey(namespace, name),
135+
}); err != nil {
136+
r.Log.Error(err, "failed to list gateways for gateway proxy", "gatewayproxy", gatewayProxy.GetName())
137+
return nil
138+
}
139+
140+
var requests []reconcile.Request
141+
142+
for _, gateway := range gatewayList.Items {
143+
consumerList := &v1alpha1.ConsumerList{}
144+
if err := r.List(ctx, consumerList, client.MatchingFields{
145+
indexer.ConsumerGatewayRef: indexer.GenIndexKey(gateway.Namespace, gateway.Name),
146+
}); err != nil {
147+
r.Log.Error(err, "failed to list consumers for gateway", "gateway", gateway.Name)
148+
continue
149+
}
150+
151+
for _, consumer := range consumerList.Items {
152+
requests = append(requests, reconcile.Request{
153+
NamespacedName: client.ObjectKey{
154+
Namespace: consumer.Namespace,
155+
Name: consumer.Name,
156+
},
157+
})
158+
}
159+
}
160+
161+
return requests
162+
}
163+
118164
func (r *ConsumerReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
119165
consumer := new(v1alpha1.Consumer)
120166
if err := r.Get(ctx, req.NamespacedName, consumer); err != nil {

internal/controller/httproute_controller.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ func (r *HTTPRouteReconciler) SetupWithManager(mgr ctrl.Manager) error {
8282
handler.EnqueueRequestsFromMapFunc(r.listHTTPRouteByHTTPRoutePolicy),
8383
builder.WithPredicates(httpRoutePolicyPredicateFuncs(r.genericEvent)),
8484
).
85+
Watches(&v1alpha1.GatewayProxy{},
86+
handler.EnqueueRequestsFromMapFunc(r.listHTTPRoutesForGatewayProxy),
87+
).
8588
WatchesRawSource(
8689
source.Channel(
8790
r.genericEvent,
@@ -535,3 +538,48 @@ func httpRoutePolicyPredicateFuncs(channel chan event.GenericEvent) predicate.Pr
535538
},
536539
}
537540
}
541+
542+
// listHTTPRoutesForGatewayProxy list all HTTPRoute resources that are affected by a given GatewayProxy
543+
func (r *HTTPRouteReconciler) listHTTPRoutesForGatewayProxy(ctx context.Context, obj client.Object) []reconcile.Request {
544+
gatewayProxy, ok := obj.(*v1alpha1.GatewayProxy)
545+
if !ok {
546+
r.Log.Error(fmt.Errorf("unexpected object type"), "failed to convert object to GatewayProxy")
547+
return nil
548+
}
549+
550+
namespace := gatewayProxy.GetNamespace()
551+
name := gatewayProxy.GetName()
552+
553+
// find all gateways that reference this gateway proxy
554+
gatewayList := &gatewayv1.GatewayList{}
555+
if err := r.List(ctx, gatewayList, client.MatchingFields{
556+
indexer.ParametersRef: indexer.GenIndexKey(namespace, name),
557+
}); err != nil {
558+
r.Log.Error(err, "failed to list gateways for gateway proxy", "gatewayproxy", gatewayProxy.GetName())
559+
return nil
560+
}
561+
562+
var requests []reconcile.Request
563+
564+
// for each gateway, find all HTTPRoute resources that reference it
565+
for _, gateway := range gatewayList.Items {
566+
httpRouteList := &gatewayv1.HTTPRouteList{}
567+
if err := r.List(ctx, httpRouteList, client.MatchingFields{
568+
indexer.ParentRefs: indexer.GenIndexKey(gateway.Namespace, gateway.Name),
569+
}); err != nil {
570+
r.Log.Error(err, "failed to list httproutes for gateway", "gateway", gateway.Name)
571+
continue
572+
}
573+
574+
for _, httpRoute := range httpRouteList.Items {
575+
requests = append(requests, reconcile.Request{
576+
NamespacedName: client.ObjectKey{
577+
Namespace: httpRoute.Namespace,
578+
Name: httpRoute.Name,
579+
},
580+
})
581+
}
582+
}
583+
584+
return requests
585+
}

internal/controller/indexer/indexer.go

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,16 @@ import (
1414
)
1515

1616
const (
17-
ServiceIndexRef = "serviceRefs"
18-
ExtensionRef = "extensionRef"
19-
ParametersRef = "parametersRef"
20-
ParentRefs = "parentRefs"
21-
IngressClass = "ingressClass"
22-
SecretIndexRef = "secretRefs"
23-
IngressClassRef = "ingressClassRef"
24-
ConsumerGatewayRef = "consumerGatewayRef"
25-
PolicyTargetRefs = "targetRefs"
17+
ServiceIndexRef = "serviceRefs"
18+
ExtensionRef = "extensionRef"
19+
ParametersRef = "parametersRef"
20+
ParentRefs = "parentRefs"
21+
IngressClass = "ingressClass"
22+
SecretIndexRef = "secretRefs"
23+
IngressClassRef = "ingressClassRef"
24+
IngressClassParametersRef = "ingressClassParametersRef"
25+
ConsumerGatewayRef = "consumerGatewayRef"
26+
PolicyTargetRefs = "targetRefs"
2627
)
2728

2829
func SetupIndexer(mgr ctrl.Manager) error {
@@ -189,6 +190,16 @@ func setupIngressIndexer(mgr ctrl.Manager) error {
189190
return err
190191
}
191192

193+
// create IngressClassParametersRef index
194+
if err := mgr.GetFieldIndexer().IndexField(
195+
context.Background(),
196+
&networkingv1.IngressClass{},
197+
IngressClassParametersRef,
198+
IngressClassParametersRefIndexFunc,
199+
); err != nil {
200+
return err
201+
}
202+
192203
return nil
193204
}
194205

@@ -366,3 +377,19 @@ func BackendTrafficPolicyIndexFunc(rawObj client.Object) []string {
366377
}
367378
return keys
368379
}
380+
381+
func IngressClassParametersRefIndexFunc(rawObj client.Object) []string {
382+
ingressClass := rawObj.(*networkingv1.IngressClass)
383+
// check if the IngressClass references this gateway proxy
384+
if ingressClass.Spec.Parameters != nil &&
385+
ingressClass.Spec.Parameters.APIGroup != nil &&
386+
*ingressClass.Spec.Parameters.APIGroup == v1alpha1.GroupVersion.Group &&
387+
ingressClass.Spec.Parameters.Kind == "GatewayProxy" {
388+
ns := ingressClass.GetNamespace()
389+
if ingressClass.Spec.Parameters.Namespace != nil {
390+
ns = *ingressClass.Spec.Parameters.Namespace
391+
}
392+
return []string{GenIndexKey(ns, ingressClass.Spec.Parameters.Name)}
393+
}
394+
return nil
395+
}

internal/controller/ingress_controller.go

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ func (r *IngressReconciler) SetupWithManager(mgr ctrl.Manager) error {
8383
handler.EnqueueRequestsFromMapFunc(r.listIngressesByHTTPRoutePolicy),
8484
builder.WithPredicates(httpRoutePolicyPredicateFuncs(r.genericEvent)),
8585
).
86+
Watches(&v1alpha1.GatewayProxy{},
87+
handler.EnqueueRequestsFromMapFunc(r.listIngressesForGatewayProxy),
88+
).
8689
WatchesRawSource(
8790
source.Channel(
8891
r.genericEvent,
@@ -219,38 +222,8 @@ func (r *IngressReconciler) getIngressClass(obj client.Object) (*networkingv1.In
219222

220223
// checkIngressClass check if the ingress uses the ingress class that we control
221224
func (r *IngressReconciler) checkIngressClass(obj client.Object) bool {
222-
ingress := obj.(*networkingv1.Ingress)
223-
224-
if ingress.Spec.IngressClassName == nil {
225-
// handle the case where IngressClassName is not specified
226-
// find all ingress classes and check if any of them is marked as default
227-
ingressClassList := &networkingv1.IngressClassList{}
228-
if err := r.List(context.Background(), ingressClassList, client.MatchingFields{
229-
indexer.IngressClass: config.GetControllerName(),
230-
}); err != nil {
231-
r.Log.Error(err, "failed to list ingress classes")
232-
return false
233-
}
234-
235-
// find the ingress class that is marked as default
236-
for _, ic := range ingressClassList.Items {
237-
if IsDefaultIngressClass(&ic) && matchesController(ic.Spec.Controller) {
238-
log.Debugw("match the default ingress class")
239-
return true
240-
}
241-
}
242-
243-
log.Debugw("no default ingress class found")
244-
return false
245-
}
246-
247-
// check if the ingress class is controlled by us
248-
ingressClass := networkingv1.IngressClass{}
249-
if err := r.Client.Get(context.Background(), client.ObjectKey{Name: *ingress.Spec.IngressClassName}, &ingressClass); err != nil {
250-
return false
251-
}
252-
253-
return matchesController(ingressClass.Spec.Controller)
225+
_, err := r.getIngressClass(obj)
226+
return err == nil
254227
}
255228

256229
// matchesIngressController check if the ingress class is controlled by us
@@ -735,3 +708,46 @@ func (r *IngressReconciler) processIngressClassParameters(ctx context.Context, t
735708

736709
return nil
737710
}
711+
712+
// listIngressesForGatewayProxy list all ingresses that use a specific gateway proxy
713+
func (r *IngressReconciler) listIngressesForGatewayProxy(ctx context.Context, obj client.Object) []reconcile.Request {
714+
gatewayProxy, ok := obj.(*v1alpha1.GatewayProxy)
715+
if !ok {
716+
r.Log.Error(fmt.Errorf("unexpected object type"), "failed to convert object to GatewayProxy")
717+
return nil
718+
}
719+
720+
// find all ingress classes that reference this gateway proxy
721+
ingressClassList := &networkingv1.IngressClassList{}
722+
if err := r.List(ctx, ingressClassList, client.MatchingFields{
723+
indexer.IngressClassParametersRef: indexer.GenIndexKey(gatewayProxy.GetNamespace(), gatewayProxy.GetName()),
724+
}); err != nil {
725+
r.Log.Error(err, "failed to list ingress classes for gateway proxy", "gatewayproxy", gatewayProxy.GetName())
726+
return nil
727+
}
728+
729+
var requests []reconcile.Request
730+
731+
for _, ingressClass := range ingressClassList.Items {
732+
requests = append(requests, r.listIngressForIngressClass(ctx, &ingressClass)...)
733+
}
734+
735+
// the requests may contain duplicates, distinct the requests
736+
requests = distinctRequests(requests)
737+
738+
return requests
739+
}
740+
741+
// distinctRequests distinct the requests
742+
func distinctRequests(requests []reconcile.Request) []reconcile.Request {
743+
uniqueRequests := make(map[string]reconcile.Request)
744+
for _, request := range requests {
745+
uniqueRequests[request.String()] = request
746+
}
747+
748+
distinctRequests := make([]reconcile.Request, 0, len(uniqueRequests))
749+
for _, request := range uniqueRequests {
750+
distinctRequests = append(distinctRequests, request)
751+
}
752+
return distinctRequests
753+
}

0 commit comments

Comments
 (0)