From aa6713c2d02dbef480b66897c547df1150bba4a7 Mon Sep 17 00:00:00 2001 From: hongming Date: Tue, 11 Aug 2020 23:04:30 +0800 Subject: [PATCH] can't list pipeline if no global role assigned Signed-off-by: hongming --- cmd/controller-manager/app/controllers.go | 10 ++- .../globalrolebinding_controller.go | 27 ++------ pkg/controller/user/user_controller.go | 64 ++++++++++++++----- pkg/controller/user/user_controller_test.go | 3 +- 4 files changed, 62 insertions(+), 42 deletions(-) diff --git a/cmd/controller-manager/app/controllers.go b/cmd/controller-manager/app/controllers.go index 0fe81ef44..49e784d6f 100644 --- a/cmd/controller-manager/app/controllers.go +++ b/cmd/controller-manager/app/controllers.go @@ -202,12 +202,14 @@ func addControllers( go fedWorkspaceRoleBindingCacheController.Run(stopCh) } - userController := user.NewUserController(client.Kubernetes(), client.KubeSphere(), client.Config(), + userController := user.NewUserController(client.Kubernetes(), client.KubeSphere(), + client.Config(), kubesphereInformer.Iam().V1alpha2().Users(), fedUserCache, fedUserCacheController, kubesphereInformer.Iam().V1alpha2().LoginRecords(), kubernetesInformer.Core().V1().ConfigMaps(), - ldapClient, authenticationOptions, multiClusterEnabled) + ldapClient, devopsClient, + authenticationOptions, multiClusterEnabled) loginRecordController := user.NewLoginRecordController( client.Kubernetes(), @@ -235,7 +237,9 @@ func addControllers( kubesphereInformer.Tenant().V1alpha2().WorkspaceTemplates(), multiClusterEnabled) globalRoleBindingController := globalrolebinding.NewController(client.Kubernetes(), client.KubeSphere(), - kubesphereInformer.Iam().V1alpha2().GlobalRoleBindings(), fedGlobalRoleBindingCache, fedGlobalRoleBindingCacheController, multiClusterEnabled, devopsClient) + kubesphereInformer.Iam().V1alpha2().GlobalRoleBindings(), + fedGlobalRoleBindingCache, fedGlobalRoleBindingCacheController, + multiClusterEnabled) workspaceRoleBindingController := workspacerolebinding.NewController(client.Kubernetes(), client.KubeSphere(), kubesphereInformer.Iam().V1alpha2().WorkspaceRoleBindings(), diff --git a/pkg/controller/globalrolebinding/globalrolebinding_controller.go b/pkg/controller/globalrolebinding/globalrolebinding_controller.go index 97abc1e1c..557935c26 100644 --- a/pkg/controller/globalrolebinding/globalrolebinding_controller.go +++ b/pkg/controller/globalrolebinding/globalrolebinding_controller.go @@ -39,7 +39,6 @@ import ( iamv1alpha2informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/iam/v1alpha2" iamv1alpha2listers "kubesphere.io/kubesphere/pkg/client/listers/iam/v1alpha2" "kubesphere.io/kubesphere/pkg/constants" - modeldevops "kubesphere.io/kubesphere/pkg/models/devops" devops "kubesphere.io/kubesphere/pkg/simple/client/devops" "reflect" @@ -58,7 +57,6 @@ const ( type Controller struct { k8sClient kubernetes.Interface ksClient kubesphere.Interface - globalRoleBindingInformer iamv1alpha2informers.GlobalRoleBindingInformer globalRoleBindingLister iamv1alpha2listers.GlobalRoleBindingLister globalRoleBindingSynced cache.InformerSynced fedGlobalRoleBindingCache cache.Store @@ -76,8 +74,10 @@ type Controller struct { devopsClient devops.Interface } -func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface, globalRoleBindingInformer iamv1alpha2informers.GlobalRoleBindingInformer, - fedGlobalRoleBindingCache cache.Store, fedGlobalRoleBindingCacheController cache.Controller, multiClusterEnabled bool, devopsClient devops.Interface) *Controller { +func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface, + globalRoleBindingInformer iamv1alpha2informers.GlobalRoleBindingInformer, + fedGlobalRoleBindingCache cache.Store, fedGlobalRoleBindingCacheController cache.Controller, + multiClusterEnabled bool) *Controller { // Create event broadcaster // Add sample-controller types to the default Kubernetes Scheme so Events can be // logged for sample-controller types. @@ -90,7 +90,6 @@ func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface ctl := &Controller{ k8sClient: k8sClient, ksClient: ksClient, - globalRoleBindingInformer: globalRoleBindingInformer, globalRoleBindingLister: globalRoleBindingInformer.Lister(), globalRoleBindingSynced: globalRoleBindingInformer.Informer().HasSynced, fedGlobalRoleBindingCache: fedGlobalRoleBindingCache, @@ -98,7 +97,6 @@ func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "GlobalRoleBinding"), recorder: recorder, multiClusterEnabled: multiClusterEnabled, - devopsClient: devopsClient, } klog.Info("Setting up event handlers") globalRoleBindingInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ @@ -235,13 +233,6 @@ func (c *Controller) reconcile(key string) error { } } - if c.devopsClient != nil { - if err := c.assignDevOpsAdminRole(globalRoleBinding); err != nil { - klog.Error(err) - return err - } - } - if c.multiClusterEnabled { if err = c.multiClusterSync(globalRoleBinding); err != nil { klog.Error(err) @@ -433,16 +424,6 @@ func (c *Controller) ensureNotControlledByKubefed(globalRoleBinding *iamv1alpha2 return nil } -func (c *Controller) assignDevOpsAdminRole(globalRoleBinding *iamv1alpha2.GlobalRoleBinding) error { - if username := findExpectUsername(globalRoleBinding); username != "" { - if err := c.devopsClient.AssignGlobalRole(modeldevops.JenkinsAdminRoleName, username); err != nil { - klog.Errorf("%+v", err) - return err - } - } - return nil -} - func ensureSubjectAPIVersionIsValid(subjects []rbacv1.Subject) []rbacv1.Subject { validSubjects := make([]rbacv1.Subject, 0) for _, subject := range subjects { diff --git a/pkg/controller/user/user_controller.go b/pkg/controller/user/user_controller.go index 96c5c6b74..8ee3ed7eb 100644 --- a/pkg/controller/user/user_controller.go +++ b/pkg/controller/user/user_controller.go @@ -44,7 +44,9 @@ import ( iamv1alpha2informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/iam/v1alpha2" iamv1alpha2listers "kubesphere.io/kubesphere/pkg/client/listers/iam/v1alpha2" "kubesphere.io/kubesphere/pkg/constants" + modelsdevops "kubesphere.io/kubesphere/pkg/models/devops" "kubesphere.io/kubesphere/pkg/models/kubeconfig" + "kubesphere.io/kubesphere/pkg/simple/client/devops" ldapclient "kubesphere.io/kubesphere/pkg/simple/client/ldap" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "reflect" @@ -65,19 +67,18 @@ const ( ) type Controller struct { - k8sClient kubernetes.Interface - ksClient kubesphere.Interface - kubeconfig kubeconfig.Interface - userInformer iamv1alpha2informers.UserInformer - userLister iamv1alpha2listers.UserLister - userSynced cache.InformerSynced - loginRecordInformer iamv1alpha2informers.LoginRecordInformer - loginRecordLister iamv1alpha2listers.LoginRecordLister - loginRecordSynced cache.InformerSynced - cmSynced cache.InformerSynced - fedUserCache cache.Store - fedUserController cache.Controller - ldapClient ldapclient.Interface + k8sClient kubernetes.Interface + ksClient kubesphere.Interface + kubeconfig kubeconfig.Interface + userLister iamv1alpha2listers.UserLister + userSynced cache.InformerSynced + loginRecordLister iamv1alpha2listers.LoginRecordLister + loginRecordSynced cache.InformerSynced + cmSynced cache.InformerSynced + fedUserCache cache.Store + fedUserController cache.Controller + ldapClient ldapclient.Interface + devopsClient devops.Interface // workqueue is a rate limited work queue. This is used to queue work to be // processed instead of performing it as soon as a change happens. This // means we can ensure we only process a fixed amount of resources at a @@ -97,6 +98,7 @@ func NewUserController(k8sClient kubernetes.Interface, ksClient kubesphere.Inter loginRecordInformer iamv1alpha2informers.LoginRecordInformer, configMapInformer corev1informers.ConfigMapInformer, ldapClient ldapclient.Interface, + devopsClient devops.Interface, authenticationOptions *authoptions.AuthenticationOptions, multiClusterEnabled bool) *Controller { @@ -114,16 +116,15 @@ func NewUserController(k8sClient kubernetes.Interface, ksClient kubesphere.Inter k8sClient: k8sClient, ksClient: ksClient, kubeconfig: kubeconfigOperator, - userInformer: userInformer, userLister: userInformer.Lister(), userSynced: userInformer.Informer().HasSynced, - loginRecordInformer: loginRecordInformer, loginRecordLister: loginRecordInformer.Lister(), loginRecordSynced: loginRecordInformer.Informer().HasSynced, cmSynced: configMapInformer.Informer().HasSynced, fedUserCache: fedUserCache, fedUserController: fedUserController, ldapClient: ldapClient, + devopsClient: devopsClient, workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "Users"), recorder: recorder, multiClusterEnabled: multiClusterEnabled, @@ -295,6 +296,14 @@ func (c *Controller) reconcile(key string) error { return err } + if c.devopsClient != nil { + // unassign jenkins role, unassign multiple times is allowed + if err := c.unassignDevOpsAdminRole(user); err != nil { + klog.Error(err) + return err + } + } + if err = c.deleteLoginRecords(user); err != nil { klog.Error(err) return err @@ -337,6 +346,15 @@ func (c *Controller) reconcile(key string) error { } } + if c.devopsClient != nil { + // assign jenkins role after user create, assign multiple times is allowed + // used as logged-in users can do anything + if err := c.assignDevOpsAdminRole(user); err != nil { + klog.Error(err) + return err + } + } + // synchronization through kubefed-controller when multi cluster is enabled if c.multiClusterEnabled { if err = c.multiClusterSync(user); err != nil { @@ -499,6 +517,22 @@ func (c *Controller) updateFederatedUser(fedUser *iamv1alpha2.FederatedUser) err return nil } +func (c *Controller) assignDevOpsAdminRole(user *iamv1alpha2.User) error { + if err := c.devopsClient.AssignGlobalRole(modelsdevops.JenkinsAdminRoleName, user.Name); err != nil { + klog.Errorf("%+v", err) + return err + } + return nil +} + +func (c *Controller) unassignDevOpsAdminRole(user *iamv1alpha2.User) error { + if err := c.devopsClient.UnAssignGlobalRole(modelsdevops.JenkinsAdminRoleName, user.Name); err != nil { + klog.Errorf("%+v", err) + return err + } + return nil +} + func (c *Controller) ldapSync(user *iamv1alpha2.User) error { encrypted, _ := strconv.ParseBool(user.Annotations[iamv1alpha2.PasswordEncryptedAnnotation]) if encrypted { diff --git a/pkg/controller/user/user_controller_test.go b/pkg/controller/user/user_controller_test.go index cd947ae07..cb42a093e 100644 --- a/pkg/controller/user/user_controller_test.go +++ b/pkg/controller/user/user_controller_test.go @@ -100,7 +100,8 @@ func (f *fixture) newController() (*Controller, ksinformers.SharedInformerFactor nil, nil, ksinformers.Iam().V1alpha2().LoginRecords(), k8sinformers.Core().V1().ConfigMaps(), - ldapClient, options.NewAuthenticateOptions(), false) + ldapClient, nil, + options.NewAuthenticateOptions(), false) c.userSynced = alwaysReady c.recorder = &record.FakeRecorder{}