@@ -4,12 +4,22 @@ import (
44 "context"
55
66 "github.com/api7/api7-ingress-controller/api/v1alpha1"
7+ "github.com/api7/api7-ingress-controller/internal/controller/indexer"
78 "github.com/api7/api7-ingress-controller/internal/provider"
89 "github.com/go-logr/logr"
10+ corev1 "k8s.io/api/core/v1"
11+ "k8s.io/apimachinery/pkg/api/meta"
912 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1013 "k8s.io/apimachinery/pkg/runtime"
14+ "k8s.io/apimachinery/pkg/types"
1115 ctrl "sigs.k8s.io/controller-runtime"
16+ "sigs.k8s.io/controller-runtime/pkg/builder"
1217 "sigs.k8s.io/controller-runtime/pkg/client"
18+ "sigs.k8s.io/controller-runtime/pkg/event"
19+ "sigs.k8s.io/controller-runtime/pkg/handler"
20+ "sigs.k8s.io/controller-runtime/pkg/predicate"
21+ "sigs.k8s.io/controller-runtime/pkg/reconcile"
22+ gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
1323)
1424
1525// ConsumerReconciler reconciles a Gateway object.
@@ -24,10 +34,59 @@ type ConsumerReconciler struct { //nolint:revive
2434// SetupWithManager sets up the controller with the Manager.
2535func (r * ConsumerReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
2636 return ctrl .NewControllerManagedBy (mgr ).
27- For (& v1alpha1.Consumer {}).
37+ For (& v1alpha1.Consumer {},
38+ builder .WithPredicates (
39+ predicate .NewPredicateFuncs (r .checkGatewayRef ),
40+ ),
41+ ).
42+ WithEventFilter (predicate.GenerationChangedPredicate {}).
43+ Watches (& gatewayv1.Gateway {},
44+ handler .EnqueueRequestsFromMapFunc (r .listConsumersForGateway ),
45+ builder .WithPredicates (
46+ predicate.Funcs {
47+ GenericFunc : func (e event.GenericEvent ) bool {
48+ return false
49+ },
50+ DeleteFunc : func (e event.DeleteEvent ) bool {
51+ return false
52+ },
53+ CreateFunc : func (e event.CreateEvent ) bool {
54+ return true
55+ },
56+ UpdateFunc : func (e event.UpdateEvent ) bool {
57+ return true
58+ },
59+ },
60+ ),
61+ ).
2862 Complete (r )
2963}
3064
65+ func (r * ConsumerReconciler ) listConsumersForGateway (ctx context.Context , obj client.Object ) []reconcile.Request {
66+ gateway , ok := obj .(* gatewayv1.Gateway )
67+ if ! ok {
68+ r .Log .Error (nil , "failed to convert to Gateway" , "object" , obj )
69+ return nil
70+ }
71+ consumerList := & v1alpha1.ConsumerList {}
72+ if err := r .List (ctx , consumerList , client.MatchingFields {
73+ indexer .ConsumerGatewayRef : indexer .GenIndexKey (gateway .Name , gateway .GetNamespace ()),
74+ }); err != nil {
75+ r .Log .Error (err , "failed to list consumers" )
76+ return nil
77+ }
78+ var requests []reconcile.Request
79+ for _ , consumer := range consumerList .Items {
80+ requests = append (requests , reconcile.Request {
81+ NamespacedName : client.ObjectKey {
82+ Name : consumer .Name ,
83+ Namespace : consumer .Namespace ,
84+ },
85+ })
86+ }
87+ return requests
88+ }
89+
3190func (r * ConsumerReconciler ) Reconcile (ctx context.Context , req ctrl.Request ) (ctrl.Result , error ) {
3291 consumer := new (v1alpha1.Consumer )
3392 if err := r .Get (ctx , req .NamespacedName , consumer ); err != nil {
@@ -41,10 +100,109 @@ func (r *ConsumerReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
41100 }
42101
43102 if err := r .Provider .Delete (ctx , consumer ); err != nil {
103+ r .Log .Error (err , "failed to delete consumer" , "consumer" , consumer )
44104 return ctrl.Result {}, err
45105 }
106+ return ctrl.Result {}, nil
46107 }
108+ r .Log .Error (err , "failed to get consumer" , "consumer" , consumer )
47109 return ctrl.Result {}, err
48110 }
111+
112+ var statusErr error
113+ tctx := provider .NewDefaultTranslateContext ()
114+
115+ if err := r .processSepc (ctx , tctx , consumer ); err != nil {
116+ r .Log .Error (err , "failed to process consumer spec" , "consumer" , consumer )
117+ statusErr = err
118+ }
119+
120+ if err := r .Provider .Update (ctx , tctx , consumer ); err != nil {
121+ r .Log .Error (err , "failed to update consumer" , "consumer" , consumer )
122+ statusErr = err
123+ }
124+
125+ if err := r .updateStatus (ctx , consumer , statusErr ); err != nil {
126+ r .Log .Error (err , "failed to update consumer status" , "consumer" , consumer )
127+ return ctrl.Result {}, err
128+ }
129+
49130 return ctrl.Result {}, nil
50131}
132+
133+ func (r * ConsumerReconciler ) processSepc (ctx context.Context , tctx * provider.TranslateContext , consumer * v1alpha1.Consumer ) error {
134+ r .Log .Info ("Processing consumer" , "name" , consumer .Name , "namespace" , consumer .Namespace )
135+
136+ for _ , credential := range consumer .Spec .Credentials {
137+ if credential .SecretRef == nil {
138+ continue
139+ }
140+ ns := consumer .GetNamespace ()
141+ if credential .SecretRef .Namespace != nil {
142+ ns = string (* credential .SecretRef .Namespace )
143+ }
144+ secret := corev1.Secret {}
145+ if err := r .Get (ctx , client.ObjectKey {
146+ Name : credential .SecretRef .Name ,
147+ Namespace : ns ,
148+ }, & secret ); err != nil {
149+ if client .IgnoreNotFound (err ) == nil {
150+ continue
151+ }
152+ r .Log .Error (err , "failed to get secret" , "secret" , credential .SecretRef .Name )
153+ return err
154+ }
155+
156+ tctx .Secrets [types.NamespacedName {
157+ Namespace : ns ,
158+ Name : credential .SecretRef .Name ,
159+ }] = & secret
160+
161+ }
162+ return nil
163+ }
164+
165+ func (r * ConsumerReconciler ) updateStatus (ctx context.Context , consumer * v1alpha1.Consumer , err error ) error {
166+ condition := NewCondition (consumer .Generation , true , "Successfully" )
167+ if err != nil {
168+ condition = NewCondition (consumer .Generation , false , err .Error ())
169+ }
170+ if ! VerifyConditions (& consumer .Status .Conditions , condition ) {
171+ return nil
172+ }
173+ meta .SetStatusCondition (& consumer .Status .Conditions , condition )
174+ if err := r .Status ().Update (ctx , consumer ); err != nil {
175+ r .Log .Error (err , "failed to update consumer status" , "consumer" , consumer )
176+ return err
177+ }
178+ return nil
179+ }
180+
181+ func (r * ConsumerReconciler ) checkGatewayRef (object client.Object ) bool {
182+ consumer , ok := object .(* v1alpha1.Consumer )
183+ if ! ok {
184+ return false
185+ }
186+ if consumer .Spec .GatewayRef .Name == "" {
187+ return false
188+ }
189+ if consumer .Spec .GatewayRef .Kind != nil && * consumer .Spec .GatewayRef .Kind != KindGateway {
190+ return false
191+ }
192+ if consumer .Spec .GatewayRef .Group != nil && * consumer .Spec .GatewayRef .Group != gatewayv1 .GroupName {
193+ return false
194+ }
195+ ns := consumer .GetNamespace ()
196+ if consumer .Spec .GatewayRef .Namespace != nil {
197+ ns = string (* consumer .Spec .GatewayRef .Namespace )
198+ }
199+ gateway := & gatewayv1.Gateway {}
200+ if err := r .Get (context .TODO (), client.ObjectKey {
201+ Name : consumer .Spec .GatewayRef .Name ,
202+ Namespace : ns ,
203+ }, gateway ); err != nil {
204+ r .Log .Error (err , "failed to get gateway" , "gateway" , consumer .Spec .GatewayRef .Name )
205+ return false
206+ }
207+ return true
208+ }
0 commit comments