@@ -1,225 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
package tenant
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/gocraft/dbr"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/db"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
"kubesphere.io/kubesphere/pkg/models/devops"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
dsClient "kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type DevOpsProjectOperator interface {
|
||||
ListDevOpsProjects(workspace, username string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error)
|
||||
CreateDevOpsProject(username string, workspace string, req *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, error)
|
||||
GetDevOpsProjectsCount(username string) (uint32, error)
|
||||
DeleteDevOpsProject(projectId, username string) error
|
||||
}
|
||||
|
||||
type devopsProjectOperator struct {
|
||||
ksProjectOperator devops.ProjectOperator
|
||||
db *mysql.Database
|
||||
dsProject dsClient.ProjectOperator
|
||||
}
|
||||
|
||||
func newProjectOperator(operator devops.ProjectOperator, db *mysql.Database, client dsClient.ProjectOperator) DevOpsProjectOperator {
|
||||
return &devopsProjectOperator{
|
||||
ksProjectOperator: operator,
|
||||
db: db,
|
||||
dsProject: client,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *devopsProjectOperator) ListDevOpsProjects(workspace, username string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error) {
|
||||
|
||||
query := o.db.Select(devops.GetColumnsFromStructWithPrefix(devops.DevOpsProjectTableName, v1alpha2.DevOpsProject{})...).
|
||||
From(devops.DevOpsProjectTableName)
|
||||
var sqconditions []dbr.Builder
|
||||
|
||||
sqconditions = append(sqconditions, db.Eq(devops.DevOpsProjectWorkSpaceColumn, workspace))
|
||||
|
||||
switch username {
|
||||
case devops.KS_ADMIN:
|
||||
default:
|
||||
onCondition := fmt.Sprintf("%s = %s", devops.ProjectMembershipProjectIdColumn, devops.DevOpsProjectIdColumn)
|
||||
query.Join(devops.ProjectMembershipTableName, onCondition)
|
||||
sqconditions = append(sqconditions, db.Eq(devops.ProjectMembershipUsernameColumn, username))
|
||||
sqconditions = append(sqconditions, db.Eq(
|
||||
devops.ProjectMembershipTableName+"."+devops.StatusColumn, devops.StatusActive))
|
||||
}
|
||||
|
||||
sqconditions = append(sqconditions, db.Eq(
|
||||
devops.DevOpsProjectTableName+"."+devops.StatusColumn, devops.StatusActive))
|
||||
if keyword := conditions.Match["keyword"]; keyword != "" {
|
||||
sqconditions = append(sqconditions, db.Like(devops.DevOpsProjectNameColumn, keyword))
|
||||
}
|
||||
projects := make([]*v1alpha2.DevOpsProject, 0)
|
||||
|
||||
if len(sqconditions) > 0 {
|
||||
query.Where(db.And(sqconditions...))
|
||||
}
|
||||
switch orderBy {
|
||||
case "name":
|
||||
if reverse {
|
||||
query.OrderDesc(devops.DevOpsProjectNameColumn)
|
||||
} else {
|
||||
query.OrderAsc(devops.DevOpsProjectNameColumn)
|
||||
}
|
||||
default:
|
||||
if reverse {
|
||||
query.OrderAsc(devops.DevOpsProjectCreateTimeColumn)
|
||||
} else {
|
||||
query.OrderDesc(devops.DevOpsProjectCreateTimeColumn)
|
||||
}
|
||||
|
||||
}
|
||||
query.Limit(uint64(limit))
|
||||
query.Offset(uint64(offset))
|
||||
_, err := query.Load(&projects)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
count, err := query.Count()
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
result := make([]interface{}, 0)
|
||||
for _, v := range projects {
|
||||
result = append(result, v)
|
||||
}
|
||||
|
||||
return &models.PageableResponse{Items: result, TotalCount: int(count)}, nil
|
||||
}
|
||||
|
||||
func (o *devopsProjectOperator) GetDevOpsProjectsCount(username string) (uint32, error) {
|
||||
|
||||
query := o.db.Select(devops.GetColumnsFromStructWithPrefix(devops.DevOpsProjectTableName, v1alpha2.DevOpsProject{})...).
|
||||
From(devops.DevOpsProjectTableName)
|
||||
var sqconditions []dbr.Builder
|
||||
|
||||
if username != devops.KS_ADMIN {
|
||||
onCondition := fmt.Sprintf("%s = %s", devops.ProjectMembershipProjectIdColumn, devops.DevOpsProjectIdColumn)
|
||||
query.Join(devops.ProjectMembershipTableName, onCondition)
|
||||
sqconditions = append(sqconditions, db.Eq(devops.ProjectMembershipUsernameColumn, username))
|
||||
sqconditions = append(sqconditions, db.Eq(
|
||||
devops.ProjectMembershipTableName+"."+devops.StatusColumn, devops.StatusActive))
|
||||
}
|
||||
|
||||
sqconditions = append(sqconditions, db.Eq(
|
||||
devops.DevOpsProjectTableName+"."+devops.StatusColumn, devops.StatusActive))
|
||||
if len(sqconditions) > 0 {
|
||||
query.Where(db.And(sqconditions...))
|
||||
}
|
||||
count, err := query.Count()
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return 0, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (o *devopsProjectOperator) DeleteDevOpsProject(projectId, username string) error {
|
||||
err := o.ksProjectOperator.CheckProjectUserInRole(username, projectId, []string{dsClient.ProjectOwner})
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return restful.NewError(http.StatusForbidden, err.Error())
|
||||
}
|
||||
|
||||
err = o.dsProject.DeleteDevOpsProject(projectId)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return err
|
||||
}
|
||||
_, err = o.db.DeleteFrom(devops.ProjectMembershipTableName).
|
||||
Where(db.Eq(devops.ProjectMembershipProjectIdColumn, projectId)).Exec()
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return err
|
||||
}
|
||||
_, err = o.db.Update(devops.DevOpsProjectTableName).
|
||||
Set(devops.StatusColumn, devops.StatusDeleted).
|
||||
Where(db.Eq(devops.DevOpsProjectIdColumn, projectId)).Exec()
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return err
|
||||
}
|
||||
project := &v1alpha2.DevOpsProject{}
|
||||
err = o.db.Select(devops.DevOpsProjectColumns...).
|
||||
From(devops.DevOpsProjectTableName).
|
||||
Where(db.Eq(devops.DevOpsProjectIdColumn, projectId)).
|
||||
LoadOne(project)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *devopsProjectOperator) CreateDevOpsProject(username string, workspace string, req *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, error) {
|
||||
|
||||
project := devops.NewDevOpsProject(req.Name, req.Description, username, req.Extra, workspace)
|
||||
_, err := o.dsProject.CreateDevOpsProject(username, project)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
_, err = o.db.InsertInto(devops.DevOpsProjectTableName).
|
||||
Columns(devops.DevOpsProjectColumns...).Record(project).Exec()
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
projectMembership := devops.NewDevOpsProjectMemberShip(username, project.ProjectId, dsClient.ProjectOwner, username)
|
||||
_, err = o.db.InsertInto(devops.ProjectMembershipTableName).
|
||||
Columns(devops.ProjectMembershipColumns...).Record(projectMembership).Exec()
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return project, nil
|
||||
}
|
||||
|
||||
func (o *devopsProjectOperator) getProjectUserRole(username, projectId string) (string, error) {
|
||||
if username == devops.KS_ADMIN {
|
||||
return dsClient.ProjectOwner, nil
|
||||
}
|
||||
|
||||
membership := &dsClient.ProjectMembership{}
|
||||
err := o.db.Select(devops.ProjectMembershipColumns...).
|
||||
From(devops.ProjectMembershipTableName).
|
||||
Where(db.And(
|
||||
db.Eq(devops.ProjectMembershipUsernameColumn, username),
|
||||
db.Eq(devops.ProjectMembershipProjectIdColumn, projectId))).LoadOne(membership)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return membership.Role, nil
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
package tenant
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
k8sinformers "k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type NamespaceInterface interface {
|
||||
Search(username string, conditions *params.Conditions, orderBy string, reverse bool) ([]*v1.Namespace, error)
|
||||
CreateNamespace(workspace string, namespace *v1.Namespace, username string) (*v1.Namespace, error)
|
||||
}
|
||||
|
||||
type namespaceSearcher struct {
|
||||
k8s kubernetes.Interface
|
||||
informers k8sinformers.SharedInformerFactory
|
||||
am am.AccessManagementInterface
|
||||
}
|
||||
|
||||
func (s *namespaceSearcher) CreateNamespace(workspace string, namespace *v1.Namespace, username string) (*v1.Namespace, error) {
|
||||
if namespace.Labels == nil {
|
||||
namespace.Labels = make(map[string]string, 0)
|
||||
}
|
||||
if username != "" {
|
||||
namespace.Annotations[constants.CreatorAnnotationKey] = username
|
||||
}
|
||||
|
||||
namespace.Labels[constants.WorkspaceLabelKey] = workspace
|
||||
|
||||
return s.k8s.CoreV1().Namespaces().Create(namespace)
|
||||
}
|
||||
|
||||
func newNamespaceOperator(k8s kubernetes.Interface, informers k8sinformers.SharedInformerFactory, am am.AccessManagementInterface) NamespaceInterface {
|
||||
return &namespaceSearcher{k8s: k8s, informers: informers, am: am}
|
||||
}
|
||||
|
||||
func (s *namespaceSearcher) match(match map[string]string, item *v1.Namespace) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
case v1alpha2.Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case v1alpha2.Keyword:
|
||||
if !strings.Contains(item.Name, v) && !contains(item.Labels, "", v) && !contains(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *namespaceSearcher) fuzzy(fuzzy map[string]string, item *v1.Namespace) bool {
|
||||
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case v1alpha2.Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *namespaceSearcher) compare(a, b *v1.Namespace, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case "createTime":
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case "name":
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
}
|
||||
|
||||
func (s *namespaceSearcher) GetNamespaces(username string) ([]*v1.Namespace, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (s *namespaceSearcher) Search(username string, conditions *params.Conditions, orderBy string, reverse bool) ([]*v1.Namespace, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
@@ -18,97 +18,147 @@
|
||||
package tenant
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
k8sinformers "k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
|
||||
ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
||||
tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
CreateNamespace(workspace string, namespace *v1.Namespace, username string) (*v1.Namespace, error)
|
||||
DeleteNamespace(workspace, namespace string) error
|
||||
DescribeWorkspace(username, workspace string) (*v1alpha1.Workspace, error)
|
||||
ListWorkspaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error)
|
||||
ListNamespaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error)
|
||||
ListDevopsProjects(username string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error)
|
||||
CountDevOpsProjects(username string) (uint32, error)
|
||||
DeleteDevOpsProject(username, projectId string) error
|
||||
ListWorkspaces(username string) (*api.ListResult, error)
|
||||
ListNamespaces(username, workspace string) (*api.ListResult, error)
|
||||
}
|
||||
|
||||
type tenantOperator struct {
|
||||
workspaces WorkspaceInterface
|
||||
namespaces NamespaceInterface
|
||||
am am.AccessManagementInterface
|
||||
devops DevOpsProjectOperator
|
||||
informers informers.InformerFactory
|
||||
am am.AccessManagementInterface
|
||||
}
|
||||
|
||||
func (t *tenantOperator) CountDevOpsProjects(username string) (uint32, error) {
|
||||
return t.devops.GetDevOpsProjectsCount(username)
|
||||
}
|
||||
|
||||
func (t *tenantOperator) DeleteDevOpsProject(username, projectId string) error {
|
||||
return t.devops.DeleteDevOpsProject(projectId, username)
|
||||
}
|
||||
|
||||
func (t *tenantOperator) GetUserDevopsSimpleRules(username string, projectId string) (interface{}, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (t *tenantOperator) ListDevopsProjects(username string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error) {
|
||||
return t.devops.ListDevOpsProjects(conditions.Match["workspace"], username, conditions, orderBy, reverse, limit, offset)
|
||||
}
|
||||
|
||||
func (t *tenantOperator) DeleteNamespace(workspace, namespace string) error {
|
||||
return t.workspaces.DeleteNamespace(workspace, namespace)
|
||||
}
|
||||
|
||||
func New(client kubernetes.Interface, informers k8sinformers.SharedInformerFactory, ksinformers ksinformers.SharedInformerFactory, db *mysql.Database) Interface {
|
||||
amOperator := am.NewAMOperator(client, informers)
|
||||
func New(k8sClient k8s.Client, informers informers.InformerFactory) Interface {
|
||||
return &tenantOperator{
|
||||
workspaces: newWorkspaceOperator(client, informers, ksinformers, amOperator, db),
|
||||
namespaces: newNamespaceOperator(client, informers, amOperator),
|
||||
am: amOperator,
|
||||
informers: informers,
|
||||
am: am.NewAMOperator(k8sClient.KubeSphere(), informers.KubeSphereSharedInformerFactory()),
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tenantOperator) CreateNamespace(workspaceName string, namespace *v1.Namespace, username string) (*v1.Namespace, error) {
|
||||
return t.namespaces.CreateNamespace(workspaceName, namespace, username)
|
||||
}
|
||||
|
||||
func (t *tenantOperator) DescribeWorkspace(username, workspaceName string) (*v1alpha1.Workspace, error) {
|
||||
workspace, err := t.workspaces.GetWorkspace(workspaceName)
|
||||
func (t *tenantOperator) ListWorkspaces(username string) (*api.ListResult, error) {
|
||||
|
||||
workspaceRoles, err := t.am.ListRolesOfUser(iamv1alpha2.WorkspaceScope, username)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return workspace, nil
|
||||
}
|
||||
workspaces := make([]*tenantv1alpha1.Workspace, 0)
|
||||
|
||||
func (t *tenantOperator) ListWorkspaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
for _, role := range workspaceRoles {
|
||||
|
||||
func (t *tenantOperator) ListNamespaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
|
||||
// all workspaces are allowed
|
||||
if role.Target.Name == iamv1alpha2.TargetAll {
|
||||
workspaces, err = t.informers.KubeSphereSharedInformerFactory().
|
||||
Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything())
|
||||
break
|
||||
}
|
||||
workspace, err := t.informers.KubeSphereSharedInformerFactory().
|
||||
Tenant().V1alpha1().Workspaces().Lister().Get(role.Target.Name)
|
||||
|
||||
namespaces, err := t.namespaces.Search(username, conditions, orderBy, reverse)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// limit offset
|
||||
result := make([]interface{}, 0)
|
||||
for i, v := range namespaces {
|
||||
if len(result) < limit && i >= offset {
|
||||
result = append(result, v)
|
||||
if errors.IsNotFound(err) {
|
||||
klog.Warningf("workspace role: %s found but workspace not exist", role.Target)
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
if !containsWorkspace(workspaces, workspace) {
|
||||
workspaces = append(workspaces, workspace)
|
||||
}
|
||||
}
|
||||
|
||||
return &models.PageableResponse{Items: result, TotalCount: len(namespaces)}, nil
|
||||
return &api.ListResult{
|
||||
TotalItems: len(workspaces),
|
||||
Items: workspacesToInterfaces(workspaces),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (t *tenantOperator) ListNamespaces(username, workspace string) (*api.ListResult, error) {
|
||||
|
||||
namespaceRoles, err := t.am.ListRolesOfUser(iamv1alpha2.NamespaceScope, username)
|
||||
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
namespaces := make([]*corev1.Namespace, 0)
|
||||
|
||||
for _, role := range namespaceRoles {
|
||||
|
||||
// all workspaces are allowed
|
||||
if role.Target.Name == iamv1alpha2.TargetAll {
|
||||
namespaces, err = t.informers.KubernetesSharedInformerFactory().
|
||||
Core().V1().Namespaces().Lister().List(labels.Everything())
|
||||
break
|
||||
}
|
||||
|
||||
namespace, err := t.informers.KubernetesSharedInformerFactory().
|
||||
Core().V1().Namespaces().Lister().Get(role.Target.Name)
|
||||
|
||||
if errors.IsNotFound(err) {
|
||||
klog.Warningf("workspace role: %s found but workspace not exist", role.Target)
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
if !containsNamespace(namespaces, namespace) {
|
||||
namespaces = append(namespaces, namespace)
|
||||
}
|
||||
}
|
||||
|
||||
return &api.ListResult{
|
||||
TotalItems: len(namespaces),
|
||||
Items: namespacesToInterfaces(namespaces),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func containsWorkspace(workspaces []*tenantv1alpha1.Workspace, workspace *tenantv1alpha1.Workspace) bool {
|
||||
for _, item := range workspaces {
|
||||
if item.Name == workspace.Name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func containsNamespace(namespaces []*corev1.Namespace, namespace *corev1.Namespace) bool {
|
||||
for _, item := range namespaces {
|
||||
if item.Name == namespace.Name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func workspacesToInterfaces(workspaces []*tenantv1alpha1.Workspace) []interface{} {
|
||||
ret := make([]interface{}, len(workspaces))
|
||||
for index, v := range workspaces {
|
||||
ret[index] = v
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func namespacesToInterfaces(namespaces []*corev1.Namespace) []interface{} {
|
||||
ret := make([]interface{}, len(namespaces))
|
||||
for index, v := range namespaces {
|
||||
ret[index] = v
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -1,263 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020 The KubeSphere Authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* /
|
||||
*/
|
||||
package tenant
|
||||
|
||||
import (
|
||||
core "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
|
||||
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/db"
|
||||
"kubesphere.io/kubesphere/pkg/models/devops"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"strings"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
type InWorkspaceUser struct {
|
||||
*iamv1alpha2.User
|
||||
WorkspaceRole string `json:"workspaceRole"`
|
||||
}
|
||||
|
||||
type WorkspaceInterface interface {
|
||||
GetWorkspace(workspace string) (*v1alpha1.Workspace, error)
|
||||
SearchWorkspace(username string, conditions *params.Conditions, orderBy string, reverse bool) ([]*v1alpha1.Workspace, error)
|
||||
ListNamespaces(workspace string) ([]*core.Namespace, error)
|
||||
DeleteNamespace(workspace, namespace string) error
|
||||
RemoveUser(user, workspace string) error
|
||||
AddUser(workspace string, user *InWorkspaceUser) error
|
||||
CountDevopsProjectsInWorkspace(workspace string) (int, error)
|
||||
CountUsersInWorkspace(workspace string) (int, error)
|
||||
CountOrgRoles() (int, error)
|
||||
CountWorkspaces() (int, error)
|
||||
CountNamespacesInWorkspace(workspace string) (int, error)
|
||||
}
|
||||
|
||||
type workspaceOperator struct {
|
||||
client kubernetes.Interface
|
||||
informers informers.SharedInformerFactory
|
||||
ksInformers externalversions.SharedInformerFactory
|
||||
am am.AccessManagementInterface
|
||||
|
||||
// TODO: use db interface instead of mysql client
|
||||
// we can refactor this after rewrite devops using crd
|
||||
db *mysql.Database
|
||||
}
|
||||
|
||||
func newWorkspaceOperator(client kubernetes.Interface, informers informers.SharedInformerFactory, ksinformers externalversions.SharedInformerFactory, am am.AccessManagementInterface, db *mysql.Database) WorkspaceInterface {
|
||||
return &workspaceOperator{
|
||||
client: client,
|
||||
informers: informers,
|
||||
ksInformers: ksinformers,
|
||||
am: am,
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *workspaceOperator) ListNamespaces(workspace string) ([]*core.Namespace, error) {
|
||||
namespaces, err := w.informers.Core().V1().Namespaces().Lister().List(labels.SelectorFromSet(labels.Set{constants.WorkspaceLabelKey: workspace}))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return namespaces, nil
|
||||
}
|
||||
|
||||
func (w *workspaceOperator) DeleteNamespace(workspace string, namespace string) error {
|
||||
ns, err := w.informers.Core().V1().Namespaces().Lister().Get(namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ns.Labels[constants.WorkspaceLabelKey] == workspace {
|
||||
deletePolicy := metav1.DeletePropagationBackground
|
||||
return w.client.CoreV1().Namespaces().Delete(namespace, &metav1.DeleteOptions{PropagationPolicy: &deletePolicy})
|
||||
} else {
|
||||
return apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: "workspace"}, workspace)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *workspaceOperator) RemoveUser(workspace string, username string) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (w *workspaceOperator) AddUser(workspaceName string, user *InWorkspaceUser) error {
|
||||
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (w *workspaceOperator) CountDevopsProjectsInWorkspace(workspaceName string) (int, error) {
|
||||
query := w.db.Select(devops.DevOpsProjectIdColumn).
|
||||
From(devops.DevOpsProjectTableName).
|
||||
Where(db.And(db.Eq(devops.DevOpsProjectWorkSpaceColumn, workspaceName),
|
||||
db.Eq(devops.StatusColumn, devops.StatusActive)))
|
||||
|
||||
devOpsProjects := make([]string, 0)
|
||||
|
||||
if _, err := query.Load(&devOpsProjects); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(devOpsProjects), nil
|
||||
}
|
||||
|
||||
func (w *workspaceOperator) CountUsersInWorkspace(workspace string) (int, error) {
|
||||
count, err := w.CountUsersInWorkspace(workspace)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (w *workspaceOperator) CountOrgRoles() (int, error) {
|
||||
return len(constants.WorkSpaceRoles), nil
|
||||
}
|
||||
|
||||
func (w *workspaceOperator) CountNamespacesInWorkspace(workspace string) (int, error) {
|
||||
ns, err := w.ListNamespaces(workspace)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return len(ns), nil
|
||||
}
|
||||
|
||||
func (*workspaceOperator) match(match map[string]string, item *v1alpha1.Workspace) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
case v1alpha2.Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case v1alpha2.Keyword:
|
||||
if !strings.Contains(item.Name, v) && !contains(item.Labels, "", v) && !contains(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*workspaceOperator) fuzzy(fuzzy map[string]string, item *v1alpha1.Workspace) bool {
|
||||
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case v1alpha2.Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (*workspaceOperator) compare(a, b *v1alpha1.Workspace, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case v1alpha2.CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case v1alpha2.Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
}
|
||||
|
||||
func (w *workspaceOperator) SearchWorkspace(username string, conditions *params.Conditions, orderBy string, reverse bool) ([]*v1alpha1.Workspace, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (w *workspaceOperator) GetWorkspace(workspaceName string) (*v1alpha1.Workspace, error) {
|
||||
return w.ksInformers.Tenant().V1alpha1().Workspaces().Lister().Get(workspaceName)
|
||||
}
|
||||
|
||||
func contains(m map[string]string, key, value string) bool {
|
||||
for k, v := range m {
|
||||
if key == "" {
|
||||
if strings.Contains(k, value) || strings.Contains(v, value) {
|
||||
return true
|
||||
}
|
||||
} else if k == key && strings.Contains(v, value) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/*
|
||||
// TODO: move to metrics package
|
||||
func GetAllProjectNums() (int, error) {
|
||||
namespaceLister := informers.SharedInformerFactory().Core().V1().Namespaces().Lister()
|
||||
list, err := namespaceLister.List(labels.Everything())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(list), nil
|
||||
}
|
||||
|
||||
func GetAllDevOpsProjectsNums() (int, error) {
|
||||
_, err := clientset.ClientSets().Devops()
|
||||
if _, notEnabled := err.(clientset.ClientSetNotEnabledError); notEnabled {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
dbconn, err := clientset.ClientSets().MySQL()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
query := dbconn.Select(devops.DevOpsProjectIdColumn).
|
||||
From(devops.DevOpsProjectTableName).
|
||||
Where(db.Eq(devops.StatusColumn, devops.StatusActive))
|
||||
|
||||
devOpsProjects := make([]string, 0)
|
||||
|
||||
if _, err := query.Load(&devOpsProjects); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(devOpsProjects), nil
|
||||
}
|
||||
*/
|
||||
|
||||
func (w *workspaceOperator) CountWorkspaces() (int, error) {
|
||||
ws, err := w.ksInformers.Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return len(ws), nil
|
||||
}
|
||||
Reference in New Issue
Block a user