From 942d3be9d4d2dd95a9e35bfcbdeb16049d032e7c Mon Sep 17 00:00:00 2001 From: smartcat999 <49057502+smartcat999@users.noreply.github.com> Date: Thu, 26 Dec 2024 13:48:08 +0800 Subject: [PATCH] Fix workspacerole sync condition (#2142) * fix: Fixed the issue that role and rolebinding do not trigger synchronization when binding a workspace to a cluster Signed-off-by: peng wu <2030047311@qq.com> * fix: update goimports Signed-off-by: peng wu <2030047311@qq.com> * fix: update workspace sync condition && update list options Signed-off-by: peng wu <2030047311@qq.com> * fix: rename enqueue request map func for workspacerole and workspacerolebinding Signed-off-by: peng wu <2030047311@qq.com> * fix: workspace role sync logic Signed-off-by: peng wu <2030047311@qq.com> --------- Signed-off-by: peng wu <2030047311@qq.com> Signed-off-by: hongming (cherry picked from commit bc128dcf784206ed74517324e78282531ce3117f) --- .../workspacerole/workspacerole_controller.go | 32 +++++++++-- .../workspacerolebinding_controller.go | 55 +++++++++++++++++-- .../workspacetemplate/predicate/predicate.go | 46 ++++++++++++++++ 3 files changed, 122 insertions(+), 11 deletions(-) create mode 100644 pkg/controller/workspacetemplate/predicate/predicate.go diff --git a/pkg/controller/workspacerole/workspacerole_controller.go b/pkg/controller/workspacerole/workspacerole_controller.go index 0b364694d..15fc549e0 100644 --- a/pkg/controller/workspacerole/workspacerole_controller.go +++ b/pkg/controller/workspacerole/workspacerole_controller.go @@ -8,7 +8,6 @@ package workspacerole import ( "context" "fmt" - "strings" "github.com/go-logr/logr" @@ -19,9 +18,6 @@ import ( "k8s.io/client-go/tools/record" "k8s.io/client-go/util/retry" "k8s.io/klog/v2" - clusterv1alpha1 "kubesphere.io/api/cluster/v1alpha1" - iamv1beta1 "kubesphere.io/api/iam/v1beta1" - tenantv1beta1 "kubesphere.io/api/tenant/v1beta1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" @@ -30,11 +26,16 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" + clusterv1alpha1 "kubesphere.io/api/cluster/v1alpha1" + iamv1beta1 "kubesphere.io/api/iam/v1beta1" + tenantv1beta1 "kubesphere.io/api/tenant/v1beta1" + rbachelper "kubesphere.io/kubesphere/pkg/componenthelper/auth/rbac" "kubesphere.io/kubesphere/pkg/constants" kscontroller "kubesphere.io/kubesphere/pkg/controller" "kubesphere.io/kubesphere/pkg/controller/cluster/predicate" clusterutils "kubesphere.io/kubesphere/pkg/controller/cluster/utils" + workspacetemplatepredicate "kubesphere.io/kubesphere/pkg/controller/workspacetemplate/predicate" "kubesphere.io/kubesphere/pkg/controller/workspacetemplate/utils" "kubesphere.io/kubesphere/pkg/utils/clusterclient" "kubesphere.io/kubesphere/pkg/utils/k8sutil" @@ -77,13 +78,16 @@ func (r *Reconciler) SetupWithManager(mgr *kscontroller.Manager) error { For(&iamv1beta1.WorkspaceRole{}). Watches( &clusterv1alpha1.Cluster{}, - handler.EnqueueRequestsFromMapFunc(r.mapper), + handler.EnqueueRequestsFromMapFunc(r.clusterSync), builder.WithPredicates(predicate.ClusterStatusChangedPredicate{}), ). + Watches(&tenantv1beta1.WorkspaceTemplate{}, + handler.EnqueueRequestsFromMapFunc(r.workspaceSync), + builder.WithPredicates(workspacetemplatepredicate.WorkspaceStatusChangedPredicate{})). Complete(r) } -func (r *Reconciler) mapper(ctx context.Context, o client.Object) []reconcile.Request { +func (r *Reconciler) clusterSync(ctx context.Context, o client.Object) []reconcile.Request { cluster := o.(*clusterv1alpha1.Cluster) if !clusterutils.IsClusterReady(cluster) { return []reconcile.Request{} @@ -108,6 +112,22 @@ func (r *Reconciler) mapper(ctx context.Context, o client.Object) []reconcile.Re return result } +func (r *Reconciler) workspaceSync(ctx context.Context, object client.Object) []reconcile.Request { + workspaceTemplate := object.(*tenantv1beta1.WorkspaceTemplate) + workspaceRoles := &iamv1beta1.WorkspaceRoleList{} + if err := r.List(ctx, workspaceRoles, client.MatchingLabels{ + tenantv1beta1.WorkspaceLabel: workspaceTemplate.Name, + }); err != nil { + r.logger.Error(err, "failed to list workspace roles") + return []reconcile.Request{} + } + var result []reconcile.Request + for _, workspaceRole := range workspaceRoles.Items { + result = append(result, reconcile.Request{NamespacedName: types.NamespacedName{Name: workspaceRole.Name}}) + } + return result +} + // +kubebuilder:rbac:groups=iam.kubesphere.io,resources=workspaceroles,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=tenant.kubesphere.io,resources=workspaces,verbs=get;list;watch; diff --git a/pkg/controller/workspacerolebinding/workspacerolebinding_controller.go b/pkg/controller/workspacerolebinding/workspacerolebinding_controller.go index 4a83ee360..54d618e7d 100644 --- a/pkg/controller/workspacerolebinding/workspacerolebinding_controller.go +++ b/pkg/controller/workspacerolebinding/workspacerolebinding_controller.go @@ -12,8 +12,6 @@ import ( "sort" "strings" - kscontroller "kubesphere.io/kubesphere/pkg/controller" - "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" v1 "k8s.io/api/rbac/v1" @@ -24,18 +22,24 @@ import ( toolscache "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" "k8s.io/klog/v2" - clusterv1alpha1 "kubesphere.io/api/cluster/v1alpha1" - iamv1beta1 "kubesphere.io/api/iam/v1beta1" - tenantv1beta1 "kubesphere.io/api/tenant/v1beta1" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" + clusterv1alpha1 "kubesphere.io/api/cluster/v1alpha1" + iamv1beta1 "kubesphere.io/api/iam/v1beta1" + tenantv1beta1 "kubesphere.io/api/tenant/v1beta1" + "kubesphere.io/kubesphere/pkg/constants" + kscontroller "kubesphere.io/kubesphere/pkg/controller" + "kubesphere.io/kubesphere/pkg/controller/cluster/predicate" clusterutils "kubesphere.io/kubesphere/pkg/controller/cluster/utils" + workspacetemplatepredicate "kubesphere.io/kubesphere/pkg/controller/workspacetemplate/predicate" "kubesphere.io/kubesphere/pkg/controller/workspacetemplate/utils" "kubesphere.io/kubesphere/pkg/utils/clusterclient" "kubesphere.io/kubesphere/pkg/utils/k8sutil" @@ -117,9 +121,50 @@ func (r *Reconciler) SetupWithManager(mgr *kscontroller.Manager) error { Named(controllerName). WithOptions(controller.Options{MaxConcurrentReconciles: 2}). For(&iamv1beta1.WorkspaceRoleBinding{}). + Watches( + &clusterv1alpha1.Cluster{}, + handler.EnqueueRequestsFromMapFunc(r.clusterSync), + builder.WithPredicates(predicate.ClusterStatusChangedPredicate{}), + ). + Watches(&tenantv1beta1.WorkspaceTemplate{}, + handler.EnqueueRequestsFromMapFunc(r.workspaceSync), + builder.WithPredicates(workspacetemplatepredicate.WorkspaceStatusChangedPredicate{})). Complete(r) } +func (r *Reconciler) clusterSync(ctx context.Context, object client.Object) []reconcile.Request { + cluster := object.(*clusterv1alpha1.Cluster) + if !clusterutils.IsClusterReady(cluster) { + return []reconcile.Request{} + } + workspaceRoleBindings := &iamv1beta1.WorkspaceRoleBindingList{} + if err := r.List(ctx, workspaceRoleBindings); err != nil { + r.logger.Error(err, "failed to list workspace roles") + return []reconcile.Request{} + } + var result []reconcile.Request + for _, workspaceRoleBinding := range workspaceRoleBindings.Items { + result = append(result, reconcile.Request{NamespacedName: types.NamespacedName{Name: workspaceRoleBinding.Name}}) + } + return result +} + +func (r *Reconciler) workspaceSync(ctx context.Context, object client.Object) []reconcile.Request { + workspaceTemplate := object.(*tenantv1beta1.WorkspaceTemplate) + workspaceRoleBindings := &iamv1beta1.WorkspaceRoleBindingList{} + if err := r.List(ctx, workspaceRoleBindings, client.MatchingLabels{ + tenantv1beta1.WorkspaceLabel: workspaceTemplate.Name, + }); err != nil { + r.logger.Error(err, "failed to list workspace roles") + return []reconcile.Request{} + } + var result []reconcile.Request + for _, workspaceRoleBinding := range workspaceRoleBindings.Items { + result = append(result, reconcile.Request{NamespacedName: types.NamespacedName{Name: workspaceRoleBinding.Name}}) + } + return result +} + // +kubebuilder:rbac:groups=iam.kubesphere.io,resources=workspacerolebindings,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=types.kubefed.io,resources=federatedworkspacerolebindings,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=tenant.kubesphere.io,resources=workspaces,verbs=get;list;watch; diff --git a/pkg/controller/workspacetemplate/predicate/predicate.go b/pkg/controller/workspacetemplate/predicate/predicate.go new file mode 100644 index 000000000..87bbe6266 --- /dev/null +++ b/pkg/controller/workspacetemplate/predicate/predicate.go @@ -0,0 +1,46 @@ +/* + * Please refer to the LICENSE file in the root directory of the project. + * https://github.com/kubesphere/kubesphere/blob/master/LICENSE + */ + +package predicate + +import ( + "reflect" + + "sigs.k8s.io/controller-runtime/pkg/event" + "sigs.k8s.io/controller-runtime/pkg/predicate" + + tenantv1alpha1 "kubesphere.io/api/tenant/v1beta1" +) + +type WorkspaceStatusChangedPredicate struct { + predicate.Funcs +} + +func (WorkspaceStatusChangedPredicate) Update(e event.UpdateEvent) bool { + oldWorkspaceTemplate, ok := e.ObjectOld.(*tenantv1alpha1.WorkspaceTemplate) + if !ok { + return false + } + newWorkspaceTemplate, ok := e.ObjectNew.(*tenantv1alpha1.WorkspaceTemplate) + if !ok { + return false + } + if !reflect.DeepEqual(oldWorkspaceTemplate.Spec, newWorkspaceTemplate.Spec) { + return true + } + return false +} + +func (WorkspaceStatusChangedPredicate) Create(_ event.CreateEvent) bool { + return false +} + +func (WorkspaceStatusChangedPredicate) Delete(_ event.DeleteEvent) bool { + return false +} + +func (WorkspaceStatusChangedPredicate) Generic(_ event.GenericEvent) bool { + return false +}