improve multicluster resource controller
Signed-off-by: hongming <talonwan@yunify.com>
This commit is contained in:
@@ -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},
|
||||
},
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user