@@ -16,24 +16,34 @@ package controllers
1616
1717import (
1818 "context"
19+ "fmt"
20+ "reflect"
21+ "runtime"
1922
23+ "emperror.dev/errors"
24+ "github.com/cisco-open/operator-tools/pkg/reconciler"
2025 "github.com/go-logr/logr"
26+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2127 ctrl "sigs.k8s.io/controller-runtime"
2228 "sigs.k8s.io/controller-runtime/pkg/client"
2329
24- "github.com/kube-logging/logging-operator/pkg/sdk/logging/api/v1beta1"
30+ "github.com/kube-logging/logging-operator/pkg/resources"
31+ axosyslogresources "github.com/kube-logging/logging-operator/pkg/resources/axosyslog"
32+ v1beta1 "github.com/kube-logging/logging-operator/pkg/sdk/logging/api/v1beta1"
2533)
2634
2735// NewAxoSyslogReconciler creates a new AxoSyslogReconciler instance
28- func NewAxoSyslogReconciler (client client.Client , log logr.Logger ) * AxoSyslogReconciler {
36+ func NewAxoSyslogReconciler (client client.Client , log logr.Logger , opts reconciler. ReconcilerOpts ) * AxoSyslogReconciler {
2937 return & AxoSyslogReconciler {
30- Client : client ,
31- Log : log ,
38+ Client : client ,
39+ GenericResourceReconciler : reconciler .NewGenericReconciler (client , log , opts ),
40+ Log : log ,
3241 }
3342}
3443
3544type AxoSyslogReconciler struct {
3645 client.Client
46+ * reconciler.GenericResourceReconciler
3747 Log logr.Logger
3848}
3949
@@ -42,29 +52,142 @@ type AxoSyslogReconciler struct {
4252// +kubebuilder:rbac:groups="",resources=configmaps;secrets,verbs=get;list;watch;create;update;patch;delete
4353// +kubebuilder:rbac:groups=apps,resources=statefulsets,verbs=get;list;watch;create;update;patch;delete
4454// +kubebuilder:rbac:groups="",resources=services;persistentvolumeclaims;serviceaccounts;pods,verbs=get;list;watch;create;update;patch;delete
45- // +kubebuilder:rbac:groups="rbac.authorization.k8s.io",resources=clusterroles;clusterrolebindings; roles;rolebindings,verbs=get;list;watch;create;update;patch;delete
55+ // +kubebuilder:rbac:groups="rbac.authorization.k8s.io",resources=roles;rolebindings,verbs=get;list;watch;create;update;patch;delete
4656
47- // Reconciles axosyslog resource
57+ // Reconcile implements the reconciliation logic for AxoSyslog resources
4858func (r * AxoSyslogReconciler ) Reconcile (ctx context.Context , req ctrl.Request ) (ctrl.Result , error ) {
49- log := r .Log .WithValues ( "axosyslog" , req . NamespacedName )
59+ r .Log .V ( 1 ). Info ( "Reconciling AxoSyslog" )
5060
51- log .V (1 ).Info ("Reconciling AxoSyslog" )
52-
53- var axosyslog v1beta1.AxoSyslog
54- if err := r .Get (ctx , req .NamespacedName , & axosyslog ); err != nil {
61+ var axoSyslog v1beta1.AxoSyslog
62+ if err := r .Get (ctx , req .NamespacedName , & axoSyslog ); err != nil {
5563 return ctrl.Result {}, client .IgnoreNotFound (err )
5664 }
5765
58- if err := axosyslog .SetDefaults (); err != nil {
66+ log := r .Log .WithValues ("axosyslog" , fmt .Sprintf ("%s/%s" , axoSyslog .Namespace , axoSyslog .Name ))
67+
68+ if err := axoSyslog .SetDefaults (); err != nil {
69+ return ctrl.Result {}, errors .WrapIf (err , "failed to set defaults" )
70+ }
71+
72+ if result , err := r .reconcileRBACResources (log , & axoSyslog ); err != nil {
73+ return ctrl.Result {}, err
74+ } else if result != nil {
75+ return * result , nil
76+ }
77+
78+ // TODO: config-check ?
79+ // TODO: output-secret && secret-mark ?
80+ // TODO: config-secret?
81+
82+ if result , err := r .reconcileWorkloadResources (log , & axoSyslog ); err != nil {
5983 return ctrl.Result {}, err
84+ } else if result != nil {
85+ return * result , nil
6086 }
6187
6288 return ctrl.Result {}, nil
6389}
6490
91+ // reconcileRBACResources handles resources related to AxoSyslog
92+ func (r * AxoSyslogReconciler ) reconcileRBACResources (log logr.Logger , axoSyslog * v1beta1.AxoSyslog ) (* ctrl.Result , error ) {
93+ resourceBuilders := []resources.ResourceWithNamespace {
94+ axosyslogresources .ServiceAccount ,
95+ axosyslogresources .Role ,
96+ axosyslogresources .RoleBinding ,
97+ }
98+
99+ for _ , buildObject := range resourceBuilders {
100+ builderName := getFunctionName (buildObject )
101+ log .V (2 ).Info ("Processing resource" , "builder" , builderName )
102+
103+ o , state , err := buildObject (axoSyslog .Namespace )
104+ if err != nil {
105+ return nil , errors .WrapIff (err , "failed to build object with %s" , builderName )
106+ }
107+ if o == nil {
108+ return nil , errors .Errorf ("reconcile error: %s returned nil object" , builderName )
109+ }
110+
111+ metaObj , ok := o .(metav1.Object )
112+ if ! ok {
113+ return nil , errors .Errorf ("reconcile error: %s returned non-metav1.Object" , builderName )
114+ }
115+
116+ if metaObj .GetNamespace () == "" {
117+ return nil , errors .Errorf ("reconcile error: %s returned resource without namespace set" , builderName )
118+ }
119+
120+ if err := ctrl .SetControllerReference (axoSyslog , metaObj , r .Scheme ()); err != nil {
121+ return nil , errors .WrapIff (err , "failed to set controller reference for %s" , metaObj .GetName ())
122+ }
123+
124+ result , err := r .ReconcileResource (o , state )
125+ if err != nil {
126+ return nil , errors .WrapIff (err , "failed to reconcile resource %s/%s" , metaObj .GetNamespace (), metaObj .GetName ())
127+ }
128+ if result != nil {
129+ return result , nil
130+ }
131+ }
132+
133+ return nil , nil
134+ }
135+
136+ // reconcileWorkloadResources handles resources related to AxoSyslog and requires it's spec
137+ func (r * AxoSyslogReconciler ) reconcileWorkloadResources (log logr.Logger , axoSyslog * v1beta1.AxoSyslog ) (* ctrl.Result , error ) {
138+ resourceBuilders := []resources.ResourceWithSpec {
139+ axosyslogresources .StatefulSet ,
140+ axosyslogresources .Service ,
141+ axosyslogresources .HeadlessService ,
142+ // TODO: service-metrics & buffer-metrics ?
143+ // axosyslogresources.ServiceMetrics,
144+ // axosyslogresources.ServiceBufferMetrics,
145+ }
146+
147+ for _ , buildObject := range resourceBuilders {
148+ builderName := getFunctionName (buildObject )
149+ log .V (2 ).Info ("Processing resource" , "builder" , builderName )
150+
151+ o , state , err := buildObject (axoSyslog )
152+ if err != nil {
153+ return nil , errors .WrapIff (err , "failed to build object with %s" , builderName )
154+ }
155+ if o == nil {
156+ return nil , errors .Errorf ("reconcile error: %s returned nil object" , builderName )
157+ }
158+
159+ metaObj , ok := o .(metav1.Object )
160+ if ! ok {
161+ return nil , errors .Errorf ("reconcile error: %s returned non-metav1.Object" , builderName )
162+ }
163+
164+ if metaObj .GetNamespace () == "" {
165+ return nil , errors .Errorf ("reconcile error: %s returned resource without namespace set" , builderName )
166+ }
167+
168+ if err := ctrl .SetControllerReference (axoSyslog , metaObj , r .Scheme ()); err != nil {
169+ return nil , errors .WrapIff (err , "failed to set controller reference for %s" , metaObj .GetName ())
170+ }
171+
172+ result , err := r .ReconcileResource (o , state )
173+ if err != nil {
174+ return nil , errors .WrapIff (err , "failed to reconcile resource %s/%s" , metaObj .GetNamespace (), metaObj .GetName ())
175+ }
176+ if result != nil {
177+ return result , nil
178+ }
179+ }
180+
181+ return nil , nil
182+ }
183+
65184func SetupAxoSyslogWithManager (mgr ctrl.Manager , logger logr.Logger ) error {
66185 return ctrl .NewControllerManagedBy (mgr ).
67186 For (& v1beta1.AxoSyslog {}).
68- Named ("AxoSyslogController" ).
69- Complete (NewAxoSyslogReconciler (mgr .GetClient (), logger ))
187+ Named ("axosyslog" ).
188+ Complete (NewAxoSyslogReconciler (mgr .GetClient (), logger , reconciler.ReconcilerOpts {}))
189+ }
190+
191+ func getFunctionName (i any ) string {
192+ return runtime .FuncForPC (reflect .ValueOf (i ).Pointer ()).Name ()
70193}
0 commit comments