@@ -16,24 +16,34 @@ package controllers
16
16
17
17
import (
18
18
"context"
19
+ "fmt"
20
+ "reflect"
21
+ "runtime"
19
22
23
+ "emperror.dev/errors"
24
+ "github.com/cisco-open/operator-tools/pkg/reconciler"
20
25
"github.com/go-logr/logr"
26
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21
27
ctrl "sigs.k8s.io/controller-runtime"
22
28
"sigs.k8s.io/controller-runtime/pkg/client"
23
29
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"
25
33
)
26
34
27
35
// 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 {
29
37
return & AxoSyslogReconciler {
30
- Client : client ,
31
- Log : log ,
38
+ Client : client ,
39
+ GenericResourceReconciler : reconciler .NewGenericReconciler (client , log , opts ),
40
+ Log : log ,
32
41
}
33
42
}
34
43
35
44
type AxoSyslogReconciler struct {
36
45
client.Client
46
+ * reconciler.GenericResourceReconciler
37
47
Log logr.Logger
38
48
}
39
49
@@ -42,29 +52,142 @@ type AxoSyslogReconciler struct {
42
52
// +kubebuilder:rbac:groups="",resources=configmaps;secrets,verbs=get;list;watch;create;update;patch;delete
43
53
// +kubebuilder:rbac:groups=apps,resources=statefulsets,verbs=get;list;watch;create;update;patch;delete
44
54
// +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
46
56
47
- // Reconciles axosyslog resource
57
+ // Reconcile implements the reconciliation logic for AxoSyslog resources
48
58
func (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" )
50
60
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 {
55
63
return ctrl.Result {}, client .IgnoreNotFound (err )
56
64
}
57
65
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 {
59
83
return ctrl.Result {}, err
84
+ } else if result != nil {
85
+ return * result , nil
60
86
}
61
87
62
88
return ctrl.Result {}, nil
63
89
}
64
90
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
+
65
184
func SetupAxoSyslogWithManager (mgr ctrl.Manager , logger logr.Logger ) error {
66
185
return ctrl .NewControllerManagedBy (mgr ).
67
186
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 ()
70
193
}
0 commit comments