improve multicluster resource controller
Signed-off-by: hongming <talonwan@yunify.com>
This commit is contained in:
@@ -17,17 +17,23 @@ limitations under the License.
|
||||
package namespace
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/yaml"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
|
||||
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
||||
tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"reflect"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
@@ -37,11 +43,6 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/source"
|
||||
)
|
||||
|
||||
/**
|
||||
* USER ACTION REQUIRED: This is a scaffold file intended for the user to modify with their own Controller
|
||||
* business logic. Delete these comments after modifying this file.*
|
||||
*/
|
||||
|
||||
// Add creates a new Namespace Controller and adds it to the Manager with default RBAC. The Manager will set fields on the Controller
|
||||
// and Start it when the Manager is Started.
|
||||
func Add(mgr manager.Manager) error {
|
||||
@@ -138,7 +139,15 @@ func (r *ReconcileNamespace) Reconcile(request reconcile.Request) (reconcile.Res
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
|
||||
if err = r.checkAndBindWorkspace(instance); err != nil {
|
||||
if err = r.bindWorkspace(instance); err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
if err = r.initRoles(instance); err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
if err = r.initCreatorRoleBinding(instance); err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
@@ -157,7 +166,7 @@ func (r *ReconcileNamespace) isControlledByWorkspace(namespace *corev1.Namespace
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (r *ReconcileNamespace) checkAndBindWorkspace(namespace *corev1.Namespace) error {
|
||||
func (r *ReconcileNamespace) bindWorkspace(namespace *corev1.Namespace) error {
|
||||
|
||||
workspaceName := namespace.Labels[constants.WorkspaceLabelKey]
|
||||
|
||||
@@ -165,7 +174,7 @@ func (r *ReconcileNamespace) checkAndBindWorkspace(namespace *corev1.Namespace)
|
||||
return nil
|
||||
}
|
||||
|
||||
workspace := &v1alpha1.Workspace{}
|
||||
workspace := &tenantv1alpha1.Workspace{}
|
||||
|
||||
err := r.Get(context.TODO(), types.NamespacedName{Name: workspaceName}, workspace)
|
||||
|
||||
@@ -174,18 +183,20 @@ func (r *ReconcileNamespace) checkAndBindWorkspace(namespace *corev1.Namespace)
|
||||
if errors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
klog.Errorf("bind workspace namespace: %s, workspace: %s, error: %s", namespace.Name, workspaceName, err)
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if !metav1.IsControlledBy(namespace, workspace) {
|
||||
// federated namespace not controlled by workspace
|
||||
if namespace.Labels[constants.KubefedManagedLabel] != "true" && !metav1.IsControlledBy(namespace, workspace) {
|
||||
namespace.OwnerReferences = removeWorkspaceOwnerReferences(namespace.OwnerReferences)
|
||||
if err := controllerutil.SetControllerReference(workspace, namespace, r.scheme); err != nil {
|
||||
klog.Errorf("bind workspace namespace: %s, workspace: %s, error: %s", namespace.Name, workspaceName, err)
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
err = r.Update(context.TODO(), namespace)
|
||||
if err != nil {
|
||||
klog.Errorf("bind workspace namespace: %s, workspace: %s, error: %s", namespace.Name, workspaceName, err)
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -193,6 +204,16 @@ func (r *ReconcileNamespace) checkAndBindWorkspace(namespace *corev1.Namespace)
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeWorkspaceOwnerReferences(ownerReferences []metav1.OwnerReference) []metav1.OwnerReference {
|
||||
for i, owner := range ownerReferences {
|
||||
if owner.Kind == tenantv1alpha1.ResourceKindWorkspace {
|
||||
ownerReferences = append(ownerReferences[:i], ownerReferences[i+1:]...)
|
||||
i--
|
||||
}
|
||||
}
|
||||
return ownerReferences
|
||||
}
|
||||
|
||||
func (r *ReconcileNamespace) deleteRouter(namespace string) error {
|
||||
routerName := constants.IngressControllerPrefix + namespace
|
||||
|
||||
@@ -230,5 +251,79 @@ func (r *ReconcileNamespace) deleteRouter(namespace string) error {
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (r *ReconcileNamespace) initRoles(namespace *corev1.Namespace) error {
|
||||
var roleBases iamv1alpha2.RoleBaseList
|
||||
|
||||
err := r.List(context.Background(), &roleBases)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, roleBase := range roleBases.Items {
|
||||
var role rbacv1.Role
|
||||
|
||||
if err = yaml.NewYAMLOrJSONDecoder(bytes.NewBuffer(roleBase.Role.Raw), 1024).Decode(&role); err == nil {
|
||||
var old rbacv1.Role
|
||||
err := r.Client.Get(context.Background(), types.NamespacedName{Namespace: namespace.Name, Name: role.Name}, &old)
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
role.Namespace = namespace.Name
|
||||
err = r.Client.Create(context.Background(), &role)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(role.Labels, old.Labels) ||
|
||||
!reflect.DeepEqual(role.Annotations, old.Annotations) ||
|
||||
!reflect.DeepEqual(role.Rules, old.Rules) {
|
||||
|
||||
old.Labels = role.Labels
|
||||
old.Annotations = role.Annotations
|
||||
old.Rules = role.Rules
|
||||
|
||||
return r.Update(context.Background(), &old)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ReconcileNamespace) initCreatorRoleBinding(namespace *corev1.Namespace) error {
|
||||
if creator := namespace.Annotations[constants.CreatorAnnotationKey]; creator != "" {
|
||||
creatorRoleBinding := &rbacv1.RoleBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: fmt.Sprintf("%s-%s", creator, iamv1alpha2.NamespaceAdmin),
|
||||
Namespace: namespace.Name,
|
||||
},
|
||||
RoleRef: rbacv1.RoleRef{
|
||||
APIGroup: rbacv1.GroupName,
|
||||
Kind: iamv1alpha2.ResourceKindRole,
|
||||
Name: iamv1alpha2.NamespaceAdmin,
|
||||
},
|
||||
Subjects: []rbacv1.Subject{
|
||||
{
|
||||
Name: creator,
|
||||
Kind: iamv1alpha2.ResourceKindUser,
|
||||
APIGroup: rbacv1.GroupName,
|
||||
},
|
||||
},
|
||||
}
|
||||
err := r.Client.Create(context.Background(), creatorRoleBinding)
|
||||
if err != nil {
|
||||
if errors.IsAlreadyExists(err) {
|
||||
return nil
|
||||
}
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user