forked from kubermatic/kubermatic
/
reconciler.go
109 lines (92 loc) · 3.61 KB
/
reconciler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*
Copyright 2020 The Kubermatic Kubernetes Platform contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package rbacusercluster
import (
"context"
"fmt"
controllerclient "sigs.k8s.io/controller-runtime/pkg/client"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/klog"
)
// reconciler creates and updates ClusterRoles and ClusterRoleBinding to achieve the desired state
type reconciler struct {
ctx context.Context
client controllerclient.Client
}
// Reconcile creates and updates ClusterRoles and ClusterRoleBinding to achieve the desired state
func (r *reconciler) Reconcile(resourceName string) error {
klog.V(4).Infof("Reconciling RBAC for %s", resourceName)
err := r.ensureRBACClusterRole(resourceName)
if err != nil {
return err
}
err = r.ensureRBACClusterRoleBinding(resourceName)
if err != nil {
return err
}
return nil
}
func (r *reconciler) ensureRBACClusterRole(resourceName string) error {
defaultClusterRole, err := GenerateRBACClusterRole(resourceName)
if err != nil {
return fmt.Errorf("failed to generate the RBAC Cluster Role: %v", err)
}
clusterRole := &rbacv1.ClusterRole{}
err = r.client.Get(r.ctx, controllerclient.ObjectKey{Namespace: metav1.NamespaceAll, Name: resourceName}, clusterRole)
if err != nil {
// create Cluster Role if not exist
if errors.IsNotFound(err) {
if err := r.client.Create(r.ctx, defaultClusterRole); err != nil {
return fmt.Errorf("failed to create the RBAC Cluster Role: %v", err)
}
klog.V(2).Infof("Created a new ClusterRole %s", defaultClusterRole.Name)
return nil
}
return err
}
// compare Cluster Role with default. If don't match update for default
if !ClusterRoleMatches(clusterRole, defaultClusterRole) {
if err := r.client.Update(r.ctx, defaultClusterRole); err != nil {
return fmt.Errorf("failed to update the RBAC Cluster Role: %v", err)
}
klog.V(2).Infof("Updated the ClusterCole %s", defaultClusterRole.Name)
}
return nil
}
func (r *reconciler) ensureRBACClusterRoleBinding(resourceName string) error {
defaultClusterBinding, err := GenerateRBACClusterRoleBinding(resourceName)
if err != nil {
return fmt.Errorf("failed to generate the RBAC Cluster Role Binding: %v", err)
}
clusterRoleBinding := &rbacv1.ClusterRoleBinding{}
if err := r.client.Get(r.ctx, controllerclient.ObjectKey{Namespace: metav1.NamespaceAll, Name: resourceName}, clusterRoleBinding); err != nil {
if errors.IsNotFound(err) {
if err := r.client.Create(r.ctx, defaultClusterBinding); err != nil {
return fmt.Errorf("failed to create the RBAC ClusterRoleBinding: %v", err)
}
klog.V(2).Infof("Created a new ClusterRoleBinding %s", defaultClusterBinding.Name)
return nil
}
return err
}
// compare cluster role bindings with default. If don't match update for default
if !ClusterRoleBindingMatches(clusterRoleBinding, defaultClusterBinding) {
if err := r.client.Update(r.ctx, defaultClusterBinding); err != nil {
return fmt.Errorf("failed to update the RBAC ClusterRoleBinding: %v", err)
}
klog.V(2).Infof("Updated the ClusterColeBinding %s", defaultClusterBinding.Name)
}
return nil
}