@@ -14,56 +14,215 @@ package controller
1414
1515import (
1616 "context"
17+ "fmt"
1718
19+ "github.com/api7/gopkg/pkg/log"
1820 "github.com/go-logr/logr"
21+ corev1 "k8s.io/api/core/v1"
22+ networkingv1 "k8s.io/api/networking/v1"
23+ k8serrors "k8s.io/apimachinery/pkg/api/errors"
1924 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2025 "k8s.io/apimachinery/pkg/runtime"
26+ "k8s.io/apimachinery/pkg/types"
2127 ctrl "sigs.k8s.io/controller-runtime"
28+ "sigs.k8s.io/controller-runtime/pkg/builder"
2229 "sigs.k8s.io/controller-runtime/pkg/client"
30+ "sigs.k8s.io/controller-runtime/pkg/handler"
31+ "sigs.k8s.io/controller-runtime/pkg/predicate"
32+ "sigs.k8s.io/controller-runtime/pkg/reconcile"
2333 gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
2434
35+ "github.com/apache/apisix-ingress-controller/api/v1alpha1"
2536 apiv2 "github.com/apache/apisix-ingress-controller/api/v2"
37+ "github.com/apache/apisix-ingress-controller/internal/controller/status"
38+ "github.com/apache/apisix-ingress-controller/internal/provider"
39+ "github.com/apache/apisix-ingress-controller/internal/utils"
2640)
2741
2842// ApisixConsumerReconciler reconciles a ApisixConsumer object
2943type ApisixConsumerReconciler struct {
3044 client.Client
3145 Scheme * runtime.Scheme
3246 Log logr.Logger
47+
48+ Provider provider.Provider
49+ Updater status.Updater
3350}
3451
3552// Reconcile FIXME: implement the reconcile logic (For now, it dose nothing other than directly accepting)
3653func (r * ApisixConsumerReconciler ) Reconcile (ctx context.Context , req ctrl.Request ) (ctrl.Result , error ) {
3754 r .Log .Info ("reconcile" , "request" , req .NamespacedName )
3855
39- var obj apiv2.ApisixConsumer
40- if err := r .Get (ctx , req .NamespacedName , & obj ); err != nil {
56+ ac := & apiv2.ApisixConsumer {}
57+ if err := r .Get (ctx , req .NamespacedName , ac ); err != nil {
58+ if k8serrors .IsNotFound (err ) {
59+ ac .Namespace = req .Namespace
60+ ac .Name = req .Name
61+ ac .TypeMeta = metav1.TypeMeta {
62+ Kind : KindApisixConsumer ,
63+ APIVersion : apiv2 .GroupVersion .String (),
64+ }
65+ if err := r .Provider .Delete (ctx , ac ); err != nil {
66+ r .Log .Error (err , "failed to delete provider" , "ApisixConsumer" , ac )
67+ return ctrl.Result {}, err
68+ }
69+ }
4170 r .Log .Error (err , "failed to get ApisixConsumer" , "request" , req .NamespacedName )
4271 return ctrl.Result {}, err
4372 }
4473
45- obj .Status .Conditions = []metav1.Condition {
46- {
47- Type : string (gatewayv1 .RouteConditionAccepted ),
48- Status : metav1 .ConditionTrue ,
49- ObservedGeneration : obj .GetGeneration (),
50- LastTransitionTime : metav1 .Now (),
51- Reason : string (gatewayv1 .RouteReasonAccepted ),
52- },
74+ tctx := provider .NewDefaultTranslateContext (ctx )
75+
76+ ingressClass , err := GetIngressClass (tctx , r .Client , r .Log , ac .Spec .IngressClassName )
77+ if err != nil {
78+ log .Error (err , "failed to get IngressClass" )
79+ return ctrl.Result {}, err
5380 }
5481
55- if err := r . Status (). Update ( ctx , & obj ); err != nil {
56- r . Log . Error (err , "failed to update status " , "request " , req . NamespacedName )
82+ if err := ProcessIngressClassParameters ( tctx , r . Client , r . Log , ac , ingressClass ); err != nil {
83+ log . Error (err , "failed to process IngressClass parameters " , "ingressClass " , ingressClass . Name )
5784 return ctrl.Result {}, err
5885 }
5986
87+ if err := r .Provider .Update (ctx , tctx , ac ); err != nil {
88+ r .Log .Error (err , "failed to update provider" , "ApisixConsumer" , ac )
89+ // Update status with failure condition
90+ r .updateStatus (ac , metav1.Condition {
91+ Type : string (apiv2 .ConditionTypeAccepted ),
92+ Status : metav1 .ConditionFalse ,
93+ ObservedGeneration : ac .Generation ,
94+ LastTransitionTime : metav1 .Now (),
95+ Reason : string (apiv2 .ConditionReasonSyncFailed ),
96+ Message : err .Error (),
97+ })
98+ return ctrl.Result {}, err
99+ }
100+
101+ // Update status with success condition
102+ r .updateStatus (ac , metav1.Condition {
103+ Type : string (gatewayv1 .RouteConditionAccepted ),
104+ Status : metav1 .ConditionTrue ,
105+ ObservedGeneration : ac .Generation ,
106+ LastTransitionTime : metav1 .Now (),
107+ Reason : string (gatewayv1 .RouteReasonAccepted ),
108+ Message : "The ApisixConsumer has been accepted by the apisix-ingress-controller" ,
109+ })
60110 return ctrl.Result {}, nil
61111}
62112
63113// SetupWithManager sets up the controller with the Manager.
64114func (r * ApisixConsumerReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
65115 return ctrl .NewControllerManagedBy (mgr ).
66- For (& apiv2.ApisixConsumer {}).
116+ For (& apiv2.ApisixConsumer {},
117+ builder .WithPredicates (
118+ predicate .NewPredicateFuncs (r .checkIngressClass ),
119+ )).
120+ WithEventFilter (
121+ predicate .Or (
122+ predicate.GenerationChangedPredicate {},
123+ predicate.AnnotationChangedPredicate {},
124+ ),
125+ ).
126+ Watches (
127+ & networkingv1.IngressClass {},
128+ handler .EnqueueRequestsFromMapFunc (r .listApisixConsumerForIngressClass ),
129+ builder .WithPredicates (
130+ predicate .NewPredicateFuncs (matchesIngressController ),
131+ ),
132+ ).
133+ Watches (& v1alpha1.GatewayProxy {},
134+ handler .EnqueueRequestsFromMapFunc (r .listApisixConsumerForGatewayProxy ),
135+ ).
67136 Named ("apisixconsumer" ).
68137 Complete (r )
69138}
139+
140+ func (r * ApisixConsumerReconciler ) checkIngressClass (obj client.Object ) bool {
141+ ac , ok := obj .(* apiv2.ApisixConsumer )
142+ if ! ok {
143+ return false
144+ }
145+
146+ return matchesIngressClass (r .Client , r .Log , ac .Spec .IngressClassName )
147+ }
148+
149+ func (r * ApisixConsumerReconciler ) listApisixConsumerForGatewayProxy (ctx context.Context , obj client.Object ) []reconcile.Request {
150+ return listIngressClassRequestsForGatewayProxy (ctx , r .Client , obj , r .Log , r .listApisixConsumerForIngressClass )
151+ }
152+
153+ func (r * ApisixConsumerReconciler ) listApisixConsumerForIngressClass (ctx context.Context , obj client.Object ) []reconcile.Request {
154+ ingressClass , ok := obj .(* networkingv1.IngressClass )
155+ if ! ok {
156+ return nil
157+ }
158+
159+ return ListMatchingRequests (
160+ ctx ,
161+ r .Client ,
162+ r .Log ,
163+ & apiv2.ApisixConsumerList {},
164+ func (obj client.Object ) bool {
165+ ac , ok := obj .(* apiv2.ApisixConsumer )
166+ if ! ok {
167+ r .Log .Error (fmt .Errorf ("expected ApisixConsumer, got %T" , obj ), "failed to match object type" )
168+ return false
169+ }
170+ return (IsDefaultIngressClass (ingressClass ) && ac .Spec .IngressClassName == "" ) || ac .Spec .IngressClassName == ingressClass .Name
171+ },
172+ )
173+ }
174+
175+ func (r * ApisixConsumerReconciler ) processSpec (ctx context.Context , tctx * provider.TranslateContext , ac * apiv2.ApisixConsumer ) error {
176+ var secretRef * corev1.LocalObjectReference
177+ if ac .Spec .AuthParameter .KeyAuth != nil {
178+ secretRef = ac .Spec .AuthParameter .KeyAuth .SecretRef
179+ } else if ac .Spec .AuthParameter .BasicAuth != nil {
180+ secretRef = ac .Spec .AuthParameter .BasicAuth .SecretRef
181+ } else if ac .Spec .AuthParameter .JwtAuth != nil {
182+ secretRef = ac .Spec .AuthParameter .JwtAuth .SecretRef
183+ } else if ac .Spec .AuthParameter .WolfRBAC != nil {
184+ secretRef = ac .Spec .AuthParameter .WolfRBAC .SecretRef
185+ } else if ac .Spec .AuthParameter .HMACAuth != nil {
186+ secretRef = ac .Spec .AuthParameter .HMACAuth .SecretRef
187+ } else if ac .Spec .AuthParameter .LDAPAuth != nil {
188+ secretRef = ac .Spec .AuthParameter .LDAPAuth .SecretRef
189+ }
190+ if secretRef == nil {
191+ return nil
192+ }
193+
194+ namespacedName := types.NamespacedName {
195+ Name : secretRef .Name ,
196+ Namespace : ac .Namespace ,
197+ }
198+
199+ secret := & corev1.Secret {}
200+ if err := r .Get (ctx , namespacedName , secret ); err != nil {
201+ if k8serrors .IsNotFound (err ) {
202+ r .Log .Info ("secret not found" , "secret" , namespacedName .String ())
203+ return nil
204+ } else {
205+ r .Log .Error (err , "failed to get secret" , "secret" , namespacedName .String ())
206+ return err
207+ }
208+ }
209+ tctx .Secrets [namespacedName ] = secret
210+ return nil
211+ }
212+
213+ func (r * ApisixConsumerReconciler ) updateStatus (consumer * apiv2.ApisixConsumer , condition metav1.Condition ) {
214+ r .Updater .Update (status.Update {
215+ NamespacedName : utils .NamespacedName (consumer ),
216+ Resource : & apiv2.ApisixConsumer {},
217+ Mutator : status .MutatorFunc (func (obj client.Object ) client.Object {
218+ ac , ok := obj .(* apiv2.ApisixConsumer )
219+ if ! ok {
220+ err := fmt .Errorf ("unsupported object type %T" , obj )
221+ panic (err )
222+ }
223+ acCopy := ac .DeepCopy ()
224+ acCopy .Status .Conditions = []metav1.Condition {condition }
225+ return acCopy
226+ }),
227+ })
228+ }
0 commit comments