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

@@ -333,9 +333,9 @@ func (am *amOperator) GetGlobalRole(globalRole string) (*iamv1alpha2.GlobalRole,
return obj.(*iamv1alpha2.GlobalRole), nil
}
func (am *amOperator) CreateGlobalRoleBinding(username string, globalRole string) error {
func (am *amOperator) CreateGlobalRoleBinding(username string, role string) error {
_, err := am.GetGlobalRole(globalRole)
_, err := am.GetGlobalRole(role)
if err != nil {
klog.Error(err)
@@ -350,7 +350,7 @@ func (am *amOperator) CreateGlobalRoleBinding(username string, globalRole string
}
for _, roleBinding := range roleBindings {
if globalRole == roleBinding.RoleRef.Name {
if role == roleBinding.RoleRef.Name {
return nil
}
err := am.ksclient.IamV1alpha2().GlobalRoleBindings().Delete(roleBinding.Name, metav1.NewDeleteOptions(0))
@@ -365,7 +365,7 @@ func (am *amOperator) CreateGlobalRoleBinding(username string, globalRole string
globalRoleBinding := iamv1alpha2.GlobalRoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-%s", username, globalRole),
Name: fmt.Sprintf("%s-%s", username, role),
Labels: map[string]string{iamv1alpha2.UserReferenceLabel: username},
},
Subjects: []rbacv1.Subject{
@@ -378,7 +378,7 @@ func (am *amOperator) CreateGlobalRoleBinding(username string, globalRole string
RoleRef: rbacv1.RoleRef{
APIGroup: iamv1alpha2.SchemeGroupVersion.Group,
Kind: iamv1alpha2.ResourceKindGlobalRole,
Name: globalRole,
Name: role,
},
}
@@ -456,7 +456,7 @@ func (am *amOperator) CreateWorkspaceRoleBinding(username string, workspace stri
roleBinding := iamv1alpha2.WorkspaceRoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-%s", role, username),
Name: fmt.Sprintf("%s-%s", username, role),
Labels: map[string]string{iamv1alpha2.UserReferenceLabel: username,
tenantv1alpha1.WorkspaceLabel: workspace},
},

View File

@@ -131,10 +131,7 @@ func (im *defaultIMOperator) ListUsers(query *query.Query) (result *api.ListResu
for _, item := range result.Items {
user := item.(*iamv1alpha2.User)
out := user.DeepCopy()
// ensure encrypted password will not be output
out.Spec.EncryptedPassword = ""
items = append(items, out)
items = append(items, ensurePasswordNotOutput(user))
}
result.Items = items
@@ -156,11 +153,8 @@ func (im *defaultIMOperator) DescribeUser(username string) (*iamv1alpha2.User, e
}
user := obj.(*iamv1alpha2.User)
out := user.DeepCopy()
// ensure encrypted password will not be output
out.Spec.EncryptedPassword = ""
return out, nil
return ensurePasswordNotOutput(user), nil
}
func (im *defaultIMOperator) DeleteUser(username string) error {
@@ -175,3 +169,10 @@ func (im *defaultIMOperator) CreateUser(user *iamv1alpha2.User) (*iamv1alpha2.Us
}
return user, nil
}
func ensurePasswordNotOutput(user *iamv1alpha2.User) *iamv1alpha2.User {
out := user.DeepCopy()
// ensure encrypted password will not be output
out.Spec.EncryptedPassword = ""
return out
}

View File

@@ -28,6 +28,7 @@ import (
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/authentication/user"
corev1informers "k8s.io/client-go/informers/core/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
@@ -60,30 +61,38 @@ type Interface interface {
}
type operator struct {
k8sclient kubernetes.Interface
config *rest.Config
masterURL string
k8sClient kubernetes.Interface
configMapInformer corev1informers.ConfigMapInformer
config *rest.Config
masterURL string
}
func NewOperator(k8sclient kubernetes.Interface, config *rest.Config, masterURL string) Interface {
return &operator{k8sclient: k8sclient, config: config, masterURL: masterURL}
func NewOperator(k8sClient kubernetes.Interface, configMapInformer corev1informers.ConfigMapInformer, config *rest.Config) Interface {
return &operator{k8sClient: k8sClient, configMapInformer: configMapInformer, config: config}
}
func NewReadOnlyOperator(configMapInformer corev1informers.ConfigMapInformer, masterURL string) Interface {
return &operator{configMapInformer: configMapInformer, masterURL: masterURL}
}
func (o *operator) CreateKubeConfig(user *iamv1alpha2.User) error {
configName := fmt.Sprintf(kubeconfigNameFormat, user.Name)
_, err := o.k8sclient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Get(configName, metav1.GetOptions{})
_, err := o.configMapInformer.Lister().ConfigMaps(constants.KubeSphereControlNamespace).Get(configName)
// already exist
if err == nil {
return nil
}
// internal error
if !errors.IsNotFound(err) {
klog.Error(err)
return err
}
// create if not exist
var ca []byte
if len(o.config.CAData) > 0 {
ca = o.config.CAData
@@ -142,7 +151,7 @@ func (o *operator) CreateKubeConfig(user *iamv1alpha2.User) error {
return err
}
_, err = o.k8sclient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Create(cm)
_, err = o.k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Create(cm)
if err != nil {
klog.Errorln(err)
@@ -154,7 +163,7 @@ func (o *operator) CreateKubeConfig(user *iamv1alpha2.User) error {
func (o *operator) GetKubeConfig(username string) (string, error) {
configName := fmt.Sprintf(kubeconfigNameFormat, username)
configMap, err := o.k8sclient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Get(configName, metav1.GetOptions{})
configMap, err := o.configMapInformer.Lister().ConfigMaps(constants.KubeSphereControlNamespace).Get(configName)
if err != nil {
klog.Errorln(err)
return "", err
@@ -171,6 +180,7 @@ func (o *operator) GetKubeConfig(username string) (string, error) {
masterURL := o.masterURL
// server host override
if cluster := kubeconfig.Clusters[defaultClusterName]; cluster != nil {
cluster.Server = masterURL
}
@@ -244,7 +254,7 @@ func (o *operator) createCSR(username string) ([]byte, error) {
}
// create csr
k8sCSR, err = o.k8sclient.CertificatesV1beta1().CertificateSigningRequests().Create(k8sCSR)
k8sCSR, err = o.k8sClient.CertificatesV1beta1().CertificateSigningRequests().Create(k8sCSR)
if err != nil {
klog.Errorln(err)
@@ -256,14 +266,14 @@ func (o *operator) createCSR(username string) ([]byte, error) {
func (o *operator) UpdateKubeconfig(username string, certificate []byte) error {
configName := fmt.Sprintf(kubeconfigNameFormat, username)
configMap, err := o.k8sclient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Get(configName, metav1.GetOptions{})
configMap, err := o.k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Get(configName, metav1.GetOptions{})
if err != nil {
klog.Errorln(err)
return err
}
configMap = appendCert(configMap, certificate)
_, err = o.k8sclient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Update(configMap)
_, err = o.k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Update(configMap)
if err != nil {
klog.Errorln(err)
return err

View File

@@ -73,6 +73,7 @@ type Interface interface {
UpdateNamespace(workspace string, namespace *corev1.Namespace) (*corev1.Namespace, error)
PatchNamespace(workspace string, namespace *corev1.Namespace) (*corev1.Namespace, error)
PatchWorkspace(workspace *tenantv1alpha2.WorkspaceTemplate) (*tenantv1alpha2.WorkspaceTemplate, error)
ListClusters(info user.Info) (*api.ListResult, error)
}
type tenantOperator struct {
@@ -355,6 +356,90 @@ func (t *tenantOperator) ListWorkspaceClusters(workspaceName string) (*api.ListR
}
return &api.ListResult{Items: clusters, TotalItems: len(clusters)}, nil
}
func (t *tenantOperator) ListClusters(user user.Info) (*api.ListResult, error) {
listClustersInGlobalScope := authorizer.AttributesRecord{
User: user,
Verb: "list",
Resource: "clusters",
ResourceScope: request.GlobalScope,
ResourceRequest: true,
}
allowedListClustersInGlobalScope, _, err := t.authorizer.Authorize(listClustersInGlobalScope)
if err != nil {
klog.Error(err)
return nil, err
}
listWorkspacesInGlobalScope := authorizer.AttributesRecord{
User: user,
Verb: "list",
Resource: "workspaces",
ResourceScope: request.GlobalScope,
ResourceRequest: true,
}
allowedListWorkspacesInGlobalScope, _, err := t.authorizer.Authorize(listWorkspacesInGlobalScope)
if err != nil {
klog.Error(err)
return nil, err
}
if allowedListClustersInGlobalScope == authorizer.DecisionAllow ||
allowedListWorkspacesInGlobalScope == authorizer.DecisionAllow {
result, err := t.resourceGetter.List(clusterv1alpha1.ResourcesPluralCluster, "", query.New())
if err != nil {
klog.Error(err)
return nil, err
}
return result, nil
}
workspaceRoleBindings, err := t.am.ListWorkspaceRoleBindings(user.GetName(), "")
if err != nil {
klog.Error(err)
return nil, err
}
clusters := map[string]*clusterv1alpha1.Cluster{}
for _, roleBinding := range workspaceRoleBindings {
workspaceName := roleBinding.Labels[tenantv1alpha1.WorkspaceLabel]
workspace, err := t.DescribeWorkspace(workspaceName)
if err != nil {
klog.Error(err)
return nil, err
}
for _, clusterName := range workspace.Spec.Clusters {
// skip if cluster exist
if clusters[clusterName] != nil {
continue
}
obj, err := t.resourceGetter.Get(clusterv1alpha1.ResourcesPluralCluster, "", clusterName)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
continue
}
return nil, err
}
cluster := obj.(*clusterv1alpha1.Cluster)
clusters[clusterName] = cluster
}
}
items := make([]interface{}, 0)
for _, cluster := range clusters {
items = append(items, cluster)
}
return &api.ListResult{Items: items, TotalItems: len(items)}, nil
}
func (t *tenantOperator) DeleteWorkspace(workspace string) error {
return t.ksclient.TenantV1alpha2().WorkspaceTemplates().Delete(workspace, metav1.NewDeleteOptions(0))