@@ -4,12 +4,22 @@ import (
4
4
"context"
5
5
6
6
"github.com/api7/api7-ingress-controller/api/v1alpha1"
7
+ "github.com/api7/api7-ingress-controller/internal/controller/indexer"
7
8
"github.com/api7/api7-ingress-controller/internal/provider"
8
9
"github.com/go-logr/logr"
10
+ corev1 "k8s.io/api/core/v1"
11
+ "k8s.io/apimachinery/pkg/api/meta"
9
12
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10
13
"k8s.io/apimachinery/pkg/runtime"
14
+ "k8s.io/apimachinery/pkg/types"
11
15
ctrl "sigs.k8s.io/controller-runtime"
16
+ "sigs.k8s.io/controller-runtime/pkg/builder"
12
17
"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"
13
23
)
14
24
15
25
// ConsumerReconciler reconciles a Gateway object.
@@ -24,10 +34,59 @@ type ConsumerReconciler struct { //nolint:revive
24
34
// SetupWithManager sets up the controller with the Manager.
25
35
func (r * ConsumerReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
26
36
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
+ ).
28
62
Complete (r )
29
63
}
30
64
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
+
31
90
func (r * ConsumerReconciler ) Reconcile (ctx context.Context , req ctrl.Request ) (ctrl.Result , error ) {
32
91
consumer := new (v1alpha1.Consumer )
33
92
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
43
102
if err := r .Provider .Delete (ctx , consumer ); err != nil {
44
103
return ctrl.Result {}, err
45
104
}
105
+ return ctrl.Result {}, nil
46
106
}
47
107
return ctrl.Result {}, err
48
108
}
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
+
49
127
return ctrl.Result {}, nil
50
128
}
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