Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
水淹萌龙
kubesphere
提交
0664eeb5
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看板
未验证
提交
0664eeb5
编写于
2月 25, 2020
作者:
H
hongming
提交者:
GitHub
2月 25, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
code refactor (#1922)
Signed-off-by:
N
hongming
<
talonwan@yunify.com
>
上级
abf9fee8
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
87 addition
and
766 deletion
+87
-766
pkg/apiserver/openpitrix/attachments.go
pkg/apiserver/openpitrix/attachments.go
+0
-54
pkg/apiserver/resources/user.go
pkg/apiserver/resources/user.go
+0
-65
pkg/apiserver/tenant/tenant.go
pkg/apiserver/tenant/tenant.go
+0
-327
pkg/kapis/devops/v1alpha2/register.go
pkg/kapis/devops/v1alpha2/register.go
+2
-5
pkg/kapis/resources/v1alpha2/handler.go
pkg/kapis/resources/v1alpha2/handler.go
+38
-2
pkg/kapis/resources/v1alpha2/register.go
pkg/kapis/resources/v1alpha2/register.go
+3
-4
pkg/models/iam/am.go
pkg/models/iam/am.go
+7
-7
pkg/models/kubeconfig/kubeconfig.go
pkg/models/kubeconfig/kubeconfig.go
+7
-288
pkg/models/kubectl/kubectl.go
pkg/models/kubectl/kubectl.go
+30
-14
未找到文件。
pkg/apiserver/openpitrix/attachments.go
已删除
100644 → 0
浏览文件 @
abf9fee8
/*
*
* 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
openpitrix
import
(
"github.com/emicklei/go-restful"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"kubesphere.io/kubesphere/pkg/models/openpitrix/attachment"
"kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/simple/client"
"net/http"
)
func
DescribeAttachment
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
attachmentId
:=
req
.
PathParameter
(
"attachment"
)
fileName
:=
req
.
QueryParameter
(
"filename"
)
result
,
err
:=
attachment
.
DescribeAttachment
(
attachmentId
)
// file raw
if
fileName
!=
""
{
data
:=
result
.
AttachmentContent
[
fileName
]
resp
.
Write
(
data
)
resp
.
Header
()
.
Set
(
"Content-Type"
,
"text/plain"
)
return
}
if
_
,
notEnabled
:=
err
.
(
client
.
ClientSetNotEnabledError
);
notEnabled
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusNotImplemented
,
errors
.
Wrap
(
err
))
return
}
if
status
.
Code
(
err
)
==
codes
.
NotFound
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusNotFound
,
errors
.
Wrap
(
err
))
return
}
resp
.
WriteEntity
(
result
)
}
pkg/apiserver/resources/user.go
已删除
100644 → 0
浏览文件 @
abf9fee8
/*
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
resources
import
(
"github.com/emicklei/go-restful"
k8serr
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/klog"
"net/http"
"kubesphere.io/kubesphere/pkg/models/kubeconfig"
"kubesphere.io/kubesphere/pkg/models/kubectl"
"kubesphere.io/kubesphere/pkg/server/errors"
)
func
GetKubectl
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
user
:=
req
.
PathParameter
(
"user"
)
kubectlPod
,
err
:=
kubectl
.
GetKubectlPod
(
user
)
if
err
!=
nil
{
klog
.
Error
(
err
)
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
return
}
resp
.
WriteAsJson
(
kubectlPod
)
}
func
GetKubeconfig
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
user
:=
req
.
PathParameter
(
"user"
)
kubectlConfig
,
err
:=
kubeconfig
.
GetKubeConfig
(
user
)
if
err
!=
nil
{
klog
.
Error
(
err
)
if
k8serr
.
IsNotFound
(
err
)
{
// recreate
kubeconfig
.
CreateKubeConfig
(
user
)
resp
.
WriteHeaderAndJson
(
http
.
StatusNotFound
,
errors
.
Wrap
(
err
),
restful
.
MIME_JSON
)
}
else
{
resp
.
WriteHeaderAndJson
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
),
restful
.
MIME_JSON
)
}
return
}
resp
.
Write
([]
byte
(
kubectlConfig
))
}
pkg/apiserver/tenant/tenant.go
已删除
100644 → 0
浏览文件 @
abf9fee8
/*
Copyright 2019 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
tenant
import
(
"github.com/emicklei/go-restful"
"k8s.io/api/core/v1"
rbacv1
"k8s.io/api/rbac/v1"
k8serr
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/util/net"
"k8s.io/klog"
devopsv1alpha2
"kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
loggingv1alpha2
"kubesphere.io/kubesphere/pkg/api/logging/v1alpha2"
"kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
"kubesphere.io/kubesphere/pkg/apiserver/logging"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/models/metrics"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/models/tenant"
"kubesphere.io/kubesphere/pkg/models/workspaces"
"kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"net/http"
"strings"
)
func
ListWorkspaceRules
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
workspace
:=
req
.
PathParameter
(
"workspace"
)
username
:=
req
.
HeaderParameter
(
constants
.
UserNameHeader
)
rules
,
err
:=
iam
.
GetUserWorkspaceSimpleRules
(
workspace
,
username
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
return
}
resp
.
WriteAsJson
(
rules
)
}
func
ListWorkspaces
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
username
:=
req
.
HeaderParameter
(
constants
.
UserNameHeader
)
conditions
,
err
:=
params
.
ParseConditions
(
req
.
QueryParameter
(
params
.
ConditionsParam
))
orderBy
:=
req
.
QueryParameter
(
params
.
OrderByParam
)
limit
,
offset
:=
params
.
ParsePaging
(
req
.
QueryParameter
(
params
.
PagingParam
))
reverse
:=
params
.
ParseReverse
(
req
)
if
orderBy
==
""
{
orderBy
=
v1alpha2
.
CreateTime
reverse
=
true
}
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusBadRequest
,
errors
.
Wrap
(
err
))
return
}
result
,
err
:=
tenant
.
ListWorkspaces
(
username
,
conditions
,
orderBy
,
reverse
,
limit
,
offset
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
return
}
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
{
klog
.
Errorf
(
"describe workspace failed: %+v"
,
err
)
if
k8serr
.
IsNotFound
(
err
)
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusNotFound
,
errors
.
Wrap
(
err
))
}
else
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
}
return
}
resp
.
WriteAsJson
(
result
)
}
func
ListNamespacesByUsername
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
ListNamespaces
(
req
,
resp
)
}
func
ListNamespaces
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
workspace
:=
req
.
PathParameter
(
"workspace"
)
username
:=
req
.
PathParameter
(
"member"
)
// /workspaces/{workspace}/members/{username}/namespaces
if
username
==
""
{
// /workspaces/{workspace}/namespaces
username
=
req
.
HeaderParameter
(
constants
.
UserNameHeader
)
}
conditions
,
err
:=
params
.
ParseConditions
(
req
.
QueryParameter
(
params
.
ConditionsParam
))
orderBy
:=
req
.
QueryParameter
(
params
.
OrderByParam
)
limit
,
offset
:=
params
.
ParsePaging
(
req
.
QueryParameter
(
params
.
PagingParam
))
reverse
:=
params
.
ParseReverse
(
req
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusBadRequest
,
errors
.
Wrap
(
err
))
return
}
conditions
.
Match
[
constants
.
WorkspaceLabelKey
]
=
workspace
result
,
err
:=
tenant
.
ListNamespaces
(
username
,
conditions
,
orderBy
,
reverse
,
limit
,
offset
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
return
}
namespaces
:=
make
([]
*
v1
.
Namespace
,
0
)
for
_
,
item
:=
range
result
.
Items
{
namespaces
=
append
(
namespaces
,
item
.
(
*
v1
.
Namespace
)
.
DeepCopy
())
}
namespaces
=
metrics
.
GetNamespacesWithMetrics
(
namespaces
)
items
:=
make
([]
interface
{},
0
)
for
_
,
item
:=
range
namespaces
{
items
=
append
(
items
,
item
)
}
result
.
Items
=
items
resp
.
WriteAsJson
(
result
)
}
func
CreateNamespace
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
workspaceName
:=
req
.
PathParameter
(
"workspace"
)
username
:=
req
.
HeaderParameter
(
constants
.
UserNameHeader
)
var
namespace
v1
.
Namespace
err
:=
req
.
ReadEntity
(
&
namespace
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusBadRequest
,
errors
.
Wrap
(
err
))
return
}
workspace
,
err
:=
tenant
.
GetWorkspace
(
workspaceName
)
err
=
checkResourceQuotas
(
workspace
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusForbidden
,
errors
.
Wrap
(
err
))
return
}
if
err
!=
nil
{
if
k8serr
.
IsNotFound
(
err
)
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusForbidden
,
errors
.
Wrap
(
err
))
}
else
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
}
return
}
created
,
err
:=
tenant
.
CreateNamespace
(
workspaceName
,
&
namespace
,
username
)
if
err
!=
nil
{
if
k8serr
.
IsAlreadyExists
(
err
)
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusConflict
,
err
)
}
else
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
err
)
}
return
}
resp
.
WriteAsJson
(
created
)
}
func
DeleteNamespace
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
workspaceName
:=
req
.
PathParameter
(
"workspace"
)
namespaceName
:=
req
.
PathParameter
(
"namespace"
)
err
:=
workspaces
.
DeleteNamespace
(
workspaceName
,
namespaceName
)
if
err
!=
nil
{
resp
.
WriteHeaderAndEntity
(
http
.
StatusBadRequest
,
errors
.
Wrap
(
err
))
return
}
resp
.
WriteAsJson
(
errors
.
None
)
}
func
checkResourceQuotas
(
wokrspace
*
v1alpha1
.
Workspace
)
error
{
return
nil
}
func
ListNamespaceRules
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
namespace
:=
req
.
PathParameter
(
"namespace"
)
username
:=
req
.
HeaderParameter
(
constants
.
UserNameHeader
)
rules
,
err
:=
iam
.
GetUserNamespaceSimpleRules
(
namespace
,
username
)
if
err
!=
nil
{
resp
.
WriteError
(
http
.
StatusInternalServerError
,
err
)
return
}
resp
.
WriteAsJson
(
rules
)
}
func
LogQuery
(
req
*
restful
.
Request
,
resp
*
restful
.
Response
)
{
operation
:=
req
.
QueryParameter
(
"operation"
)
req
,
err
:=
regenerateLoggingRequest
(
req
)
switch
{
case
err
!=
nil
:
resp
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
case
req
!=
nil
:
logging
.
LoggingQueryCluster
(
req
,
resp
)
default
:
if
operation
==
"export"
{
resp
.
Header
()
.
Set
(
restful
.
HEADER_ContentType
,
"text/plain"
)
resp
.
Header
()
.
Set
(
"Content-Disposition"
,
"attachment"
)
resp
.
Write
(
nil
)
}
else
{
resp
.
WriteAsJson
(
loggingv1alpha2
.
QueryResult
{
Read
:
new
(
loggingv1alpha2
.
ReadResult
)})
}
}
}
// override namespace query conditions
func
regenerateLoggingRequest
(
req
*
restful
.
Request
)
(
*
restful
.
Request
,
error
)
{
username
:=
req
.
HeaderParameter
(
constants
.
UserNameHeader
)
// regenerate the request for log query
newUrl
:=
net
.
FormatURL
(
"http"
,
"127.0.0.1"
,
80
,
"/kapis/logging.kubesphere.io/v1alpha2/cluster"
)
values
:=
req
.
Request
.
URL
.
Query
()
clusterRules
,
err
:=
iam
.
GetUserClusterRules
(
username
)
if
err
!=
nil
{
klog
.
Errorln
(
err
)
return
nil
,
err
}
hasClusterLogAccess
:=
iam
.
RulesMatchesRequired
(
clusterRules
,
rbacv1
.
PolicyRule
{
Verbs
:
[]
string
{
"get"
},
Resources
:
[]
string
{
"*"
},
APIGroups
:
[]
string
{
"logging.kubesphere.io"
}})
// if the user is not a cluster admin
if
!
hasClusterLogAccess
{
queryNamespaces
:=
strings
.
Split
(
req
.
QueryParameter
(
"namespaces"
),
","
)
// then the user can only view logs of namespaces he belongs to
namespaces
:=
make
([]
string
,
0
)
roles
,
err
:=
iam
.
GetUserRoles
(
""
,
username
)
if
err
!=
nil
{
klog
.
Errorln
(
err
)
return
nil
,
err
}
for
_
,
role
:=
range
roles
{
if
!
sliceutil
.
HasString
(
namespaces
,
role
.
Namespace
)
&&
iam
.
RulesMatchesRequired
(
role
.
Rules
,
rbacv1
.
PolicyRule
{
Verbs
:
[]
string
{
"get"
},
Resources
:
[]
string
{
"*"
},
APIGroups
:
[]
string
{
"logging.kubesphere.io"
}})
{
namespaces
=
append
(
namespaces
,
role
.
Namespace
)
}
}
// if the user belongs to no namespace
// then no log visible
if
len
(
namespaces
)
==
0
{
return
nil
,
nil
}
else
if
len
(
queryNamespaces
)
==
1
&&
queryNamespaces
[
0
]
==
""
{
values
.
Set
(
"namespaces"
,
strings
.
Join
(
namespaces
,
","
))
}
else
{
inter
:=
intersection
(
queryNamespaces
,
namespaces
)
if
len
(
inter
)
==
0
{
return
nil
,
nil
}
values
.
Set
(
"namespaces"
,
strings
.
Join
(
inter
,
","
))
}
}
newUrl
.
RawQuery
=
values
.
Encode
()
// forward the request to logging model
newHttpRequest
,
_
:=
http
.
NewRequest
(
http
.
MethodGet
,
newUrl
.
String
(),
nil
)
return
restful
.
NewRequest
(
newHttpRequest
),
nil
}
func
intersection
(
s1
,
s2
[]
string
)
(
inter
[]
string
)
{
hash
:=
make
(
map
[
string
]
bool
)
for
_
,
e
:=
range
s1
{
hash
[
e
]
=
true
}
for
_
,
e
:=
range
s2
{
// If elements present in the hashmap then append intersection list.
if
hash
[
e
]
{
inter
=
append
(
inter
,
e
)
}
}
//Remove dups from slice.
inter
=
removeDups
(
inter
)
return
}
//Remove dups from slice.
func
removeDups
(
elements
[]
string
)
(
nodups
[]
string
)
{
encountered
:=
make
(
map
[
string
]
bool
)
for
_
,
element
:=
range
elements
{
if
!
encountered
[
element
]
{
nodups
=
append
(
nodups
,
element
)
encountered
[
element
]
=
true
}
}
return
}
pkg/kapis/devops/v1alpha2/register.go
浏览文件 @
0664eeb5
...
...
@@ -78,7 +78,7 @@ func addWebService(c *restful.Container, devopsClient devops.Interface,
Writes
([]
sonarqube
.
SonarStatus
{}))
}
if
projectPipleineEnable
{
if
projectPipleineEnable
{
projectPipelineHander
:=
NewProjectPipelineHandler
(
devopsClient
,
dbClient
)
webservice
.
Route
(
webservice
.
GET
(
"/devops/{devops}"
)
.
To
(
projectPipelineHander
.
GetDevOpsProjectHandler
)
.
...
...
@@ -190,8 +190,6 @@ func addWebService(c *restful.Container, devopsClient devops.Interface,
Returns
(
http
.
StatusOK
,
RespOK
,
devops
.
ProjectPipeline
{})
.
Writes
(
devops
.
ProjectPipeline
{}))
webservice
.
Route
(
webservice
.
POST
(
"/devops/{devops}/credentials"
)
.
To
(
projectPipelineHander
.
CreateDevOpsProjectCredentialHandler
)
.
Doc
(
"Create a credential in the specified DevOps project"
)
.
...
...
@@ -785,7 +783,6 @@ The last one is encrypted info, such as the password of the username-password ty
Writes
(
devops
.
ResJson
{}))
}
if
s2iEnable
{
s2iHandler
:=
NewS2iBinaryHandler
(
ksClient
,
ksInformer
,
s3Client
)
webservice
.
Route
(
webservice
.
PUT
(
"/namespaces/{namespace}/s2ibinaries/{s2ibinary}/file"
)
.
...
...
@@ -808,7 +805,7 @@ The last one is encrypted info, such as the password of the username-password ty
Param
(
webservice
.
PathParameter
(
"file"
,
"the name of binary file"
))
.
Returns
(
http
.
StatusOK
,
RespOK
,
nil
))
}
c
.
Add
(
webservice
)
return
nil
...
...
pkg/kapis/resources/v1alpha2/handler.go
浏览文件 @
0664eeb5
...
...
@@ -5,10 +5,13 @@ import (
"github.com/emicklei/go-restful"
v1
"k8s.io/api/core/v1"
k8serr
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/components"
"kubesphere.io/kubesphere/pkg/models/git"
"kubesphere.io/kubesphere/pkg/models/kubeconfig"
"kubesphere.io/kubesphere/pkg/models/kubectl"
"kubesphere.io/kubesphere/pkg/models/quotas"
"kubesphere.io/kubesphere/pkg/models/registries"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
...
...
@@ -31,6 +34,8 @@ type resourceHandler struct {
routerOperator
routers
.
RouterOperator
gitVerifier
git
.
GitVerifier
registryGetter
registries
.
RegistryGetter
kubeconfigOperator
kubeconfig
.
Interface
kubectlOperator
kubectl
.
Interface
}
func
newResourceHandler
(
client
k8s
.
Client
)
*
resourceHandler
{
...
...
@@ -45,6 +50,8 @@ func newResourceHandler(client k8s.Client) *resourceHandler {
routerOperator
:
routers
.
NewRouterOperator
(
client
.
Kubernetes
(),
factory
.
KubernetesSharedInformerFactory
()),
gitVerifier
:
git
.
NewGitVerifier
(
factory
.
KubernetesSharedInformerFactory
()),
registryGetter
:
registries
.
NewRegistryGetter
(
factory
.
KubernetesSharedInformerFactory
()),
kubeconfigOperator
:
kubeconfig
.
NewKubeconfigOperator
(),
kubectlOperator
:
kubectl
.
NewKubectlOperator
(
client
.
Kubernetes
(),
factory
.
KubernetesSharedInformerFactory
()),
}
}
...
...
@@ -340,6 +347,35 @@ func (r *resourceHandler) handleGetNamespacedAbnormalWorkloads(request *restful.
}
func
(
r
*
resourceHandler
)
handleGetAbnormalWorkloads
(
request
*
restful
.
Request
,
response
*
restful
.
Response
)
{
r
.
handleGetNamespacedAbnormalWorkloads
(
request
,
response
)
func
(
r
*
resourceHandler
)
GetKubectlPod
(
request
*
restful
.
Request
,
response
*
restful
.
Response
)
{
user
:=
request
.
PathParameter
(
"user"
)
kubectlPod
,
err
:=
r
.
kubectlOperator
.
GetKubectlPod
(
user
)
if
err
!=
nil
{
klog
.
Errorln
(
err
)
response
.
WriteHeaderAndEntity
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
))
return
}
response
.
WriteEntity
(
kubectlPod
)
}
func
(
r
*
resourceHandler
)
GetKubeconfig
(
request
*
restful
.
Request
,
response
*
restful
.
Response
)
{
user
:=
request
.
PathParameter
(
"user"
)
kubectlConfig
,
err
:=
r
.
kubeconfigOperator
.
GetKubeConfig
(
user
)
if
err
!=
nil
{
klog
.
Error
(
err
)
if
k8serr
.
IsNotFound
(
err
)
{
// recreate
response
.
WriteHeaderAndJson
(
http
.
StatusNotFound
,
errors
.
Wrap
(
err
),
restful
.
MIME_JSON
)
}
else
{
response
.
WriteHeaderAndJson
(
http
.
StatusInternalServerError
,
errors
.
Wrap
(
err
),
restful
.
MIME_JSON
)
}
return
}
response
.
Write
([]
byte
(
kubectlConfig
))
}
pkg/kapis/resources/v1alpha2/register.go
浏览文件 @
0664eeb5
...
...
@@ -25,7 +25,6 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/api/resource/v1alpha2"
"kubesphere.io/kubesphere/pkg/apiserver/resources"
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models"
...
...
@@ -82,7 +81,7 @@ func AddToContainer(c *restful.Container, client k8s.Client) error {
Param
(
webservice
.
QueryParameter
(
params
.
OrderByParam
,
"sort parameters, e.g. orderBy=createTime"
)))
webservice
.
Route
(
webservice
.
GET
(
"/users/{user}/kubectl"
)
.
To
(
resources
.
GetKubectl
)
.
To
(
handler
.
GetKubectlPod
)
.
Doc
(
"get user's kubectl pod"
)
.
Param
(
webservice
.
PathParameter
(
"user"
,
"username"
))
.
Metadata
(
restfulspec
.
KeyOpenAPITags
,
[]
string
{
constants
.
UserResourcesTag
})
.
...
...
@@ -90,7 +89,7 @@ func AddToContainer(c *restful.Container, client k8s.Client) error {
webservice
.
Route
(
webservice
.
GET
(
"/users/{user}/kubeconfig"
)
.
Produces
(
"text/plain"
,
restful
.
MIME_JSON
)
.
To
(
resources
.
GetKubeconfig
)
.
To
(
handler
.
GetKubeconfig
)
.
Doc
(
"get users' kubeconfig"
)
.
Param
(
webservice
.
PathParameter
(
"user"
,
"username"
))
.
Returns
(
http
.
StatusOK
,
api
.
StatusOK
,
""
)
.
...
...
@@ -214,7 +213,7 @@ func AddToContainer(c *restful.Container, client k8s.Client) error {
Doc
(
"get abnormal workloads' count of whole cluster"
)
.
Metadata
(
restfulspec
.
KeyOpenAPITags
,
[]
string
{
constants
.
ClusterResourcesTag
})
.
Returns
(
http
.
StatusOK
,
api
.
StatusOK
,
api
.
Workloads
{})
.
To
(
handler
.
handleGetAbnormalWorkloads
))
To
(
handler
.
handleGet
Namespaced
AbnormalWorkloads
))
webservice
.
Route
(
webservice
.
GET
(
"/namespaces/{namespace}/abnormalworkloads"
)
.
Doc
(
"get abnormal workloads' count of specified namespace"
)
.
Param
(
webservice
.
PathParameter
(
"namespace"
,
"the name of the project"
))
.
...
...
pkg/models/iam/am.go
浏览文件 @
0664eeb5
...
...
@@ -28,7 +28,6 @@ import (
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/iam/policy"
"kubesphere.io/kubesphere/pkg/models/kubectl"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/clusterrole"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/resource"
...
...
@@ -538,17 +537,18 @@ func (am *amOperator) CreateClusterRoleBinding(username string, clusterRoleName
return
err
}
// TODO move to user controller
if
clusterRoleName
==
constants
.
ClusterAdmin
{
// create kubectl pod if cluster role is cluster-admin
if
err
:=
kubectl
.
CreateKubectlDeploy
(
username
);
err
!=
nil
{
klog
.
Error
(
"create user terminal pod failed"
,
username
,
err
)
}
//
if err := kubectl.CreateKubectlDeploy(username); err != nil {
//
klog.Error("create user terminal pod failed", username, err)
//
}
}
else
{
// delete kubectl pod if cluster role is not cluster-admin, whether it exists or not
if
err
:=
kubectl
.
DelKubectlDeploy
(
username
);
err
!=
nil
{
klog
.
Error
(
"delete user terminal pod failed"
,
username
,
err
)
}
//
if err := kubectl.DelKubectlDeploy(username); err != nil {
//
klog.Error("delete user terminal pod failed", username, err)
//
}
}
clusterRoleBinding
:=
&
rbacv1
.
ClusterRoleBinding
{}
...
...
pkg/models/kubeconfig/kubeconfig.go
浏览文件 @
0664eeb5
...
...
@@ -18,298 +18,17 @@
package
kubeconfig
import
(
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/base64"
"encoding/pem"
"fmt"
"gopkg.in/yaml.v2"
"io/ioutil"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/simple/client"
"math/big"
rd
"math/rand"
"time"
metaV1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/api/core/v1"
"kubesphere.io/kubesphere/pkg/constants"
)
const
(
caPath
=
"/etc/kubernetes/pki/ca.crt"
keyPath
=
"/etc/kubernetes/pki/ca.key"
clusterName
=
"kubernetes"
kubectlConfigKey
=
"config"
defaultNamespace
=
"default"
)
type
clusterInfo
struct
{
CertificateAuthorityData
string
`yaml:"certificate-authority-data"`
Server
string
`yaml:"server"`
}
type
cluster
struct
{
Cluster
clusterInfo
`yaml:"cluster"`
Name
string
`yaml:"name"`
}
type
contextInfo
struct
{
Cluster
string
`yaml:"cluster"`
User
string
`yaml:"user"`
NameSpace
string
`yaml:"namespace"`
}
type
contextObject
struct
{
Context
contextInfo
`yaml:"context"`
Name
string
`yaml:"name"`
}
type
userInfo
struct
{
CaData
string
`yaml:"client-certificate-data"`
KeyData
string
`yaml:"client-key-data"`
}
type
user
struct
{
Name
string
`yaml:"name"`
User
userInfo
`yaml:"user"`
}
type
kubeConfig
struct
{
ApiVersion
string
`yaml:"apiVersion"`
Clusters
[]
cluster
`yaml:"clusters"`
Contexts
[]
contextObject
`yaml:"contexts"`
CurrentContext
string
`yaml:"current-context"`
Kind
string
`yaml:"kind"`
Preferences
map
[
string
]
string
`yaml:"preferences"`
Users
[]
user
`yaml:"users"`
}
type
CertInformation
struct
{
Country
[]
string
Organization
[]
string
OrganizationalUnit
[]
string
EmailAddress
[]
string
Province
[]
string
Locality
[]
string
CommonName
string
CrtName
,
KeyName
string
IsCA
bool
Names
[]
pkix
.
AttributeTypeAndValue
}
func
createCRT
(
RootCa
*
x509
.
Certificate
,
RootKey
*
rsa
.
PrivateKey
,
info
CertInformation
)
([]
byte
,
[]
byte
,
error
)
{
var
cert
,
key
bytes
.
Buffer
Crt
:=
newCertificate
(
info
)
Key
,
err
:=
rsa
.
GenerateKey
(
rand
.
Reader
,
2048
)
if
err
!=
nil
{
klog
.
Error
(
err
)
return
nil
,
nil
,
err
}
var
buf
[]
byte
buf
,
err
=
x509
.
CreateCertificate
(
rand
.
Reader
,
Crt
,
RootCa
,
&
Key
.
PublicKey
,
RootKey
)
if
err
!=
nil
{
klog
.
Error
(
err
)
return
nil
,
nil
,
err
}
pem
.
Encode
(
&
cert
,
&
pem
.
Block
{
Type
:
"CERTIFICATE"
,
Bytes
:
buf
})
if
err
!=
nil
{
klog
.
Error
(
err
)
return
nil
,
nil
,
err
}
buf
=
x509
.
MarshalPKCS1PrivateKey
(
Key
)
pem
.
Encode
(
&
key
,
&
pem
.
Block
{
Type
:
"PRIVATE KEY"
,
Bytes
:
buf
})
return
cert
.
Bytes
(),
key
.
Bytes
(),
nil
}
func
Parse
(
crtPath
,
keyPath
string
)
(
rootcertificate
*
x509
.
Certificate
,
rootPrivateKey
*
rsa
.
PrivateKey
,
err
error
)
{
rootcertificate
,
err
=
parseCrt
(
crtPath
)
if
err
!=
nil
{
klog
.
Error
(
err
)
return
nil
,
nil
,
err
}
rootPrivateKey
,
err
=
parseKey
(
keyPath
)
return
rootcertificate
,
rootPrivateKey
,
nil
}
func
parseCrt
(
path
string
)
(
*
x509
.
Certificate
,
error
)
{
buf
,
err
:=
ioutil
.
ReadFile
(
path
)
if
err
!=
nil
{
klog
.
Error
(
err
)
return
nil
,
err
}
p
:=
&
pem
.
Block
{}
p
,
buf
=
pem
.
Decode
(
buf
)
return
x509
.
ParseCertificate
(
p
.
Bytes
)
}
func
parseKey
(
path
string
)
(
*
rsa
.
PrivateKey
,
error
)
{
buf
,
err
:=
ioutil
.
ReadFile
(
path
)
if
err
!=
nil
{
klog
.
Error
(
err
)
return
nil
,
err
}
p
,
buf
:=
pem
.
Decode
(
buf
)
return
x509
.
ParsePKCS1PrivateKey
(
p
.
Bytes
)
type
Interface
interface
{
GetKubeConfig
(
username
string
)
(
string
,
error
)
}
func
newCertificate
(
info
CertInformation
)
*
x509
.
Certificate
{
rd
.
Seed
(
time
.
Now
()
.
UnixNano
())
return
&
x509
.
Certificate
{
SerialNumber
:
big
.
NewInt
(
rd
.
Int63
()),
Subject
:
pkix
.
Name
{
Country
:
info
.
Country
,
Organization
:
info
.
Organization
,
OrganizationalUnit
:
info
.
OrganizationalUnit
,
Province
:
info
.
Province
,
CommonName
:
info
.
CommonName
,
Locality
:
info
.
Locality
,
ExtraNames
:
info
.
Names
,
},
NotBefore
:
time
.
Now
(),
NotAfter
:
time
.
Now
()
.
AddDate
(
20
,
0
,
0
),
BasicConstraintsValid
:
true
,
IsCA
:
info
.
IsCA
,
ExtKeyUsage
:
[]
x509
.
ExtKeyUsage
{
x509
.
ExtKeyUsageClientAuth
,
x509
.
ExtKeyUsageServerAuth
},
KeyUsage
:
x509
.
KeyUsageDigitalSignature
|
x509
.
KeyUsageCertSign
,
EmailAddresses
:
info
.
EmailAddress
,
}
type
operator
struct
{
}
func
generateCaAndKey
(
user
,
caPath
,
keyPath
string
)
(
string
,
string
,
error
)
{
crtInfo
:=
CertInformation
{
CommonName
:
user
,
IsCA
:
false
}
crt
,
pri
,
err
:=
Parse
(
caPath
,
keyPath
)
if
err
!=
nil
{
klog
.
Error
(
err
)
return
""
,
""
,
err
}
cert
,
key
,
err
:=
createCRT
(
crt
,
pri
,
crtInfo
)
if
err
!=
nil
{
klog
.
Error
(
err
)
return
""
,
""
,
err
}
base64Cert
:=
base64
.
StdEncoding
.
EncodeToString
(
cert
)
base64Key
:=
base64
.
StdEncoding
.
EncodeToString
(
key
)
return
base64Cert
,
base64Key
,
nil
func
(
o
operator
)
GetKubeConfig
(
username
string
)
(
string
,
error
)
{
panic
(
"implement me"
)
}
func
createKubeConfig
(
username
string
)
(
string
,
error
)
{
tmpKubeConfig
:=
kubeConfig
{
ApiVersion
:
"v1"
,
Kind
:
"Config"
}
serverCa
,
err
:=
ioutil
.
ReadFile
(
caPath
)
if
err
!=
nil
{
klog
.
Errorln
(
err
)
return
""
,
err
}
base64ServerCa
:=
base64
.
StdEncoding
.
EncodeToString
(
serverCa
)
tmpClusterInfo
:=
clusterInfo
{
CertificateAuthorityData
:
base64ServerCa
,
Server
:
client
.
ClientSets
()
.
K8s
()
.
Master
()}
tmpCluster
:=
cluster
{
Cluster
:
tmpClusterInfo
,
Name
:
clusterName
}
tmpKubeConfig
.
Clusters
=
append
(
tmpKubeConfig
.
Clusters
,
tmpCluster
)
contextName
:=
username
+
"@"
+
clusterName
tmpContext
:=
contextObject
{
Context
:
contextInfo
{
User
:
username
,
Cluster
:
clusterName
,
NameSpace
:
defaultNamespace
},
Name
:
contextName
}
tmpKubeConfig
.
Contexts
=
append
(
tmpKubeConfig
.
Contexts
,
tmpContext
)
cert
,
key
,
err
:=
generateCaAndKey
(
username
,
caPath
,
keyPath
)
if
err
!=
nil
{
return
""
,
err
}
tmpUser
:=
user
{
User
:
userInfo
{
CaData
:
cert
,
KeyData
:
key
},
Name
:
username
}
tmpKubeConfig
.
Users
=
append
(
tmpKubeConfig
.
Users
,
tmpUser
)
tmpKubeConfig
.
CurrentContext
=
contextName
config
,
err
:=
yaml
.
Marshal
(
tmpKubeConfig
)
if
err
!=
nil
{
return
""
,
err
}
return
string
(
config
),
nil
}
func
CreateKubeConfig
(
username
string
)
error
{
k8sClient
:=
client
.
ClientSets
()
.
K8s
()
.
Kubernetes
()
configName
:=
fmt
.
Sprintf
(
"kubeconfig-%s"
,
username
)
_
,
err
:=
k8sClient
.
CoreV1
()
.
ConfigMaps
(
constants
.
KubeSphereControlNamespace
)
.
Get
(
configName
,
metaV1
.
GetOptions
{})
if
errors
.
IsNotFound
(
err
)
{
config
,
err
:=
createKubeConfig
(
username
)
if
err
!=
nil
{
klog
.
Errorln
(
err
)
return
err
}
data
:=
map
[
string
]
string
{
"config"
:
config
}
configMap
:=
v1
.
ConfigMap
{
TypeMeta
:
metaV1
.
TypeMeta
{
Kind
:
"Configmap"
,
APIVersion
:
"v1"
},
ObjectMeta
:
metaV1
.
ObjectMeta
{
Name
:
configName
},
Data
:
data
}
_
,
err
=
k8sClient
.
CoreV1
()
.
ConfigMaps
(
constants
.
KubeSphereControlNamespace
)
.
Create
(
&
configMap
)
if
err
!=
nil
&&
!
errors
.
IsAlreadyExists
(
err
)
{
klog
.
Errorf
(
"create username %s's kubeConfig failed, reason: %v"
,
username
,
err
)
return
err
}
}
return
nil
}
func
GetKubeConfig
(
username
string
)
(
string
,
error
)
{
k8sClient
:=
client
.
ClientSets
()
.
K8s
()
.
Kubernetes
()
configName
:=
fmt
.
Sprintf
(
"kubeconfig-%s"
,
username
)
configMap
,
err
:=
k8sClient
.
CoreV1
()
.
ConfigMaps
(
constants
.
KubeSphereControlNamespace
)
.
Get
(
configName
,
metaV1
.
GetOptions
{})
if
err
!=
nil
{
klog
.
Errorf
(
"cannot get username %s's kubeConfig, reason: %v"
,
username
,
err
)
return
""
,
err
}
str
:=
configMap
.
Data
[
kubectlConfigKey
]
var
kubeConfig
kubeConfig
err
=
yaml
.
Unmarshal
([]
byte
(
str
),
&
kubeConfig
)
if
err
!=
nil
{
klog
.
Error
(
err
)
return
""
,
err
}
masterURL
:=
client
.
ClientSets
()
.
K8s
()
.
Master
()
for
i
,
cluster
:=
range
kubeConfig
.
Clusters
{
cluster
.
Cluster
.
Server
=
masterURL
kubeConfig
.
Clusters
[
i
]
=
cluster
}
data
,
err
:=
yaml
.
Marshal
(
kubeConfig
)
if
err
!=
nil
{
klog
.
Error
(
err
)
return
""
,
err
}
return
string
(
data
),
nil
}
func
DelKubeConfig
(
username
string
)
error
{
k8sClient
:=
client
.
ClientSets
()
.
K8s
()
.
Kubernetes
()
configName
:=
fmt
.
Sprintf
(
"kubeconfig-%s"
,
username
)
_
,
err
:=
k8sClient
.
CoreV1
()
.
ConfigMaps
(
constants
.
KubeSphereControlNamespace
)
.
Get
(
configName
,
metaV1
.
GetOptions
{})
if
errors
.
IsNotFound
(
err
)
{
return
nil
}
deletePolicy
:=
metaV1
.
DeletePropagationBackground
err
=
k8sClient
.
CoreV1
()
.
ConfigMaps
(
constants
.
KubeSphereControlNamespace
)
.
Delete
(
configName
,
&
metaV1
.
DeleteOptions
{
PropagationPolicy
:
&
deletePolicy
})
if
err
!=
nil
{
klog
.
Errorf
(
"delete username %s's kubeConfig failed, reason: %v"
,
username
,
err
)
return
err
}
return
nil
func
NewKubeconfigOperator
()
Interface
{
return
&
operator
{}
}
pkg/models/kubectl/kubectl.go
浏览文件 @
0664eeb5
...
...
@@ -20,9 +20,10 @@ package kubectl
import
(
"fmt"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/simple/client"
"math/rand"
"os"
...
...
@@ -40,6 +41,21 @@ const (
namespace
=
constants
.
KubeSphereControlNamespace
)
type
Interface
interface
{
GetKubectlPod
(
username
string
)
(
models
.
PodInfo
,
error
)
CreateKubectlDeploy
(
username
string
)
error
DelKubectlDeploy
(
username
string
)
error
}
type
operator
struct
{
k8sClient
kubernetes
.
Interface
informers
informers
.
SharedInformerFactory
}
func
NewKubectlOperator
(
k8sClient
kubernetes
.
Interface
,
informers
informers
.
SharedInformerFactory
)
Interface
{
return
&
operator
{
k8sClient
:
k8sClient
,
informers
:
informers
}
}
var
DefaultImage
=
"kubesphere/kubectl:advanced-1.0.0"
func
init
()
{
...
...
@@ -48,24 +64,23 @@ func init() {
}
}
func
GetKubectlPod
(
username
string
)
(
models
.
PodInfo
,
error
)
{
k8sClient
:=
client
.
ClientSets
()
.
K8s
()
.
Kubernetes
()
func
(
o
*
operator
)
GetKubectlPod
(
username
string
)
(
models
.
PodInfo
,
error
)
{
deployName
:=
fmt
.
Sprintf
(
"kubectl-%s"
,
username
)
deploy
,
err
:=
k8sClient
.
AppsV1
()
.
Deployments
(
namespace
)
.
Get
(
deployName
,
metav1
.
GetOptions
{}
)
deploy
,
err
:=
o
.
informers
.
Apps
()
.
V1
()
.
Deployments
()
.
Lister
()
.
Deployments
(
namespace
)
.
Get
(
deployName
)
if
err
!=
nil
{
klog
.
Errorln
(
err
)
return
models
.
PodInfo
{},
err
}
selectors
:=
deploy
.
Spec
.
Selector
.
MatchLabels
labelSelector
:=
labels
.
Set
(
selectors
)
.
AsSelector
()
.
String
()
pod
List
,
err
:=
k8sClient
.
CoreV1
()
.
Pods
(
namespace
)
.
List
(
metav1
.
ListOptions
{
LabelSelector
:
labelSelector
}
)
labelSelector
:=
labels
.
Set
(
selectors
)
.
AsSelector
()
pod
s
,
err
:=
o
.
informers
.
Core
()
.
V1
()
.
Pods
()
.
Lister
()
.
Pods
(
namespace
)
.
List
(
labelSelector
)
if
err
!=
nil
{
klog
.
Errorln
(
err
)
return
models
.
PodInfo
{},
err
}
pod
,
err
:=
selectCorrectPod
(
namespace
,
pod
List
.
Item
s
)
pod
,
err
:=
selectCorrectPod
(
namespace
,
pods
)
if
err
!=
nil
{
klog
.
Errorln
(
err
)
return
models
.
PodInfo
{},
err
...
...
@@ -77,9 +92,9 @@ func GetKubectlPod(username string) (models.PodInfo, error) {
}
func
selectCorrectPod
(
namespace
string
,
pods
[]
v1
.
Pod
)
(
kubectlPod
v1
.
Pod
,
err
error
)
{
func
selectCorrectPod
(
namespace
string
,
pods
[]
*
v1
.
Pod
)
(
kubectlPod
*
v1
.
Pod
,
err
error
)
{
var
kubectlPodList
[]
v1
.
Pod
var
kubectlPodList
[]
*
v1
.
Pod
for
_
,
pod
:=
range
pods
{
for
_
,
condition
:=
range
pod
.
Status
.
Conditions
{
if
condition
.
Type
==
"Ready"
&&
condition
.
Status
==
"True"
{
...
...
@@ -89,15 +104,16 @@ func selectCorrectPod(namespace string, pods []v1.Pod) (kubectlPod v1.Pod, err e
}
if
len
(
kubectlPodList
)
<
1
{
err
=
fmt
.
Errorf
(
"cannot find valid kubectl pod in namespace:%s"
,
namespace
)
return
v1
.
Pod
{},
err
return
&
v1
.
Pod
{},
err
}
random
:=
rand
.
Intn
(
len
(
kubectlPodList
))
return
kubectlPodList
[
random
],
nil
}
func
CreateKubectlDeploy
(
username
string
)
error
{
k8sClient
:=
client
.
ClientSets
()
.
K8s
()
.
Kubernetes
()
func
(
o
*
operator
)
CreateKubectlDeploy
(
username
string
)
error
{
k8sClient
:=
o
.
k8sClient
deployName
:=
fmt
.
Sprintf
(
"kubectl-%s"
,
username
)
_
,
err
:=
k8sClient
.
AppsV1
()
.
Deployments
(
namespace
)
.
Get
(
deployName
,
metav1
.
GetOptions
{})
if
err
==
nil
{
...
...
@@ -136,8 +152,8 @@ func CreateKubectlDeploy(username string) error {
return
err
}
func
DelKubectlDeploy
(
username
string
)
error
{
k8sClient
:=
client
.
ClientSets
()
.
K8s
()
.
Kubernetes
()
func
(
o
*
operator
)
DelKubectlDeploy
(
username
string
)
error
{
k8sClient
:=
o
.
k8sClient
deployName
:=
fmt
.
Sprintf
(
"kubectl-%s"
,
username
)
_
,
err
:=
k8sClient
.
AppsV1
()
.
Deployments
(
namespace
)
.
Get
(
deployName
,
metav1
.
GetOptions
{})
if
errors
.
IsNotFound
(
err
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录