Signed-off-by: hongming <talonwan@yunify.com>
This commit is contained in:
hongming
2020-04-10 10:16:26 +08:00
parent 0e814bb5e4
commit a3d3c8e427
44 changed files with 2178 additions and 1283 deletions

View File

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

View File

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

View File

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

View File

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