Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
水淹萌龙
kubesphere
提交
5c4efd53
K
kubesphere
项目概览
水淹萌龙
/
kubesphere
与 Fork 源项目一致
Fork自
KubeSphere / kubesphere
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kubesphere
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
5c4efd53
编写于
4月 10, 2019
作者:
H
hongming
提交者:
zryfish
4月 11, 2019
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor tenant api
Signed-off-by:
N
hongming
<
talonwan@yunify.com
>
上级
71633730
变更
29
隐藏空白更改
内联
并排
Showing
29 changed file
with
576 addition
and
583 deletion
+576
-583
pkg/apis/iam/v1alpha2/register.go
pkg/apis/iam/v1alpha2/register.go
+2
-1
pkg/apis/resources/v1alpha2/register.go
pkg/apis/resources/v1alpha2/register.go
+17
-2
pkg/apis/tenant/v1alpha2/register.go
pkg/apis/tenant/v1alpha2/register.go
+5
-1
pkg/apis/terminal/v1alpha2/register.go
pkg/apis/terminal/v1alpha2/register.go
+1
-1
pkg/apiserver/iam/groups.go
pkg/apiserver/iam/groups.go
+1
-1
pkg/apiserver/iam/im.go
pkg/apiserver/iam/im.go
+0
-11
pkg/apiserver/iam/workspaces.go
pkg/apiserver/iam/workspaces.go
+3
-9
pkg/apiserver/resources/application.go
pkg/apiserver/resources/application.go
+42
-2
pkg/apiserver/resources/resources.go
pkg/apiserver/resources/resources.go
+1
-8
pkg/apiserver/routers/routers.go
pkg/apiserver/routers/routers.go
+6
-1
pkg/apiserver/tenant/tenant.go
pkg/apiserver/tenant/tenant.go
+37
-11
pkg/constants/constants.go
pkg/constants/constants.go
+0
-2
pkg/controller/workspace/workspace_controller.go
pkg/controller/workspace/workspace_controller.go
+4
-4
pkg/models/iam/am.go
pkg/models/iam/am.go
+9
-62
pkg/models/iam/im.go
pkg/models/iam/im.go
+117
-31
pkg/models/iam/policy/policy.go
pkg/models/iam/policy/policy.go
+14
-2
pkg/models/resources/clusterroles.go
pkg/models/resources/clusterroles.go
+14
-0
pkg/models/resources/resources.go
pkg/models/resources/resources.go
+6
-15
pkg/models/routers/routers.go
pkg/models/routers/routers.go
+2
-1
pkg/models/tenant/devops.go
pkg/models/tenant/devops.go
+18
-47
pkg/models/tenant/namespaces.go
pkg/models/tenant/namespaces.go
+9
-0
pkg/models/tenant/tenant.go
pkg/models/tenant/tenant.go
+41
-19
pkg/models/tenant/workspaces.go
pkg/models/tenant/workspaces.go
+17
-0
pkg/models/types.go
pkg/models/types.go
+1
-1
pkg/models/workspaces/workspaces.go
pkg/models/workspaces/workspaces.go
+14
-336
pkg/params/params.go
pkg/params/params.go
+0
-12
pkg/simple/client/kubesphere/devops.go
pkg/simple/client/kubesphere/devops.go
+186
-0
pkg/simple/client/kubesphere/kubesphereclient.go
pkg/simple/client/kubesphere/kubesphereclient.go
+7
-0
pkg/simple/client/openpitrix/applications.go
pkg/simple/client/openpitrix/applications.go
+2
-3
未找到文件。
pkg/apis/iam/v1alpha2/register.go
浏览文件 @
5c4efd53
...
...
@@ -192,9 +192,10 @@ func addWebService(c *restful.Container) error {
Param
(
ws
.
PathParameter
(
"workspace"
,
"workspace name"
))
.
Doc
(
"Add user to workspace"
)
.
Metadata
(
restfulspec
.
KeyOpenAPITags
,
tags
))
ws
.
Route
(
ws
.
POST
(
"/workspaces/{workspace}/members
"
)
.
ws
.
Route
(
ws
.
DELETE
(
"/workspaces/{workspace}/members/{username}
"
)
.
To
(
iam
.
RemoveUser
)
.
Param
(
ws
.
PathParameter
(
"workspace"
,
"workspace name"
))
.
Param
(
ws
.
PathParameter
(
"name"
,
"username"
))
.
Doc
(
"Remove user from workspace"
)
.
Metadata
(
restfulspec
.
KeyOpenAPITags
,
tags
))
ws
.
Route
(
ws
.
GET
(
"/workspaces/{workspace}/members/{username}"
)
.
...
...
pkg/apis/resources/v1alpha2/register.go
浏览文件 @
5c4efd53
...
...
@@ -91,7 +91,7 @@ func addWebService(c *restful.Container) error {
To
(
resources
.
ApplicationHandler
)
.
Writes
(
models
.
PageableResponse
{})
.
Metadata
(
restfulspec
.
KeyOpenAPITags
,
tags
)
.
Doc
(
"
Cluster level resource query
"
)
.
Doc
(
"
List applications in cluster
"
)
.
Param
(
webservice
.
QueryParameter
(
params
.
ConditionsParam
,
"query conditions"
)
.
Required
(
false
)
.
DataFormat
(
"key=value,key~value"
)
.
...
...
@@ -103,9 +103,24 @@ func addWebService(c *restful.Container) error {
DataFormat
(
"limit=%d,page=%d"
)
.
DefaultValue
(
"limit=10,page=1"
)))
webservice
.
Route
(
webservice
.
GET
(
"/namespaces/{namespace}/applications"
)
.
To
(
resources
.
NamespacedApplicationHandler
)
.
Writes
(
models
.
PageableResponse
{})
.
Metadata
(
restfulspec
.
KeyOpenAPITags
,
tags
)
.
Doc
(
"List applications"
)
.
Param
(
webservice
.
QueryParameter
(
params
.
ConditionsParam
,
"query conditions"
)
.
Required
(
false
)
.
DataFormat
(
"key=value,key~value"
)
.
DefaultValue
(
""
))
.
Param
(
webservice
.
PathParameter
(
"namespace"
,
"namespace"
))
.
Param
(
webservice
.
QueryParameter
(
params
.
PagingParam
,
"page"
)
.
Required
(
false
)
.
DataFormat
(
"limit=%d,page=%d"
)
.
DefaultValue
(
"limit=10,page=1"
)))
webservice
.
Route
(
webservice
.
GET
(
"/storageclasses/{storageclass}/persistentvolumeclaims"
)
.
To
(
resources
.
GetPvcListBySc
)
.
Doc
(
"
get user's kubectl pod
"
)
.
Doc
(
"
query persistent volume claims by storageclass
"
)
.
Param
(
webservice
.
PathParameter
(
"username"
,
"username"
))
.
Metadata
(
restfulspec
.
KeyOpenAPITags
,
tags
))
...
...
pkg/apis/tenant/v1alpha2/register.go
浏览文件 @
5c4efd53
...
...
@@ -42,6 +42,10 @@ func addWebService(c *restful.Container) error {
To
(
tenant
.
ListWorkspaces
)
.
Doc
(
"List workspace by user"
)
.
Metadata
(
restfulspec
.
KeyOpenAPITags
,
tags
))
ws
.
Route
(
ws
.
GET
(
"/workspaces/{workspace}"
)
.
To
(
tenant
.
DescribeWorkspace
)
.
Doc
(
"Get workspace detail"
)
.
Metadata
(
restfulspec
.
KeyOpenAPITags
,
tags
))
ws
.
Route
(
ws
.
GET
(
"/workspaces/{workspace}/rules"
)
.
To
(
tenant
.
ListWorkspaceRules
)
.
Param
(
ws
.
PathParameter
(
"workspace"
,
"workspace name"
))
.
...
...
@@ -96,7 +100,7 @@ func addWebService(c *restful.Container) error {
Param
(
ws
.
PathParameter
(
"workspace"
,
"workspace name"
))
.
Doc
(
"Create devops project"
)
.
Metadata
(
restfulspec
.
KeyOpenAPITags
,
tags
))
ws
.
Route
(
ws
.
DELETE
(
"/workspaces/{workspace}/devops"
)
.
ws
.
Route
(
ws
.
DELETE
(
"/workspaces/{workspace}/devops
/{id}
"
)
.
To
(
tenant
.
DeleteDevopsProject
)
.
Param
(
ws
.
PathParameter
(
"workspace"
,
"workspace name"
))
.
Doc
(
"Delete devops project"
)
.
...
...
pkg/apis/terminal/v1alpha2/register.go
浏览文件 @
5c4efd53
...
...
@@ -41,7 +41,7 @@ func addWebService(c *restful.Container) error {
tags
:=
[]
string
{
"Terminal"
}
webservice
.
Route
(
webservice
.
GET
(
"/namespace/{namespace}/pods/{pods}"
)
.
webservice
.
Route
(
webservice
.
GET
(
"/namespace
s
/{namespace}/pods/{pods}"
)
.
To
(
terminal
.
CreateTerminalSession
)
.
Doc
(
"create terminal session"
)
.
Metadata
(
restfulspec
.
KeyOpenAPITags
,
tags
)
.
...
...
pkg/apiserver/iam/groups.go
浏览文件 @
5c4efd53
...
...
@@ -142,7 +142,7 @@ func ListGroupUsers(req *restful.Request, resp *restful.Response) {
for
i
:=
0
;
i
<
len
(
group
.
Members
);
i
++
{
name
:=
group
.
Members
[
i
]
user
,
err
:=
iam
.
DescribeUser
(
name
)
user
,
err
:=
iam
.
GetUserInfo
(
name
)
if
err
!=
nil
{
if
ldap
.
IsErrorWithCode
(
err
,
ldap
.
LDAPResultNoSuchObject
)
{
...
...
pkg/apiserver/iam/im.go
浏览文件 @
5c4efd53
...
...
@@ -234,22 +234,11 @@ func ListUsers(req *restful.Request, resp *restful.Response) {
conditions
,
err
:=
params
.
ParseConditions
(
req
.
QueryParameter
(
params
.
ConditionsParam
))
orderBy
:=
req
.
QueryParameter
(
params
.
OrderByParam
)
reverse
:=
params
.
ParseReverse
(
req
)
names
:=
params
.
ParseArray
(
req
.
QueryParameter
(
params
.
NameParam
))
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusBadRequest
,
errors
.
Wrap
(
err
))
return
}
if
len
(
names
)
>
0
{
users
,
err
:=
iam
.
ListUsersByName
(
names
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusBadRequest
,
errors
.
Wrap
(
err
))
return
}
resp
.
WriteAsJson
(
users
)
return
}
users
,
err
:=
iam
.
ListUsers
(
conditions
,
orderBy
,
reverse
,
limit
,
offset
)
...
...
pkg/apiserver/iam/workspaces.go
浏览文件 @
5c4efd53
...
...
@@ -91,7 +91,7 @@ func DescribeWorkspaceUser(req *restful.Request, resp *restful.Response) {
return
}
user
,
err
:=
iam
.
DescribeUser
(
username
)
user
,
err
:=
iam
.
GetUserInfo
(
username
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
...
...
@@ -132,15 +132,9 @@ func InviteUser(req *restful.Request, resp *restful.Response) {
func
RemoveUser
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
workspace
:=
req
.
PathParameter
(
"workspace"
)
var
user
models
.
User
err
:=
req
.
ReadEntity
(
&
user
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusBadRequest
,
errors
.
Wrap
(
err
))
return
}
err
=
workspaces
.
InviteUser
(
workspace
,
&
user
)
username
:=
req
.
PathParameter
(
"username"
)
err
:=
workspaces
.
RemoveUser
(
workspace
,
username
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
return
...
...
pkg/apiserver/resources/application.go
浏览文件 @
5c4efd53
...
...
@@ -19,10 +19,11 @@ package resources
import
(
"github.com/emicklei/go-restful"
"k8s.io/api/core/v1"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/errors"
"kubesphere.io/kubesphere/pkg/models/applications"
//"kubesphere.io/kubesphere/pkg/models/applications"
"kubesphere.io/kubesphere/pkg/models/resources"
"kubesphere.io/kubesphere/pkg/params"
"net/http"
)
...
...
@@ -58,3 +59,42 @@ func ApplicationHandler(req *restful.Request, resp *restful.Response) {
resp
.
WriteAsJson
(
result
)
}
func
NamespacedApplicationHandler
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
limit
,
offset
:=
params
.
ParsePaging
(
req
.
QueryParameter
(
params
.
PagingParam
))
namespaceName
:=
req
.
PathParameter
(
"namespace"
)
conditions
,
err
:=
params
.
ParseConditions
(
req
.
QueryParameter
(
params
.
ConditionsParam
))
if
err
!=
nil
{
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusBadRequest
,
errors
.
Wrap
(
err
))
return
}
}
namespace
,
err
:=
resources
.
GetResource
(
""
,
resources
.
Namespaces
,
namespaceName
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
return
}
var
runtimeId
string
if
ns
,
ok
:=
namespace
.
(
*
v1
.
Namespace
);
ok
{
runtimeId
=
ns
.
Annotations
[
constants
.
OpenPitrixRuntimeAnnotationKey
]
}
if
runtimeId
==
""
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
New
(
"openpitrix runtime not init"
))
return
}
result
,
err
:=
applications
.
ListApplication
(
runtimeId
,
conditions
,
limit
,
offset
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
return
}
resp
.
WriteAsJson
(
result
)
}
pkg/apiserver/resources/resources.go
浏览文件 @
5c4efd53
...
...
@@ -19,7 +19,6 @@ package resources
import
(
"github.com/emicklei/go-restful"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/resources"
"net/http"
...
...
@@ -34,7 +33,6 @@ func ListResources(req *restful.Request, resp *restful.Response) {
orderBy
:=
req
.
QueryParameter
(
params
.
OrderByParam
)
limit
,
offset
:=
params
.
ParsePaging
(
req
.
QueryParameter
(
params
.
PagingParam
))
reverse
:=
params
.
ParseReverse
(
req
)
names
:=
params
.
ParseArray
(
req
.
QueryParameter
(
params
.
NameParam
))
if
orderBy
==
""
{
orderBy
=
resources
.
CreateTime
...
...
@@ -46,12 +44,7 @@ func ListResources(req *restful.Request, resp *restful.Response) {
return
}
var
result
*
models
.
PageableResponse
if
len
(
names
)
>
0
{
result
,
err
=
resources
.
ListResourcesByName
(
namespace
,
resourceName
,
names
)
}
else
{
result
,
err
=
resources
.
ListResources
(
namespace
,
resourceName
,
conditions
,
orderBy
,
reverse
,
limit
,
offset
)
}
result
,
err
:=
resources
.
ListResources
(
namespace
,
resourceName
,
conditions
,
orderBy
,
reverse
,
limit
,
offset
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
...
...
pkg/apiserver/routers/routers.go
浏览文件 @
5c4efd53
...
...
@@ -21,6 +21,7 @@ package routers
import
(
"fmt"
"github.com/emicklei/go-restful"
k8serr
"k8s.io/apimachinery/pkg/api/errors"
"net/http"
"kubesphere.io/kubesphere/pkg/errors"
...
...
@@ -57,7 +58,11 @@ func GetRouter(request *restful.Request, response *restful.Response) {
router
,
err
:=
routers
.
GetRouter
(
namespace
)
if
err
!=
nil
{
response
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
if
k8serr
.
IsNotFound
(
err
)
{
response
.
WriteHeaderAndEntity
(
http
.
StatusNotFound
,
errors
.
Wrap
(
err
))
}
else
{
response
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
}
return
}
...
...
pkg/apiserver/tenant/tenant.go
浏览文件 @
5c4efd53
...
...
@@ -19,6 +19,7 @@ package tenant
import
(
"github.com/emicklei/go-restful"
"github.com/golang/glog"
"k8s.io/api/core/v1"
k8serr
"k8s.io/apimachinery/pkg/api/errors"
"kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
...
...
@@ -26,10 +27,11 @@ import (
"kubesphere.io/kubesphere/pkg/errors"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/models/resources"
"kubesphere.io/kubesphere/pkg/models/tenant"
"kubesphere.io/kubesphere/pkg/models/workspaces"
"kubesphere.io/kubesphere/pkg/params"
"
log
"
"
kubesphere.io/kubesphere/pkg/simple/client/kubesphere
"
"net/http"
)
...
...
@@ -54,6 +56,11 @@ func ListWorkspaces(req *restful.Request, resp *restful.Response) {
limit
,
offset
:=
params
.
ParsePaging
(
req
.
QueryParameter
(
params
.
PagingParam
))
reverse
:=
params
.
ParseReverse
(
req
)
if
orderBy
==
""
{
orderBy
=
resources
.
CreateTime
reverse
=
true
}
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusBadRequest
,
errors
.
Wrap
(
err
))
return
...
...
@@ -69,6 +76,20 @@ func ListWorkspaces(req *restful.Request, resp *restful.Response) {
resp
.
WriteAsJson
(
result
)
}
func
DescribeWorkspace
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
username
:=
req
.
HeaderParameter
(
constants
.
UserNameHeader
)
workspaceName
:=
req
.
PathParameter
(
"workspace"
)
result
,
err
:=
tenant
.
DescribeWorkspace
(
username
,
workspaceName
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
return
}
resp
.
WriteAsJson
(
result
)
}
func
ListNamespaces
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
workspace
:=
req
.
PathParameter
(
"workspace"
)
username
:=
req
.
PathParameter
(
"username"
)
...
...
@@ -88,7 +109,7 @@ func ListNamespaces(req *restful.Request, resp *restful.Response) {
return
}
conditions
.
Match
[
"kubesphere.io/workspace"
]
=
workspace
conditions
.
Match
[
constants
.
WorkspaceLabelKey
]
=
workspace
result
,
err
:=
tenant
.
ListNamespaces
(
username
,
conditions
,
orderBy
,
reverse
,
limit
,
offset
)
...
...
@@ -188,18 +209,24 @@ func ListDevopsProjects(req *restful.Request, resp *restful.Response) {
func
DeleteDevopsProject
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
devops
:=
req
.
PathParameter
(
"id"
)
workspace
:=
req
.
PathParameter
(
"workspace"
)
force
:=
req
.
QueryParameter
(
"force"
)
workspaceName
:=
req
.
PathParameter
(
"workspace"
)
username
:=
req
.
HeaderParameter
(
constants
.
UserNameHeader
)
err
:=
workspaces
.
UnBindDevopsProject
(
workspace
,
devops
)
_
,
err
:=
tenant
.
GetWorkspace
(
workspaceName
)
if
err
!=
nil
&&
force
!=
"true"
{
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusBadRequest
,
errors
.
Wrap
(
err
))
return
}
err
=
kubesphere
.
Client
()
.
DeleteDevopsProject
(
username
,
devops
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
return
}
err
=
workspaces
.
DeleteDevopsProject
(
usern
ame
,
devops
)
err
=
workspaces
.
UnBindDevopsProject
(
workspaceN
ame
,
devops
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
...
...
@@ -211,7 +238,7 @@ func DeleteDevopsProject(req *restful.Request, resp *restful.Response) {
func
CreateDevopsProject
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
workspace
:=
req
.
PathParameter
(
"workspace"
)
workspace
Name
:=
req
.
PathParameter
(
"workspace"
)
username
:=
req
.
HeaderParameter
(
constants
.
UserNameHeader
)
var
devops
models
.
DevopsProject
...
...
@@ -223,8 +250,8 @@ func CreateDevopsProject(req *restful.Request, resp *restful.Response) {
return
}
log
.
Println
(
"create workspace"
,
username
,
workspac
e
,
devops
)
project
,
err
:=
workspaces
.
CreateDevopsProject
(
username
,
workspace
,
devops
)
glog
.
Infoln
(
"create workspace"
,
username
,
workspaceNam
e
,
devops
)
project
,
err
:=
workspaces
.
CreateDevopsProject
(
username
,
workspace
Name
,
&
devops
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
...
...
@@ -232,7 +259,6 @@ func CreateDevopsProject(req *restful.Request, resp *restful.Response) {
}
resp
.
WriteAsJson
(
project
)
}
func
ListNamespaceRules
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
...
...
pkg/constants/constants.go
浏览文件 @
5c4efd53
...
...
@@ -47,7 +47,5 @@ const (
var
(
WorkSpaceRoles
=
[]
string
{
WorkspaceAdmin
,
WorkspaceRegular
,
WorkspaceViewer
}
SystemWorkspace
=
"system-workspace"
DevopsAPIServer
=
"ks-devops.kubesphere-devops-system.svc"
SystemNamespaces
=
[]
string
{
KubeSphereNamespace
,
OpenPitrixNamespace
,
KubeSystemNamespace
}
)
pkg/controller/workspace/workspace_controller.go
浏览文件 @
5c4efd53
...
...
@@ -153,9 +153,9 @@ func (r *ReconcileWorkspace) Reconcile(request reconcile.Request) (reconcile.Res
return
reconcile
.
Result
{},
err
}
if
err
=
r
.
createGroup
(
instance
);
err
!=
nil
{
return
reconcile
.
Result
{},
err
}
//
if err = r.createGroup(instance); err != nil {
//
return reconcile.Result{}, err
//
}
if
err
=
r
.
createWorkspaceRoleBindings
(
instance
);
err
!=
nil
{
return
reconcile
.
Result
{},
err
...
...
@@ -369,7 +369,7 @@ func (r *ReconcileWorkspace) createWorkspaceRoleBindings(instance *tenantv1alpha
regularRoleBinding
:=
&
rbac
.
ClusterRoleBinding
{}
regularRoleBinding
.
Name
=
getWorkspaceRegularRoleBindingName
(
instance
.
Name
)
regularRoleBinding
.
Labels
=
map
[
string
]
string
{
constants
.
WorkspaceLabelKey
:
instance
.
Name
}
regularRoleBinding
.
RoleRef
=
rbac
.
RoleRef
{
APIGroup
:
"rbac.authorization.k8s.io"
,
Kind
:
"ClusterRole"
,
Name
:
getWorkspace
Viewe
rRoleName
(
instance
.
Name
)}
regularRoleBinding
.
RoleRef
=
rbac
.
RoleRef
{
APIGroup
:
"rbac.authorization.k8s.io"
,
Kind
:
"ClusterRole"
,
Name
:
getWorkspace
Regula
rRoleName
(
instance
.
Name
)}
regularRoleBinding
.
Subjects
=
[]
rbac
.
Subject
{}
if
err
=
controllerutil
.
SetControllerReference
(
instance
,
regularRoleBinding
,
r
.
scheme
);
err
!=
nil
{
...
...
pkg/models/iam/am.go
浏览文件 @
5c4efd53
...
...
@@ -18,20 +18,17 @@
package
iam
import
(
"encoding/json"
"errors"
"fmt"
"github.com/golang/glog"
"io/ioutil"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/resources"
"kubesphere.io/kubesphere/pkg/params"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/simple/client/kubesphere"
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"net/http"
"sort"
"strings"
...
...
@@ -47,7 +44,7 @@ import (
const
ClusterRoleKind
=
"ClusterRole"
func
GetUserDevopsSimpleRules
(
username
,
projectId
string
)
([]
models
.
SimpleRule
,
error
)
{
role
,
err
:=
GetUserDevopsRole
(
projectId
,
username
)
role
,
err
:=
kubesphere
.
Client
()
.
GetUserDevopsRole
(
username
,
projectId
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -100,53 +97,6 @@ func GetDevopsRoleSimpleRules(role string) []models.SimpleRule {
return
rules
}
func
GetUserDevopsRole
(
projectId
string
,
username
string
)
(
string
,
error
)
{
//Hard fix
if
username
==
"admin"
{
return
"owner"
,
nil
}
req
,
err
:=
http
.
NewRequest
(
http
.
MethodGet
,
fmt
.
Sprintf
(
"http://%s/api/v1alpha/projects/%s/members"
,
constants
.
DevopsAPIServer
,
projectId
),
nil
)
if
err
!=
nil
{
return
""
,
err
}
req
.
Header
.
Set
(
constants
.
UserNameHeader
,
username
)
resp
,
err
:=
http
.
DefaultClient
.
Do
(
req
)
if
err
!=
nil
{
return
""
,
err
}
defer
resp
.
Body
.
Close
()
data
,
err
:=
ioutil
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
return
""
,
err
}
if
resp
.
StatusCode
>
200
{
return
""
,
errors
.
New
(
string
(
data
))
}
var
result
[]
map
[
string
]
string
err
=
json
.
Unmarshal
(
data
,
&
result
)
if
err
!=
nil
{
return
""
,
err
}
for
_
,
item
:=
range
result
{
if
item
[
"username"
]
==
username
{
return
item
[
"role"
],
nil
}
}
return
""
,
nil
}
// Get user roles in namespace
func
GetUserRoles
(
namespace
,
username
string
)
([]
*
v1
.
Role
,
error
)
{
clusterRoleLister
:=
informers
.
SharedInformerFactory
()
.
Rbac
()
.
V1
()
.
ClusterRoles
()
.
Lister
()
...
...
@@ -267,13 +217,6 @@ func GetUserRules(namespace, username string) ([]v1.PolicyRule, error) {
return
rules
,
nil
}
func
isUserFacingClusterRole
(
role
*
v1
.
ClusterRole
)
bool
{
if
role
.
Labels
[
constants
.
CreatorLabelKey
]
!=
""
{
return
true
}
return
false
}
func
GetWorkspaceRoleBindings
(
workspace
string
)
([]
*
v1
.
ClusterRoleBinding
,
error
)
{
clusterRoleBindings
,
err
:=
informers
.
SharedInformerFactory
()
.
Rbac
()
.
V1
()
.
ClusterRoleBindings
()
.
Lister
()
.
List
(
labels
.
Everything
())
...
...
@@ -386,7 +329,7 @@ func ListClusterRoleUsers(clusterRoleName string, conditions *params.Conditions,
for
_
,
roleBinding
:=
range
roleBindings
{
for
_
,
subject
:=
range
roleBinding
.
Subjects
{
if
subject
.
Kind
==
v1
.
UserKind
&&
!
k8sutil
.
ContainsUser
(
users
,
subject
.
Name
)
{
user
,
err
:=
DescribeUser
(
subject
.
Name
)
user
,
err
:=
GetUserInfo
(
subject
.
Name
)
if
ldap
.
IsErrorWithCode
(
err
,
ldap
.
LDAPResultNoSuchObject
)
{
continue
}
...
...
@@ -436,7 +379,7 @@ func RoleUsers(namespace string, roleName string) ([]*models.User, error) {
for
_
,
roleBinding
:=
range
roleBindings
{
for
_
,
subject
:=
range
roleBinding
.
Subjects
{
if
subject
.
Kind
==
v1
.
UserKind
&&
!
k8sutil
.
ContainsUser
(
users
,
subject
.
Name
)
{
user
,
err
:=
DescribeUser
(
subject
.
Name
)
user
,
err
:=
GetUserInfo
(
subject
.
Name
)
if
err
!=
nil
{
if
ldap
.
IsErrorWithCode
(
err
,
ldap
.
LDAPResultNoSuchObject
)
{
...
...
@@ -491,10 +434,14 @@ func NamespaceUsers(namespaceName string) ([]*models.User, error) {
users
:=
make
([]
*
models
.
User
,
0
)
for
_
,
roleBinding
:=
range
roleBindings
{
// controlled by ks-controller-manager
if
roleBinding
.
Name
==
"admin"
||
roleBinding
.
Name
==
"viewer"
{
continue
}
for
_
,
subject
:=
range
roleBinding
.
Subjects
{
if
subject
.
Kind
==
v1
.
UserKind
&&
!
k8sutil
.
ContainsUser
(
users
,
subject
.
Name
)
{
user
,
err
:=
DescribeUser
(
subject
.
Name
)
user
,
err
:=
GetUserInfo
(
subject
.
Name
)
if
err
!=
nil
{
if
ldap
.
IsErrorWithCode
(
err
,
ldap
.
LDAPResultNoSuchObject
)
{
...
...
pkg/models/iam/im.go
浏览文件 @
5c4efd53
...
...
@@ -26,6 +26,7 @@ import (
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/simple/client/redis"
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"regexp"
"sort"
"strconv"
...
...
@@ -232,7 +233,7 @@ func ListUsersByName(names []string) (*models.PageableResponse, error) {
for
_
,
name
:=
range
names
{
if
!
k8sutil
.
ContainsUser
(
users
,
name
)
{
user
,
err
:=
DescribeUser
(
name
)
user
,
err
:=
GetUserInfo
(
name
)
if
err
!=
nil
{
if
ldap
.
IsErrorWithCode
(
err
,
ldap
.
LDAPResultNoSuchObject
)
{
continue
...
...
@@ -252,6 +253,30 @@ func ListUsersByName(names []string) (*models.PageableResponse, error) {
return
&
models
.
PageableResponse
{
Items
:
items
,
TotalCount
:
len
(
items
)},
nil
}
func
ListUserByEmail
(
email
[]
string
)
(
*
models
.
PageableResponse
,
error
)
{
users
:=
make
([]
*
models
.
User
,
0
)
for
_
,
mail
:=
range
email
{
user
,
err
:=
GetUserInfoByEmail
(
mail
)
if
err
!=
nil
{
if
ldap
.
IsErrorWithCode
(
err
,
ldap
.
LDAPResultNoSuchObject
)
{
continue
}
return
nil
,
err
}
if
!
k8sutil
.
ContainsUser
(
users
,
user
.
Username
)
{
users
=
append
(
users
,
user
)
}
}
items
:=
make
([]
interface
{},
0
)
for
_
,
u
:=
range
users
{
items
=
append
(
items
,
u
)
}
return
&
models
.
PageableResponse
{
Items
:
items
,
TotalCount
:
len
(
items
)},
nil
}
func
ListUsers
(
conditions
*
params
.
Conditions
,
orderBy
string
,
reverse
bool
,
limit
,
offset
int
)
(
*
models
.
PageableResponse
,
error
)
{
conn
,
err
:=
ldapclient
.
Client
()
...
...
@@ -272,6 +297,22 @@ func ListUsers(conditions *params.Conditions, orderBy string, reverse bool, limi
filter
=
fmt
.
Sprintf
(
"(&(objectClass=inetOrgPerson)(|(uid=*%s*)(mail=*%s*)(description=*%s*)))"
,
keyword
,
keyword
,
keyword
)
}
if
username
:=
conditions
.
Match
[
"username"
];
username
!=
""
{
uidFilter
:=
""
for
_
,
username
:=
range
strings
.
Split
(
username
,
"|"
)
{
uidFilter
+=
fmt
.
Sprintf
(
"(uid=%s)"
,
username
)
}
filter
=
fmt
.
Sprintf
(
"(&(objectClass=inetOrgPerson)(|%s))"
,
uidFilter
)
}
if
email
:=
conditions
.
Match
[
"email"
];
email
!=
""
{
emailFilter
:=
""
for
_
,
username
:=
range
strings
.
Split
(
email
,
"|"
)
{
emailFilter
+=
fmt
.
Sprintf
(
"(mail=%s)"
,
username
)
}
filter
=
fmt
.
Sprintf
(
"(&(objectClass=inetOrgPerson)(|%s))"
,
emailFilter
)
}
for
{
userSearchRequest
:=
ldap
.
NewSearchRequest
(
ldapclient
.
UserSearchBase
,
...
...
@@ -331,26 +372,13 @@ func ListUsers(conditions *params.Conditions, orderBy string, reverse bool, limi
if
i
>=
offset
&&
len
(
items
)
<
limit
{
avatar
,
err
:=
getAvatar
(
user
.
Username
)
if
err
!=
nil
{
return
nil
,
err
}
user
.
AvatarUrl
=
avatar
lastLoginTime
,
err
:=
getLastLoginTime
(
user
.
Username
)
if
err
!=
nil
{
return
nil
,
err
}
user
.
LastLoginTime
=
lastLoginTime
user
.
AvatarUrl
=
getAvatar
(
user
.
Username
)
user
.
LastLoginTime
=
getLastLoginTime
(
user
.
Username
)
clusterRole
,
err
:=
GetUserClusterRole
(
user
.
Username
)
if
err
!=
nil
{
return
nil
,
err
}
user
.
ClusterRole
=
clusterRole
.
Name
items
=
append
(
items
,
user
)
}
}
...
...
@@ -373,23 +401,47 @@ func DescribeUser(username string) (*models.User, error) {
}
user
.
Groups
=
groups
user
.
AvatarUrl
=
getAvatar
(
username
)
avatar
,
err
:=
getAvatar
(
username
)
return
user
,
nil
}
func
GetUserInfoByEmail
(
mail
string
)
(
*
models
.
User
,
error
)
{
conn
,
err
:=
ldapclient
.
Client
()
if
err
!=
nil
{
return
nil
,
err
}
user
.
AvatarUrl
=
avatar
userSearchRequest
:=
ldap
.
NewSearchRequest
(
ldapclient
.
UserSearchBase
,
ldap
.
ScopeWholeSubtree
,
ldap
.
NeverDerefAliases
,
0
,
0
,
false
,
fmt
.
Sprintf
(
"(&(objectClass=inetOrgPerson)(mail=%s))"
,
mail
),
[]
string
{
"uid"
,
"description"
,
"preferredLanguage"
,
"createTimestamp"
},
nil
,
)
lastLoginTime
,
err
:=
getLastLoginTime
(
username
)
result
,
err
:=
conn
.
Search
(
userSearchRequest
)
if
err
!=
nil
{
return
nil
,
err
}
user
.
LastLoginTime
=
lastLoginTime
if
len
(
result
.
Entries
)
!=
1
{
return
nil
,
ldap
.
NewError
(
ldap
.
LDAPResultNoSuchObject
,
fmt
.
Errorf
(
"user %s does not exist"
,
mail
))
}
username
:=
result
.
Entries
[
0
]
.
GetAttributeValue
(
"uid"
)
description
:=
result
.
Entries
[
0
]
.
GetAttributeValue
(
"description"
)
lang
:=
result
.
Entries
[
0
]
.
GetAttributeValue
(
"preferredLanguage"
)
createTimestamp
,
_
:=
time
.
Parse
(
"20060102150405Z"
,
result
.
Entries
[
0
]
.
GetAttributeValue
(
"createTimestamp"
))
user
:=
&
models
.
User
{
Username
:
username
,
Email
:
mail
,
Description
:
description
,
Lang
:
lang
,
CreateTime
:
createTimestamp
}
user
.
LastLoginTime
=
getLastLoginTime
(
username
)
clusterRole
,
err
:=
GetUserClusterRole
(
user
.
Username
)
if
err
!=
nil
{
return
nil
,
err
}
user
.
ClusterRole
=
clusterRole
.
Name
return
user
,
nil
}
...
...
@@ -426,6 +478,8 @@ func GetUserInfo(username string) (*models.User, error) {
createTimestamp
,
_
:=
time
.
Parse
(
"20060102150405Z"
,
result
.
Entries
[
0
]
.
GetAttributeValue
(
"createTimestamp"
))
user
:=
&
models
.
User
{
Username
:
username
,
Email
:
email
,
Description
:
description
,
Lang
:
lang
,
CreateTime
:
createTimestamp
}
user
.
LastLoginTime
=
getLastLoginTime
(
username
)
return
user
,
nil
}
...
...
@@ -462,17 +516,18 @@ func GetUserGroups(username string) ([]string, error) {
return
groups
,
nil
}
func
getLastLoginTime
(
username
string
)
(
string
,
error
)
{
func
getLastLoginTime
(
username
string
)
string
{
lastLogin
,
err
:=
redis
.
Client
()
.
LRange
(
fmt
.
Sprintf
(
"kubesphere:users:%s:login-log"
,
username
),
-
1
,
-
1
)
.
Result
()
if
err
!=
nil
{
return
""
,
err
return
""
}
if
len
(
lastLogin
)
>
0
{
return
strings
.
Split
(
lastLogin
[
0
],
","
)[
0
]
,
nil
return
strings
.
Split
(
lastLogin
[
0
],
","
)[
0
]
}
return
""
,
nil
return
""
}
func
setAvatar
(
username
,
avatar
string
)
error
{
...
...
@@ -480,20 +535,21 @@ func setAvatar(username, avatar string) error {
return
err
}
func
getAvatar
(
username
string
)
(
string
,
error
)
{
func
getAvatar
(
username
string
)
string
{
avatar
,
err
:=
redis
.
Client
()
.
HMGet
(
"kubesphere:users:avatar"
,
username
)
.
Result
()
if
err
!=
nil
{
return
""
,
err
return
""
}
if
len
(
avatar
)
>
0
{
if
url
,
ok
:=
avatar
[
0
]
.
(
string
);
ok
{
return
url
,
nil
return
url
}
}
return
""
,
nil
return
""
}
func
DeleteUser
(
username
string
)
error
{
...
...
@@ -811,7 +867,7 @@ func UpdateUser(user *models.User) (*models.User, error) {
return
nil
,
err
}
return
DescribeUser
(
user
.
Username
)
return
GetUserInfo
(
user
.
Username
)
}
func
DeleteGroup
(
path
string
)
error
{
...
...
@@ -1105,13 +1161,15 @@ func ListWorkspaceUsers(workspace string, conditions *params.Conditions, orderBy
for
_
,
roleBinding
:=
range
workspaceRoleBindings
{
for
_
,
subject
:=
range
roleBinding
.
Subjects
{
if
subject
.
Kind
==
v1
.
UserKind
&&
!
k8sutil
.
ContainsUser
(
users
,
subject
.
Name
)
{
user
,
err
:=
DescribeUser
(
subject
.
Name
)
user
,
err
:=
GetUserInfo
(
subject
.
Name
)
if
err
!=
nil
{
return
nil
,
err
}
prefix
:=
fmt
.
Sprintf
(
"workspace:%s:"
,
workspace
)
user
.
WorkspaceRole
=
fmt
.
Sprintf
(
"workspace-%s"
,
strings
.
TrimPrefix
(
roleBinding
.
Name
,
prefix
))
users
=
append
(
users
,
user
)
if
matchConditions
(
conditions
,
user
)
{
users
=
append
(
users
,
user
)
}
}
}
}
...
...
@@ -1141,3 +1199,31 @@ func ListWorkspaceUsers(workspace string, conditions *params.Conditions, orderBy
return
&
models
.
PageableResponse
{
Items
:
result
,
TotalCount
:
len
(
users
)},
nil
}
func
matchConditions
(
conditions
*
params
.
Conditions
,
user
*
models
.
User
)
bool
{
for
k
,
v
:=
range
conditions
.
Match
{
switch
k
{
case
"keyword"
:
if
!
strings
.
Contains
(
user
.
Username
,
v
)
&&
!
strings
.
Contains
(
user
.
Email
,
v
)
&&
!
strings
.
Contains
(
user
.
Description
,
v
)
{
return
false
}
case
"name"
:
names
:=
strings
.
Split
(
v
,
"|"
)
if
!
sliceutil
.
HasString
(
names
,
user
.
Username
)
{
return
false
}
case
"email"
:
email
:=
strings
.
Split
(
v
,
"|"
)
if
!
sliceutil
.
HasString
(
email
,
user
.
Email
)
{
return
false
}
case
"role"
:
if
user
.
WorkspaceRole
!=
v
{
return
false
}
}
}
return
true
}
pkg/models/iam/policy/policy.go
浏览文件 @
5c4efd53
...
...
@@ -126,6 +126,18 @@ var (
},
},
},
{
Name
:
"logging"
,
Actions
:
[]
models
.
Action
{
{
Name
:
"view"
,
Rules
:
[]
v1
.
PolicyRule
{{
Verbs
:
[]
string
{
"get"
,
"list"
},
APIGroups
:
[]
string
{
"logging.kubesphere.io"
},
Resources
:
[]
string
{
"*"
},
}},
},
},
},
{
Name
:
"accounts"
,
Actions
:
[]
models
.
Action
{
...
...
@@ -683,8 +695,8 @@ var (
Rules
:
[]
v1
.
PolicyRule
{
{
Verbs
:
[]
string
{
"get"
},
APIGroups
:
[]
string
{
"
resources
.kubesphere.io"
},
Resources
:
[]
string
{
"pod
/terminal
"
},
APIGroups
:
[]
string
{
"
terminal
.kubesphere.io"
},
Resources
:
[]
string
{
"pod
s
"
},
},
},
},
...
...
pkg/models/resources/clusterroles.go
浏览文件 @
5c4efd53
...
...
@@ -18,6 +18,7 @@
package
resources
import
(
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/params"
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
...
...
@@ -55,6 +56,12 @@ func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRol
if
!
strings
.
Contains
(
item
.
Name
,
v
)
&&
!
searchFuzzy
(
item
.
Labels
,
""
,
v
)
&&
!
searchFuzzy
(
item
.
Annotations
,
""
,
v
)
{
return
false
}
case
"userfacing"
:
if
v
==
"true"
{
if
!
isUserFacingClusterRole
(
item
)
{
return
false
}
}
default
:
if
item
.
Labels
[
k
]
!=
v
{
return
false
...
...
@@ -134,3 +141,10 @@ func (s *clusterRoleSearcher) search(namespace string, conditions *params.Condit
}
return
r
,
nil
}
func
isUserFacingClusterRole
(
role
*
rbac
.
ClusterRole
)
bool
{
if
role
.
Labels
[
constants
.
CreatorLabelKey
]
!=
""
&&
role
.
Labels
[
constants
.
WorkspaceLabelKey
]
==
""
{
return
true
}
return
false
}
pkg/models/resources/resources.go
浏览文件 @
5c4efd53
...
...
@@ -103,24 +103,15 @@ type resourceSearchInterface interface {
search
(
namespace
string
,
conditions
*
params
.
Conditions
,
orderBy
string
,
reverse
bool
)
([]
interface
{},
error
)
}
func
ListResourcesByName
(
namespace
,
resource
string
,
names
[]
string
)
(
*
models
.
PageableResponse
,
error
)
{
items
:=
make
([]
interface
{},
0
)
func
GetResource
(
namespace
,
resource
,
name
string
)
(
interface
{},
error
)
{
if
searcher
,
ok
:=
resources
[
resource
];
ok
{
for
_
,
name
:=
range
names
{
item
,
err
:=
searcher
.
get
(
namespace
,
name
)
if
err
!=
nil
{
return
nil
,
err
}
items
=
append
(
items
,
item
)
resource
,
err
:=
searcher
.
get
(
namespace
,
name
)
if
err
!=
nil
{
return
nil
,
err
}
}
else
{
return
nil
,
fmt
.
Errorf
(
"not found"
)
return
resource
,
nil
}
return
&
models
.
PageableResponse
{
TotalCount
:
len
(
items
),
Items
:
items
},
nil
return
nil
,
fmt
.
Errorf
(
"resource %s not found"
,
resource
)
}
func
ListResources
(
namespace
,
resource
string
,
conditions
*
params
.
Conditions
,
orderBy
string
,
reverse
bool
,
limit
,
offset
int
)
(
*
models
.
PageableResponse
,
error
)
{
...
...
pkg/models/routers/routers.go
浏览文件 @
5c4efd53
...
...
@@ -22,6 +22,7 @@ import (
"fmt"
"github.com/golang/glog"
"io/ioutil"
"k8s.io/apimachinery/pkg/api/errors"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"sort"
...
...
@@ -127,7 +128,7 @@ func GetRouter(namespace string) (*corev1.Service, error) {
}
}
return
nil
,
fmt
.
Errorf
(
"resources not found %s"
,
serviceName
)
return
nil
,
errors
.
NewNotFound
(
corev1
.
Resource
(
"service"
)
,
serviceName
)
}
// Load all resource yamls
...
...
pkg/models/tenant/devops.go
浏览文件 @
5c4efd53
...
...
@@ -18,15 +18,10 @@
package
tenant
import
(
"encoding/json"
"fmt"
"io/ioutil"
"kubesphere.io/kubesphere/pkg/constants"
kserr
"kubesphere.io/kubesphere/pkg/errors"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/params"
"kubesphere.io/kubesphere/pkg/simple/client/kubesphere"
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
"net/http"
"sort"
"strings"
)
...
...
@@ -41,79 +36,55 @@ func ListDevopsProjects(workspace, username string, conditions *params.Condition
return
nil
,
err
}
devOpsProjects
:=
make
([]
models
.
DevopsProject
,
0
)
request
,
_
:=
http
.
NewRequest
(
http
.
MethodGet
,
fmt
.
Sprintf
(
"http://%s/api/v1alpha/projects"
,
constants
.
DevopsAPIServer
),
nil
)
request
.
Header
.
Add
(
constants
.
UserNameHeader
,
username
)
resp
,
err
:=
http
.
DefaultClient
.
Do
(
request
)
if
err
!=
nil
{
return
nil
,
err
}
defer
resp
.
Body
.
Close
()
data
,
err
:=
ioutil
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
return
nil
,
err
}
if
resp
.
StatusCode
>
200
{
return
nil
,
kserr
.
Parse
(
data
)
}
err
=
json
.
Unmarshal
(
data
,
&
devOpsProjects
)
projects
,
err
:=
kubesphere
.
Client
()
.
ListDevopsProjects
(
username
)
if
err
!=
nil
{
return
nil
,
err
}
if
keyword
:=
conditions
.
Match
[
"keyword"
];
keyword
!=
""
{
for
i
:=
0
;
i
<
len
(
devOpsP
rojects
);
i
++
{
if
!
strings
.
Contains
(
devOpsP
rojects
[
i
]
.
Name
,
keyword
)
{
devOpsProjects
=
append
(
devOpsProjects
[
:
i
],
devOpsP
rojects
[
i
+
1
:
]
...
)
for
i
:=
0
;
i
<
len
(
p
rojects
);
i
++
{
if
!
strings
.
Contains
(
p
rojects
[
i
]
.
Name
,
keyword
)
{
projects
=
append
(
projects
[
:
i
],
p
rojects
[
i
+
1
:
]
...
)
i
--
}
}
}
sort
.
Slice
(
devOpsProjects
,
func
(
i
,
j
int
)
bool
{
sort
.
Slice
(
projects
,
func
(
i
,
j
int
)
bool
{
if
reverse
{
tmp
:=
i
i
=
j
j
=
tmp
}
switch
orderBy
{
case
"name"
:
if
reverse
{
return
devOpsProjects
[
i
]
.
Name
<
devOpsProjects
[
j
]
.
Name
}
else
{
return
devOpsProjects
[
i
]
.
Name
>
devOpsProjects
[
j
]
.
Name
}
return
projects
[
i
]
.
Name
>
projects
[
j
]
.
Name
default
:
if
reverse
{
return
devOpsProjects
[
i
]
.
CreateTime
.
After
(
*
devOpsProjects
[
j
]
.
CreateTime
)
}
else
{
return
devOpsProjects
[
i
]
.
CreateTime
.
Before
(
*
devOpsProjects
[
j
]
.
CreateTime
)
}
return
projects
[
i
]
.
CreateTime
.
Before
(
*
projects
[
j
]
.
CreateTime
)
}
})
for
i
:=
0
;
i
<
len
(
devOpsP
rojects
);
i
++
{
for
i
:=
0
;
i
<
len
(
p
rojects
);
i
++
{
inWorkspace
:=
false
for
_
,
binding
:=
range
workspaceDOPBindings
{
if
binding
.
DevOpsProject
==
*
devOpsP
rojects
[
i
]
.
ProjectId
{
if
binding
.
DevOpsProject
==
p
rojects
[
i
]
.
ProjectId
{
inWorkspace
=
true
}
}
if
!
inWorkspace
{
devOpsProjects
=
append
(
devOpsProjects
[
:
i
],
devOpsP
rojects
[
i
+
1
:
]
...
)
projects
=
append
(
projects
[
:
i
],
p
rojects
[
i
+
1
:
]
...
)
i
--
}
}
// limit offset
result
:=
make
([]
interface
{},
0
)
for
i
,
v
:=
range
devOpsP
rojects
{
for
i
,
v
:=
range
p
rojects
{
if
len
(
result
)
<
limit
&&
i
>=
offset
{
result
=
append
(
result
,
v
)
}
}
return
&
models
.
PageableResponse
{
Items
:
result
,
TotalCount
:
len
(
devOpsP
rojects
)},
nil
return
&
models
.
PageableResponse
{
Items
:
result
,
TotalCount
:
len
(
p
rojects
)},
nil
}
pkg/models/tenant/namespaces.go
浏览文件 @
5c4efd53
...
...
@@ -21,6 +21,7 @@ import (
"k8s.io/api/core/v1"
rbacv1
"k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/params"
...
...
@@ -35,6 +36,14 @@ type namespaceSearcher struct {
func
(
*
namespaceSearcher
)
match
(
match
map
[
string
]
string
,
item
*
v1
.
Namespace
)
bool
{
for
k
,
v
:=
range
match
{
switch
k
{
case
"name"
:
if
item
.
Name
!=
v
&&
item
.
Labels
[
constants
.
DisplayNameLabelKey
]
!=
v
{
return
false
}
case
"keyword"
:
if
!
strings
.
Contains
(
item
.
Name
,
v
)
&&
!
contains
(
item
.
Labels
,
""
,
v
)
&&
!
contains
(
item
.
Annotations
,
""
,
v
)
{
return
false
}
default
:
if
item
.
Labels
[
k
]
!=
v
{
return
false
...
...
pkg/models/tenant/tenant.go
浏览文件 @
5c4efd53
...
...
@@ -19,7 +19,9 @@ package tenant
import
(
"k8s.io/api/core/v1"
"kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
"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/params"
...
...
@@ -45,6 +47,18 @@ func CreateNamespace(workspaceName string, namespace *v1.Namespace, username str
return
k8s
.
Client
()
.
CoreV1
()
.
Namespaces
()
.
Create
(
namespace
)
}
func
DescribeWorkspace
(
username
,
workspaceName
string
)
(
*
v1alpha1
.
Workspace
,
error
)
{
workspace
,
err
:=
informers
.
KsSharedInformerFactory
()
.
Tenant
()
.
V1alpha1
()
.
Workspaces
()
.
Lister
()
.
Get
(
workspaceName
)
if
err
!=
nil
{
return
nil
,
err
}
workspace
=
appendAnnotations
(
username
,
workspace
)
return
workspace
,
nil
}
func
ListWorkspaces
(
username
string
,
conditions
*
params
.
Conditions
,
orderBy
string
,
reverse
bool
,
limit
,
offset
int
)
(
*
models
.
PageableResponse
,
error
)
{
workspaces
,
err
:=
workspaces
.
search
(
username
,
conditions
,
orderBy
,
reverse
)
...
...
@@ -57,25 +71,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
:=
workspace
.
DeepCopy
()
ns
,
err
:=
ListNamespaces
(
username
,
&
params
.
Conditions
{
Match
:
map
[
string
]
string
{
"kubesphere.io/workspace"
:
workspace
.
Name
}},
""
,
false
,
1
,
0
)
if
err
!=
nil
{
return
nil
,
err
}
if
workspace
.
Annotations
==
nil
{
workspace
.
Annotations
=
make
(
map
[
string
]
string
)
}
workspace
.
Annotations
[
"kubesphere.io/namespace-count"
]
=
strconv
.
Itoa
(
ns
.
TotalCount
)
devops
,
err
:=
ListDevopsProjects
(
workspace
.
Name
,
username
,
&
params
.
Conditions
{},
""
,
false
,
1
,
0
)
if
err
!=
nil
{
return
nil
,
err
}
workspace
.
Annotations
[
"kubesphere.io/devops-count"
]
=
strconv
.
Itoa
(
devops
.
TotalCount
)
userCount
,
err
:=
ws
.
WorkspaceUserCount
(
workspace
.
Name
)
if
err
!=
nil
{
return
nil
,
err
}
workspace
.
Annotations
[
"kubesphere.io/member-count"
]
=
strconv
.
Itoa
(
userCount
)
workspace
:=
appendAnnotations
(
username
,
workspace
)
result
=
append
(
result
,
workspace
)
}
}
...
...
@@ -83,6 +79,32 @@ 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
{
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
)
if
err
==
nil
{
workspace
.
Annotations
[
"kubesphere.io/namespace-count"
]
=
strconv
.
Itoa
(
ns
.
TotalCount
)
}
else
{
workspace
.
Annotations
[
"kubesphere.io/namespace-count"
]
=
"-1"
}
devops
,
err
:=
ListDevopsProjects
(
workspace
.
Name
,
username
,
&
params
.
Conditions
{},
""
,
false
,
1
,
0
)
if
err
==
nil
{
workspace
.
Annotations
[
"kubesphere.io/devops-count"
]
=
strconv
.
Itoa
(
devops
.
TotalCount
)
}
else
{
workspace
.
Annotations
[
"kubesphere.io/devops-count"
]
=
"-1"
}
userCount
,
err
:=
ws
.
WorkspaceUserCount
(
workspace
.
Name
)
if
err
==
nil
{
workspace
.
Annotations
[
"kubesphere.io/member-count"
]
=
strconv
.
Itoa
(
userCount
)
}
else
{
workspace
.
Annotations
[
"kubesphere.io/member-count"
]
=
"-1"
}
return
workspace
}
func
ListNamespaces
(
username
string
,
conditions
*
params
.
Conditions
,
orderBy
string
,
reverse
bool
,
limit
,
offset
int
)
(
*
models
.
PageableResponse
,
error
)
{
namespaces
,
err
:=
namespaces
.
search
(
username
,
conditions
,
orderBy
,
reverse
)
...
...
pkg/models/tenant/workspaces.go
浏览文件 @
5c4efd53
...
...
@@ -40,6 +40,10 @@ func (*workspaceSearcher) match(match map[string]string, item *v1alpha1.Workspac
if
item
.
Name
!=
v
&&
item
.
Labels
[
constants
.
DisplayNameLabelKey
]
!=
v
{
return
false
}
case
"keyword"
:
if
!
strings
.
Contains
(
item
.
Name
,
v
)
&&
!
contains
(
item
.
Labels
,
""
,
v
)
&&
!
contains
(
item
.
Annotations
,
""
,
v
)
{
return
false
}
default
:
if
item
.
Labels
[
k
]
!=
v
{
return
false
...
...
@@ -128,3 +132,16 @@ func (s *workspaceSearcher) search(username string, conditions *params.Condition
func
GetWorkspace
(
workspaceName
string
)
(
*
v1alpha1
.
Workspace
,
error
)
{
return
informers
.
KsSharedInformerFactory
()
.
Tenant
()
.
V1alpha1
()
.
Workspaces
()
.
Lister
()
.
Get
(
workspaceName
)
}
func
contains
(
m
map
[
string
]
string
,
key
,
value
string
)
bool
{
for
k
,
v
:=
range
m
{
if
key
==
""
{
if
strings
.
Contains
(
k
,
value
)
||
strings
.
Contains
(
v
,
value
)
{
return
true
}
}
else
if
k
==
key
&&
strings
.
Contains
(
v
,
value
)
{
return
true
}
}
return
false
}
pkg/models/types.go
浏览文件 @
5c4efd53
...
...
@@ -42,7 +42,7 @@ type WorkspaceDPBinding struct {
}
type
DevopsProject
struct
{
ProjectId
*
string
`json:"project_id,omitempty"`
ProjectId
string
`json:"project_id,omitempty"`
Name
string
`json:"name"`
Description
string
`json:"description"`
Creator
string
`json:"creator"`
...
...
pkg/models/workspaces/workspaces.go
浏览文件 @
5c4efd53
...
...
@@ -18,41 +18,29 @@
package
workspaces
import
(
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"k8s.io/apimachinery/pkg/runtime/schema"
"kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/models/resources"
"kubesphere.io/kubesphere/pkg/params"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/simple/client/
ldap
"
"kubesphere.io/kubesphere/pkg/simple/client/
kubesphere
"
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"net/http"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/iam"
"strings"
"github.com/jinzhu/gorm"
core
"k8s.io/api/core/v1"
"errors"
"github.com/golang/glog"
"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"
"sort"
kserr
"kubesphere.io/kubesphere/pkg/errors"
)
func
UnBindDevopsProject
(
workspace
string
,
devops
string
)
error
{
...
...
@@ -60,191 +48,26 @@ func UnBindDevopsProject(workspace string, devops string) error {
return
db
.
Delete
(
&
models
.
WorkspaceDPBinding
{
Workspace
:
workspace
,
DevOpsProject
:
devops
})
.
Error
}
func
DeleteDevopsProject
(
username
string
,
devops
string
)
error
{
request
,
_
:=
http
.
NewRequest
(
http
.
MethodDelete
,
fmt
.
Sprintf
(
"http://%s/api/v1alpha/projects/%s"
,
constants
.
DevopsAPIServer
,
devops
),
nil
)
request
.
Header
.
Add
(
"X-Token-Username"
,
username
)
result
,
err
:=
http
.
DefaultClient
.
Do
(
request
)
if
err
!=
nil
{
return
err
}
defer
result
.
Body
.
Close
()
data
,
err
:=
ioutil
.
ReadAll
(
result
.
Body
)
if
err
!=
nil
{
return
err
}
if
result
.
StatusCode
>
200
{
return
kserr
.
Parse
(
data
)
}
return
nil
}
func
CreateDevopsProject
(
username
string
,
workspace
string
,
devops
models
.
DevopsProject
)
(
*
models
.
DevopsProject
,
error
)
{
data
,
err
:=
json
.
Marshal
(
devops
)
if
err
!=
nil
{
return
nil
,
err
}
request
,
_
:=
http
.
NewRequest
(
http
.
MethodPost
,
fmt
.
Sprintf
(
"http://%s/api/v1alpha/projects"
,
constants
.
DevopsAPIServer
),
bytes
.
NewReader
(
data
))
request
.
Header
.
Add
(
"X-Token-Username"
,
username
)
request
.
Header
.
Add
(
"Content-Type"
,
"application/json"
)
result
,
err
:=
http
.
DefaultClient
.
Do
(
request
)
if
err
!=
nil
{
return
nil
,
err
}
defer
result
.
Body
.
Close
()
data
,
err
=
ioutil
.
ReadAll
(
result
.
Body
)
if
err
!=
nil
{
return
nil
,
err
}
func
CreateDevopsProject
(
username
string
,
workspace
string
,
devops
*
models
.
DevopsProject
)
(
*
models
.
DevopsProject
,
error
)
{
if
result
.
StatusCode
>
200
{
return
nil
,
kserr
.
Parse
(
data
)
}
var
project
models
.
DevopsProject
err
=
json
.
Unmarshal
(
data
,
&
project
)
created
,
err
:=
kubesphere
.
Client
()
.
CreateDevopsProject
(
username
,
devops
)
if
err
!=
nil
{
return
nil
,
err
}
err
=
BindingDevopsProject
(
workspace
,
*
project
.
ProjectId
)
err
=
BindingDevopsProject
(
workspace
,
created
.
ProjectId
)
if
err
!=
nil
{
DeleteDevopsProject
(
username
,
*
project
.
ProjectId
)
return
nil
,
err
}
go
createDefaultDevopsRoleBinding
(
workspace
,
project
)
return
&
project
,
nil
}
func
createDefaultDevopsRoleBinding
(
workspace
string
,
project
models
.
DevopsProject
)
error
{
admins
:=
[]
string
{
""
}
for
_
,
admin
:=
range
admins
{
createDevopsRoleBinding
(
workspace
,
*
project
.
ProjectId
,
admin
,
constants
.
DevopsOwner
)
}
viewers
:=
[]
string
{
""
}
for
_
,
viewer
:=
range
viewers
{
createDevopsRoleBinding
(
workspace
,
*
project
.
ProjectId
,
viewer
,
constants
.
DevopsReporter
)
}
return
nil
}
func
createDevopsRoleBinding
(
workspace
string
,
projectId
string
,
user
string
,
role
string
)
{
projects
:=
make
([]
string
,
0
)
if
projectId
!=
""
{
projects
=
append
(
projects
,
projectId
)
}
else
{
p
,
err
:=
GetDevOpsProjects
(
workspace
)
if
err
!=
nil
{
glog
.
Warning
(
"create devops role binding failed"
,
workspace
,
projectId
,
user
,
role
)
return
}
projects
=
append
(
projects
,
p
...
)
}
for
_
,
project
:=
range
projects
{
data
:=
[]
byte
(
fmt
.
Sprintf
(
`{"username":"%s","role":"%s"}`
,
user
,
role
))
request
,
_
:=
http
.
NewRequest
(
http
.
MethodPost
,
fmt
.
Sprintf
(
"http://%s/api/v1alpha/projects/%s/members"
,
constants
.
DevopsAPIServer
,
project
),
bytes
.
NewReader
(
data
))
request
.
Header
.
Add
(
"Content-Type"
,
"application/json"
)
request
.
Header
.
Add
(
"X-Token-Username"
,
"admin"
)
resp
,
err
:=
http
.
DefaultClient
.
Do
(
request
)
if
err
!=
nil
||
resp
.
StatusCode
>
200
{
glog
.
Warning
(
fmt
.
Sprintf
(
"create devops role binding failed %s,%s,%s,%s"
,
workspace
,
project
,
user
,
role
))
}
if
resp
!=
nil
{
resp
.
Body
.
Close
()
}
}
}
func
ListNamespaceByUser
(
workspaceName
string
,
username
string
,
keyword
string
,
orderBy
string
,
reverse
bool
,
limit
int
,
offset
int
)
(
int
,
[]
*
core
.
Namespace
,
error
)
{
namespaces
,
err
:=
Namespaces
(
workspaceName
)
if
err
!=
nil
{
return
0
,
nil
,
err
}
if
keyword
!=
""
{
for
i
:=
0
;
i
<
len
(
namespaces
);
i
++
{
if
!
strings
.
Contains
(
namespaces
[
i
]
.
Name
,
keyword
)
{
namespaces
=
append
(
namespaces
[
:
i
],
namespaces
[
i
+
1
:
]
...
)
i
--
}
}
}
sort
.
Slice
(
namespaces
,
func
(
i
,
j
int
)
bool
{
switch
orderBy
{
case
"name"
:
if
reverse
{
return
namespaces
[
i
]
.
Name
<
namespaces
[
j
]
.
Name
}
else
{
return
namespaces
[
i
]
.
Name
>
namespaces
[
j
]
.
Name
}
default
:
if
reverse
{
return
namespaces
[
i
]
.
CreationTimestamp
.
Time
.
After
(
namespaces
[
j
]
.
CreationTimestamp
.
Time
)
}
else
{
return
namespaces
[
i
]
.
CreationTimestamp
.
Time
.
Before
(
namespaces
[
j
]
.
CreationTimestamp
.
Time
)
}
}
})
rules
,
err
:=
iam
.
GetUserClusterRules
(
username
)
if
err
!=
nil
{
return
0
,
nil
,
err
}
namespacesManager
:=
v1
.
PolicyRule
{
APIGroups
:
[]
string
{
"kubesphere.io"
},
ResourceNames
:
[]
string
{
workspaceName
},
Verbs
:
[]
string
{
"get"
},
Resources
:
[]
string
{
"workspaces/namespaces"
}}
if
!
iam
.
RulesMatchesRequired
(
rules
,
namespacesManager
)
{
for
i
:=
0
;
i
<
len
(
namespaces
);
i
++
{
roles
,
err
:=
iam
.
GetUserRoles
(
namespaces
[
i
]
.
Name
,
username
)
if
err
!=
nil
{
return
0
,
nil
,
err
}
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
--
}
}
}
if
len
(
namespaces
)
<
offset
{
return
len
(
namespaces
),
namespaces
,
nil
}
else
if
len
(
namespaces
)
<
limit
+
offset
{
return
len
(
namespaces
),
namespaces
[
offset
:
],
nil
}
else
{
return
len
(
namespaces
),
namespaces
[
offset
:
limit
+
offset
],
nil
}
return
created
,
nil
}
func
Namespaces
(
workspaceName
string
)
([]
*
core
.
Namespace
,
error
)
{
namespaceLister
:=
informers
.
SharedInformerFactory
()
.
Core
()
.
V1
()
.
Namespaces
()
.
Lister
()
namespaces
,
err
:=
namespaceLister
.
List
(
labels
.
SelectorFromSet
(
labels
.
Set
{
"kubesphere.io/workspace"
:
workspaceName
}))
namespaces
,
err
:=
namespaceLister
.
List
(
labels
.
SelectorFromSet
(
labels
.
Set
{
constants
.
WorkspaceLabelKey
:
workspaceName
}))
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -281,161 +104,18 @@ func DeleteNamespace(workspace string, namespaceName string) error {
}
}
func
Delete
(
workspace
*
models
.
Workspace
)
error
{
err
:=
release
(
workspace
)
func
RemoveUser
(
workspaceName
string
,
username
string
)
error
{
workspaceRole
,
err
:=
iam
.
GetUserWorkspaceRole
(
workspaceName
,
username
)
if
err
!=
nil
{
return
err
}
err
=
iam
.
DeleteGroup
(
workspace
.
Name
)
err
=
DeleteWorkspaceRoleBinding
(
workspaceName
,
username
,
workspaceRole
.
Labels
[
constants
.
DisplayNameLabelKey
])
if
err
!=
nil
{
return
err
}
return
nil
}
// TODO
func
release
(
workspace
*
models
.
Workspace
)
error
{
for
_
,
namespace
:=
range
workspace
.
Namespaces
{
err
:=
DeleteNamespace
(
workspace
.
Name
,
namespace
)
if
err
!=
nil
&&
!
apierrors
.
IsNotFound
(
err
)
{
return
err
}
}
for
_
,
devops
:=
range
workspace
.
DevopsProjects
{
err
:=
DeleteDevopsProject
(
"admin"
,
devops
)
if
err
!=
nil
&&
!
strings
.
Contains
(
err
.
Error
(),
"not found"
)
{
return
err
}
}
err
:=
workspaceRoleRelease
(
workspace
.
Name
)
return
err
}
func
workspaceRoleRelease
(
workspace
string
)
error
{
k8sClient
:=
k8s
.
Client
()
deletePolicy
:=
meta_v1
.
DeletePropagationForeground
for
_
,
role
:=
range
constants
.
WorkSpaceRoles
{
err
:=
k8sClient
.
RbacV1
()
.
ClusterRoles
()
.
Delete
(
fmt
.
Sprintf
(
"system:%s:%s"
,
workspace
,
role
),
&
meta_v1
.
DeleteOptions
{
PropagationPolicy
:
&
deletePolicy
})
if
err
!=
nil
&&
!
apierrors
.
IsNotFound
(
err
)
{
return
err
}
}
for
_
,
role
:=
range
constants
.
WorkSpaceRoles
{
err
:=
k8sClient
.
RbacV1
()
.
ClusterRoleBindings
()
.
Delete
(
fmt
.
Sprintf
(
"system:%s:%s"
,
workspace
,
role
),
&
meta_v1
.
DeleteOptions
{
PropagationPolicy
:
&
deletePolicy
})
if
err
!=
nil
&&
!
apierrors
.
IsNotFound
(
err
)
{
return
err
}
}
return
nil
}
func
Edit
(
workspace
*
models
.
Workspace
)
(
*
models
.
Workspace
,
error
)
{
group
,
err
:=
iam
.
UpdateGroup
(
&
workspace
.
Group
)
if
err
!=
nil
{
return
nil
,
err
}
workspace
.
Group
=
*
group
return
workspace
,
nil
}
func
DescribeWorkspace
(
workspaceName
string
)
(
*
v1alpha1
.
Workspace
,
error
)
{
workspace
,
err
:=
informers
.
KsSharedInformerFactory
()
.
Tenant
()
.
V1alpha1
()
.
Workspaces
()
.
Lister
()
.
Get
(
workspaceName
)
if
err
!=
nil
{
return
nil
,
err
}
return
workspace
,
nil
}
func
fetch
(
names
[]
string
)
([]
*
models
.
Workspace
,
error
)
{
if
names
!=
nil
&&
len
(
names
)
==
0
{
return
make
([]
*
models
.
Workspace
,
0
),
nil
}
var
groups
[]
models
.
Group
var
err
error
if
names
==
nil
{
groups
,
err
=
iam
.
ChildList
(
""
)
if
err
!=
nil
{
return
nil
,
err
}
}
else
{
conn
,
err
:=
ldap
.
Client
()
if
err
!=
nil
{
return
nil
,
err
}
defer
conn
.
Close
()
for
_
,
name
:=
range
names
{
group
,
err
:=
iam
.
DescribeGroup
(
name
)
if
err
!=
nil
{
return
nil
,
err
}
groups
=
append
(
groups
,
*
group
)
}
}
db
:=
mysql
.
Client
()
workspaces
:=
make
([]
*
models
.
Workspace
,
0
)
for
_
,
group
:=
range
groups
{
workspace
,
err
:=
convertGroupToWorkspace
(
db
,
group
)
if
err
!=
nil
{
return
nil
,
err
}
workspaces
=
append
(
workspaces
,
workspace
)
}
return
workspaces
,
nil
}
func
convertGroupToWorkspace
(
db
*
gorm
.
DB
,
group
models
.
Group
)
(
*
models
.
Workspace
,
error
)
{
namespaces
,
err
:=
Namespaces
(
group
.
Name
)
if
err
!=
nil
{
return
nil
,
err
}
namespacesNames
:=
make
([]
string
,
0
)
for
_
,
namespace
:=
range
namespaces
{
namespacesNames
=
append
(
namespacesNames
,
namespace
.
Name
)
}
var
workspaceDOPBindings
[]
models
.
WorkspaceDPBinding
if
err
:=
db
.
Where
(
"workspace = ?"
,
group
.
Name
)
.
Find
(
&
workspaceDOPBindings
)
.
Error
;
err
!=
nil
{
return
nil
,
err
}
devOpsProjects
:=
make
([]
string
,
0
)
for
_
,
workspaceDOPBinding
:=
range
workspaceDOPBindings
{
devOpsProjects
=
append
(
devOpsProjects
,
workspaceDOPBinding
.
DevOpsProject
)
}
workspace
:=
models
.
Workspace
{
Group
:
group
}
workspace
.
Namespaces
=
namespacesNames
workspace
.
DevopsProjects
=
devOpsProjects
return
&
workspace
,
nil
}
func
InviteUser
(
workspaceName
string
,
user
*
models
.
User
)
error
{
workspaceRole
,
err
:=
iam
.
GetUserWorkspaceRole
(
workspaceName
,
user
.
Username
)
...
...
@@ -463,7 +143,6 @@ func CreateWorkspaceRoleBinding(workspace, username string, role string) error {
}
roleBindingName
:=
fmt
.
Sprintf
(
"workspace:%s:%s"
,
workspace
,
strings
.
TrimPrefix
(
role
,
"workspace-"
))
workspaceRoleBinding
,
err
:=
informers
.
SharedInformerFactory
()
.
Rbac
()
.
V1
()
.
ClusterRoleBindings
()
.
Lister
()
.
Get
(
roleBindingName
)
workspaceRoleBinding
=
workspaceRoleBinding
.
DeepCopy
()
if
err
!=
nil
{
...
...
@@ -487,11 +166,10 @@ func DeleteWorkspaceRoleBinding(workspace, username string, role string) error {
roleBindingName
:=
fmt
.
Sprintf
(
"workspace:%s:%s"
,
workspace
,
strings
.
TrimPrefix
(
role
,
"workspace-"
))
workspaceRoleBinding
,
err
:=
informers
.
SharedInformerFactory
()
.
Rbac
()
.
V1
()
.
ClusterRoleBindings
()
.
Lister
()
.
Get
(
roleBindingName
)
workspaceRoleBinding
=
workspaceRoleBinding
.
DeepCopy
()
if
err
!=
nil
{
return
err
}
workspaceRoleBinding
=
workspaceRoleBinding
.
DeepCopy
()
for
i
,
v
:=
range
workspaceRoleBinding
.
Subjects
{
if
v
.
Kind
==
v1
.
UserKind
&&
v
.
Name
==
username
{
...
...
pkg/params/params.go
浏览文件 @
5c4efd53
...
...
@@ -82,18 +82,6 @@ func ParseReverse(req *restful.Request) bool {
return
b
}
func
ParseArray
(
str
string
)
[]
string
{
arr
:=
make
([]
string
,
0
)
for
_
,
item
:=
range
strings
.
Split
(
str
,
","
)
{
if
item
=
strings
.
TrimSpace
(
item
);
item
!=
""
{
arr
=
append
(
arr
,
item
)
}
}
return
arr
}
type
Conditions
struct
{
Match
map
[
string
]
string
Fuzzy
map
[
string
]
string
...
...
pkg/simple/client/kubesphere/devops.go
0 → 100644
浏览文件 @
5c4efd53
/*
Copyright 2019 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
kubesphere
import
(
"bytes"
"encoding/json"
"fmt"
"github.com/golang/glog"
"io/ioutil"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models"
"net/http"
)
func
(
c
client
)
DeleteDevopsProject
(
username
string
,
projectId
string
)
error
{
request
,
_
:=
http
.
NewRequest
(
http
.
MethodDelete
,
fmt
.
Sprintf
(
"%s/api/v1alpha/projects/%s"
,
devopsAPIServer
,
projectId
),
nil
)
if
username
==
""
{
username
=
constants
.
AdminUserName
}
request
.
Header
.
Add
(
"X-Token-Username"
,
username
)
resp
,
err
:=
c
.
client
.
Do
(
request
)
if
err
!=
nil
{
return
err
}
defer
resp
.
Body
.
Close
()
data
,
err
:=
ioutil
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
return
err
}
if
resp
.
StatusCode
>
http
.
StatusOK
{
return
Error
{
resp
.
StatusCode
,
string
(
data
)}
}
return
nil
}
func
(
c
client
)
GetUserDevopsRole
(
username
string
,
projectId
string
)
(
string
,
error
)
{
if
username
==
"admin"
{
return
"owner"
,
nil
}
req
,
err
:=
http
.
NewRequest
(
http
.
MethodGet
,
fmt
.
Sprintf
(
"%s/api/v1alpha/projects/%s/members"
,
devopsAPIServer
,
projectId
),
nil
)
if
err
!=
nil
{
return
""
,
err
}
req
.
Header
.
Set
(
constants
.
UserNameHeader
,
username
)
resp
,
err
:=
c
.
client
.
Do
(
req
)
if
err
!=
nil
{
return
""
,
err
}
defer
resp
.
Body
.
Close
()
data
,
err
:=
ioutil
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
return
""
,
err
}
if
resp
.
StatusCode
>
http
.
StatusOK
{
return
""
,
Error
{
resp
.
StatusCode
,
string
(
data
)}
}
var
result
[]
map
[
string
]
string
err
=
json
.
Unmarshal
(
data
,
&
result
)
if
err
!=
nil
{
return
""
,
err
}
for
_
,
item
:=
range
result
{
if
item
[
"username"
]
==
username
{
return
item
[
"role"
],
nil
}
}
return
""
,
nil
}
func
(
c
client
)
CreateDevopsProject
(
username
string
,
project
*
models
.
DevopsProject
)
(
*
models
.
DevopsProject
,
error
)
{
data
,
err
:=
json
.
Marshal
(
project
)
if
err
!=
nil
{
return
nil
,
err
}
request
,
_
:=
http
.
NewRequest
(
http
.
MethodPost
,
fmt
.
Sprintf
(
"%s/api/v1alpha/projects"
,
devopsAPIServer
),
bytes
.
NewReader
(
data
))
request
.
Header
.
Add
(
"X-Token-Username"
,
username
)
request
.
Header
.
Add
(
"Content-Type"
,
"application/json"
)
resp
,
err
:=
c
.
client
.
Do
(
request
)
if
err
!=
nil
{
return
nil
,
err
}
defer
resp
.
Body
.
Close
()
data
,
err
=
ioutil
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
return
nil
,
err
}
if
resp
.
StatusCode
>
http
.
StatusOK
{
return
nil
,
Error
{
resp
.
StatusCode
,
string
(
data
)}
}
var
created
models
.
DevopsProject
err
=
json
.
Unmarshal
(
data
,
&
created
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
created
,
nil
}
func
(
c
client
)
CreateDevopsRoleBinding
(
projectId
string
,
user
string
,
role
string
)
{
projects
:=
make
([]
string
,
0
)
projects
=
append
(
projects
,
projectId
)
for
_
,
project
:=
range
projects
{
data
:=
[]
byte
(
fmt
.
Sprintf
(
`{"username":"%s","role":"%s"}`
,
user
,
role
))
request
,
_
:=
http
.
NewRequest
(
http
.
MethodPost
,
fmt
.
Sprintf
(
"%s/api/v1alpha/projects/%s/members"
,
devopsAPIServer
,
project
),
bytes
.
NewReader
(
data
))
request
.
Header
.
Add
(
"Content-Type"
,
"application/json"
)
request
.
Header
.
Add
(
"X-Token-Username"
,
"admin"
)
resp
,
err
:=
c
.
client
.
Do
(
request
)
if
err
!=
nil
||
resp
.
StatusCode
>
200
{
glog
.
Warning
(
fmt
.
Sprintf
(
"create devops role binding failed %s,%s,%s"
,
project
,
user
,
role
))
}
if
resp
!=
nil
{
resp
.
Body
.
Close
()
}
}
}
func
(
c
client
)
ListDevopsProjects
(
username
string
)
([]
models
.
DevopsProject
,
error
)
{
projects
:=
make
([]
models
.
DevopsProject
,
0
)
request
,
_
:=
http
.
NewRequest
(
http
.
MethodGet
,
fmt
.
Sprintf
(
"%s/api/v1alpha/projects"
,
devopsAPIServer
),
nil
)
request
.
Header
.
Add
(
constants
.
UserNameHeader
,
username
)
resp
,
err
:=
c
.
client
.
Do
(
request
)
if
err
!=
nil
{
return
nil
,
err
}
defer
resp
.
Body
.
Close
()
data
,
err
:=
ioutil
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
return
nil
,
err
}
if
resp
.
StatusCode
>
http
.
StatusOK
{
return
nil
,
Error
{
resp
.
StatusCode
,
string
(
data
)}
}
err
=
json
.
Unmarshal
(
data
,
&
projects
)
if
err
!=
nil
{
return
nil
,
err
}
return
projects
,
nil
}
pkg/simple/client/kubesphere/kubesphereclient.go
浏览文件 @
5c4efd53
...
...
@@ -32,6 +32,7 @@ import (
var
(
accountAPIServer
string
devopsAPIServer
string
once
sync
.
Once
c
client
)
...
...
@@ -41,6 +42,11 @@ type Interface interface {
UpdateGroup
(
group
*
models
.
Group
)
(
*
models
.
Group
,
error
)
DescribeGroup
(
name
string
)
(
*
models
.
Group
,
error
)
DeleteGroup
(
name
string
)
error
DeleteDevopsProject
(
username
string
,
projectId
string
)
error
GetUserDevopsRole
(
username
string
,
projectId
string
)
(
string
,
error
)
CreateDevopsProject
(
username
string
,
project
*
models
.
DevopsProject
)
(
*
models
.
DevopsProject
,
error
)
CreateDevopsRoleBinding
(
projectId
string
,
user
string
,
role
string
)
ListDevopsProjects
(
username
string
)
([]
models
.
DevopsProject
,
error
)
}
type
client
struct
{
...
...
@@ -49,6 +55,7 @@ type client struct {
func
init
()
{
flag
.
StringVar
(
&
accountAPIServer
,
"ks-account-api-server"
,
"http://ks-account.kubesphere-system.svc"
,
"kubesphere account api server"
)
flag
.
StringVar
(
&
devopsAPIServer
,
"ks-devops-api-server"
,
"http://ks-devops.kubesphere-devops-system.svc"
,
"kubesphere devops api server"
)
}
func
Client
()
Interface
{
...
...
pkg/simple/client/openpitrix/applications.go
浏览文件 @
5c4efd53
...
...
@@ -273,11 +273,10 @@ func makeHttpRequest(method, url, data string) ([]byte, error) {
return
nil
,
err
}
httpClient
:=
&
http
.
Client
{}
resp
,
err
:=
httpClient
.
Do
(
req
)
resp
,
err
:=
http
.
DefaultClient
.
Do
(
req
)
if
err
!=
nil
{
err
:=
fmt
.
Errorf
(
"Request to %s failed, method: %s,
reason: %s "
,
url
,
method
,
err
)
err
:=
fmt
.
Errorf
(
"Request to %s failed, method: %s,
token: %s, reason: %s "
,
url
,
method
,
openpitrixProxyToken
,
err
)
glog
.
Error
(
err
)
return
nil
,
err
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录