@@ -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+ requests := make ([]reconcile.Request , 0 , len (consumerList .Items ))
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 {
@@ -43,8 +102,107 @@ func (r *ConsumerReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
43102 if err := r .Provider .Delete (ctx , consumer ); err != nil {
44103 return ctrl.Result {}, err
45104 }
105+ return ctrl.Result {}, nil
46106 }
47107 return ctrl.Result {}, err
48108 }
109+
110+ var statusErr error
111+ tctx := provider .NewDefaultTranslateContext ()
112+
113+ if err := r .processSpec (ctx , tctx , consumer ); err != nil {
114+ r .Log .Error (err , "failed to process consumer spec" , "consumer" , consumer )
115+ statusErr = err
116+ }
117+
118+ if err := r .Provider .Update (ctx , tctx , consumer ); err != nil {
119+ r .Log .Error (err , "failed to update consumer" , "consumer" , consumer )
120+ statusErr = err
121+ }
122+
123+ if err := r .updateStatus (ctx , consumer , statusErr ); err != nil {
124+ return ctrl.Result {}, err
125+ }
126+
49127 return ctrl.Result {}, nil
50128}
129+
130+ func (r * ConsumerReconciler ) processSpec (ctx context.Context , tctx * provider.TranslateContext , consumer * v1alpha1.Consumer ) error {
131+ for _ , credential := range consumer .Spec .Credentials {
132+ if credential .SecretRef == nil {
133+ continue
134+ }
135+ ns := consumer .GetNamespace ()
136+ if credential .SecretRef .Namespace != nil {
137+ ns = * credential .SecretRef .Namespace
138+ }
139+ secret := corev1.Secret {}
140+ if err := r .Get (ctx , client.ObjectKey {
141+ Name : credential .SecretRef .Name ,
142+ Namespace : ns ,
143+ }, & secret ); err != nil {
144+ if client .IgnoreNotFound (err ) == nil {
145+ continue
146+ }
147+ r .Log .Error (err , "failed to get secret" , "secret" , credential .SecretRef .Name )
148+ return err
149+ }
150+
151+ tctx .Secrets [types.NamespacedName {
152+ Namespace : ns ,
153+ Name : credential .SecretRef .Name ,
154+ }] = & secret
155+
156+ }
157+ return nil
158+ }
159+
160+ func (r * ConsumerReconciler ) updateStatus (ctx context.Context , consumer * v1alpha1.Consumer , err error ) error {
161+ condition := NewCondition (consumer .Generation , true , "Successfully" )
162+ if err != nil {
163+ condition = NewCondition (consumer .Generation , false , err .Error ())
164+ }
165+ if ! VerifyConditions (& consumer .Status .Conditions , condition ) {
166+ return nil
167+ }
168+ meta .SetStatusCondition (& consumer .Status .Conditions , condition )
169+ if err := r .Status ().Update (ctx , consumer ); err != nil {
170+ r .Log .Error (err , "failed to update consumer status" , "consumer" , consumer )
171+ return err
172+ }
173+ return nil
174+ }
175+
176+ func (r * ConsumerReconciler ) checkGatewayRef (object client.Object ) bool {
177+ consumer , ok := object .(* v1alpha1.Consumer )
178+ if ! ok {
179+ return false
180+ }
181+ if consumer .Spec .GatewayRef .Name == "" {
182+ return false
183+ }
184+ if consumer .Spec .GatewayRef .Kind != nil && * consumer .Spec .GatewayRef .Kind != KindGateway {
185+ return false
186+ }
187+ if consumer .Spec .GatewayRef .Group != nil && * consumer .Spec .GatewayRef .Group != gatewayv1 .GroupName {
188+ return false
189+ }
190+ ns := consumer .GetNamespace ()
191+ if consumer .Spec .GatewayRef .Namespace != nil {
192+ ns = * consumer .Spec .GatewayRef .Namespace
193+ }
194+ gateway := & gatewayv1.Gateway {}
195+ if err := r .Get (context .Background (), client.ObjectKey {
196+ Name : consumer .Spec .GatewayRef .Name ,
197+ Namespace : ns ,
198+ }, gateway ); err != nil {
199+ r .Log .Error (err , "failed to get gateway" , "gateway" , consumer .Spec .GatewayRef .Name )
200+ return false
201+ }
202+ gatewayClass := & gatewayv1.GatewayClass {}
203+ if err := r .Client .Get (context .Background (), client.ObjectKey {Name : string (gateway .Spec .GatewayClassName )}, gatewayClass ); err != nil {
204+ r .Log .Error (err , "failed to get gateway class" , "gateway" , gateway .GetName (), "gatewayclass" , gateway .Spec .GatewayClassName )
205+ return false
206+ }
207+ return matchesController (string (gatewayClass .Spec .ControllerName ))
208+ }
0 commit comments