diff --git a/pkg/controller/group/group_controller.go b/pkg/controller/group/group_controller.go index 6a0f35a28..bdd455987 100644 --- a/pkg/controller/group/group_controller.go +++ b/pkg/controller/group/group_controller.go @@ -37,6 +37,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" iam1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2" + tenantv1alpha2 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha2" fedv1beta1types "kubesphere.io/kubesphere/pkg/apis/types/v1beta1" kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned" iamv1alpha2informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/iam/v1alpha2" @@ -145,10 +146,11 @@ func (c *Controller) reconcile(key string) error { } } - if group.Labels != nil { - // Set OwnerReferences when the group has a parent. And it's not owned by kubefed - if group.Labels[constants.KubefedManagedLabel] != "true" { - if parent, ok := group.Labels[iam1alpha2.GroupParent]; ok && !k8sutil.IsControlledBy(group.OwnerReferences, "Group", parent) { + // Set OwnerReferences when the group has a parent or Workspace. And it's not owned by kubefed + if group.Labels != nil && group.Labels[constants.KubefedManagedLabel] != "true" { + if parent, ok := group.Labels[iam1alpha2.GroupParent]; ok { + // If the Group is owned by a Parent + if !k8sutil.IsControlledBy(group.OwnerReferences, "Group", parent) { if g == nil { g = group.DeepCopy() } @@ -156,7 +158,7 @@ func (c *Controller) reconcile(key string) error { if err != nil { if errors.IsNotFound(err) { utilruntime.HandleError(fmt.Errorf("Parent group '%s' no longer exists", key)) - delete(group.Labels, iam1alpha2.GroupParent) + delete(g.Labels, iam1alpha2.GroupParent) } else { klog.Error(err) return err @@ -168,6 +170,27 @@ func (c *Controller) reconcile(key string) error { } } } + } else if ws, ok := group.Labels[constants.WorkspaceLabelKey]; ok { + // If the Group is owned by a Workspace + if !k8sutil.IsControlledBy(group.OwnerReferences, tenantv1alpha2.ResourceKindWorkspaceTemplate, ws) { + workspace, err := c.ksClient.TenantV1alpha2().WorkspaceTemplates().Get(context.Background(), ws, metav1.GetOptions{}) + if err != nil { + if errors.IsNotFound(err) { + utilruntime.HandleError(fmt.Errorf("Workspace '%s' no longer exists", ws)) + } else { + klog.Error(err) + return err + } + } else { + if g == nil { + g = group.DeepCopy() + } + g.OwnerReferences = k8sutil.RemoveWorkspaceOwnerReference(g.OwnerReferences) + if err := controllerutil.SetControllerReference(workspace, g, scheme.Scheme); err != nil { + return err + } + } + } } } if g != nil { diff --git a/pkg/controller/group/group_controller_test.go b/pkg/controller/group/group_controller_test.go index 073b20a83..68472429f 100644 --- a/pkg/controller/group/group_controller_test.go +++ b/pkg/controller/group/group_controller_test.go @@ -21,6 +21,7 @@ import ( "testing" "time" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -34,12 +35,11 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" v1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2" + tenantv1alpha2 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha2" fedv1beta1types "kubesphere.io/kubesphere/pkg/apis/types/v1beta1" "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake" ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions" "kubesphere.io/kubesphere/pkg/constants" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) var ( @@ -49,6 +49,7 @@ var ( func init() { v1alpha2.AddToScheme(scheme.Scheme) + tenantv1alpha2.AddToScheme(scheme.Scheme) } type fixture struct { @@ -268,6 +269,7 @@ func filterInformerActions(actions []core.Action) []core.Action { action.Matches("watch", "groups") || action.Matches("list", "groups") || action.Matches("list", "namespaces") || + action.Matches("get", "workspacetemplates") || action.Matches("list", "federatedgroups") || action.Matches("watch", "federatedgroups")) { continue @@ -289,6 +291,20 @@ func (f *fixture) expectUpdateGroupsFinalizerAction(group *v1alpha2.Group) { f.actions = append(f.actions, action) } +func (f *fixture) expectUpdateWorkspaceRefAction(child *v1alpha2.Group, wsp *tenantv1alpha2.WorkspaceTemplate) { + expect := child.DeepCopy() + if expect.Labels == nil { + expect.Labels = make(map[string]string, 0) + } + + controllerutil.SetControllerReference(wsp, expect, scheme.Scheme) + + expect.Finalizers = []string{"finalizers.kubesphere.io/groups"} + expect.Labels[constants.KubefedManagedLabel] = "false" + updateAction := core.NewUpdateAction(schema.GroupVersionResource{Resource: "groups"}, "", expect) + f.actions = append(f.actions, updateAction) +} + func (f *fixture) expectUpdateParentsRefAction(parent, child *v1alpha2.Group) { expect := child.DeepCopy() if expect.Labels == nil { @@ -385,6 +401,26 @@ func TestGroupCreateWithParent(t *testing.T) { f.run(getKey(child, t)) } +func TestGroupCreateWithWorkspace(t *testing.T) { + f := newFixture(t) + child := newGroup("child") + child.Labels = map[string]string{constants.WorkspaceLabelKey: "wsp"} + + f.groupLister = append(f.groupLister, child) + f.objects = append(f.objects, child) + + wsp := tenantv1alpha2.WorkspaceTemplate{ + TypeMeta: metav1.TypeMeta{APIVersion: tenantv1alpha2.SchemeGroupVersion.String(), Kind: tenantv1alpha2.ResourceKindWorkspaceTemplate}, + ObjectMeta: metav1.ObjectMeta{ + Name: "wsp", + }, + } + f.objects = append(f.objects, &wsp) + + f.expectUpdateWorkspaceRefAction(child, &wsp) + f.run(getKey(child, t)) +} + func TestFederetedGroupCreate(t *testing.T) { f := newFixture(t)