@@ -63,7 +63,7 @@ func userRolesHandler(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
username := req.PathParameter("username")
|
||||
|
||||
roles, err := iam.GetRoles(username)
|
||||
roles, err := iam.GetRoles("", username)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
@@ -206,7 +206,7 @@ func clusterRoleRulesHandler(req *restful.Request, resp *restful.Response) {
|
||||
var rules []iam.Rule
|
||||
|
||||
if name == "" {
|
||||
rules = iam.ClusterRoleRuleGroup
|
||||
rules = iam.ClusterRoleRuleMapping
|
||||
} else {
|
||||
var err error
|
||||
rules, err = iam.GetClusterRoleRules(name)
|
||||
@@ -227,7 +227,7 @@ func roleRulesHandler(req *restful.Request, resp *restful.Response) {
|
||||
var rules []iam.Rule
|
||||
|
||||
if namespace == "" && name == "" {
|
||||
rules = iam.RoleRuleGroup
|
||||
rules = iam.RoleRuleMapping
|
||||
} else {
|
||||
var err error
|
||||
rules, err = iam.GetRoleRules(namespace, name)
|
||||
|
||||
37
pkg/apis/v1alpha/monitoring/monitor_handler.go
Normal file → Executable file
37
pkg/apis/v1alpha/monitoring/monitor_handler.go
Normal file → Executable file
@@ -58,6 +58,18 @@ func (u MonitorResource) monitorWorkload(request *restful.Request, response *res
|
||||
}
|
||||
}
|
||||
|
||||
// merge multiple metric: all-devops, all-roles, all-projects...this api is designed for admin
|
||||
func (u MonitorResource) monitorWorkspaceUserInfo(request *restful.Request, response *restful.Response) {
|
||||
res := metrics.MonitorWorkspaceUserInfo(request)
|
||||
response.WriteAsJson(res)
|
||||
}
|
||||
|
||||
// merge multiple metric: devops, roles, projects...
|
||||
func (u MonitorResource) monitorWorkspaceResourceLevelMetrics(request *restful.Request, response *restful.Response) {
|
||||
res := metrics.MonitorWorkspaceResourceLevelMetrics(request)
|
||||
response.WriteAsJson(res)
|
||||
}
|
||||
|
||||
func (u MonitorResource) monitorWorkspacePodLevelMetrics(request *restful.Request, response *restful.Response) {
|
||||
res := metrics.MonitorAllMetrics(request)
|
||||
response.WriteAsJson(res)
|
||||
@@ -223,4 +235,29 @@ func Register(ws *restful.WebService, subPath string) {
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/workspaces/{workspace_name}/pods").To(u.monitorWorkspacePodLevelMetrics).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor specific workspace level metrics").
|
||||
Param(ws.PathParameter("workspace_name", "workspace name").DataType("string").Required(true)).
|
||||
Param(ws.QueryParameter("namespaces_filter", "namespaces filter").DataType("string").Required(false).DefaultValue("k.*")).
|
||||
Param(ws.QueryParameter("metrics_filter", "metrics name cpu memory...").DataType("string").Required(false).DefaultValue("tenant_memory_utilisation_wo_cache")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/workspaces/{workspace_name}").To(u.monitorWorkspaceResourceLevelMetrics).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor specific workspace level metrics").
|
||||
Param(ws.PathParameter("workspace_name", "workspace name").DataType("string").Required(true)).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/workspaces").To(u.monitorWorkspaceUserInfo).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor specific workspace level metrics").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
}
|
||||
|
||||
@@ -16,18 +16,22 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/models/workspaces"
|
||||
)
|
||||
|
||||
const UserNameHeader = "X-Token-Username"
|
||||
|
||||
func Register(ws *restful.WebService, subPath string) {
|
||||
ws.Route(ws.GET(subPath).To(WorkspaceListHandler))
|
||||
|
||||
ws.Route(ws.GET(subPath).To(UserWorkspaceListHandler))
|
||||
ws.Route(ws.POST(subPath).To(WorkspaceCreateHandler))
|
||||
ws.Route(ws.DELETE(subPath + "/{name}").To(DeleteWorkspaceHandler))
|
||||
ws.Route(ws.GET(subPath + "/{name}").To(WorkspaceDetailHandler))
|
||||
ws.Route(ws.PUT(subPath + "/{name}").To(WorkspaceEditHandler))
|
||||
ws.Route(ws.GET(subPath + "/{name}/namespaces").To(NamespaceHandler))
|
||||
ws.Route(ws.GET(subPath + "/{workspace}/namespaces").To(UserNamespaceListHandler))
|
||||
ws.Route(ws.POST(subPath + "/{name}/namespaces").To(NamespaceCreateHandler))
|
||||
ws.Route(ws.DELETE(subPath + "/{name}/namespaces/{namespace}").To(NamespaceDeleteHandler))
|
||||
ws.Route(ws.GET(subPath + "/{name}/devops").To(DevOpsProjectHandler))
|
||||
ws.Route(ws.POST(subPath + "/{name}/devops").To(DevOpsProjectCreateHandler))
|
||||
ws.Route(ws.DELETE(subPath + "/{name}/devops/{id}").To(DevOpsProjectDeleteHandler))
|
||||
|
||||
ws.Route(ws.GET(subPath + "/{name}/members").To(MembersHandler))
|
||||
ws.Route(ws.GET(subPath + "/{name}/members/{member}").To(MemberHandler))
|
||||
ws.Route(ws.GET(subPath + "/{name}/roles").To(RolesHandler))
|
||||
@@ -107,6 +111,7 @@ func MemberHandler(req *restful.Request, resp *restful.Response) {
|
||||
}
|
||||
|
||||
namespaces, err := workspaces.Namespaces(workspace)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
@@ -169,14 +174,9 @@ func MembersRemoveHandler(req *restful.Request, resp *restful.Response) {
|
||||
func NamespaceDeleteHandler(req *restful.Request, resp *restful.Response) {
|
||||
namespace := req.PathParameter("namespace")
|
||||
workspace := req.PathParameter("name")
|
||||
force := req.QueryParameter("force")
|
||||
err := workspaces.UnBindNamespace(workspace, namespace)
|
||||
//force := req.QueryParameter("force")
|
||||
|
||||
if err != nil && force != "true" {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
err = workspaces.DeleteNamespace(namespace)
|
||||
err := workspaces.DeleteNamespace(workspace, namespace)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
@@ -190,7 +190,7 @@ func DevOpsProjectDeleteHandler(req *restful.Request, resp *restful.Response) {
|
||||
devops := req.PathParameter("id")
|
||||
workspace := req.PathParameter("name")
|
||||
force := req.QueryParameter("force")
|
||||
username := req.HeaderParameter("X-Token-Username")
|
||||
username := req.HeaderParameter(UserNameHeader)
|
||||
|
||||
err := workspaces.UnBindDevopsProject(workspace, devops)
|
||||
|
||||
@@ -212,7 +212,7 @@ func DevOpsProjectDeleteHandler(req *restful.Request, resp *restful.Response) {
|
||||
func DevOpsProjectCreateHandler(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
workspace := req.PathParameter("name")
|
||||
username := req.HeaderParameter("X-Token-Username")
|
||||
username := req.HeaderParameter(UserNameHeader)
|
||||
|
||||
var devops workspaces.DevopsProject
|
||||
|
||||
@@ -248,7 +248,7 @@ func DevOpsProjectCreateHandler(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
func NamespaceCreateHandler(req *restful.Request, resp *restful.Response) {
|
||||
workspace := req.PathParameter("name")
|
||||
username := req.HeaderParameter("X-Token-Username")
|
||||
username := req.HeaderParameter(UserNameHeader)
|
||||
|
||||
namespace := &v1.Namespace{}
|
||||
|
||||
@@ -266,6 +266,12 @@ func NamespaceCreateHandler(req *restful.Request, resp *restful.Response) {
|
||||
namespace.Annotations["creator"] = username
|
||||
namespace.Annotations["workspace"] = workspace
|
||||
|
||||
if namespace.Labels == nil {
|
||||
namespace.Labels = make(map[string]string, 0)
|
||||
}
|
||||
|
||||
namespace.Labels["kubesphere.io/workspace"] = workspace
|
||||
|
||||
namespace, err = workspaces.CreateNamespace(namespace)
|
||||
|
||||
if err != nil {
|
||||
@@ -273,14 +279,6 @@ func NamespaceCreateHandler(req *restful.Request, resp *restful.Response) {
|
||||
return
|
||||
}
|
||||
|
||||
err = workspaces.BindingNamespace(workspace, namespace.Name)
|
||||
|
||||
if err != nil {
|
||||
workspaces.DeleteNamespace(namespace.Name)
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteEntity(namespace)
|
||||
}
|
||||
|
||||
@@ -298,22 +296,9 @@ func DevOpsProjectHandler(req *restful.Request, resp *restful.Response) {
|
||||
resp.WriteEntity(devOpsProjects)
|
||||
}
|
||||
|
||||
func NamespaceHandler(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
workspace := req.PathParameter("name")
|
||||
|
||||
namespaces, err := workspaces.Namespaces(workspace)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteEntity(namespaces)
|
||||
}
|
||||
func WorkspaceCreateHandler(req *restful.Request, resp *restful.Response) {
|
||||
var workspace workspaces.Workspace
|
||||
username := req.HeaderParameter("X-Token-Username")
|
||||
username := req.HeaderParameter(UserNameHeader)
|
||||
err := req.ReadEntity(&workspace)
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, constants.MessageResponse{Message: err.Error()})
|
||||
@@ -327,7 +312,11 @@ func WorkspaceCreateHandler(req *restful.Request, resp *restful.Response) {
|
||||
workspace.Path = workspace.Name
|
||||
workspace.Members = nil
|
||||
|
||||
workspace.Creator = username
|
||||
if workspace.Admin != "" {
|
||||
workspace.Creator = workspace.Admin
|
||||
} else {
|
||||
workspace.Creator = username
|
||||
}
|
||||
|
||||
created, err := workspaces.Create(&workspace)
|
||||
|
||||
@@ -411,15 +400,12 @@ func WorkspaceDetailHandler(req *restful.Request, resp *restful.Response) {
|
||||
resp.WriteEntity(workspace)
|
||||
}
|
||||
|
||||
func WorkspaceListHandler(req *restful.Request, resp *restful.Response) {
|
||||
// List all workspaces for the current user
|
||||
func UserWorkspaceListHandler(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
var names []string
|
||||
username := req.HeaderParameter(UserNameHeader)
|
||||
|
||||
if query := req.QueryParameter("name"); query != "" {
|
||||
names = strings.Split(query, ",")
|
||||
}
|
||||
|
||||
list, err := workspaces.List(names)
|
||||
list, err := workspaces.ListByUser(username)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
@@ -428,3 +414,18 @@ func WorkspaceListHandler(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
resp.WriteEntity(list)
|
||||
}
|
||||
|
||||
func UserNamespaceListHandler(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
username := req.HeaderParameter(UserNameHeader)
|
||||
workspaceName := req.PathParameter("workspace")
|
||||
|
||||
namespaces, err := workspaces.ListNamespaceByUser(workspaceName, username)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteEntity(namespaces)
|
||||
}
|
||||
|
||||
62
pkg/models/controllers/clusterrole_bindings.go
Normal file
62
pkg/models/controllers/clusterrole_bindings.go
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright 2018 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 controllers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/informers"
|
||||
)
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) Name() string {
|
||||
return ctl.CommonAttribute.Name
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) sync(stopChan chan struct{}) {
|
||||
ctl.initListerAndInformer()
|
||||
ctl.informer.Run(stopChan)
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) total() int {
|
||||
list, err := ctl.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Errorf("count %s falied, reason:%s", err, ctl.Name())
|
||||
return 0
|
||||
}
|
||||
return len(list)
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) initListerAndInformer() {
|
||||
informerFactory := informers.NewSharedInformerFactory(ctl.K8sClient, time.Second*resyncCircle)
|
||||
ctl.lister = informerFactory.Rbac().V1().ClusterRoleBindings().Lister()
|
||||
ctl.informer = informerFactory.Rbac().V1().ClusterRoleBindings().Informer()
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) CountWithConditions(conditions string) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
return 0, nil, errors.New("not implement")
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) Lister() interface{} {
|
||||
return ctl.lister
|
||||
}
|
||||
@@ -74,7 +74,9 @@ func (ctl *ClusterRoleCtl) sync(stopChan chan struct{}) {
|
||||
for _, item := range list {
|
||||
obj := ctl.generateObject(*item)
|
||||
if obj != nil {
|
||||
db.Create(obj)
|
||||
if err := db.Create(obj).Error; err != nil {
|
||||
glog.Error("cluster roles sync error", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,14 +113,18 @@ func (ctl *ClusterRoleCtl) initListerAndInformer() {
|
||||
object := obj.(*v1.ClusterRole)
|
||||
mysqlObject := ctl.generateObject(*object)
|
||||
if mysqlObject != nil {
|
||||
db.Create(mysqlObject)
|
||||
if err := db.Create(mysqlObject).Error; err != nil {
|
||||
glog.Error("cluster roles sync error", err)
|
||||
}
|
||||
}
|
||||
},
|
||||
UpdateFunc: func(old, new interface{}) {
|
||||
object := new.(*v1.ClusterRole)
|
||||
mysqlObject := ctl.generateObject(*object)
|
||||
if mysqlObject != nil {
|
||||
db.Save(mysqlObject)
|
||||
if err := db.Save(mysqlObject).Error; err != nil {
|
||||
glog.Error("cluster roles update error", err)
|
||||
}
|
||||
}
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
|
||||
@@ -147,9 +147,9 @@ func (ctl *NamespaceCtl) createDefaultRoleBinding(ns, user string) error {
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) createDefaultRole(ns string) error {
|
||||
adminRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: admin, Namespace: ns}, Rules: adminRules}
|
||||
editorRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: editor, Namespace: ns}, Rules: editorRules}
|
||||
viewerRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: viewer, Namespace: ns}, Rules: viewerRules}
|
||||
adminRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: admin, Namespace: ns, Annotations: map[string]string{"creator": "system"}}, Rules: adminRules}
|
||||
editorRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: editor, Namespace: ns, Annotations: map[string]string{"creator": "system"}}, Rules: editorRules}
|
||||
viewerRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: viewer, Namespace: ns, Annotations: map[string]string{"creator": "system"}}, Rules: viewerRules}
|
||||
|
||||
_, err := ctl.K8sClient.RbacV1().Roles(ns).Create(adminRole)
|
||||
|
||||
|
||||
64
pkg/models/controllers/role_bindings.go
Normal file
64
pkg/models/controllers/role_bindings.go
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
Copyright 2018 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 controllers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/informers"
|
||||
)
|
||||
|
||||
func (ctl *RoleBindingCtl) Name() string {
|
||||
return ctl.CommonAttribute.Name
|
||||
}
|
||||
|
||||
func (ctl *RoleBindingCtl) sync(stopChan chan struct{}) {
|
||||
ctl.initListerAndInformer()
|
||||
ctl.informer.Run(stopChan)
|
||||
}
|
||||
|
||||
func (ctl *RoleBindingCtl) total() int {
|
||||
list, err := ctl.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Errorf("count %s falied, reason:%s", err, ctl.Name())
|
||||
return 0
|
||||
}
|
||||
return len(list)
|
||||
}
|
||||
|
||||
func (ctl *RoleBindingCtl) initListerAndInformer() {
|
||||
|
||||
informerFactory := informers.NewSharedInformerFactory(ctl.K8sClient, time.Second*resyncCircle)
|
||||
|
||||
ctl.lister = informerFactory.Rbac().V1().RoleBindings().Lister()
|
||||
ctl.informer = informerFactory.Rbac().V1().RoleBindings().Informer()
|
||||
}
|
||||
|
||||
func (ctl *RoleBindingCtl) CountWithConditions(conditions string) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (ctl *RoleBindingCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
return 0, nil, errors.New("not implement")
|
||||
}
|
||||
|
||||
func (ctl *RoleBindingCtl) Lister() interface{} {
|
||||
return ctl.lister
|
||||
}
|
||||
@@ -37,7 +37,7 @@ type resourceControllers struct {
|
||||
|
||||
var ResourceControllers resourceControllers
|
||||
|
||||
func (rec *resourceControllers) runContoller(name string, stopChan chan struct{}, wg *sync.WaitGroup) {
|
||||
func (rec *resourceControllers) runController(name string, stopChan chan struct{}, wg *sync.WaitGroup) {
|
||||
var ctl Controller
|
||||
attr := CommonAttribute{DB: client.NewDBClient(), K8sClient: rec.k8sClient, stopChan: stopChan,
|
||||
aliveChan: make(chan struct{}), Name: name}
|
||||
@@ -78,6 +78,10 @@ func (rec *resourceControllers) runContoller(name string, stopChan chan struct{}
|
||||
ctl = &ConfigMapCtl{CommonAttribute: attr}
|
||||
case Secrets:
|
||||
ctl = &SecretCtl{CommonAttribute: attr}
|
||||
case ClusterRoleBindings:
|
||||
ctl = &ClusterRoleBindingCtl{CommonAttribute: attr}
|
||||
case RoleBindings:
|
||||
ctl = &RoleBindingCtl{CommonAttribute: attr}
|
||||
default:
|
||||
return
|
||||
}
|
||||
@@ -116,9 +120,9 @@ func Run(stopChan chan struct{}, wg *sync.WaitGroup) {
|
||||
ResourceControllers = resourceControllers{k8sClient: k8sClient, Controllers: make(map[string]Controller)}
|
||||
|
||||
for _, item := range []string{Deployments, Statefulsets, Daemonsets, PersistentVolumeClaim, Pods, Services,
|
||||
Ingresses, Roles, ClusterRoles, Namespaces, StorageClasses, Jobs, Cronjobs, Nodes, Replicasets,
|
||||
Ingresses, Roles, RoleBindings, ClusterRoles, ClusterRoleBindings, Namespaces, StorageClasses, Jobs, Cronjobs, Nodes, Replicasets,
|
||||
ControllerRevisions, ConfigMaps, Secrets} {
|
||||
ResourceControllers.runContoller(item, stopChan, wg)
|
||||
ResourceControllers.runController(item, stopChan, wg)
|
||||
}
|
||||
|
||||
go dbHealthCheck(client.NewDBClient())
|
||||
@@ -131,7 +135,7 @@ func Run(stopChan chan struct{}, wg *sync.WaitGroup) {
|
||||
case _, isClose := <-controller.chanAlive():
|
||||
if !isClose {
|
||||
glog.Errorf("controller %s have stopped, restart it", ctlName)
|
||||
ResourceControllers.runContoller(ctlName, stopChan, wg)
|
||||
ResourceControllers.runController(ctlName, stopChan, wg)
|
||||
}
|
||||
default:
|
||||
time.Sleep(3 * time.Second)
|
||||
|
||||
@@ -59,7 +59,9 @@ const (
|
||||
Ingresses = "ingresses"
|
||||
PersistentVolumeClaim = "persistent-volume-claims"
|
||||
Roles = "roles"
|
||||
RoleBindings = "role-bindings"
|
||||
ClusterRoles = "cluster-roles"
|
||||
ClusterRoleBindings = "cluster-role-bindings"
|
||||
Services = "services"
|
||||
StorageClasses = "storage-classes"
|
||||
Applications = "applications"
|
||||
@@ -464,6 +466,17 @@ type ClusterRoleCtl struct {
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type ClusterRoleBindingCtl struct {
|
||||
lister rbacV1.ClusterRoleBindingLister
|
||||
informer cache.SharedIndexInformer
|
||||
CommonAttribute
|
||||
}
|
||||
type RoleBindingCtl struct {
|
||||
lister rbacV1.RoleBindingLister
|
||||
informer cache.SharedIndexInformer
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type JobCtl struct {
|
||||
lister batchv1.JobLister
|
||||
informer cache.SharedIndexInformer
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
@@ -12,10 +11,12 @@ import (
|
||||
"k8s.io/api/rbac/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/pkg/util/slice"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
v12 "k8s.io/client-go/listers/rbac/v1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/controllers"
|
||||
ksErr "kubesphere.io/kubesphere/pkg/util/errors"
|
||||
)
|
||||
|
||||
@@ -133,7 +134,7 @@ func WorkspaceRoleRules(workspace string, roleName string) (*v1.ClusterRole, []R
|
||||
rule := Rule{Name: WorkspaceRoleRuleMapping[i].Name}
|
||||
rule.Actions = make([]Action, 0)
|
||||
for j := 0; j < len(WorkspaceRoleRuleMapping[i].Actions); j++ {
|
||||
if actionValidate(role.Rules, WorkspaceRoleRuleMapping[i].Actions[j]) {
|
||||
if rulesMatchesAction(role.Rules, WorkspaceRoleRuleMapping[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, WorkspaceRoleRuleMapping[i].Actions[j])
|
||||
}
|
||||
}
|
||||
@@ -161,18 +162,22 @@ func GetUserNamespaces(username string, requiredRule v1.PolicyRule) (allNamespac
|
||||
}
|
||||
|
||||
if requiredRule.Size() == 0 {
|
||||
if ruleValidate(clusterRules, v1.PolicyRule{
|
||||
Verbs: []string{"get", "list"},
|
||||
APIGroups: []string{""},
|
||||
Resources: []string{"namespaces"},
|
||||
if RulesMatchesRequired(clusterRules, v1.PolicyRule{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
Resources: []string{"workspaces/namespaces"},
|
||||
}) {
|
||||
return true, nil, nil
|
||||
}
|
||||
} else if ruleValidate(clusterRules, requiredRule) {
|
||||
return true, nil, nil
|
||||
} else {
|
||||
|
||||
if RulesMatchesRequired(clusterRules, requiredRule) {
|
||||
return true, nil, nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
roles, err := GetRoles(username)
|
||||
roles, err := GetRoles("", username)
|
||||
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
@@ -192,7 +197,7 @@ func GetUserNamespaces(username string, requiredRule v1.PolicyRule) (allNamespac
|
||||
namespaces = make([]string, 0)
|
||||
|
||||
for namespace, rules := range rulesMapping {
|
||||
if requiredRule.Size() == 0 || ruleValidate(rules, requiredRule) {
|
||||
if requiredRule.Size() == 0 || RulesMatchesRequired(rules, requiredRule) {
|
||||
namespaces = append(namespaces, namespace)
|
||||
}
|
||||
}
|
||||
@@ -309,22 +314,24 @@ func GetClusterRole(name string) (*v1.ClusterRole, error) {
|
||||
return role, nil
|
||||
}
|
||||
|
||||
func GetRoles(username string) ([]v1.Role, error) {
|
||||
k8s := client.NewK8sClient()
|
||||
func GetRoles(namespace string, username string) ([]v1.Role, error) {
|
||||
roleBindingLister := controllers.ResourceControllers.Controllers[controllers.RoleBindings].Lister().(v12.RoleBindingLister)
|
||||
roleLister := controllers.ResourceControllers.Controllers[controllers.Roles].Lister().(v12.RoleLister)
|
||||
clusterRoleLister := controllers.ResourceControllers.Controllers[controllers.ClusterRoles].Lister().(v12.ClusterRoleLister)
|
||||
|
||||
roleBindings, err := k8s.RbacV1().RoleBindings("").List(meta_v1.ListOptions{})
|
||||
roleBindings, err := roleBindingLister.RoleBindings(namespace).List(labels.Everything())
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roles := make([]v1.Role, 0)
|
||||
|
||||
for _, roleBinding := range roleBindings.Items {
|
||||
for _, roleBinding := range roleBindings {
|
||||
|
||||
for _, subject := range roleBinding.Subjects {
|
||||
if subject.Kind == v1.UserKind && subject.Name == username {
|
||||
if roleBinding.RoleRef.Kind == ClusterRoleKind {
|
||||
clusterRole, err := k8s.RbacV1().ClusterRoles().Get(roleBinding.RoleRef.Name, meta_v1.GetOptions{})
|
||||
clusterRole, err := clusterRoleLister.Get(roleBinding.RoleRef.Name)
|
||||
if err == nil {
|
||||
var role = v1.Role{TypeMeta: (*clusterRole).TypeMeta, ObjectMeta: (*clusterRole).ObjectMeta, Rules: (*clusterRole).Rules}
|
||||
role.Namespace = roleBinding.Namespace
|
||||
@@ -339,7 +346,7 @@ func GetRoles(username string) ([]v1.Role, error) {
|
||||
|
||||
} else {
|
||||
if subject.Kind == v1.UserKind && subject.Name == username {
|
||||
rule, err := k8s.RbacV1().Roles(roleBinding.Namespace).Get(roleBinding.RoleRef.Name, meta_v1.GetOptions{})
|
||||
rule, err := roleLister.Roles(roleBinding.Namespace).Get(roleBinding.RoleRef.Name)
|
||||
if err == nil {
|
||||
roles = append(roles, *rule)
|
||||
break
|
||||
@@ -361,10 +368,12 @@ func GetRoles(username string) ([]v1.Role, error) {
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
// Get cluster roles by username
|
||||
func GetClusterRoles(username string) ([]v1.ClusterRole, error) {
|
||||
k8s := client.NewK8sClient()
|
||||
|
||||
clusterRoleBindings, err := k8s.RbacV1().ClusterRoleBindings().List(meta_v1.ListOptions{})
|
||||
//TODO fix NPE
|
||||
clusterRoleBindingLister := controllers.ResourceControllers.Controllers[controllers.ClusterRoleBindings].Lister().(v12.ClusterRoleBindingLister)
|
||||
clusterRoleLister := controllers.ResourceControllers.Controllers[controllers.ClusterRoles].Lister().(v12.ClusterRoleLister)
|
||||
clusterRoleBindings, err := clusterRoleBindingLister.List(labels.Everything())
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -372,27 +381,24 @@ func GetClusterRoles(username string) ([]v1.ClusterRole, error) {
|
||||
|
||||
roles := make([]v1.ClusterRole, 0)
|
||||
|
||||
for _, roleBinding := range clusterRoleBindings.Items {
|
||||
for _, roleBinding := range clusterRoleBindings {
|
||||
for _, subject := range roleBinding.Subjects {
|
||||
if subject.Kind == v1.UserKind && subject.Name == username {
|
||||
if roleBinding.RoleRef.Kind == ClusterRoleKind {
|
||||
role, err := k8s.RbacV1().ClusterRoles().Get(roleBinding.RoleRef.Name, meta_v1.GetOptions{})
|
||||
role, err := clusterRoleLister.Get(roleBinding.RoleRef.Name)
|
||||
if err == nil {
|
||||
if role.Annotations == nil {
|
||||
role.Annotations = make(map[string]string, 0)
|
||||
}
|
||||
|
||||
role.Annotations["rbac.authorization.k8s.io/clusterrolebinding"] = roleBinding.Name
|
||||
|
||||
if roleBinding.Annotations != nil &&
|
||||
roleBinding.Annotations["rbac.authorization.k8s.io/clusterrole"] == roleBinding.RoleRef.Name {
|
||||
role.Annotations["rbac.authorization.k8s.io/clusterrole"] = "true"
|
||||
}
|
||||
|
||||
roles = append(roles, *role)
|
||||
break
|
||||
} else if apierrors.IsNotFound(err) {
|
||||
log.Println(err)
|
||||
glog.Warning(err)
|
||||
break
|
||||
} else {
|
||||
return nil, err
|
||||
@@ -405,80 +411,80 @@ func GetClusterRoles(username string) ([]v1.ClusterRole, error) {
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
func ruleValidate(rules []v1.PolicyRule, rule v1.PolicyRule) bool {
|
||||
//func RuleValidate(rules []v1.PolicyRule, rule v1.PolicyRule) bool {
|
||||
//
|
||||
// for _, apiGroup := range rule.APIGroups {
|
||||
// if len(rule.NonResourceURLs) == 0 {
|
||||
// for _, resource := range rule.Resources {
|
||||
//
|
||||
// //if len(Rule.ResourceNames) == 0 {
|
||||
//
|
||||
// for _, verb := range rule.Verbs {
|
||||
// if !verbValidate(rules, apiGroup, "", resource, "", verb) {
|
||||
// return false
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// //} else {
|
||||
// // for _, resourceName := range Rule.ResourceNames {
|
||||
// // for _, verb := range Rule.Verbs {
|
||||
// // if !verbValidate(rules, apiGroup, "", resource, resourceName, verb) {
|
||||
// // return false
|
||||
// // }
|
||||
// // }
|
||||
// // }
|
||||
// //}
|
||||
// }
|
||||
// } else {
|
||||
// for _, nonResourceURL := range rule.NonResourceURLs {
|
||||
// for _, verb := range rule.Verbs {
|
||||
// if !verbValidate(rules, apiGroup, nonResourceURL, "", "", verb) {
|
||||
// return false
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return true
|
||||
//}
|
||||
|
||||
for _, apiGroup := range rule.APIGroups {
|
||||
if len(rule.NonResourceURLs) == 0 {
|
||||
for _, resource := range rule.Resources {
|
||||
|
||||
//if len(Rule.ResourceNames) == 0 {
|
||||
|
||||
for _, verb := range rule.Verbs {
|
||||
if !verbValidate(rules, apiGroup, "", resource, "", verb) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
//} else {
|
||||
// for _, resourceName := range Rule.ResourceNames {
|
||||
// for _, verb := range Rule.Verbs {
|
||||
// if !verbValidate(rules, apiGroup, "", resource, resourceName, verb) {
|
||||
// return false
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
} else {
|
||||
for _, nonResourceURL := range rule.NonResourceURLs {
|
||||
for _, verb := range rule.Verbs {
|
||||
if !verbValidate(rules, apiGroup, nonResourceURL, "", "", verb) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func verbValidate(rules []v1.PolicyRule, apiGroup string, nonResourceURL string, resource string, resourceName string, verb string) bool {
|
||||
for _, rule := range rules {
|
||||
|
||||
if nonResourceURL == "" {
|
||||
if slice.ContainsString(rule.APIGroups, apiGroup, nil) ||
|
||||
slice.ContainsString(rule.APIGroups, v1.APIGroupAll, nil) {
|
||||
if slice.ContainsString(rule.Verbs, verb, nil) ||
|
||||
slice.ContainsString(rule.Verbs, v1.VerbAll, nil) {
|
||||
if slice.ContainsString(rule.Resources, v1.ResourceAll, nil) {
|
||||
return true
|
||||
} else if slice.ContainsString(rule.Resources, resource, nil) {
|
||||
if len(rule.ResourceNames) > 0 {
|
||||
if slice.ContainsString(rule.ResourceNames, resourceName, nil) {
|
||||
return true
|
||||
}
|
||||
} else if resourceName == "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if slice.ContainsString(rule.NonResourceURLs, nonResourceURL, nil) ||
|
||||
slice.ContainsString(rule.NonResourceURLs, v1.NonResourceAll, nil) {
|
||||
if slice.ContainsString(rule.Verbs, verb, nil) ||
|
||||
slice.ContainsString(rule.Verbs, v1.VerbAll, nil) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
//func verbValidate(rules []v1.PolicyRule, apiGroup string, nonResourceURL string, resource string, resourceName string, verb string) bool {
|
||||
// for _, rule := range rules {
|
||||
//
|
||||
// if nonResourceURL == "" {
|
||||
// if slice.ContainsString(rule.APIGroups, apiGroup, nil) ||
|
||||
// slice.ContainsString(rule.APIGroups, v1.APIGroupAll, nil) {
|
||||
// if slice.ContainsString(rule.Verbs, verb, nil) ||
|
||||
// slice.ContainsString(rule.Verbs, v1.VerbAll, nil) {
|
||||
// if slice.ContainsString(rule.Resources, v1.ResourceAll, nil) {
|
||||
// return true
|
||||
// } else if slice.ContainsString(rule.Resources, resource, nil) {
|
||||
// if len(rule.ResourceNames) > 0 {
|
||||
// if slice.ContainsString(rule.ResourceNames, resourceName, nil) {
|
||||
// return true
|
||||
// }
|
||||
// } else if resourceName == "" {
|
||||
// return true
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// } else if slice.ContainsString(rule.NonResourceURLs, nonResourceURL, nil) ||
|
||||
// slice.ContainsString(rule.NonResourceURLs, v1.NonResourceAll, nil) {
|
||||
// if slice.ContainsString(rule.Verbs, verb, nil) ||
|
||||
// slice.ContainsString(rule.Verbs, v1.VerbAll, nil) {
|
||||
// return true
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return false
|
||||
//}
|
||||
|
||||
func GetUserRules(username string) (map[string][]Rule, error) {
|
||||
|
||||
items := make(map[string][]Rule, 0)
|
||||
userRoles, err := GetRoles(username)
|
||||
userRoles, err := GetRoles("", username)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -508,12 +514,12 @@ func GetUserRules(username string) (map[string][]Rule, error) {
|
||||
func convertToRules(policyRules []v1.PolicyRule) []Rule {
|
||||
rules := make([]Rule, 0)
|
||||
|
||||
for i := 0; i < (len(RoleRuleGroup)); i++ {
|
||||
rule := Rule{Name: RoleRuleGroup[i].Name}
|
||||
for i := 0; i < (len(RoleRuleMapping)); i++ {
|
||||
rule := Rule{Name: RoleRuleMapping[i].Name}
|
||||
rule.Actions = make([]Action, 0)
|
||||
for j := 0; j < (len(RoleRuleGroup[i].Actions)); j++ {
|
||||
if actionValidate(policyRules, RoleRuleGroup[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, RoleRuleGroup[i].Actions[j])
|
||||
for j := 0; j < (len(RoleRuleMapping[i].Actions)); j++ {
|
||||
if rulesMatchesAction(policyRules, RoleRuleMapping[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, RoleRuleMapping[i].Actions[j])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,12 +547,12 @@ func GetUserClusterRules(username string) ([]Rule, error) {
|
||||
clusterRules = append(clusterRules, role.Rules...)
|
||||
}
|
||||
|
||||
for i := 0; i < (len(ClusterRoleRuleGroup)); i++ {
|
||||
rule := Rule{Name: ClusterRoleRuleGroup[i].Name}
|
||||
for i := 0; i < (len(ClusterRoleRuleMapping)); i++ {
|
||||
rule := Rule{Name: ClusterRoleRuleMapping[i].Name}
|
||||
rule.Actions = make([]Action, 0)
|
||||
for j := 0; j < (len(ClusterRoleRuleGroup[i].Actions)); j++ {
|
||||
if actionValidate(clusterRules, ClusterRoleRuleGroup[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, ClusterRoleRuleGroup[i].Actions[j])
|
||||
for j := 0; j < (len(ClusterRoleRuleMapping[i].Actions)); j++ {
|
||||
if rulesMatchesAction(clusterRules, ClusterRoleRuleMapping[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, ClusterRoleRuleMapping[i].Actions[j])
|
||||
}
|
||||
}
|
||||
if len(rule.Actions) > 0 {
|
||||
@@ -567,12 +573,12 @@ func GetClusterRoleRules(name string) ([]Rule, error) {
|
||||
|
||||
rules := make([]Rule, 0)
|
||||
|
||||
for i := 0; i < len(ClusterRoleRuleGroup); i++ {
|
||||
rule := Rule{Name: ClusterRoleRuleGroup[i].Name}
|
||||
for i := 0; i < len(ClusterRoleRuleMapping); i++ {
|
||||
rule := Rule{Name: ClusterRoleRuleMapping[i].Name}
|
||||
rule.Actions = make([]Action, 0)
|
||||
for j := 0; j < (len(ClusterRoleRuleGroup[i].Actions)); j++ {
|
||||
if actionValidate(clusterRole.Rules, ClusterRoleRuleGroup[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, ClusterRoleRuleGroup[i].Actions[j])
|
||||
for j := 0; j < (len(ClusterRoleRuleMapping[i].Actions)); j++ {
|
||||
if rulesMatchesAction(clusterRole.Rules, ClusterRoleRuleMapping[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, ClusterRoleRuleMapping[i].Actions[j])
|
||||
}
|
||||
}
|
||||
if len(rule.Actions) > 0 {
|
||||
@@ -590,12 +596,12 @@ func GetRoleRules(namespace string, name string) ([]Rule, error) {
|
||||
}
|
||||
|
||||
rules := make([]Rule, 0)
|
||||
for i := 0; i < len(RoleRuleGroup); i++ {
|
||||
rule := Rule{Name: RoleRuleGroup[i].Name}
|
||||
for i := 0; i < len(RoleRuleMapping); i++ {
|
||||
rule := Rule{Name: RoleRuleMapping[i].Name}
|
||||
rule.Actions = make([]Action, 0)
|
||||
for j := 0; j < len(RoleRuleGroup[i].Actions); j++ {
|
||||
if actionValidate(role.Rules, RoleRuleGroup[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, RoleRuleGroup[i].Actions[j])
|
||||
for j := 0; j < len(RoleRuleMapping[i].Actions); j++ {
|
||||
if rulesMatchesAction(role.Rules, RoleRuleMapping[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, RoleRuleMapping[i].Actions[j])
|
||||
}
|
||||
}
|
||||
if len(rule.Actions) > 0 {
|
||||
@@ -605,11 +611,157 @@ func GetRoleRules(namespace string, name string) ([]Rule, error) {
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func actionValidate(rules []v1.PolicyRule, action Action) bool {
|
||||
func rulesMatchesAction(rules []v1.PolicyRule, action Action) bool {
|
||||
|
||||
for _, rule := range action.Rules {
|
||||
if !ruleValidate(rules, rule) {
|
||||
if !RulesMatchesRequired(rules, rule) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func RulesMatchesRequired(rules []v1.PolicyRule, required v1.PolicyRule) bool {
|
||||
for _, rule := range rules {
|
||||
if ruleMatchesRequired(rule, required) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func ruleMatchesRequired(rule v1.PolicyRule, required v1.PolicyRule) bool {
|
||||
|
||||
if len(required.NonResourceURLs) == 0 {
|
||||
for _, apiGroup := range required.APIGroups {
|
||||
for _, resource := range required.Resources {
|
||||
resources := strings.Split(resource, "/")
|
||||
resource = resources[0]
|
||||
var subsource string
|
||||
if len(resources) > 1 {
|
||||
subsource = resources[1]
|
||||
}
|
||||
|
||||
if len(required.ResourceNames) == 0 {
|
||||
for _, verb := range required.Verbs {
|
||||
if !ruleMatchesRequest(rule, apiGroup, "", resource, subsource, "", verb) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, resourceName := range required.ResourceNames {
|
||||
for _, verb := range required.Verbs {
|
||||
if !ruleMatchesRequest(rule, apiGroup, "", resource, subsource, resourceName, verb) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, apiGroup := range required.APIGroups {
|
||||
for _, nonResourceURL := range required.NonResourceURLs {
|
||||
for _, verb := range required.Verbs {
|
||||
if !ruleMatchesRequest(rule, apiGroup, nonResourceURL, "", "", "", verb) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func ruleMatchesResources(rule v1.PolicyRule, apiGroup string, resource string, subresource string, resourceName string) bool {
|
||||
|
||||
if resource == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
if !hasString(rule.APIGroups, apiGroup) && !hasString(rule.APIGroups, v1.ResourceAll) {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(rule.ResourceNames) > 0 && !hasString(rule.ResourceNames, resourceName) {
|
||||
return false
|
||||
}
|
||||
|
||||
combinedResource := resource
|
||||
|
||||
if subresource != "" {
|
||||
combinedResource = combinedResource + "/" + subresource
|
||||
}
|
||||
|
||||
for _, res := range rule.Resources {
|
||||
|
||||
// match "*"
|
||||
if res == v1.ResourceAll || res == combinedResource {
|
||||
return true
|
||||
}
|
||||
|
||||
// match "*/subresource"
|
||||
if len(subresource) > 0 && strings.HasPrefix(res, "*/") && subresource == strings.TrimLeft(res, "*/") {
|
||||
return true
|
||||
}
|
||||
// match "resource/*"
|
||||
if strings.HasSuffix(res, "/*") && resource == strings.TrimRight(res, "/*") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func ruleMatchesRequest(rule v1.PolicyRule, apiGroup string, nonResourceURL string, resource string, subresource string, resourceName string, verb string) bool {
|
||||
|
||||
if !hasString(rule.Verbs, verb) && !hasString(rule.Verbs, v1.VerbAll) {
|
||||
return false
|
||||
}
|
||||
|
||||
if nonResourceURL == "" {
|
||||
return ruleMatchesResources(rule, apiGroup, resource, subresource, resourceName)
|
||||
} else {
|
||||
return ruleMatchesNonResource(rule, nonResourceURL)
|
||||
}
|
||||
}
|
||||
|
||||
func ruleMatchesNonResource(rule v1.PolicyRule, nonResourceURL string) bool {
|
||||
|
||||
if nonResourceURL == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, spec := range rule.NonResourceURLs {
|
||||
if pathMatches(nonResourceURL, spec) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func pathMatches(path, spec string) bool {
|
||||
// Allow wildcard match
|
||||
if spec == "*" {
|
||||
return true
|
||||
}
|
||||
// Allow exact match
|
||||
if spec == path {
|
||||
return true
|
||||
}
|
||||
// Allow a trailing * subpath match
|
||||
if strings.HasSuffix(spec, "*") && strings.HasPrefix(path, strings.TrimRight(spec, "*")) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func hasString(slice []string, value string) bool {
|
||||
for _, s := range slice {
|
||||
if s == value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
0
pkg/models/metrics/containers.go
Normal file → Executable file
0
pkg/models/metrics/containers.go
Normal file → Executable file
129
pkg/models/metrics/metricscollector.go
Normal file → Executable file
129
pkg/models/metrics/metricscollector.go
Normal file → Executable file
@@ -26,11 +26,19 @@ import (
|
||||
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/api/core/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"sync"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
v12 "k8s.io/client-go/listers/core/v1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
"kubesphere.io/kubesphere/pkg/models/controllers"
|
||||
"kubesphere.io/kubesphere/pkg/models/workspaces"
|
||||
)
|
||||
|
||||
func getPodNameRegexInWorkload(request *restful.Request) string {
|
||||
@@ -186,6 +194,15 @@ func MonitorAllMetrics(request *restful.Request) FormatedLevelMetric {
|
||||
go collectPodMetrics(request, metricName, ch)
|
||||
} else if sourceType == MetricLevelWorkload {
|
||||
go collectWorkloadMetrics(request, metricName, ch)
|
||||
} else if sourceType == MetricLevelWorkspace {
|
||||
name := request.PathParameter("workspace_name")
|
||||
namespaces, err := workspaces.WorkspaceNamespaces(name)
|
||||
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
}
|
||||
namespaces = filterNamespace(request, namespaces)
|
||||
go collectWorkspaceMetrics(request, metricName, namespaces, ch)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -213,6 +230,106 @@ func MonitorAllMetrics(request *restful.Request) FormatedLevelMetric {
|
||||
}
|
||||
}
|
||||
|
||||
func MonitorWorkspaceUserInfo(req *restful.Request) FormatedLevelMetric {
|
||||
|
||||
var metricsArray []FormatedMetric
|
||||
timestamp := time.Now().Unix()
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
var orgResultItem FormatedMetric
|
||||
var dvpResultItem FormatedMetric
|
||||
var projResultItem FormatedMetric
|
||||
var actResultItem FormatedMetric
|
||||
|
||||
wg.Add(4)
|
||||
|
||||
go func() {
|
||||
orgNums, errOrg := workspaces.GetAllOrgNums()
|
||||
orgResultItem = getSpecificMetricItem(timestamp, MetricNameWorkspaceAllOrganizationCount, WorkspaceResourceKindOrganization, orgNums, errOrg)
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
devOpsProjectNums, errDevops := workspaces.GetAllDevOpsProjectsNums()
|
||||
dvpResultItem = getSpecificMetricItem(timestamp, MetricNameWorkspaceAllDevopsCount, WorkspaceResourceKindDevops, devOpsProjectNums, errDevops)
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
projNums, errProj := workspaces.GetAllProjectNums()
|
||||
projResultItem = getSpecificMetricItem(timestamp, MetricNameWorkspaceAllProjectCount, WorkspaceResourceKindNamespace, projNums, errProj)
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
actNums, errAct := workspaces.GetAllAccountNums()
|
||||
actResultItem = getSpecificMetricItem(timestamp, MetricNameWorkspaceAllAccountCount, WorkspaceResourceKindAccount, actNums, errAct)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
metricsArray = append(metricsArray, orgResultItem, dvpResultItem, projResultItem, actResultItem)
|
||||
|
||||
return FormatedLevelMetric{
|
||||
MetricsLevel: MetricLevelWorkspace,
|
||||
Results: metricsArray,
|
||||
}
|
||||
}
|
||||
|
||||
//func getWorkspaceMetricItem(timestamp int64, namespaceNums int64, resourceName string, err error) FormatedMetric {
|
||||
// var fMetric FormatedMetric
|
||||
// fMetric.Data.ResultType = ResultTypeVector
|
||||
// fMetric.MetricName = MetricNameWorkspaceInfoCount
|
||||
// fMetric.Status = MetricStatusSuccess
|
||||
// if err != nil {
|
||||
// fMetric.Status = MetricStatusError
|
||||
// }
|
||||
// resultItem := make(map[string]interface{})
|
||||
// tmp := make(map[string]string)
|
||||
// tmp[ResultItemMetricResource] = resourceName
|
||||
// resultItem[ResultItemMetric] = tmp
|
||||
// resultItem[ResultItemValue] = []interface{}{timestamp, strconv.FormatInt(namespaceNums, 10)}
|
||||
// return fMetric
|
||||
//}
|
||||
|
||||
func MonitorWorkspaceResourceLevelMetrics(request *restful.Request) FormatedLevelMetric {
|
||||
wsName := request.PathParameter("workspace_name")
|
||||
namspaces, errNs := workspaces.WorkspaceNamespaces(wsName)
|
||||
|
||||
devOpsProjects, errDevOps := workspaces.GetDevOpsProjects(wsName)
|
||||
members, errMemb := workspaces.GetOrgMembers(wsName)
|
||||
roles, errRole := workspaces.GetOrgRoles(wsName)
|
||||
|
||||
var fMetricsArray []FormatedMetric
|
||||
timestamp := int64(time.Now().Unix())
|
||||
namespaces, noneExistentNs := getExistingNamespace(namspaces)
|
||||
if len(noneExistentNs) != 0 {
|
||||
nsStr := strings.Join(noneExistentNs, "|")
|
||||
errStr := "the namespaces " + nsStr + " do not exist"
|
||||
if errNs == nil {
|
||||
errNs = errors.New(errStr)
|
||||
} else {
|
||||
errNs = errors.New(errNs.Error() + "\t" + errStr)
|
||||
}
|
||||
}
|
||||
|
||||
// add namespaces(project) metric
|
||||
nsMetrics := getSpecificMetricItem(timestamp, MetricNameWorkspaceNamespaceCount, WorkspaceResourceKindNamespace, len(namespaces), errNs)
|
||||
// add devops metric
|
||||
devopsMetrics := getSpecificMetricItem(timestamp, MetricNameWorkspaceDevopsCount, WorkspaceResourceKindDevops, len(devOpsProjects), errDevOps)
|
||||
// add member metric
|
||||
memberMetrics := getSpecificMetricItem(timestamp, MetricNameWorkspaceMemberCount, WorkspaceResourceKindMember, len(members), errMemb)
|
||||
// add role metric
|
||||
roleMetrics := getSpecificMetricItem(timestamp, MetricNameWorkspaceRoleCount, WorkspaceResourceKindRole, len(roles), errRole)
|
||||
// add workloads count metric
|
||||
wlMetrics := getWorkspaceWorkloadCountMetrics(namespaces)
|
||||
// add pods count metric
|
||||
podsCountMetrics := getWorkspacePodsCountMetrics(request, namespaces)
|
||||
fMetricsArray = append(fMetricsArray, nsMetrics, devopsMetrics, memberMetrics, roleMetrics, wlMetrics, *podsCountMetrics)
|
||||
|
||||
return FormatedLevelMetric{
|
||||
MetricsLevel: MetricLevelWorkspace,
|
||||
Results: fMetricsArray,
|
||||
}
|
||||
}
|
||||
|
||||
func getWorkspacePodsCountMetrics(request *restful.Request, namespaces []string) *FormatedMetric {
|
||||
metricName := MetricNameNamespacePodCount
|
||||
var recordingRule = RulePromQLTmplMap[metricName]
|
||||
@@ -289,13 +406,13 @@ func MonitorNodeorClusterSingleMetric(request *restful.Request, metricsName stri
|
||||
var fMetric FormatedMetric
|
||||
timestamp := int64(time.Now().Unix())
|
||||
|
||||
if metricsName == MetricNameClusterHealthyNodeCount {
|
||||
if metricsName == "cluster_node_online" {
|
||||
onlineNodes, _ := getNodeHealthyConditionMetric()
|
||||
fMetric = getSpecificMetricItem(timestamp, MetricNameClusterHealthyNodeCount, "node_count", len(onlineNodes), nil)
|
||||
} else if metricsName == MetricNameClusterUnhealthyNodeCount {
|
||||
} else if metricsName == "cluster_node_offline" {
|
||||
_, offlineNodes := getNodeHealthyConditionMetric()
|
||||
fMetric = getSpecificMetricItem(timestamp, MetricNameClusterUnhealthyNodeCount, "node_count", len(offlineNodes), nil)
|
||||
} else if metricsName == MetricNameClusterNodeCount {
|
||||
} else if metricsName == "cluster_node_total" {
|
||||
onlineNodes, offlineNodes := getNodeHealthyConditionMetric()
|
||||
fMetric = getSpecificMetricItem(timestamp, MetricNameClusterNodeCount, "node_count", len(onlineNodes)+len(offlineNodes), nil)
|
||||
} else {
|
||||
@@ -355,14 +472,14 @@ func getExistingNamespace(namespaces []string) ([]string, []string) {
|
||||
}
|
||||
|
||||
func getAllNamespace() (map[string]int, error) {
|
||||
k8sClient := client.NewK8sClient()
|
||||
nsList, err := k8sClient.CoreV1().Namespaces().List(metaV1.ListOptions{})
|
||||
lister := controllers.ResourceControllers.Controllers[controllers.Namespaces].Lister().(v12.NamespaceLister)
|
||||
nsList, err := lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
namespaceMap := make(map[string]int)
|
||||
for _, item := range nsList.Items {
|
||||
for _, item := range nsList {
|
||||
namespaceMap[item.Name] = 0
|
||||
}
|
||||
return namespaceMap, nil
|
||||
|
||||
2
pkg/models/metrics/metricsconst.go
Normal file → Executable file
2
pkg/models/metrics/metricsconst.go
Normal file → Executable file
@@ -148,7 +148,7 @@ var RulePromQLTmplMap = MetricMap{
|
||||
"cluster_memory_bytes_available": "sum(node:node_memory_bytes_available:sum)",
|
||||
"cluster_memory_bytes_total": "sum(node:node_memory_bytes_total:sum)",
|
||||
"cluster_memory_bytes_usage": "sum(node:node_memory_bytes_total:sum) - sum(node:node_memory_bytes_available:sum)",
|
||||
"cluster_net_utilisation": "sum(node:node_net_utilisation:sum_irate)",
|
||||
"cluster_net_utilisation": ":node_net_utilisation:sum_irate",
|
||||
"cluster_net_bytes_transmitted": "sum(node:node_net_bytes_transmitted:sum_irate)",
|
||||
"cluster_net_bytes_received": "sum(node:node_net_bytes_received:sum_irate)",
|
||||
"cluster_disk_read_iops": "sum(node:data_volume_iops_reads:sum)",
|
||||
|
||||
0
pkg/models/metrics/metricsrule.go
Normal file → Executable file
0
pkg/models/metrics/metricsrule.go
Normal file → Executable file
0
pkg/models/metrics/metricsstruct.go
Normal file → Executable file
0
pkg/models/metrics/metricsstruct.go
Normal file → Executable file
0
pkg/models/metrics/nodes.go
Normal file → Executable file
0
pkg/models/metrics/nodes.go
Normal file → Executable file
0
pkg/models/metrics/pods.go
Normal file → Executable file
0
pkg/models/metrics/pods.go
Normal file → Executable file
@@ -4,8 +4,9 @@ import "time"
|
||||
|
||||
type Workspace struct {
|
||||
Group `json:",inline"`
|
||||
Namespaces []string `json:"namespaces,omitempty"`
|
||||
DevopsProjects []string `json:"devops_projects,omitempty"`
|
||||
Admin string `json:"admin,omitempty"`
|
||||
Namespaces []string `json:"namespaces"`
|
||||
DevopsProjects []string `json:"devops_projects"`
|
||||
}
|
||||
|
||||
type UserInvite struct {
|
||||
|
||||
@@ -7,19 +7,21 @@ import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
core "k8s.io/api/core/v1"
|
||||
k8sErr "k8s.io/apimachinery/pkg/api/errors"
|
||||
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
core "k8s.io/api/core/v1"
|
||||
|
||||
"errors"
|
||||
"regexp"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"k8s.io/api/rbac/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
v13 "k8s.io/client-go/listers/rbac/v1"
|
||||
clientV1 "k8s.io/client-go/listers/core/v1"
|
||||
"k8s.io/kubernetes/pkg/util/slice"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
@@ -31,12 +33,6 @@ import (
|
||||
|
||||
var WorkSpaceRoles = []string{"admin", "operator", "viewer"}
|
||||
|
||||
func UnBindNamespace(workspace string, namespace string) error {
|
||||
db := client.NewSharedDBClient()
|
||||
defer db.Close()
|
||||
return db.Delete(&WorkspaceNSBinding{Workspace: workspace, Namespace: namespace}).Error
|
||||
}
|
||||
|
||||
func UnBindDevopsProject(workspace string, devops string) error {
|
||||
db := client.NewSharedDBClient()
|
||||
defer db.Close()
|
||||
@@ -100,44 +96,85 @@ func CreateDevopsProject(username string, devops DevopsProject) (*DevopsProject,
|
||||
return &project, nil
|
||||
}
|
||||
|
||||
func Namespaces(workspace string) ([]*core.Namespace, error) {
|
||||
db := client.NewSharedDBClient()
|
||||
defer db.Close()
|
||||
func ListNamespaceByUser(workspaceName string, username string) ([]*core.Namespace, error) {
|
||||
|
||||
var workspaceNSBindings []WorkspaceNSBinding
|
||||
namespaces, err := Namespaces(workspaceName)
|
||||
|
||||
if err := db.Where("workspace = ?", workspace).Find(&workspaceNSBindings).Error; err != nil {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
namespaces := make([]*core.Namespace, 0)
|
||||
clusterRoles, err := iam.GetClusterRoles(username)
|
||||
|
||||
for _, workspaceNSBinding := range workspaceNSBindings {
|
||||
namespace, err := client.NewK8sClient().CoreV1().Namespaces().Get(workspaceNSBinding.Namespace, meta_v1.GetOptions{})
|
||||
if err != nil {
|
||||
if k8sErr.IsNotFound(err) {
|
||||
db.Delete(&WorkspaceNSBinding{Workspace: workspace, Namespace: workspaceNSBinding.Namespace})
|
||||
} else {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rules := make([]v1.PolicyRule, 0)
|
||||
|
||||
for _, clusterRole := range clusterRoles {
|
||||
rules = append(rules, clusterRole.Rules...)
|
||||
}
|
||||
|
||||
namespacesManager := v1.PolicyRule{APIGroups: []string{"kubesphere.io"}, ResourceNames: []string{workspaceName}, Verbs: []string{"get"}, Resources: []string{"workspaces/namespaces"}}
|
||||
|
||||
if iam.RulesMatchesRequired(rules, namespacesManager) {
|
||||
return namespaces, nil
|
||||
} else {
|
||||
for i := 0; i < len(namespaces); i++ {
|
||||
roles, err := iam.GetRoles(namespaces[i].Name, username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
namespaces = append(namespaces, namespace)
|
||||
rules := make([]v1.PolicyRule, 0)
|
||||
for _, role := range roles {
|
||||
rules = append(rules, role.Rules...)
|
||||
}
|
||||
if !iam.RulesMatchesRequired(rules, v1.PolicyRule{APIGroups: []string{""}, ResourceNames: []string{namespaces[i].Name}, Verbs: []string{"get"}, Resources: []string{"namespaces"}}) {
|
||||
namespaces = append(namespaces[:i], namespaces[i+1:]...)
|
||||
i--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return namespaces, nil
|
||||
}
|
||||
|
||||
func Namespaces(workspaceName string) ([]*core.Namespace, error) {
|
||||
|
||||
lister := controllers.ResourceControllers.Controllers[controllers.Namespaces].Lister().(clientV1.NamespaceLister)
|
||||
|
||||
namespaces, err := lister.List(labels.SelectorFromSet(labels.Set{"kubesphere.io/workspace": workspaceName}))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if namespaces == nil {
|
||||
return make([]*core.Namespace, 0), nil
|
||||
}
|
||||
|
||||
return namespaces, nil
|
||||
}
|
||||
|
||||
func BindingDevopsProject(workspace string, devops string) error {
|
||||
db := client.NewSharedDBClient()
|
||||
defer db.Close()
|
||||
return db.Create(&WorkspaceDPBinding{Workspace: workspace, DevOpsProject: devops}).Error
|
||||
}
|
||||
|
||||
func DeleteNamespace(namespace string) error {
|
||||
deletePolicy := meta_v1.DeletePropagationBackground
|
||||
err := client.NewK8sClient().CoreV1().Namespaces().Delete(namespace, &meta_v1.DeleteOptions{PropagationPolicy: &deletePolicy})
|
||||
return err
|
||||
func DeleteNamespace(workspace string, namespaceName string) error {
|
||||
namespace, err := client.NewK8sClient().CoreV1().Namespaces().Get(namespaceName, meta_v1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if namespace.Labels != nil && namespace.Labels["kubesphere.io/workspace"] == workspace {
|
||||
deletePolicy := meta_v1.DeletePropagationBackground
|
||||
return client.NewK8sClient().CoreV1().Namespaces().Delete(namespaceName, &meta_v1.DeleteOptions{PropagationPolicy: &deletePolicy})
|
||||
} else {
|
||||
return errors.New("resource not found")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Delete(workspace *Workspace) error {
|
||||
@@ -174,7 +211,7 @@ func Delete(workspace *Workspace) error {
|
||||
|
||||
func release(workspace *Workspace) error {
|
||||
for _, namespace := range workspace.Namespaces {
|
||||
err := DeleteNamespace(namespace)
|
||||
err := DeleteNamespace(workspace.Name, namespace)
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
@@ -335,7 +372,44 @@ func Detail(name string) (*Workspace, error) {
|
||||
return workspace, nil
|
||||
}
|
||||
|
||||
func List(names []string) ([]*Workspace, error) {
|
||||
// List all workspaces for the current user
|
||||
func ListByUser(username string) ([]*Workspace, error) {
|
||||
|
||||
clusterRoles, err := iam.GetClusterRoles(username)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rules := make([]v1.PolicyRule, 0)
|
||||
|
||||
for _, clusterRole := range clusterRoles {
|
||||
rules = append(rules, clusterRole.Rules...)
|
||||
}
|
||||
|
||||
workspacesManager := v1.PolicyRule{APIGroups: []string{"kubesphere.io"}, Verbs: []string{"list", "get"}, Resources: []string{"workspaces"}}
|
||||
|
||||
if iam.RulesMatchesRequired(rules, workspacesManager) {
|
||||
return fetch(nil)
|
||||
} else {
|
||||
workspaceNames := make([]string, 0)
|
||||
|
||||
for _, clusterRole := range clusterRoles {
|
||||
if regexp.MustCompile("^system:\\w+:(admin|operator|viewer)$").MatchString(clusterRole.Name) {
|
||||
arr := strings.Split(clusterRole.Name, ":")
|
||||
workspaceNames = append(workspaceNames, arr[1])
|
||||
}
|
||||
}
|
||||
|
||||
if len(workspaceNames) == 0 {
|
||||
return make([]*Workspace, 0), nil
|
||||
}
|
||||
|
||||
return fetch(workspaceNames)
|
||||
}
|
||||
}
|
||||
|
||||
func fetch(names []string) ([]*Workspace, error) {
|
||||
|
||||
url := fmt.Sprintf("http://%s/apis/account.kubesphere.io/v1alpha1/groups", constants.AccountAPIServer)
|
||||
|
||||
@@ -379,6 +453,7 @@ func List(names []string) ([]*Workspace, error) {
|
||||
}
|
||||
workspaces = append(workspaces, workspace)
|
||||
}
|
||||
|
||||
return workspaces, nil
|
||||
}
|
||||
|
||||
@@ -434,16 +509,16 @@ func DevopsProjects(workspace string) ([]DevopsProject, error) {
|
||||
|
||||
}
|
||||
func convertGroupToWorkspace(db *gorm.DB, group Group) (*Workspace, error) {
|
||||
var workspaceNSBindings []WorkspaceNSBinding
|
||||
namespaces, err := Namespaces(group.Name)
|
||||
|
||||
if err := db.Where("workspace = ?", group.Name).Find(&workspaceNSBindings).Error; err != nil {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
namespaces := make([]string, 0)
|
||||
namespacesNames := make([]string, 0)
|
||||
|
||||
for _, workspaceNSBinding := range workspaceNSBindings {
|
||||
namespaces = append(namespaces, workspaceNSBinding.Namespace)
|
||||
for _, namespace := range namespaces {
|
||||
namespacesNames = append(namespacesNames, namespace.Name)
|
||||
}
|
||||
|
||||
var workspaceDOPBindings []WorkspaceDPBinding
|
||||
@@ -459,7 +534,7 @@ func convertGroupToWorkspace(db *gorm.DB, group Group) (*Workspace, error) {
|
||||
}
|
||||
|
||||
workspace := Workspace{Group: group}
|
||||
workspace.Namespaces = namespaces
|
||||
workspace.Namespaces = namespacesNames
|
||||
workspace.DevopsProjects = devOpsProjects
|
||||
return &workspace, nil
|
||||
}
|
||||
@@ -468,12 +543,6 @@ func CreateNamespace(namespace *core.Namespace) (*core.Namespace, error) {
|
||||
return client.NewK8sClient().CoreV1().Namespaces().Create(namespace)
|
||||
}
|
||||
|
||||
func BindingNamespace(workspace string, namespace string) error {
|
||||
db := client.NewSharedDBClient()
|
||||
defer db.Close()
|
||||
return db.Create(&WorkspaceNSBinding{Workspace: workspace, Namespace: namespace}).Error
|
||||
}
|
||||
|
||||
func Invite(workspaceName string, users []UserInvite) error {
|
||||
for _, user := range users {
|
||||
if !slice.ContainsString(WorkSpaceRoles, user.Role, nil) {
|
||||
@@ -523,38 +592,22 @@ func RemoveMembers(workspaceName string, users []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < len(workspace.Members); i++ {
|
||||
if slice.ContainsString(users, workspace.Members[i], nil) {
|
||||
workspace.Members = append(workspace.Members[:i], workspace.Members[i+1:]...)
|
||||
i--
|
||||
}
|
||||
}
|
||||
|
||||
workspace, err = Edit(workspace)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//func checkUserExist(username string) (bool, error) {
|
||||
// result, err := http.Get(fmt.Sprintf("http://%s/apis/account.kubesphere.io/v1alpha1/users?check=%s", constants.AccountAPIServer, username))
|
||||
//
|
||||
// if err != nil {
|
||||
// return false, err
|
||||
// }
|
||||
//
|
||||
// data, err := ioutil.ReadAll(result.Body)
|
||||
//
|
||||
// if err != nil {
|
||||
// return false, err
|
||||
// }
|
||||
//
|
||||
// if result.StatusCode > 200 {
|
||||
// return false, ksErr.Wrap(data)
|
||||
// }
|
||||
//
|
||||
// var r map[string]bool
|
||||
//
|
||||
// err = json.Unmarshal(data, &r)
|
||||
//
|
||||
// if err != nil {
|
||||
// return false, err
|
||||
// }
|
||||
//
|
||||
// return r["exist"], nil
|
||||
//
|
||||
//}
|
||||
|
||||
func Roles(workspace *Workspace) ([]*v1.ClusterRole, error) {
|
||||
roles := make([]*v1.ClusterRole, 0)
|
||||
|
||||
@@ -614,11 +667,138 @@ func WorkspaceRoleInit(workspace *Workspace) error {
|
||||
admin.Name = fmt.Sprintf("system:%s:admin", workspace.Name)
|
||||
admin.Kind = iam.ClusterRoleKind
|
||||
admin.Rules = []v1.PolicyRule{
|
||||
// apis/kubesphere.io/v1alpha1/workspaces/sample
|
||||
// apis/kubesphere.io/v1alpha1/workspaces/sample/namespaces
|
||||
// apis/kubesphere.io/v1alpha1/workspaces/sample/devops
|
||||
// apis/kubesphere.io/v1alpha1/workspaces/sample/roles
|
||||
// apis/kubesphere.io/v1alpha1/workspaces/sample/members
|
||||
// apis/kubesphere.io/v1alpha1/workspaces/sample/members/admin
|
||||
|
||||
{
|
||||
Verbs: []string{"*"},
|
||||
APIGroups: []string{"kubesphere.io", "account.kubesphere.io"},
|
||||
ResourceNames: []string{workspace.Name},
|
||||
Resources: []string{"workspaces", "workspaces/*"},
|
||||
},
|
||||
|
||||
// post apis/kubesphere.io/v1alpha1/workspaces/sample/namespaces
|
||||
|
||||
{
|
||||
Verbs: []string{"create"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
ResourceNames: []string{workspace.Name},
|
||||
Resources: []string{"workspaces", "workspaces/namespaces", "workspaces/members", "workspaces/devops", "workspaces/registries"},
|
||||
Resources: []string{"workspaces/namespaces"},
|
||||
},
|
||||
|
||||
// post apis/kubesphere.io/v1alpha1/workspaces/sample/members
|
||||
|
||||
{
|
||||
Verbs: []string{"create"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
ResourceNames: []string{workspace.Name},
|
||||
Resources: []string{"workspaces/members"},
|
||||
},
|
||||
|
||||
// post apis/kubesphere.io/v1alpha1/workspaces/sample/devops
|
||||
{
|
||||
Verbs: []string{"create"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
ResourceNames: []string{workspace.Name},
|
||||
Resources: []string{"workspaces/devops"},
|
||||
},
|
||||
// TODO have risks
|
||||
// get apis/apps/v1/namespaces/proj1/deployments/?labelSelector
|
||||
// post api/v1/namespaces/project-0vya57/limitranges
|
||||
{
|
||||
Verbs: []string{"*"},
|
||||
APIGroups: []string{"", "apps", "extensions", "batch"},
|
||||
Resources: []string{"limitranges", "deployments", "configmaps", "secrets", "jobs", "cronjobs", "persistentvolumes", "statefulsets", "daemonsets", "ingresses", "services", "pods/*", "pods", "events", "deployments/scale"},
|
||||
},
|
||||
// get apis/kubesphere.io/v1alpha1/quota/namespaces/proj1
|
||||
{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
Resources: []string{"quota/*"},
|
||||
},
|
||||
// get api/v1/namespaces/proj1
|
||||
{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{""},
|
||||
Resources: []string{"namespaces", "serviceaccounts", "configmaps"},
|
||||
},
|
||||
// get api/v1/namespaces/proj1/serviceaccounts
|
||||
// get api/v1/namespaces/proj1/configmaps
|
||||
// get api/v1/namespaces/proj1/secrets
|
||||
|
||||
{
|
||||
Verbs: []string{"list"},
|
||||
APIGroups: []string{""},
|
||||
Resources: []string{"serviceaccounts", "configmaps", "secrets"},
|
||||
},
|
||||
|
||||
// get apis/kubesphere.io/v1alpha1/status/namespaces/proj1
|
||||
{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
ResourceNames: []string{"namespaces"},
|
||||
Resources: []string{"status/*"},
|
||||
},
|
||||
// apis/kubesphere.io/v1alpha1/namespaces/proj1/router
|
||||
{
|
||||
Verbs: []string{"list"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
Resources: []string{"router"},
|
||||
},
|
||||
// get apis/kubesphere.io/v1alpha1/registries/proj1
|
||||
{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
Resources: []string{"registries"},
|
||||
},
|
||||
|
||||
// get apis/kubesphere.io/v1alpha1/monitoring/namespaces/proj1
|
||||
|
||||
{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
ResourceNames: []string{"namespaces"},
|
||||
Resources: []string{"monitoring/*"},
|
||||
},
|
||||
|
||||
// get apis/kubesphere.io/v1alpha1/resources/persistent-volume-claims
|
||||
// get apis/kubesphere.io/v1alpha1/resources/deployments
|
||||
// get apis/kubesphere.io/v1alpha1/resources/statefulsets
|
||||
// get apis/kubesphere.io/v1alpha1/resources/daemonsets
|
||||
// get apis/kubesphere.io/v1alpha1/resources/jobs
|
||||
// get apis/kubesphere.io/v1alpha1/resources/cronjobs
|
||||
// get apis/kubesphere.io/v1alpha1/resources/persistent-volume-claims
|
||||
// get apis/kubesphere.io/v1alpha1/resources/services
|
||||
// get apis/kubesphere.io/v1alpha1/resources/ingresses
|
||||
// get apis/kubesphere.io/v1alpha1/resources/secrets
|
||||
// get apis/kubesphere.io/v1alpha1/resources/configmaps
|
||||
// get apis/kubesphere.io/v1alpha1/resources/roles
|
||||
|
||||
{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
Resources: []string{"resources"},
|
||||
},
|
||||
|
||||
// apis/account.kubesphere.io/v1alpha1/users
|
||||
// apis/account.kubesphere.io/v1alpha1/namespaces/proj1/users
|
||||
{
|
||||
Verbs: []string{"list"},
|
||||
APIGroups: []string{"account.kubesphere.io"},
|
||||
Resources: []string{"users"},
|
||||
},
|
||||
|
||||
// apis/kubesphere.io/v1alpha1/monitoring/workspaces/sample?metrics_filter=
|
||||
// apis/kubesphere.io/v1alpha1/monitoring/workspaces/sample/pods?step=30m
|
||||
{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
ResourceNames: []string{"workspaces"},
|
||||
Resources: []string{"monitoring/" + workspace.Name},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -634,35 +814,159 @@ func WorkspaceRoleInit(workspace *Workspace) error {
|
||||
Resources: []string{"workspaces"},
|
||||
ResourceNames: []string{workspace.Name},
|
||||
}, {
|
||||
Verbs: []string{"list", "create"},
|
||||
Verbs: []string{"create", "get"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
Resources: []string{"workspaces/namespaces", "workspaces/devops"},
|
||||
ResourceNames: []string{workspace.Name},
|
||||
}, {
|
||||
Verbs: []string{"list"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
Resources: []string{"workspaces/members", "workspaces/registries"},
|
||||
ResourceNames: []string{workspace.Name},
|
||||
},
|
||||
{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
Resources: []string{"registries"},
|
||||
},
|
||||
}
|
||||
|
||||
operator.Labels = map[string]string{"creator": "system"}
|
||||
|
||||
viewer := new(v1.ClusterRole)
|
||||
viewer.Name = fmt.Sprintf("system:%s:viewer", workspace.Name)
|
||||
viewer.Kind = iam.ClusterRoleKind
|
||||
viewer.Rules = []v1.PolicyRule{
|
||||
// apis/kubesphere.io/v1alpha1/workspaces/sample
|
||||
// apis/kubesphere.io/v1alpha1/workspaces/sample/namespaces
|
||||
// apis/kubesphere.io/v1alpha1/workspaces/sample/devops
|
||||
// apis/kubesphere.io/v1alpha1/workspaces/sample/roles
|
||||
// apis/kubesphere.io/v1alpha1/workspaces/sample/members
|
||||
// apis/kubesphere.io/v1alpha1/workspaces/sample/members/admin
|
||||
|
||||
{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{"kubesphere.io", "account.kubesphere.io"},
|
||||
ResourceNames: []string{workspace.Name},
|
||||
Resources: []string{"workspaces", "workspaces/*"},
|
||||
},
|
||||
|
||||
// post apis/kubesphere.io/v1alpha1/workspaces/sample/namespaces
|
||||
|
||||
//{
|
||||
// Verbs: []string{"create"},
|
||||
// APIGroups: []string{"kubesphere.io"},
|
||||
// ResourceNames: []string{workspace.Name},
|
||||
// Resources: []string{"workspaces/namespaces"},
|
||||
//},
|
||||
|
||||
// post apis/kubesphere.io/v1alpha1/workspaces/sample/members
|
||||
|
||||
//{
|
||||
// Verbs: []string{"create"},
|
||||
// APIGroups: []string{"kubesphere.io"},
|
||||
// ResourceNames: []string{workspace.Name},
|
||||
// Resources: []string{"workspaces/members"},
|
||||
//},
|
||||
|
||||
// post apis/kubesphere.io/v1alpha1/workspaces/sample/devops
|
||||
//{
|
||||
// Verbs: []string{"create"},
|
||||
// APIGroups: []string{"kubesphere.io"},
|
||||
// ResourceNames: []string{workspace.Name},
|
||||
// Resources: []string{"workspaces/devops"},
|
||||
//},
|
||||
// TODO have risks
|
||||
// get apis/apps/v1/namespaces/proj1/deployments/?labelSelector
|
||||
// post api/v1/namespaces/project-0vya57/limitranges
|
||||
{
|
||||
Verbs: []string{"get", "list"},
|
||||
APIGroups: []string{"", "apps", "extensions", "batch"},
|
||||
Resources: []string{"limitranges", "deployments", "configmaps", "secrets", "jobs", "cronjobs", "persistentvolumes", "statefulsets", "daemonsets", "ingresses", "services", "pods/*", "pods", "events", "deployments/scale"},
|
||||
},
|
||||
// get apis/kubesphere.io/v1alpha1/quota/namespaces/proj1
|
||||
{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
Resources: []string{"quota/*"},
|
||||
},
|
||||
// get api/v1/namespaces/proj1
|
||||
{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{""},
|
||||
Resources: []string{"namespaces", "serviceaccounts", "configmaps"},
|
||||
},
|
||||
// get api/v1/namespaces/proj1/serviceaccounts
|
||||
// get api/v1/namespaces/proj1/configmaps
|
||||
// get api/v1/namespaces/proj1/secrets
|
||||
|
||||
{
|
||||
Verbs: []string{"list"},
|
||||
APIGroups: []string{""},
|
||||
Resources: []string{"serviceaccounts", "configmaps", "secrets"},
|
||||
},
|
||||
|
||||
// get apis/kubesphere.io/v1alpha1/status/namespaces/proj1
|
||||
{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
Resources: []string{"workspaces"},
|
||||
ResourceNames: []string{workspace.Name},
|
||||
}, {
|
||||
Verbs: []string{"list"},
|
||||
ResourceNames: []string{"namespaces"},
|
||||
Resources: []string{"status/*"},
|
||||
},
|
||||
// apis/kubesphere.io/v1alpha1/namespaces/proj1/router
|
||||
{
|
||||
Verbs: []string{"list"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
Resources: []string{"router"},
|
||||
},
|
||||
// get apis/kubesphere.io/v1alpha1/registries/proj1
|
||||
{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
Resources: []string{"registries"},
|
||||
},
|
||||
|
||||
// get apis/kubesphere.io/v1alpha1/monitoring/namespaces/proj1
|
||||
|
||||
{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
Resources: []string{"workspaces/namespaces", "workspaces/members", "workspaces/devops", "workspaces/registries"},
|
||||
ResourceNames: []string{workspace.Name},
|
||||
ResourceNames: []string{"namespaces"},
|
||||
Resources: []string{"monitoring/*"},
|
||||
},
|
||||
|
||||
// get apis/kubesphere.io/v1alpha1/resources/persistent-volume-claims
|
||||
// get apis/kubesphere.io/v1alpha1/resources/deployments
|
||||
// get apis/kubesphere.io/v1alpha1/resources/statefulsets
|
||||
// get apis/kubesphere.io/v1alpha1/resources/daemonsets
|
||||
// get apis/kubesphere.io/v1alpha1/resources/jobs
|
||||
// get apis/kubesphere.io/v1alpha1/resources/cronjobs
|
||||
// get apis/kubesphere.io/v1alpha1/resources/persistent-volume-claims
|
||||
// get apis/kubesphere.io/v1alpha1/resources/services
|
||||
// get apis/kubesphere.io/v1alpha1/resources/ingresses
|
||||
// get apis/kubesphere.io/v1alpha1/resources/secrets
|
||||
// get apis/kubesphere.io/v1alpha1/resources/configmaps
|
||||
// get apis/kubesphere.io/v1alpha1/resources/roles
|
||||
|
||||
{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
Resources: []string{"resources"},
|
||||
},
|
||||
|
||||
// apis/account.kubesphere.io/v1alpha1/users
|
||||
// apis/account.kubesphere.io/v1alpha1/namespaces/proj1/users
|
||||
{
|
||||
Verbs: []string{"list"},
|
||||
APIGroups: []string{"account.kubesphere.io"},
|
||||
Resources: []string{"users"},
|
||||
},
|
||||
|
||||
// apis/kubesphere.io/v1alpha1/monitoring/workspaces/sample?metrics_filter=
|
||||
// apis/kubesphere.io/v1alpha1/monitoring/workspaces/sample/pods?step=30m
|
||||
{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
ResourceNames: []string{"workspaces"},
|
||||
Resources: []string{"monitoring/" + workspace.Name},
|
||||
},
|
||||
}
|
||||
|
||||
viewer.Labels = map[string]string{"creator": "system"}
|
||||
|
||||
_, err := k8sClient.RbacV1().ClusterRoles().Create(admin)
|
||||
@@ -677,6 +981,7 @@ func WorkspaceRoleInit(workspace *Workspace) error {
|
||||
adminRoleBinding.Name = admin.Name
|
||||
adminRoleBinding.RoleRef = v1.RoleRef{Kind: "ClusterRole", Name: admin.Name}
|
||||
adminRoleBinding.Subjects = []v1.Subject{{Kind: v1.UserKind, Name: workspace.Creator}}
|
||||
|
||||
_, err = k8sClient.RbacV1().ClusterRoleBindings().Create(adminRoleBinding)
|
||||
if err != nil {
|
||||
if !apierrors.IsAlreadyExists(err) {
|
||||
@@ -761,17 +1066,15 @@ func unbindWorkspaceRole(workspace string, users []string) error {
|
||||
|
||||
func unbindNamespacesRole(namespaces []string, users []string) error {
|
||||
|
||||
lister := controllers.ResourceControllers.Controllers[controllers.Namespaces].Lister().(v13.RoleBindingLister)
|
||||
|
||||
k8sClient := client.NewK8sClient()
|
||||
for _, namespace := range namespaces {
|
||||
|
||||
roleBindings, err := lister.RoleBindings(namespace).List(labels.Everything())
|
||||
roleBindings, err := k8sClient.RbacV1().RoleBindings(namespace).List(meta_v1.ListOptions{})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, roleBinding := range roleBindings {
|
||||
for _, roleBinding := range roleBindings.Items {
|
||||
|
||||
modify := false
|
||||
for i := 0; i < len(roleBinding.Subjects); i++ {
|
||||
@@ -781,7 +1084,7 @@ func unbindNamespacesRole(namespaces []string, users []string) error {
|
||||
}
|
||||
}
|
||||
if modify {
|
||||
_, err := k8sClient.RbacV1().RoleBindings(namespace).Update(roleBinding)
|
||||
_, err := k8sClient.RbacV1().RoleBindings(namespace).Update(&roleBinding)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -857,3 +1160,150 @@ func CreateWorkspaceRoleBinding(workspace *Workspace, username string, role stri
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetDevOpsProjects(name string) ([]string, error) {
|
||||
|
||||
db := client.NewSharedDBClient()
|
||||
defer db.Close()
|
||||
|
||||
var workspaceDOPBindings []WorkspaceDPBinding
|
||||
|
||||
if err := db.Where("workspace = ?", name).Find(&workspaceDOPBindings).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
devOpsProjects := make([]string, 0)
|
||||
|
||||
for _, workspaceDOPBinding := range workspaceDOPBindings {
|
||||
devOpsProjects = append(devOpsProjects, workspaceDOPBinding.DevOpsProject)
|
||||
}
|
||||
return devOpsProjects, nil
|
||||
}
|
||||
|
||||
func GetOrgMembers(workspace string) ([]string, error) {
|
||||
ws, err := Detail(workspace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ws.Members, nil
|
||||
}
|
||||
|
||||
func GetOrgRoles(name string) ([]string, error) {
|
||||
return []string{"admin", "operator", "user"}, nil
|
||||
}
|
||||
|
||||
func WorkspaceNamespaces(workspaceName string) ([]string, error) {
|
||||
ns, err := Namespaces(workspaceName)
|
||||
|
||||
namespaces := make([]string, 0)
|
||||
|
||||
if err != nil {
|
||||
return namespaces, err
|
||||
}
|
||||
|
||||
for i := 0; i < len(ns); i++ {
|
||||
namespaces = append(namespaces, ns[i].Name)
|
||||
}
|
||||
|
||||
return namespaces, nil
|
||||
}
|
||||
|
||||
func CountAll() (int, error) {
|
||||
result, err := http.Get(fmt.Sprintf("http://%s/apis/account.kubesphere.io/v1alpha1/groups/count", constants.AccountAPIServer))
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(result.Body)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if result.StatusCode > 200 {
|
||||
return 0, ksErr.Wrap(data)
|
||||
}
|
||||
var count map[string]interface{}
|
||||
|
||||
err = json.Unmarshal(data, &count)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
val, ok := count["total"]
|
||||
|
||||
if !ok {
|
||||
return 0, errors.New("not found")
|
||||
}
|
||||
|
||||
switch val.(type) {
|
||||
case int:
|
||||
return val.(int), nil
|
||||
case float32:
|
||||
return int(val.(float32)), nil
|
||||
case float64:
|
||||
return int(val.(float64)), nil
|
||||
}
|
||||
|
||||
return 0, errors.New("not found")
|
||||
}
|
||||
|
||||
func GetAllOrgNums() (int, error) {
|
||||
count, err := CountAll()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func GetAllProjectNums() (int, error) {
|
||||
return controllers.ResourceControllers.Controllers[controllers.Namespaces].CountWithConditions(""), nil
|
||||
}
|
||||
|
||||
func GetAllDevOpsProjectsNums() (int, error) {
|
||||
db := client.NewSharedDBClient()
|
||||
defer db.Close()
|
||||
|
||||
var count int
|
||||
if err := db.Find(&WorkspaceDPBinding{}).Count(&count).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func GetAllAccountNums() (int, error) {
|
||||
result, err := http.Get(fmt.Sprintf("http://%s/apis/account.kubesphere.io/v1alpha1/users", constants.AccountAPIServer))
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(result.Body)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if result.StatusCode > 200 {
|
||||
return 0, ksErr.Wrap(data)
|
||||
}
|
||||
var count map[string]interface{}
|
||||
|
||||
err = json.Unmarshal(data, &count)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
val, ok := count["total"]
|
||||
|
||||
if !ok {
|
||||
return 0, errors.New("not found")
|
||||
}
|
||||
|
||||
switch val.(type) {
|
||||
case int:
|
||||
return val.(int), nil
|
||||
case float32:
|
||||
return int(val.(float32)), nil
|
||||
case float64:
|
||||
return int(val.(float64)), nil
|
||||
}
|
||||
return 0, errors.New("not found")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user