Files
kubesphere/pkg/controller/group/group_controller.go
KubeSphere CI Bot 447a51f08b feat: kubesphere 4.0 (#6115)
* feat: kubesphere 4.0

Signed-off-by: ci-bot <ci-bot@kubesphere.io>

* feat: kubesphere 4.0

Signed-off-by: ci-bot <ci-bot@kubesphere.io>

---------

Signed-off-by: ci-bot <ci-bot@kubesphere.io>
Co-authored-by: ks-ci-bot <ks-ci-bot@example.com>
Co-authored-by: joyceliu <joyceliu@yunify.com>
2024-09-06 11:05:52 +08:00

135 lines
3.9 KiB
Go

/*
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package group
import (
"context"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/client-go/tools/record"
iamv1beta1 "kubesphere.io/api/iam/v1beta1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"kubesphere.io/kubesphere/pkg/controller"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
)
const (
controllerName = "group"
finalizer = "finalizers.kubesphere.io/groups"
)
type Reconciler struct {
client.Client
recorder record.EventRecorder
}
func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
r.recorder = mgr.GetEventRecorderFor(controllerName)
r.Client = mgr.GetClient()
return builder.
ControllerManagedBy(mgr).
For(
&iamv1beta1.Group{},
builder.WithPredicates(
predicate.ResourceVersionChangedPredicate{},
),
).
Named(controllerName).
Complete(r)
}
func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
group := &iamv1beta1.Group{}
if err := r.Get(ctx, req.NamespacedName, group); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
if group.ObjectMeta.DeletionTimestamp.IsZero() {
var g *iamv1beta1.Group
if !sliceutil.HasString(group.Finalizers, finalizer) {
g = group.DeepCopy()
g.ObjectMeta.Finalizers = append(g.ObjectMeta.Finalizers, finalizer)
}
if g != nil {
return ctrl.Result{}, r.Update(ctx, g)
}
} else {
// The object is being deleted
if sliceutil.HasString(group.ObjectMeta.Finalizers, finalizer) {
if err := r.deleteGroupBindings(ctx, group); err != nil {
return ctrl.Result{}, err
}
if err := r.deleteRoleBindings(ctx, group); err != nil {
return ctrl.Result{}, err
}
group.Finalizers = sliceutil.RemoveString(group.ObjectMeta.Finalizers, func(item string) bool {
return item == finalizer
})
return ctrl.Result{}, r.Update(ctx, group)
}
return ctrl.Result{}, nil
}
// TODO: sync logic needs to be updated and no longer relies on KubeFed, it needs to be synchronized manually.
r.recorder.Event(group, corev1.EventTypeNormal, controller.Synced, controller.MessageResourceSynced)
return ctrl.Result{}, nil
}
func (r *Reconciler) deleteGroupBindings(ctx context.Context, group *iamv1beta1.Group) error {
if len(group.Name) > validation.LabelValueMaxLength {
// ignore invalid label value error
return nil
}
// Group bindings that created by kubesphere will be deleted directly.
return r.DeleteAllOf(ctx, &iamv1beta1.GroupBinding{}, client.GracePeriodSeconds(0), client.MatchingLabelsSelector{
Selector: labels.SelectorFromValidatedSet(labels.Set{iamv1beta1.GroupReferenceLabel: group.Name}),
})
}
// remove all RoleBindings.
func (r *Reconciler) deleteRoleBindings(ctx context.Context, group *iamv1beta1.Group) error {
if len(group.Name) > validation.LabelValueMaxLength {
// ignore invalid label value error
return nil
}
selector := labels.SelectorFromValidatedSet(labels.Set{iamv1beta1.GroupReferenceLabel: group.Name})
deleteOption := client.GracePeriodSeconds(0)
if err := r.DeleteAllOf(ctx, &iamv1beta1.WorkspaceRoleBinding{}, deleteOption, client.MatchingLabelsSelector{Selector: selector}); err != nil {
return err
}
if err := r.DeleteAllOf(ctx, &rbacv1.ClusterRoleBinding{}, deleteOption, client.MatchingLabelsSelector{Selector: selector}); err != nil {
return err
}
namespaces := &corev1.NamespaceList{}
if err := r.List(ctx, namespaces); err != nil {
return err
}
for _, namespace := range namespaces.Items {
if err := r.DeleteAllOf(ctx, &rbacv1.RoleBinding{}, deleteOption, client.MatchingLabelsSelector{Selector: selector}, client.InNamespace(namespace.Name)); err != nil {
return err
}
}
return nil
}