Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
水淹萌龙
kubesphere
提交
7f780bd3
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看板
未验证
提交
7f780bd3
编写于
11月 16, 2018
作者:
Z
zryfish
提交者:
GitHub
11月 16, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #206 from wansir/master
refactor workspace api
上级
6156b6da
bce25036
变更
8
展开全部
隐藏空白更改
内联
并排
Showing
8 changed file
with
748 addition
and
515 deletion
+748
-515
pkg/apis/v1alpha/workspaces/workspaces.go
pkg/apis/v1alpha/workspaces/workspaces.go
+115
-22
pkg/models/controllers/clusterrole_bindings.go
pkg/models/controllers/clusterrole_bindings.go
+59
-0
pkg/models/controllers/namespaces.go
pkg/models/controllers/namespaces.go
+123
-69
pkg/models/iam/iam.go
pkg/models/iam/iam.go
+26
-75
pkg/models/iam/policy.go
pkg/models/iam/policy.go
+90
-74
pkg/models/iam/types.go
pkg/models/iam/types.go
+3
-5
pkg/models/metrics/namespaces.go
pkg/models/metrics/namespaces.go
+51
-0
pkg/models/workspaces/workspaces.go
pkg/models/workspaces/workspaces.go
+281
-270
未找到文件。
pkg/apis/v1alpha/workspaces/workspaces.go
浏览文件 @
7f780bd3
...
...
@@ -11,8 +11,13 @@ import (
"k8s.io/kubernetes/pkg/util/slice"
"strconv"
"regexp"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/models/metrics"
"kubesphere.io/kubesphere/pkg/models/workspaces"
)
...
...
@@ -26,9 +31,13 @@ func Register(ws *restful.WebService, subPath string) {
ws
.
Route
(
ws
.
GET
(
subPath
+
"/{name}"
)
.
To
(
WorkspaceDetailHandler
))
ws
.
Route
(
ws
.
PUT
(
subPath
+
"/{name}"
)
.
To
(
WorkspaceEditHandler
))
ws
.
Route
(
ws
.
GET
(
subPath
+
"/{workspace}/namespaces"
)
.
To
(
UserNamespaceListHandler
))
ws
.
Route
(
ws
.
GET
(
subPath
+
"/{workspace}/members/{username}/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}/namespaces/{namespace}"
)
.
To
(
NamespaceCheckHandler
))
ws
.
Route
(
ws
.
GET
(
"/namespaces/{namespace}"
)
.
To
(
NamespaceCheckHandler
))
ws
.
Route
(
ws
.
GET
(
subPath
+
"/{name}/devops"
)
.
To
(
DevOpsProjectHandler
))
ws
.
Route
(
ws
.
GET
(
subPath
+
"/{name}/members/{username}/devops"
)
.
To
(
DevOpsProjectHandler
))
ws
.
Route
(
ws
.
POST
(
subPath
+
"/{name}/devops"
)
.
To
(
DevOpsProjectCreateHandler
))
ws
.
Route
(
ws
.
DELETE
(
subPath
+
"/{name}/devops/{id}"
)
.
To
(
DevOpsProjectDeleteHandler
))
...
...
@@ -171,10 +180,22 @@ func MembersRemoveHandler(req *restful.Request, resp *restful.Response) {
resp
.
WriteHeaderAndEntity
(
http
.
StatusOK
,
constants
.
MessageResponse
{
Message
:
"success"
})
}
func
NamespaceCheckHandler
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
namespace
:=
req
.
PathParameter
(
"namespace"
)
exist
,
err
:=
workspaces
.
NamespaceExistCheck
(
namespace
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
constants
.
MessageResponse
{
Message
:
err
.
Error
()})
return
}
resp
.
WriteEntity
(
map
[
string
]
bool
{
"exist"
:
exist
})
}
func
NamespaceDeleteHandler
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
namespace
:=
req
.
PathParameter
(
"namespace"
)
workspace
:=
req
.
PathParameter
(
"name"
)
//force := req.QueryParameter("force")
err
:=
workspaces
.
DeleteNamespace
(
workspace
,
namespace
)
...
...
@@ -223,26 +244,14 @@ func DevOpsProjectCreateHandler(req *restful.Request, resp *restful.Response) {
return
}
project
,
err
:=
workspaces
.
CreateDevopsProject
(
username
,
devops
)
project
,
err
:=
workspaces
.
CreateDevopsProject
(
username
,
workspace
,
devops
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
constants
.
MessageResponse
{
Message
:
err
.
Error
()})
return
}
if
project
.
ProjectId
==
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
constants
.
MessageResponse
{
Message
:
"project create failed"
})
}
else
{
err
=
workspaces
.
BindingDevopsProject
(
workspace
,
*
project
.
ProjectId
)
if
err
!=
nil
{
workspaces
.
DeleteDevopsProject
(
username
,
*
project
.
ProjectId
)
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
constants
.
MessageResponse
{
Message
:
err
.
Error
()})
return
}
resp
.
WriteEntity
(
project
)
}
resp
.
WriteEntity
(
project
)
}
...
...
@@ -285,15 +294,53 @@ func NamespaceCreateHandler(req *restful.Request, resp *restful.Response) {
func
DevOpsProjectHandler
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
workspace
:=
req
.
PathParameter
(
"name"
)
username
:=
req
.
PathParameter
(
"username"
)
keyword
:=
req
.
QueryParameter
(
"keyword"
)
if
username
==
""
{
username
=
req
.
HeaderParameter
(
UserNameHeader
)
}
limit
:=
65535
offset
:=
0
orderBy
:=
"createTime"
reverse
:=
true
if
groups
:=
regexp
.
MustCompile
(
`^limit=(\d+),page=(\d+)$`
)
.
FindStringSubmatch
(
req
.
QueryParameter
(
"paging"
));
len
(
groups
)
==
3
{
limit
,
_
=
strconv
.
Atoi
(
groups
[
1
])
page
,
_
:=
strconv
.
Atoi
(
groups
[
2
])
if
page
<
0
{
page
=
1
}
offset
=
(
page
-
1
)
*
limit
}
if
groups
:=
regexp
.
MustCompile
(
`^(createTime|name)$`
)
.
FindStringSubmatch
(
req
.
QueryParameter
(
"order"
));
len
(
groups
)
==
2
{
orderBy
=
groups
[
1
]
reverse
=
false
}
if
q
:=
req
.
QueryParameter
(
"reverse"
);
q
!=
""
{
b
,
err
:=
strconv
.
ParseBool
(
q
)
if
err
==
nil
{
reverse
=
b
}
}
devOpsProjects
,
err
:=
workspaces
.
DevopsProjects
(
workspace
)
total
,
devOpsProjects
,
err
:=
workspaces
.
ListDevopsProjectsByUser
(
username
,
workspace
,
keyword
,
orderBy
,
reverse
,
limit
,
offset
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
constants
.
MessageResponse
{
Message
:
err
.
Error
()})
return
}
resp
.
WriteEntity
(
devOpsProjects
)
result
:=
constants
.
PageableResponse
{}
result
.
TotalCount
=
total
result
.
Items
=
make
([]
interface
{},
0
)
for
_
,
n
:=
range
devOpsProjects
{
result
.
Items
=
append
(
result
.
Items
,
n
)
}
resp
.
WriteEntity
(
result
)
}
func
WorkspaceCreateHandler
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
...
...
@@ -402,10 +449,10 @@ func WorkspaceDetailHandler(req *restful.Request, resp *restful.Response) {
// List all workspaces for the current user
func
UserWorkspaceListHandler
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
keyword
:=
req
.
QueryParameter
(
"keyword"
)
username
:=
req
.
HeaderParameter
(
UserNameHeader
)
list
,
err
:=
workspaces
.
List
ByUser
(
username
)
list
,
err
:=
workspaces
.
List
WorkspaceByUser
(
username
,
keyword
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
constants
.
MessageResponse
{
Message
:
err
.
Error
()})
...
...
@@ -416,16 +463,62 @@ func UserWorkspaceListHandler(req *restful.Request, resp *restful.Response) {
}
func
UserNamespaceListHandler
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
withMetrics
,
err
:=
strconv
.
ParseBool
(
req
.
QueryParameter
(
"metrics"
))
if
err
!=
nil
{
withMetrics
=
false
}
username
:=
req
.
PathParameter
(
"username"
)
keyword
:=
req
.
QueryParameter
(
"keyword"
)
if
username
==
""
{
username
=
req
.
HeaderParameter
(
UserNameHeader
)
}
limit
:=
65535
offset
:=
0
orderBy
:=
"createTime"
reverse
:=
true
if
groups
:=
regexp
.
MustCompile
(
`^limit=(\d+),page=(\d+)$`
)
.
FindStringSubmatch
(
req
.
QueryParameter
(
"paging"
));
len
(
groups
)
==
3
{
limit
,
_
=
strconv
.
Atoi
(
groups
[
1
])
page
,
_
:=
strconv
.
Atoi
(
groups
[
2
])
if
page
<
0
{
page
=
1
}
offset
=
(
page
-
1
)
*
limit
}
if
groups
:=
regexp
.
MustCompile
(
`^(createTime|name)$`
)
.
FindStringSubmatch
(
req
.
QueryParameter
(
"order"
));
len
(
groups
)
==
2
{
orderBy
=
groups
[
1
]
reverse
=
false
}
if
q
:=
req
.
QueryParameter
(
"reverse"
);
q
!=
""
{
b
,
err
:=
strconv
.
ParseBool
(
q
)
if
err
==
nil
{
reverse
=
b
}
}
username
:=
req
.
HeaderParameter
(
UserNameHeader
)
workspaceName
:=
req
.
PathParameter
(
"workspace"
)
namespaces
,
err
:=
workspaces
.
ListNamespaceByUser
(
workspaceName
,
username
)
total
,
namespaces
,
err
:=
workspaces
.
ListNamespaceByUser
(
workspaceName
,
username
,
keyword
,
orderBy
,
reverse
,
limit
,
offset
)
if
withMetrics
{
namespaces
=
metrics
.
GetNamespacesWithMetrics
(
namespaces
)
}
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
constants
.
MessageResponse
{
Message
:
err
.
Error
()})
return
}
resp
.
WriteEntity
(
namespaces
)
result
:=
constants
.
PageableResponse
{}
result
.
TotalCount
=
total
result
.
Items
=
make
([]
interface
{},
0
)
for
_
,
n
:=
range
namespaces
{
result
.
Items
=
append
(
result
.
Items
,
n
)
}
resp
.
WriteEntity
(
result
)
}
pkg/models/controllers/clusterrole_bindings.go
浏览文件 @
7f780bd3
...
...
@@ -19,10 +19,16 @@ package controllers
import
(
"time"
"fmt"
"regexp"
"github.com/golang/glog"
"github.com/pkg/errors"
rbac
"k8s.io/api/rbac/v1"
meta_v1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers"
"k8s.io/client-go/tools/cache"
)
func
(
ctl
*
ClusterRoleBindingCtl
)
Name
()
string
{
...
...
@@ -43,10 +49,63 @@ func (ctl *ClusterRoleBindingCtl) total() int {
return
len
(
list
)
}
func
(
ctl
*
ClusterRoleBindingCtl
)
handleWorkspaceRoleChange
(
clusterRole
*
rbac
.
ClusterRoleBinding
)
{
if
groups
:=
regexp
.
MustCompile
(
"^system:(
\\
w+):(admin|operator|viewer)$"
)
.
FindStringSubmatch
(
clusterRole
.
Name
);
len
(
groups
)
==
3
{
workspace
:=
groups
[
1
]
go
ctl
.
restNamespaceRoleBinding
(
workspace
)
}
}
func
(
ctl
*
ClusterRoleBindingCtl
)
restNamespaceRoleBinding
(
workspace
string
)
{
selector
:=
labels
.
SelectorFromSet
(
labels
.
Set
{
"kubesphere.io/workspace"
:
workspace
})
namespaces
,
err
:=
ctl
.
K8sClient
.
CoreV1
()
.
Namespaces
()
.
List
(
meta_v1
.
ListOptions
{
LabelSelector
:
selector
.
String
()})
if
err
!=
nil
{
glog
.
Warning
(
"workspace roles sync failed"
,
workspace
,
err
)
return
}
for
_
,
namespace
:=
range
namespaces
.
Items
{
pathJson
:=
fmt
.
Sprintf
(
`{"metadata":{"annotations":{"%s":"%s"}}}`
,
initTimeAnnotateKey
,
""
)
_
,
err
:=
ctl
.
K8sClient
.
CoreV1
()
.
Namespaces
()
.
Patch
(
namespace
.
Name
,
"application/strategic-merge-patch+json"
,
[]
byte
(
pathJson
))
if
err
!=
nil
{
glog
.
Warning
(
"workspace roles sync failed"
,
workspace
,
err
)
return
}
}
}
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
()
ctl
.
informer
.
AddEventHandler
(
cache
.
ResourceEventHandlerFuncs
{
AddFunc
:
func
(
obj
interface
{})
{
},
UpdateFunc
:
func
(
old
,
new
interface
{})
{
oldValue
:=
old
.
(
*
rbac
.
ClusterRoleBinding
)
newValue
:=
new
.
(
*
rbac
.
ClusterRoleBinding
)
if
!
subjectsCompile
(
oldValue
.
Subjects
,
newValue
.
Subjects
)
{
ctl
.
handleWorkspaceRoleChange
(
newValue
)
}
},
DeleteFunc
:
func
(
obj
interface
{})
{
},
})
}
func
subjectsCompile
(
s1
[]
rbac
.
Subject
,
s2
[]
rbac
.
Subject
)
bool
{
if
len
(
s1
)
!=
len
(
s2
)
{
return
false
}
for
i
,
v
:=
range
s1
{
if
v
.
Name
!=
s2
[
i
]
.
Name
||
v
.
Kind
!=
s2
[
i
]
.
Kind
{
return
false
}
}
return
true
}
func
(
ctl
*
ClusterRoleBindingCtl
)
CountWithConditions
(
conditions
string
)
int
{
...
...
pkg/models/controllers/namespaces.go
浏览文件 @
7f780bd3
...
...
@@ -46,17 +46,19 @@ import (
const
(
provider
=
"kubernetes"
admin
=
"admin"
editor
=
"
edi
tor"
editor
=
"
opera
tor"
viewer
=
"viewer"
kubectlNamespace
=
constants
.
KubeSphereControlNamespace
kubectlConfigKey
=
"config"
openPitrixRuntimeAnnotateKey
=
"openpitrix_runtime"
creatorAnnotateKey
=
"creator"
initTimeAnnotateKey
=
"kubesphere.io/init-time"
workspaceLabelKey
=
"kubesphere.io/workspace"
)
var
adminRules
=
[]
rbac
.
PolicyRule
{{
Verbs
:
[]
string
{
"*"
},
APIGroups
:
[]
string
{
"*"
},
Resources
:
[]
string
{
"*"
}}}
var
editorRules
=
[]
rbac
.
PolicyRule
{{
Verbs
:
[]
string
{
"*"
},
APIGroups
:
[]
string
{
""
,
"apps"
,
"extensions"
,
"batch"
},
Resources
:
[]
string
{
"*"
}}}
var
viewerRules
=
[]
rbac
.
PolicyRule
{{
Verbs
:
[]
string
{
"list"
,
"get"
,
"watch"
},
APIGroups
:
[]
string
{
""
,
"apps"
,
"extensions"
,
"batch"
},
Resources
:
[]
string
{
"*"
}}}
var
editorRules
=
[]
rbac
.
PolicyRule
{{
Verbs
:
[]
string
{
"*"
},
APIGroups
:
[]
string
{
""
,
"apps"
,
"extensions"
,
"batch"
,
"kubesphere.io"
,
"account.kubesphere.io"
},
Resources
:
[]
string
{
"*"
}}}
var
viewerRules
=
[]
rbac
.
PolicyRule
{{
Verbs
:
[]
string
{
"list"
,
"get"
,
"watch"
},
APIGroups
:
[]
string
{
""
,
"apps"
,
"extensions"
,
"batch"
,
"kubesphere.io"
,
"account.kubesphere.io"
},
Resources
:
[]
string
{
"*"
}}}
type
runTime
struct
{
RuntimeId
string
`json:"runtime_id"`
...
...
@@ -131,15 +133,84 @@ func (ctl *NamespaceCtl) createOpRuntime(namespace string) ([]byte, error) {
return
makeHttpRequest
(
"POST"
,
url
,
string
(
body
))
}
func
(
ctl
*
NamespaceCtl
)
createDefaultRoleBinding
(
n
s
,
user
string
)
error
{
func
(
ctl
*
NamespaceCtl
)
createDefaultRoleBinding
(
n
amespace
*
v1
.
Namespace
)
error
{
roleBinding
:=
&
rbac
.
RoleBinding
{
ObjectMeta
:
metaV1
.
ObjectMeta
{
Name
:
admin
,
Namespace
:
ns
},
Subjects
:
[]
rbac
.
Subject
{{
Name
:
user
,
Kind
:
rbac
.
UserKind
}},
RoleRef
:
rbac
.
RoleRef
{
Kind
:
"Role"
,
Name
:
admin
}}
workspace
:=
""
creator
:=
""
if
namespace
.
Annotations
!=
nil
{
creator
=
namespace
.
Annotations
[
creatorAnnotateKey
]
}
if
namespace
.
Labels
!=
nil
{
workspace
=
namespace
.
Labels
[
workspaceLabelKey
]
}
_
,
err
:=
ctl
.
K8sClient
.
RbacV1
()
.
RoleBindings
(
ns
)
.
Create
(
roleBinding
)
adminBinding
,
err
:=
ctl
.
K8sClient
.
RbacV1
()
.
RoleBindings
(
namespace
.
Name
)
.
Get
(
admin
,
metaV1
.
GetOptions
{}
)
if
err
!=
nil
&&
!
errors
.
IsAlreadyExists
(
err
)
{
glog
.
Error
(
err
)
if
err
!=
nil
{
if
errors
.
IsNotFound
(
err
)
{
adminBinding
=
new
(
rbac
.
RoleBinding
)
adminBinding
.
Name
=
admin
adminBinding
.
Namespace
=
namespace
.
Name
adminBinding
.
RoleRef
=
rbac
.
RoleRef
{
Kind
:
"Role"
,
Name
:
admin
}
}
else
{
return
err
}
}
adminBinding
.
Subjects
=
make
([]
rbac
.
Subject
,
0
)
if
creator
!=
""
{
adminBinding
.
Subjects
=
append
(
adminBinding
.
Subjects
,
rbac
.
Subject
{
Name
:
creator
,
Kind
:
rbac
.
UserKind
})
}
if
workspace
!=
""
{
workspaceAdmin
,
err
:=
ctl
.
K8sClient
.
RbacV1
()
.
ClusterRoleBindings
()
.
Get
(
fmt
.
Sprintf
(
"system:%s:admin"
,
workspace
),
metaV1
.
GetOptions
{})
if
err
!=
nil
{
return
err
}
adminBinding
.
Subjects
=
append
(
adminBinding
.
Subjects
,
workspaceAdmin
.
Subjects
...
)
}
if
adminBinding
.
ResourceVersion
==
""
{
_
,
err
=
ctl
.
K8sClient
.
RbacV1
()
.
RoleBindings
(
namespace
.
Name
)
.
Create
(
adminBinding
)
}
else
{
_
,
err
=
ctl
.
K8sClient
.
RbacV1
()
.
RoleBindings
(
namespace
.
Name
)
.
Update
(
adminBinding
)
}
if
err
!=
nil
{
return
err
}
viewerBinding
,
err
:=
ctl
.
K8sClient
.
RbacV1
()
.
RoleBindings
(
namespace
.
Name
)
.
Get
(
viewer
,
metaV1
.
GetOptions
{})
if
err
!=
nil
{
if
errors
.
IsNotFound
(
err
)
{
viewerBinding
=
new
(
rbac
.
RoleBinding
)
viewerBinding
.
Name
=
viewer
viewerBinding
.
Namespace
=
namespace
.
Name
viewerBinding
.
RoleRef
=
rbac
.
RoleRef
{
Kind
:
"Role"
,
Name
:
viewer
}
}
else
{
return
err
}
}
viewerBinding
.
Subjects
=
make
([]
rbac
.
Subject
,
0
)
if
workspace
!=
""
{
workspaceViewer
,
err
:=
ctl
.
K8sClient
.
RbacV1
()
.
ClusterRoleBindings
()
.
Get
(
fmt
.
Sprintf
(
"system:%s:viewer"
,
workspace
),
metaV1
.
GetOptions
{})
if
err
!=
nil
{
return
err
}
viewerBinding
.
Subjects
=
append
(
viewerBinding
.
Subjects
,
workspaceViewer
.
Subjects
...
)
}
if
viewerBinding
.
ResourceVersion
==
""
{
_
,
err
=
ctl
.
K8sClient
.
RbacV1
()
.
RoleBindings
(
namespace
.
Name
)
.
Create
(
viewerBinding
)
}
else
{
_
,
err
=
ctl
.
K8sClient
.
RbacV1
()
.
RoleBindings
(
namespace
.
Name
)
.
Update
(
viewerBinding
)
}
if
err
!=
nil
{
return
err
}
...
...
@@ -172,60 +243,44 @@ func (ctl *NamespaceCtl) createDefaultRole(ns string) error {
return
nil
}
func
(
ctl
*
NamespaceCtl
)
createRoleAndRuntime
(
item
v1
.
Namespace
)
{
var
creator
string
var
runtime
string
ns
:=
item
.
Name
if
item
.
Annotations
==
nil
{
creator
=
""
runtime
=
""
}
else
{
runtime
=
item
.
Annotations
[
openPitrixRuntimeAnnotateKey
]
creator
=
item
.
Annotations
[
creatorAnnotateKey
]
func
(
ctl
*
NamespaceCtl
)
createRoleAndRuntime
(
namespace
*
v1
.
Namespace
)
{
runtime
:=
""
initTime
:=
""
if
namespace
.
Annotations
!=
nil
{
runtime
=
namespace
.
Annotations
[
openPitrixRuntimeAnnotateKey
]
initTime
=
namespace
.
Annotations
[
initTimeAnnotateKey
]
}
componentsNamespaces
:=
[]
string
{
constants
.
KubeSystemNamespace
,
constants
.
OpenPitrixNamespace
,
constants
.
IstioNamespace
,
constants
.
KubeSphereNamespace
}
if
len
(
runtime
)
==
0
&&
!
slice
.
ContainsString
(
componentsNamespaces
,
ns
,
nil
)
{
glog
.
Infoln
(
"create runtime:"
,
ns
)
var
runtimeCreateError
error
resp
,
runtimeCreateError
:=
ctl
.
createOpRuntime
(
ns
)
if
runtimeCreateError
==
nil
{
var
runtime
runTime
runtimeCreateError
=
json
.
Unmarshal
(
resp
,
&
runtime
)
if
runtimeCreateError
==
nil
{
if
item
.
Annotations
==
nil
{
item
.
Annotations
=
make
(
map
[
string
]
string
,
0
)
}
item
.
Annotations
[
openPitrixRuntimeAnnotateKey
]
=
runtime
.
RuntimeId
_
,
runtimeCreateError
=
ctl
.
K8sClient
.
CoreV1
()
.
Namespaces
()
.
Update
(
&
item
)
}
}
if
runtime
==
""
&&
!
slice
.
ContainsString
(
componentsNamespaces
,
namespace
.
Name
,
nil
)
{
glog
.
Infoln
(
"create runtime:"
,
namespace
.
Name
)
_
,
runtimeCreateError
:=
ctl
.
createOpRuntime
(
namespace
.
Name
)
if
runtimeCreateError
!=
nil
{
glog
.
Error
(
"runtime create error:"
,
runtimeCreateError
)
}
}
if
len
(
creator
)
>
0
{
roleCreateError
:=
ctl
.
createDefaultRole
(
ns
)
glog
.
Infoln
(
"create default role:"
,
ns
)
if
roleCreateError
==
nil
{
roleBindingError
:=
ctl
.
createDefaultRoleBinding
(
ns
,
creator
)
glog
.
Infoln
(
"create default role binding:"
,
ns
)
if
roleBindingError
!=
nil
{
glog
.
Error
(
"default role binding create error:"
,
roleBindingError
)
}
}
else
{
glog
.
Error
(
"default role create error:"
,
roleCreateError
)
if
initTime
==
""
{
err
:=
ctl
.
createDefaultRole
(
namespace
.
Name
)
glog
.
Infoln
(
"create default role:"
,
namespace
.
Name
)
if
err
==
nil
{
err
=
ctl
.
createDefaultRoleBinding
(
namespace
)
glog
.
Infoln
(
"create default role binding:"
,
namespace
.
Name
)
if
err
!=
nil
{
glog
.
Error
(
"default role binding create error:"
,
err
)
}
}
else
{
glog
.
Error
(
"default role create error:"
,
err
)
}
if
err
==
nil
{
pathJson
:=
fmt
.
Sprintf
(
`{"metadata":{"annotations":{"%s":"%s"}}}`
,
initTimeAnnotateKey
,
time
.
Now
()
.
UTC
()
.
Format
(
"2006-01-02T15:04:05Z"
))
_
,
err
=
ctl
.
K8sClient
.
CoreV1
()
.
Namespaces
()
.
Patch
(
namespace
.
Name
,
"application/strategic-merge-patch+json"
,
[]
byte
(
pathJson
))
if
err
!=
nil
{
glog
.
Error
(
"annotations patch error init failed:"
,
namespace
.
Name
,
err
)
}
}
}
}
...
...
@@ -293,7 +348,7 @@ func (ctl *NamespaceCtl) createCephSecretAfterNewNs(item v1.Namespace) {
}
}
func
(
ctl
*
NamespaceCtl
)
generateObject
(
item
v1
.
Namespace
)
*
Namespace
{
func
(
ctl
*
NamespaceCtl
)
generateObject
(
item
*
v1
.
Namespace
)
*
Namespace
{
var
displayName
string
if
item
.
Annotations
!=
nil
&&
len
(
item
.
Annotations
[
DisplayName
])
>
0
{
...
...
@@ -333,17 +388,17 @@ func (ctl *NamespaceCtl) sync(stopChan chan struct{}) {
db
=
db
.
CreateTable
(
&
Namespace
{})
ctl
.
initListerAndInformer
()
list
,
err
:=
ctl
.
lister
.
List
(
labels
.
Everything
())
if
err
!=
nil
{
glog
.
Error
(
err
)
return
}
for
_
,
item
:=
range
list
{
obj
:=
ctl
.
generateObject
(
*
item
)
db
.
Create
(
obj
)
ctl
.
createRoleAndRuntime
(
*
item
)
}
//
list, err := ctl.lister.List(labels.Everything())
//
if err != nil {
//
glog.Error(err)
//
return
//
}
//
for _, item := range list {
// obj := ctl.generateObject(
item)
//
db.Create(obj)
// ctl.createRoleAndRuntime(
item)
//
}
ctl
.
informer
.
Run
(
stopChan
)
}
...
...
@@ -369,16 +424,16 @@ func (ctl *NamespaceCtl) initListerAndInformer() {
AddFunc
:
func
(
obj
interface
{})
{
object
:=
obj
.
(
*
v1
.
Namespace
)
mysqlObject
:=
ctl
.
generateObject
(
*
object
)
mysqlObject
:=
ctl
.
generateObject
(
object
)
db
.
Create
(
mysqlObject
)
ctl
.
createRoleAndRuntime
(
*
object
)
ctl
.
createRoleAndRuntime
(
object
)
ctl
.
createCephSecretAfterNewNs
(
*
object
)
},
UpdateFunc
:
func
(
old
,
new
interface
{})
{
object
:=
new
.
(
*
v1
.
Namespace
)
mysqlObject
:=
ctl
.
generateObject
(
*
object
)
mysqlObject
:=
ctl
.
generateObject
(
object
)
db
.
Save
(
mysqlObject
)
ctl
.
createRoleAndRuntime
(
*
object
)
ctl
.
createRoleAndRuntime
(
object
)
},
DeleteFunc
:
func
(
obj
interface
{})
{
var
item
Namespace
...
...
@@ -386,7 +441,6 @@ func (ctl *NamespaceCtl) initListerAndInformer() {
db
.
Where
(
"name=?"
,
object
.
Name
)
.
Find
(
&
item
)
db
.
Delete
(
item
)
ctl
.
deleteOpRuntime
(
*
object
)
},
})
...
...
pkg/models/iam/iam.go
浏览文件 @
7f780bd3
...
...
@@ -14,6 +14,8 @@ import (
"k8s.io/apimachinery/pkg/labels"
v12
"k8s.io/client-go/listers/rbac/v1"
"k8s.io/kubernetes/pkg/util/slice"
"kubesphere.io/kubesphere/pkg/client"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/controllers"
...
...
@@ -67,6 +69,7 @@ func GetUsers(names []string) ([]User, error) {
return
nil
,
err
}
defer
result
.
Body
.
Close
()
data
,
err
:=
ioutil
.
ReadAll
(
result
.
Body
)
if
err
!=
nil
{
...
...
@@ -94,6 +97,7 @@ func GetUser(name string) (*User, error) {
return
nil
,
err
}
defer
result
.
Body
.
Close
()
data
,
err
:=
ioutil
.
ReadAll
(
result
.
Body
)
if
err
!=
nil
{
...
...
@@ -228,7 +232,8 @@ func DeleteRoleBindings(username string) error {
length2
:=
len
(
roleBinding
.
Subjects
)
if
length2
==
0
{
k8s
.
RbacV1
()
.
RoleBindings
(
roleBinding
.
Namespace
)
.
Delete
(
roleBinding
.
Name
,
&
meta_v1
.
DeleteOptions
{})
deletePolicy
:=
meta_v1
.
DeletePropagationForeground
k8s
.
RbacV1
()
.
RoleBindings
(
roleBinding
.
Namespace
)
.
Delete
(
roleBinding
.
Name
,
&
meta_v1
.
DeleteOptions
{
PropagationPolicy
:
&
deletePolicy
})
}
else
if
length2
<
length1
{
k8s
.
RbacV1
()
.
RoleBindings
(
roleBinding
.
Namespace
)
.
Update
(
&
roleBinding
)
}
...
...
@@ -248,7 +253,8 @@ func DeleteRoleBindings(username string) error {
length2
:=
len
(
roleBinding
.
Subjects
)
if
length2
==
0
{
k8s
.
RbacV1
()
.
ClusterRoleBindings
()
.
Delete
(
roleBinding
.
Name
,
&
meta_v1
.
DeleteOptions
{})
deletePolicy
:=
meta_v1
.
DeletePropagationForeground
k8s
.
RbacV1
()
.
ClusterRoleBindings
()
.
Delete
(
roleBinding
.
Name
,
&
meta_v1
.
DeleteOptions
{
PropagationPolicy
:
&
deletePolicy
})
}
else
if
length2
<
length1
{
k8s
.
RbacV1
()
.
ClusterRoleBindings
()
.
Update
(
&
roleBinding
)
}
...
...
@@ -265,6 +271,21 @@ func GetRole(namespace string, name string) (*v1.Role, error) {
}
return
role
,
nil
}
func
GetWorkspaceUsers
(
workspace
string
,
role
string
)
[]
string
{
users
:=
make
([]
string
,
0
)
clusterRoleBindingLister
:=
controllers
.
ResourceControllers
.
Controllers
[
controllers
.
ClusterRoleBindings
]
.
Lister
()
.
(
v12
.
ClusterRoleBindingLister
)
clusterRoleBinding
,
err
:=
clusterRoleBindingLister
.
Get
(
fmt
.
Sprintf
(
"system:%s:%s"
,
workspace
,
role
))
if
err
!=
nil
{
return
users
}
for
_
,
s
:=
range
clusterRoleBinding
.
Subjects
{
if
s
.
Kind
==
v1
.
UserKind
&&
!
slice
.
ContainsString
(
users
,
s
.
Name
,
nil
)
{
users
=
append
(
users
,
s
.
Name
)
}
}
return
users
}
func
GetClusterRoleBindings
(
name
string
)
([]
v1
.
ClusterRoleBinding
,
error
)
{
k8s
:=
client
.
NewK8sClient
()
...
...
@@ -370,7 +391,6 @@ func GetRoles(namespace string, username string) ([]v1.Role, error) {
// Get cluster roles by username
func
GetClusterRoles
(
username
string
)
([]
v1
.
ClusterRole
,
error
)
{
//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
())
...
...
@@ -382,7 +402,7 @@ func GetClusterRoles(username string) ([]v1.ClusterRole, error) {
roles
:=
make
([]
v1
.
ClusterRole
,
0
)
for
_
,
roleBinding
:=
range
clusterRoleBindings
{
for
_
,
subject
:=
range
roleBinding
.
Subjects
{
for
i
,
subject
:=
range
roleBinding
.
Subjects
{
if
subject
.
Kind
==
v1
.
UserKind
&&
subject
.
Name
==
username
{
if
roleBinding
.
RoleRef
.
Kind
==
ClusterRoleKind
{
role
,
err
:=
clusterRoleLister
.
Get
(
roleBinding
.
RoleRef
.
Name
)
...
...
@@ -398,7 +418,8 @@ func GetClusterRoles(username string) ([]v1.ClusterRole, error) {
roles
=
append
(
roles
,
*
role
)
break
}
else
if
apierrors
.
IsNotFound
(
err
)
{
glog
.
Warning
(
err
)
roleBinding
.
Subjects
=
append
(
roleBinding
.
Subjects
[
:
i
],
roleBinding
.
Subjects
[
i
+
1
:
]
...
)
client
.
NewK8sClient
()
.
RbacV1
()
.
ClusterRoleBindings
()
.
Update
(
roleBinding
)
break
}
else
{
return
nil
,
err
...
...
@@ -411,76 +432,6 @@ func GetClusterRoles(username string) ([]v1.ClusterRole, error) {
return
roles
,
nil
}
//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
//}
//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
)
...
...
pkg/models/iam/policy.go
浏览文件 @
7f780bd3
...
...
@@ -60,9 +60,22 @@ var (
{
Name
:
"edit"
,
Rules
:
[]
v1
.
PolicyRule
{
{
Verbs
:
[]
string
{
"
update"
,
"patch
"
},
Verbs
:
[]
string
{
"
*
"
},
APIGroups
:
[]
string
{
"kubesphere.io"
},
Resources
:
[]
string
{
"workspaces"
},
},
{
Verbs
:
[]
string
{
"*"
},
APIGroups
:
[]
string
{
"kubesphere.io"
},
Resources
:
[]
string
{
"workspaces/*"
},
},
{
Verbs
:
[]
string
{
"*"
},
APIGroups
:
[]
string
{
"jenkins.kubesphere.io"
},
Resources
:
[]
string
{
"*"
},
},
{
Verbs
:
[]
string
{
"*"
},
APIGroups
:
[]
string
{
"devops.kubesphere.io"
},
Resources
:
[]
string
{
"*"
},
},
},
},
...
...
@@ -83,7 +96,34 @@ var (
{
Name
:
"view"
,
Rules
:
[]
v1
.
PolicyRule
{
{
Verbs
:
[]
string
{
"list"
},
Verbs
:
[]
string
{
"get"
},
APIGroups
:
[]
string
{
"kubesphere.io"
},
Resources
:
[]
string
{
"workspaces/members"
},
},
},
},
{
Name
:
"create"
,
Rules
:
[]
v1
.
PolicyRule
{
{
Verbs
:
[]
string
{
"create"
},
APIGroups
:
[]
string
{
"kubesphere.io"
},
Resources
:
[]
string
{
"workspaces/members"
},
},
},
},
{
Name
:
"edit"
,
Rules
:
[]
v1
.
PolicyRule
{
{
Verbs
:
[]
string
{
"patch"
,
"update"
},
APIGroups
:
[]
string
{
"kubesphere.io"
},
Resources
:
[]
string
{
"workspaces/members"
},
},
},
},
{
Name
:
"delete"
,
Rules
:
[]
v1
.
PolicyRule
{
{
Verbs
:
[]
string
{
"delete"
},
APIGroups
:
[]
string
{
"kubesphere.io"
},
Resources
:
[]
string
{
"workspaces/members"
},
},
...
...
@@ -97,7 +137,7 @@ var (
{
Name
:
"view"
,
Rules
:
[]
v1
.
PolicyRule
{
{
Verbs
:
[]
string
{
"
lis
t"
},
Verbs
:
[]
string
{
"
ge
t"
},
APIGroups
:
[]
string
{
"kubesphere.io"
},
Resources
:
[]
string
{
"workspaces/devops"
},
},
...
...
@@ -124,7 +164,7 @@ var (
{
Name
:
"delete"
,
Rules
:
[]
v1
.
PolicyRule
{
{
Verbs
:
[]
string
{
"delete"
,
"deletecollection"
},
Verbs
:
[]
string
{
"delete"
},
APIGroups
:
[]
string
{
"kubesphere.io"
},
Resources
:
[]
string
{
"workspaces/devops"
},
},
...
...
@@ -138,7 +178,7 @@ var (
{
Name
:
"view"
,
Rules
:
[]
v1
.
PolicyRule
{
{
Verbs
:
[]
string
{
"
lis
t"
},
Verbs
:
[]
string
{
"
ge
t"
},
APIGroups
:
[]
string
{
"kubesphere.io"
},
Resources
:
[]
string
{
"workspaces/namespaces"
},
},
...
...
@@ -165,7 +205,7 @@ var (
{
Name
:
"delete"
,
Rules
:
[]
v1
.
PolicyRule
{
{
Verbs
:
[]
string
{
"delete"
,
"deletecollection"
},
Verbs
:
[]
string
{
"delete"
},
APIGroups
:
[]
string
{
"kubesphere.io"
},
Resources
:
[]
string
{
"workspaces/namespaces"
},
},
...
...
@@ -173,31 +213,57 @@ var (
},
},
},
{
Name
:
"registries"
,
Actions
:
[]
Action
{
{
Name
:
"view"
},
{
Name
:
"create"
},
{
Name
:
"edit"
},
{
Name
:
"delete"
},
},
},
{
Name
:
"organizations"
,
Actions
:
[]
Action
{
{
Name
:
"view"
},
{
Name
:
"create"
},
{
Name
:
"edit"
},
{
Name
:
"delete"
},
},
{
Name
:
"view"
,
Rules
:
[]
v1
.
PolicyRule
{
{
Verbs
:
[]
string
{
"get"
},
APIGroups
:
[]
string
{
"account.kubesphere.io"
},
Resources
:
[]
string
{
"workspaces/organizations"
},
},
},
},
{
Name
:
"create"
,
Rules
:
[]
v1
.
PolicyRule
{
{
Verbs
:
[]
string
{
"create"
},
APIGroups
:
[]
string
{
"account.kubesphere.io"
},
Resources
:
[]
string
{
"workspaces/organizations"
},
},
},
},
{
Name
:
"edit"
,
Rules
:
[]
v1
.
PolicyRule
{
{
Verbs
:
[]
string
{
"update"
,
"patch"
},
APIGroups
:
[]
string
{
"account.kubesphere.io"
},
Resources
:
[]
string
{
"workspaces/organizations"
},
},
},
},
{
Name
:
"delete"
,
Rules
:
[]
v1
.
PolicyRule
{
{
Verbs
:
[]
string
{
"delete"
},
APIGroups
:
[]
string
{
"account.kubesphere.io"
},
Resources
:
[]
string
{
"workspaces/organizations"
},
},
},
}},
},
{
Name
:
"roles"
,
Actions
:
[]
Action
{
{
Name
:
"view"
},
{
Name
:
"create"
},
{
Name
:
"edit"
},
{
Name
:
"delete"
},
{
Name
:
"view"
,
Rules
:
[]
v1
.
PolicyRule
{
{
Verbs
:
[]
string
{
"get"
},
APIGroups
:
[]
string
{
"kubesphere.io"
},
Resources
:
[]
string
{
"workspaces/roles"
},
},
}},
},
},
}
...
...
@@ -242,56 +308,6 @@ var (
},
},
},
//{
// Name: "projects",
// Actions: []Action{
// {Name: "view",
// Rules: []v1.PolicyRule{
// {
// Verbs: []string{"get", "watch", "list"},
// APIGroups: []string{""},
// Resources: []string{"namespaces"},
// },
// },
// },
// {Name: "create",
// Rules: []v1.PolicyRule{
// {
// Verbs: []string{"create"},
// APIGroups: []string{""},
// Resources: []string{"namespaces"},
// },
// },
// },
// {Name: "edit",
// Rules: []v1.PolicyRule{
// {
// Verbs: []string{"update", "patch"},
// APIGroups: []string{""},
// Resources: []string{"namespaces"},
// },
// },
// },
// {Name: "delete",
// Rules: []v1.PolicyRule{
// {
// Verbs: []string{"delete", "deletecollection"},
// APIGroups: []string{""},
// Resources: []string{"namespaces"},
// },
// },
// },
// {Name: "members",
// Rules: []v1.PolicyRule{
// {
// Verbs: []string{"get", "watch", "list", "create", "delete", "patch", "update"},
// APIGroups: []string{"rbac.authorization.k8s.io"},
// Resources: []string{"rolebindings", "roles"},
// },
// },
// },
// },
//},
{
Name
:
"accounts"
,
Actions
:
[]
Action
{
...
...
pkg/models/iam/types.go
浏览文件 @
7f780bd3
...
...
@@ -20,11 +20,9 @@ type SimpleRule struct {
}
type
User
struct
{
Username
string
`json:"username"`
//UID string `json:"uid"`
Groups
[]
string
`json:"groups"`
Password
string
`json:"password,omitempty"`
//Extra map[string]interface{} `json:"extra"`
Username
string
`json:"username"`
Groups
[]
string
`json:"groups"`
Password
string
`json:"password,omitempty"`
AvatarUrl
string
`json:"avatar_url"`
Description
string
`json:"description"`
Email
string
`json:"email"`
...
...
pkg/models/metrics/namespaces.go
0 → 100644
浏览文件 @
7f780bd3
package
metrics
import
(
"net/url"
"strings"
"k8s.io/api/core/v1"
"kubesphere.io/kubesphere/pkg/client"
)
func
GetNamespacesWithMetrics
(
namespaces
[]
*
v1
.
Namespace
)
[]
*
v1
.
Namespace
{
var
nsNameList
[]
string
for
i
:=
range
namespaces
{
nsNameList
=
append
(
nsNameList
,
namespaces
[
i
]
.
Name
)
}
nsFilter
:=
"^("
+
strings
.
Join
(
nsNameList
,
"|"
)
+
")$"
var
timeRelateParams
=
make
(
url
.
Values
)
params
:=
client
.
MonitoringRequestParams
{
NsFilter
:
nsFilter
,
Params
:
timeRelateParams
,
QueryType
:
client
.
DefaultQueryType
,
MetricsFilter
:
"namespace_cpu_usage|namespace_memory_usage_wo_cache|namespace_pod_count"
,
}
rawMetrics
:=
MonitorAllMetrics
(
&
params
,
MetricLevelNamespace
)
for
_
,
result
:=
range
rawMetrics
.
Results
{
for
_
,
data
:=
range
result
.
Data
.
Result
{
metricDescMap
,
ok
:=
data
[
"metric"
]
.
(
map
[
string
]
interface
{})
if
ok
{
if
ns
,
exist
:=
metricDescMap
[
"namespace"
];
exist
{
timeAndValue
,
ok
:=
data
[
"value"
]
.
([]
interface
{})
if
ok
&&
len
(
timeAndValue
)
==
2
{
for
i
:=
0
;
i
<
len
(
namespaces
);
i
++
{
if
namespaces
[
i
]
.
Name
==
ns
{
if
namespaces
[
i
]
.
Annotations
==
nil
{
namespaces
[
i
]
.
Annotations
=
make
(
map
[
string
]
string
,
0
)
}
namespaces
[
i
]
.
Annotations
[
result
.
MetricName
]
=
timeAndValue
[
1
]
.
(
string
)
}
}
}
}
}
}
}
return
namespaces
}
pkg/models/workspaces/workspaces.go
浏览文件 @
7f780bd3
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录