fix: cluster list granted to users is incorrect
This commit is contained in:
@@ -488,9 +488,10 @@ func addAllControllers(mgr manager.Manager, client k8s.Client, informerFactory i
|
|||||||
if cmOptions.MultiClusterOptions.Enable {
|
if cmOptions.MultiClusterOptions.Enable {
|
||||||
clusterController := cluster.NewClusterController(
|
clusterController := cluster.NewClusterController(
|
||||||
client.Kubernetes(),
|
client.Kubernetes(),
|
||||||
|
client.KubeSphere(),
|
||||||
client.Config(),
|
client.Config(),
|
||||||
kubesphereInformer.Cluster().V1alpha1().Clusters(),
|
kubesphereInformer.Cluster().V1alpha1().Clusters(),
|
||||||
client.KubeSphere().ClusterV1alpha1().Clusters(),
|
kubesphereInformer.Iam().V1alpha2().Users().Lister(),
|
||||||
cmOptions.MultiClusterOptions.ClusterControllerResyncPeriod,
|
cmOptions.MultiClusterOptions.ClusterControllerResyncPeriod,
|
||||||
cmOptions.MultiClusterOptions.HostClusterName,
|
cmOptions.MultiClusterOptions.HostClusterName,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -26,31 +26,25 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"kubesphere.io/kubesphere/pkg/models/openpitrix"
|
|
||||||
"kubesphere.io/kubesphere/pkg/utils/clusterclient"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
|
||||||
"k8s.io/client-go/discovery"
|
|
||||||
|
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/client-go/util/retry"
|
|
||||||
|
|
||||||
"github.com/emicklei/go-restful"
|
"github.com/emicklei/go-restful"
|
||||||
extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
urlruntime "k8s.io/apimachinery/pkg/util/runtime"
|
urlruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
unionauth "k8s.io/apiserver/pkg/authentication/request/union"
|
unionauth "k8s.io/apiserver/pkg/authentication/request/union"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
|
"k8s.io/client-go/util/retry"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
runtimecache "sigs.k8s.io/controller-runtime/pkg/cache"
|
|
||||||
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
|
|
||||||
|
|
||||||
clusterv1alpha1 "kubesphere.io/api/cluster/v1alpha1"
|
clusterv1alpha1 "kubesphere.io/api/cluster/v1alpha1"
|
||||||
iamv1alpha2 "kubesphere.io/api/iam/v1alpha2"
|
iamv1alpha2 "kubesphere.io/api/iam/v1alpha2"
|
||||||
notificationv2beta1 "kubesphere.io/api/notification/v2beta1"
|
notificationv2beta1 "kubesphere.io/api/notification/v2beta1"
|
||||||
tenantv1alpha1 "kubesphere.io/api/tenant/v1alpha1"
|
tenantv1alpha1 "kubesphere.io/api/tenant/v1alpha1"
|
||||||
typesv1beta1 "kubesphere.io/api/types/v1beta1"
|
typesv1beta1 "kubesphere.io/api/types/v1beta1"
|
||||||
|
runtimecache "sigs.k8s.io/controller-runtime/pkg/cache"
|
||||||
|
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
|
||||||
audit "kubesphere.io/kubesphere/pkg/apiserver/auditing"
|
audit "kubesphere.io/kubesphere/pkg/apiserver/auditing"
|
||||||
"kubesphere.io/kubesphere/pkg/apiserver/authentication/authenticators/basic"
|
"kubesphere.io/kubesphere/pkg/apiserver/authentication/authenticators/basic"
|
||||||
@@ -101,6 +95,7 @@ import (
|
|||||||
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
||||||
"kubesphere.io/kubesphere/pkg/models/iam/group"
|
"kubesphere.io/kubesphere/pkg/models/iam/group"
|
||||||
"kubesphere.io/kubesphere/pkg/models/iam/im"
|
"kubesphere.io/kubesphere/pkg/models/iam/im"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/openpitrix"
|
||||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/loginrecord"
|
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/loginrecord"
|
||||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/user"
|
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/user"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/alerting"
|
"kubesphere.io/kubesphere/pkg/simple/client/alerting"
|
||||||
@@ -113,6 +108,7 @@ import (
|
|||||||
"kubesphere.io/kubesphere/pkg/simple/client/monitoring"
|
"kubesphere.io/kubesphere/pkg/simple/client/monitoring"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/s3"
|
"kubesphere.io/kubesphere/pkg/simple/client/s3"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/sonarqube"
|
"kubesphere.io/kubesphere/pkg/simple/client/sonarqube"
|
||||||
|
"kubesphere.io/kubesphere/pkg/utils/clusterclient"
|
||||||
"kubesphere.io/kubesphere/pkg/utils/iputil"
|
"kubesphere.io/kubesphere/pkg/utils/iputil"
|
||||||
"kubesphere.io/kubesphere/pkg/utils/metrics"
|
"kubesphere.io/kubesphere/pkg/utils/metrics"
|
||||||
)
|
)
|
||||||
@@ -238,9 +234,9 @@ func (s *APIServer) installKubeSphereAPIs(stopCh <-chan struct{}) {
|
|||||||
urlruntime.Must(resourcesv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.InformerFactory,
|
urlruntime.Must(resourcesv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.InformerFactory,
|
||||||
s.KubernetesClient.Master()))
|
s.KubernetesClient.Master()))
|
||||||
urlruntime.Must(tenantv1alpha2.AddToContainer(s.container, s.InformerFactory, s.KubernetesClient.Kubernetes(),
|
urlruntime.Must(tenantv1alpha2.AddToContainer(s.container, s.InformerFactory, s.KubernetesClient.Kubernetes(),
|
||||||
s.KubernetesClient.KubeSphere(), s.EventsClient, s.LoggingClient, s.AuditingClient, amOperator, rbacAuthorizer, s.MonitoringClient, s.RuntimeCache, s.Config.MeteringOptions, s.OpenpitrixClient))
|
s.KubernetesClient.KubeSphere(), s.EventsClient, s.LoggingClient, s.AuditingClient, amOperator, imOperator, rbacAuthorizer, s.MonitoringClient, s.RuntimeCache, s.Config.MeteringOptions, s.OpenpitrixClient))
|
||||||
urlruntime.Must(tenantv1alpha3.AddToContainer(s.container, s.InformerFactory, s.KubernetesClient.Kubernetes(),
|
urlruntime.Must(tenantv1alpha3.AddToContainer(s.container, s.InformerFactory, s.KubernetesClient.Kubernetes(),
|
||||||
s.KubernetesClient.KubeSphere(), s.EventsClient, s.LoggingClient, s.AuditingClient, amOperator, rbacAuthorizer, s.MonitoringClient, s.RuntimeCache, s.Config.MeteringOptions, s.OpenpitrixClient))
|
s.KubernetesClient.KubeSphere(), s.EventsClient, s.LoggingClient, s.AuditingClient, amOperator, imOperator, rbacAuthorizer, s.MonitoringClient, s.RuntimeCache, s.Config.MeteringOptions, s.OpenpitrixClient))
|
||||||
urlruntime.Must(terminalv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), rbacAuthorizer, s.KubernetesClient.Config(), s.Config.TerminalOptions))
|
urlruntime.Must(terminalv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), rbacAuthorizer, s.KubernetesClient.Config(), s.Config.TerminalOptions))
|
||||||
urlruntime.Must(clusterkapisv1alpha1.AddToContainer(s.container,
|
urlruntime.Must(clusterkapisv1alpha1.AddToContainer(s.container,
|
||||||
s.KubernetesClient.KubeSphere(),
|
s.KubernetesClient.KubeSphere(),
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
@@ -48,11 +49,13 @@ import (
|
|||||||
fedv1b1 "sigs.k8s.io/kubefed/pkg/apis/core/v1beta1"
|
fedv1b1 "sigs.k8s.io/kubefed/pkg/apis/core/v1beta1"
|
||||||
|
|
||||||
clusterv1alpha1 "kubesphere.io/api/cluster/v1alpha1"
|
clusterv1alpha1 "kubesphere.io/api/cluster/v1alpha1"
|
||||||
|
iamv1alpha2 "kubesphere.io/api/iam/v1alpha2"
|
||||||
|
|
||||||
"kubesphere.io/kubesphere/pkg/apiserver/config"
|
"kubesphere.io/kubesphere/pkg/apiserver/config"
|
||||||
clusterclient "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/cluster/v1alpha1"
|
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||||
clusterinformer "kubesphere.io/kubesphere/pkg/client/informers/externalversions/cluster/v1alpha1"
|
clusterinformer "kubesphere.io/kubesphere/pkg/client/informers/externalversions/cluster/v1alpha1"
|
||||||
clusterlister "kubesphere.io/kubesphere/pkg/client/listers/cluster/v1alpha1"
|
clusterlister "kubesphere.io/kubesphere/pkg/client/listers/cluster/v1alpha1"
|
||||||
|
iamv1alpha2listers "kubesphere.io/kubesphere/pkg/client/listers/iam/v1alpha2"
|
||||||
"kubesphere.io/kubesphere/pkg/constants"
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/multicluster"
|
"kubesphere.io/kubesphere/pkg/simple/client/multicluster"
|
||||||
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
|
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
|
||||||
@@ -126,12 +129,13 @@ type clusterController struct {
|
|||||||
eventRecorder record.EventRecorder
|
eventRecorder record.EventRecorder
|
||||||
|
|
||||||
// build this only for host cluster
|
// build this only for host cluster
|
||||||
client kubernetes.Interface
|
k8sClient kubernetes.Interface
|
||||||
hostConfig *rest.Config
|
hostConfig *rest.Config
|
||||||
|
|
||||||
clusterClient clusterclient.ClusterInterface
|
ksClient kubesphere.Interface
|
||||||
|
|
||||||
clusterLister clusterlister.ClusterLister
|
clusterLister clusterlister.ClusterLister
|
||||||
|
userLister iamv1alpha2listers.UserLister
|
||||||
clusterHasSynced cache.InformerSynced
|
clusterHasSynced cache.InformerSynced
|
||||||
|
|
||||||
queue workqueue.RateLimitingInterface
|
queue workqueue.RateLimitingInterface
|
||||||
@@ -144,10 +148,11 @@ type clusterController struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewClusterController(
|
func NewClusterController(
|
||||||
client kubernetes.Interface,
|
k8sClient kubernetes.Interface,
|
||||||
|
ksClient kubesphere.Interface,
|
||||||
config *rest.Config,
|
config *rest.Config,
|
||||||
clusterInformer clusterinformer.ClusterInformer,
|
clusterInformer clusterinformer.ClusterInformer,
|
||||||
clusterClient clusterclient.ClusterInterface,
|
userLister iamv1alpha2listers.UserLister,
|
||||||
resyncPeriod time.Duration,
|
resyncPeriod time.Duration,
|
||||||
hostClusterName string,
|
hostClusterName string,
|
||||||
) *clusterController {
|
) *clusterController {
|
||||||
@@ -156,19 +161,20 @@ func NewClusterController(
|
|||||||
broadcaster.StartLogging(func(format string, args ...interface{}) {
|
broadcaster.StartLogging(func(format string, args ...interface{}) {
|
||||||
klog.Info(fmt.Sprintf(format, args))
|
klog.Info(fmt.Sprintf(format, args))
|
||||||
})
|
})
|
||||||
broadcaster.StartRecordingToSink(&corev1.EventSinkImpl{Interface: client.CoreV1().Events("")})
|
broadcaster.StartRecordingToSink(&corev1.EventSinkImpl{Interface: k8sClient.CoreV1().Events("")})
|
||||||
recorder := broadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cluster-controller"})
|
recorder := broadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cluster-controller"})
|
||||||
|
|
||||||
c := &clusterController{
|
c := &clusterController{
|
||||||
eventBroadcaster: broadcaster,
|
eventBroadcaster: broadcaster,
|
||||||
eventRecorder: recorder,
|
eventRecorder: recorder,
|
||||||
client: client,
|
k8sClient: k8sClient,
|
||||||
|
ksClient: ksClient,
|
||||||
hostConfig: config,
|
hostConfig: config,
|
||||||
clusterClient: clusterClient,
|
|
||||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "cluster"),
|
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "cluster"),
|
||||||
workerLoopPeriod: time.Second,
|
workerLoopPeriod: time.Second,
|
||||||
resyncPeriod: resyncPeriod,
|
resyncPeriod: resyncPeriod,
|
||||||
hostClusterName: hostClusterName,
|
hostClusterName: hostClusterName,
|
||||||
|
userLister: userLister,
|
||||||
}
|
}
|
||||||
c.clusterLister = clusterInformer.Lister()
|
c.clusterLister = clusterInformer.Lister()
|
||||||
c.clusterHasSynced = clusterInformer.Informer().HasSynced
|
c.clusterHasSynced = clusterInformer.Informer().HasSynced
|
||||||
@@ -213,7 +219,7 @@ func (c *clusterController) Run(workers int, stopCh <-chan struct{}) error {
|
|||||||
klog.Errorf("Error create host cluster, error %v", err)
|
klog.Errorf("Error create host cluster, error %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.probeClusters(); err != nil {
|
if err := c.resyncClusters(); err != nil {
|
||||||
klog.Errorf("failed to reconcile cluster ready status, err: %v", err)
|
klog.Errorf("failed to reconcile cluster ready status, err: %v", err)
|
||||||
}
|
}
|
||||||
}, c.resyncPeriod, stopCh)
|
}, c.resyncPeriod, stopCh)
|
||||||
@@ -256,7 +262,7 @@ func (c *clusterController) reconcileHostCluster() error {
|
|||||||
if len(clusters) == 0 {
|
if len(clusters) == 0 {
|
||||||
hostCluster.Spec.Connection.KubeConfig = hostKubeConfig
|
hostCluster.Spec.Connection.KubeConfig = hostKubeConfig
|
||||||
hostCluster.Name = c.hostClusterName
|
hostCluster.Name = c.hostClusterName
|
||||||
_, err = c.clusterClient.Create(context.TODO(), hostCluster, metav1.CreateOptions{})
|
_, err = c.ksClient.ClusterV1alpha1().Clusters().Create(context.TODO(), hostCluster, metav1.CreateOptions{})
|
||||||
return err
|
return err
|
||||||
} else if len(clusters) > 1 {
|
} else if len(clusters) > 1 {
|
||||||
return fmt.Errorf("there MUST not be more than one host clusters, while there are %d", len(clusters))
|
return fmt.Errorf("there MUST not be more than one host clusters, while there are %d", len(clusters))
|
||||||
@@ -280,18 +286,20 @@ func (c *clusterController) reconcileHostCluster() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update host cluster config
|
// update host cluster config
|
||||||
_, err = c.clusterClient.Update(context.TODO(), cluster, metav1.UpdateOptions{})
|
_, err = c.ksClient.ClusterV1alpha1().Clusters().Update(context.TODO(), cluster, metav1.UpdateOptions{})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clusterController) probeClusters() error {
|
func (c *clusterController) resyncClusters() error {
|
||||||
clusters, err := c.clusterLister.List(labels.Everything())
|
clusters, err := c.clusterLister.List(labels.Everything())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, cluster := range clusters {
|
for _, cluster := range clusters {
|
||||||
c.syncCluster(cluster.Name)
|
if err = c.syncCluster(cluster.Name); err != nil {
|
||||||
|
klog.Warningf("failed to sync cluster %s: %s", cluster.Name, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -328,7 +336,7 @@ func (c *clusterController) syncCluster(key string) error {
|
|||||||
// registering our finalizer.
|
// registering our finalizer.
|
||||||
if !sets.NewString(cluster.ObjectMeta.Finalizers...).Has(clusterv1alpha1.Finalizer) {
|
if !sets.NewString(cluster.ObjectMeta.Finalizers...).Has(clusterv1alpha1.Finalizer) {
|
||||||
cluster.ObjectMeta.Finalizers = append(cluster.ObjectMeta.Finalizers, clusterv1alpha1.Finalizer)
|
cluster.ObjectMeta.Finalizers = append(cluster.ObjectMeta.Finalizers, clusterv1alpha1.Finalizer)
|
||||||
if cluster, err = c.clusterClient.Update(context.TODO(), cluster, metav1.UpdateOptions{}); err != nil {
|
if cluster, err = c.ksClient.ClusterV1alpha1().Clusters().Update(context.TODO(), cluster, metav1.UpdateOptions{}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -338,17 +346,21 @@ func (c *clusterController) syncCluster(key string) error {
|
|||||||
// need to unJoin federation first, before there are
|
// need to unJoin federation first, before there are
|
||||||
// some cleanup work to do in member cluster which depends
|
// some cleanup work to do in member cluster which depends
|
||||||
// agent to proxy traffic
|
// agent to proxy traffic
|
||||||
err = c.unJoinFederation(nil, name)
|
if err = c.unJoinFederation(nil, name); err != nil {
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("Failed to unjoin federation for cluster %s, error %v", name, err)
|
klog.Errorf("Failed to unjoin federation for cluster %s, error %v", name, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cleanup after cluster has been deleted
|
||||||
|
if err := c.syncClusterMembers(nil, cluster); err != nil {
|
||||||
|
klog.Errorf("Failed to sync cluster members for %s: %v", name, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
// remove our cluster finalizer
|
// remove our cluster finalizer
|
||||||
finalizers := sets.NewString(cluster.ObjectMeta.Finalizers...)
|
finalizers := sets.NewString(cluster.ObjectMeta.Finalizers...)
|
||||||
finalizers.Delete(clusterv1alpha1.Finalizer)
|
finalizers.Delete(clusterv1alpha1.Finalizer)
|
||||||
cluster.ObjectMeta.Finalizers = finalizers.List()
|
cluster.ObjectMeta.Finalizers = finalizers.List()
|
||||||
if _, err = c.clusterClient.Update(context.TODO(), cluster, metav1.UpdateOptions{}); err != nil {
|
if _, err = c.ksClient.ClusterV1alpha1().Clusters().Update(context.TODO(), cluster, metav1.UpdateOptions{}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -407,7 +419,7 @@ func (c *clusterController) syncCluster(key string) error {
|
|||||||
}
|
}
|
||||||
c.updateClusterCondition(cluster, federationNotReadyCondition)
|
c.updateClusterCondition(cluster, federationNotReadyCondition)
|
||||||
|
|
||||||
_, err = c.clusterClient.Update(context.TODO(), cluster, metav1.UpdateOptions{})
|
_, err = c.ksClient.ClusterV1alpha1().Clusters().Update(context.TODO(), cluster, metav1.UpdateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Failed to update cluster status, %#v", err)
|
klog.Errorf("Failed to update cluster status, %#v", err)
|
||||||
}
|
}
|
||||||
@@ -496,8 +508,8 @@ func (c *clusterController) syncCluster(key string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(oldCluster, cluster) {
|
if !reflect.DeepEqual(oldCluster.Status, cluster.Status) {
|
||||||
_, err = c.clusterClient.Update(context.TODO(), cluster, metav1.UpdateOptions{})
|
_, err = c.ksClient.ClusterV1alpha1().Clusters().Update(context.TODO(), cluster, metav1.UpdateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Failed to update cluster status, %#v", err)
|
klog.Errorf("Failed to update cluster status, %#v", err)
|
||||||
return err
|
return err
|
||||||
@@ -508,6 +520,10 @@ func (c *clusterController) syncCluster(key string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = c.syncClusterMembers(clusterClient, cluster); err != nil {
|
||||||
|
return fmt.Errorf("failed to sync cluster membership for %s: %s", cluster.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,7 +557,7 @@ func (c *clusterController) setClusterNameInConfigMap(client kubernetes.Interfac
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *clusterController) checkIfClusterIsHostCluster(memberClusterNodes *v1.NodeList) bool {
|
func (c *clusterController) checkIfClusterIsHostCluster(memberClusterNodes *v1.NodeList) bool {
|
||||||
hostNodes, err := c.client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
|
hostNodes, err := c.k8sClient.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -786,3 +802,55 @@ func (c *clusterController) updateKubeConfigExpirationDateCondition(cluster *clu
|
|||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// syncClusterMembers Sync granted clusters for users periodically
|
||||||
|
func (c *clusterController) syncClusterMembers(clusterClient *kubernetes.Clientset, cluster *clusterv1alpha1.Cluster) error {
|
||||||
|
users, err := c.userLister.List(labels.Everything())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to list users: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
grantedUsers := sets.NewString()
|
||||||
|
clusterName := cluster.Name
|
||||||
|
if cluster.DeletionTimestamp.IsZero() {
|
||||||
|
list, err := clusterClient.RbacV1().ClusterRoleBindings().List(context.Background(),
|
||||||
|
metav1.ListOptions{LabelSelector: iamv1alpha2.UserReferenceLabel})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to list clusterrolebindings: %s", err)
|
||||||
|
}
|
||||||
|
for _, clusterRoleBinding := range list.Items {
|
||||||
|
for _, sub := range clusterRoleBinding.Subjects {
|
||||||
|
if sub.Kind == iamv1alpha2.ResourceKindUser {
|
||||||
|
grantedUsers.Insert(sub.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, user := range users {
|
||||||
|
user = user.DeepCopy()
|
||||||
|
grantedClustersAnnotation := user.Annotations[iamv1alpha2.GrantedClustersAnnotation]
|
||||||
|
var grantedClusters sets.String
|
||||||
|
if len(grantedClustersAnnotation) > 0 {
|
||||||
|
grantedClusters = sets.NewString(strings.Split(grantedClustersAnnotation, ",")...)
|
||||||
|
} else {
|
||||||
|
grantedClusters = sets.NewString()
|
||||||
|
}
|
||||||
|
if grantedUsers.Has(user.Name) && !grantedClusters.Has(clusterName) {
|
||||||
|
grantedClusters.Insert(clusterName)
|
||||||
|
} else if !grantedUsers.Has(user.Name) && grantedClusters.Has(clusterName) {
|
||||||
|
grantedClusters.Delete(clusterName)
|
||||||
|
}
|
||||||
|
grantedClustersAnnotation = strings.Join(grantedClusters.List(), ",")
|
||||||
|
if user.Annotations[iamv1alpha2.GrantedClustersAnnotation] != grantedClustersAnnotation {
|
||||||
|
if user.Annotations == nil {
|
||||||
|
user.Annotations = make(map[string]string, 0)
|
||||||
|
}
|
||||||
|
user.Annotations[iamv1alpha2.GrantedClustersAnnotation] = grantedClustersAnnotation
|
||||||
|
if _, err := c.ksClient.IamV1alpha2().Users().Update(context.Background(), user, metav1.UpdateOptions{}); err != nil {
|
||||||
|
return fmt.Errorf("failed to update user %s: %s", user.Name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ import (
|
|||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
|
||||||
"kubesphere.io/kubesphere/pkg/models/openpitrix"
|
|
||||||
|
|
||||||
quotav1alpha2 "kubesphere.io/api/quota/v1alpha2"
|
quotav1alpha2 "kubesphere.io/api/quota/v1alpha2"
|
||||||
tenantv1alpha2 "kubesphere.io/api/tenant/v1alpha2"
|
tenantv1alpha2 "kubesphere.io/api/tenant/v1alpha2"
|
||||||
|
|
||||||
@@ -43,6 +41,8 @@ import (
|
|||||||
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||||
"kubesphere.io/kubesphere/pkg/informers"
|
"kubesphere.io/kubesphere/pkg/informers"
|
||||||
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/iam/im"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/openpitrix"
|
||||||
resourcev1alpha3 "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource"
|
resourcev1alpha3 "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource"
|
||||||
"kubesphere.io/kubesphere/pkg/models/tenant"
|
"kubesphere.io/kubesphere/pkg/models/tenant"
|
||||||
servererr "kubesphere.io/kubesphere/pkg/server/errors"
|
servererr "kubesphere.io/kubesphere/pkg/server/errors"
|
||||||
@@ -60,7 +60,7 @@ type tenantHandler struct {
|
|||||||
|
|
||||||
func NewTenantHandler(factory informers.InformerFactory, k8sclient kubernetes.Interface, ksclient kubesphere.Interface,
|
func NewTenantHandler(factory informers.InformerFactory, k8sclient kubernetes.Interface, ksclient kubesphere.Interface,
|
||||||
evtsClient events.Client, loggingClient logging.Client, auditingclient auditing.Client,
|
evtsClient events.Client, loggingClient logging.Client, auditingclient auditing.Client,
|
||||||
am am.AccessManagementInterface, authorizer authorizer.Authorizer,
|
am am.AccessManagementInterface, im im.IdentityManagementInterface, authorizer authorizer.Authorizer,
|
||||||
monitoringclient monitoringclient.Interface, resourceGetter *resourcev1alpha3.ResourceGetter,
|
monitoringclient monitoringclient.Interface, resourceGetter *resourcev1alpha3.ResourceGetter,
|
||||||
meteringOptions *meteringclient.Options, opClient openpitrix.Interface) *tenantHandler {
|
meteringOptions *meteringclient.Options, opClient openpitrix.Interface) *tenantHandler {
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ func NewTenantHandler(factory informers.InformerFactory, k8sclient kubernetes.In
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &tenantHandler{
|
return &tenantHandler{
|
||||||
tenant: tenant.New(factory, k8sclient, ksclient, evtsClient, loggingClient, auditingclient, am, authorizer, monitoringclient, resourceGetter, opClient),
|
tenant: tenant.New(factory, k8sclient, ksclient, evtsClient, loggingClient, auditingclient, am, im, authorizer, monitoringclient, resourceGetter, opClient),
|
||||||
meteringOptions: meteringOptions,
|
meteringOptions: meteringOptions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -557,8 +557,8 @@ func (h *tenantHandler) ListClusters(r *restful.Request, response *restful.Respo
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := h.tenant.ListClusters(user)
|
queryParam := query.ParseQueryParameter(r)
|
||||||
|
result, err := h.tenant.ListClusters(user, queryParam)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
if errors.IsNotFound(err) {
|
if errors.IsNotFound(err) {
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ package v1alpha2
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"kubesphere.io/kubesphere/pkg/models/openpitrix"
|
|
||||||
|
|
||||||
"github.com/emicklei/go-restful"
|
"github.com/emicklei/go-restful"
|
||||||
restfulspec "github.com/emicklei/go-restful-openapi"
|
restfulspec "github.com/emicklei/go-restful-openapi"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
@@ -42,8 +40,10 @@ import (
|
|||||||
"kubesphere.io/kubesphere/pkg/informers"
|
"kubesphere.io/kubesphere/pkg/informers"
|
||||||
"kubesphere.io/kubesphere/pkg/models"
|
"kubesphere.io/kubesphere/pkg/models"
|
||||||
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/iam/im"
|
||||||
"kubesphere.io/kubesphere/pkg/models/metering"
|
"kubesphere.io/kubesphere/pkg/models/metering"
|
||||||
"kubesphere.io/kubesphere/pkg/models/monitoring"
|
"kubesphere.io/kubesphere/pkg/models/monitoring"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/openpitrix"
|
||||||
resourcev1alpha3 "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource"
|
resourcev1alpha3 "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource"
|
||||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/auditing"
|
"kubesphere.io/kubesphere/pkg/simple/client/auditing"
|
||||||
@@ -65,12 +65,12 @@ func Resource(resource string) schema.GroupResource {
|
|||||||
|
|
||||||
func AddToContainer(c *restful.Container, factory informers.InformerFactory, k8sclient kubernetes.Interface,
|
func AddToContainer(c *restful.Container, factory informers.InformerFactory, k8sclient kubernetes.Interface,
|
||||||
ksclient kubesphere.Interface, evtsClient events.Client, loggingClient logging.Client,
|
ksclient kubesphere.Interface, evtsClient events.Client, loggingClient logging.Client,
|
||||||
auditingclient auditing.Client, am am.AccessManagementInterface, authorizer authorizer.Authorizer,
|
auditingclient auditing.Client, am am.AccessManagementInterface, im im.IdentityManagementInterface, authorizer authorizer.Authorizer,
|
||||||
monitoringclient monitoringclient.Interface, cache cache.Cache, meteringOptions *meteringclient.Options, opClient openpitrix.Interface) error {
|
monitoringclient monitoringclient.Interface, cache cache.Cache, meteringOptions *meteringclient.Options, opClient openpitrix.Interface) error {
|
||||||
mimePatch := []string{restful.MIME_JSON, runtime.MimeMergePatchJson, runtime.MimeJsonPatchJson}
|
mimePatch := []string{restful.MIME_JSON, runtime.MimeMergePatchJson, runtime.MimeJsonPatchJson}
|
||||||
|
|
||||||
ws := runtime.NewWebService(GroupVersion)
|
ws := runtime.NewWebService(GroupVersion)
|
||||||
handler := NewTenantHandler(factory, k8sclient, ksclient, evtsClient, loggingClient, auditingclient, am, authorizer, monitoringclient, resourcev1alpha3.NewResourceGetter(factory, cache), meteringOptions, opClient)
|
handler := NewTenantHandler(factory, k8sclient, ksclient, evtsClient, loggingClient, auditingclient, am, im, authorizer, monitoringclient, resourcev1alpha3.NewResourceGetter(factory, cache), meteringOptions, opClient)
|
||||||
|
|
||||||
ws.Route(ws.GET("/clusters").
|
ws.Route(ws.GET("/clusters").
|
||||||
To(handler.ListClusters).
|
To(handler.ListClusters).
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ import (
|
|||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
|
||||||
"kubesphere.io/kubesphere/pkg/models/openpitrix"
|
|
||||||
|
|
||||||
"kubesphere.io/kubesphere/pkg/api"
|
"kubesphere.io/kubesphere/pkg/api"
|
||||||
"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
|
"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
|
||||||
"kubesphere.io/kubesphere/pkg/apiserver/query"
|
"kubesphere.io/kubesphere/pkg/apiserver/query"
|
||||||
@@ -33,6 +31,8 @@ import (
|
|||||||
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||||
"kubesphere.io/kubesphere/pkg/informers"
|
"kubesphere.io/kubesphere/pkg/informers"
|
||||||
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/iam/im"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/openpitrix"
|
||||||
resourcev1alpha3 "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource"
|
resourcev1alpha3 "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource"
|
||||||
"kubesphere.io/kubesphere/pkg/models/tenant"
|
"kubesphere.io/kubesphere/pkg/models/tenant"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/auditing"
|
"kubesphere.io/kubesphere/pkg/simple/client/auditing"
|
||||||
@@ -49,7 +49,7 @@ type tenantHandler struct {
|
|||||||
|
|
||||||
func newTenantHandler(factory informers.InformerFactory, k8sclient kubernetes.Interface, ksclient kubesphere.Interface,
|
func newTenantHandler(factory informers.InformerFactory, k8sclient kubernetes.Interface, ksclient kubesphere.Interface,
|
||||||
evtsClient events.Client, loggingClient logging.Client, auditingclient auditing.Client,
|
evtsClient events.Client, loggingClient logging.Client, auditingclient auditing.Client,
|
||||||
am am.AccessManagementInterface, authorizer authorizer.Authorizer,
|
am am.AccessManagementInterface, im im.IdentityManagementInterface, authorizer authorizer.Authorizer,
|
||||||
monitoringclient monitoringclient.Interface, resourceGetter *resourcev1alpha3.ResourceGetter,
|
monitoringclient monitoringclient.Interface, resourceGetter *resourcev1alpha3.ResourceGetter,
|
||||||
meteringOptions *meteringclient.Options, opClient openpitrix.Interface) *tenantHandler {
|
meteringOptions *meteringclient.Options, opClient openpitrix.Interface) *tenantHandler {
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ func newTenantHandler(factory informers.InformerFactory, k8sclient kubernetes.In
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &tenantHandler{
|
return &tenantHandler{
|
||||||
tenant: tenant.New(factory, k8sclient, ksclient, evtsClient, loggingClient, auditingclient, am, authorizer, monitoringclient, resourceGetter, opClient),
|
tenant: tenant.New(factory, k8sclient, ksclient, evtsClient, loggingClient, auditingclient, am, im, authorizer, monitoringclient, resourceGetter, opClient),
|
||||||
meteringOptions: meteringOptions,
|
meteringOptions: meteringOptions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ package v1alpha3
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"kubesphere.io/kubesphere/pkg/models/openpitrix"
|
|
||||||
|
|
||||||
"github.com/emicklei/go-restful"
|
"github.com/emicklei/go-restful"
|
||||||
restfulspec "github.com/emicklei/go-restful-openapi"
|
restfulspec "github.com/emicklei/go-restful-openapi"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
@@ -39,6 +37,8 @@ import (
|
|||||||
"kubesphere.io/kubesphere/pkg/kapis/tenant/v1alpha2"
|
"kubesphere.io/kubesphere/pkg/kapis/tenant/v1alpha2"
|
||||||
"kubesphere.io/kubesphere/pkg/models"
|
"kubesphere.io/kubesphere/pkg/models"
|
||||||
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/iam/im"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/openpitrix"
|
||||||
resourcev1alpha3 "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource"
|
resourcev1alpha3 "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource"
|
||||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/auditing"
|
"kubesphere.io/kubesphere/pkg/simple/client/auditing"
|
||||||
@@ -60,14 +60,13 @@ func Resource(resource string) schema.GroupResource {
|
|||||||
|
|
||||||
func AddToContainer(c *restful.Container, factory informers.InformerFactory, k8sclient kubernetes.Interface,
|
func AddToContainer(c *restful.Container, factory informers.InformerFactory, k8sclient kubernetes.Interface,
|
||||||
ksclient kubesphere.Interface, evtsClient events.Client, loggingClient logging.Client,
|
ksclient kubesphere.Interface, evtsClient events.Client, loggingClient logging.Client,
|
||||||
auditingclient auditing.Client, am am.AccessManagementInterface, authorizer authorizer.Authorizer,
|
auditingclient auditing.Client, am am.AccessManagementInterface, im im.IdentityManagementInterface, authorizer authorizer.Authorizer,
|
||||||
monitoringclient monitoringclient.Interface, cache cache.Cache, meteringOptions *meteringclient.Options,
|
monitoringclient monitoringclient.Interface, cache cache.Cache, meteringOptions *meteringclient.Options, opClient openpitrix.Interface) error {
|
||||||
opClient openpitrix.Interface) error {
|
|
||||||
mimePatch := []string{restful.MIME_JSON, runtime.MimeMergePatchJson, runtime.MimeJsonPatchJson}
|
mimePatch := []string{restful.MIME_JSON, runtime.MimeMergePatchJson, runtime.MimeJsonPatchJson}
|
||||||
|
|
||||||
ws := runtime.NewWebService(GroupVersion)
|
ws := runtime.NewWebService(GroupVersion)
|
||||||
v1alpha2Handler := v1alpha2.NewTenantHandler(factory, k8sclient, ksclient, evtsClient, loggingClient, auditingclient, am, authorizer, monitoringclient, resourcev1alpha3.NewResourceGetter(factory, cache), meteringOptions, opClient)
|
v1alpha2Handler := v1alpha2.NewTenantHandler(factory, k8sclient, ksclient, evtsClient, loggingClient, auditingclient, am, im, authorizer, monitoringclient, resourcev1alpha3.NewResourceGetter(factory, cache), meteringOptions, opClient)
|
||||||
handler := newTenantHandler(factory, k8sclient, ksclient, evtsClient, loggingClient, auditingclient, am, authorizer, monitoringclient, resourcev1alpha3.NewResourceGetter(factory, cache), meteringOptions, opClient)
|
handler := newTenantHandler(factory, k8sclient, ksclient, evtsClient, loggingClient, auditingclient, am, im, authorizer, monitoringclient, resourcev1alpha3.NewResourceGetter(factory, cache), meteringOptions, opClient)
|
||||||
|
|
||||||
ws.Route(ws.POST("/workspacetemplates").
|
ws.Route(ws.POST("/workspacetemplates").
|
||||||
To(v1alpha2Handler.CreateWorkspaceTemplate).
|
To(v1alpha2Handler.CreateWorkspaceTemplate).
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
|
"k8s.io/klog"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
|
||||||
@@ -150,33 +153,13 @@ func DefaultObjectMetaFilter(item metav1.ObjectMeta, filter query.Filter) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func labelMatch(labels map[string]string, filter string) bool {
|
func labelMatch(m map[string]string, filter string) bool {
|
||||||
fields := strings.SplitN(filter, "=", 2)
|
labelSelector, err := labels.Parse(filter)
|
||||||
var key, value string
|
if err != nil {
|
||||||
var opposite bool
|
klog.Warningf("invalid labelSelector %s: %s", filter, err)
|
||||||
if len(fields) == 2 {
|
return false
|
||||||
key = fields[0]
|
|
||||||
if strings.HasSuffix(key, "!") {
|
|
||||||
key = strings.TrimSuffix(key, "!")
|
|
||||||
opposite = true
|
|
||||||
}
|
|
||||||
value = fields[1]
|
|
||||||
} else {
|
|
||||||
key = fields[0]
|
|
||||||
value = "*"
|
|
||||||
}
|
}
|
||||||
for k, v := range labels {
|
return labelSelector.Matches(labels.Set(m))
|
||||||
if opposite {
|
|
||||||
if (k == key) && v != value {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (k == key) && (value == "*" || v == value) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func objectsToInterfaces(objs []runtime.Object) []interface{} {
|
func objectsToInterfaces(objs []runtime.Object) []interface{} {
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
@@ -40,6 +41,8 @@ import (
|
|||||||
tenantv1alpha2 "kubesphere.io/api/tenant/v1alpha2"
|
tenantv1alpha2 "kubesphere.io/api/tenant/v1alpha2"
|
||||||
typesv1beta1 "kubesphere.io/api/types/v1beta1"
|
typesv1beta1 "kubesphere.io/api/types/v1beta1"
|
||||||
|
|
||||||
|
iamv1alpha2 "kubesphere.io/api/iam/v1alpha2"
|
||||||
|
|
||||||
"kubesphere.io/kubesphere/pkg/api"
|
"kubesphere.io/kubesphere/pkg/api"
|
||||||
auditingv1alpha1 "kubesphere.io/kubesphere/pkg/api/auditing/v1alpha1"
|
auditingv1alpha1 "kubesphere.io/kubesphere/pkg/api/auditing/v1alpha1"
|
||||||
eventsv1alpha1 "kubesphere.io/kubesphere/pkg/api/events/v1alpha1"
|
eventsv1alpha1 "kubesphere.io/kubesphere/pkg/api/events/v1alpha1"
|
||||||
@@ -53,6 +56,7 @@ import (
|
|||||||
"kubesphere.io/kubesphere/pkg/models/auditing"
|
"kubesphere.io/kubesphere/pkg/models/auditing"
|
||||||
"kubesphere.io/kubesphere/pkg/models/events"
|
"kubesphere.io/kubesphere/pkg/models/events"
|
||||||
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/iam/im"
|
||||||
"kubesphere.io/kubesphere/pkg/models/logging"
|
"kubesphere.io/kubesphere/pkg/models/logging"
|
||||||
"kubesphere.io/kubesphere/pkg/models/metering"
|
"kubesphere.io/kubesphere/pkg/models/metering"
|
||||||
"kubesphere.io/kubesphere/pkg/models/monitoring"
|
"kubesphere.io/kubesphere/pkg/models/monitoring"
|
||||||
@@ -92,7 +96,7 @@ type Interface interface {
|
|||||||
DeleteNamespace(workspace, namespace string) error
|
DeleteNamespace(workspace, namespace string) error
|
||||||
UpdateNamespace(workspace string, namespace *corev1.Namespace) (*corev1.Namespace, error)
|
UpdateNamespace(workspace string, namespace *corev1.Namespace) (*corev1.Namespace, error)
|
||||||
PatchNamespace(workspace string, namespace *corev1.Namespace) (*corev1.Namespace, error)
|
PatchNamespace(workspace string, namespace *corev1.Namespace) (*corev1.Namespace, error)
|
||||||
ListClusters(info user.Info) (*api.ListResult, error)
|
ListClusters(info user.Info, queryParam *query.Query) (*api.ListResult, error)
|
||||||
Metering(user user.Info, queryParam *meteringv1alpha1.Query, priceInfo meteringclient.PriceInfo) (monitoring.Metrics, error)
|
Metering(user user.Info, queryParam *meteringv1alpha1.Query, priceInfo meteringclient.PriceInfo) (monitoring.Metrics, error)
|
||||||
MeteringHierarchy(user user.Info, queryParam *meteringv1alpha1.Query, priceInfo meteringclient.PriceInfo) (metering.ResourceStatistic, error)
|
MeteringHierarchy(user user.Info, queryParam *meteringv1alpha1.Query, priceInfo meteringclient.PriceInfo) (metering.ResourceStatistic, error)
|
||||||
CreateWorkspaceResourceQuota(workspace string, resourceQuota *quotav1alpha2.ResourceQuota) (*quotav1alpha2.ResourceQuota, error)
|
CreateWorkspaceResourceQuota(workspace string, resourceQuota *quotav1alpha2.ResourceQuota) (*quotav1alpha2.ResourceQuota, error)
|
||||||
@@ -103,6 +107,7 @@ type Interface interface {
|
|||||||
|
|
||||||
type tenantOperator struct {
|
type tenantOperator struct {
|
||||||
am am.AccessManagementInterface
|
am am.AccessManagementInterface
|
||||||
|
im im.IdentityManagementInterface
|
||||||
authorizer authorizer.Authorizer
|
authorizer authorizer.Authorizer
|
||||||
k8sclient kubernetes.Interface
|
k8sclient kubernetes.Interface
|
||||||
ksclient kubesphere.Interface
|
ksclient kubesphere.Interface
|
||||||
@@ -114,9 +119,10 @@ type tenantOperator struct {
|
|||||||
opRelease openpitrix.ReleaseInterface
|
opRelease openpitrix.ReleaseInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(informers informers.InformerFactory, k8sclient kubernetes.Interface, ksclient kubesphere.Interface, evtsClient eventsclient.Client, loggingClient loggingclient.Client, auditingclient auditingclient.Client, am am.AccessManagementInterface, authorizer authorizer.Authorizer, monitoringclient monitoringclient.Interface, resourceGetter *resourcev1alpha3.ResourceGetter, opClient openpitrix.Interface) Interface {
|
func New(informers informers.InformerFactory, k8sclient kubernetes.Interface, ksclient kubesphere.Interface, evtsClient eventsclient.Client, loggingClient loggingclient.Client, auditingclient auditingclient.Client, am am.AccessManagementInterface, im im.IdentityManagementInterface, authorizer authorizer.Authorizer, monitoringclient monitoringclient.Interface, resourceGetter *resourcev1alpha3.ResourceGetter, opClient openpitrix.Interface) Interface {
|
||||||
return &tenantOperator{
|
return &tenantOperator{
|
||||||
am: am,
|
am: am,
|
||||||
|
im: im,
|
||||||
authorizer: authorizer,
|
authorizer: authorizer,
|
||||||
resourceGetter: resourcesv1alpha3.NewResourceGetter(informers, nil),
|
resourceGetter: resourcesv1alpha3.NewResourceGetter(informers, nil),
|
||||||
k8sclient: k8sclient,
|
k8sclient: k8sclient,
|
||||||
@@ -498,7 +504,7 @@ func (t *tenantOperator) ListWorkspaceClusters(workspaceName string) (*api.ListR
|
|||||||
for _, cluster := range workspace.Spec.Placement.Clusters {
|
for _, cluster := range workspace.Spec.Placement.Clusters {
|
||||||
obj, err := t.resourceGetter.Get(clusterv1alpha1.ResourcesPluralCluster, "", cluster.Name)
|
obj, err := t.resourceGetter.Get(clusterv1alpha1.ResourcesPluralCluster, "", cluster.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Error(err)
|
klog.Warning(err)
|
||||||
if errors.IsNotFound(err) {
|
if errors.IsNotFound(err) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -527,89 +533,69 @@ func (t *tenantOperator) ListWorkspaceClusters(workspaceName string) (*api.ListR
|
|||||||
return &api.ListResult{Items: []interface{}{}, TotalItems: 0}, nil
|
return &api.ListResult{Items: []interface{}{}, TotalItems: 0}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tenantOperator) ListClusters(user user.Info) (*api.ListResult, error) {
|
func (t *tenantOperator) ListClusters(user user.Info, queryParam *query.Query) (*api.ListResult, error) {
|
||||||
|
|
||||||
listClustersInGlobalScope := authorizer.AttributesRecord{
|
listClustersInGlobalScope := authorizer.AttributesRecord{
|
||||||
User: user,
|
User: user,
|
||||||
Verb: "list",
|
Verb: "list",
|
||||||
|
APIGroup: "cluster.kubesphere.io",
|
||||||
Resource: "clusters",
|
Resource: "clusters",
|
||||||
ResourceScope: request.GlobalScope,
|
ResourceScope: request.GlobalScope,
|
||||||
ResourceRequest: true,
|
ResourceRequest: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedListClustersInGlobalScope, _, err := t.authorizer.Authorize(listClustersInGlobalScope)
|
allowedListClustersInGlobalScope, _, err := t.authorizer.Authorize(listClustersInGlobalScope)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Error(err)
|
return nil, fmt.Errorf("failed to authorize: %s", err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
listWorkspacesInGlobalScope := authorizer.AttributesRecord{
|
if allowedListClustersInGlobalScope == authorizer.DecisionAllow {
|
||||||
User: user,
|
return t.resourceGetter.List(clusterv1alpha1.ResourcesPluralCluster, "", queryParam)
|
||||||
Verb: "list",
|
|
||||||
Resource: "workspaces",
|
|
||||||
ResourceScope: request.GlobalScope,
|
|
||||||
ResourceRequest: true,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedListWorkspacesInGlobalScope, _, err := t.authorizer.Authorize(listWorkspacesInGlobalScope)
|
userDetail, err := t.im.DescribeUser(user.GetName())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Error(err)
|
return nil, fmt.Errorf("failed to describe user: %s", err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if allowedListClustersInGlobalScope == authorizer.DecisionAllow ||
|
grantedClustersAnnotation := userDetail.Annotations[iamv1alpha2.GrantedClustersAnnotation]
|
||||||
allowedListWorkspacesInGlobalScope == authorizer.DecisionAllow {
|
var grantedClusters sets.String
|
||||||
result, err := t.resourceGetter.List(clusterv1alpha1.ResourcesPluralCluster, "", query.New())
|
if len(grantedClustersAnnotation) > 0 {
|
||||||
|
grantedClusters = sets.NewString(strings.Split(grantedClustersAnnotation, ",")...)
|
||||||
|
} else {
|
||||||
|
grantedClusters = sets.NewString()
|
||||||
|
}
|
||||||
|
var clusters []*clusterv1alpha1.Cluster
|
||||||
|
for _, grantedCluster := range grantedClusters.List() {
|
||||||
|
obj, err := t.resourceGetter.Get(clusterv1alpha1.ResourcesPluralCluster, "", grantedCluster)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Error(err)
|
if errors.IsNotFound(err) {
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
workspaceRoleBindings, err := t.am.ListWorkspaceRoleBindings(user.GetName(), user.GetGroups(), "")
|
|
||||||
|
|
||||||
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.DescribeWorkspaceTemplate(workspaceName)
|
|
||||||
if err != nil {
|
|
||||||
klog.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, grantedCluster := range workspace.Spec.Placement.Clusters {
|
|
||||||
// skip if cluster exist
|
|
||||||
if clusters[grantedCluster.Name] != nil {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
obj, err := t.resourceGetter.Get(clusterv1alpha1.ResourcesPluralCluster, "", grantedCluster.Name)
|
return nil, fmt.Errorf("failed to fetch cluster: %s", err)
|
||||||
if err != nil {
|
|
||||||
klog.Error(err)
|
|
||||||
if errors.IsNotFound(err) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
cluster := obj.(*clusterv1alpha1.Cluster)
|
|
||||||
clusters[cluster.Name] = cluster
|
|
||||||
}
|
}
|
||||||
|
cluster := obj.(*clusterv1alpha1.Cluster)
|
||||||
|
clusters = append(clusters, cluster)
|
||||||
}
|
}
|
||||||
|
|
||||||
items := make([]interface{}, 0)
|
items := make([]runtime.Object, 0)
|
||||||
for _, cluster := range clusters {
|
for _, cluster := range clusters {
|
||||||
items = append(items, cluster)
|
items = append(items, cluster)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &api.ListResult{Items: items, TotalItems: len(items)}, nil
|
// apply additional labelSelector
|
||||||
|
if queryParam.LabelSelector != "" {
|
||||||
|
queryParam.Filters[query.FieldLabel] = query.Value(queryParam.LabelSelector)
|
||||||
|
}
|
||||||
|
|
||||||
|
// use default pagination search logic
|
||||||
|
result := resources.DefaultList(items, queryParam, func(left runtime.Object, right runtime.Object, field query.Field) bool {
|
||||||
|
return resources.DefaultObjectMetaCompare(left.(*clusterv1alpha1.Cluster).ObjectMeta, right.(*clusterv1alpha1.Cluster).ObjectMeta, field)
|
||||||
|
}, func(workspace runtime.Object, filter query.Filter) bool {
|
||||||
|
return resources.DefaultObjectMetaFilter(workspace.(*clusterv1alpha1.Cluster).ObjectMeta, filter)
|
||||||
|
})
|
||||||
|
|
||||||
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tenantOperator) DeleteWorkspaceTemplate(workspace string, opts metav1.DeleteOptions) error {
|
func (t *tenantOperator) DeleteWorkspaceTemplate(workspace string, opts metav1.DeleteOptions) error {
|
||||||
|
|||||||
@@ -544,5 +544,5 @@ func prepare() Interface {
|
|||||||
amOperator := am.NewOperator(ksClient, k8sClient, fakeInformerFactory, nil)
|
amOperator := am.NewOperator(ksClient, k8sClient, fakeInformerFactory, nil)
|
||||||
authorizer := rbac.NewRBACAuthorizer(amOperator)
|
authorizer := rbac.NewRBACAuthorizer(amOperator)
|
||||||
|
|
||||||
return New(fakeInformerFactory, k8sClient, ksClient, nil, nil, nil, amOperator, authorizer, nil, nil, nil)
|
return New(fakeInformerFactory, k8sClient, ksClient, nil, nil, nil, amOperator, nil, authorizer, nil, nil, nil)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ const (
|
|||||||
GlobalRoleAnnotation = "iam.kubesphere.io/globalrole"
|
GlobalRoleAnnotation = "iam.kubesphere.io/globalrole"
|
||||||
WorkspaceRoleAnnotation = "iam.kubesphere.io/workspacerole"
|
WorkspaceRoleAnnotation = "iam.kubesphere.io/workspacerole"
|
||||||
ClusterRoleAnnotation = "iam.kubesphere.io/clusterrole"
|
ClusterRoleAnnotation = "iam.kubesphere.io/clusterrole"
|
||||||
|
GrantedClustersAnnotation = "iam.kubesphere.io/granted-clusters"
|
||||||
UninitializedAnnotation = "iam.kubesphere.io/uninitialized"
|
UninitializedAnnotation = "iam.kubesphere.io/uninitialized"
|
||||||
LastPasswordChangeTimeAnnotation = "iam.kubesphere.io/last-password-change-time"
|
LastPasswordChangeTimeAnnotation = "iam.kubesphere.io/last-password-change-time"
|
||||||
RoleAnnotation = "iam.kubesphere.io/role"
|
RoleAnnotation = "iam.kubesphere.io/role"
|
||||||
|
|||||||
Reference in New Issue
Block a user