@@ -160,7 +160,6 @@ func addControllers(
|
|||||||
fedWorkspaceCacheController, fedWorkspaceRoleCacheController, fedWorkspaceRoleBindingCacheController cache.Controller
|
fedWorkspaceCacheController, fedWorkspaceRoleCacheController, fedWorkspaceRoleBindingCacheController cache.Controller
|
||||||
|
|
||||||
if multiClusterEnabled {
|
if multiClusterEnabled {
|
||||||
|
|
||||||
fedUserClient, err := util.NewResourceClient(client.Config(), &iamv1alpha2.FedUserResource)
|
fedUserClient, err := util.NewResourceClient(client.Config(), &iamv1alpha2.FedUserResource)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
@@ -208,31 +207,42 @@ func addControllers(
|
|||||||
}
|
}
|
||||||
|
|
||||||
userController := user.NewController(client.Kubernetes(), client.KubeSphere(), client.Config(),
|
userController := user.NewController(client.Kubernetes(), client.KubeSphere(), client.Config(),
|
||||||
kubesphereInformer.Iam().V1alpha2().Users(), fedUserCache, fedUserCacheController,
|
kubesphereInformer.Iam().V1alpha2().Users(),
|
||||||
|
fedUserCache, fedUserCacheController,
|
||||||
kubernetesInformer.Core().V1().ConfigMaps(), ldapClient, multiClusterEnabled)
|
kubernetesInformer.Core().V1().ConfigMaps(), ldapClient, multiClusterEnabled)
|
||||||
|
|
||||||
csrController := certificatesigningrequest.NewController(client.Kubernetes(), kubernetesInformer.Certificates().V1beta1().CertificateSigningRequests(),
|
csrController := certificatesigningrequest.NewController(client.Kubernetes(),
|
||||||
|
kubernetesInformer.Certificates().V1beta1().CertificateSigningRequests(),
|
||||||
kubernetesInformer.Core().V1().ConfigMaps(), client.Config())
|
kubernetesInformer.Core().V1().ConfigMaps(), client.Config())
|
||||||
|
|
||||||
clusterRoleBindingController := clusterrolebinding.NewController(client.Kubernetes(),
|
clusterRoleBindingController := clusterrolebinding.NewController(client.Kubernetes(),
|
||||||
kubernetesInformer.Rbac().V1().ClusterRoleBindings(), kubernetesInformer.Apps().V1().Deployments(),
|
kubernetesInformer.Rbac().V1().ClusterRoleBindings(),
|
||||||
kubernetesInformer.Core().V1().Pods(), kubesphereInformer.Iam().V1alpha2().Users())
|
kubernetesInformer.Apps().V1().Deployments(),
|
||||||
|
kubernetesInformer.Core().V1().Pods(),
|
||||||
|
kubesphereInformer.Iam().V1alpha2().Users())
|
||||||
|
|
||||||
globalRoleController := globalrole.NewController(client.Kubernetes(), client.KubeSphere(),
|
globalRoleController := globalrole.NewController(client.Kubernetes(), client.KubeSphere(),
|
||||||
kubesphereInformer.Iam().V1alpha2().GlobalRoles(), fedGlobalRoleCache, fedGlobalRoleCacheController)
|
kubesphereInformer.Iam().V1alpha2().GlobalRoles(), fedGlobalRoleCache, fedGlobalRoleCacheController)
|
||||||
|
|
||||||
workspaceRoleController := workspacerole.NewController(client.Kubernetes(), client.KubeSphere(),
|
workspaceRoleController := workspacerole.NewController(client.Kubernetes(), client.KubeSphere(),
|
||||||
kubesphereInformer.Iam().V1alpha2().WorkspaceRoles(), fedWorkspaceRoleCache, fedWorkspaceRoleCacheController)
|
kubesphereInformer.Iam().V1alpha2().WorkspaceRoles(),
|
||||||
|
fedWorkspaceRoleCache, fedWorkspaceRoleCacheController,
|
||||||
|
kubesphereInformer.Tenant().V1alpha2().WorkspaceTemplates(), multiClusterEnabled)
|
||||||
|
|
||||||
globalRoleBindingController := globalrolebinding.NewController(client.Kubernetes(), client.KubeSphere(),
|
globalRoleBindingController := globalrolebinding.NewController(client.Kubernetes(), client.KubeSphere(),
|
||||||
kubesphereInformer.Iam().V1alpha2().GlobalRoleBindings(), fedGlobalRoleBindingCache, fedGlobalRoleBindingCacheController, multiClusterEnabled)
|
kubesphereInformer.Iam().V1alpha2().GlobalRoleBindings(),
|
||||||
|
fedGlobalRoleBindingCache, fedGlobalRoleBindingCacheController, multiClusterEnabled)
|
||||||
|
|
||||||
workspaceRoleBindingController := workspacerolebinding.NewController(client.Kubernetes(), client.KubeSphere(),
|
workspaceRoleBindingController := workspacerolebinding.NewController(client.Kubernetes(), client.KubeSphere(),
|
||||||
kubesphereInformer.Iam().V1alpha2().WorkspaceRoleBindings(), fedWorkspaceRoleBindingCache, fedWorkspaceRoleBindingCacheController)
|
kubesphereInformer.Iam().V1alpha2().WorkspaceRoleBindings(),
|
||||||
|
fedWorkspaceRoleBindingCache, fedWorkspaceRoleBindingCacheController,
|
||||||
|
kubesphereInformer.Tenant().V1alpha2().WorkspaceTemplates(), multiClusterEnabled)
|
||||||
|
|
||||||
workspaceTemplateController := workspacetemplate.NewController(client.Kubernetes(), client.KubeSphere(),
|
workspaceTemplateController := workspacetemplate.NewController(client.Kubernetes(), client.KubeSphere(),
|
||||||
kubesphereInformer.Tenant().V1alpha2().WorkspaceTemplates(), kubesphereInformer.Tenant().V1alpha1().Workspaces(),
|
kubesphereInformer.Tenant().V1alpha2().WorkspaceTemplates(),
|
||||||
kubesphereInformer.Iam().V1alpha2().RoleBases(), kubesphereInformer.Iam().V1alpha2().WorkspaceRoles(),
|
kubesphereInformer.Tenant().V1alpha1().Workspaces(),
|
||||||
|
kubesphereInformer.Iam().V1alpha2().RoleBases(),
|
||||||
|
kubesphereInformer.Iam().V1alpha2().WorkspaceRoles(),
|
||||||
fedWorkspaceCache, fedWorkspaceCacheController, multiClusterEnabled)
|
fedWorkspaceCache, fedWorkspaceCacheController, multiClusterEnabled)
|
||||||
|
|
||||||
var clusterController manager.Runnable
|
var clusterController manager.Runnable
|
||||||
@@ -253,8 +263,10 @@ func addControllers(
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsnpController = nsnetworkpolicy.NewNSNetworkPolicyController(client.Kubernetes(),
|
nsnpController = nsnetworkpolicy.NewNSNetworkPolicyController(client.Kubernetes(),
|
||||||
client.KubeSphere().NetworkV1alpha1(), kubesphereInformer.Network().V1alpha1().NamespaceNetworkPolicies(),
|
client.KubeSphere().NetworkV1alpha1(),
|
||||||
kubernetesInformer.Core().V1().Services(), kubernetesInformer.Core().V1().Nodes(),
|
kubesphereInformer.Network().V1alpha1().NamespaceNetworkPolicies(),
|
||||||
|
kubernetesInformer.Core().V1().Services(),
|
||||||
|
kubernetesInformer.Core().V1().Nodes(),
|
||||||
kubesphereInformer.Tenant().V1alpha1().Workspaces(),
|
kubesphereInformer.Tenant().V1alpha1().Workspaces(),
|
||||||
kubernetesInformer.Core().V1().Namespaces(), nsnpProvider)
|
kubernetesInformer.Core().V1().Namespaces(), nsnpProvider)
|
||||||
}
|
}
|
||||||
@@ -275,6 +287,8 @@ func addControllers(
|
|||||||
"clusterrolebinding-controller": clusterRoleBindingController,
|
"clusterrolebinding-controller": clusterRoleBindingController,
|
||||||
"globalrolebinding-controller": globalRoleBindingController,
|
"globalrolebinding-controller": globalRoleBindingController,
|
||||||
"workspacetemplate-controller": workspaceTemplateController,
|
"workspacetemplate-controller": workspaceTemplateController,
|
||||||
|
"workspacerole-controller": workspaceRoleController,
|
||||||
|
"workspacerolebinding-controller": workspaceRoleBindingController,
|
||||||
}
|
}
|
||||||
|
|
||||||
if devopsClient != nil {
|
if devopsClient != nil {
|
||||||
@@ -285,8 +299,6 @@ func addControllers(
|
|||||||
|
|
||||||
if multiClusterEnabled {
|
if multiClusterEnabled {
|
||||||
controllers["globalrole-controller"] = globalRoleController
|
controllers["globalrole-controller"] = globalRoleController
|
||||||
controllers["workspacerole-controller"] = workspaceRoleController
|
|
||||||
controllers["workspacerolebinding-controller"] = workspaceRoleBindingController
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, ctrl := range controllers {
|
for name, ctrl := range controllers {
|
||||||
|
|||||||
@@ -97,11 +97,11 @@ func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface
|
|||||||
}
|
}
|
||||||
klog.Info("Setting up event handlers")
|
klog.Info("Setting up event handlers")
|
||||||
globalRoleBindingInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
globalRoleBindingInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||||
AddFunc: ctl.enqueueClusterRoleBinding,
|
AddFunc: ctl.enqueueGlobalRoleBinding,
|
||||||
UpdateFunc: func(old, new interface{}) {
|
UpdateFunc: func(old, new interface{}) {
|
||||||
ctl.enqueueClusterRoleBinding(new)
|
ctl.enqueueGlobalRoleBinding(new)
|
||||||
},
|
},
|
||||||
DeleteFunc: ctl.enqueueClusterRoleBinding,
|
DeleteFunc: ctl.enqueueGlobalRoleBinding,
|
||||||
})
|
})
|
||||||
return ctl
|
return ctl
|
||||||
}
|
}
|
||||||
@@ -138,7 +138,7 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) enqueueClusterRoleBinding(obj interface{}) {
|
func (c *Controller) enqueueGlobalRoleBinding(obj interface{}) {
|
||||||
var key string
|
var key string
|
||||||
var err error
|
var err error
|
||||||
if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil {
|
if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil {
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ func (r *ReconcileNamespace) bindWorkspace(namespace *corev1.Namespace) error {
|
|||||||
|
|
||||||
// federated namespace not controlled by workspace
|
// federated namespace not controlled by workspace
|
||||||
if namespace.Labels[constants.KubefedManagedLabel] != "true" && !metav1.IsControlledBy(namespace, workspace) {
|
if namespace.Labels[constants.KubefedManagedLabel] != "true" && !metav1.IsControlledBy(namespace, workspace) {
|
||||||
namespace.OwnerReferences = removeWorkspaceOwnerReferences(namespace.OwnerReferences)
|
namespace.OwnerReferences = nil
|
||||||
if err := controllerutil.SetControllerReference(workspace, namespace, r.scheme); err != nil {
|
if err := controllerutil.SetControllerReference(workspace, namespace, r.scheme); err != nil {
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
return err
|
return err
|
||||||
@@ -204,17 +204,6 @@ func (r *ReconcileNamespace) bindWorkspace(namespace *corev1.Namespace) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeWorkspaceOwnerReferences(ownerReferences []metav1.OwnerReference) []metav1.OwnerReference {
|
|
||||||
for i := 0; i < len(ownerReferences); i++ {
|
|
||||||
owner := ownerReferences[i]
|
|
||||||
if owner.Kind == tenantv1alpha1.ResourceKindWorkspace {
|
|
||||||
ownerReferences = append(ownerReferences[:i], ownerReferences[i+1:]...)
|
|
||||||
i--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ownerReferences
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ReconcileNamespace) deleteRouter(namespace string) error {
|
func (r *ReconcileNamespace) deleteRouter(namespace string) error {
|
||||||
routerName := constants.IngressControllerPrefix + namespace
|
routerName := constants.IngressControllerPrefix + namespace
|
||||||
|
|
||||||
@@ -296,11 +285,40 @@ func (r *ReconcileNamespace) initRoles(namespace *corev1.Namespace) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *ReconcileNamespace) resetNamespaceOwner(namespace *corev1.Namespace) error {
|
||||||
|
namespace = namespace.DeepCopy()
|
||||||
|
delete(namespace.Annotations, constants.CreatorAnnotationKey)
|
||||||
|
err := r.Update(context.Background(), namespace)
|
||||||
|
klog.V(4).Infof("update namespace after creator has been deleted")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (r *ReconcileNamespace) initCreatorRoleBinding(namespace *corev1.Namespace) error {
|
func (r *ReconcileNamespace) initCreatorRoleBinding(namespace *corev1.Namespace) error {
|
||||||
if creator := namespace.Annotations[constants.CreatorAnnotationKey]; creator != "" {
|
creator := namespace.Annotations[constants.CreatorAnnotationKey]
|
||||||
|
if creator == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var user iamv1alpha2.User
|
||||||
|
err := r.Get(context.Background(), types.NamespacedName{Name: creator}, &user)
|
||||||
|
if err != nil {
|
||||||
|
// skip if user has been deleted
|
||||||
|
if errors.IsNotFound(err) {
|
||||||
|
return r.resetNamespaceOwner(namespace)
|
||||||
|
}
|
||||||
|
klog.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip if user has been deleted
|
||||||
|
if !user.DeletionTimestamp.IsZero() {
|
||||||
|
return r.resetNamespaceOwner(namespace)
|
||||||
|
}
|
||||||
|
|
||||||
creatorRoleBinding := &rbacv1.RoleBinding{
|
creatorRoleBinding := &rbacv1.RoleBinding{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: fmt.Sprintf("%s-%s", creator, iamv1alpha2.NamespaceAdmin),
|
Name: fmt.Sprintf("%s-%s", creator, iamv1alpha2.NamespaceAdmin),
|
||||||
|
Labels: map[string]string{iamv1alpha2.UserReferenceLabel: creator},
|
||||||
Namespace: namespace.Name,
|
Namespace: namespace.Name,
|
||||||
},
|
},
|
||||||
RoleRef: rbacv1.RoleRef{
|
RoleRef: rbacv1.RoleRef{
|
||||||
@@ -316,7 +334,7 @@ func (r *ReconcileNamespace) initCreatorRoleBinding(namespace *corev1.Namespace)
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := r.Client.Create(context.Background(), creatorRoleBinding)
|
err = r.Client.Create(context.Background(), creatorRoleBinding)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.IsAlreadyExists(err) {
|
if errors.IsAlreadyExists(err) {
|
||||||
return nil
|
return nil
|
||||||
@@ -324,7 +342,6 @@ func (r *ReconcileNamespace) initCreatorRoleBinding(namespace *corev1.Namespace)
|
|||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
@@ -39,8 +40,8 @@ import (
|
|||||||
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
||||||
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||||
kubespherescheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme"
|
kubespherescheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme"
|
||||||
userinformer "kubesphere.io/kubesphere/pkg/client/informers/externalversions/iam/v1alpha2"
|
iamv1alpha2informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/iam/v1alpha2"
|
||||||
userlister "kubesphere.io/kubesphere/pkg/client/listers/iam/v1alpha2"
|
iamv1alpha2listers "kubesphere.io/kubesphere/pkg/client/listers/iam/v1alpha2"
|
||||||
"kubesphere.io/kubesphere/pkg/constants"
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
"kubesphere.io/kubesphere/pkg/models/kubeconfig"
|
"kubesphere.io/kubesphere/pkg/models/kubeconfig"
|
||||||
ldapclient "kubesphere.io/kubesphere/pkg/simple/client/ldap"
|
ldapclient "kubesphere.io/kubesphere/pkg/simple/client/ldap"
|
||||||
@@ -63,8 +64,8 @@ type Controller struct {
|
|||||||
k8sClient kubernetes.Interface
|
k8sClient kubernetes.Interface
|
||||||
ksClient kubesphere.Interface
|
ksClient kubesphere.Interface
|
||||||
kubeconfig kubeconfig.Interface
|
kubeconfig kubeconfig.Interface
|
||||||
userInformer userinformer.UserInformer
|
userInformer iamv1alpha2informers.UserInformer
|
||||||
userLister userlister.UserLister
|
userLister iamv1alpha2listers.UserLister
|
||||||
userSynced cache.InformerSynced
|
userSynced cache.InformerSynced
|
||||||
cmSynced cache.InformerSynced
|
cmSynced cache.InformerSynced
|
||||||
fedUserCache cache.Store
|
fedUserCache cache.Store
|
||||||
@@ -83,8 +84,10 @@ type Controller struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface,
|
func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface,
|
||||||
config *rest.Config, userInformer userinformer.UserInformer, fedUserCache cache.Store, fedUserController cache.Controller,
|
config *rest.Config, userInformer iamv1alpha2informers.UserInformer,
|
||||||
configMapInformer corev1informers.ConfigMapInformer, ldapClient ldapclient.Interface, multiClusterEnabled bool) *Controller {
|
fedUserCache cache.Store, fedUserController cache.Controller,
|
||||||
|
configMapInformer corev1informers.ConfigMapInformer,
|
||||||
|
ldapClient ldapclient.Interface, multiClusterEnabled bool) *Controller {
|
||||||
// Create event broadcaster
|
// Create event broadcaster
|
||||||
// Add sample-controller types to the default Kubernetes Scheme so Events can be
|
// Add sample-controller types to the default Kubernetes Scheme so Events can be
|
||||||
// logged for sample-controller types.
|
// logged for sample-controller types.
|
||||||
@@ -266,6 +269,11 @@ func (c *Controller) reconcile(key string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = c.deleteRoleBindings(user); err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// remove our finalizer from the list and update it.
|
// remove our finalizer from the list and update it.
|
||||||
user.Finalizers = sliceutil.RemoveString(user.ObjectMeta.Finalizers, func(item string) bool {
|
user.Finalizers = sliceutil.RemoveString(user.ObjectMeta.Finalizers, func(item string) bool {
|
||||||
return item == finalizer
|
return item == finalizer
|
||||||
@@ -483,6 +491,46 @@ func (c *Controller) ldapSync(user *iamv1alpha2.User) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Controller) deleteRoleBindings(user *iamv1alpha2.User) error {
|
||||||
|
listOptions := metav1.ListOptions{
|
||||||
|
LabelSelector: labels.SelectorFromSet(labels.Set{iamv1alpha2.UserReferenceLabel: user.Name}).String(),
|
||||||
|
}
|
||||||
|
deleteOptions := metav1.NewDeleteOptions(0)
|
||||||
|
|
||||||
|
if err := c.ksClient.IamV1alpha2().GlobalRoleBindings().
|
||||||
|
DeleteCollection(deleteOptions, listOptions); err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.ksClient.IamV1alpha2().WorkspaceRoleBindings().
|
||||||
|
DeleteCollection(deleteOptions, listOptions); err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.k8sClient.RbacV1().ClusterRoleBindings().
|
||||||
|
DeleteCollection(deleteOptions, listOptions); err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if result, err := c.k8sClient.CoreV1().Namespaces().List(metav1.ListOptions{}); err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
for _, namespace := range result.Items {
|
||||||
|
if err := c.k8sClient.RbacV1().RoleBindings(namespace.Name).
|
||||||
|
DeleteCollection(deleteOptions, listOptions); err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func encrypt(password string) (string, error) {
|
func encrypt(password string) (string, error) {
|
||||||
// when user is already mapped to another identity, password is empty by default
|
// when user is already mapped to another identity, password is empty by default
|
||||||
// unable to log in directly until password reset
|
// unable to log in directly until password reset
|
||||||
|
|||||||
@@ -94,7 +94,11 @@ func (f *fixture) newController() (*Controller, ksinformers.SharedInformerFactor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c := NewController(f.k8sclient, f.ksclient, nil, ksinformers.Iam().V1alpha2().Users(), nil, nil, k8sinformers.Core().V1().ConfigMaps(), ldapClient, false)
|
c := NewController(f.k8sclient, f.ksclient, nil,
|
||||||
|
ksinformers.Iam().V1alpha2().Users(),
|
||||||
|
nil, nil,
|
||||||
|
k8sinformers.Core().V1().ConfigMaps(),
|
||||||
|
ldapClient, false)
|
||||||
c.userSynced = alwaysReady
|
c.userSynced = alwaysReady
|
||||||
c.recorder = &record.FakeRecorder{}
|
c.recorder = &record.FakeRecorder{}
|
||||||
|
|
||||||
@@ -209,9 +213,7 @@ func checkAction(expected, actual core.Action, t *testing.T) {
|
|||||||
func filterInformerActions(actions []core.Action) []core.Action {
|
func filterInformerActions(actions []core.Action) []core.Action {
|
||||||
var ret []core.Action
|
var ret []core.Action
|
||||||
for _, action := range actions {
|
for _, action := range actions {
|
||||||
if action.Matches("list", "users") ||
|
if !action.Matches("update", "users") {
|
||||||
action.Matches("list", "configmaps") ||
|
|
||||||
action.Matches("watch", "users") {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ret = append(ret, action)
|
ret = append(ret, action)
|
||||||
|
|||||||
@@ -36,7 +36,9 @@ import (
|
|||||||
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
||||||
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||||
iamv1alpha2informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/iam/v1alpha2"
|
iamv1alpha2informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/iam/v1alpha2"
|
||||||
|
tenantv1alpha2informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/tenant/v1alpha2"
|
||||||
iamv1alpha2listers "kubesphere.io/kubesphere/pkg/client/listers/iam/v1alpha2"
|
iamv1alpha2listers "kubesphere.io/kubesphere/pkg/client/listers/iam/v1alpha2"
|
||||||
|
tenantv1alpha2listers "kubesphere.io/kubesphere/pkg/client/listers/tenant/v1alpha2"
|
||||||
"kubesphere.io/kubesphere/pkg/constants"
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||||
@@ -52,13 +54,18 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Controller struct {
|
type Controller struct {
|
||||||
|
scheme *runtime.Scheme
|
||||||
k8sClient kubernetes.Interface
|
k8sClient kubernetes.Interface
|
||||||
ksClient kubesphere.Interface
|
ksClient kubesphere.Interface
|
||||||
workspaceRoleInformer iamv1alpha2informers.WorkspaceRoleInformer
|
workspaceRoleInformer iamv1alpha2informers.WorkspaceRoleInformer
|
||||||
workspaceRoleLister iamv1alpha2listers.WorkspaceRoleLister
|
workspaceRoleLister iamv1alpha2listers.WorkspaceRoleLister
|
||||||
workspaceRoleSynced cache.InformerSynced
|
workspaceRoleSynced cache.InformerSynced
|
||||||
|
workspaceTemplateInformer tenantv1alpha2informers.WorkspaceTemplateInformer
|
||||||
|
workspaceTemplateLister tenantv1alpha2listers.WorkspaceTemplateLister
|
||||||
|
workspaceTemplateSynced cache.InformerSynced
|
||||||
fedWorkspaceRoleCache cache.Store
|
fedWorkspaceRoleCache cache.Store
|
||||||
fedWorkspaceRoleCacheController cache.Controller
|
fedWorkspaceRoleCacheController cache.Controller
|
||||||
|
multiClusterEnabled bool
|
||||||
// workqueue is a rate limited work queue. This is used to queue work to be
|
// 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
|
// 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
|
// means we can ensure we only process a fixed amount of resources at a
|
||||||
@@ -71,7 +78,7 @@ type Controller struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface, workspaceRoleInformer iamv1alpha2informers.WorkspaceRoleInformer,
|
func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface, workspaceRoleInformer iamv1alpha2informers.WorkspaceRoleInformer,
|
||||||
fedWorkspaceRoleCache cache.Store, fedWorkspaceRoleCacheController cache.Controller) *Controller {
|
fedWorkspaceRoleCache cache.Store, fedWorkspaceRoleCacheController cache.Controller, workspaceTemplateInformer tenantv1alpha2informers.WorkspaceTemplateInformer, multiClusterEnabled bool) *Controller {
|
||||||
// Create event broadcaster
|
// Create event broadcaster
|
||||||
// Add sample-controller types to the default Kubernetes Scheme so Events can be
|
// Add sample-controller types to the default Kubernetes Scheme so Events can be
|
||||||
// logged for sample-controller types.
|
// logged for sample-controller types.
|
||||||
@@ -89,6 +96,10 @@ func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface
|
|||||||
workspaceRoleSynced: workspaceRoleInformer.Informer().HasSynced,
|
workspaceRoleSynced: workspaceRoleInformer.Informer().HasSynced,
|
||||||
fedWorkspaceRoleCache: fedWorkspaceRoleCache,
|
fedWorkspaceRoleCache: fedWorkspaceRoleCache,
|
||||||
fedWorkspaceRoleCacheController: fedWorkspaceRoleCacheController,
|
fedWorkspaceRoleCacheController: fedWorkspaceRoleCacheController,
|
||||||
|
workspaceTemplateInformer: workspaceTemplateInformer,
|
||||||
|
workspaceTemplateLister: workspaceTemplateInformer.Lister(),
|
||||||
|
workspaceTemplateSynced: workspaceTemplateInformer.Informer().HasSynced,
|
||||||
|
multiClusterEnabled: multiClusterEnabled,
|
||||||
workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "WorkspaceRole"),
|
workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "WorkspaceRole"),
|
||||||
recorder: recorder,
|
recorder: recorder,
|
||||||
}
|
}
|
||||||
@@ -113,7 +124,13 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error {
|
|||||||
// Wait for the caches to be synced before starting workers
|
// Wait for the caches to be synced before starting workers
|
||||||
klog.Info("Waiting for informer caches to sync")
|
klog.Info("Waiting for informer caches to sync")
|
||||||
|
|
||||||
if ok := cache.WaitForCacheSync(stopCh, c.workspaceRoleSynced, c.fedWorkspaceRoleCacheController.HasSynced); !ok {
|
synced := make([]cache.InformerSynced, 0)
|
||||||
|
synced = append(synced, c.workspaceRoleSynced, c.workspaceTemplateSynced)
|
||||||
|
if c.multiClusterEnabled {
|
||||||
|
synced = append(synced, c.fedWorkspaceRoleCacheController.HasSynced)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok := cache.WaitForCacheSync(stopCh); !ok {
|
||||||
return fmt.Errorf("failed to wait for caches to sync")
|
return fmt.Errorf("failed to wait for caches to sync")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,10 +231,17 @@ func (c *Controller) reconcile(key string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = c.bindWorkspace(workspaceRole); err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.multiClusterEnabled {
|
||||||
if err = c.multiClusterSync(workspaceRole); err != nil {
|
if err = c.multiClusterSync(workspaceRole); err != nil {
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
c.recorder.Event(workspaceRole, corev1.EventTypeNormal, successSynced, messageResourceSynced)
|
c.recorder.Event(workspaceRole, corev1.EventTypeNormal, successSynced, messageResourceSynced)
|
||||||
return nil
|
return nil
|
||||||
@@ -227,6 +251,40 @@ func (c *Controller) Start(stopCh <-chan struct{}) error {
|
|||||||
return c.Run(4, stopCh)
|
return c.Run(4, stopCh)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Controller) bindWorkspace(workspaceRole *iamv1alpha2.WorkspaceRole) error {
|
||||||
|
|
||||||
|
workspaceName := workspaceRole.Labels[constants.WorkspaceLabelKey]
|
||||||
|
|
||||||
|
if workspaceName == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
workspace, err := c.workspaceTemplateLister.Get(workspaceName)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// skip if workspace not found
|
||||||
|
if errors.IsNotFound(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
klog.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !metav1.IsControlledBy(workspaceRole, workspace) {
|
||||||
|
workspaceRole.OwnerReferences = nil
|
||||||
|
if err := controllerutil.SetControllerReference(workspace, workspaceRole, scheme.Scheme); err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = c.ksClient.IamV1alpha2().WorkspaceRoles().Update(workspaceRole)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Controller) multiClusterSync(workspaceRole *iamv1alpha2.WorkspaceRole) error {
|
func (c *Controller) multiClusterSync(workspaceRole *iamv1alpha2.WorkspaceRole) error {
|
||||||
|
|
||||||
if err := c.ensureNotControlledByKubefed(workspaceRole); err != nil {
|
if err := c.ensureNotControlledByKubefed(workspaceRole); err != nil {
|
||||||
|
|||||||
@@ -37,7 +37,9 @@ import (
|
|||||||
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
||||||
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||||
iamv1alpha2informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/iam/v1alpha2"
|
iamv1alpha2informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/iam/v1alpha2"
|
||||||
|
tenantv1alpha2informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/tenant/v1alpha2"
|
||||||
iamv1alpha2listers "kubesphere.io/kubesphere/pkg/client/listers/iam/v1alpha2"
|
iamv1alpha2listers "kubesphere.io/kubesphere/pkg/client/listers/iam/v1alpha2"
|
||||||
|
tenantv1alpha2listers "kubesphere.io/kubesphere/pkg/client/listers/tenant/v1alpha2"
|
||||||
"kubesphere.io/kubesphere/pkg/constants"
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||||
@@ -60,6 +62,10 @@ type Controller struct {
|
|||||||
workspaceRoleBindingSynced cache.InformerSynced
|
workspaceRoleBindingSynced cache.InformerSynced
|
||||||
fedWorkspaceRoleBindingCache cache.Store
|
fedWorkspaceRoleBindingCache cache.Store
|
||||||
fedWorkspaceRoleBindingCacheController cache.Controller
|
fedWorkspaceRoleBindingCacheController cache.Controller
|
||||||
|
workspaceTemplateInformer tenantv1alpha2informers.WorkspaceTemplateInformer
|
||||||
|
workspaceTemplateLister tenantv1alpha2listers.WorkspaceTemplateLister
|
||||||
|
workspaceTemplateSynced cache.InformerSynced
|
||||||
|
multiClusterEnabled bool
|
||||||
// workqueue is a rate limited work queue. This is used to queue work to be
|
// 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
|
// 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
|
// means we can ensure we only process a fixed amount of resources at a
|
||||||
@@ -72,7 +78,7 @@ type Controller struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface, workspaceRoleBindingInformer iamv1alpha2informers.WorkspaceRoleBindingInformer,
|
func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface, workspaceRoleBindingInformer iamv1alpha2informers.WorkspaceRoleBindingInformer,
|
||||||
fedWorkspaceRoleBindingCache cache.Store, fedWorkspaceRoleBindingCacheController cache.Controller) *Controller {
|
fedWorkspaceRoleBindingCache cache.Store, fedWorkspaceRoleBindingCacheController cache.Controller, workspaceTemplateInformer tenantv1alpha2informers.WorkspaceTemplateInformer, multiClusterEnabled bool) *Controller {
|
||||||
// Create event broadcaster
|
// Create event broadcaster
|
||||||
// Add sample-controller types to the default Kubernetes Scheme so Events can be
|
// Add sample-controller types to the default Kubernetes Scheme so Events can be
|
||||||
// logged for sample-controller types.
|
// logged for sample-controller types.
|
||||||
@@ -90,16 +96,20 @@ func NewController(k8sClient kubernetes.Interface, ksClient kubesphere.Interface
|
|||||||
workspaceRoleBindingSynced: workspaceRoleBindingInformer.Informer().HasSynced,
|
workspaceRoleBindingSynced: workspaceRoleBindingInformer.Informer().HasSynced,
|
||||||
fedWorkspaceRoleBindingCache: fedWorkspaceRoleBindingCache,
|
fedWorkspaceRoleBindingCache: fedWorkspaceRoleBindingCache,
|
||||||
fedWorkspaceRoleBindingCacheController: fedWorkspaceRoleBindingCacheController,
|
fedWorkspaceRoleBindingCacheController: fedWorkspaceRoleBindingCacheController,
|
||||||
|
workspaceTemplateInformer: workspaceTemplateInformer,
|
||||||
|
workspaceTemplateLister: workspaceTemplateInformer.Lister(),
|
||||||
|
workspaceTemplateSynced: workspaceTemplateInformer.Informer().HasSynced,
|
||||||
|
multiClusterEnabled: multiClusterEnabled,
|
||||||
workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "WorkspaceRoleBinding"),
|
workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "WorkspaceRoleBinding"),
|
||||||
recorder: recorder,
|
recorder: recorder,
|
||||||
}
|
}
|
||||||
klog.Info("Setting up event handlers")
|
klog.Info("Setting up event handlers")
|
||||||
workspaceRoleBindingInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
workspaceRoleBindingInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||||
AddFunc: ctl.enqueueClusterRoleBinding,
|
AddFunc: ctl.enqueueWorkspaceRoleBinding,
|
||||||
UpdateFunc: func(old, new interface{}) {
|
UpdateFunc: func(old, new interface{}) {
|
||||||
ctl.enqueueClusterRoleBinding(new)
|
ctl.enqueueWorkspaceRoleBinding(new)
|
||||||
},
|
},
|
||||||
DeleteFunc: ctl.enqueueClusterRoleBinding,
|
DeleteFunc: ctl.enqueueWorkspaceRoleBinding,
|
||||||
})
|
})
|
||||||
return ctl
|
return ctl
|
||||||
}
|
}
|
||||||
@@ -114,7 +124,13 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error {
|
|||||||
// Wait for the caches to be synced before starting workers
|
// Wait for the caches to be synced before starting workers
|
||||||
klog.Info("Waiting for informer caches to sync")
|
klog.Info("Waiting for informer caches to sync")
|
||||||
|
|
||||||
if ok := cache.WaitForCacheSync(stopCh, c.workspaceRoleBindingSynced, c.fedWorkspaceRoleBindingCacheController.HasSynced); !ok {
|
synced := make([]cache.InformerSynced, 0)
|
||||||
|
synced = append(synced, c.workspaceRoleBindingSynced, c.workspaceTemplateSynced)
|
||||||
|
if c.multiClusterEnabled {
|
||||||
|
synced = append(synced, c.fedWorkspaceRoleBindingCacheController.HasSynced)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok := cache.WaitForCacheSync(stopCh, synced...); !ok {
|
||||||
return fmt.Errorf("failed to wait for caches to sync")
|
return fmt.Errorf("failed to wait for caches to sync")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +146,7 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) enqueueClusterRoleBinding(obj interface{}) {
|
func (c *Controller) enqueueWorkspaceRoleBinding(obj interface{}) {
|
||||||
var key string
|
var key string
|
||||||
var err error
|
var err error
|
||||||
if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil {
|
if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil {
|
||||||
@@ -215,10 +231,17 @@ func (c *Controller) reconcile(key string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = c.bindWorkspace(workspaceRoleBinding); err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.multiClusterEnabled {
|
||||||
if err = c.multiClusterSync(workspaceRoleBinding); err != nil {
|
if err = c.multiClusterSync(workspaceRoleBinding); err != nil {
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
c.recorder.Event(workspaceRoleBinding, corev1.EventTypeNormal, successSynced, messageResourceSynced)
|
c.recorder.Event(workspaceRoleBinding, corev1.EventTypeNormal, successSynced, messageResourceSynced)
|
||||||
return nil
|
return nil
|
||||||
@@ -228,6 +251,40 @@ func (c *Controller) Start(stopCh <-chan struct{}) error {
|
|||||||
return c.Run(4, stopCh)
|
return c.Run(4, stopCh)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Controller) bindWorkspace(workspaceRoleBinding *iamv1alpha2.WorkspaceRoleBinding) error {
|
||||||
|
|
||||||
|
workspaceName := workspaceRoleBinding.Labels[constants.WorkspaceLabelKey]
|
||||||
|
|
||||||
|
if workspaceName == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
workspace, err := c.workspaceTemplateLister.Get(workspaceName)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// skip if workspace not found
|
||||||
|
if errors.IsNotFound(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
klog.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !metav1.IsControlledBy(workspaceRoleBinding, workspace) {
|
||||||
|
workspaceRoleBinding.OwnerReferences = nil
|
||||||
|
if err := controllerutil.SetControllerReference(workspace, workspaceRoleBinding, scheme.Scheme); err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = c.ksClient.IamV1alpha2().WorkspaceRoleBindings().Update(workspaceRoleBinding)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Controller) multiClusterSync(workspaceRoleBinding *iamv1alpha2.WorkspaceRoleBinding) error {
|
func (c *Controller) multiClusterSync(workspaceRoleBinding *iamv1alpha2.WorkspaceRoleBinding) error {
|
||||||
|
|
||||||
if err := c.ensureNotControlledByKubefed(workspaceRoleBinding); err != nil {
|
if err := c.ensureNotControlledByKubefed(workspaceRoleBinding); err != nil {
|
||||||
|
|||||||
@@ -477,15 +477,43 @@ func (r *Controller) initRoles(workspace *tenantv1alpha2.WorkspaceTemplate) erro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Controller) resetWorkspaceOwner(workspace *tenantv1alpha2.WorkspaceTemplate) error {
|
||||||
|
workspace = workspace.DeepCopy()
|
||||||
|
workspace.Spec.Template.Spec.Manager = ""
|
||||||
|
_, err := r.ksClient.TenantV1alpha2().WorkspaceTemplates().Update(workspace)
|
||||||
|
klog.V(4).Infof("update workspace after manager has been deleted")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Controller) initManagerRoleBinding(workspace *tenantv1alpha2.WorkspaceTemplate) error {
|
func (r *Controller) initManagerRoleBinding(workspace *tenantv1alpha2.WorkspaceTemplate) error {
|
||||||
if manager := workspace.Spec.Template.Spec.Manager; manager != "" {
|
manager := workspace.Spec.Template.Spec.Manager
|
||||||
|
if manager == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := r.ksClient.IamV1alpha2().Users().Get(manager, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
// skip if user has been deleted
|
||||||
|
if errors.IsNotFound(err) {
|
||||||
|
return r.resetWorkspaceOwner(workspace)
|
||||||
|
}
|
||||||
|
klog.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip if user has been deleted
|
||||||
|
if !user.DeletionTimestamp.IsZero() {
|
||||||
|
return r.resetWorkspaceOwner(workspace)
|
||||||
|
}
|
||||||
|
|
||||||
workspaceAdminRoleName := fmt.Sprintf(iamv1alpha2.WorkspaceAdminFormat, workspace.Name)
|
workspaceAdminRoleName := fmt.Sprintf(iamv1alpha2.WorkspaceAdminFormat, workspace.Name)
|
||||||
|
|
||||||
managerRoleBinding := &iamv1alpha2.WorkspaceRoleBinding{
|
managerRoleBinding := &iamv1alpha2.WorkspaceRoleBinding{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: fmt.Sprintf("%s-%s", manager, workspaceAdminRoleName),
|
Name: fmt.Sprintf("%s-%s", manager, workspaceAdminRoleName),
|
||||||
Labels: map[string]string{tenantv1alpha1.WorkspaceLabel: workspace.Name},
|
Labels: map[string]string{
|
||||||
|
tenantv1alpha1.WorkspaceLabel: workspace.Name,
|
||||||
|
iamv1alpha2.UserReferenceLabel: manager,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
RoleRef: rbacv1.RoleRef{
|
RoleRef: rbacv1.RoleRef{
|
||||||
APIGroup: iamv1alpha2.SchemeGroupVersion.Group,
|
APIGroup: iamv1alpha2.SchemeGroupVersion.Group,
|
||||||
@@ -500,7 +528,7 @@ func (r *Controller) initManagerRoleBinding(workspace *tenantv1alpha2.WorkspaceT
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := r.ksClient.IamV1alpha2().WorkspaceRoleBindings().Create(managerRoleBinding)
|
_, err = r.ksClient.IamV1alpha2().WorkspaceRoleBindings().Create(managerRoleBinding)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.IsAlreadyExists(err) {
|
if errors.IsAlreadyExists(err) {
|
||||||
return nil
|
return nil
|
||||||
@@ -508,7 +536,6 @@ func (r *Controller) initManagerRoleBinding(workspace *tenantv1alpha2.WorkspaceT
|
|||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,12 +28,3 @@ func IsControlledBy(reference []metav1.OwnerReference, kind string, name string)
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetControlledWorkspace(reference []metav1.OwnerReference) string {
|
|
||||||
for _, ref := range reference {
|
|
||||||
if ref.Kind == "Workspace" {
|
|
||||||
return ref.Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user