[WIP] API refactor (#1737)

* refactor openpitrix API

Signed-off-by: hongming <talonwan@yunify.com>

* add openpitrix mock client

Signed-off-by: hongming <talonwan@yunify.com>

* refactor tenant API

Signed-off-by: hongming <talonwan@yunify.com>

* refactor IAM API

Signed-off-by: hongming <talonwan@yunify.com>

* refactor IAM API

Signed-off-by: hongming <talonwan@yunify.com>
This commit is contained in:
hongming
2020-01-13 13:36:21 +08:00
committed by zryfish
parent c40d1542a2
commit 71849f028f
66 changed files with 5415 additions and 4366 deletions

View File

@@ -28,6 +28,7 @@ import (
"kubesphere.io/kubesphere/pkg/gojenkins/utils"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/devops"
"kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/server/params"
cs "kubesphere.io/kubesphere/pkg/simple/client"
"net/http"
@@ -317,7 +318,7 @@ func CreateDevopsProject(username string, workspace string, req *v1alpha2.DevOps
return project, nil
}
func GetUserDevopsSimpleRules(username, projectId string) ([]models.SimpleRule, error) {
func GetUserDevopsSimpleRules(username, projectId string) ([]iam.SimpleRule, error) {
role, err := devops.GetProjectUserRole(username, projectId)
if err != nil {
klog.Errorf("%+v", err)
@@ -326,12 +327,12 @@ func GetUserDevopsSimpleRules(username, projectId string) ([]models.SimpleRule,
return GetDevopsRoleSimpleRules(role), nil
}
func GetDevopsRoleSimpleRules(role string) []models.SimpleRule {
var rules []models.SimpleRule
func GetDevopsRoleSimpleRules(role string) []iam.SimpleRule {
var rules []iam.SimpleRule
switch role {
case "developer":
rules = []models.SimpleRule{
rules = []iam.SimpleRule{
{Name: "pipelines", Actions: []string{"view", "trigger"}},
{Name: "roles", Actions: []string{"view"}},
{Name: "members", Actions: []string{"view"}},
@@ -339,7 +340,7 @@ func GetDevopsRoleSimpleRules(role string) []models.SimpleRule {
}
break
case "owner":
rules = []models.SimpleRule{
rules = []iam.SimpleRule{
{Name: "pipelines", Actions: []string{"create", "edit", "view", "delete", "trigger"}},
{Name: "roles", Actions: []string{"view"}},
{Name: "members", Actions: []string{"create", "edit", "view", "delete"}},
@@ -348,7 +349,7 @@ func GetDevopsRoleSimpleRules(role string) []models.SimpleRule {
}
break
case "maintainer":
rules = []models.SimpleRule{
rules = []iam.SimpleRule{
{Name: "pipelines", Actions: []string{"create", "edit", "view", "delete", "trigger"}},
{Name: "roles", Actions: []string{"view"}},
{Name: "members", Actions: []string{"view"}},
@@ -359,7 +360,7 @@ func GetDevopsRoleSimpleRules(role string) []models.SimpleRule {
case "reporter":
fallthrough
default:
rules = []models.SimpleRule{
rules = []iam.SimpleRule{
{Name: "pipelines", Actions: []string{"view"}},
{Name: "roles", Actions: []string{"view"}},
{Name: "members", Actions: []string{"view"}},

View File

@@ -21,9 +21,10 @@ import (
"k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/labels"
k8sinformers "k8s.io/client-go/informers"
kubernetes "k8s.io/client-go/kubernetes"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
@@ -32,11 +33,34 @@ import (
"strings"
)
type namespaceSearcher struct {
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)
}
// Exactly Match
func (*namespaceSearcher) match(match map[string]string, item *v1.Namespace) bool {
type namespaceSearcher struct {
k8s kubernetes.Interface
informers k8sinformers.SharedInformerFactory
}
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) NamespaceInterface {
return &namespaceSearcher{k8s: k8s, informers: informers}
}
func (s *namespaceSearcher) match(match map[string]string, item *v1.Namespace) bool {
for k, v := range match {
switch k {
case v1alpha2.Name:
@@ -58,7 +82,7 @@ func (*namespaceSearcher) match(match map[string]string, item *v1.Namespace) boo
return true
}
func (*namespaceSearcher) fuzzy(fuzzy map[string]string, item *v1.Namespace) bool {
func (s *namespaceSearcher) fuzzy(fuzzy map[string]string, item *v1.Namespace) bool {
for k, v := range fuzzy {
switch k {
@@ -74,7 +98,7 @@ func (*namespaceSearcher) fuzzy(fuzzy map[string]string, item *v1.Namespace) boo
return true
}
func (*namespaceSearcher) compare(a, b *v1.Namespace, orderBy string) bool {
func (s *namespaceSearcher) compare(a, b *v1.Namespace, orderBy string) bool {
switch orderBy {
case "createTime":
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
@@ -85,7 +109,7 @@ func (*namespaceSearcher) compare(a, b *v1.Namespace, orderBy string) bool {
}
}
func (*namespaceSearcher) GetNamespaces(username string) ([]*v1.Namespace, error) {
func (s *namespaceSearcher) GetNamespaces(username string) ([]*v1.Namespace, error) {
roles, err := iam.GetUserRoles("", username)
@@ -93,7 +117,7 @@ func (*namespaceSearcher) GetNamespaces(username string) ([]*v1.Namespace, error
return nil, err
}
namespaces := make([]*v1.Namespace, 0)
namespaceLister := informers.SharedInformerFactory().Core().V1().Namespaces().Lister()
namespaceLister := s.informers.Core().V1().Namespaces().Lister()
for _, role := range roles {
namespace, err := namespaceLister.Get(role.Namespace)
if err != nil {
@@ -117,7 +141,7 @@ func containsNamespace(namespaces []*v1.Namespace, namespace *v1.Namespace) bool
return false
}
func (s *namespaceSearcher) search(username string, conditions *params.Conditions, orderBy string, reverse bool) ([]*v1.Namespace, error) {
func (s *namespaceSearcher) Search(username string, conditions *params.Conditions, orderBy string, reverse bool) ([]*v1.Namespace, error) {
rules, err := iam.GetUserClusterRules(username)
@@ -128,7 +152,7 @@ func (s *namespaceSearcher) search(username string, conditions *params.Condition
namespaces := make([]*v1.Namespace, 0)
if iam.RulesMatchesRequired(rules, rbacv1.PolicyRule{Verbs: []string{"list"}, APIGroups: []string{"tenant.kubesphere.io"}, Resources: []string{"namespaces"}}) {
namespaces, err = informers.SharedInformerFactory().Core().V1().Namespaces().Lister().List(labels.Everything())
namespaces, err = s.informers.Core().V1().Namespaces().Lister().List(labels.Everything())
} else {
namespaces, err = s.GetNamespaces(username)
}
@@ -148,12 +172,14 @@ func (s *namespaceSearcher) search(username string, conditions *params.Condition
// order & reverse
sort.Slice(result, func(i, j int) bool {
if reverse {
tmp := i
i = j
j = tmp
i, j = j, i
}
return s.compare(result[i], result[j], orderBy)
})
return result, nil
}
func CreateNamespace() {
}

View File

@@ -19,49 +19,62 @@ 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/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models"
ws "kubesphere.io/kubesphere/pkg/models/workspaces"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/simple/client"
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
"strconv"
)
var (
workspaces = workspaceSearcher{}
namespaces = namespaceSearcher{}
)
func CreateNamespace(workspaceName 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] = workspaceName
return client.ClientSets().K8s().Kubernetes().CoreV1().Namespaces().Create(namespace)
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)
}
func DescribeWorkspace(username, workspaceName string) (*v1alpha1.Workspace, error) {
workspace, err := informers.KsSharedInformerFactory().Tenant().V1alpha1().Workspaces().Lister().Get(workspaceName)
type tenantOperator struct {
workspaces WorkspaceInterface
namespaces NamespaceInterface
}
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 {
return &tenantOperator{
workspaces: newWorkspaceOperator(client, informers, ksinformers, db),
namespaces: newNamespaceOperator(client, informers),
}
}
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)
if err != nil {
return nil, err
}
workspace = appendAnnotations(username, workspace)
if username != "" {
workspace = t.appendAnnotations(username, workspace)
}
return workspace, nil
}
func ListWorkspaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
func (t *tenantOperator) ListWorkspaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
workspaces, err := workspaces.search(username, conditions, orderBy, reverse)
workspaces, err := t.workspaces.SearchWorkspace(username, conditions, orderBy, reverse)
if err != nil {
return nil, err
@@ -71,7 +84,7 @@ func ListWorkspaces(username string, conditions *params.Conditions, orderBy stri
result := make([]interface{}, 0)
for i, workspace := range workspaces {
if len(result) < limit && i >= offset {
workspace := appendAnnotations(username, workspace)
workspace := t.appendAnnotations(username, workspace)
result = append(result, workspace)
}
}
@@ -79,12 +92,12 @@ func ListWorkspaces(username string, conditions *params.Conditions, orderBy stri
return &models.PageableResponse{Items: result, TotalCount: len(workspaces)}, nil
}
func appendAnnotations(username string, workspace *v1alpha1.Workspace) *v1alpha1.Workspace {
func (t *tenantOperator) appendAnnotations(username string, workspace *v1alpha1.Workspace) *v1alpha1.Workspace {
workspace = workspace.DeepCopy()
if workspace.Annotations == nil {
workspace.Annotations = make(map[string]string)
}
ns, err := ListNamespaces(username, &params.Conditions{Match: map[string]string{constants.WorkspaceLabelKey: workspace.Name}}, "", false, 1, 0)
ns, err := t.ListNamespaces(username, &params.Conditions{Match: map[string]string{constants.WorkspaceLabelKey: workspace.Name}}, "", false, 1, 0)
if err == nil {
workspace.Annotations["kubesphere.io/namespace-count"] = strconv.Itoa(ns.TotalCount)
}
@@ -92,16 +105,18 @@ func appendAnnotations(username string, workspace *v1alpha1.Workspace) *v1alpha1
if err == nil {
workspace.Annotations["kubesphere.io/devops-count"] = strconv.Itoa(devops.TotalCount)
}
userCount, err := ws.WorkspaceUserCount(workspace.Name)
userCount, err := t.workspaces.CountUsersInWorkspace(workspace.Name)
if err == nil {
workspace.Annotations["kubesphere.io/member-count"] = strconv.Itoa(userCount)
}
return workspace
}
func ListNamespaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
func (t *tenantOperator) ListNamespaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
namespaces, err := namespaces.search(username, conditions, orderBy, reverse)
namespaces, err := t.namespaces.Search(username, conditions, orderBy, reverse)
if err != nil {
return nil, err

View File

@@ -1,41 +1,241 @@
/*
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.
*/
*
* 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 (
"fmt"
core "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/db"
"kubesphere.io/kubesphere/pkg/models/devops"
"kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
clientset "kubesphere.io/kubesphere/pkg/simple/client"
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
"strings"
"k8s.io/api/rbac/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
)
type workspaceSearcher struct {
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 *iam.User) error
CountDevopsProjectsInWorkspace(workspace string) (int, error)
CountUsersInWorkspace(workspace string) (int, error)
CountOrgRoles() (int, error)
CountWorkspaces() (int, error)
CountNamespacesInWorkspace(workspace string) (int, error)
}
// Exactly Match
func (*workspaceSearcher) match(match map[string]string, item *v1alpha1.Workspace) bool {
type workspaceOperator struct {
client kubernetes.Interface
informers informers.SharedInformerFactory
ksInformers externalversions.SharedInformerFactory
// 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, db *mysql.Database) WorkspaceInterface {
return &workspaceOperator{
client: client,
informers: informers,
ksInformers: ksinformers,
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 {
workspaceRole, err := iam.GetUserWorkspaceRole(workspace, username)
if err != nil {
return err
}
err = w.deleteWorkspaceRoleBinding(workspace, username, workspaceRole.Annotations[constants.DisplayNameAnnotationKey])
if err != nil {
return err
}
return nil
}
func (w *workspaceOperator) AddUser(workspaceName string, user *iam.User) error {
workspaceRole, err := iam.GetUserWorkspaceRole(workspaceName, user.Username)
if err != nil && !apierrors.IsNotFound(err) {
klog.Errorf("get workspace role failed: %+v", err)
return err
}
workspaceRoleName := fmt.Sprintf("workspace:%s:%s", workspaceName, strings.TrimPrefix(user.WorkspaceRole, "workspace-"))
var currentWorkspaceRoleName string
if workspaceRole != nil {
currentWorkspaceRoleName = workspaceRole.Name
}
if currentWorkspaceRoleName != workspaceRoleName && currentWorkspaceRoleName != "" {
err := w.deleteWorkspaceRoleBinding(workspaceName, user.Username, workspaceRole.Annotations[constants.DisplayNameAnnotationKey])
if err != nil {
klog.Errorf("delete workspace role binding failed: %+v", err)
return err
}
} else if currentWorkspaceRoleName != "" {
return nil
}
return w.createWorkspaceRoleBinding(workspaceName, user.Username, user.WorkspaceRole)
}
func (w *workspaceOperator) createWorkspaceRoleBinding(workspace, username string, role string) error {
if !sliceutil.HasString(constants.WorkSpaceRoles, role) {
return apierrors.NewNotFound(schema.GroupResource{Resource: "workspace role"}, role)
}
roleBindingName := fmt.Sprintf("workspace:%s:%s", workspace, strings.TrimPrefix(role, "workspace-"))
workspaceRoleBinding, err := w.informers.Rbac().V1().ClusterRoleBindings().Lister().Get(roleBindingName)
if err != nil {
return err
}
if !k8sutil.ContainsUser(workspaceRoleBinding.Subjects, username) {
workspaceRoleBinding = workspaceRoleBinding.DeepCopy()
workspaceRoleBinding.Subjects = append(workspaceRoleBinding.Subjects, v1.Subject{APIGroup: "rbac.authorization.k8s.io", Kind: "User", Name: username})
_, err = w.client.RbacV1().ClusterRoleBindings().Update(workspaceRoleBinding)
if err != nil {
klog.Errorf("update workspace role binding failed: %+v", err)
return err
}
}
return nil
}
func (w *workspaceOperator) deleteWorkspaceRoleBinding(workspace, username string, role string) error {
if !sliceutil.HasString(constants.WorkSpaceRoles, role) {
return apierrors.NewNotFound(schema.GroupResource{Resource: "workspace role"}, role)
}
roleBindingName := fmt.Sprintf("workspace:%s:%s", workspace, strings.TrimPrefix(role, "workspace-"))
workspaceRoleBinding, err := w.informers.Rbac().V1().ClusterRoleBindings().Lister().Get(roleBindingName)
if err != nil {
return err
}
workspaceRoleBinding = workspaceRoleBinding.DeepCopy()
for i, v := range workspaceRoleBinding.Subjects {
if v.Kind == v1.UserKind && v.Name == username {
workspaceRoleBinding.Subjects = append(workspaceRoleBinding.Subjects[:i], workspaceRoleBinding.Subjects[i+1:]...)
i--
}
}
workspaceRoleBinding, err = w.client.RbacV1().ClusterRoleBindings().Update(workspaceRoleBinding)
return err
}
func (w *workspaceOperator) CountDevopsProjectsInWorkspace(workspaceName string) (int, error) {
if w.db == nil {
return 0, clientset.ErrClientSetNotEnabled
}
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 := iam.WorkspaceUsersTotalCount(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:
@@ -57,7 +257,7 @@ func (*workspaceSearcher) match(match map[string]string, item *v1alpha1.Workspac
return true
}
func (*workspaceSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.Workspace) bool {
func (*workspaceOperator) fuzzy(fuzzy map[string]string, item *v1alpha1.Workspace) bool {
for k, v := range fuzzy {
switch k {
@@ -73,7 +273,7 @@ func (*workspaceSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.Workspac
return true
}
func (*workspaceSearcher) compare(a, b *v1alpha1.Workspace, orderBy string) bool {
func (*workspaceOperator) compare(a, b *v1alpha1.Workspace, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
@@ -84,7 +284,7 @@ func (*workspaceSearcher) compare(a, b *v1alpha1.Workspace, orderBy string) bool
}
}
func (s *workspaceSearcher) search(username string, conditions *params.Conditions, orderBy string, reverse bool) ([]*v1alpha1.Workspace, error) {
func (w *workspaceOperator) SearchWorkspace(username string, conditions *params.Conditions, orderBy string, reverse bool) ([]*v1alpha1.Workspace, error) {
rules, err := iam.GetUserClusterRules(username)
if err != nil {
@@ -94,7 +294,7 @@ func (s *workspaceSearcher) search(username string, conditions *params.Condition
workspaces := make([]*v1alpha1.Workspace, 0)
if iam.RulesMatchesRequired(rules, rbacv1.PolicyRule{Verbs: []string{"list"}, APIGroups: []string{"tenant.kubesphere.io"}, Resources: []string{"workspaces"}}) {
workspaces, err = informers.KsSharedInformerFactory().Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything())
workspaces, err = w.ksInformers.Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything())
if err != nil {
return nil, err
}
@@ -104,7 +304,7 @@ func (s *workspaceSearcher) search(username string, conditions *params.Condition
return nil, err
}
for k := range workspaceRoles {
workspace, err := informers.KsSharedInformerFactory().Tenant().V1alpha1().Workspaces().Lister().Get(k)
workspace, err := w.ksInformers.Tenant().V1alpha1().Workspaces().Lister().Get(k)
if err != nil {
return nil, err
}
@@ -115,7 +315,7 @@ func (s *workspaceSearcher) search(username string, conditions *params.Condition
result := make([]*v1alpha1.Workspace, 0)
for _, workspace := range workspaces {
if s.match(conditions.Match, workspace) && s.fuzzy(conditions.Fuzzy, workspace) {
if w.match(conditions.Match, workspace) && w.fuzzy(conditions.Fuzzy, workspace) {
result = append(result, workspace)
}
}
@@ -123,18 +323,16 @@ func (s *workspaceSearcher) search(username string, conditions *params.Condition
// order & reverse
sort.Slice(result, func(i, j int) bool {
if reverse {
tmp := i
i = j
j = tmp
i, j = j, i
}
return s.compare(result[i], result[j], orderBy)
return w.compare(result[i], result[j], orderBy)
})
return result, nil
}
func GetWorkspace(workspaceName string) (*v1alpha1.Workspace, error) {
return informers.KsSharedInformerFactory().Tenant().V1alpha1().Workspaces().Lister().Get(workspaceName)
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 {
@@ -149,3 +347,47 @@ func contains(m map[string]string, key, value string) bool {
}
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
}