@@ -2,19 +2,21 @@ package operator
22
33import (
44 "context"
5- "fmt"
65
76 cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
87 "github.com/cloudnative-pg/cnpg-i-machinery/pkg/pluginhelper/decoder"
98 "github.com/cloudnative-pg/cnpg-i-machinery/pkg/pluginhelper/object"
109 "github.com/cloudnative-pg/cnpg-i/pkg/reconciler"
1110 rbacv1 "k8s.io/api/rbac/v1"
11+ "k8s.io/apimachinery/pkg/api/equality"
1212 apierrs "k8s.io/apimachinery/pkg/api/errors"
13- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1413 ctrl "sigs.k8s.io/controller-runtime"
1514 "sigs.k8s.io/controller-runtime/pkg/client"
15+ "sigs.k8s.io/controller-runtime/pkg/log"
1616
17+ barmancloudv1 "github.com/cloudnative-pg/plugin-barman-cloud/api/v1"
1718 "github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config"
19+ "github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/specs"
1820)
1921
2022// ReconcilerImplementation implements the Reconciler capability
@@ -45,6 +47,8 @@ func (r ReconcilerImplementation) Pre(
4547 ctx context.Context ,
4648 request * reconciler.ReconcilerHooksRequest ,
4749) (* reconciler.ReconcilerHooksResult , error ) {
50+ contextLogger := log .FromContext (ctx )
51+
4852 reconciledKind , err := object .GetKind (request .GetResourceDefinition ())
4953 if err != nil {
5054 return nil , err
@@ -60,12 +64,28 @@ func (r ReconcilerImplementation) Pre(
6064 return nil , err
6165 }
6266
67+ contextLogger = contextLogger .WithValues ("name" , cluster .Name , "namespace" , cluster .Namespace )
68+ ctx = log .IntoContext (ctx , contextLogger )
69+
6370 pluginConfiguration , err := config .NewFromCluster (cluster )
6471 if err != nil {
6572 return nil , err
6673 }
6774
68- if err := r .ensureRole (ctx , cluster , pluginConfiguration .BarmanObjectName ); err != nil {
75+ var barmanObject barmancloudv1.ObjectStore
76+ if err := r .Client .Get (ctx , client.ObjectKey {
77+ Namespace : cluster .Namespace ,
78+ Name : pluginConfiguration .BarmanObjectName ,
79+ }, & barmanObject ); err != nil {
80+ if apierrs .IsNotFound (err ) {
81+ contextLogger .Info ("Not found barman object configuration, requeuing" )
82+ return & reconciler.ReconcilerHooksResult {
83+ Behavior : reconciler .ReconcilerHooksResult_BEHAVIOR_REQUEUE ,
84+ }, nil
85+ }
86+ }
87+
88+ if err := r .ensureRole (ctx , cluster , & barmanObject ); err != nil {
6989 return nil , err
7090 }
7191
@@ -91,21 +111,50 @@ func (r ReconcilerImplementation) Post(
91111func (r ReconcilerImplementation ) ensureRole (
92112 ctx context.Context ,
93113 cluster * cnpgv1.Cluster ,
94- barmanObjectName string ,
114+ barmanObject * barmancloudv1. ObjectStore ,
95115) error {
116+ contextLogger := log .FromContext (ctx )
117+ newRole := specs .BuildRole (cluster , barmanObject )
118+
96119 var role rbacv1.Role
97120 if err := r .Client .Get (ctx , client.ObjectKey {
98- Namespace : cluster .Namespace ,
99- Name : getRBACName ( cluster .Name ) ,
121+ Namespace : newRole .Namespace ,
122+ Name : newRole .Name ,
100123 }, & role ); err != nil {
101- if apierrs .IsNotFound (err ) {
102- return r . createRole ( ctx , cluster , barmanObjectName )
124+ if ! apierrs .IsNotFound (err ) {
125+ return err
103126 }
104- return err
127+
128+ contextLogger .Info (
129+ "Creating role" ,
130+ "name" , newRole .Name ,
131+ "namespace" , newRole .Namespace ,
132+ )
133+
134+ if err := ctrl .SetControllerReference (
135+ cluster ,
136+ newRole ,
137+ r .Client .Scheme (),
138+ ); err != nil {
139+ return err
140+ }
141+
142+ return r .Client .Create (ctx , newRole )
105143 }
106144
107- // TODO: patch existing role
108- return nil
145+ if equality .Semantic .DeepEqual (newRole .Rules , role .Rules ) {
146+ // There's no need to hit the API server again
147+ return nil
148+ }
149+
150+ contextLogger .Info (
151+ "Patching role" ,
152+ "name" , newRole .Name ,
153+ "namespace" , newRole .Namespace ,
154+ "rules" , newRole .Rules ,
155+ )
156+
157+ return r .Client .Patch (ctx , newRole , client .MergeFrom (& role ))
109158}
110159
111160func (r ReconcilerImplementation ) ensureRoleBinding (
@@ -115,98 +164,26 @@ func (r ReconcilerImplementation) ensureRoleBinding(
115164 var role rbacv1.RoleBinding
116165 if err := r .Client .Get (ctx , client.ObjectKey {
117166 Namespace : cluster .Namespace ,
118- Name : getRBACName (cluster .Name ),
167+ Name : specs . GetRBACName (cluster .Name ),
119168 }, & role ); err != nil {
120169 if apierrs .IsNotFound (err ) {
121170 return r .createRoleBinding (ctx , cluster )
122171 }
123172 return err
124173 }
125174
126- // TODO: patch existing role binding
175+ // TODO: this assumes role bindings never change.
176+ // Is that true? Should we relax this assumption?
127177 return nil
128178}
129179
130- func (r ReconcilerImplementation ) createRole (
131- ctx context.Context ,
132- cluster * cnpgv1.Cluster ,
133- barmanObjectName string ,
134- ) error {
135- role := buildRole (cluster , barmanObjectName )
136- if err := ctrl .SetControllerReference (cluster , role , r .Client .Scheme ()); err != nil {
137- return err
138- }
139- return r .Client .Create (ctx , role )
140- }
141-
142180func (r ReconcilerImplementation ) createRoleBinding (
143181 ctx context.Context ,
144182 cluster * cnpgv1.Cluster ,
145183) error {
146- roleBinding := buildRoleBinding (cluster )
184+ roleBinding := specs . BuildRoleBinding (cluster )
147185 if err := ctrl .SetControllerReference (cluster , roleBinding , r .Client .Scheme ()); err != nil {
148186 return err
149187 }
150188 return r .Client .Create (ctx , roleBinding )
151189}
152-
153- func buildRole (
154- cluster * cnpgv1.Cluster ,
155- barmanObjectName string ,
156- ) * rbacv1.Role {
157- return & rbacv1.Role {
158- ObjectMeta : metav1.ObjectMeta {
159- Namespace : cluster .Namespace ,
160- Name : getRBACName (cluster .Name ),
161- },
162-
163- Rules : []rbacv1.PolicyRule {
164- {
165- APIGroups : []string {
166- "barmancloud.cnpg.io" ,
167- },
168- Verbs : []string {
169- "get" ,
170- "watch" ,
171- "list" ,
172- },
173- Resources : []string {
174- "objectstores" ,
175- },
176- ResourceNames : []string {
177- barmanObjectName ,
178- },
179- },
180- },
181- }
182- }
183-
184- func buildRoleBinding (
185- cluster * cnpgv1.Cluster ,
186- ) * rbacv1.RoleBinding {
187- return & rbacv1.RoleBinding {
188- ObjectMeta : metav1.ObjectMeta {
189- Namespace : cluster .Namespace ,
190- Name : getRBACName (cluster .Name ),
191- },
192- Subjects : []rbacv1.Subject {
193- {
194- Kind : "ServiceAccount" ,
195- APIGroup : "" ,
196- Name : cluster .Name ,
197- Namespace : cluster .Namespace ,
198- },
199- },
200- RoleRef : rbacv1.RoleRef {
201- APIGroup : "rbac.authorization.k8s.io" ,
202- Kind : "Role" ,
203- Name : getRBACName (cluster .Name ),
204- },
205- }
206- }
207-
208- // getRBACName returns the name of the RBAC entities for the
209- // barman cloud plugin
210- func getRBACName (clusterName string ) string {
211- return fmt .Sprintf ("%s-barman" , clusterName )
212- }
0 commit comments