improve multicluster resource controller

Signed-off-by: hongming <talonwan@yunify.com>
This commit is contained in:
hongming
2020-06-15 14:09:32 +08:00
parent 61d827db54
commit 4fcaa78b45
51 changed files with 3583 additions and 381 deletions

View File

@@ -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
}