Compare commits
60 Commits
master
...
release-2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c905fdbdb4 | ||
|
|
31d0e0e966 | ||
|
|
ed4d046b6d | ||
|
|
296c028d42 | ||
|
|
1ece2e8104 | ||
|
|
d51cd98e12 | ||
|
|
24527a7125 | ||
|
|
81982adcdd | ||
|
|
59de78aba1 | ||
|
|
a285cf70f8 | ||
|
|
856ea6ef2d | ||
|
|
bebf592fb7 | ||
|
|
eabb28f3b8 | ||
|
|
aca8ee023d | ||
|
|
ecf94db4e9 | ||
|
|
af2c4e7a44 | ||
|
|
8308b93ac2 | ||
|
|
cbc43b60ba | ||
|
|
54eb886e5e | ||
|
|
afb92dfc53 | ||
|
|
a003b57351 | ||
|
|
3387c9da50 | ||
|
|
c0ffdfd9cc | ||
|
|
4fc40e5faf | ||
|
|
2238998e78 | ||
|
|
4006c363e1 | ||
|
|
ed530b826a | ||
|
|
6339e66125 | ||
|
|
2f434b1483 | ||
|
|
0180c9e679 | ||
|
|
3698af5e8e | ||
|
|
77b66dab14 | ||
|
|
eff9918e6e | ||
|
|
291af6707e | ||
|
|
fdabeadf20 | ||
|
|
be8e88cd60 | ||
|
|
e29cc286c1 | ||
|
|
76c8785c2d | ||
|
|
47e3241090 | ||
|
|
736a744451 | ||
|
|
6a623c4c66 | ||
|
|
2ac4bc5371 | ||
|
|
751eff2da7 | ||
|
|
88da4f7809 | ||
|
|
bafbd7c4db | ||
|
|
26d62b5f6e | ||
|
|
da074e22bd | ||
|
|
4a5049d7ca | ||
|
|
b6b6f14fb6 | ||
|
|
9f06d62e29 | ||
|
|
b3690795a6 | ||
|
|
3ec030974b | ||
|
|
08786877f8 | ||
|
|
0531e2ce48 | ||
|
|
20d3f8fa4f | ||
|
|
4b30fd8c13 | ||
|
|
a3a0371203 | ||
|
|
7a97a696b6 | ||
|
|
89f1158a67 | ||
|
|
05e949103e |
17
.travis.yml
17
.travis.yml
@@ -9,7 +9,7 @@ git:
|
||||
depth: false
|
||||
|
||||
go:
|
||||
- "1.12.x"
|
||||
- "1.13.x"
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
cache:
|
||||
@@ -29,8 +29,13 @@ install:
|
||||
- go get golang.org/x/lint/golint
|
||||
|
||||
deploy:
|
||||
skip_cleanup: true
|
||||
provider: script
|
||||
script: bash hack/docker_build.sh
|
||||
on:
|
||||
branch: master
|
||||
- skip_cleanup: true
|
||||
provider: script
|
||||
script: bash hack/docker_build.sh
|
||||
on:
|
||||
branch: master
|
||||
- skip_cleanup: true
|
||||
provider: script
|
||||
script: bash hack/docker_build.sh
|
||||
on:
|
||||
branch: release-2.1
|
||||
|
||||
@@ -37,12 +37,12 @@ import (
|
||||
|
||||
istioclientset "github.com/knative/pkg/client/clientset/versioned"
|
||||
istioinformers "github.com/knative/pkg/client/informers/externalversions"
|
||||
applicationclientset "github.com/kubernetes-sigs/application/pkg/client/clientset/versioned"
|
||||
applicationinformers "github.com/kubernetes-sigs/application/pkg/client/informers/externalversions"
|
||||
s2iclientset "github.com/kubesphere/s2ioperator/pkg/client/clientset/versioned"
|
||||
s2iinformers "github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions"
|
||||
kubesphereclientset "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||
kubesphereinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
||||
applicationclientset "sigs.k8s.io/application/pkg/client/clientset/versioned"
|
||||
applicationinformers "sigs.k8s.io/application/pkg/client/informers/externalversions"
|
||||
)
|
||||
|
||||
const defaultResync = 600 * time.Second
|
||||
|
||||
18
go.mod
18
go.mod
@@ -15,7 +15,6 @@ require (
|
||||
github.com/Microsoft/go-winio v0.4.12 // indirect
|
||||
github.com/NYTimes/gziphandler v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/goquery v1.5.0
|
||||
github.com/appscode/jsonpatch v0.0.0-20190108182946-7c0e3b262f30 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf
|
||||
github.com/aws/aws-sdk-go v1.22.2
|
||||
github.com/beevik/etree v1.1.0
|
||||
@@ -45,7 +44,6 @@ require (
|
||||
github.com/fatih/structs v1.1.0
|
||||
github.com/go-ldap/ldap v3.0.3+incompatible
|
||||
github.com/go-logr/logr v0.1.0
|
||||
github.com/go-logr/zapr v0.1.1 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.0 // indirect
|
||||
github.com/go-openapi/spec v0.19.0
|
||||
@@ -74,11 +72,10 @@ require (
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.6
|
||||
github.com/kelseyhightower/envconfig v1.4.0 // indirect
|
||||
github.com/kiali/kiali v0.15.1-0.20190407071308-6b5b818211c3
|
||||
github.com/kiali/kiali v0.15.1-0.20200213040359-608aece2aa66
|
||||
github.com/klauspost/cpuid v1.2.1 // indirect
|
||||
github.com/knative/pkg v0.0.0-20190314204845-cd278f2d3394
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
||||
github.com/kubernetes-sigs/application v0.0.0-20190518133311-b9d9eb0b5cf7
|
||||
github.com/kubesphere/s2ioperator v0.0.13
|
||||
github.com/kubesphere/sonargo v0.0.2
|
||||
github.com/leodido/go-urn v1.1.0 // indirect
|
||||
@@ -92,13 +89,14 @@ require (
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
|
||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect
|
||||
github.com/onsi/ginkgo v1.8.0
|
||||
github.com/onsi/gomega v1.5.0
|
||||
github.com/onsi/ginkgo v1.10.1
|
||||
github.com/onsi/gomega v1.7.0
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1
|
||||
github.com/opencontainers/image-spec v1.0.1 // indirect
|
||||
github.com/openshift/api v3.9.0+incompatible // indirect
|
||||
github.com/pborman/uuid v0.0.0-20180906182336-adf5a7427709 // indirect
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/projectcalico/go-json v0.0.0-20161128004156-6219dc7339ba // indirect
|
||||
github.com/projectcalico/go-yaml v0.0.0-20161201183616-955bc3e451ef // indirect
|
||||
github.com/projectcalico/go-yaml-wrapper v0.0.0-20161127220527-598e54215bee // indirect
|
||||
@@ -131,7 +129,7 @@ require (
|
||||
gopkg.in/src-d/go-git.v4 v4.11.0
|
||||
gopkg.in/yaml.v2 v2.2.2
|
||||
gotest.tools v2.2.0+incompatible // indirect
|
||||
k8s.io/api v0.0.0-20181213150558-05914d821849
|
||||
k8s.io/api v0.0.0-20190831074750-7364b6bdad65
|
||||
k8s.io/apiextensions-apiserver v0.0.0-20181213153335-0fe22c71c476
|
||||
k8s.io/apimachinery v0.0.0-20190831074630-461753078381
|
||||
k8s.io/apiserver v0.0.0-20190507070644-e9c02aff496d
|
||||
@@ -148,7 +146,6 @@ require (
|
||||
sigs.k8s.io/application v0.0.0-20190404151855-67ae7f915d4e
|
||||
sigs.k8s.io/controller-runtime v0.1.10
|
||||
sigs.k8s.io/controller-tools v0.1.12
|
||||
sigs.k8s.io/testing_frameworks v0.1.1 // indirect
|
||||
sigs.k8s.io/yaml v1.1.0 // indirect
|
||||
)
|
||||
|
||||
@@ -294,7 +291,7 @@ replace (
|
||||
github.com/kelseyhightower/envconfig => github.com/kelseyhightower/envconfig v1.4.0
|
||||
github.com/kevinburke/ssh_config => github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e
|
||||
github.com/keybase/go-ps => github.com/keybase/go-ps v0.0.0-20161005175911-668c8856d999
|
||||
github.com/kiali/kiali => github.com/kubesphere/kiali v0.15.1-0.20190407071308-6b5b818211c3
|
||||
github.com/kiali/kiali => github.com/kubesphere/kiali v0.15.1-0.20200213040359-608aece2aa66
|
||||
github.com/klauspost/cpuid => github.com/klauspost/cpuid v1.2.1
|
||||
github.com/knative/pkg => github.com/knative/pkg v0.0.0-20190314204845-cd278f2d3394
|
||||
github.com/koding/multiconfig => github.com/koding/multiconfig v0.0.0-20171124222453-69c27309b2d7
|
||||
@@ -303,7 +300,6 @@ replace (
|
||||
github.com/kr/pretty => github.com/kr/pretty v0.1.0
|
||||
github.com/kr/pty => github.com/kr/pty v1.1.1
|
||||
github.com/kr/text => github.com/kr/text v0.1.0
|
||||
github.com/kubernetes-sigs/application => github.com/kubesphere/application v0.0.0-20190518133311-b9d9eb0b5cf7
|
||||
github.com/kubesphere/s2ioperator => github.com/kubesphere/s2ioperator v0.0.13
|
||||
github.com/kubesphere/sonargo => github.com/kubesphere/sonargo v0.0.2
|
||||
github.com/kylelemons/godebug => github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348
|
||||
@@ -430,7 +426,7 @@ replace (
|
||||
openpitrix.io/logger v0.1.0 => github.com/openpitrix/logger v0.1.0
|
||||
openpitrix.io/openpitrix => openpitrix.io/openpitrix v0.4.1-0.20190920134345-4d2be6e4965c
|
||||
rsc.io/goversion => rsc.io/goversion v1.0.0
|
||||
sigs.k8s.io/application => sigs.k8s.io/application v0.0.0-20190404151855-67ae7f915d4e
|
||||
sigs.k8s.io/application => github.com/kubesphere/application v0.0.0-20200221140547-8beafe2fa7ef
|
||||
sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.1.10
|
||||
sigs.k8s.io/controller-tools => sigs.k8s.io/controller-tools v0.1.12
|
||||
sigs.k8s.io/testing_frameworks => sigs.k8s.io/testing_frameworks v0.1.1
|
||||
|
||||
8
go.sum
8
go.sum
@@ -268,10 +268,14 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kubernetes-sigs/application v0.8.1 h1:tnIN+iijr0kDJxvOhnqjoXV+3hWydRNy8OHisMyO71U=
|
||||
github.com/kubernetes-sigs/application v0.8.1/go.mod h1:KqAScqo78PXUrmoFOH8z6P4xQDBdzyJH1FMqrhgJJLE=
|
||||
github.com/kubesphere/application v0.0.0-20190518133311-b9d9eb0b5cf7 h1:9dongD6mbssQJGb9pV4sE7IHyua6I/lCOu4h6rEfj20=
|
||||
github.com/kubesphere/application v0.0.0-20190518133311-b9d9eb0b5cf7/go.mod h1:xCs7b2bgA24oBSuZYf+5btESJC3xPs//ZTSK1ql+W6I=
|
||||
github.com/kubesphere/kiali v0.15.1-0.20190407071308-6b5b818211c3 h1:5IASnVaVqZFzzIc/0FZuAnjWO1gVCUxJe1OFUS42/fU=
|
||||
github.com/kubesphere/kiali v0.15.1-0.20190407071308-6b5b818211c3/go.mod h1:Y1EqeixoXkKkU8I+yvOfhdh21+8+etFE6wYOVT2XFdI=
|
||||
github.com/kubesphere/application v0.0.0-20200221140547-8beafe2fa7ef h1:0s/3VfJ9xP9cqLB7dKj1eXCfC+Nr8fy/5xUJhD2lojU=
|
||||
github.com/kubesphere/application v0.0.0-20200221140547-8beafe2fa7ef/go.mod h1:Sn/bPGEhZxJeByRvkBo3I+n343KJ+5PBbhdmCdoJZX8=
|
||||
github.com/kubesphere/kiali v0.15.1-0.20200213040359-608aece2aa66 h1:xrYcJkIEsE6RDmBprHn1SSMOoYcew/SAxJPm2+rHg1s=
|
||||
github.com/kubesphere/kiali v0.15.1-0.20200213040359-608aece2aa66/go.mod h1:Y1EqeixoXkKkU8I+yvOfhdh21+8+etFE6wYOVT2XFdI=
|
||||
github.com/kubesphere/s2ioperator v0.0.13 h1:K6RdjaFluhn/GterbnIykORrueAZcwR/Qj3MsVI4qQs=
|
||||
github.com/kubesphere/s2ioperator v0.0.13/go.mod h1:dv9L+zRYDlHvnKPp0j6VHRtlGB1BU+lloltW9SAWqVU=
|
||||
github.com/kubesphere/sonargo v0.0.2 h1:hsSRE3sv3mkPcUAeSABdp7rtfcNW2zzeHXzFa01CTkU=
|
||||
|
||||
@@ -13,6 +13,10 @@ elif [[ $TRAVIS_EVENT_TYPE == "cron" ]]; then
|
||||
TAG=dev-$(date +%Y%m%d)
|
||||
fi
|
||||
|
||||
if [[ $TRAVIS_BRANCH == "release-2.1" ]]; then
|
||||
TAG=release-2.1
|
||||
fi
|
||||
|
||||
|
||||
docker build -f build/ks-apigateway/Dockerfile -t $REPO/ks-apigateway:$TAG .
|
||||
docker build -f build/ks-apiserver/Dockerfile -t $REPO/ks-apiserver:$TAG .
|
||||
|
||||
@@ -48,7 +48,7 @@ mkdir -p "${_tmp}"
|
||||
|
||||
# Add the require directive
|
||||
echo "Running: go get ${dep}@${sha}"
|
||||
go get -m -d "${dep}@${sha}"
|
||||
go get -d "${dep}@${sha}"
|
||||
|
||||
# Find the resolved version
|
||||
rev=$(go mod edit -json | jq -r ".Require[] | select(.Path == \"${dep}\") | .Version")
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
"github.com/knative/pkg/apis/istio/v1alpha3"
|
||||
"kubesphere.io/kubesphere/pkg/apis/servicemesh/v1alpha2"
|
||||
|
||||
"github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1"
|
||||
appv1beta1 "sigs.k8s.io/application/pkg/apis/app/v1beta1"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -31,5 +31,5 @@ func init() {
|
||||
AddToSchemes = append(AddToSchemes, v1alpha3.SchemeBuilder.AddToScheme)
|
||||
|
||||
// Register application scheme
|
||||
AddToSchemes = append(AddToSchemes, v1beta1.SchemeBuilder.AddToScheme)
|
||||
AddToSchemes = append(AddToSchemes, appv1beta1.SchemeBuilder.AddToScheme)
|
||||
}
|
||||
|
||||
@@ -405,5 +405,8 @@ func addWebService(c *restful.Container) error {
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
c.Add(ws)
|
||||
|
||||
metrics.CompatibleMetrics()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/emicklei/go-restful-openapi"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
storagev1 "k8s.io/api/storage/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/components"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/git"
|
||||
@@ -257,7 +258,14 @@ func addWebService(c *restful.Container) error {
|
||||
Returns(http.StatusOK, ok, status.WorkLoadStatus{}).
|
||||
To(workloadstatuses.GetNamespacedAbnormalWorkloads))
|
||||
|
||||
c.Add(webservice)
|
||||
webservice.Route(webservice.PATCH("/storageclasses/{storageclass}").
|
||||
To(resources.PatchStorageClass).
|
||||
Doc("patch storage class").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterResourcesTag}).
|
||||
Returns(http.StatusOK, ok, storagev1.StorageClass{}).
|
||||
Writes(storagev1.StorageClass{}).
|
||||
Param(webservice.PathParameter("storageclass", "the name of storage class")))
|
||||
|
||||
c.Add(webservice)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -38,9 +38,9 @@ func GetDevOpsProjectMembersHandler(request *restful.Request, resp *restful.Resp
|
||||
return
|
||||
}
|
||||
orderBy := request.QueryParameter(params.OrderByParam)
|
||||
reverse := params.ParseReverse(request)
|
||||
limit, offset := params.ParsePaging(request.QueryParameter(params.PagingParam))
|
||||
conditions, err := params.ParseConditions(request.QueryParameter(params.ConditionsParam))
|
||||
reverse := params.GetBoolValueWithDefault(request, params.ReverseParam, false)
|
||||
limit, offset := params.ParsePaging(request)
|
||||
conditions, err := params.ParseConditions(request)
|
||||
|
||||
project, err := devops.GetProjectMembers(projectId, conditions, orderBy, reverse, limit, offset)
|
||||
|
||||
|
||||
@@ -39,6 +39,12 @@ func CreateDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.
|
||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||
return
|
||||
}
|
||||
err = devops.ValidatePipelineConfig(pipeline)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
|
||||
return
|
||||
}
|
||||
pipelineName, err := devops.CreateProjectPipeline(projectId, pipeline)
|
||||
|
||||
if err != nil {
|
||||
@@ -96,6 +102,12 @@ func UpdateDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.
|
||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||
return
|
||||
}
|
||||
err = devops.ValidatePipelineConfig(pipeline)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
|
||||
return
|
||||
}
|
||||
pipelineName, err := devops.UpdateProjectPipeline(projectId, pipelineId, pipeline)
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"k8s.io/api/rbac/v1"
|
||||
k8serr "k8s.io/apimachinery/pkg/api/errors"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"net/http"
|
||||
"sort"
|
||||
@@ -50,10 +51,10 @@ func ListRoleUsers(req *restful.Request, resp *restful.Response) {
|
||||
}
|
||||
|
||||
func ListClusterRoles(req *restful.Request, resp *restful.Response) {
|
||||
conditions, err := params.ParseConditions(req.QueryParameter(params.ConditionsParam))
|
||||
conditions, err := params.ParseConditions(req)
|
||||
orderBy := req.QueryParameter(params.OrderByParam)
|
||||
limit, offset := params.ParsePaging(req.QueryParameter(params.PagingParam))
|
||||
reverse := params.ParseReverse(req)
|
||||
limit, offset := params.ParsePaging(req)
|
||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
@@ -73,10 +74,10 @@ func ListClusterRoles(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
func ListRoles(req *restful.Request, resp *restful.Response) {
|
||||
namespace := req.PathParameter("namespace")
|
||||
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)
|
||||
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, resources.CreateTime)
|
||||
limit, offset := params.ParsePaging(req)
|
||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||
conditions, err := params.ParseConditions(req)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
@@ -161,10 +162,10 @@ func ListClusterRoleRules(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
func ListClusterRoleUsers(req *restful.Request, resp *restful.Response) {
|
||||
clusterRoleName := req.PathParameter("clusterrole")
|
||||
conditions, err := params.ParseConditions(req.QueryParameter(params.ConditionsParam))
|
||||
conditions, err := params.ParseConditions(req)
|
||||
orderBy := req.QueryParameter(params.OrderByParam)
|
||||
limit, offset := params.ParsePaging(req.QueryParameter(params.PagingParam))
|
||||
reverse := params.ParseReverse(req)
|
||||
limit, offset := params.ParsePaging(req)
|
||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
|
||||
@@ -20,6 +20,7 @@ package iam
|
||||
import (
|
||||
"fmt"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"net/http"
|
||||
"net/mail"
|
||||
@@ -149,14 +150,21 @@ func UpdateUser(req *restful.Request, resp *restful.Response) {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
|
||||
return
|
||||
}
|
||||
if !isUserManager {
|
||||
_, err = iam.Login(usernameInHeader, user.CurrentPassword, "")
|
||||
}
|
||||
if err != nil {
|
||||
err = fmt.Errorf("incorrect current password")
|
||||
klog.Info(err)
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
return
|
||||
|
||||
// user manager can modify password without verify old password
|
||||
// if the old password is defined must be verified
|
||||
if !isUserManager || user.CurrentPassword != "" {
|
||||
if _, err = iam.Login(usernameInHeader, user.CurrentPassword, ""); err != nil {
|
||||
if ldap.IsErrorWithCode(err, ldap.LDAPResultInvalidCredentials) {
|
||||
err = fmt.Errorf("incorrect current password")
|
||||
klog.V(4).Info(err)
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
} else {
|
||||
klog.Errorln(err)
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,15 +289,16 @@ func Precheck(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
func ListUsers(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
if check := req.QueryParameter("check"); check != "" {
|
||||
// TODO use dry-run instead
|
||||
if check := params.GetBoolValueWithDefault(req, "check", false); check {
|
||||
Precheck(req, resp)
|
||||
return
|
||||
}
|
||||
|
||||
limit, offset := params.ParsePaging(req.QueryParameter(params.PagingParam))
|
||||
conditions, err := params.ParseConditions(req.QueryParameter(params.ConditionsParam))
|
||||
orderBy := req.QueryParameter(params.OrderByParam)
|
||||
reverse := params.ParseReverse(req)
|
||||
limit, offset := params.ParsePaging(req)
|
||||
conditions, err := params.ParseConditions(req)
|
||||
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, resources.CreateTime)
|
||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||
|
||||
if err != nil {
|
||||
klog.Info(err)
|
||||
|
||||
@@ -32,10 +32,10 @@ import (
|
||||
func ListWorkspaceRoles(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
workspace := req.PathParameter("workspace")
|
||||
conditions, err := params.ParseConditions(req.QueryParameter(params.ConditionsParam))
|
||||
conditions, err := params.ParseConditions(req)
|
||||
orderBy := req.QueryParameter(params.OrderByParam)
|
||||
limit, offset := params.ParsePaging(req.QueryParameter(params.PagingParam))
|
||||
reverse := params.ParseReverse(req)
|
||||
limit, offset := params.ParsePaging(req)
|
||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
@@ -145,10 +145,10 @@ func RemoveUser(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
func ListWorkspaceUsers(req *restful.Request, resp *restful.Response) {
|
||||
workspace := req.PathParameter("workspace")
|
||||
conditions, err := params.ParseConditions(req.QueryParameter(params.ConditionsParam))
|
||||
conditions, err := params.ParseConditions(req)
|
||||
orderBy := req.QueryParameter(params.OrderByParam)
|
||||
limit, offset := params.ParsePaging(req.QueryParameter(params.PagingParam))
|
||||
reverse := params.ParseReverse(req)
|
||||
limit, offset := params.ParsePaging(req)
|
||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
|
||||
@@ -36,22 +36,18 @@ import (
|
||||
)
|
||||
|
||||
func ListApplications(req *restful.Request, resp *restful.Response) {
|
||||
limit, offset := params.ParsePaging(req.QueryParameter(params.PagingParam))
|
||||
limit, offset := params.ParsePaging(req)
|
||||
namespaceName := req.PathParameter("namespace")
|
||||
conditions, err := params.ParseConditions(req.QueryParameter(params.ConditionsParam))
|
||||
orderBy := req.QueryParameter(params.OrderByParam)
|
||||
reverse := params.ParseReverse(req)
|
||||
|
||||
if orderBy == "" {
|
||||
orderBy = "create_time"
|
||||
reverse = true
|
||||
}
|
||||
conditions, err := params.ParseConditions(req)
|
||||
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.CreateTime)
|
||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
return
|
||||
}
|
||||
|
||||
// filter namespaced applications by runtime_id
|
||||
if namespaceName != "" {
|
||||
namespace, err := resources.GetResource("", resources.Namespaces, namespaceName)
|
||||
|
||||
@@ -60,6 +56,7 @@ func ListApplications(req *restful.Request, resp *restful.Response) {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
|
||||
return
|
||||
}
|
||||
|
||||
var runtimeId string
|
||||
|
||||
if ns, ok := namespace.(*v1.Namespace); ok {
|
||||
@@ -70,7 +67,7 @@ func ListApplications(req *restful.Request, resp *restful.Response) {
|
||||
resp.WriteAsJson(models.PageableResponse{Items: []interface{}{}, TotalCount: 0})
|
||||
return
|
||||
} else {
|
||||
conditions.Match["runtime_id"] = runtimeId
|
||||
conditions.Match[openpitrix.RuntimeId] = runtimeId
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -143,23 +143,19 @@ func GetAppVersionFiles(req *restful.Request, resp *restful.Response) {
|
||||
}
|
||||
|
||||
func ListAppVersionAudits(req *restful.Request, resp *restful.Response) {
|
||||
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)
|
||||
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.StatusTime)
|
||||
limit, offset := params.ParsePaging(req)
|
||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||
appId := req.PathParameter("app")
|
||||
versionId := req.PathParameter("version")
|
||||
if orderBy == "" {
|
||||
orderBy = "status_time"
|
||||
reverse = true
|
||||
}
|
||||
conditions, err := params.ParseConditions(req)
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
return
|
||||
}
|
||||
conditions.Match["app"] = appId
|
||||
conditions.Match[openpitrix.AppId] = appId
|
||||
if versionId != "" {
|
||||
conditions.Match["version"] = versionId
|
||||
conditions.Match[openpitrix.VersionId] = versionId
|
||||
}
|
||||
|
||||
result, err := openpitrix.ListAppVersionAudits(conditions, orderBy, reverse, limit, offset)
|
||||
@@ -179,14 +175,11 @@ func ListAppVersionAudits(req *restful.Request, resp *restful.Response) {
|
||||
}
|
||||
|
||||
func ListReviews(req *restful.Request, resp *restful.Response) {
|
||||
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 = "status_time"
|
||||
reverse = true
|
||||
}
|
||||
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.StatusTime)
|
||||
limit, offset := params.ParsePaging(req)
|
||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||
conditions, err := params.ParseConditions(req)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
return
|
||||
@@ -209,21 +202,17 @@ func ListReviews(req *restful.Request, resp *restful.Response) {
|
||||
}
|
||||
|
||||
func ListAppVersions(req *restful.Request, resp *restful.Response) {
|
||||
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)
|
||||
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.CreateTime)
|
||||
limit, offset := params.ParsePaging(req)
|
||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||
appId := req.PathParameter("app")
|
||||
statistics, _ := strconv.ParseBool(req.QueryParameter("statistics"))
|
||||
if orderBy == "" {
|
||||
orderBy = "create_time"
|
||||
reverse = true
|
||||
}
|
||||
statistics := params.GetBoolValueWithDefault(req, "statistics", false)
|
||||
conditions, err := params.ParseConditions(req)
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
return
|
||||
}
|
||||
conditions.Match["app"] = appId
|
||||
conditions.Match[openpitrix.AppId] = appId
|
||||
|
||||
result, err := openpitrix.ListAppVersions(conditions, orderBy, reverse, limit, offset)
|
||||
|
||||
@@ -241,7 +230,7 @@ func ListAppVersions(req *restful.Request, resp *restful.Response) {
|
||||
if statistics {
|
||||
for _, item := range result.Items {
|
||||
if version, ok := item.(*openpitrix.AppVersion); ok {
|
||||
statisticsResult, err := openpitrix.ListApplications(¶ms.Conditions{Match: map[string]string{"app_id": version.AppId, "version_id": version.VersionId}}, 0, 0, "", false)
|
||||
statisticsResult, err := openpitrix.ListApplications(¶ms.Conditions{Match: map[string]string{openpitrix.AppId: version.AppId, openpitrix.VersionId: version.VersionId}}, 0, 0, "", false)
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
|
||||
@@ -256,15 +245,11 @@ func ListAppVersions(req *restful.Request, resp *restful.Response) {
|
||||
}
|
||||
|
||||
func ListApps(req *restful.Request, resp *restful.Response) {
|
||||
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)
|
||||
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.CreateTime)
|
||||
limit, offset := params.ParsePaging(req)
|
||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||
statistics, _ := strconv.ParseBool(req.QueryParameter("statistics"))
|
||||
if orderBy == "" {
|
||||
orderBy = "create_time"
|
||||
reverse = true
|
||||
}
|
||||
conditions, err := params.ParseConditions(req)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
@@ -288,7 +273,7 @@ func ListApps(req *restful.Request, resp *restful.Response) {
|
||||
for _, item := range result.Items {
|
||||
if app, ok := item.(*openpitrix.App); ok {
|
||||
status := "active|used|enabled|stopped|pending|creating|upgrading|updating|rollbacking|stopping|starting|recovering|resizing|scaling|deleting"
|
||||
statisticsResult, err := openpitrix.ListApplications(¶ms.Conditions{Match: map[string]string{"app_id": app.AppId, "status": status}}, 0, 0, "", false)
|
||||
statisticsResult, err := openpitrix.ListApplications(¶ms.Conditions{Match: map[string]string{openpitrix.AppId: app.AppId, openpitrix.Status: status}}, 0, 0, "", false)
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
|
||||
@@ -394,7 +379,7 @@ func CreateApp(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
createAppRequest.Username = req.HeaderParameter(constants.UserNameHeader)
|
||||
|
||||
validate, _ := strconv.ParseBool(req.QueryParameter("validate"))
|
||||
validate := params.GetBoolValueWithDefault(req, "validate", false)
|
||||
|
||||
var result interface{}
|
||||
|
||||
@@ -437,7 +422,7 @@ func CreateAppVersion(req *restful.Request, resp *restful.Response) {
|
||||
createAppVersionRequest.AppId = req.PathParameter("app")
|
||||
createAppVersionRequest.Username = req.HeaderParameter(constants.UserNameHeader)
|
||||
|
||||
validate, _ := strconv.ParseBool(req.QueryParameter("validate"))
|
||||
validate := params.GetBoolValueWithDefault(req, "validate", false)
|
||||
|
||||
var result interface{}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func CreateCategory(req *restful.Request, resp *restful.Response) {
|
||||
@@ -125,15 +124,11 @@ func DescribeCategory(req *restful.Request, resp *restful.Response) {
|
||||
resp.WriteEntity(result)
|
||||
}
|
||||
func ListCategories(req *restful.Request, resp *restful.Response) {
|
||||
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 = "create_time"
|
||||
reverse = true
|
||||
}
|
||||
statistics, _ := strconv.ParseBool(req.QueryParameter("statistics"))
|
||||
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.CreateTime)
|
||||
limit, offset := params.ParsePaging(req)
|
||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||
statistics := params.GetBoolValueWithDefault(req, "statistics", false)
|
||||
conditions, err := params.ParseConditions(req)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
@@ -156,7 +151,7 @@ func ListCategories(req *restful.Request, resp *restful.Response) {
|
||||
if statistics {
|
||||
for _, item := range result.Items {
|
||||
if category, ok := item.(*openpitrix.Category); ok {
|
||||
statisticsResult, err := openpitrix.ListApps(¶ms.Conditions{Match: map[string]string{"category_id": category.CategoryID, "status": openpitrix.StatusActive, "repo": openpitrix.BuiltinRepoId}}, "", false, 0, 0)
|
||||
statisticsResult, err := openpitrix.ListApps(¶ms.Conditions{Match: map[string]string{openpitrix.CategoryId: category.CategoryID, openpitrix.Status: openpitrix.StatusActive, openpitrix.RepoId: openpitrix.BuiltinRepoId}}, "", false, 0, 0)
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
|
||||
|
||||
@@ -165,14 +165,10 @@ func DescribeRepo(req *restful.Request, resp *restful.Response) {
|
||||
resp.WriteEntity(result)
|
||||
}
|
||||
func ListRepos(req *restful.Request, resp *restful.Response) {
|
||||
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 = "create_time"
|
||||
reverse = true
|
||||
}
|
||||
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, openpitrix.CreateTime)
|
||||
limit, offset := params.ParsePaging(req)
|
||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||
conditions, err := params.ParseConditions(req)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
@@ -197,8 +193,8 @@ func ListRepos(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
func ListRepoEvents(req *restful.Request, resp *restful.Response) {
|
||||
repoId := req.PathParameter("repo")
|
||||
conditions, err := params.ParseConditions(req.QueryParameter(params.ConditionsParam))
|
||||
limit, offset := params.ParsePaging(req.QueryParameter(params.PagingParam))
|
||||
limit, offset := params.ParsePaging(req)
|
||||
conditions, err := params.ParseConditions(req)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
|
||||
@@ -21,6 +21,7 @@ package registries
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/models/registries"
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
@@ -68,6 +69,25 @@ func RegistryImageBlob(request *restful.Request, response *restful.Response) {
|
||||
return
|
||||
}
|
||||
|
||||
// default use ssl
|
||||
checkSSl := func(serverAddress string) bool {
|
||||
if strings.HasPrefix(serverAddress, "http://") {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(imageName, "http") {
|
||||
dockerurl, err := registries.ParseDockerURL(imageName)
|
||||
if err != nil {
|
||||
log.Errorf("%+v", err)
|
||||
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), response)
|
||||
return
|
||||
}
|
||||
imageName = dockerurl.StringWithoutScheme()
|
||||
}
|
||||
|
||||
// parse image
|
||||
image, err := registries.ParseImage(imageName)
|
||||
if err != nil {
|
||||
@@ -76,8 +96,10 @@ func RegistryImageBlob(request *restful.Request, response *restful.Response) {
|
||||
return
|
||||
}
|
||||
|
||||
useSSL := checkSSl(entry.ServerAddress)
|
||||
|
||||
// Create the registry client.
|
||||
r, err := registries.CreateRegistryClient(entry.Username, entry.Password, image.Domain)
|
||||
r, err := registries.CreateRegistryClient(entry.Username, entry.Password, image.Domain, useSSL)
|
||||
if err != nil {
|
||||
log.Errorf("%+v", err)
|
||||
response.WriteAsJson(®istries.ImageDetails{Status: registries.StatusFailed, Message: err.Error()})
|
||||
|
||||
@@ -33,15 +33,10 @@ func ListNamespacedResources(req *restful.Request, resp *restful.Response) {
|
||||
func ListResources(req *restful.Request, resp *restful.Response) {
|
||||
namespace := req.PathParameter("namespace")
|
||||
resourceName := req.PathParameter("resources")
|
||||
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 = resources.CreateTime
|
||||
reverse = true
|
||||
}
|
||||
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, resources.CreateTime)
|
||||
limit, offset := params.ParsePaging(req)
|
||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||
conditions, err := params.ParseConditions(req)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
|
||||
@@ -20,8 +20,10 @@ package resources
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/klog"
|
||||
"net/http"
|
||||
|
||||
storagev1 "k8s.io/api/storage/v1"
|
||||
"kubesphere.io/kubesphere/pkg/models/storage"
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
)
|
||||
@@ -69,3 +71,26 @@ func GetPvcListBySc(request *restful.Request, response *restful.Response) {
|
||||
|
||||
response.WriteAsJson(result)
|
||||
}
|
||||
|
||||
func PatchStorageClass(request *restful.Request, response *restful.Response) {
|
||||
scObj := &storagev1.StorageClass{}
|
||||
err := request.ReadEntity(scObj)
|
||||
if err != nil {
|
||||
klog.Errorf("read entity error: %s", err.Error())
|
||||
response.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
return
|
||||
}
|
||||
klog.V(5).Infof("succeed to read entity %v", scObj)
|
||||
scName := request.PathParameter("storageclass")
|
||||
if scObj.Annotations[storage.IsDefaultStorageClassAnnotation] == "true" {
|
||||
// Set default storage class
|
||||
sc, err := storage.SetDefaultStorageClass(scName)
|
||||
if err != nil {
|
||||
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
|
||||
return
|
||||
}
|
||||
response.WriteEntity(sc)
|
||||
return
|
||||
}
|
||||
response.WriteEntity(errors.None)
|
||||
}
|
||||
|
||||
@@ -58,15 +58,10 @@ func ListWorkspaceRules(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
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 = resources.CreateTime
|
||||
reverse = true
|
||||
}
|
||||
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, resources.CreateTime)
|
||||
limit, offset := params.ParsePaging(req)
|
||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||
conditions, err := params.ParseConditions(req)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
@@ -114,10 +109,10 @@ func ListNamespaces(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)
|
||||
conditions, err := params.ParseConditions(req)
|
||||
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, resources.CreateTime)
|
||||
limit, offset := params.ParsePaging(req)
|
||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||
@@ -223,9 +218,9 @@ func ListDevopsProjects(req *restful.Request, resp *restful.Response) {
|
||||
username = req.HeaderParameter(constants.UserNameHeader)
|
||||
}
|
||||
orderBy := req.QueryParameter(params.OrderByParam)
|
||||
reverse := params.ParseReverse(req)
|
||||
limit, offset := params.ParsePaging(req.QueryParameter(params.PagingParam))
|
||||
conditions, err := params.ParseConditions(req.QueryParameter(params.ConditionsParam))
|
||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||
limit, offset := params.ParsePaging(req)
|
||||
conditions, err := params.ParseConditions(req)
|
||||
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
|
||||
@@ -17,7 +17,7 @@ limitations under the License.
|
||||
package controller
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/application/pkg/controller/application"
|
||||
application "sigs.k8s.io/application/controllers"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -4,9 +4,6 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
applicationclient "github.com/kubernetes-sigs/application/pkg/client/clientset/versioned"
|
||||
applicationinformers "github.com/kubernetes-sigs/application/pkg/client/informers/externalversions/app/v1beta1"
|
||||
applicationlister "github.com/kubernetes-sigs/application/pkg/client/listers/app/v1beta1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -27,6 +24,9 @@ import (
|
||||
servicemeshinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/servicemesh/v1alpha2"
|
||||
servicemeshlisters "kubesphere.io/kubesphere/pkg/client/listers/servicemesh/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/controller/virtualservice/util"
|
||||
applicationclient "sigs.k8s.io/application/pkg/client/clientset/versioned"
|
||||
applicationinformers "sigs.k8s.io/application/pkg/client/informers/externalversions/app/v1beta1"
|
||||
applicationlister "sigs.k8s.io/application/pkg/client/listers/app/v1beta1"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -20,7 +20,6 @@ package clusterrolebinding
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -29,6 +28,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
log "k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam"
|
||||
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
|
||||
"reflect"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
@@ -99,8 +99,8 @@ func (r *ReconcileClusterRoleBinding) Reconcile(request reconcile.Request) (reco
|
||||
workspaceName := instance.Labels[constants.WorkspaceLabelKey]
|
||||
|
||||
if workspaceName != "" && k8sutil.IsControlledBy(instance.OwnerReferences, "Workspace", workspaceName) {
|
||||
if instance.Name == getWorkspaceAdminRoleBindingName(workspaceName) ||
|
||||
instance.Name == getWorkspaceViewerRoleBindingName(workspaceName) {
|
||||
if instance.Name == iam.GetWorkspaceAdminRoleBindingName(workspaceName) ||
|
||||
instance.Name == iam.GetWorkspaceViewerRoleBindingName(workspaceName) {
|
||||
nsList := &corev1.NamespaceList{}
|
||||
options := client.ListOptions{LabelSelector: labels.SelectorFromSet(labels.Set{constants.WorkspaceLabelKey: workspaceName})}
|
||||
|
||||
@@ -121,100 +121,60 @@ func (r *ReconcileClusterRoleBinding) Reconcile(request reconcile.Request) (reco
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
|
||||
func (r *ReconcileClusterRoleBinding) updateRoleBindings(clusterRoleBinding *rbac.ClusterRoleBinding, namespace *corev1.Namespace) error {
|
||||
|
||||
workspaceName := namespace.Labels[constants.WorkspaceLabelKey]
|
||||
|
||||
if clusterRoleBinding.Name == getWorkspaceAdminRoleBindingName(workspaceName) {
|
||||
adminBinding := &rbac.RoleBinding{}
|
||||
adminBinding.Name = "admin"
|
||||
adminBinding.Namespace = namespace.Name
|
||||
adminBinding.RoleRef = rbac.RoleRef{Name: "admin", APIGroup: "rbac.authorization.k8s.io", Kind: "Role"}
|
||||
adminBinding.Subjects = clusterRoleBinding.Subjects
|
||||
|
||||
found := &rbac.RoleBinding{}
|
||||
|
||||
err := r.Get(context.TODO(), types.NamespacedName{Namespace: namespace.Name, Name: adminBinding.Name}, found)
|
||||
|
||||
func (r *ReconcileClusterRoleBinding) createRoleBindingsIfNotExist(roleBinding *rbac.RoleBinding) error {
|
||||
found := &rbac.RoleBinding{}
|
||||
if err := r.Get(context.TODO(), types.NamespacedName{Namespace: roleBinding.Namespace, Name: roleBinding.Name}, found); err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
err = r.Create(context.TODO(), adminBinding)
|
||||
err := r.Create(context.TODO(), roleBinding)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
log.Errorln(err)
|
||||
}
|
||||
return err
|
||||
} else if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(found.RoleRef, adminBinding.RoleRef) {
|
||||
err = r.Delete(context.TODO(), found)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("conflict role binding %s.%s, waiting for recreate", namespace.Name, adminBinding.Name)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(found.Subjects, adminBinding.Subjects) {
|
||||
found.Subjects = adminBinding.Subjects
|
||||
err = r.Update(context.TODO(), found)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if clusterRoleBinding.Name == getWorkspaceViewerRoleBindingName(workspaceName) {
|
||||
|
||||
found := &rbac.RoleBinding{}
|
||||
|
||||
viewerBinding := &rbac.RoleBinding{}
|
||||
viewerBinding.Name = "viewer"
|
||||
viewerBinding.Namespace = namespace.Name
|
||||
viewerBinding.RoleRef = rbac.RoleRef{Name: "viewer", APIGroup: "rbac.authorization.k8s.io", Kind: "Role"}
|
||||
viewerBinding.Subjects = clusterRoleBinding.Subjects
|
||||
|
||||
err := r.Get(context.TODO(), types.NamespacedName{Namespace: namespace.Name, Name: viewerBinding.Name}, found)
|
||||
|
||||
if errors.IsNotFound(err) {
|
||||
err = r.Create(context.TODO(), viewerBinding)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
if !reflect.DeepEqual(found.Subjects, roleBinding.Subjects) {
|
||||
found.Subjects = roleBinding.Subjects
|
||||
if err := r.Update(context.TODO(), found); err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
} else if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(found.RoleRef, viewerBinding.RoleRef) {
|
||||
err = r.Delete(context.TODO(), found)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("conflict role binding %s.%s, waiting for recreate", namespace.Name, viewerBinding.Name)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(found.Subjects, viewerBinding.Subjects) {
|
||||
found.Subjects = viewerBinding.Subjects
|
||||
err = r.Update(context.TODO(), found)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getWorkspaceAdminRoleBindingName(workspaceName string) string {
|
||||
return fmt.Sprintf("workspace:%s:admin", workspaceName)
|
||||
}
|
||||
func (r *ReconcileClusterRoleBinding) updateRoleBindings(clusterRoleBinding *rbac.ClusterRoleBinding, namespace *corev1.Namespace) error {
|
||||
|
||||
func getWorkspaceViewerRoleBindingName(workspaceName string) string {
|
||||
return fmt.Sprintf("workspace:%s:viewer", workspaceName)
|
||||
workspaceName := namespace.Labels[constants.WorkspaceLabelKey]
|
||||
|
||||
if clusterRoleBinding.Name == iam.GetWorkspaceAdminRoleBindingName(workspaceName) {
|
||||
adminBinding := &rbac.RoleBinding{}
|
||||
adminBinding.Name = iam.NamespaceAdminRoleBindName
|
||||
adminBinding.Namespace = namespace.Name
|
||||
adminBinding.RoleRef = rbac.RoleRef{Name: iam.NamespaceAdminRoleName, APIGroup: "rbac.authorization.k8s.io", Kind: iam.RoleKind}
|
||||
adminBinding.Subjects = clusterRoleBinding.Subjects
|
||||
|
||||
if err := r.createRoleBindingsIfNotExist(adminBinding); err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if clusterRoleBinding.Name == iam.GetWorkspaceViewerRoleBindingName(workspaceName) {
|
||||
viewerBinding := &rbac.RoleBinding{}
|
||||
viewerBinding.Name = iam.NamespaceViewerRoleBindName
|
||||
viewerBinding.Namespace = namespace.Name
|
||||
viewerBinding.RoleRef = rbac.RoleRef{Name: iam.NamespaceViewerRoleName, APIGroup: "rbac.authorization.k8s.io", Kind: iam.RoleKind}
|
||||
viewerBinding.Subjects = clusterRoleBinding.Subjects
|
||||
|
||||
if err := r.createRoleBindingsIfNotExist(viewerBinding); err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@ import (
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam"
|
||||
cs "kubesphere.io/kubesphere/pkg/simple/client"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
|
||||
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"openpitrix.io/openpitrix/pkg/pb"
|
||||
"reflect"
|
||||
@@ -54,12 +54,12 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
admin = rbac.Role{ObjectMeta: metav1.ObjectMeta{Name: "admin", Annotations: map[string]string{constants.DescriptionAnnotationKey: adminDescription, constants.CreatorAnnotationKey: constants.System}}, Rules: []rbac.PolicyRule{{Verbs: []string{"*"}, APIGroups: []string{"*"}, Resources: []string{"*"}}}}
|
||||
operator = rbac.Role{ObjectMeta: metav1.ObjectMeta{Name: "operator", Annotations: map[string]string{constants.DescriptionAnnotationKey: operatorDescription, constants.CreatorAnnotationKey: constants.System}}, Rules: []rbac.PolicyRule{{Verbs: []string{"get", "list", "watch"}, APIGroups: []string{"*"}, Resources: []string{"*"}},
|
||||
admin = rbac.Role{ObjectMeta: metav1.ObjectMeta{Name: iam.NamespaceAdminRoleName, Annotations: map[string]string{constants.DescriptionAnnotationKey: adminDescription, constants.CreatorAnnotationKey: constants.System}}, Rules: []rbac.PolicyRule{{Verbs: []string{"*"}, APIGroups: []string{"*"}, Resources: []string{"*"}}}}
|
||||
operator = rbac.Role{ObjectMeta: metav1.ObjectMeta{Name: iam.NamespaceOperatorRoleName, Annotations: map[string]string{constants.DescriptionAnnotationKey: operatorDescription, constants.CreatorAnnotationKey: constants.System}}, Rules: []rbac.PolicyRule{{Verbs: []string{"get", "list", "watch"}, APIGroups: []string{"*"}, Resources: []string{"*"}},
|
||||
{Verbs: []string{"*"}, APIGroups: []string{"apps", "extensions", "batch", "logging.kubesphere.io", "monitoring.kubesphere.io", "iam.kubesphere.io", "autoscaling", "alerting.kubesphere.io", "openpitrix.io", "app.k8s.io", "servicemesh.kubesphere.io", "operations.kubesphere.io", "devops.kubesphere.io"}, Resources: []string{"*"}},
|
||||
{Verbs: []string{"*"}, APIGroups: []string{"", "resources.kubesphere.io"}, Resources: []string{"jobs", "cronjobs", "daemonsets", "deployments", "horizontalpodautoscalers", "ingresses", "endpoints", "configmaps", "events", "persistentvolumeclaims", "pods", "podtemplates", "pods", "secrets", "services"}},
|
||||
}}
|
||||
viewer = rbac.Role{ObjectMeta: metav1.ObjectMeta{Name: "viewer", Annotations: map[string]string{constants.DescriptionAnnotationKey: viewerDescription, constants.CreatorAnnotationKey: constants.System}}, Rules: []rbac.PolicyRule{{Verbs: []string{"get", "list", "watch"}, APIGroups: []string{"*"}, Resources: []string{"*"}}}}
|
||||
viewer = rbac.Role{ObjectMeta: metav1.ObjectMeta{Name: iam.NamespaceViewerRoleName, Annotations: map[string]string{constants.DescriptionAnnotationKey: viewerDescription, constants.CreatorAnnotationKey: constants.System}}, Rules: []rbac.PolicyRule{{Verbs: []string{"get", "list", "watch"}, APIGroups: []string{"*"}, Resources: []string{"*"}}}}
|
||||
defaultRoles = []rbac.Role{admin, operator, viewer}
|
||||
)
|
||||
|
||||
@@ -170,9 +170,15 @@ func (r *ReconcileNamespace) Reconcile(request reconcile.Request) (reconcile.Res
|
||||
|
||||
if !controlledByWorkspace {
|
||||
|
||||
err = r.deleteRoleBindings(instance)
|
||||
if err = r.unbindWorkspace(instance); err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
return reconcile.Result{}, err
|
||||
if err = r.deleteRoleBindings(instance); err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
|
||||
if err = r.checkAndBindWorkspace(instance); err != nil {
|
||||
@@ -220,6 +226,7 @@ func (r *ReconcileNamespace) checkAndCreateRoles(namespace *corev1.Namespace) er
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
found = role
|
||||
} else {
|
||||
klog.Error(err)
|
||||
return err
|
||||
@@ -236,119 +243,84 @@ func (r *ReconcileNamespace) checkAndCreateRoles(namespace *corev1.Namespace) er
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ReconcileNamespace) createRoleBindingsIfNotExist(roleBinding *rbac.RoleBinding) error {
|
||||
found := &rbac.RoleBinding{}
|
||||
if err := r.Get(context.TODO(), types.NamespacedName{Namespace: roleBinding.Namespace, Name: roleBinding.Name}, found); err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
err := r.Create(context.TODO(), roleBinding)
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
klog.Errorln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(found.Subjects, roleBinding.Subjects) {
|
||||
found.Subjects = roleBinding.Subjects
|
||||
if err := r.Update(context.TODO(), found); err != nil {
|
||||
klog.Errorln(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ReconcileNamespace) checkAndCreateRoleBindings(namespace *corev1.Namespace) error {
|
||||
|
||||
workspaceName := namespace.Labels[constants.WorkspaceLabelKey]
|
||||
creatorName := namespace.Annotations[constants.CreatorAnnotationKey]
|
||||
|
||||
creator := rbac.Subject{APIGroup: "rbac.authorization.k8s.io", Kind: "User", Name: creatorName}
|
||||
if creatorName != "" {
|
||||
creatorRoleBinding := &rbac.RoleBinding{}
|
||||
creatorRoleBinding.Name = fmt.Sprintf("%s-%s", admin.Name, creatorName)
|
||||
creatorRoleBinding.Namespace = namespace.Name
|
||||
creatorRoleBinding.RoleRef = rbac.RoleRef{Name: admin.Name, APIGroup: "rbac.authorization.k8s.io", Kind: "Role"}
|
||||
creatorRoleBinding.Subjects = []rbac.Subject{{APIGroup: "rbac.authorization.k8s.io", Kind: "User", Name: creatorName}}
|
||||
if err := r.createRoleBindingsIfNotExist(creatorRoleBinding); err != nil {
|
||||
klog.Errorln(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
workspaceAdminBinding := &rbac.ClusterRoleBinding{}
|
||||
|
||||
err := r.Get(context.TODO(), types.NamespacedName{Name: fmt.Sprintf("workspace:%s:admin", workspaceName)}, workspaceAdminBinding)
|
||||
|
||||
if err != nil {
|
||||
if err := r.Get(context.TODO(), types.NamespacedName{Name: iam.GetWorkspaceAdminRoleBindingName(workspaceName)}, workspaceAdminBinding); err != nil {
|
||||
klog.Errorln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
adminBinding := &rbac.RoleBinding{}
|
||||
adminBinding.Name = admin.Name
|
||||
adminBinding.Name = iam.NamespaceAdminRoleBindName
|
||||
adminBinding.Namespace = namespace.Name
|
||||
adminBinding.RoleRef = rbac.RoleRef{Name: admin.Name, APIGroup: "rbac.authorization.k8s.io", Kind: "Role"}
|
||||
adminBinding.RoleRef = rbac.RoleRef{Name: admin.Name, APIGroup: "rbac.authorization.k8s.io", Kind: iam.RoleKind}
|
||||
adminBinding.Subjects = workspaceAdminBinding.Subjects
|
||||
|
||||
if creator.Name != "" {
|
||||
if adminBinding.Subjects == nil {
|
||||
adminBinding.Subjects = make([]rbac.Subject, 0)
|
||||
}
|
||||
if !k8sutil.ContainsUser(adminBinding.Subjects, creatorName) {
|
||||
adminBinding.Subjects = append(adminBinding.Subjects, creator)
|
||||
}
|
||||
}
|
||||
|
||||
found := &rbac.RoleBinding{}
|
||||
|
||||
err = r.Get(context.TODO(), types.NamespacedName{Namespace: namespace.Name, Name: adminBinding.Name}, found)
|
||||
|
||||
if errors.IsNotFound(err) {
|
||||
err = r.Create(context.TODO(), adminBinding)
|
||||
if err != nil {
|
||||
klog.Errorf("creating role binding namespace: %s,role binding: %s, error: %s", namespace.Name, adminBinding.Name, err)
|
||||
return err
|
||||
}
|
||||
found = adminBinding
|
||||
} else if err != nil {
|
||||
klog.Errorf("get role binding namespace: %s,role binding: %s, error: %s", namespace.Name, adminBinding.Name, err)
|
||||
if err := r.createRoleBindingsIfNotExist(adminBinding); err != nil {
|
||||
klog.Errorln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(found.RoleRef, adminBinding.RoleRef) {
|
||||
err = r.Delete(context.TODO(), found)
|
||||
if err != nil {
|
||||
klog.Errorf("deleting role binding namespace: %s, role binding: %s, error: %s", namespace.Name, adminBinding.Name, err)
|
||||
return err
|
||||
}
|
||||
err = fmt.Errorf("conflict role binding %s.%s, waiting for recreate", namespace.Name, adminBinding.Name)
|
||||
klog.Errorf("conflict role binding namespace: %s, role binding: %s, error: %s", namespace.Name, adminBinding.Name, err)
|
||||
return err
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(found.Subjects, adminBinding.Subjects) {
|
||||
found.Subjects = adminBinding.Subjects
|
||||
err = r.Update(context.TODO(), found)
|
||||
if err != nil {
|
||||
klog.Errorf("updating role binding namespace: %s, role binding: %s, error: %s", namespace.Name, adminBinding.Name, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
workspaceViewerBinding := &rbac.ClusterRoleBinding{}
|
||||
|
||||
err = r.Get(context.TODO(), types.NamespacedName{Name: fmt.Sprintf("workspace:%s:viewer", workspaceName)}, workspaceViewerBinding)
|
||||
|
||||
if err != nil {
|
||||
if err := r.Get(context.TODO(), types.NamespacedName{Name: iam.GetWorkspaceViewerRoleBindingName(workspaceName)}, workspaceViewerBinding); err != nil {
|
||||
klog.Errorln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
viewerBinding := &rbac.RoleBinding{}
|
||||
viewerBinding.Name = viewer.Name
|
||||
viewerBinding.Name = iam.NamespaceViewerRoleBindName
|
||||
viewerBinding.Namespace = namespace.Name
|
||||
viewerBinding.RoleRef = rbac.RoleRef{Name: viewer.Name, APIGroup: "rbac.authorization.k8s.io", Kind: "Role"}
|
||||
viewerBinding.RoleRef = rbac.RoleRef{Name: viewer.Name, APIGroup: "rbac.authorization.k8s.io", Kind: iam.RoleKind}
|
||||
viewerBinding.Subjects = workspaceViewerBinding.Subjects
|
||||
|
||||
err = r.Get(context.TODO(), types.NamespacedName{Namespace: namespace.Name, Name: viewerBinding.Name}, found)
|
||||
|
||||
if errors.IsNotFound(err) {
|
||||
err = r.Create(context.TODO(), viewerBinding)
|
||||
if err != nil {
|
||||
klog.Errorf("creating role binding namespace: %s, role binding: %s, error: %s", namespace.Name, viewerBinding.Name, err)
|
||||
return err
|
||||
}
|
||||
found = viewerBinding
|
||||
} else if err != nil {
|
||||
if err := r.createRoleBindingsIfNotExist(viewerBinding); err != nil {
|
||||
klog.Errorln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(found.RoleRef, viewerBinding.RoleRef) {
|
||||
err = r.Delete(context.TODO(), found)
|
||||
if err != nil {
|
||||
klog.Errorf("deleting conflict role binding namespace: %s, role binding: %s, %s", namespace.Name, viewerBinding.Name, err)
|
||||
return err
|
||||
}
|
||||
err = fmt.Errorf("conflict role binding %s.%s, waiting for recreate", namespace.Name, viewerBinding.Name)
|
||||
klog.Errorf("conflict role binding namespace: %s, role binding: %s, error: %s", namespace.Name, viewerBinding.Name, err)
|
||||
return err
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(found.Subjects, viewerBinding.Subjects) {
|
||||
found.Subjects = viewerBinding.Subjects
|
||||
err = r.Update(context.TODO(), found)
|
||||
if err != nil {
|
||||
klog.Errorf("updating role binding namespace: %s, role binding: %s, error: %s", namespace.Name, viewerBinding.Name, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -451,6 +423,21 @@ func (r *ReconcileNamespace) deleteRuntime(namespace *corev1.Namespace) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
func (r *ReconcileNamespace) unbindWorkspace(instance *corev1.Namespace) error {
|
||||
ownerReferences := make([]metav1.OwnerReference, 0)
|
||||
|
||||
for _, ref := range instance.OwnerReferences {
|
||||
if ref.Kind != v1alpha1.ResourceKindWorkspace {
|
||||
ownerReferences = append(ownerReferences, ref)
|
||||
}
|
||||
}
|
||||
|
||||
if len(ownerReferences) != len(instance.OwnerReferences) {
|
||||
instance.OwnerReferences = ownerReferences
|
||||
return r.Update(context.TODO(), instance)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create openpitrix runtime
|
||||
func (r *ReconcileNamespace) checkAndBindWorkspace(namespace *corev1.Namespace) error {
|
||||
|
||||
@@ -530,7 +530,7 @@ func (j *Jenkins) CreateSshCredential(id, username, passphrase, privateKey, desc
|
||||
requestStruct := NewCreateSshCredentialRequest(id, username, passphrase, privateKey, description)
|
||||
param := map[string]string{"json": makeJson(requestStruct)}
|
||||
responseString := ""
|
||||
response, err := j.Requester.Post("/credentials/store/system/domain/_/createCredentials",
|
||||
response, err := j.Requester.PostForm("/credentials/store/system/domain/_/createCredentials",
|
||||
nil, &responseString, param)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -545,7 +545,7 @@ func (j *Jenkins) CreateUsernamePasswordCredential(id, username, password, descr
|
||||
requestStruct := NewCreateUsernamePasswordRequest(id, username, password, description)
|
||||
param := map[string]string{"json": makeJson(requestStruct)}
|
||||
responseString := ""
|
||||
response, err := j.Requester.Post("/credentials/store/system/domain/_/createCredentials",
|
||||
response, err := j.Requester.PostForm("/credentials/store/system/domain/_/createCredentials",
|
||||
nil, &responseString, param)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -570,7 +570,7 @@ func (j *Jenkins) CreateSshCredentialInFolder(domain, id, username, passphrase,
|
||||
for _, folder := range folders {
|
||||
prePath = prePath + fmt.Sprintf("/job/%s", folder)
|
||||
}
|
||||
response, err := j.Requester.Post(prePath+
|
||||
response, err := j.Requester.PostForm(prePath+
|
||||
fmt.Sprintf("/credentials/store/folder/domain/%s/createCredentials", domain),
|
||||
nil, &responseString, param)
|
||||
if err != nil {
|
||||
@@ -596,7 +596,7 @@ func (j *Jenkins) CreateUsernamePasswordCredentialInFolder(domain, id, username,
|
||||
for _, folder := range folders {
|
||||
prePath = prePath + fmt.Sprintf("/job/%s", folder)
|
||||
}
|
||||
response, err := j.Requester.Post(prePath+
|
||||
response, err := j.Requester.PostForm(prePath+
|
||||
fmt.Sprintf("/credentials/store/folder/domain/%s/createCredentials", domain),
|
||||
nil, &responseString, param)
|
||||
if err != nil {
|
||||
@@ -622,7 +622,7 @@ func (j *Jenkins) CreateSecretTextCredentialInFolder(domain, id, secret, descrip
|
||||
for _, folder := range folders {
|
||||
prePath = prePath + fmt.Sprintf("/job/%s", folder)
|
||||
}
|
||||
response, err := j.Requester.Post(prePath+
|
||||
response, err := j.Requester.PostForm(prePath+
|
||||
fmt.Sprintf("/credentials/store/folder/domain/%s/createCredentials", domain),
|
||||
nil, &responseString, param)
|
||||
if err != nil {
|
||||
@@ -648,7 +648,7 @@ func (j *Jenkins) CreateKubeconfigCredentialInFolder(domain, id, content, descri
|
||||
for _, folder := range folders {
|
||||
prePath = prePath + fmt.Sprintf("/job/%s", folder)
|
||||
}
|
||||
response, err := j.Requester.Post(prePath+
|
||||
response, err := j.Requester.PostForm(prePath+
|
||||
fmt.Sprintf("/credentials/store/folder/domain/%s/createCredentials", domain),
|
||||
nil, &responseString, param)
|
||||
if err != nil {
|
||||
@@ -673,7 +673,7 @@ func (j *Jenkins) UpdateSshCredentialInFolder(domain, id, username, passphrase,
|
||||
for _, folder := range folders {
|
||||
prePath = prePath + fmt.Sprintf("/job/%s", folder)
|
||||
}
|
||||
response, err := j.Requester.Post(prePath+
|
||||
response, err := j.Requester.PostForm(prePath+
|
||||
fmt.Sprintf("/credentials/store/folder/domain/%s/credential/%s/updateSubmit", domain, id),
|
||||
nil, nil, param)
|
||||
if err != nil {
|
||||
@@ -698,7 +698,7 @@ func (j *Jenkins) UpdateUsernamePasswordCredentialInFolder(domain, id, username,
|
||||
for _, folder := range folders {
|
||||
prePath = prePath + fmt.Sprintf("/job/%s", folder)
|
||||
}
|
||||
response, err := j.Requester.Post(prePath+
|
||||
response, err := j.Requester.PostForm(prePath+
|
||||
fmt.Sprintf("/credentials/store/folder/domain/%s/credential/%s/updateSubmit", domain, id),
|
||||
nil, nil, param)
|
||||
if err != nil {
|
||||
@@ -723,7 +723,7 @@ func (j *Jenkins) UpdateSecretTextCredentialInFolder(domain, id, secret, descrip
|
||||
for _, folder := range folders {
|
||||
prePath = prePath + fmt.Sprintf("/job/%s", folder)
|
||||
}
|
||||
response, err := j.Requester.Post(prePath+
|
||||
response, err := j.Requester.PostForm(prePath+
|
||||
fmt.Sprintf("/credentials/store/folder/domain/%s/credential/%s/updateSubmit", domain, id),
|
||||
nil, nil, param)
|
||||
if err != nil {
|
||||
@@ -748,7 +748,7 @@ func (j *Jenkins) UpdateKubeconfigCredentialInFolder(domain, id, content, descri
|
||||
for _, folder := range folders {
|
||||
prePath = prePath + fmt.Sprintf("/job/%s", folder)
|
||||
}
|
||||
response, err := j.Requester.Post(prePath+
|
||||
response, err := j.Requester.PostForm(prePath+
|
||||
fmt.Sprintf("/credentials/store/folder/domain/%s/credential/%s/updateSubmit", domain, id),
|
||||
nil, nil, param)
|
||||
if err != nil {
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
package informers
|
||||
|
||||
import (
|
||||
applicationinformers "github.com/kubernetes-sigs/application/pkg/client/informers/externalversions"
|
||||
s2iinformers "github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions"
|
||||
k8sinformers "k8s.io/client-go/informers"
|
||||
ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client"
|
||||
applicationinformers "sigs.k8s.io/application/pkg/client/informers/externalversions"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -15,14 +15,15 @@ package devops
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/beevik/etree"
|
||||
"github.com/kubesphere/sonargo/sonar"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/gojenkins"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -375,16 +376,50 @@ func (s *Parameters) fromEtree(properties *etree.Element) *Parameters {
|
||||
*s = append(*s, &Parameter{
|
||||
Name: param.SelectElement("name").Text(),
|
||||
Description: param.SelectElement("description").Text(),
|
||||
DefaultValue: param.SelectElement("name").Text(),
|
||||
DefaultValue: param.SelectElement("defaultValue").Text(),
|
||||
Type: ParameterTypeMap["hudson.model.PasswordParameterDefinition"],
|
||||
})
|
||||
case "hudson.model.ChoiceParameterDefinition":
|
||||
/*
|
||||
In Jenkins, different configuration methods will lead to different serialization results.
|
||||
We need to be compatible with serialization results.
|
||||
|
||||
case1: Configured by KubeSphere console / Jenkins console
|
||||
<hudson.model.ChoiceParameterDefinition>
|
||||
<name>1</name>
|
||||
<description>x</description>
|
||||
<choices class="java.util.Arrays$ArrayList">
|
||||
<a class="string-array">
|
||||
<string>1</string>
|
||||
<string>2</string>
|
||||
<string>3</string>
|
||||
</a>
|
||||
</choices>
|
||||
</hudson.model.ChoiceParameterDefinition>
|
||||
case2: Configured by pipeline syntax, sample: parameters { choice(name: 'CHOICES', choices: ['one', 'two', 'three'], description: '') }
|
||||
<hudson.model.ChoiceParameterDefinition>
|
||||
<name>1</name>
|
||||
<description>x</description>
|
||||
<choices class="java.util.Arrays$ArrayList">
|
||||
<string>1</string>
|
||||
<string>2</string>
|
||||
<string>3</string>
|
||||
</choices>
|
||||
</hudson.model.ChoiceParameterDefinition>
|
||||
*/
|
||||
choiceParameter := &Parameter{
|
||||
Name: param.SelectElement("name").Text(),
|
||||
Description: param.SelectElement("description").Text(),
|
||||
Type: ParameterTypeMap["hudson.model.ChoiceParameterDefinition"],
|
||||
}
|
||||
choices := param.SelectElement("choices").SelectElement("a").SelectElements("string")
|
||||
choicesSection := param.SelectElement("choices")
|
||||
a := choicesSection.SelectElement("a")
|
||||
var choices []*etree.Element
|
||||
if a != nil {
|
||||
choices = a.SelectElements("string")
|
||||
} else {
|
||||
choices = choicesSection.SelectElements("string")
|
||||
}
|
||||
for _, choice := range choices {
|
||||
choiceParameter.DefaultValue += fmt.Sprintf("%s\n", choice.Text())
|
||||
}
|
||||
|
||||
@@ -309,3 +309,39 @@ func GetMultiBranchPipelineSonar(projectId, pipelineId, branchId string) ([]*Son
|
||||
}
|
||||
return sonarStatus, nil
|
||||
}
|
||||
|
||||
func ValidatePipelineConfig(pipeline *ProjectPipeline) error {
|
||||
switch pipeline.Type {
|
||||
case NoScmPipelineType:
|
||||
if pipeline.Pipeline == nil {
|
||||
err := fmt.Errorf("request should contains Pipeline struct")
|
||||
return err
|
||||
}
|
||||
if pipeline.Pipeline.Name == "" {
|
||||
err := fmt.Errorf("pipeline name suport not be nil")
|
||||
return err
|
||||
}
|
||||
if pipeline.Pipeline.Parameters != nil {
|
||||
params := []*Parameter(*pipeline.Pipeline.Parameters)
|
||||
for _, param := range params {
|
||||
if param.Name == "" {
|
||||
err := fmt.Errorf("param name should not be nil")
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
case MultiBranchPipelineType:
|
||||
if pipeline.MultiBranchPipeline == nil {
|
||||
err := fmt.Errorf("request should contains MultiBranchPipeline struct")
|
||||
return err
|
||||
}
|
||||
if pipeline.MultiBranchPipeline.Name == "" {
|
||||
err := fmt.Errorf("pipeline name suport not be nil")
|
||||
return err
|
||||
}
|
||||
default:
|
||||
err := fmt.Errorf("unsupport job type")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -631,3 +631,266 @@ func Test_MultiBranchPipelineMultibranchTrigger(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Test_ParsePipelineConfigChoiceParameters(t *testing.T) {
|
||||
|
||||
case1 := `<flow-definition plugin="workflow-job@2.32">
|
||||
<actions>
|
||||
<org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobAction plugin="pipeline-model-definition@1.3.9"/>
|
||||
<org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobPropertyTrackerAction plugin="pipeline-model-definition@1.3.9">
|
||||
<jobProperties/>
|
||||
<triggers/>
|
||||
<parameters>
|
||||
<string>BIOGRAPHY</string>
|
||||
<string>PERSON</string>
|
||||
<string>PASSWORD</string>
|
||||
<string>TOGGLE</string>
|
||||
</parameters>
|
||||
<options/>
|
||||
</org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobPropertyTrackerAction>
|
||||
</actions>
|
||||
<description/>
|
||||
<keepDependencies>false</keepDependencies>
|
||||
<properties>
|
||||
<hudson.plugins.jira.JiraProjectProperty plugin="jira@3.0.8"/>
|
||||
<jenkins.model.BuildDiscarderProperty>
|
||||
<strategy class="hudson.tasks.LogRotator">
|
||||
<daysToKeep>7</daysToKeep>
|
||||
<numToKeep>10</numToKeep>
|
||||
<artifactDaysToKeep>-1</artifactDaysToKeep>
|
||||
<artifactNumToKeep>-1</artifactNumToKeep>
|
||||
</strategy>
|
||||
</jenkins.model.BuildDiscarderProperty>
|
||||
<hudson.model.ParametersDefinitionProperty>
|
||||
<parameterDefinitions>
|
||||
<hudson.model.StringParameterDefinition>
|
||||
<name>PERSON</name>
|
||||
<description>Who should I say hello to?</description>
|
||||
<defaultValue>Mr Jenkins</defaultValue>
|
||||
<trim>false</trim>
|
||||
</hudson.model.StringParameterDefinition>
|
||||
<hudson.model.TextParameterDefinition>
|
||||
<name>BIOGRAPHY</name>
|
||||
<description>Enter some information about the person</description>
|
||||
<defaultValue/>
|
||||
<trim>false</trim>
|
||||
</hudson.model.TextParameterDefinition>
|
||||
<hudson.model.BooleanParameterDefinition>
|
||||
<name>TOGGLE</name>
|
||||
<description>Toggle this value</description>
|
||||
<defaultValue>true</defaultValue>
|
||||
</hudson.model.BooleanParameterDefinition>
|
||||
<hudson.model.PasswordParameterDefinition>
|
||||
<name>PASSWORD</name>
|
||||
<description>Enter a password</description>
|
||||
<defaultValue>
|
||||
{AQAAABAAAAAQHD/HoXKklrRKtlQ5ylr1lgN1dj7im57I8SGfkLIe17s=}
|
||||
</defaultValue>
|
||||
</hudson.model.PasswordParameterDefinition>
|
||||
<hudson.model.ChoiceParameterDefinition>
|
||||
<name>1</name>
|
||||
<description>x</description>
|
||||
<choices class="java.util.Arrays$ArrayList">
|
||||
<a class="string-array">
|
||||
<string>1</string>
|
||||
<string>2</string>
|
||||
<string>3</string>
|
||||
</a>
|
||||
</choices>
|
||||
</hudson.model.ChoiceParameterDefinition>
|
||||
</parameterDefinitions>
|
||||
</hudson.model.ParametersDefinitionProperty>
|
||||
</properties>
|
||||
<definition class="org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition" plugin="workflow-cps@2.73">
|
||||
<script>
|
||||
pipeline { agent any parameters { string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?') text(name: 'BIOGRAPHY', defaultValue: '', description: 'Enter some information about the person') booleanParam(name: 'TOGGLE', defaultValue: true, description: 'Toggle this value') password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'Enter a password') } stages { stage('Example') { steps { echo "Hello ${params.PERSON}" echo "Biography: ${params.BIOGRAPHY}" echo "Toggle: ${params.TOGGLE}" echo "Choice: ${params.CHOICE}" echo "Password: ${params.PASSWORD}" } } } }
|
||||
</script>
|
||||
<sandbox>true</sandbox>
|
||||
</definition>
|
||||
<triggers/>
|
||||
<disabled>false</disabled>
|
||||
</flow-definition>`
|
||||
case2 := `
|
||||
<flow-definition plugin="workflow-job@2.32">
|
||||
<actions>
|
||||
<org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobAction plugin="pipeline-model-definition@1.3.9"/>
|
||||
<org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobPropertyTrackerAction plugin="pipeline-model-definition@1.3.9">
|
||||
<jobProperties/>
|
||||
<triggers/>
|
||||
<parameters>
|
||||
<string>BIOGRAPHY</string>
|
||||
<string>PERSON</string>
|
||||
<string>PASSWORD</string>
|
||||
<string>TOGGLE</string>
|
||||
</parameters>
|
||||
<options/>
|
||||
</org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobPropertyTrackerAction>
|
||||
</actions>
|
||||
<description/>
|
||||
<keepDependencies>false</keepDependencies>
|
||||
<properties>
|
||||
<hudson.plugins.jira.JiraProjectProperty plugin="jira@3.0.8"/>
|
||||
<jenkins.model.BuildDiscarderProperty>
|
||||
<strategy class="hudson.tasks.LogRotator">
|
||||
<daysToKeep>7</daysToKeep>
|
||||
<numToKeep>10</numToKeep>
|
||||
<artifactDaysToKeep>-1</artifactDaysToKeep>
|
||||
<artifactNumToKeep>-1</artifactNumToKeep>
|
||||
</strategy>
|
||||
</jenkins.model.BuildDiscarderProperty>
|
||||
<hudson.model.ParametersDefinitionProperty>
|
||||
<parameterDefinitions>
|
||||
<hudson.model.StringParameterDefinition>
|
||||
<name>PERSON</name>
|
||||
<description>Who should I say hello to?</description>
|
||||
<defaultValue>Mr Jenkins</defaultValue>
|
||||
<trim>false</trim>
|
||||
</hudson.model.StringParameterDefinition>
|
||||
<hudson.model.TextParameterDefinition>
|
||||
<name>BIOGRAPHY</name>
|
||||
<description>Enter some information about the person</description>
|
||||
<defaultValue/>
|
||||
<trim>false</trim>
|
||||
</hudson.model.TextParameterDefinition>
|
||||
<hudson.model.BooleanParameterDefinition>
|
||||
<name>TOGGLE</name>
|
||||
<description>Toggle this value</description>
|
||||
<defaultValue>true</defaultValue>
|
||||
</hudson.model.BooleanParameterDefinition>
|
||||
<hudson.model.PasswordParameterDefinition>
|
||||
<name>PASSWORD</name>
|
||||
<description>Enter a password</description>
|
||||
<defaultValue>
|
||||
{AQAAABAAAAAQHD/HoXKklrRKtlQ5ylr1lgN1dj7im57I8SGfkLIe17s=}
|
||||
</defaultValue>
|
||||
</hudson.model.PasswordParameterDefinition>
|
||||
<hudson.model.ChoiceParameterDefinition>
|
||||
<name>1</name>
|
||||
<description>x</description>
|
||||
<choices class="java.util.Arrays$ArrayList">
|
||||
<string>1</string>
|
||||
<string>2</string>
|
||||
<string>3</string>
|
||||
</choices>
|
||||
</hudson.model.ChoiceParameterDefinition>
|
||||
</parameterDefinitions>
|
||||
</hudson.model.ParametersDefinitionProperty>
|
||||
</properties>
|
||||
<definition class="org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition" plugin="workflow-cps@2.73">
|
||||
<script>
|
||||
pipeline { agent any parameters { string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?') text(name: 'BIOGRAPHY', defaultValue: '', description: 'Enter some information about the person') booleanParam(name: 'TOGGLE', defaultValue: true, description: 'Toggle this value') password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'Enter a password') } stages { stage('Example') { steps { echo "Hello ${params.PERSON}" echo "Biography: ${params.BIOGRAPHY}" echo "Toggle: ${params.TOGGLE}" echo "Choice: ${params.CHOICE}" echo "Password: ${params.PASSWORD}" } } } }
|
||||
</script>
|
||||
<sandbox>true</sandbox>
|
||||
</definition>
|
||||
<triggers/>
|
||||
<disabled>false</disabled>
|
||||
</flow-definition>`
|
||||
|
||||
case1Pipeline, err := parsePipelineConfigXml(case1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
case2Pipeline, err := parsePipelineConfigXml(case2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(case1Pipeline, case2Pipeline) {
|
||||
t.Fatalf("case1 [%+v] case2 [%+v] should equal ", case1Pipeline, case2Pipeline)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Test_ValidatePipelineConfig(t *testing.T) {
|
||||
rightInput := []*ProjectPipeline{
|
||||
{
|
||||
Type: "pipeline",
|
||||
Pipeline: &NoScmPipeline{
|
||||
Name: "test",
|
||||
Parameters: nil,
|
||||
Jenkinsfile: "echo 1",
|
||||
},
|
||||
}, {
|
||||
Type: "multi-branch-pipeline",
|
||||
MultiBranchPipeline: &MultiBranchPipeline{
|
||||
Name: "multibranch-test",
|
||||
Description: "xx",
|
||||
},
|
||||
}, {
|
||||
Type: "pipeline",
|
||||
Pipeline: &NoScmPipeline{
|
||||
Name: "test2",
|
||||
Description: "",
|
||||
Discarder: nil,
|
||||
Parameters: &Parameters{
|
||||
&Parameter{
|
||||
Name: "xx",
|
||||
Type: "yy",
|
||||
}, &Parameter{
|
||||
Name: "tt",
|
||||
DefaultValue: "",
|
||||
Type: "",
|
||||
Description: "ccc",
|
||||
},
|
||||
},
|
||||
DisableConcurrent: false,
|
||||
TimerTrigger: nil,
|
||||
RemoteTrigger: nil,
|
||||
Jenkinsfile: "",
|
||||
},
|
||||
},
|
||||
}
|
||||
errorInput := []*ProjectPipeline{
|
||||
{
|
||||
Type: "xx",
|
||||
Pipeline: &NoScmPipeline{
|
||||
Name: "",
|
||||
Parameters: nil,
|
||||
Jenkinsfile: "echo 1",
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: "pipeline",
|
||||
Pipeline: &NoScmPipeline{
|
||||
Name: "",
|
||||
Parameters: nil,
|
||||
Jenkinsfile: "echo 1",
|
||||
},
|
||||
}, {
|
||||
Type: "multi-branch-pipeline",
|
||||
MultiBranchPipeline: &MultiBranchPipeline{
|
||||
Name: "",
|
||||
Description: "xx",
|
||||
},
|
||||
}, {
|
||||
Type: "pipeline",
|
||||
Pipeline: &NoScmPipeline{
|
||||
Name: "test2",
|
||||
Description: "",
|
||||
Discarder: nil,
|
||||
Parameters: &Parameters{
|
||||
&Parameter{
|
||||
Name: "",
|
||||
Type: "yy",
|
||||
}, &Parameter{
|
||||
Name: "tt",
|
||||
Description: "ccc",
|
||||
},
|
||||
},
|
||||
Jenkinsfile: "",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, input := range rightInput {
|
||||
err := ValidatePipelineConfig(input)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, input := range errorInput {
|
||||
err := ValidatePipelineConfig(input)
|
||||
if err == nil {
|
||||
t.Fatalf("%+v, is an error configuration", input)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,10 +42,22 @@ import (
|
||||
|
||||
const (
|
||||
ClusterRoleKind = "ClusterRole"
|
||||
NamespaceAdminRoleBindName = "admin"
|
||||
NamespaceViewerRoleBindName = "viewer"
|
||||
RoleKind = "Role"
|
||||
NamespaceAdminRoleName = "admin"
|
||||
NamespaceOperatorRoleName = "operator"
|
||||
NamespaceViewerRoleName = "viewer"
|
||||
NamespaceAdminRoleBindName = NamespaceAdminRoleName
|
||||
NamespaceViewerRoleBindName = NamespaceViewerRoleName
|
||||
)
|
||||
|
||||
func GetWorkspaceAdminRoleBindingName(workspaceName string) string {
|
||||
return fmt.Sprintf("workspace:%s:admin", workspaceName)
|
||||
}
|
||||
|
||||
func GetWorkspaceViewerRoleBindingName(workspaceName string) string {
|
||||
return fmt.Sprintf("workspace:%s:viewer", workspaceName)
|
||||
}
|
||||
|
||||
func GetDevopsRoleSimpleRules(role string) []models.SimpleRule {
|
||||
var rules []models.SimpleRule
|
||||
|
||||
@@ -489,23 +501,21 @@ func GetUserWorkspaceSimpleRules(workspace, username string) ([]models.SimpleRul
|
||||
return GetWorkspaceRoleSimpleRules(workspace, constants.WorkspaceAdmin), nil
|
||||
}
|
||||
|
||||
// workspaces-manager
|
||||
if RulesMatchesRequired(clusterRules, rbacv1.PolicyRule{
|
||||
Verbs: []string{"*"},
|
||||
APIGroups: []string{"*"},
|
||||
Resources: []string{"workspaces", "workspaces/*"},
|
||||
}) {
|
||||
return GetWorkspaceRoleSimpleRules(workspace, constants.WorkspacesManager), nil
|
||||
}
|
||||
|
||||
workspaceRole, err := GetUserWorkspaceRole(workspace, username)
|
||||
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
|
||||
// workspaces-manager
|
||||
if RulesMatchesRequired(clusterRules, rbacv1.PolicyRule{
|
||||
Verbs: []string{"*"},
|
||||
APIGroups: []string{"*"},
|
||||
Resources: []string{"workspaces", "workspaces/*"},
|
||||
}) {
|
||||
return GetWorkspaceRoleSimpleRules(workspace, constants.WorkspacesManager), nil
|
||||
}
|
||||
|
||||
return []models.SimpleRule{}, nil
|
||||
}
|
||||
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -504,6 +504,19 @@ func loginLog(uid, ip string) {
|
||||
redisClient.LTrim(fmt.Sprintf("kubesphere:users:%s:login-log", uid), -10, -1)
|
||||
}
|
||||
}
|
||||
func deleteLoginLogs(uid string) error {
|
||||
redisClient, err := clientset.ClientSets().Redis()
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return err
|
||||
}
|
||||
err = redisClient.Del(fmt.Sprintf("kubesphere:users:%s:login-log", uid)).Err()
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func LoginLog(username string) ([]string, error) {
|
||||
redisClient, err := clientset.ClientSets().Redis()
|
||||
@@ -790,6 +803,11 @@ func DeleteUser(username string) error {
|
||||
if err := deleteUserInDevOps(username); err != nil {
|
||||
klog.Errorln("delete user in devops failed", username, err)
|
||||
}
|
||||
|
||||
if err := deleteLoginLogs(username); err != nil {
|
||||
klog.Errorln(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
64
pkg/models/kubeconfig/internal/pki_helpers.go
Normal file
64
pkg/models/kubeconfig/internal/pki_helpers.go
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020 The KubeSphere Authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* /
|
||||
*/
|
||||
|
||||
package pkiutil
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
cryptorand "crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"github.com/pkg/errors"
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
)
|
||||
|
||||
// NewCSRAndKey generates a new key and CSR and that could be signed to create the given certificate
|
||||
func NewCSRAndKey(config *certutil.Config) (*x509.CertificateRequest, *rsa.PrivateKey, error) {
|
||||
key, err := certutil.NewPrivateKey()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "unable to create private key")
|
||||
}
|
||||
|
||||
csr, err := NewCSR(*config, key)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "unable to generate CSR")
|
||||
}
|
||||
|
||||
return csr, key, nil
|
||||
}
|
||||
|
||||
// NewCSR creates a new CSR
|
||||
func NewCSR(cfg certutil.Config, key crypto.Signer) (*x509.CertificateRequest, error) {
|
||||
template := &x509.CertificateRequest{
|
||||
Subject: pkix.Name{
|
||||
CommonName: cfg.CommonName,
|
||||
Organization: cfg.Organization,
|
||||
},
|
||||
DNSNames: cfg.AltNames.DNSNames,
|
||||
IPAddresses: cfg.AltNames.IPs,
|
||||
}
|
||||
|
||||
csrBytes, err := x509.CreateCertificateRequest(cryptorand.Reader, template, key)
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create a CSR")
|
||||
}
|
||||
|
||||
return x509.ParseCertificateRequest(csrBytes)
|
||||
}
|
||||
@@ -21,294 +21,237 @@ 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"
|
||||
|
||||
certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
pkiutil "kubesphere.io/kubesphere/pkg/models/kubeconfig/internal"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
caPath = "/etc/kubernetes/pki/ca.crt"
|
||||
keyPath = "/etc/kubernetes/pki/ca.key"
|
||||
clusterName = "kubernetes"
|
||||
kubectlConfigKey = "config"
|
||||
defaultNamespace = "default"
|
||||
inClusterCAFilePath = "/run/secrets/kubernetes.io/serviceaccount/ca.crt"
|
||||
kubeconfigNameFormat = "kubeconfig-%s"
|
||||
defaultClusterName = "local"
|
||||
defaultNamespace = "default"
|
||||
fileName = "config"
|
||||
configMapKind = "ConfigMap"
|
||||
configMapAPIVersion = "v1"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
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 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{})
|
||||
|
||||
configName := fmt.Sprintf(kubeconfigNameFormat, username)
|
||||
_, err := k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Get(configName, metav1.GetOptions{})
|
||||
|
||||
if errors.IsNotFound(err) {
|
||||
config, err := createKubeConfig(username)
|
||||
kubeconfig, 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)
|
||||
data := map[string]string{fileName: string(kubeconfig)}
|
||||
cm := &corev1.ConfigMap{TypeMeta: metav1.TypeMeta{Kind: configMapKind, APIVersion: configMapAPIVersion}, ObjectMeta: metav1.ObjectMeta{Name: configName}, Data: data}
|
||||
_, err = k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Create(cm)
|
||||
if err != nil && !errors.IsAlreadyExists(err) {
|
||||
klog.Errorf("create username %s's kubeConfig failed, reason: %v", username, err)
|
||||
klog.Errorln(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createKubeConfig(username string) ([]byte, error) {
|
||||
k8sClient := client.ClientSets().K8s().Kubernetes()
|
||||
kubeconfig := client.ClientSets().K8s().Config()
|
||||
|
||||
var err error
|
||||
var ca []byte
|
||||
if len(kubeconfig.CAData) > 0 {
|
||||
ca = kubeconfig.CAData
|
||||
} else {
|
||||
ca, err = ioutil.ReadFile(inClusterCAFilePath)
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
csrConfig := &certutil.Config{
|
||||
CommonName: username,
|
||||
Organization: nil,
|
||||
AltNames: certutil.AltNames{},
|
||||
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
x509csr, x509key, err := pkiutil.NewCSRAndKey(csrConfig)
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var csrBuffer, keyBuffer bytes.Buffer
|
||||
pem.Encode(&keyBuffer, &pem.Block{Type: "PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(x509key)})
|
||||
|
||||
csrBytes, _ := x509.CreateCertificateRequest(rand.Reader, x509csr, x509key)
|
||||
pem.Encode(&csrBuffer, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrBytes})
|
||||
|
||||
csr := csrBuffer.Bytes()
|
||||
key := keyBuffer.Bytes()
|
||||
|
||||
csrName := fmt.Sprintf("%s-csr-%d", username, time.Now().Unix())
|
||||
|
||||
k8sCSR := &certificatesv1beta1.CertificateSigningRequest{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "CertificateSigningRequest",
|
||||
APIVersion: "certificates.k8s.io/v1beta1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: csrName,
|
||||
},
|
||||
Spec: certificatesv1beta1.CertificateSigningRequestSpec{
|
||||
Request: csr,
|
||||
Usages: []certificatesv1beta1.KeyUsage{certificatesv1beta1.UsageServerAuth, certificatesv1beta1.UsageKeyEncipherment, certificatesv1beta1.UsageClientAuth, certificatesv1beta1.UsageDigitalSignature},
|
||||
Username: username,
|
||||
Groups: []string{"system:authenticated"},
|
||||
},
|
||||
}
|
||||
|
||||
// create csr
|
||||
k8sCSR, err = k8sClient.CertificatesV1beta1().CertificateSigningRequests().Create(k8sCSR)
|
||||
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// release csr, if it fails need to delete it manually
|
||||
defer func() {
|
||||
err := k8sClient.CertificatesV1beta1().CertificateSigningRequests().Delete(csrName, &metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
}
|
||||
}()
|
||||
|
||||
k8sCSR.Status = certificatesv1beta1.CertificateSigningRequestStatus{
|
||||
Conditions: []certificatesv1beta1.CertificateSigningRequestCondition{{
|
||||
Type: "Approved",
|
||||
Reason: "KubeSphereApprove",
|
||||
Message: "This CSR was approved by KubeSphere certificate approve.",
|
||||
LastUpdateTime: metav1.Time{
|
||||
Time: time.Now(),
|
||||
},
|
||||
}},
|
||||
}
|
||||
|
||||
// approve csr
|
||||
k8sCSR, err = k8sClient.CertificatesV1beta1().CertificateSigningRequests().UpdateApproval(k8sCSR)
|
||||
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// get client cert
|
||||
var cert []byte
|
||||
maxRetries := 3
|
||||
for i := 0; i < maxRetries; i++ {
|
||||
|
||||
k8sCSR, err = k8sClient.CertificatesV1beta1().CertificateSigningRequests().Get(csrName, metav1.GetOptions{})
|
||||
|
||||
if k8sCSR != nil && k8sCSR.Status.Certificate != nil {
|
||||
cert = k8sCSR.Status.Certificate
|
||||
break
|
||||
}
|
||||
|
||||
// sleep 0/200/400 millisecond
|
||||
time.Sleep(200 * time.Millisecond * time.Duration(i))
|
||||
}
|
||||
|
||||
if cert == nil {
|
||||
return nil, fmt.Errorf("create client certificate failed: %v", err)
|
||||
}
|
||||
|
||||
currentContext := fmt.Sprintf("%s@%s", username, defaultClusterName)
|
||||
|
||||
config := clientcmdapi.Config{
|
||||
Kind: configMapKind,
|
||||
APIVersion: configMapAPIVersion,
|
||||
Preferences: clientcmdapi.Preferences{},
|
||||
Clusters: map[string]*clientcmdapi.Cluster{defaultClusterName: {
|
||||
Server: kubeconfig.Host,
|
||||
InsecureSkipTLSVerify: false,
|
||||
CertificateAuthorityData: ca,
|
||||
}},
|
||||
AuthInfos: map[string]*clientcmdapi.AuthInfo{username: {
|
||||
ClientCertificateData: cert,
|
||||
ClientKeyData: key,
|
||||
}},
|
||||
Contexts: map[string]*clientcmdapi.Context{currentContext: {
|
||||
Cluster: defaultClusterName,
|
||||
AuthInfo: username,
|
||||
Namespace: defaultNamespace,
|
||||
}},
|
||||
CurrentContext: currentContext,
|
||||
}
|
||||
|
||||
return clientcmd.Write(config)
|
||||
}
|
||||
|
||||
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{})
|
||||
configName := fmt.Sprintf(kubeconfigNameFormat, 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)
|
||||
klog.Errorln(err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
str := configMap.Data[kubectlConfigKey]
|
||||
var kubeConfig kubeConfig
|
||||
err = yaml.Unmarshal([]byte(str), &kubeConfig)
|
||||
data := []byte(configMap.Data[fileName])
|
||||
|
||||
kubeconfig, err := clientcmd.Load(data)
|
||||
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
klog.Errorln(err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
masterURL := client.ClientSets().K8s().Master()
|
||||
for i, cluster := range kubeConfig.Clusters {
|
||||
cluster.Cluster.Server = masterURL
|
||||
kubeConfig.Clusters[i] = cluster
|
||||
|
||||
if cluster := kubeconfig.Clusters[defaultClusterName]; cluster != nil {
|
||||
cluster.Server = masterURL
|
||||
}
|
||||
data, err := yaml.Marshal(kubeConfig)
|
||||
|
||||
data, err = clientcmd.Write(*kubeconfig)
|
||||
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
klog.Errorln(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
|
||||
}
|
||||
configName := fmt.Sprintf(kubeconfigNameFormat, username)
|
||||
|
||||
deletePolicy := metaV1.DeletePropagationBackground
|
||||
err = k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Delete(configName, &metaV1.DeleteOptions{PropagationPolicy: &deletePolicy})
|
||||
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)
|
||||
klog.Errorln(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -313,7 +313,7 @@ func GetPodMetrics(params RequestParams) *Response {
|
||||
|
||||
// add label resouce_name
|
||||
for _, item := range response.Data.Result {
|
||||
item.Metric["resource_name"] = item.Metric["pod_name"]
|
||||
item.Metric["resource_name"] = item.Metric[labelNamePod]
|
||||
}
|
||||
|
||||
ch <- APIResponse{
|
||||
@@ -364,7 +364,7 @@ func GetContainerMetrics(params RequestParams) *Response {
|
||||
|
||||
// add label resouce_name
|
||||
for _, item := range response.Data.Result {
|
||||
item.Metric["resource_name"] = item.Metric["container_name"]
|
||||
item.Metric["resource_name"] = item.Metric[labelNameContainer]
|
||||
}
|
||||
|
||||
ch <- APIResponse{
|
||||
@@ -616,9 +616,9 @@ func makePromqlForContainer(metricName string, params RequestParams) string {
|
||||
var containerSelector string
|
||||
|
||||
if params.ContainerName != "" {
|
||||
containerSelector = fmt.Sprintf(`pod_name="%s", namespace="%s", container_name="%s"`, params.PodName, params.NamespaceName, params.ContainerName)
|
||||
containerSelector = fmt.Sprintf(`%s="%s", namespace="%s", %s="%s"`, labelNamePod, params.PodName, params.NamespaceName, labelNameContainer, params.ContainerName)
|
||||
} else {
|
||||
containerSelector = fmt.Sprintf(`pod_name="%s", namespace="%s", container_name=~"%s"`, params.PodName, params.NamespaceName, params.ResourcesFilter)
|
||||
containerSelector = fmt.Sprintf(`%s="%s", namespace="%s", %s=~"%s"`, labelNamePod, params.PodName, params.NamespaceName, labelNameContainer, params.ResourcesFilter)
|
||||
}
|
||||
|
||||
return strings.Replace(exp, "$1", containerSelector, -1)
|
||||
|
||||
@@ -13,6 +13,16 @@ limitations under the License.
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client"
|
||||
)
|
||||
|
||||
var (
|
||||
labelNamePod = "pod_name"
|
||||
labelNameContainer = "container_name"
|
||||
)
|
||||
|
||||
const (
|
||||
// TODO: expose the following metrics in prometheus format
|
||||
MetricClusterWorkspaceCount = "cluster_workspace_count"
|
||||
@@ -293,7 +303,7 @@ var metricsPromqlMap = map[string]string{
|
||||
"cluster_disk_inode_total": `sum(node:node_inodes_total:)`,
|
||||
"cluster_disk_inode_usage": `sum(node:node_inodes_total:) - sum(node:node_inodes_free:)`,
|
||||
"cluster_disk_inode_utilisation": `cluster:disk_inode_utilization:ratio`,
|
||||
"cluster_namespace_count": `count(kube_namespace_annotations)`,
|
||||
"cluster_namespace_count": `count(kube_namespace_labels)`,
|
||||
"cluster_pod_count": `cluster:pod:sum`,
|
||||
"cluster_pod_quota": `sum(max(kube_node_status_capacity_pods) by (node) unless on (node) (kube_node_status_condition{condition="Ready",status=~"unknown|false"} > 0))`,
|
||||
"cluster_pod_utilisation": `cluster:pod_utilization:ratio`,
|
||||
@@ -311,7 +321,7 @@ var metricsPromqlMap = map[string]string{
|
||||
"cluster_hpa_count": `sum(kube_hpa_labels)`,
|
||||
"cluster_job_count": `sum(kube_job_labels)`,
|
||||
"cluster_statefulset_count": `sum(kube_statefulset_labels)`,
|
||||
"cluster_replicaset_count": `count(kube_replicaset_created)`,
|
||||
"cluster_replicaset_count": `count(kube_replicaset_labels)`,
|
||||
"cluster_service_count": `sum(kube_service_info)`,
|
||||
"cluster_secret_count": `sum(kube_secret_info)`,
|
||||
"cluster_pv_count": `sum(kube_persistentvolume_labels)`,
|
||||
@@ -374,7 +384,7 @@ var metricsPromqlMap = map[string]string{
|
||||
"workspace_hpa_count": `sum by (label_kubesphere_io_workspace) (kube_hpa_labels{namespace!=""} * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels{$1}))`,
|
||||
"workspace_job_count": `sum by (label_kubesphere_io_workspace) (kube_job_labels{namespace!=""} * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels{$1}))`,
|
||||
"workspace_statefulset_count": `sum by (label_kubesphere_io_workspace) (kube_statefulset_labels{namespace!=""} * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels{$1}))`,
|
||||
"workspace_replicaset_count": `count by (label_kubesphere_io_workspace) (kube_replicaset_created{namespace!=""} * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels{$1}))`,
|
||||
"workspace_replicaset_count": `count by (label_kubesphere_io_workspace) (kube_replicaset_labels{namespace!=""} * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels{$1}))`,
|
||||
"workspace_service_count": `sum by (label_kubesphere_io_workspace) (kube_service_info{namespace!=""} * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels{$1}))`,
|
||||
"workspace_secret_count": `sum by (label_kubesphere_io_workspace) (kube_secret_info{namespace!=""} * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels{$1}))`,
|
||||
"workspace_pod_abnormal_ratio": `count by (label_kubesphere_io_workspace) ((kube_pod_info{node!=""} unless on (pod, namespace) (kube_pod_status_phase{job="kube-state-metrics", phase="Succeeded"}>0) unless on (pod, namespace) ((kube_pod_status_ready{job="kube-state-metrics", condition="true"}>0) and on (pod, namespace) (kube_pod_status_phase{job="kube-state-metrics", phase="Running"}>0)) unless on (pod, namespace) (kube_pod_container_status_waiting_reason{job="kube-state-metrics", reason="ContainerCreating"}>0)) * on (namespace) group_left(label_kubesphere_io_workspace) kube_namespace_labels{$1}) / sum by (label_kubesphere_io_workspace) (kube_pod_status_phase{phase!="Succeeded", namespace!=""} * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels{$1}))`,
|
||||
@@ -401,7 +411,7 @@ var metricsPromqlMap = map[string]string{
|
||||
"namespace_hpa_count": `sum by (namespace) (kube_hpa_labels{namespace!=""} * on (namespace) group_left(label_kubesphere_io_workspace) kube_namespace_labels{$1})`,
|
||||
"namespace_job_count": `sum by (namespace) (kube_job_labels{namespace!=""} * on (namespace) group_left(label_kubesphere_io_workspace) kube_namespace_labels{$1})`,
|
||||
"namespace_statefulset_count": `sum by (namespace) (kube_statefulset_labels{namespace!=""} * on (namespace) group_left(label_kubesphere_io_workspace) kube_namespace_labels{$1})`,
|
||||
"namespace_replicaset_count": `count by (namespace) (kube_replicaset_created{namespace!=""} * on (namespace) group_left(label_kubesphere_io_workspace) kube_namespace_labels{$1})`,
|
||||
"namespace_replicaset_count": `count by (namespace) (kube_replicaset_labels{namespace!=""} * on (namespace) group_left(label_kubesphere_io_workspace) kube_namespace_labels{$1})`,
|
||||
"namespace_service_count": `sum by (namespace) (kube_service_info{namespace!=""} * on (namespace) group_left(label_kubesphere_io_workspace) kube_namespace_labels{$1})`,
|
||||
"namespace_secret_count": `sum by (namespace) (kube_secret_info{namespace!=""} * on (namespace) group_left(label_kubesphere_io_workspace) kube_namespace_labels{$1})`,
|
||||
"namespace_configmap_count": `sum by (namespace) (kube_configmap_info{namespace!=""} * on (namespace) group_left(label_kubesphere_io_workspace) kube_namespace_labels{$1})`,
|
||||
@@ -435,14 +445,14 @@ var metricsPromqlMap = map[string]string{
|
||||
// pod
|
||||
"pod_cpu_usage": `round(label_join(sum by (namespace, pod_name) (irate(container_cpu_usage_seconds_total{job="kubelet", pod_name!="", image!=""}[5m])), "pod", "", "pod_name") * on (namespace, pod) group_left(owner_kind, owner_name) kube_pod_owner{$1} * on (namespace, pod) group_left(node) kube_pod_info{$2}, 0.001)`,
|
||||
"pod_memory_usage": `label_join(sum by (namespace, pod_name) (container_memory_usage_bytes{job="kubelet", pod_name!="", image!=""}), "pod", "", "pod_name") * on (namespace, pod) group_left(owner_kind, owner_name) kube_pod_owner{$1} * on (namespace, pod) group_left(node) kube_pod_info{$2}`,
|
||||
"pod_memory_usage_wo_cache": `label_join(sum by (namespace, pod_name) (container_memory_usage_bytes{job="kubelet", pod_name!="", image!=""} - container_memory_cache{job="kubelet", pod_name!="", image!=""}), "pod", "", "pod_name") * on (namespace, pod) group_left(owner_kind, owner_name) kube_pod_owner{$1} * on (namespace, pod) group_left(node) kube_pod_info{$2}`,
|
||||
"pod_memory_usage_wo_cache": `label_join(sum by (namespace, pod_name) (container_memory_working_set_bytes{job="kubelet", pod_name!="", image!=""}), "pod", "", "pod_name") * on (namespace, pod) group_left(owner_kind, owner_name) kube_pod_owner{$1} * on (namespace, pod) group_left(node) kube_pod_info{$2}`,
|
||||
"pod_net_bytes_transmitted": `label_join(sum by (namespace, pod_name) (irate(container_network_transmit_bytes_total{pod_name!="", interface!~"^(cali.+|tunl.+|dummy.+|kube.+|flannel.+|cni.+|docker.+|veth.+|lo.*)", job="kubelet"}[5m])), "pod", "", "pod_name") * on (namespace, pod) group_left(owner_kind, owner_name) kube_pod_owner{$1} * on (namespace, pod) group_left(node) kube_pod_info{$2}`,
|
||||
"pod_net_bytes_received": `label_join(sum by (namespace, pod_name) (irate(container_network_receive_bytes_total{pod_name!="", interface!~"^(cali.+|tunl.+|dummy.+|kube.+|flannel.+|cni.+|docker.+|veth.+|lo.*)", job="kubelet"}[5m])), "pod", "", "pod_name") * on (namespace, pod) group_left(owner_kind, owner_name) kube_pod_owner{$1} * on (namespace, pod) group_left(node) kube_pod_info{$2}`,
|
||||
|
||||
// container
|
||||
"container_cpu_usage": `round(sum by (namespace, pod_name, container_name) (irate(container_cpu_usage_seconds_total{job="kubelet", container_name!="POD", container_name!="", image!="", $1}[5m])), 0.001)`,
|
||||
"container_memory_usage": `sum by (namespace, pod_name, container_name) (container_memory_usage_bytes{job="kubelet", container_name!="POD", container_name!="", image!="", $1})`,
|
||||
"container_memory_usage_wo_cache": `sum by (namespace, pod_name, container_name) (container_memory_usage_bytes{job="kubelet", container_name!="POD", container_name!="", image!="", $1} - container_memory_cache{job="kubelet", container_name!="POD", container_name!="", image!="", $1})`,
|
||||
"container_memory_usage_wo_cache": `sum by (namespace, pod_name, container_name) (container_memory_working_set_bytes{job="kubelet", container_name!="POD", container_name!="", image!="", $1})`,
|
||||
|
||||
// pvc
|
||||
"pvc_inodes_available": `max by (namespace, persistentvolumeclaim) (kubelet_volume_stats_inodes_free) * on (namespace, persistentvolumeclaim) group_left (storageclass) kube_persistentvolumeclaim_info{$1}`,
|
||||
@@ -506,3 +516,36 @@ var metricsPromqlMap = map[string]string{
|
||||
"prometheus_up_sum": `prometheus:up:sum`,
|
||||
"prometheus_tsdb_head_samples_appended_rate": `prometheus:prometheus_tsdb_head_samples_appended:sum_rate`,
|
||||
}
|
||||
|
||||
// As of Kubernetes v1.16, any Prometheus queries that match `pod_name` and
|
||||
// `container_name` labels must be updated to use `pod` and `container` instead.
|
||||
func CompatibleMetrics() {
|
||||
if client.ClientSets() == nil {
|
||||
return
|
||||
}
|
||||
|
||||
version, err := client.ClientSets().K8s().Discovery().ServerVersion()
|
||||
if err != nil {
|
||||
klog.Errorf("fail to fetch k8s version: %v.", err)
|
||||
return
|
||||
}
|
||||
|
||||
if version.Minor >= "16" {
|
||||
labelNamePod = "pod"
|
||||
labelNameContainer = "container"
|
||||
|
||||
m := metricsPromqlMap
|
||||
m["workspace_net_bytes_transmitted"] = `sum by (label_kubesphere_io_workspace) (sum by (namespace) (irate(container_network_transmit_bytes_total{namespace!="", pod!="", interface!~"^(cali.+|tunl.+|dummy.+|kube.+|flannel.+|cni.+|docker.+|veth.+|lo.*)", job="kubelet"}[5m])) * on (namespace) group_left(label_kubesphere_io_workspace) kube_namespace_labels{$1})`
|
||||
m["workspace_net_bytes_received"] = `sum by (label_kubesphere_io_workspace) (sum by (namespace) (irate(container_network_receive_bytes_total{namespace!="", pod!="", interface!~"^(cali.+|tunl.+|dummy.+|kube.+|flannel.+|cni.+|docker.+|veth.+|lo.*)", job="kubelet"}[5m])) * on (namespace) group_left(label_kubesphere_io_workspace) kube_namespace_labels{$1})`
|
||||
m["namespace_net_bytes_transmitted"] = `sum by (namespace) (irate(container_network_transmit_bytes_total{namespace!="", pod!="", interface!~"^(cali.+|tunl.+|dummy.+|kube.+|flannel.+|cni.+|docker.+|veth.+|lo.*)", job="kubelet"}[5m]) * on (namespace) group_left(label_kubesphere_io_workspace) kube_namespace_labels{$1})`
|
||||
m["namespace_net_bytes_received"] = `sum by (namespace) (irate(container_network_receive_bytes_total{namespace!="", pod!="", interface!~"^(cali.+|tunl.+|dummy.+|kube.+|flannel.+|cni.+|docker.+|veth.+|lo.*)", job="kubelet"}[5m]) * on (namespace) group_left(label_kubesphere_io_workspace) kube_namespace_labels{$1})`
|
||||
m["pod_cpu_usage"] = `round(sum by (namespace, pod) (irate(container_cpu_usage_seconds_total{job="kubelet", pod!="", image!=""}[5m])) * on (namespace, pod) group_left(owner_kind, owner_name) kube_pod_owner{$1} * on (namespace, pod) group_left(node) kube_pod_info{$2}, 0.001)`
|
||||
m["pod_memory_usage"] = `sum by (namespace, pod) (container_memory_usage_bytes{job="kubelet", pod!="", image!=""}) * on (namespace, pod) group_left(owner_kind, owner_name) kube_pod_owner{$1} * on (namespace, pod) group_left(node) kube_pod_info{$2}`
|
||||
m["pod_memory_usage_wo_cache"] = `sum by (namespace, pod) (container_memory_working_set_bytes{job="kubelet", pod!="", image!=""}) * on (namespace, pod) group_left(owner_kind, owner_name) kube_pod_owner{$1} * on (namespace, pod) group_left(node) kube_pod_info{$2}`
|
||||
m["pod_net_bytes_transmitted"] = `sum by (namespace, pod) (irate(container_network_transmit_bytes_total{pod!="", interface!~"^(cali.+|tunl.+|dummy.+|kube.+|flannel.+|cni.+|docker.+|veth.+|lo.*)", job="kubelet"}[5m])) * on (namespace, pod) group_left(owner_kind, owner_name) kube_pod_owner{$1} * on (namespace, pod) group_left(node) kube_pod_info{$2}`
|
||||
m["pod_net_bytes_received"] = `sum by (namespace, pod) (irate(container_network_receive_bytes_total{pod!="", interface!~"^(cali.+|tunl.+|dummy.+|kube.+|flannel.+|cni.+|docker.+|veth.+|lo.*)", job="kubelet"}[5m])) * on (namespace, pod) group_left(owner_kind, owner_name) kube_pod_owner{$1} * on (namespace, pod) group_left(node) kube_pod_info{$2}`
|
||||
m["container_cpu_usage"] = `round(sum by (namespace, pod, container) (irate(container_cpu_usage_seconds_total{job="kubelet", container!="POD", container!="", image!="", $1}[5m])), 0.001)`
|
||||
m["container_memory_usage"] = `sum by (namespace, pod, container) (container_memory_usage_bytes{job="kubelet", container!="POD", container!="", image!="", $1})`
|
||||
m["container_memory_usage_wo_cache"] = `sum by (namespace, pod, container) (container_memory_working_set_bytes{job="kubelet", container!="POD", container!="", image!="", $1})`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ func (rawMetrics *Response) SortBy(sortMetricName string, sortType string) (*Res
|
||||
// record the ordering of resource_name to indexMap
|
||||
// example: {"metric":{ResultItemMetricResourceName: "Deployment:xxx"},"value":[1541142931.731,"3"]}
|
||||
resourceName, exist := r.Metric[ResultItemMetricResourceName]
|
||||
if exist {
|
||||
if exist && resourceName != "" {
|
||||
if _, exist := indexMap[resourceName]; !exist {
|
||||
indexMap[resourceName] = i
|
||||
i = i + 1
|
||||
@@ -138,7 +138,7 @@ func (rawMetrics *Response) SortBy(sortMetricName string, sortType string) (*Res
|
||||
// iterator all metric to find max metricItems length
|
||||
for _, r := range metricItem.Data.Result {
|
||||
k, ok := r.Metric[ResultItemMetricResourceName]
|
||||
if ok {
|
||||
if ok && k != "" {
|
||||
currentResourceMap[k] = 1
|
||||
}
|
||||
}
|
||||
@@ -167,7 +167,7 @@ func (rawMetrics *Response) SortBy(sortMetricName string, sortType string) (*Res
|
||||
for j := 0; j < len(re.Data.Result); j++ {
|
||||
r := re.Data.Result[j]
|
||||
k, exist := r.Metric[ResultItemMetricResourceName]
|
||||
if exist {
|
||||
if exist && k != "" {
|
||||
index, exist := indexMap[k]
|
||||
if exist {
|
||||
sortedMetric[index] = r
|
||||
|
||||
315
pkg/models/metrics/util_test.go
Normal file
315
pkg/models/metrics/util_test.go
Normal file
@@ -0,0 +1,315 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/api/monitoring/v1alpha2"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSortBy(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
rawMetrics *Response
|
||||
sortMetrics string
|
||||
sortType string
|
||||
expected *Response
|
||||
}{
|
||||
{
|
||||
description: "sort a set of node metrics for node1, node2 and a node with blank name (this should be considered as abnormal).",
|
||||
rawMetrics: &Response{
|
||||
Results: []APIResponse{
|
||||
{
|
||||
MetricName: "node_cpu_usage",
|
||||
APIResponse: v1alpha2.APIResponse{
|
||||
Status: "success",
|
||||
Data: v1alpha2.QueryResult{
|
||||
ResultType: "vector",
|
||||
Result: []v1alpha2.QueryValue{
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node1"},
|
||||
Value: []interface{}{1578987135.334, "0.221"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node2"},
|
||||
Value: []interface{}{1578987135.334, "0.177"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": ""},
|
||||
Value: []interface{}{1578987135.334, ""},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MetricName: "node_memory_total",
|
||||
APIResponse: v1alpha2.APIResponse{
|
||||
Status: "success",
|
||||
Data: v1alpha2.QueryResult{
|
||||
ResultType: "vector",
|
||||
Result: []v1alpha2.QueryValue{
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node1"},
|
||||
Value: []interface{}{1578987135.334, "8201043968"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node2"},
|
||||
Value: []interface{}{1578987135.334, "8201039872"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": ""},
|
||||
Value: []interface{}{1578987135.334, ""},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MetricName: "node_pod_running_count",
|
||||
APIResponse: v1alpha2.APIResponse{
|
||||
Status: "success",
|
||||
Data: v1alpha2.QueryResult{
|
||||
ResultType: "vector",
|
||||
Result: []v1alpha2.QueryValue{
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node1"},
|
||||
Value: []interface{}{1578987135.334, "19"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node2"},
|
||||
Value: []interface{}{1578987135.334, "6"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": ""},
|
||||
Value: []interface{}{1578987135.334, ""},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sortMetrics: "node_cpu_usage",
|
||||
sortType: "desc",
|
||||
expected: &Response{
|
||||
Results: []APIResponse{
|
||||
{
|
||||
MetricName: "node_cpu_usage",
|
||||
APIResponse: v1alpha2.APIResponse{
|
||||
Status: "success",
|
||||
Data: v1alpha2.QueryResult{
|
||||
ResultType: "vector",
|
||||
Result: []v1alpha2.QueryValue{
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node1"},
|
||||
Value: []interface{}{1578987135.334, "0.221"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node2"},
|
||||
Value: []interface{}{1578987135.334, "0.177"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MetricName: "node_memory_total",
|
||||
APIResponse: v1alpha2.APIResponse{
|
||||
Status: "success",
|
||||
Data: v1alpha2.QueryResult{
|
||||
ResultType: "vector",
|
||||
Result: []v1alpha2.QueryValue{
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node1"},
|
||||
Value: []interface{}{1578987135.334, "8201043968"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node2"},
|
||||
Value: []interface{}{1578987135.334, "8201039872"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MetricName: "node_pod_running_count",
|
||||
APIResponse: v1alpha2.APIResponse{
|
||||
Status: "success",
|
||||
Data: v1alpha2.QueryResult{
|
||||
ResultType: "vector",
|
||||
Result: []v1alpha2.QueryValue{
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node1"},
|
||||
Value: []interface{}{1578987135.334, "19"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node2"},
|
||||
Value: []interface{}{1578987135.334, "6"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "sort a set of node metrics for node1, node2 and node3.",
|
||||
rawMetrics: &Response{
|
||||
Results: []APIResponse{
|
||||
{
|
||||
MetricName: "node_cpu_usage",
|
||||
APIResponse: v1alpha2.APIResponse{
|
||||
Status: "success",
|
||||
Data: v1alpha2.QueryResult{
|
||||
ResultType: "vector",
|
||||
Result: []v1alpha2.QueryValue{
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node1"},
|
||||
Value: []interface{}{1578987135.334, "0.221"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node2"},
|
||||
Value: []interface{}{1578987135.334, "0.177"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node3"},
|
||||
Value: []interface{}{1578987135.334, "0.194"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MetricName: "node_memory_total",
|
||||
APIResponse: v1alpha2.APIResponse{
|
||||
Status: "success",
|
||||
Data: v1alpha2.QueryResult{
|
||||
ResultType: "vector",
|
||||
Result: []v1alpha2.QueryValue{
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node1"},
|
||||
Value: []interface{}{1578987135.334, "8201043968"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node2"},
|
||||
Value: []interface{}{1578987135.334, "8201039872"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node3"},
|
||||
Value: []interface{}{1578987135.334, "8201056256"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MetricName: "node_pod_running_count",
|
||||
APIResponse: v1alpha2.APIResponse{
|
||||
Status: "success",
|
||||
Data: v1alpha2.QueryResult{
|
||||
ResultType: "vector",
|
||||
Result: []v1alpha2.QueryValue{
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node1"},
|
||||
Value: []interface{}{1578987135.334, "19"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node2"},
|
||||
Value: []interface{}{1578987135.334, "6"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node3"},
|
||||
Value: []interface{}{1578987135.334, "14"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sortMetrics: "node_cpu_usage",
|
||||
sortType: "desc",
|
||||
expected: &Response{
|
||||
Results: []APIResponse{
|
||||
{
|
||||
MetricName: "node_cpu_usage",
|
||||
APIResponse: v1alpha2.APIResponse{
|
||||
Status: "success",
|
||||
Data: v1alpha2.QueryResult{
|
||||
ResultType: "vector",
|
||||
Result: []v1alpha2.QueryValue{
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node1"},
|
||||
Value: []interface{}{1578987135.334, "0.221"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node3"},
|
||||
Value: []interface{}{1578987135.334, "0.194"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node2"},
|
||||
Value: []interface{}{1578987135.334, "0.177"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MetricName: "node_memory_total",
|
||||
APIResponse: v1alpha2.APIResponse{
|
||||
Status: "success",
|
||||
Data: v1alpha2.QueryResult{
|
||||
ResultType: "vector",
|
||||
Result: []v1alpha2.QueryValue{
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node1"},
|
||||
Value: []interface{}{1578987135.334, "8201043968"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node3"},
|
||||
Value: []interface{}{1578987135.334, "8201056256"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node2"},
|
||||
Value: []interface{}{1578987135.334, "8201039872"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MetricName: "node_pod_running_count",
|
||||
APIResponse: v1alpha2.APIResponse{
|
||||
Status: "success",
|
||||
Data: v1alpha2.QueryResult{
|
||||
ResultType: "vector",
|
||||
Result: []v1alpha2.QueryValue{
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node1"},
|
||||
Value: []interface{}{1578987135.334, "19"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node3"},
|
||||
Value: []interface{}{1578987135.334, "14"},
|
||||
},
|
||||
{
|
||||
Metric: map[string]string{"resource_name": "node2"},
|
||||
Value: []interface{}{1578987135.334, "6"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
res, _ := test.rawMetrics.SortBy(test.sortMetrics, test.sortType)
|
||||
if !reflect.DeepEqual(res, test.expected) {
|
||||
t.Errorf("got unexpected results: %v", res)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,25 +65,25 @@ func ListApplications(conditions *params.Conditions, limit, offset int, orderBy
|
||||
describeClustersRequest := &pb.DescribeClustersRequest{
|
||||
Limit: uint32(limit),
|
||||
Offset: uint32(offset)}
|
||||
if keyword := conditions.Match["keyword"]; keyword != "" {
|
||||
if keyword := conditions.Match[Keyword]; keyword != "" {
|
||||
describeClustersRequest.SearchWord = &wrappers.StringValue{Value: keyword}
|
||||
}
|
||||
if runtimeId := conditions.Match["runtime_id"]; runtimeId != "" {
|
||||
if runtimeId := conditions.Match[RuntimeId]; runtimeId != "" {
|
||||
describeClustersRequest.RuntimeId = []string{runtimeId}
|
||||
}
|
||||
if appId := conditions.Match["app_id"]; appId != "" {
|
||||
if appId := conditions.Match[AppId]; appId != "" {
|
||||
describeClustersRequest.AppId = []string{appId}
|
||||
}
|
||||
if versionId := conditions.Match["version_id"]; versionId != "" {
|
||||
if versionId := conditions.Match[VersionId]; versionId != "" {
|
||||
describeClustersRequest.VersionId = []string{versionId}
|
||||
}
|
||||
if status := conditions.Match["status"]; status != "" {
|
||||
if status := conditions.Match[Status]; status != "" {
|
||||
describeClustersRequest.Status = strings.Split(status, "|")
|
||||
}
|
||||
if orderBy != "" {
|
||||
describeClustersRequest.SortKey = &wrappers.StringValue{Value: orderBy}
|
||||
}
|
||||
describeClustersRequest.Reverse = &wrappers.BoolValue{Value: !reverse}
|
||||
describeClustersRequest.Reverse = &wrappers.BoolValue{Value: reverse}
|
||||
resp, err := client.Cluster().DescribeClusters(openpitrix.SystemContext(), describeClustersRequest)
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
@@ -405,7 +405,8 @@ func DeleteApplication(clusterId string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = client.Cluster().DeleteClusters(openpitrix.SystemContext(), &pb.DeleteClustersRequest{ClusterId: []string{clusterId}, Force: &wrappers.BoolValue{Value: true}})
|
||||
_, err = client.Cluster().CeaseClusters(openpitrix.SystemContext(),
|
||||
&pb.CeaseClustersRequest{ClusterId: []string{clusterId}, Force: &wrappers.BoolValue{Value: true}})
|
||||
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
|
||||
@@ -45,19 +45,19 @@ func ListApps(conditions *params.Conditions, orderBy string, reverse bool, limit
|
||||
}
|
||||
|
||||
describeAppsRequest := &pb.DescribeAppsRequest{}
|
||||
if keyword := conditions.Match["keyword"]; keyword != "" {
|
||||
if keyword := conditions.Match[Keyword]; keyword != "" {
|
||||
describeAppsRequest.SearchWord = &wrappers.StringValue{Value: keyword}
|
||||
}
|
||||
if appId := conditions.Match["app_id"]; appId != "" {
|
||||
if appId := conditions.Match[AppId]; appId != "" {
|
||||
describeAppsRequest.AppId = strings.Split(appId, "|")
|
||||
}
|
||||
if isv := conditions.Match["isv"]; isv != "" {
|
||||
if isv := conditions.Match[ISV]; isv != "" {
|
||||
describeAppsRequest.Isv = strings.Split(isv, "|")
|
||||
}
|
||||
if categoryId := conditions.Match["category_id"]; categoryId != "" {
|
||||
if categoryId := conditions.Match[CategoryId]; categoryId != "" {
|
||||
describeAppsRequest.CategoryId = strings.Split(categoryId, "|")
|
||||
}
|
||||
if repoId := conditions.Match["repo"]; repoId != "" {
|
||||
if repoId := conditions.Match[RepoId]; repoId != "" {
|
||||
// hard code, app template in built-in repo has no repo_id attribute
|
||||
if repoId == BuiltinRepoId {
|
||||
describeAppsRequest.RepoId = []string{"\u0000"}
|
||||
@@ -65,7 +65,7 @@ func ListApps(conditions *params.Conditions, orderBy string, reverse bool, limit
|
||||
describeAppsRequest.RepoId = strings.Split(repoId, "|")
|
||||
}
|
||||
}
|
||||
if status := conditions.Match["status"]; status != "" {
|
||||
if status := conditions.Match[Status]; status != "" {
|
||||
describeAppsRequest.Status = strings.Split(status, "|")
|
||||
}
|
||||
if orderBy != "" {
|
||||
@@ -451,7 +451,7 @@ func DoAppAction(appId string, request *ActionRequest) error {
|
||||
// TODO openpitrix need to implement app suspend interface
|
||||
resp, err := op.App().DescribeAppVersions(openpitrix.SystemContext(), &pb.DescribeAppVersionsRequest{
|
||||
AppId: []string{appId},
|
||||
Status: []string{"active"},
|
||||
Status: []string{StatusActive},
|
||||
Limit: 200,
|
||||
Offset: 0,
|
||||
})
|
||||
@@ -572,22 +572,22 @@ func ListAppVersionAudits(conditions *params.Conditions, orderBy string, reverse
|
||||
|
||||
describeAppVersionAudits := &pb.DescribeAppVersionAuditsRequest{}
|
||||
|
||||
if keyword := conditions.Match["keyword"]; keyword != "" {
|
||||
if keyword := conditions.Match[Keyword]; keyword != "" {
|
||||
describeAppVersionAudits.SearchWord = &wrappers.StringValue{Value: keyword}
|
||||
}
|
||||
if appId := conditions.Match["app"]; appId != "" {
|
||||
if appId := conditions.Match[AppId]; appId != "" {
|
||||
describeAppVersionAudits.AppId = []string{appId}
|
||||
}
|
||||
if versionId := conditions.Match["version"]; versionId != "" {
|
||||
if versionId := conditions.Match[VersionId]; versionId != "" {
|
||||
describeAppVersionAudits.VersionId = []string{versionId}
|
||||
}
|
||||
if status := conditions.Match["status"]; status != "" {
|
||||
if status := conditions.Match[Status]; status != "" {
|
||||
describeAppVersionAudits.Status = strings.Split(status, "|")
|
||||
}
|
||||
if orderBy != "" {
|
||||
describeAppVersionAudits.SortKey = &wrappers.StringValue{Value: orderBy}
|
||||
}
|
||||
describeAppVersionAudits.Reverse = &wrappers.BoolValue{Value: !reverse}
|
||||
describeAppVersionAudits.Reverse = &wrappers.BoolValue{Value: reverse}
|
||||
describeAppVersionAudits.Limit = uint32(limit)
|
||||
describeAppVersionAudits.Offset = uint32(offset)
|
||||
resp, err := client.App().DescribeAppVersionAudits(openpitrix.SystemContext(), describeAppVersionAudits)
|
||||
@@ -617,16 +617,16 @@ func ListAppVersionReviews(conditions *params.Conditions, orderBy string, revers
|
||||
|
||||
describeAppVersionReviews := &pb.DescribeAppVersionReviewsRequest{}
|
||||
|
||||
if keyword := conditions.Match["keyword"]; keyword != "" {
|
||||
if keyword := conditions.Match[Keyword]; keyword != "" {
|
||||
describeAppVersionReviews.SearchWord = &wrappers.StringValue{Value: keyword}
|
||||
}
|
||||
if status := conditions.Match["status"]; status != "" {
|
||||
if status := conditions.Match[Status]; status != "" {
|
||||
describeAppVersionReviews.Status = strings.Split(status, "|")
|
||||
}
|
||||
if orderBy != "" {
|
||||
describeAppVersionReviews.SortKey = &wrappers.StringValue{Value: orderBy}
|
||||
}
|
||||
describeAppVersionReviews.Reverse = &wrappers.BoolValue{Value: !reverse}
|
||||
describeAppVersionReviews.Reverse = &wrappers.BoolValue{Value: reverse}
|
||||
describeAppVersionReviews.Limit = uint32(limit)
|
||||
describeAppVersionReviews.Offset = uint32(offset)
|
||||
// TODO icon is needed
|
||||
@@ -657,19 +657,19 @@ func ListAppVersions(conditions *params.Conditions, orderBy string, reverse bool
|
||||
|
||||
describeAppVersionsRequest := &pb.DescribeAppVersionsRequest{}
|
||||
|
||||
if keyword := conditions.Match["keyword"]; keyword != "" {
|
||||
if keyword := conditions.Match[Keyword]; keyword != "" {
|
||||
describeAppVersionsRequest.SearchWord = &wrappers.StringValue{Value: keyword}
|
||||
}
|
||||
if appId := conditions.Match["app"]; appId != "" {
|
||||
if appId := conditions.Match[AppId]; appId != "" {
|
||||
describeAppVersionsRequest.AppId = []string{appId}
|
||||
}
|
||||
if status := conditions.Match["status"]; status != "" {
|
||||
if status := conditions.Match[Status]; status != "" {
|
||||
describeAppVersionsRequest.Status = strings.Split(status, "|")
|
||||
}
|
||||
if orderBy != "" {
|
||||
describeAppVersionsRequest.SortKey = &wrappers.StringValue{Value: orderBy}
|
||||
}
|
||||
describeAppVersionsRequest.Reverse = &wrappers.BoolValue{Value: !reverse}
|
||||
describeAppVersionsRequest.Reverse = &wrappers.BoolValue{Value: reverse}
|
||||
describeAppVersionsRequest.Limit = uint32(limit)
|
||||
describeAppVersionsRequest.Offset = uint32(offset)
|
||||
resp, err := client.App().DescribeAppVersions(openpitrix.SystemContext(), describeAppVersionsRequest)
|
||||
|
||||
@@ -138,13 +138,13 @@ func ListCategories(conditions *params.Conditions, orderBy string, reverse bool,
|
||||
|
||||
req := &pb.DescribeCategoriesRequest{}
|
||||
|
||||
if keyword := conditions.Match["keyword"]; keyword != "" {
|
||||
if keyword := conditions.Match[Keyword]; keyword != "" {
|
||||
req.SearchWord = &wrappers.StringValue{Value: keyword}
|
||||
}
|
||||
if orderBy != "" {
|
||||
req.SortKey = &wrappers.StringValue{Value: orderBy}
|
||||
}
|
||||
req.Reverse = &wrappers.BoolValue{Value: !reverse}
|
||||
req.Reverse = &wrappers.BoolValue{Value: reverse}
|
||||
req.Limit = uint32(limit)
|
||||
req.Offset = uint32(offset)
|
||||
resp, err := client.Category().DescribeCategories(openpitrix.SystemContext(), req)
|
||||
|
||||
@@ -169,28 +169,28 @@ func ListRepos(conditions *params.Conditions, orderBy string, reverse bool, limi
|
||||
|
||||
req := &pb.DescribeReposRequest{}
|
||||
|
||||
if keyword := conditions.Match["keyword"]; keyword != "" {
|
||||
if keyword := conditions.Match[Keyword]; keyword != "" {
|
||||
req.SearchWord = &wrappers.StringValue{Value: keyword}
|
||||
}
|
||||
if status := conditions.Match["status"]; status != "" {
|
||||
if status := conditions.Match[Status]; status != "" {
|
||||
req.Status = strings.Split(status, "|")
|
||||
}
|
||||
if typeStr := conditions.Match["type"]; typeStr != "" {
|
||||
if typeStr := conditions.Match[Type]; typeStr != "" {
|
||||
req.Type = strings.Split(typeStr, "|")
|
||||
}
|
||||
if visibility := conditions.Match["visibility"]; visibility != "" {
|
||||
if visibility := conditions.Match[Visibility]; visibility != "" {
|
||||
req.Visibility = strings.Split(visibility, "|")
|
||||
}
|
||||
if status := conditions.Match["status"]; status != "" {
|
||||
if status := conditions.Match[Status]; status != "" {
|
||||
req.Status = strings.Split(status, "|")
|
||||
}
|
||||
if workspace := conditions.Match["workspace"]; workspace != "" {
|
||||
if workspace := conditions.Match[WorkspaceLabel]; workspace != "" {
|
||||
req.Label = &wrappers.StringValue{Value: fmt.Sprintf("workspace=%s", workspace)}
|
||||
}
|
||||
if orderBy != "" {
|
||||
req.SortKey = &wrappers.StringValue{Value: orderBy}
|
||||
}
|
||||
req.Reverse = &wrappers.BoolValue{Value: !reverse}
|
||||
req.Reverse = &wrappers.BoolValue{Value: reverse}
|
||||
req.Limit = uint32(limit)
|
||||
req.Offset = uint32(offset)
|
||||
resp, err := client.Repo().DescribeRepos(openpitrix.SystemContext(), req)
|
||||
@@ -270,10 +270,10 @@ func ListRepoEvents(repoId string, conditions *params.Conditions, limit, offset
|
||||
describeRepoEventsRequest := &pb.DescribeRepoEventsRequest{
|
||||
RepoId: []string{repoId},
|
||||
}
|
||||
if eventId := conditions.Match["repo_event_id"]; eventId != "" {
|
||||
if eventId := conditions.Match[RepoEventId]; eventId != "" {
|
||||
describeRepoEventsRequest.RepoEventId = strings.Split(eventId, "|")
|
||||
}
|
||||
if status := conditions.Match["status"]; status != "" {
|
||||
if status := conditions.Match[Status]; status != "" {
|
||||
describeRepoEventsRequest.Status = strings.Split(status, "|")
|
||||
}
|
||||
describeRepoEventsRequest.Limit = uint32(limit)
|
||||
|
||||
@@ -835,3 +835,20 @@ type ModifyClusterAttributesRequest struct {
|
||||
// cluster name
|
||||
Name *string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
const (
|
||||
CreateTime = "create_time"
|
||||
StatusTime = "status_time"
|
||||
RuntimeId = "runtime_id"
|
||||
VersionId = "version_id"
|
||||
RepoId = "repo_id"
|
||||
CategoryId = "category_id"
|
||||
RepoEventId = "repo_event_id"
|
||||
Status = "status"
|
||||
Type = "type"
|
||||
Visibility = "visibility"
|
||||
AppId = "app_id"
|
||||
Keyword = "keyword"
|
||||
ISV = "isv"
|
||||
WorkspaceLabel = "workspace"
|
||||
)
|
||||
|
||||
@@ -2,9 +2,11 @@ package registries
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/go-digest"
|
||||
log "k8s.io/klog"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Image holds information about an image.
|
||||
@@ -30,9 +32,28 @@ func (i *Image) Reference() string {
|
||||
return i.Tag
|
||||
}
|
||||
|
||||
type DockerURL struct {
|
||||
*url.URL
|
||||
}
|
||||
|
||||
func (u *DockerURL) StringWithoutScheme() string {
|
||||
u.Scheme = ""
|
||||
s := u.String()
|
||||
return strings.Trim(s, "//")
|
||||
}
|
||||
|
||||
func ParseDockerURL(rawurl string) (*DockerURL, error) {
|
||||
url, err := url.Parse(rawurl)
|
||||
if err != nil {
|
||||
log.Errorf("%+v", err)
|
||||
return nil, err
|
||||
}
|
||||
return &DockerURL{URL: url}, nil
|
||||
}
|
||||
|
||||
// ParseImage returns an Image struct with all the values filled in for a given image.
|
||||
// example : localhost:5000/nginx:latest, nginx:perl etc.
|
||||
func ParseImage(image string) (Image, error) {
|
||||
func ParseImage(image string) (i Image, err error) {
|
||||
// Parse the image name and tag.
|
||||
named, err := reference.ParseNormalizedNamed(image)
|
||||
if err != nil {
|
||||
@@ -41,7 +62,7 @@ func ParseImage(image string) (Image, error) {
|
||||
// Add the latest lag if they did not provide one.
|
||||
named = reference.TagNameOnly(named)
|
||||
|
||||
i := Image{
|
||||
i = Image{
|
||||
named: named,
|
||||
Domain: reference.Domain(named),
|
||||
Path: reference.Path(named),
|
||||
|
||||
73
pkg/models/registries/image_test.go
Normal file
73
pkg/models/registries/image_test.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package registries
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseImage(t *testing.T) {
|
||||
type testImage struct {
|
||||
inputImageName string
|
||||
ExImage Image
|
||||
}
|
||||
|
||||
testImages := []testImage{
|
||||
{inputImageName: "dockerhub.qingcloud.com/kubesphere/test:v1", ExImage: Image{Domain: "dockerhub.qingcloud.com", Tag: "v1", Path: "kubesphere/test"}},
|
||||
{inputImageName: "harbor.devops.kubesphere.local:30280/library/tomcat:latest", ExImage: Image{Domain: "harbor.devops.kubesphere.local:30280", Tag: "latest", Path: "library/tomcat"}},
|
||||
{inputImageName: "zhuxiaoyang/nginx:v1", ExImage: Image{Domain: "docker.io", Tag: "v1", Path: "zhuxiaoyang/nginx"}},
|
||||
{inputImageName: "nginx", ExImage: Image{Domain: "docker.io", Tag: "latest", Path: "library/nginx"}},
|
||||
{inputImageName: "nginx:latest", ExImage: Image{Domain: "docker.io", Tag: "latest", Path: "library/nginx"}},
|
||||
{inputImageName: "kubesphere/ks-account:v2.1.0", ExImage: Image{Domain: "docker.io", Tag: "v2.1.0", Path: "kubesphere/ks-account"}},
|
||||
{inputImageName: "http://docker.io/nginx:latest", ExImage: Image{}},
|
||||
{inputImageName: "https://harbor.devops.kubesphere.local:30280/library/tomcat:latest", ExImage: Image{}},
|
||||
{inputImageName: "docker.io/nginx:latest:latest", ExImage: Image{}},
|
||||
{inputImageName: "nginx:8000:latest", ExImage: Image{}},
|
||||
}
|
||||
|
||||
for _, image := range testImages {
|
||||
res, err := ParseImage(image.inputImageName)
|
||||
if err != nil {
|
||||
if res != image.ExImage {
|
||||
t.Fatalf("Get err %s", err)
|
||||
}
|
||||
}
|
||||
if res.Domain != image.ExImage.Domain {
|
||||
t.Fatalf("Doamin got %v, expected %v", res.Domain, image.ExImage.Domain)
|
||||
}
|
||||
|
||||
if res.Tag != image.ExImage.Tag {
|
||||
t.Fatalf("Tag got %v, expected %v", res.Tag, image.ExImage.Tag)
|
||||
}
|
||||
|
||||
if res.Path != image.ExImage.Path {
|
||||
t.Fatalf("Path got %v, expected %v", res.Path, image.ExImage.Path)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestStringWithoutScheme(t *testing.T) {
|
||||
type testRawUrl struct {
|
||||
Rawurl string
|
||||
ExUrl string
|
||||
}
|
||||
testRawurls := []testRawUrl{
|
||||
{"http://dockerhub.qingcloud.com/kubesphere/nginx:v1", "dockerhub.qingcloud.com/kubesphere/nginx:v1"},
|
||||
{"https://dockerhub.qingcloud.com/kubesphere/nginx:v1", "dockerhub.qingcloud.com/kubesphere/nginx:v1"},
|
||||
{"http://harbor.devops.kubesphere.local:30280/library/tomcat:latest", "harbor.devops.kubesphere.local:30280/library/tomcat:latest"},
|
||||
{"https://harbor.devops.kubesphere.local:30280/library/tomcat:latest", "harbor.devops.kubesphere.local:30280/library/tomcat:latest"},
|
||||
}
|
||||
|
||||
for _, rawurl := range testRawurls {
|
||||
dockerurl, err := ParseDockerURL(rawurl.Rawurl)
|
||||
if err != nil {
|
||||
t.Fatalf("Get err %s", err)
|
||||
}
|
||||
|
||||
imageName := dockerurl.StringWithoutScheme()
|
||||
|
||||
if imageName != rawurl.ExUrl {
|
||||
t.Fatalf("imagename got %v, expected %v", imageName, rawurl.ExUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// TODO: deprecated, use github.com/docker/docker/api/types.AuthConfig instead
|
||||
type AuthInfo struct {
|
||||
Username string `json:"username" description:"username"`
|
||||
Password string `json:"password" description:"password"`
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
func TestDigestFromDockerHub(t *testing.T) {
|
||||
|
||||
testImage := Image{Domain: "docker.io", Path: "library/alpine", Tag: "latest"}
|
||||
r, err := CreateRegistryClient("", "", "docker.io")
|
||||
r, err := CreateRegistryClient("", "", "docker.io", true)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get client: %s", err)
|
||||
}
|
||||
|
||||
@@ -25,9 +25,11 @@ import (
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/client"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/klog"
|
||||
log "k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -58,7 +60,7 @@ func RegistryVerify(authInfo AuthInfo) error {
|
||||
cli, err := client.NewClientWithOpts(client.WithAPIVersionNegotiation())
|
||||
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
log.Error(err)
|
||||
}
|
||||
|
||||
config := types.AuthConfig{
|
||||
@@ -68,6 +70,22 @@ func RegistryVerify(authInfo AuthInfo) error {
|
||||
ServerAddress: authInfo.ServerHost,
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(authInfo.ServerHost, "https://") && !strings.HasPrefix(authInfo.ServerHost, "http://") {
|
||||
authInfo.ServerHost = "https://" + authInfo.ServerHost
|
||||
}
|
||||
|
||||
u, err := url.Parse(authInfo.ServerHost)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if u.Host != DefaultDockerHub {
|
||||
_, err := http.Get(authInfo.ServerHost + "/v2/")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: deprecated, use native Docker Registry v2 authentication.
|
||||
resp, err := cli.RegistryLogin(ctx, config)
|
||||
cli.Close()
|
||||
|
||||
|
||||
33
pkg/models/registries/registries_test.go
Normal file
33
pkg/models/registries/registries_test.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package registries
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRegistryVerify(t *testing.T) {
|
||||
type testRegistry struct {
|
||||
Auth AuthInfo
|
||||
Result bool
|
||||
}
|
||||
|
||||
// some registry can not login with guest.
|
||||
registries := []testRegistry{
|
||||
{Auth: AuthInfo{Username: "guest", Password: "guest", ServerHost: "docker.io"}, Result: true},
|
||||
{Auth: AuthInfo{Username: "guest", Password: "guest", ServerHost: "https://docker.io"}, Result: true},
|
||||
{Auth: AuthInfo{Username: "guest", Password: "guest", ServerHost: "dockerhub.qingcloud.com"}, Result: true},
|
||||
{Auth: AuthInfo{Username: "guest", Password: "guest", ServerHost: "https://dockerhub.qingcloud.com"}, Result: true},
|
||||
{Auth: AuthInfo{Username: "guest", Password: "guest", ServerHost: "http://dockerhub.qingcloud.com"}, Result: false},
|
||||
{Auth: AuthInfo{Username: "guest", Password: "guest", ServerHost: "registry.cn-hangzhou.aliyuncs.com"}, Result: false},
|
||||
}
|
||||
|
||||
for _, registry := range registries {
|
||||
err := RegistryVerify(registry.Auth)
|
||||
if registry.Result == true && err != nil {
|
||||
t.Fatalf("Get err %s", err)
|
||||
}
|
||||
|
||||
if registry.Result == false && err == nil {
|
||||
t.Fatalf("Input Wrong data but without any error.")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ type authService struct {
|
||||
Scope []string
|
||||
}
|
||||
|
||||
func CreateRegistryClient(username, password, domain string) (*Registry, error) {
|
||||
func CreateRegistryClient(username, password, domain string, useSSL bool) (*Registry, error) {
|
||||
authDomain := domain
|
||||
auth, err := GetAuthConfig(username, password, authDomain)
|
||||
if err != nil {
|
||||
@@ -75,6 +75,7 @@ func CreateRegistryClient(username, password, domain string) (*Registry, error)
|
||||
// Create the registry client.
|
||||
return New(auth, RegistryOpt{
|
||||
Domain: domain,
|
||||
UseSSL: useSSL,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
const DockerHub = "docker.io"
|
||||
|
||||
func TestCreateRegistryClient(t *testing.T) {
|
||||
type imageInfo struct {
|
||||
Username string
|
||||
@@ -11,17 +13,19 @@ func TestCreateRegistryClient(t *testing.T) {
|
||||
Domain string
|
||||
ExDomain string
|
||||
ExUrl string
|
||||
UseSSL bool
|
||||
}
|
||||
|
||||
testImages := []imageInfo{
|
||||
{Domain: "kubesphere.io", ExDomain: "kubesphere.io", ExUrl: "http://kubesphere.io"},
|
||||
{Domain: "127.0.0.1:5000", ExDomain: "127.0.0.1:5000", ExUrl: "http://127.0.0.1:5000"},
|
||||
{Username: "Username", Password: "Password", Domain: "docker.io", ExDomain: "registry-1.docker.io", ExUrl: "https://registry-1.docker.io"},
|
||||
{Domain: "harbor.devops.kubesphere.local:30280", ExDomain: "harbor.devops.kubesphere.local:30280", ExUrl: "http://harbor.devops.kubesphere.local:30280"},
|
||||
{Domain: "kubesphere.io", ExDomain: "kubesphere.io", ExUrl: "https://kubesphere.io", UseSSL: true},
|
||||
{Domain: "127.0.0.1:5000", ExDomain: "127.0.0.1:5000", ExUrl: "http://127.0.0.1:5000", UseSSL: false},
|
||||
{Username: "Username", Password: "Password", Domain: DockerHub, ExDomain: "registry-1.docker.io", ExUrl: "https://registry-1.docker.io", UseSSL: true},
|
||||
{Domain: "harbor.devops.kubesphere.local:30280", ExDomain: "harbor.devops.kubesphere.local:30280", ExUrl: "http://harbor.devops.kubesphere.local:30280", UseSSL: false},
|
||||
{Domain: "dockerhub.qingcloud.com/zxytest/s2i-jj:jj", ExDomain: "dockerhub.qingcloud.com", ExUrl: "https://dockerhub.qingcloud.com/zxytest/s2i-jj:jj", UseSSL: true},
|
||||
}
|
||||
|
||||
for _, testImage := range testImages {
|
||||
reg, err := CreateRegistryClient(testImage.Username, testImage.Password, testImage.Domain)
|
||||
reg, err := CreateRegistryClient(testImage.Username, testImage.Password, testImage.Domain, testImage.UseSSL)
|
||||
if err != nil {
|
||||
t.Fatalf("Get err %s", err)
|
||||
}
|
||||
@@ -36,8 +40,8 @@ func TestCreateRegistryClient(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
testImage := Image{Domain: "docker.io", Path: "library/alpine", Tag: "latest"}
|
||||
r, err := CreateRegistryClient("", "", "docker.io")
|
||||
testImage := Image{Domain: DockerHub, Path: "library/alpine", Tag: "latest"}
|
||||
r, err := CreateRegistryClient("", "", DockerHub, true)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get client: %s", err)
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ func (asm authServiceMock) equalTo(v *authService) bool {
|
||||
|
||||
func TestToken(t *testing.T) {
|
||||
testImage := Image{Domain: "docker.io", Path: "library/alpine", Tag: "latest"}
|
||||
r, err := CreateRegistryClient("", "", "docker.io")
|
||||
r, err := CreateRegistryClient("", "", "docker.io", true)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get registry client: %s", err)
|
||||
}
|
||||
|
||||
@@ -19,14 +19,11 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sigs.k8s.io/application/pkg/apis/app/v1beta1"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type appSearcher struct {
|
||||
@@ -37,67 +34,27 @@ func (*appSearcher) get(namespace, name string) (interface{}, error) {
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*appSearcher) match(match map[string]string, item *v1beta1.Application) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
func (*appSearcher) match(kv map[string]string, item *v1beta1.Application) bool {
|
||||
for k, v := range kv {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*appSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Application) bool {
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*appSearcher) fuzzy(kv map[string]string, item *v1beta1.Application) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*appSearcher) compare(a, b *v1beta1.Application, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *appSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -18,16 +18,13 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
type clusterRoleSearcher struct {
|
||||
@@ -38,26 +35,17 @@ func (*clusterRoleSearcher) get(namespace, name string) (interface{}, error) {
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRole) bool {
|
||||
for k, v := range match {
|
||||
func (*clusterRoleSearcher) match(kv map[string]string, item *rbac.ClusterRole) bool {
|
||||
for k, v := range kv {
|
||||
switch k {
|
||||
case OwnerKind:
|
||||
fallthrough
|
||||
case OwnerName:
|
||||
kind := match[OwnerKind]
|
||||
name := match[OwnerName]
|
||||
kind := kv[OwnerKind]
|
||||
name := kv[OwnerName]
|
||||
if !k8sutil.IsControlledBy(item.OwnerReferences, kind, name) {
|
||||
return false
|
||||
}
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
case UserFacing:
|
||||
if v == "true" {
|
||||
if !isUserFacingClusterRole(item) {
|
||||
@@ -65,8 +53,7 @@ func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRol
|
||||
}
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -75,40 +62,17 @@ func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRol
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*clusterRoleSearcher) fuzzy(fuzzy map[string]string, item *rbac.ClusterRole) bool {
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*clusterRoleSearcher) fuzzy(kv map[string]string, item *rbac.ClusterRole) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*clusterRoleSearcher) compare(a, b *rbac.ClusterRole, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *clusterRoleSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -18,15 +18,11 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type configMapSearcher struct {
|
||||
@@ -37,67 +33,27 @@ func (*configMapSearcher) get(namespace, name string) (interface{}, error) {
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*configMapSearcher) match(match map[string]string, item *v1.ConfigMap) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
func (*configMapSearcher) match(kv map[string]string, item *v1.ConfigMap) bool {
|
||||
for k, v := range kv {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*configMapSearcher) fuzzy(fuzzy map[string]string, item *v1.ConfigMap) bool {
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*configMapSearcher) fuzzy(kv map[string]string, item *v1.ConfigMap) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*configMapSearcher) compare(a, b *v1.ConfigMap, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *configMapSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -18,10 +18,8 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -45,25 +43,15 @@ func cronJobStatus(item *v1beta1.CronJob) string {
|
||||
}
|
||||
|
||||
// Exactly Match
|
||||
func (*cronJobSearcher) match(match map[string]string, item *v1beta1.CronJob) bool {
|
||||
for k, v := range match {
|
||||
func (*cronJobSearcher) match(kv map[string]string, item *v1beta1.CronJob) bool {
|
||||
for k, v := range kv {
|
||||
switch k {
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Status:
|
||||
if cronJobStatus(item) != v {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -71,34 +59,12 @@ func (*cronJobSearcher) match(match map[string]string, item *v1beta1.CronJob) bo
|
||||
return true
|
||||
}
|
||||
|
||||
func (*cronJobSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.CronJob) bool {
|
||||
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*cronJobSearcher) fuzzy(kv map[string]string, item *v1beta1.CronJob) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -111,13 +77,12 @@ func (*cronJobSearcher) compare(a, b *v1beta1.CronJob, orderBy string) bool {
|
||||
if b.Status.LastScheduleTime == nil {
|
||||
return false
|
||||
}
|
||||
if a.Status.LastScheduleTime.Equal(b.Status.LastScheduleTime) {
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return a.Status.LastScheduleTime.Before(b.Status.LastScheduleTime)
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
default:
|
||||
fallthrough
|
||||
case Name:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,15 +18,11 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/apps/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type daemonSetSearcher struct {
|
||||
@@ -47,25 +43,15 @@ func daemonSetStatus(item *v1.DaemonSet) string {
|
||||
}
|
||||
|
||||
// Exactly Match
|
||||
func (*daemonSetSearcher) match(match map[string]string, item *v1.DaemonSet) bool {
|
||||
for k, v := range match {
|
||||
func (*daemonSetSearcher) match(kv map[string]string, item *v1.DaemonSet) bool {
|
||||
for k, v := range kv {
|
||||
switch k {
|
||||
case Status:
|
||||
if daemonSetStatus(item) != v {
|
||||
return false
|
||||
}
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -73,46 +59,17 @@ func (*daemonSetSearcher) match(match map[string]string, item *v1.DaemonSet) boo
|
||||
return true
|
||||
}
|
||||
|
||||
func (*daemonSetSearcher) fuzzy(fuzzy map[string]string, item *v1.DaemonSet) bool {
|
||||
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*daemonSetSearcher) fuzzy(kv map[string]string, item *v1.DaemonSet) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (*daemonSetSearcher) compare(a, b *v1.DaemonSet, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *daemonSetSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -18,10 +18,8 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -52,25 +50,15 @@ func deploymentStatus(item *v1.Deployment) string {
|
||||
}
|
||||
|
||||
// Exactly Match
|
||||
func (*deploymentSearcher) match(match map[string]string, item *v1.Deployment) bool {
|
||||
for k, v := range match {
|
||||
func (*deploymentSearcher) match(kv map[string]string, item *v1.Deployment) bool {
|
||||
for k, v := range kv {
|
||||
switch k {
|
||||
case Status:
|
||||
if deploymentStatus(item) != v {
|
||||
return false
|
||||
}
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -78,47 +66,27 @@ func (*deploymentSearcher) match(match map[string]string, item *v1.Deployment) b
|
||||
return true
|
||||
}
|
||||
|
||||
func (*deploymentSearcher) fuzzy(fuzzy map[string]string, item *v1.Deployment) bool {
|
||||
func (*deploymentSearcher) fuzzy(kv map[string]string, item *v1.Deployment) bool {
|
||||
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *deploymentSearcher) compare(a, b *v1.Deployment, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case UpdateTime:
|
||||
return s.lastUpdateTime(a).Before(s.lastUpdateTime(b))
|
||||
case Name:
|
||||
fallthrough
|
||||
aLastUpdateTime := s.lastUpdateTime(a)
|
||||
bLastUpdateTime := s.lastUpdateTime(b)
|
||||
if aLastUpdateTime.Equal(bLastUpdateTime) {
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return aLastUpdateTime.Before(bLastUpdateTime)
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,14 +19,10 @@ package resources
|
||||
|
||||
import (
|
||||
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
type hpaSearcher struct {
|
||||
@@ -41,28 +37,19 @@ func hpaTargetMatch(item *autoscalingv2beta2.HorizontalPodAutoscaler, kind, name
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*hpaSearcher) match(match map[string]string, item *autoscalingv2beta2.HorizontalPodAutoscaler) bool {
|
||||
for k, v := range match {
|
||||
func (*hpaSearcher) match(kv map[string]string, item *autoscalingv2beta2.HorizontalPodAutoscaler) bool {
|
||||
for k, v := range kv {
|
||||
switch k {
|
||||
case TargetKind:
|
||||
fallthrough
|
||||
case TargetName:
|
||||
kind := match[TargetKind]
|
||||
name := match[TargetName]
|
||||
kind := kv[TargetKind]
|
||||
name := kv[TargetName]
|
||||
if !hpaTargetMatch(item, kind, name) {
|
||||
return false
|
||||
}
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if item.Labels[k] != v {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -71,44 +58,17 @@ func (*hpaSearcher) match(match map[string]string, item *autoscalingv2beta2.Hori
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*hpaSearcher) fuzzy(fuzzy map[string]string, item *autoscalingv2beta2.HorizontalPodAutoscaler) bool {
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*hpaSearcher) fuzzy(kv map[string]string, item *autoscalingv2beta2.HorizontalPodAutoscaler) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) && !searchFuzzy(item.Annotations, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*hpaSearcher) compare(a, b *autoscalingv2beta2.HorizontalPodAutoscaler, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *hpaSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -18,14 +18,10 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
extensions "k8s.io/api/extensions/v1beta1"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
@@ -38,67 +34,27 @@ func (*ingressSearcher) get(namespace, name string) (interface{}, error) {
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*ingressSearcher) match(match map[string]string, item *extensions.Ingress) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
func (*ingressSearcher) match(kv map[string]string, item *extensions.Ingress) bool {
|
||||
for k, v := range kv {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*ingressSearcher) fuzzy(fuzzy map[string]string, item *extensions.Ingress) bool {
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*ingressSearcher) fuzzy(kv map[string]string, item *extensions.Ingress) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*ingressSearcher) compare(a, b *extensions.Ingress, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *ingressSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -18,11 +18,9 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -51,8 +49,8 @@ func jobStatus(item *batchv1.Job) string {
|
||||
}
|
||||
|
||||
// Exactly Match
|
||||
func (*jobSearcher) match(match map[string]string, item *batchv1.Job) bool {
|
||||
for k, v := range match {
|
||||
func (*jobSearcher) match(kv map[string]string, item *batchv1.Job) bool {
|
||||
for k, v := range kv {
|
||||
switch k {
|
||||
case Status:
|
||||
if jobStatus(item) != v {
|
||||
@@ -66,18 +64,8 @@ func (*jobSearcher) match(match map[string]string, item *batchv1.Job) bool {
|
||||
if v == "false" && k8sutil.IsControlledBy(item.OwnerReferences, s2iRunKind, "") {
|
||||
return false
|
||||
}
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -85,34 +73,12 @@ func (*jobSearcher) match(match map[string]string, item *batchv1.Job) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (*jobSearcher) fuzzy(fuzzy map[string]string, item *batchv1.Job) bool {
|
||||
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*jobSearcher) fuzzy(kv map[string]string, item *batchv1.Job) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -131,14 +97,15 @@ func jobUpdateTime(item *batchv1.Job) time.Time {
|
||||
|
||||
func (*jobSearcher) compare(a, b *batchv1.Job, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case UpdateTime:
|
||||
return jobUpdateTime(a).Before(jobUpdateTime(b))
|
||||
case Name:
|
||||
fallthrough
|
||||
aUpdateTime := jobUpdateTime(a)
|
||||
bUpdateTime := jobUpdateTime(b)
|
||||
if aUpdateTime.Equal(bUpdateTime) {
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return aUpdateTime.Before(bUpdateTime)
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,15 +18,11 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type namespaceSearcher struct {
|
||||
@@ -37,67 +33,27 @@ func (*namespaceSearcher) get(namespace, name string) (interface{}, error) {
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*namespaceSearcher) match(match map[string]string, item *v1.Namespace) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
func (*namespaceSearcher) match(kv map[string]string, item *v1.Namespace) bool {
|
||||
for k, v := range kv {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*namespaceSearcher) fuzzy(fuzzy map[string]string, item *v1.Namespace) bool {
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*namespaceSearcher) fuzzy(kv map[string]string, item *v1.Namespace) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*namespaceSearcher) compare(a, b *v1.Namespace, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *namespaceSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -19,15 +19,11 @@ package resources
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type nodeSearcher struct {
|
||||
@@ -53,10 +49,14 @@ func getNodeStatus(node *v1.Node) string {
|
||||
const NodeConfigOK v1.NodeConditionType = "ConfigOK"
|
||||
const NodeKubeletReady v1.NodeConditionType = "KubeletReady"
|
||||
|
||||
var expectedConditions = map[v1.NodeConditionType]v1.ConditionStatus{v1.NodeOutOfDisk: v1.ConditionFalse,
|
||||
v1.NodeMemoryPressure: v1.ConditionFalse, v1.NodeDiskPressure: v1.ConditionFalse, v1.NodePIDPressure: v1.ConditionFalse,
|
||||
v1.NodeNetworkUnavailable: v1.ConditionFalse, NodeConfigOK: v1.ConditionTrue, NodeKubeletReady: v1.ConditionTrue,
|
||||
v1.NodeReady: v1.ConditionTrue,
|
||||
var expectedConditions = map[v1.NodeConditionType]v1.ConditionStatus{
|
||||
v1.NodeMemoryPressure: v1.ConditionFalse,
|
||||
v1.NodeDiskPressure: v1.ConditionFalse,
|
||||
v1.NodePIDPressure: v1.ConditionFalse,
|
||||
v1.NodeNetworkUnavailable: v1.ConditionFalse,
|
||||
NodeConfigOK: v1.ConditionTrue,
|
||||
NodeKubeletReady: v1.ConditionTrue,
|
||||
v1.NodeReady: v1.ConditionTrue,
|
||||
}
|
||||
|
||||
func isUnhealthStatus(condition v1.NodeCondition) bool {
|
||||
@@ -68,14 +68,9 @@ func isUnhealthStatus(condition v1.NodeCondition) bool {
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool {
|
||||
for k, v := range match {
|
||||
func (*nodeSearcher) match(kv map[string]string, item *v1.Node) bool {
|
||||
for k, v := range kv {
|
||||
switch k {
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Role:
|
||||
labelKey := fmt.Sprintf("node-role.kubernetes.io/%s", v)
|
||||
if _, ok := item.Labels[labelKey]; !ok {
|
||||
@@ -85,13 +80,8 @@ func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool {
|
||||
if getNodeStatus(item) != v {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -100,44 +90,17 @@ func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool {
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*nodeSearcher) fuzzy(fuzzy map[string]string, item *v1.Node) bool {
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*nodeSearcher) fuzzy(kv map[string]string, item *v1.Node) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*nodeSearcher) compare(a, b *v1.Node, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *nodeSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
@@ -49,14 +48,9 @@ func pvcStatus(item *v1.PersistentVolumeClaim) string {
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.PersistentVolumeClaim) bool {
|
||||
for k, v := range match {
|
||||
func (*persistentVolumeClaimSearcher) match(kv map[string]string, item *v1.PersistentVolumeClaim) bool {
|
||||
for k, v := range kv {
|
||||
switch k {
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Status:
|
||||
statuses := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(statuses, pvcStatus(item)) {
|
||||
@@ -66,13 +60,8 @@ func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.Pe
|
||||
if item.Spec.StorageClassName == nil || *item.Spec.StorageClassName != v {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -81,44 +70,17 @@ func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.Pe
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*persistentVolumeClaimSearcher) fuzzy(fuzzy map[string]string, item *v1.PersistentVolumeClaim) bool {
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*persistentVolumeClaimSearcher) fuzzy(kv map[string]string, item *v1.PersistentVolumeClaim) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*persistentVolumeClaimSearcher) compare(a, b *v1.PersistentVolumeClaim, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *persistentVolumeClaimSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -19,10 +19,8 @@ package resources
|
||||
|
||||
import (
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -147,14 +145,14 @@ func podBelongToService(item *v1.Pod, serviceName string) bool {
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*podSearcher) match(match map[string]string, item *v1.Pod) bool {
|
||||
for k, v := range match {
|
||||
func (*podSearcher) match(kv map[string]string, item *v1.Pod) bool {
|
||||
for k, v := range kv {
|
||||
switch k {
|
||||
case OwnerKind:
|
||||
fallthrough
|
||||
case OwnerName:
|
||||
kind := match[OwnerKind]
|
||||
name := match[OwnerName]
|
||||
kind := kv[OwnerKind]
|
||||
name := kv[OwnerName]
|
||||
if !podBelongTo(item, kind, name) {
|
||||
return false
|
||||
}
|
||||
@@ -170,18 +168,8 @@ func (*podSearcher) match(match map[string]string, item *v1.Pod) bool {
|
||||
if !podBelongToService(item, v) {
|
||||
return false
|
||||
}
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -190,30 +178,10 @@ func (*podSearcher) match(match map[string]string, item *v1.Pod) bool {
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*podSearcher) fuzzy(fuzzy map[string]string, item *v1.Pod) bool {
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*podSearcher) fuzzy(kv map[string]string, item *v1.Pod) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
@@ -228,13 +196,12 @@ func (*podSearcher) compare(a, b *v1.Pod, orderBy string) bool {
|
||||
if b.Status.StartTime == nil {
|
||||
return true
|
||||
}
|
||||
if a.Status.StartTime.Equal(b.Status.StartTime) {
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return a.Status.StartTime.Before(b.Status.StartTime)
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,9 @@ package resources
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
@@ -160,13 +162,26 @@ func ListResources(namespace, resource string, conditions *params.Conditions, or
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i, item := range result {
|
||||
if i >= offset && (limit == -1 || len(items) < limit) {
|
||||
items = append(items, injector.addExtraAnnotations(item))
|
||||
}
|
||||
totalCount := len(result)
|
||||
|
||||
// query all
|
||||
if limit < 0 || offset < 0 {
|
||||
result = result[:totalCount]
|
||||
// out of range
|
||||
} else if offset > totalCount {
|
||||
result = result[:0]
|
||||
// last page
|
||||
} else if limit+offset > totalCount {
|
||||
result = result[offset:totalCount]
|
||||
} else {
|
||||
result = result[offset : offset+limit]
|
||||
}
|
||||
|
||||
return &models.PageableResponse{TotalCount: len(result), Items: items}, nil
|
||||
for _, item := range result {
|
||||
items = append(items, injector.addExtraAnnotations(item))
|
||||
}
|
||||
|
||||
return &models.PageableResponse{TotalCount: totalCount, Items: items}, nil
|
||||
}
|
||||
|
||||
func searchFuzzy(m map[string]string, key, value string) bool {
|
||||
@@ -181,3 +196,64 @@ func searchFuzzy(m map[string]string, key, value string) bool {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func match(key, value string, item metav1.ObjectMeta) bool {
|
||||
switch key {
|
||||
case Name:
|
||||
names := strings.Split(value, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, value) && !searchFuzzy(item.Labels, "", value) && !searchFuzzy(item.Annotations, "", value) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[key]; !ok || val != value {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func fuzzy(key, value string, item metav1.ObjectMeta) bool {
|
||||
switch key {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, value) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], value) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", value) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", value) {
|
||||
return false
|
||||
}
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], value) && !strings.Contains(item.Labels[release], value) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, key, value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func compare(a, b metav1.ObjectMeta, by string) bool {
|
||||
switch by {
|
||||
case CreateTime:
|
||||
if a.CreationTimestamp.Equal(&b.CreationTimestamp) {
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,15 +18,12 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
type roleSearcher struct {
|
||||
@@ -37,18 +34,9 @@ func (*roleSearcher) get(namespace, name string) (interface{}, error) {
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*roleSearcher) match(match map[string]string, item *rbac.Role) bool {
|
||||
for k, v := range match {
|
||||
func (*roleSearcher) match(kv map[string]string, item *rbac.Role) bool {
|
||||
for k, v := range kv {
|
||||
switch k {
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
case UserFacing:
|
||||
if v == "true" {
|
||||
if !isUserFacingRole(item) {
|
||||
@@ -56,8 +44,7 @@ func (*roleSearcher) match(match map[string]string, item *rbac.Role) bool {
|
||||
}
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -66,40 +53,17 @@ func (*roleSearcher) match(match map[string]string, item *rbac.Role) bool {
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*roleSearcher) fuzzy(fuzzy map[string]string, item *rbac.Role) bool {
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*roleSearcher) fuzzy(kv map[string]string, item *rbac.Role) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*roleSearcher) compare(a, b *rbac.Role, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *roleSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -21,12 +21,9 @@ package resources
|
||||
import (
|
||||
"github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type s2iBuilderSearcher struct {
|
||||
@@ -37,67 +34,27 @@ func (*s2iBuilderSearcher) get(namespace, name string) (interface{}, error) {
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*s2iBuilderSearcher) match(match map[string]string, item *v1alpha1.S2iBuilder) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
func (*s2iBuilderSearcher) match(kv map[string]string, item *v1alpha1.S2iBuilder) bool {
|
||||
for k, v := range kv {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*s2iBuilderSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iBuilder) bool {
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*s2iBuilderSearcher) fuzzy(kv map[string]string, item *v1alpha1.S2iBuilder) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*s2iBuilderSearcher) compare(a, b *v1alpha1.S2iBuilder, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *s2iBuilderSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -19,14 +19,10 @@ package resources
|
||||
|
||||
import (
|
||||
"github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
type s2iBuilderTemplateSearcher struct {
|
||||
@@ -37,63 +33,27 @@ func (*s2iBuilderTemplateSearcher) get(namespace, name string) (interface{}, err
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*s2iBuilderTemplateSearcher) match(match map[string]string, item *v1alpha1.S2iBuilderTemplate) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
func (*s2iBuilderTemplateSearcher) match(kv map[string]string, item *v1alpha1.S2iBuilderTemplate) bool {
|
||||
for k, v := range kv {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*s2iBuilderTemplateSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iBuilderTemplate) bool {
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*s2iBuilderTemplateSearcher) fuzzy(kv map[string]string, item *v1alpha1.S2iBuilderTemplate) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*s2iBuilderTemplateSearcher) compare(a, b *v1alpha1.S2iBuilderTemplate, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *s2iBuilderTemplateSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -19,13 +19,9 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
|
||||
@@ -40,25 +36,15 @@ func (*s2iRunSearcher) get(namespace, name string) (interface{}, error) {
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*s2iRunSearcher) match(match map[string]string, item *v1alpha1.S2iRun) bool {
|
||||
for k, v := range match {
|
||||
func (*s2iRunSearcher) match(kv map[string]string, item *v1alpha1.S2iRun) bool {
|
||||
for k, v := range kv {
|
||||
switch k {
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Status:
|
||||
if string(item.Status.RunState) != v {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -67,44 +53,17 @@ func (*s2iRunSearcher) match(match map[string]string, item *v1alpha1.S2iRun) boo
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*s2iRunSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iRun) bool {
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*s2iRunSearcher) fuzzy(kv map[string]string, item *v1alpha1.S2iRun) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*s2iRunSearcher) compare(a, b *v1alpha1.S2iRun, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *s2iRunSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -18,15 +18,11 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type secretSearcher struct {
|
||||
@@ -37,25 +33,15 @@ func (*secretSearcher) get(namespace, name string) (interface{}, error) {
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*secretSearcher) match(match map[string]string, item *v1.Secret) bool {
|
||||
for k, v := range match {
|
||||
func (*secretSearcher) match(kv map[string]string, item *v1.Secret) bool {
|
||||
for k, v := range kv {
|
||||
switch k {
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case "type":
|
||||
if string(item.Type) != v {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -64,44 +50,17 @@ func (*secretSearcher) match(match map[string]string, item *v1.Secret) bool {
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*secretSearcher) fuzzy(fuzzy map[string]string, item *v1.Secret) bool {
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*secretSearcher) fuzzy(kv map[string]string, item *v1.Secret) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*secretSearcher) compare(a, b *v1.Secret, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *secretSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -18,15 +18,11 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type serviceSearcher struct {
|
||||
@@ -37,67 +33,27 @@ func (*serviceSearcher) get(namespace, name string) (interface{}, error) {
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*serviceSearcher) match(match map[string]string, item *v1.Service) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
func (*serviceSearcher) match(kv map[string]string, item *v1.Service) bool {
|
||||
for k, v := range kv {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*serviceSearcher) fuzzy(fuzzy map[string]string, item *v1.Service) bool {
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*serviceSearcher) fuzzy(kv map[string]string, item *v1.Service) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*serviceSearcher) compare(a, b *v1.Service, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *serviceSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -18,15 +18,11 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/apps/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type statefulSetSearcher struct {
|
||||
@@ -50,25 +46,15 @@ func statefulSetStatus(item *v1.StatefulSet) string {
|
||||
}
|
||||
|
||||
// Exactly Match
|
||||
func (*statefulSetSearcher) match(match map[string]string, item *v1.StatefulSet) bool {
|
||||
for k, v := range match {
|
||||
func (*statefulSetSearcher) match(kv map[string]string, item *v1.StatefulSet) bool {
|
||||
for k, v := range kv {
|
||||
switch k {
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
case Status:
|
||||
if statefulSetStatus(item) != v {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -76,46 +62,17 @@ func (*statefulSetSearcher) match(match map[string]string, item *v1.StatefulSet)
|
||||
return true
|
||||
}
|
||||
|
||||
func (*statefulSetSearcher) fuzzy(fuzzy map[string]string, item *v1.StatefulSet) bool {
|
||||
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*statefulSetSearcher) fuzzy(kv map[string]string, item *v1.StatefulSet) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (*statefulSetSearcher) compare(a, b *v1.StatefulSet, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *statefulSetSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -18,15 +18,11 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/storage/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type storageClassesSearcher struct {
|
||||
@@ -37,63 +33,27 @@ func (*storageClassesSearcher) get(namespace, name string) (interface{}, error)
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*storageClassesSearcher) match(match map[string]string, item *v1.StorageClass) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
func (*storageClassesSearcher) match(kv map[string]string, item *v1.StorageClass) bool {
|
||||
for k, v := range kv {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*storageClassesSearcher) fuzzy(fuzzy map[string]string, item *v1.StorageClass) bool {
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*storageClassesSearcher) fuzzy(kv map[string]string, item *v1.StorageClass) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*storageClassesSearcher) compare(a, b *v1.StorageClass, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *storageClassesSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -18,15 +18,11 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
type workspaceSearcher struct {
|
||||
@@ -37,67 +33,27 @@ func (*workspaceSearcher) get(namespace, name string) (interface{}, error) {
|
||||
}
|
||||
|
||||
// exactly Match
|
||||
func (*workspaceSearcher) match(match map[string]string, item *tenantv1alpha1.Workspace) bool {
|
||||
for k, v := range match {
|
||||
switch k {
|
||||
case Name:
|
||||
names := strings.Split(v, "|")
|
||||
if !sliceutil.HasString(names, item.Name) {
|
||||
return false
|
||||
}
|
||||
case Keyword:
|
||||
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
// label not exist or value not equal
|
||||
if val, ok := item.Labels[k]; !ok || val != v {
|
||||
return false
|
||||
}
|
||||
func (*workspaceSearcher) match(kv map[string]string, item *tenantv1alpha1.Workspace) bool {
|
||||
for k, v := range kv {
|
||||
if !match(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fuzzy searchInNamespace
|
||||
func (*workspaceSearcher) fuzzy(fuzzy map[string]string, item *tenantv1alpha1.Workspace) bool {
|
||||
for k, v := range fuzzy {
|
||||
switch k {
|
||||
case Name:
|
||||
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
|
||||
return false
|
||||
}
|
||||
case Label:
|
||||
if !searchFuzzy(item.Labels, "", v) {
|
||||
return false
|
||||
}
|
||||
case annotation:
|
||||
if !searchFuzzy(item.Annotations, "", v) {
|
||||
return false
|
||||
}
|
||||
func (*workspaceSearcher) fuzzy(kv map[string]string, item *tenantv1alpha1.Workspace) bool {
|
||||
for k, v := range kv {
|
||||
if !fuzzy(k, v, item.ObjectMeta) {
|
||||
return false
|
||||
case app:
|
||||
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
if !searchFuzzy(item.Labels, k, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (*workspaceSearcher) compare(a, b *tenantv1alpha1.Workspace, orderBy string) bool {
|
||||
switch orderBy {
|
||||
case CreateTime:
|
||||
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
|
||||
case Name:
|
||||
fallthrough
|
||||
default:
|
||||
return strings.Compare(a.Name, b.Name) <= 0
|
||||
}
|
||||
return compare(a.ObjectMeta, b.ObjectMeta, orderBy)
|
||||
}
|
||||
|
||||
func (s *workspaceSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
|
||||
|
||||
@@ -21,6 +21,7 @@ package routers
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
v1 "k8s.io/api/apps/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/klog"
|
||||
@@ -31,8 +32,7 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
|
||||
"strings"
|
||||
@@ -41,24 +41,24 @@ import (
|
||||
)
|
||||
|
||||
// choose router node ip by labels, currently select master node
|
||||
var RouterNodeIPLabelSelector = map[string]string{
|
||||
var routerNodeIPLabelSelector = map[string]string{
|
||||
"node-role.kubernetes.io/master": "",
|
||||
}
|
||||
|
||||
const (
|
||||
SERVICEMESH_ENABLED = "servicemesh.kubesphere.io/enabled"
|
||||
SIDECAR_INJECT = "sidecar.istio.io/inject"
|
||||
servicemeshEnabled = "servicemesh.kubesphere.io/enabled"
|
||||
sidecarInject = "sidecar.istio.io/inject"
|
||||
)
|
||||
|
||||
var routerTemplates map[string]runtime.Object
|
||||
|
||||
// Load yamls
|
||||
func init() {
|
||||
yamls, err := LoadYamls()
|
||||
yamls, err := loadYamls()
|
||||
routerTemplates = make(map[string]runtime.Object, 2)
|
||||
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
klog.Warning("error happened during loading external yamls", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ func init() {
|
||||
switch obj.(type) {
|
||||
case *corev1.Service:
|
||||
routerTemplates["SERVICE"] = obj
|
||||
case *extensionsv1beta1.Deployment:
|
||||
case *v1.Deployment:
|
||||
routerTemplates["DEPLOYMENT"] = obj
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,7 @@ func init() {
|
||||
func getMasterNodeIp() string {
|
||||
|
||||
nodeLister := informers.SharedInformerFactory().Core().V1().Nodes().Lister()
|
||||
selector := labels.SelectorFromSet(RouterNodeIPLabelSelector)
|
||||
selector := labels.SelectorFromSet(routerNodeIPLabelSelector)
|
||||
|
||||
masters, err := nodeLister.List(selector)
|
||||
sort.Slice(masters, func(i, j int) bool {
|
||||
@@ -174,13 +174,13 @@ func getRouterService(namespace string) (*corev1.Service, error) {
|
||||
}
|
||||
|
||||
// Load all resource yamls
|
||||
func LoadYamls() ([]string, error) {
|
||||
func loadYamls() ([]string, error) {
|
||||
|
||||
var yamls []string
|
||||
|
||||
files, err := ioutil.ReadDir(constants.IngressControllerFolder)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
klog.Warning(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ func LoadYamls() ([]string, error) {
|
||||
func CreateRouter(namespace string, routerType corev1.ServiceType, annotations map[string]string) (*corev1.Service, error) {
|
||||
|
||||
injectSidecar := false
|
||||
if enabled, ok := annotations[SERVICEMESH_ENABLED]; ok {
|
||||
if enabled, ok := annotations[servicemeshEnabled]; ok {
|
||||
if enabled == "true" {
|
||||
injectSidecar = true
|
||||
}
|
||||
@@ -307,7 +307,7 @@ func deleteRouterService(namespace string) (*corev1.Service, error) {
|
||||
|
||||
// delete controller service
|
||||
serviceName := constants.IngressControllerPrefix + namespace
|
||||
deleteOptions := meta_v1.DeleteOptions{}
|
||||
deleteOptions := metav1.DeleteOptions{}
|
||||
|
||||
err = k8sClient.CoreV1().Services(constants.IngressControllerNamespace).Delete(serviceName, &deleteOptions)
|
||||
if err != nil {
|
||||
@@ -328,13 +328,13 @@ func createOrUpdateRouterWorkload(namespace string, publishService bool, service
|
||||
deployName := constants.IngressControllerPrefix + namespace
|
||||
|
||||
k8sClient := client.ClientSets().K8s().Kubernetes()
|
||||
deployment, err := k8sClient.ExtensionsV1beta1().Deployments(constants.IngressControllerNamespace).Get(deployName, meta_v1.GetOptions{})
|
||||
deployment, err := k8sClient.AppsV1().Deployments(constants.IngressControllerNamespace).Get(deployName, metav1.GetOptions{})
|
||||
|
||||
createDeployment := true
|
||||
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
deployment = obj.(*extensionsv1beta1.Deployment)
|
||||
deployment = obj.(*v1.Deployment)
|
||||
|
||||
deployment.Name = constants.IngressControllerPrefix + namespace
|
||||
|
||||
@@ -376,9 +376,9 @@ func createOrUpdateRouterWorkload(namespace string, publishService bool, service
|
||||
deployment.Spec.Template.Annotations = make(map[string]string, 0)
|
||||
}
|
||||
if servicemeshEnabled {
|
||||
deployment.Spec.Template.Annotations[SIDECAR_INJECT] = "true"
|
||||
deployment.Spec.Template.Annotations[sidecarInject] = "true"
|
||||
} else {
|
||||
deployment.Spec.Template.Annotations[SIDECAR_INJECT] = "false"
|
||||
deployment.Spec.Template.Annotations[sidecarInject] = "false"
|
||||
}
|
||||
|
||||
if publishService {
|
||||
@@ -388,9 +388,9 @@ func createOrUpdateRouterWorkload(namespace string, publishService bool, service
|
||||
}
|
||||
|
||||
if createDeployment {
|
||||
deployment, err = k8sClient.ExtensionsV1beta1().Deployments(constants.IngressControllerNamespace).Create(deployment)
|
||||
deployment, err = k8sClient.AppsV1().Deployments(constants.IngressControllerNamespace).Create(deployment)
|
||||
} else {
|
||||
deployment, err = k8sClient.ExtensionsV1beta1().Deployments(constants.IngressControllerNamespace).Update(deployment)
|
||||
deployment, err = k8sClient.AppsV1().Deployments(constants.IngressControllerNamespace).Update(deployment)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -404,10 +404,10 @@ func createOrUpdateRouterWorkload(namespace string, publishService bool, service
|
||||
func deleteRouterWorkload(namespace string) error {
|
||||
k8sClient := client.ClientSets().K8s().Kubernetes()
|
||||
|
||||
deleteOptions := meta_v1.DeleteOptions{}
|
||||
deleteOptions := metav1.DeleteOptions{}
|
||||
// delete controller deployment
|
||||
deploymentName := constants.IngressControllerPrefix + namespace
|
||||
err := k8sClient.ExtensionsV1beta1().Deployments(constants.IngressControllerNamespace).Delete(deploymentName, &deleteOptions)
|
||||
err := k8sClient.AppsV1().Deployments(constants.IngressControllerNamespace).Delete(deploymentName, &deleteOptions)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
}
|
||||
@@ -448,7 +448,7 @@ func UpdateRouter(namespace string, routerType corev1.ServiceType, annotations m
|
||||
return router, err
|
||||
}
|
||||
|
||||
enableServicemesh := annotations[SERVICEMESH_ENABLED] == "true"
|
||||
enableServicemesh := annotations[servicemeshEnabled] == "true"
|
||||
|
||||
err = createOrUpdateRouterWorkload(namespace, routerType == corev1.ServiceTypeLoadBalancer, enableServicemesh)
|
||||
if err != nil {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/simple/client"
|
||||
"strconv"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
@@ -27,16 +28,17 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
)
|
||||
|
||||
const (
|
||||
IsDefaultStorageClassAnnotation = "storageclass.kubernetes.io/is-default-class"
|
||||
betaIsDefaultStorageClassAnnotation = "storageclass.beta.kubernetes.io/is-default-class"
|
||||
)
|
||||
|
||||
type ScMetrics struct {
|
||||
Capacity string `json:"capacity,omitempty"`
|
||||
Usage string `json:"usage,omitempty"`
|
||||
PvcNumber string `json:"pvcNumber"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
}
|
||||
|
||||
func GetPvcListBySc(scName string) ([]*v1.PersistentVolumeClaim, error) {
|
||||
persistentVolumeClaimLister := informers.SharedInformerFactory().Core().V1().PersistentVolumeClaims().Lister()
|
||||
all, err := persistentVolumeClaimLister.List(labels.Everything())
|
||||
@@ -102,3 +104,36 @@ func GetScList() ([]*storageV1.StorageClass, error) {
|
||||
|
||||
return scList, nil
|
||||
}
|
||||
|
||||
func SetDefaultStorageClass(defaultScName string) (*storageV1.StorageClass, error) {
|
||||
scLister := informers.SharedInformerFactory().Storage().V1().StorageClasses().Lister()
|
||||
// 1. verify storage class name
|
||||
sc, err := scLister.Get(defaultScName)
|
||||
if sc == nil || err != nil {
|
||||
return sc, err
|
||||
}
|
||||
// 2. unset all default sc and then set default sc
|
||||
scList, err := scLister.List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
k8sClient := client.ClientSets().K8s().Kubernetes()
|
||||
var defaultSc *storageV1.StorageClass
|
||||
for _, sc := range scList {
|
||||
_, hasDefault := sc.Annotations[IsDefaultStorageClassAnnotation]
|
||||
_, hasBeta := sc.Annotations[betaIsDefaultStorageClassAnnotation]
|
||||
if sc.Name == defaultScName || hasDefault || hasBeta {
|
||||
delete(sc.Annotations, IsDefaultStorageClassAnnotation)
|
||||
delete(sc.Annotations, betaIsDefaultStorageClassAnnotation)
|
||||
if sc.Name == defaultScName {
|
||||
sc.Annotations[IsDefaultStorageClassAnnotation] = "true"
|
||||
defaultSc = sc
|
||||
}
|
||||
_, err := k8sClient.StorageV1().StorageClasses().Update(sc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultSc, nil
|
||||
}
|
||||
|
||||
@@ -123,9 +123,7 @@ func (s *workspaceSearcher) search(username string, conditions *params.Condition
|
||||
// order & reverse
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if reverse {
|
||||
tmp := i
|
||||
i = j
|
||||
j = tmp
|
||||
i, j = j, i
|
||||
}
|
||||
return s.compare(result[i], result[j], orderBy)
|
||||
})
|
||||
|
||||
@@ -156,16 +156,26 @@ func DeleteWorkspaceRoleBinding(workspace, username string, role string) error {
|
||||
}
|
||||
workspaceRoleBinding = workspaceRoleBinding.DeepCopy()
|
||||
|
||||
for i, v := range workspaceRoleBinding.Subjects {
|
||||
if v.Kind == v1.UserKind && v.Name == username {
|
||||
workspaceRoleBinding.Subjects = append(workspaceRoleBinding.Subjects[:i], workspaceRoleBinding.Subjects[i+1:]...)
|
||||
i--
|
||||
subjects := make([]v1.Subject, 0)
|
||||
|
||||
for _, subject := range workspaceRoleBinding.Subjects {
|
||||
if subject.Kind != v1.UserKind || subject.Name != username {
|
||||
subjects = append(subjects, subject)
|
||||
}
|
||||
}
|
||||
|
||||
workspaceRoleBinding, err = clientset.ClientSets().K8s().Kubernetes().RbacV1().ClusterRoleBindings().Update(workspaceRoleBinding)
|
||||
if len(subjects) != len(workspaceRoleBinding.Subjects) {
|
||||
workspaceRoleBinding.Subjects = subjects
|
||||
|
||||
return err
|
||||
_, err = clientset.ClientSets().K8s().Kubernetes().RbacV1().ClusterRoleBindings().Update(workspaceRoleBinding)
|
||||
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetDevOpsProjectsCount(workspaceName string) (int, error) {
|
||||
|
||||
@@ -30,22 +30,26 @@ const (
|
||||
OrderByParam = "orderBy"
|
||||
ConditionsParam = "conditions"
|
||||
ReverseParam = "reverse"
|
||||
NameParam = "name"
|
||||
defaultLimit = 10
|
||||
defaultOffset = 0
|
||||
)
|
||||
|
||||
func ParsePaging(paging string) (limit, offset int) {
|
||||
|
||||
limit = 10
|
||||
offset = 0
|
||||
func ParsePaging(req *restful.Request) (limit, offset int) {
|
||||
paging := req.QueryParameter(PagingParam)
|
||||
if groups := regexp.MustCompile(`^limit=(-?\d+),page=(\d+)$`).FindStringSubmatch(paging); len(groups) == 3 {
|
||||
limit, _ = strconv.Atoi(groups[1])
|
||||
page, _ := strconv.Atoi(groups[2])
|
||||
offset = (page - 1) * limit
|
||||
} else {
|
||||
limit = defaultLimit
|
||||
offset = defaultOffset
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ParseConditions(conditionsStr string) (*Conditions, error) {
|
||||
func ParseConditions(req *restful.Request) (*Conditions, error) {
|
||||
|
||||
conditionsStr := req.QueryParameter(ConditionsParam)
|
||||
|
||||
conditions := &Conditions{Match: make(map[string]string, 0), Fuzzy: make(map[string]string, 0)}
|
||||
|
||||
@@ -76,16 +80,23 @@ func ParseConditions(conditionsStr string) (*Conditions, error) {
|
||||
return conditions, nil
|
||||
}
|
||||
|
||||
func ParseReverse(req *restful.Request) bool {
|
||||
reverse := req.QueryParameter(ReverseParam)
|
||||
b, err := strconv.ParseBool(reverse)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
type Conditions struct {
|
||||
Match map[string]string
|
||||
Fuzzy map[string]string
|
||||
}
|
||||
|
||||
func GetBoolValueWithDefault(req *restful.Request, name string, dv bool) bool {
|
||||
reverse := req.QueryParameter(name)
|
||||
if v, err := strconv.ParseBool(reverse); err == nil {
|
||||
return v
|
||||
}
|
||||
return dv
|
||||
}
|
||||
|
||||
func GetStringValueWithDefault(req *restful.Request, name string, dv string) string {
|
||||
v := req.QueryParameter(name)
|
||||
if v == "" {
|
||||
v = dv
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package k8s
|
||||
|
||||
import (
|
||||
applicationclientset "github.com/kubernetes-sigs/application/pkg/client/clientset/versioned"
|
||||
s2i "github.com/kubesphere/s2ioperator/pkg/client/clientset/versioned"
|
||||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||
applicationclientset "sigs.k8s.io/application/pkg/client/clientset/versioned"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
||||
@@ -212,16 +212,15 @@ func (c *OpenPitrixClient) Attachment() pb.AttachmentManagerClient {
|
||||
}
|
||||
|
||||
func SystemContext() context.Context {
|
||||
ctx := context.Background()
|
||||
ctx = ctxutil.ContextWithSender(ctx, sender.New(SystemUsername, SystemUserPath, ""))
|
||||
return ctx
|
||||
return ContextWithUsername(SystemUsername)
|
||||
}
|
||||
func ContextWithUsername(username string) context.Context {
|
||||
ctx := context.Background()
|
||||
if username == "" {
|
||||
username = SystemUsername
|
||||
}
|
||||
ctx = ctxutil.ContextWithSender(ctx, sender.New(username, SystemUserPath, ""))
|
||||
ownerPath := fmt.Sprintf(":%s", username)
|
||||
ctx = ctxutil.ContextWithSender(ctx, sender.New(username, sender.OwnerPath(ownerPath), ""))
|
||||
return ctx
|
||||
}
|
||||
|
||||
|
||||
15
vendor/github.com/kiali/kiali/business/workloads.go
generated
vendored
15
vendor/github.com/kiali/kiali/business/workloads.go
generated
vendored
@@ -6,8 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
osappsv1 "github.com/openshift/api/apps/v1"
|
||||
"k8s.io/api/apps/v1beta1"
|
||||
"k8s.io/api/apps/v1beta2"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
batch_v1 "k8s.io/api/batch/v1"
|
||||
batch_v1beta1 "k8s.io/api/batch/v1beta1"
|
||||
"k8s.io/api/core/v1"
|
||||
@@ -123,10 +122,10 @@ func (in *WorkloadService) GetPods(namespace string, labelSelector string) (mode
|
||||
func fetchWorkloads(k8s kubernetes.IstioClientInterface, namespace string, labelSelector string) (models.Workloads, error) {
|
||||
var pods []v1.Pod
|
||||
var repcon []v1.ReplicationController
|
||||
var dep []v1beta1.Deployment
|
||||
var repset []v1beta2.ReplicaSet
|
||||
var dep []appsv1.Deployment
|
||||
var repset []appsv1.ReplicaSet
|
||||
var depcon []osappsv1.DeploymentConfig
|
||||
var fulset []v1beta2.StatefulSet
|
||||
var fulset []appsv1.StatefulSet
|
||||
var jbs []batch_v1.Job
|
||||
var conjbs []batch_v1beta1.CronJob
|
||||
|
||||
@@ -572,10 +571,10 @@ func fetchWorkloads(k8s kubernetes.IstioClientInterface, namespace string, label
|
||||
func fetchWorkload(k8s kubernetes.IstioClientInterface, namespace string, workloadName string) (*models.Workload, error) {
|
||||
var pods []v1.Pod
|
||||
var repcon []v1.ReplicationController
|
||||
var dep *v1beta1.Deployment
|
||||
var repset []v1beta2.ReplicaSet
|
||||
var dep *appsv1.Deployment
|
||||
var repset []appsv1.ReplicaSet
|
||||
var depcon *osappsv1.DeploymentConfig
|
||||
var fulset *v1beta2.StatefulSet
|
||||
var fulset *appsv1.StatefulSet
|
||||
var jbs []batch_v1.Job
|
||||
var conjbs []batch_v1beta1.CronJob
|
||||
|
||||
|
||||
77
vendor/github.com/kiali/kiali/kubernetes/cache.go
generated
vendored
77
vendor/github.com/kiali/kiali/kubernetes/cache.go
generated
vendored
@@ -6,8 +6,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/apps/v1beta1"
|
||||
"k8s.io/api/apps/v1beta2"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
batch_v1 "k8s.io/api/batch/v1"
|
||||
batch_v1beta1 "k8s.io/api/batch/v1beta1"
|
||||
"k8s.io/api/core/v1"
|
||||
@@ -31,17 +30,17 @@ type (
|
||||
|
||||
// Business methods
|
||||
GetCronJobs(namespace string) ([]batch_v1beta1.CronJob, error)
|
||||
GetDeployment(namespace string, name string) (*v1beta1.Deployment, error)
|
||||
GetDeployments(namespace string) ([]v1beta1.Deployment, error)
|
||||
GetDeployment(namespace string, name string) (*appsv1.Deployment, error)
|
||||
GetDeployments(namespace string) ([]appsv1.Deployment, error)
|
||||
GetEndpoints(namespace, name string) (*v1.Endpoints, error)
|
||||
GetJobs(namespace string) ([]batch_v1.Job, error)
|
||||
GetPods(namespace string) ([]v1.Pod, error)
|
||||
GetReplicationControllers(namespace string) ([]v1.ReplicationController, error)
|
||||
GetReplicaSets(namespace string) ([]v1beta2.ReplicaSet, error)
|
||||
GetReplicaSets(namespace string) ([]appsv1.ReplicaSet, error)
|
||||
GetService(namespace string, name string) (*v1.Service, error)
|
||||
GetServices(namespace string) ([]v1.Service, error)
|
||||
GetStatefulSet(namespace string, name string) (*v1beta2.StatefulSet, error)
|
||||
GetStatefulSets(namespace string) ([]v1beta2.StatefulSet, error)
|
||||
GetStatefulSet(namespace string, name string) (*appsv1.StatefulSet, error)
|
||||
GetStatefulSets(namespace string) ([]appsv1.StatefulSet, error)
|
||||
}
|
||||
|
||||
controllerImpl struct {
|
||||
@@ -106,9 +105,9 @@ func initControllers(clientset kube.Interface, refreshDuration time.Duration) ma
|
||||
controllers := make(map[string]cache.SharedIndexInformer)
|
||||
controllers["Pod"] = sharedInformers.Core().V1().Pods().Informer()
|
||||
controllers["ReplicationController"] = sharedInformers.Core().V1().ReplicationControllers().Informer()
|
||||
controllers["Deployment"] = sharedInformers.Apps().V1beta1().Deployments().Informer()
|
||||
controllers["ReplicaSet"] = sharedInformers.Apps().V1beta2().ReplicaSets().Informer()
|
||||
controllers["StatefulSet"] = sharedInformers.Apps().V1beta2().StatefulSets().Informer()
|
||||
controllers["Deployment"] = sharedInformers.Apps().V1().Deployments().Informer()
|
||||
controllers["ReplicaSet"] = sharedInformers.Apps().V1().ReplicaSets().Informer()
|
||||
controllers["StatefulSet"] = sharedInformers.Apps().V1().StatefulSets().Informer()
|
||||
controllers["Job"] = sharedInformers.Batch().V1().Jobs().Informer()
|
||||
controllers["CronJob"] = sharedInformers.Batch().V1beta1().CronJobs().Informer()
|
||||
controllers["Service"] = sharedInformers.Core().V1().Services().Informer()
|
||||
@@ -221,7 +220,7 @@ func (c *controllerImpl) GetCronJobs(namespace string) ([]batch_v1beta1.CronJob,
|
||||
return []batch_v1beta1.CronJob{}, nil
|
||||
}
|
||||
|
||||
func (c *controllerImpl) GetDeployment(namespace, name string) (*v1beta1.Deployment, error) {
|
||||
func (c *controllerImpl) GetDeployment(namespace, name string) (*appsv1.Deployment, error) {
|
||||
if err := c.checkStateAndRetry(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -231,36 +230,36 @@ func (c *controllerImpl) GetDeployment(namespace, name string) (*v1beta1.Deploym
|
||||
return nil, err
|
||||
}
|
||||
if exist {
|
||||
dep, ok := deps.(*v1beta1.Deployment)
|
||||
dep, ok := deps.(*appsv1.Deployment)
|
||||
if !ok {
|
||||
return nil, errors.New("Bad Deployment type found in cache")
|
||||
}
|
||||
return dep, nil
|
||||
}
|
||||
return nil, NewNotFound(name, "apps/v1beta1", "Deployment")
|
||||
return nil, NewNotFound(name, "apps/v1", "Deployment")
|
||||
}
|
||||
|
||||
func (c *controllerImpl) GetDeployments(namespace string) ([]v1beta1.Deployment, error) {
|
||||
func (c *controllerImpl) GetDeployments(namespace string) ([]appsv1.Deployment, error) {
|
||||
if err := c.checkStateAndRetry(); err != nil {
|
||||
return []v1beta1.Deployment{}, err
|
||||
return []appsv1.Deployment{}, err
|
||||
}
|
||||
indexer := c.controllers["Deployment"].GetIndexer()
|
||||
deps, err := indexer.ByIndex("namespace", namespace)
|
||||
if err != nil {
|
||||
return []v1beta1.Deployment{}, err
|
||||
return []appsv1.Deployment{}, err
|
||||
}
|
||||
if len(deps) > 0 {
|
||||
_, ok := deps[0].(*v1beta1.Deployment)
|
||||
_, ok := deps[0].(*appsv1.Deployment)
|
||||
if !ok {
|
||||
return nil, errors.New("Bad Deployment type found in cache")
|
||||
}
|
||||
nsDeps := make([]v1beta1.Deployment, len(deps))
|
||||
nsDeps := make([]appsv1.Deployment, len(deps))
|
||||
for i, dep := range deps {
|
||||
nsDeps[i] = *(dep.(*v1beta1.Deployment))
|
||||
nsDeps[i] = *(dep.(*appsv1.Deployment))
|
||||
}
|
||||
return nsDeps, nil
|
||||
}
|
||||
return []v1beta1.Deployment{}, nil
|
||||
return []appsv1.Deployment{}, nil
|
||||
}
|
||||
|
||||
func (c *controllerImpl) GetEndpoints(namespace, name string) (*v1.Endpoints, error) {
|
||||
@@ -351,30 +350,30 @@ func (c *controllerImpl) GetReplicationControllers(namespace string) ([]v1.Repli
|
||||
return []v1.ReplicationController{}, nil
|
||||
}
|
||||
|
||||
func (c *controllerImpl) GetReplicaSets(namespace string) ([]v1beta2.ReplicaSet, error) {
|
||||
func (c *controllerImpl) GetReplicaSets(namespace string) ([]appsv1.ReplicaSet, error) {
|
||||
if err := c.checkStateAndRetry(); err != nil {
|
||||
return []v1beta2.ReplicaSet{}, err
|
||||
return []appsv1.ReplicaSet{}, err
|
||||
}
|
||||
indexer := c.controllers["ReplicaSet"].GetIndexer()
|
||||
repsets, err := indexer.ByIndex("namespace", namespace)
|
||||
if err != nil {
|
||||
return []v1beta2.ReplicaSet{}, err
|
||||
return []appsv1.ReplicaSet{}, err
|
||||
}
|
||||
if len(repsets) > 0 {
|
||||
_, ok := repsets[0].(*v1beta2.ReplicaSet)
|
||||
_, ok := repsets[0].(*appsv1.ReplicaSet)
|
||||
if !ok {
|
||||
return []v1beta2.ReplicaSet{}, errors.New("Bad ReplicaSet type found in cache")
|
||||
return []appsv1.ReplicaSet{}, errors.New("Bad ReplicaSet type found in cache")
|
||||
}
|
||||
nsRepsets := make([]v1beta2.ReplicaSet, len(repsets))
|
||||
nsRepsets := make([]appsv1.ReplicaSet, len(repsets))
|
||||
for i, repset := range repsets {
|
||||
nsRepsets[i] = *(repset.(*v1beta2.ReplicaSet))
|
||||
nsRepsets[i] = *(repset.(*appsv1.ReplicaSet))
|
||||
}
|
||||
return nsRepsets, nil
|
||||
}
|
||||
return []v1beta2.ReplicaSet{}, nil
|
||||
return []appsv1.ReplicaSet{}, nil
|
||||
}
|
||||
|
||||
func (c *controllerImpl) GetStatefulSet(namespace, name string) (*v1beta2.StatefulSet, error) {
|
||||
func (c *controllerImpl) GetStatefulSet(namespace, name string) (*appsv1.StatefulSet, error) {
|
||||
if err := c.checkStateAndRetry(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -384,36 +383,36 @@ func (c *controllerImpl) GetStatefulSet(namespace, name string) (*v1beta2.Statef
|
||||
return nil, err
|
||||
}
|
||||
if exist {
|
||||
fulset, ok := fulsets.(*v1beta2.StatefulSet)
|
||||
fulset, ok := fulsets.(*appsv1.StatefulSet)
|
||||
if !ok {
|
||||
return nil, errors.New("Bad StatefulSet type found in cache")
|
||||
}
|
||||
return fulset, nil
|
||||
}
|
||||
return nil, NewNotFound(name, "apps/v1beta2", "StatefulSet")
|
||||
return nil, NewNotFound(name, "apps/v1", "StatefulSet")
|
||||
}
|
||||
|
||||
func (c *controllerImpl) GetStatefulSets(namespace string) ([]v1beta2.StatefulSet, error) {
|
||||
func (c *controllerImpl) GetStatefulSets(namespace string) ([]appsv1.StatefulSet, error) {
|
||||
if err := c.checkStateAndRetry(); err != nil {
|
||||
return []v1beta2.StatefulSet{}, err
|
||||
return []appsv1.StatefulSet{}, err
|
||||
}
|
||||
indexer := c.controllers["StatefulSet"].GetIndexer()
|
||||
fulsets, err := indexer.ByIndex("namespace", namespace)
|
||||
if err != nil {
|
||||
return []v1beta2.StatefulSet{}, err
|
||||
return []appsv1.StatefulSet{}, err
|
||||
}
|
||||
if len(fulsets) > 0 {
|
||||
_, ok := fulsets[0].(*v1beta2.StatefulSet)
|
||||
_, ok := fulsets[0].(*appsv1.StatefulSet)
|
||||
if !ok {
|
||||
return []v1beta2.StatefulSet{}, errors.New("Bad StatefulSet type found in cache")
|
||||
return []appsv1.StatefulSet{}, errors.New("Bad StatefulSet type found in cache")
|
||||
}
|
||||
nsFulsets := make([]v1beta2.StatefulSet, len(fulsets))
|
||||
nsFulsets := make([]appsv1.StatefulSet, len(fulsets))
|
||||
for i, fulset := range fulsets {
|
||||
nsFulsets[i] = *(fulset.(*v1beta2.StatefulSet))
|
||||
nsFulsets[i] = *(fulset.(*appsv1.StatefulSet))
|
||||
}
|
||||
return nsFulsets, nil
|
||||
}
|
||||
return []v1beta2.StatefulSet{}, nil
|
||||
return []appsv1.StatefulSet{}, nil
|
||||
}
|
||||
|
||||
func (c *controllerImpl) GetService(namespace, name string) (*v1.Service, error) {
|
||||
|
||||
13
vendor/github.com/kiali/kiali/kubernetes/client.go
generated
vendored
13
vendor/github.com/kiali/kiali/kubernetes/client.go
generated
vendored
@@ -7,8 +7,7 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/apps/v1beta1"
|
||||
"k8s.io/api/apps/v1beta2"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
auth_v1 "k8s.io/api/authorization/v1"
|
||||
batch_v1 "k8s.io/api/batch/v1"
|
||||
batch_v1beta1 "k8s.io/api/batch/v1beta1"
|
||||
@@ -39,8 +38,8 @@ type IstioClientInterface interface {
|
||||
GetAdapter(namespace, adapterType, adapterName string) (IstioObject, error)
|
||||
GetAdapters(namespace string) ([]IstioObject, error)
|
||||
GetCronJobs(namespace string) ([]batch_v1beta1.CronJob, error)
|
||||
GetDeployment(namespace string, deploymentName string) (*v1beta1.Deployment, error)
|
||||
GetDeployments(namespace string) ([]v1beta1.Deployment, error)
|
||||
GetDeployment(namespace string, deploymentName string) (*appsv1.Deployment, error)
|
||||
GetDeployments(namespace string) ([]appsv1.Deployment, error)
|
||||
GetDeploymentConfig(namespace string, deploymentconfigName string) (*osappsv1.DeploymentConfig, error)
|
||||
GetDeploymentConfigs(namespace string) ([]osappsv1.DeploymentConfig, error)
|
||||
GetDestinationRule(namespace string, destinationrule string) (IstioObject, error)
|
||||
@@ -62,14 +61,14 @@ type IstioClientInterface interface {
|
||||
GetQuotaSpecBinding(namespace string, quotaSpecBindingName string) (IstioObject, error)
|
||||
GetQuotaSpecBindings(namespace string) ([]IstioObject, error)
|
||||
GetReplicationControllers(namespace string) ([]v1.ReplicationController, error)
|
||||
GetReplicaSets(namespace string) ([]v1beta2.ReplicaSet, error)
|
||||
GetReplicaSets(namespace string) ([]appsv1.ReplicaSet, error)
|
||||
GetSelfSubjectAccessReview(namespace, api, resourceType string, verbs []string) ([]*auth_v1.SelfSubjectAccessReview, error)
|
||||
GetService(namespace string, serviceName string) (*v1.Service, error)
|
||||
GetServices(namespace string, selectorLabels map[string]string) ([]v1.Service, error)
|
||||
GetServiceEntries(namespace string) ([]IstioObject, error)
|
||||
GetServiceEntry(namespace string, serviceEntryName string) (IstioObject, error)
|
||||
GetStatefulSet(namespace string, statefulsetName string) (*v1beta2.StatefulSet, error)
|
||||
GetStatefulSets(namespace string) ([]v1beta2.StatefulSet, error)
|
||||
GetStatefulSet(namespace string, statefulsetName string) (*appsv1.StatefulSet, error)
|
||||
GetStatefulSets(namespace string) ([]appsv1.StatefulSet, error)
|
||||
GetTemplate(namespace, templateType, templateName string) (IstioObject, error)
|
||||
GetTemplates(namespace string) ([]IstioObject, error)
|
||||
GetPolicy(namespace string, policyName string) (IstioObject, error)
|
||||
|
||||
29
vendor/github.com/kiali/kiali/kubernetes/kubernetes_service.go
generated
vendored
29
vendor/github.com/kiali/kiali/kubernetes/kubernetes_service.go
generated
vendored
@@ -1,8 +1,7 @@
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
"k8s.io/api/apps/v1beta1"
|
||||
"k8s.io/api/apps/v1beta2"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
auth_v1 "k8s.io/api/authorization/v1"
|
||||
batch_v1 "k8s.io/api/batch/v1"
|
||||
batch_v1beta1 "k8s.io/api/batch/v1beta1"
|
||||
@@ -109,23 +108,23 @@ func (in *IstioClient) GetServices(namespace string, selectorLabels map[string]s
|
||||
|
||||
// GetDeployment returns the definition of a specific deployment.
|
||||
// It returns an error on any problem.
|
||||
func (in *IstioClient) GetDeployment(namespace, deploymentName string) (*v1beta1.Deployment, error) {
|
||||
func (in *IstioClient) GetDeployment(namespace, deploymentName string) (*appsv1.Deployment, error) {
|
||||
if in.k8sCache != nil {
|
||||
return in.k8sCache.GetDeployment(namespace, deploymentName)
|
||||
}
|
||||
return in.k8s.AppsV1beta1().Deployments(namespace).Get(deploymentName, emptyGetOptions)
|
||||
return in.k8s.AppsV1().Deployments(namespace).Get(deploymentName, emptyGetOptions)
|
||||
}
|
||||
|
||||
// GetDeployments returns an array of deployments for a given namespace and a set of labels.
|
||||
// It returns an error on any problem.
|
||||
func (in *IstioClient) GetDeployments(namespace string) ([]v1beta1.Deployment, error) {
|
||||
func (in *IstioClient) GetDeployments(namespace string) ([]appsv1.Deployment, error) {
|
||||
if in.k8sCache != nil {
|
||||
return in.k8sCache.GetDeployments(namespace)
|
||||
}
|
||||
if depList, err := in.k8s.AppsV1beta1().Deployments(namespace).List(emptyListOptions); err == nil {
|
||||
if depList, err := in.k8s.AppsV1().Deployments(namespace).List(emptyListOptions); err == nil {
|
||||
return depList.Items, nil
|
||||
} else {
|
||||
return []v1beta1.Deployment{}, err
|
||||
return []appsv1.Deployment{}, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,32 +151,32 @@ func (in *IstioClient) GetDeploymentConfigs(namespace string) ([]osappsv1.Deploy
|
||||
return result.Items, nil
|
||||
}
|
||||
|
||||
func (in *IstioClient) GetReplicaSets(namespace string) ([]v1beta2.ReplicaSet, error) {
|
||||
func (in *IstioClient) GetReplicaSets(namespace string) ([]appsv1.ReplicaSet, error) {
|
||||
if in.k8sCache != nil {
|
||||
return in.k8sCache.GetReplicaSets(namespace)
|
||||
}
|
||||
if rsList, err := in.k8s.AppsV1beta2().ReplicaSets(namespace).List(emptyListOptions); err == nil {
|
||||
if rsList, err := in.k8s.AppsV1().ReplicaSets(namespace).List(emptyListOptions); err == nil {
|
||||
return rsList.Items, nil
|
||||
} else {
|
||||
return []v1beta2.ReplicaSet{}, err
|
||||
return []appsv1.ReplicaSet{}, err
|
||||
}
|
||||
}
|
||||
|
||||
func (in *IstioClient) GetStatefulSet(namespace string, statefulsetName string) (*v1beta2.StatefulSet, error) {
|
||||
func (in *IstioClient) GetStatefulSet(namespace string, statefulsetName string) (*appsv1.StatefulSet, error) {
|
||||
if in.k8sCache != nil {
|
||||
return in.k8sCache.GetStatefulSet(namespace, statefulsetName)
|
||||
}
|
||||
return in.k8s.AppsV1beta2().StatefulSets(namespace).Get(statefulsetName, emptyGetOptions)
|
||||
return in.k8s.AppsV1().StatefulSets(namespace).Get(statefulsetName, emptyGetOptions)
|
||||
}
|
||||
|
||||
func (in *IstioClient) GetStatefulSets(namespace string) ([]v1beta2.StatefulSet, error) {
|
||||
func (in *IstioClient) GetStatefulSets(namespace string) ([]appsv1.StatefulSet, error) {
|
||||
if in.k8sCache != nil {
|
||||
return in.k8sCache.GetStatefulSets(namespace)
|
||||
}
|
||||
if ssList, err := in.k8s.AppsV1beta2().StatefulSets(namespace).List(emptyListOptions); err == nil {
|
||||
if ssList, err := in.k8s.AppsV1().StatefulSets(namespace).List(emptyListOptions); err == nil {
|
||||
return ssList.Items, nil
|
||||
} else {
|
||||
return []v1beta2.StatefulSet{}, err
|
||||
return []appsv1.StatefulSet{}, err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
35
vendor/github.com/kiali/kiali/kubernetes/kubetest/mock.go
generated
vendored
35
vendor/github.com/kiali/kiali/kubernetes/kubetest/mock.go
generated
vendored
@@ -6,8 +6,7 @@ import (
|
||||
osappsv1 "github.com/openshift/api/apps/v1"
|
||||
osv1 "github.com/openshift/api/project/v1"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"k8s.io/api/apps/v1beta1"
|
||||
"k8s.io/api/apps/v1beta2"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
auth_v1 "k8s.io/api/authorization/v1"
|
||||
batch_v1 "k8s.io/api/batch/v1"
|
||||
batch_v1beta1 "k8s.io/api/batch/v1beta1"
|
||||
@@ -33,11 +32,11 @@ func NewK8SClientMock() *K8SClientMock {
|
||||
|
||||
// MockEmptyWorkloads setup the current mock to return empty workloads for every type of workloads (deployment, dc, rs, jobs, etc.)
|
||||
func (o *K8SClientMock) MockEmptyWorkloads(namespace interface{}) {
|
||||
o.On("GetDeployments", namespace).Return([]v1beta1.Deployment{}, nil)
|
||||
o.On("GetReplicaSets", namespace).Return([]v1beta2.ReplicaSet{}, nil)
|
||||
o.On("GetDeployments", namespace).Return([]appsv1.Deployment{}, nil)
|
||||
o.On("GetReplicaSets", namespace).Return([]appsv1.ReplicaSet{}, nil)
|
||||
o.On("GetReplicationControllers", namespace).Return([]v1.ReplicationController{}, nil)
|
||||
o.On("GetDeploymentConfigs", namespace).Return([]osappsv1.DeploymentConfig{}, nil)
|
||||
o.On("GetStatefulSets", namespace).Return([]v1beta2.StatefulSet{}, nil)
|
||||
o.On("GetStatefulSets", namespace).Return([]appsv1.StatefulSet{}, nil)
|
||||
o.On("GetJobs", namespace).Return([]batch_v1.Job{}, nil)
|
||||
o.On("GetCronJobs", namespace).Return([]batch_v1beta1.CronJob{}, nil)
|
||||
}
|
||||
@@ -45,10 +44,10 @@ func (o *K8SClientMock) MockEmptyWorkloads(namespace interface{}) {
|
||||
// MockEmptyWorkload setup the current mock to return an empty workload for every type of workloads (deployment, dc, rs, jobs, etc.)
|
||||
func (o *K8SClientMock) MockEmptyWorkload(namespace interface{}, workload interface{}) {
|
||||
notfound := fmt.Errorf("not found")
|
||||
o.On("GetDeployment", namespace, workload).Return(&v1beta1.Deployment{}, notfound)
|
||||
o.On("GetStatefulSet", namespace, workload).Return(&v1beta2.StatefulSet{}, notfound)
|
||||
o.On("GetDeployment", namespace, workload).Return(&appsv1.Deployment{}, notfound)
|
||||
o.On("GetStatefulSet", namespace, workload).Return(&appsv1.StatefulSet{}, notfound)
|
||||
o.On("GetDeploymentConfig", namespace, workload).Return(&osappsv1.DeploymentConfig{}, notfound)
|
||||
o.On("GetReplicaSets", namespace).Return([]v1beta2.ReplicaSet{}, nil)
|
||||
o.On("GetReplicaSets", namespace).Return([]appsv1.ReplicaSet{}, nil)
|
||||
o.On("GetReplicationControllers", namespace).Return([]v1.ReplicationController{}, nil)
|
||||
o.On("GetJobs", namespace).Return([]batch_v1.Job{}, nil)
|
||||
o.On("GetCronJobs", namespace).Return([]batch_v1beta1.CronJob{}, nil)
|
||||
@@ -79,14 +78,14 @@ func (o *K8SClientMock) GetCronJobs(namespace string) ([]batch_v1beta1.CronJob,
|
||||
return args.Get(0).([]batch_v1beta1.CronJob), args.Error(1)
|
||||
}
|
||||
|
||||
func (o *K8SClientMock) GetDeployment(namespace string, deploymentName string) (*v1beta1.Deployment, error) {
|
||||
func (o *K8SClientMock) GetDeployment(namespace string, deploymentName string) (*appsv1.Deployment, error) {
|
||||
args := o.Called(namespace, deploymentName)
|
||||
return args.Get(0).(*v1beta1.Deployment), args.Error(1)
|
||||
return args.Get(0).(*appsv1.Deployment), args.Error(1)
|
||||
}
|
||||
|
||||
func (o *K8SClientMock) GetDeployments(namespace string) ([]v1beta1.Deployment, error) {
|
||||
func (o *K8SClientMock) GetDeployments(namespace string) ([]appsv1.Deployment, error) {
|
||||
args := o.Called(namespace)
|
||||
return args.Get(0).([]v1beta1.Deployment), args.Error(1)
|
||||
return args.Get(0).([]appsv1.Deployment), args.Error(1)
|
||||
}
|
||||
|
||||
func (o *K8SClientMock) GetDeploymentConfig(namespace string, deploymentName string) (*osappsv1.DeploymentConfig, error) {
|
||||
@@ -194,9 +193,9 @@ func (o *K8SClientMock) GetReplicationControllers(namespace string) ([]v1.Replic
|
||||
return args.Get(0).([]v1.ReplicationController), args.Error(1)
|
||||
}
|
||||
|
||||
func (o *K8SClientMock) GetReplicaSets(namespace string) ([]v1beta2.ReplicaSet, error) {
|
||||
func (o *K8SClientMock) GetReplicaSets(namespace string) ([]appsv1.ReplicaSet, error) {
|
||||
args := o.Called(namespace)
|
||||
return args.Get(0).([]v1beta2.ReplicaSet), args.Error(1)
|
||||
return args.Get(0).([]appsv1.ReplicaSet), args.Error(1)
|
||||
}
|
||||
|
||||
func (o *K8SClientMock) GetSelfSubjectAccessReview(namespace, api, resourceType string, verbs []string) ([]*auth_v1.SelfSubjectAccessReview, error) {
|
||||
@@ -224,14 +223,14 @@ func (o *K8SClientMock) GetServiceEntry(namespace string, serviceEntryName strin
|
||||
return args.Get(0).(kubernetes.IstioObject), args.Error(1)
|
||||
}
|
||||
|
||||
func (o *K8SClientMock) GetStatefulSet(namespace string, statefulsetName string) (*v1beta2.StatefulSet, error) {
|
||||
func (o *K8SClientMock) GetStatefulSet(namespace string, statefulsetName string) (*appsv1.StatefulSet, error) {
|
||||
args := o.Called(namespace, statefulsetName)
|
||||
return args.Get(0).(*v1beta2.StatefulSet), args.Error(1)
|
||||
return args.Get(0).(*appsv1.StatefulSet), args.Error(1)
|
||||
}
|
||||
|
||||
func (o *K8SClientMock) GetStatefulSets(namespace string) ([]v1beta2.StatefulSet, error) {
|
||||
func (o *K8SClientMock) GetStatefulSets(namespace string) ([]appsv1.StatefulSet, error) {
|
||||
args := o.Called(namespace)
|
||||
return args.Get(0).([]v1beta2.StatefulSet), args.Error(1)
|
||||
return args.Get(0).([]appsv1.StatefulSet), args.Error(1)
|
||||
}
|
||||
|
||||
func (o *K8SClientMock) GetTemplate(namespace, templateType, templateName string) (kubernetes.IstioObject, error) {
|
||||
|
||||
9
vendor/github.com/kiali/kiali/models/workload.go
generated
vendored
9
vendor/github.com/kiali/kiali/models/workload.go
generated
vendored
@@ -2,8 +2,7 @@ package models
|
||||
|
||||
import (
|
||||
osappsv1 "github.com/openshift/api/apps/v1"
|
||||
"k8s.io/api/apps/v1beta1"
|
||||
"k8s.io/api/apps/v1beta2"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
batch_v1 "k8s.io/api/batch/v1"
|
||||
batch_v1beta1 "k8s.io/api/batch/v1beta1"
|
||||
"k8s.io/api/core/v1"
|
||||
@@ -125,7 +124,7 @@ func (workload *WorkloadListItem) ParseWorkload(w *Workload) {
|
||||
_, workload.VersionLabel = w.Labels[conf.IstioLabels.VersionLabelName]
|
||||
}
|
||||
|
||||
func (workload *Workload) ParseDeployment(d *v1beta1.Deployment) {
|
||||
func (workload *Workload) ParseDeployment(d *appsv1.Deployment) {
|
||||
conf := config.Get()
|
||||
workload.Name = d.Name
|
||||
workload.Type = "Deployment"
|
||||
@@ -144,7 +143,7 @@ func (workload *Workload) ParseDeployment(d *v1beta1.Deployment) {
|
||||
workload.UnavailableReplicas = workload.Replicas - workload.AvailableReplicas
|
||||
}
|
||||
|
||||
func (workload *Workload) ParseReplicaSet(r *v1beta2.ReplicaSet) {
|
||||
func (workload *Workload) ParseReplicaSet(r *appsv1.ReplicaSet) {
|
||||
conf := config.Get()
|
||||
workload.Name = r.Name
|
||||
workload.Type = "ReplicaSet"
|
||||
@@ -195,7 +194,7 @@ func (workload *Workload) ParseDeploymentConfig(dc *osappsv1.DeploymentConfig) {
|
||||
workload.UnavailableReplicas = workload.Replicas - workload.AvailableReplicas
|
||||
}
|
||||
|
||||
func (workload *Workload) ParseStatefulSet(s *v1beta2.StatefulSet) {
|
||||
func (workload *Workload) ParseStatefulSet(s *appsv1.StatefulSet) {
|
||||
conf := config.Get()
|
||||
workload.Name = s.Name
|
||||
workload.Type = "StatefulSet"
|
||||
|
||||
201
vendor/github.com/kubernetes-sigs/application/LICENSE
generated
vendored
201
vendor/github.com/kubernetes-sigs/application/LICENSE
generated
vendored
@@ -1,201 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
||||
180
vendor/github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1/application.go
generated
vendored
180
vendor/github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1/application.go
generated
vendored
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 v1beta1
|
||||
|
||||
import (
|
||||
"github.com/kubernetes-sigs/application/pkg/component"
|
||||
cr "github.com/kubernetes-sigs/application/pkg/customresource"
|
||||
"github.com/kubernetes-sigs/application/pkg/finalizer"
|
||||
"github.com/kubernetes-sigs/application/pkg/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Mutate - mutate expected
|
||||
func (a *Application) Mutate(rsrc interface{}, labels map[string]string, status interface{}, expected, dependent, observed *resource.ObjectBag) (*resource.ObjectBag, error) {
|
||||
exp := resource.ObjectBag{}
|
||||
for _, o := range observed.Items() {
|
||||
o.Lifecycle = resource.LifecycleManaged
|
||||
exp.Add(o)
|
||||
}
|
||||
return &exp, nil
|
||||
}
|
||||
|
||||
// Finalize - execute finalizers
|
||||
func (a *Application) Finalize(rsrc, sts interface{}, observed *resource.ObjectBag) error {
|
||||
finalizer.Remove(a, finalizer.Cleanup)
|
||||
return nil
|
||||
}
|
||||
|
||||
//DependentResources - returns dependent rsrc
|
||||
func (a *Application) DependentResources(rsrc interface{}) *resource.ObjectBag {
|
||||
return &resource.ObjectBag{}
|
||||
}
|
||||
|
||||
// ExpectedResources returns the list of resource/name for those resources created by
|
||||
// the operator for this spec and those resources referenced by this operator.
|
||||
// Mark resources as owned, referred
|
||||
func (a *Application) ExpectedResources(rsrc interface{}, rsrclabels map[string]string, dependent, aggregated *resource.ObjectBag) (*resource.ObjectBag, error) {
|
||||
return &resource.ObjectBag{}, nil
|
||||
}
|
||||
|
||||
// GKVersions returns the gvks for the given gk
|
||||
func GKVersions(s *runtime.Scheme, mgk metav1.GroupKind) []schema.GroupVersionKind {
|
||||
gvks := []schema.GroupVersionKind{}
|
||||
gk := schema.GroupKind{Group: mgk.Group, Kind: mgk.Kind}
|
||||
for gvk := range s.AllKnownTypes() {
|
||||
if gk != gvk.GroupKind() {
|
||||
continue
|
||||
}
|
||||
gvks = append(gvks, gvk)
|
||||
}
|
||||
return gvks
|
||||
}
|
||||
|
||||
// Observables - return selectors
|
||||
func (a *Application) Observables(scheme *runtime.Scheme, rsrc interface{}, rsrclabels map[string]string, expected *resource.ObjectBag) []resource.Observable {
|
||||
var observables []resource.Observable
|
||||
if a.Spec.Selector == nil || a.Spec.Selector.MatchLabels == nil {
|
||||
return observables
|
||||
}
|
||||
for _, gk := range a.Spec.ComponentGroupKinds {
|
||||
listGK := gk
|
||||
if !strings.HasSuffix(listGK.Kind, "List") {
|
||||
listGK.Kind = listGK.Kind + "List"
|
||||
}
|
||||
for _, gvk := range GKVersions(scheme, listGK) {
|
||||
ol, err := scheme.New(gvk)
|
||||
if err == nil {
|
||||
observable := resource.Observable{
|
||||
ObjList: ol.(metav1.ListInterface),
|
||||
Labels: a.Spec.Selector.MatchLabels,
|
||||
Namespace: rsrc.(metav1.Object).GetNamespace(),
|
||||
}
|
||||
observables = append(observables, observable)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return observables
|
||||
}
|
||||
|
||||
// Differs returns true if the resource needs to be updated
|
||||
func (a *Application) Differs(expected metav1.Object, observed metav1.Object) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// UpdateComponentStatus use reconciled objects to update component status
|
||||
func (a *Application) UpdateComponentStatus(rsrci, statusi interface{}, reconciled *resource.ObjectBag, err error) {
|
||||
if a != nil {
|
||||
stts := statusi.(*ApplicationStatus)
|
||||
stts.UpdateStatus(reconciled.Objs(), err)
|
||||
}
|
||||
}
|
||||
|
||||
// ApplyDefaults default app crd
|
||||
func (a *Application) ApplyDefaults() {
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateRsrcStatus records status or error in status
|
||||
func (a *Application) UpdateRsrcStatus(status interface{}, err error) bool {
|
||||
appstatus := status.(*ApplicationStatus)
|
||||
if status != nil {
|
||||
a.Status = *appstatus
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
a.Status.SetError("ErrorSeen", err.Error())
|
||||
} else {
|
||||
a.Status.ClearError()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Validate the Application
|
||||
func (a *Application) Validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Components returns components for this resource
|
||||
func (a *Application) Components() []component.Component {
|
||||
c := []component.Component{}
|
||||
c = append(c, component.Component{
|
||||
Handle: a,
|
||||
Name: "app",
|
||||
CR: a,
|
||||
OwnerRef: a.OwnerRef(),
|
||||
})
|
||||
return c
|
||||
}
|
||||
|
||||
// OwnerRef returns owner ref object with the component's resource as owner
|
||||
func (a *Application) OwnerRef() *metav1.OwnerReference {
|
||||
if !a.Spec.AddOwnerRef {
|
||||
return nil
|
||||
}
|
||||
|
||||
isController := false
|
||||
gvk := schema.GroupVersionKind{
|
||||
Group: SchemeGroupVersion.Group,
|
||||
Version: SchemeGroupVersion.Version,
|
||||
Kind: "Application",
|
||||
}
|
||||
ref := metav1.NewControllerRef(a, gvk)
|
||||
ref.Controller = &isController
|
||||
return ref
|
||||
}
|
||||
|
||||
// NewRsrc - return a new resource object
|
||||
func (a *Application) NewRsrc() cr.Handle {
|
||||
return &Application{}
|
||||
}
|
||||
|
||||
// NewStatus - return a resource status object
|
||||
func (a *Application) NewStatus() interface{} {
|
||||
s := a.Status.DeepCopy()
|
||||
s.ComponentList = ComponentList{}
|
||||
return s
|
||||
}
|
||||
|
||||
// StatusDiffers returns True if there is a change in status
|
||||
func (a *Application) StatusDiffers(new ApplicationStatus) bool {
|
||||
return true
|
||||
}
|
||||
168
vendor/github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1/condition.go
generated
vendored
168
vendor/github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1/condition.go
generated
vendored
@@ -1,168 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 v1beta1
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func (m *ApplicationStatus) addCondition(ctype ConditionType, status corev1.ConditionStatus, reason, message string) {
|
||||
now := metav1.Now()
|
||||
c := &Condition{
|
||||
Type: ctype,
|
||||
LastUpdateTime: now,
|
||||
LastTransitionTime: now,
|
||||
Status: status,
|
||||
Reason: reason,
|
||||
Message: message,
|
||||
}
|
||||
m.Conditions = append(m.Conditions, *c)
|
||||
}
|
||||
|
||||
// setConditionValue updates or creates a new condition
|
||||
func (m *ApplicationStatus) setConditionValue(ctype ConditionType, status corev1.ConditionStatus, reason, message string) {
|
||||
var c *Condition
|
||||
for i := range m.Conditions {
|
||||
if m.Conditions[i].Type == ctype {
|
||||
c = &m.Conditions[i]
|
||||
}
|
||||
}
|
||||
if c == nil {
|
||||
m.addCondition(ctype, status, reason, message)
|
||||
} else {
|
||||
// check message ?
|
||||
if c.Status == status && c.Reason == reason && c.Message == message {
|
||||
return
|
||||
}
|
||||
now := metav1.Now()
|
||||
c.LastUpdateTime = now
|
||||
if c.Status != status {
|
||||
c.LastTransitionTime = now
|
||||
}
|
||||
c.Status = status
|
||||
c.Reason = reason
|
||||
c.Message = message
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveCondition removes the condition with the provided type.
|
||||
func (m *ApplicationStatus) RemoveCondition(ctype ConditionType) {
|
||||
for i, c := range m.Conditions {
|
||||
if c.Type == ctype {
|
||||
m.Conditions[i] = m.Conditions[len(m.Conditions)-1]
|
||||
m.Conditions = m.Conditions[:len(m.Conditions)-1]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetCondition get existing condition
|
||||
func (m *ApplicationStatus) GetCondition(ctype ConditionType) *Condition {
|
||||
for i := range m.Conditions {
|
||||
if m.Conditions[i].Type == ctype {
|
||||
return &m.Conditions[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsConditionTrue - if condition is true
|
||||
func (m *ApplicationStatus) IsConditionTrue(ctype ConditionType) bool {
|
||||
if c := m.GetCondition(ctype); c != nil {
|
||||
return c.Status == corev1.ConditionTrue
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsReady returns true if ready condition is set
|
||||
func (m *ApplicationStatus) IsReady() bool { return m.IsConditionTrue(Ready) }
|
||||
|
||||
// IsNotReady returns true if ready condition is set
|
||||
func (m *ApplicationStatus) IsNotReady() bool { return !m.IsConditionTrue(Ready) }
|
||||
|
||||
// ConditionReason - return condition reason
|
||||
func (m *ApplicationStatus) ConditionReason(ctype ConditionType) string {
|
||||
if c := m.GetCondition(ctype); c != nil {
|
||||
return c.Reason
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Ready - shortcut to set ready contition to true
|
||||
func (m *ApplicationStatus) Ready(reason, message string) {
|
||||
m.SetCondition(Ready, reason, message)
|
||||
}
|
||||
|
||||
// NotReady - shortcut to set ready contition to false
|
||||
func (m *ApplicationStatus) NotReady(reason, message string) {
|
||||
m.ClearCondition(Ready, reason, message)
|
||||
}
|
||||
|
||||
// SetError - shortcut to set error condition
|
||||
func (m *ApplicationStatus) SetError(reason, message string) {
|
||||
m.SetCondition(Error, reason, message)
|
||||
}
|
||||
|
||||
// ClearError - shortcut to set error condition
|
||||
func (m *ApplicationStatus) ClearError() {
|
||||
m.ClearCondition(Error, "NoError", "No error seen")
|
||||
}
|
||||
|
||||
// Settled - shortcut to set Settled contition to true
|
||||
func (m *ApplicationStatus) Settled(reason, message string) {
|
||||
m.SetCondition(Settled, reason, message)
|
||||
}
|
||||
|
||||
// NotSettled - shortcut to set Settled contition to false
|
||||
func (m *ApplicationStatus) NotSettled(reason, message string) {
|
||||
m.ClearCondition(Settled, reason, message)
|
||||
}
|
||||
|
||||
// EnsureCondition useful for adding default conditions
|
||||
func (m *ApplicationStatus) EnsureCondition(ctype ConditionType) {
|
||||
if c := m.GetCondition(ctype); c != nil {
|
||||
return
|
||||
}
|
||||
m.addCondition(ctype, corev1.ConditionUnknown, ReasonInit, "Not Observed")
|
||||
}
|
||||
|
||||
// EnsureStandardConditions - helper to inject standard conditions
|
||||
func (m *ApplicationStatus) EnsureStandardConditions() {
|
||||
m.EnsureCondition(Ready)
|
||||
m.EnsureCondition(Settled)
|
||||
m.EnsureCondition(Error)
|
||||
}
|
||||
|
||||
// ClearCondition updates or creates a new condition
|
||||
func (m *ApplicationStatus) ClearCondition(ctype ConditionType, reason, message string) {
|
||||
m.setConditionValue(ctype, corev1.ConditionFalse, reason, message)
|
||||
}
|
||||
|
||||
// SetCondition updates or creates a new condition
|
||||
func (m *ApplicationStatus) SetCondition(ctype ConditionType, reason, message string) {
|
||||
m.setConditionValue(ctype, corev1.ConditionTrue, reason, message)
|
||||
}
|
||||
|
||||
// RemoveAllConditions updates or creates a new condition
|
||||
func (m *ApplicationStatus) RemoveAllConditions() {
|
||||
m.Conditions = []Condition{}
|
||||
}
|
||||
|
||||
// ClearAllConditions updates or creates a new condition
|
||||
func (m *ApplicationStatus) ClearAllConditions() {
|
||||
for i := range m.Conditions {
|
||||
m.Conditions[i].Status = corev1.ConditionFalse
|
||||
}
|
||||
}
|
||||
23
vendor/github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1/doc.go
generated
vendored
23
vendor/github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1/doc.go
generated
vendored
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 v1beta1 contains API Schema definitions for the app v1beta1 API group
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package,register
|
||||
// +k8s:conversion-gen=github.com/kubernetes-sigs/application/pkg/apis/app
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=app.k8s.io
|
||||
package v1beta1
|
||||
46
vendor/github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1/register.go
generated
vendored
46
vendor/github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1/register.go
generated
vendored
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// NOTE: Boilerplate only. Ignore this file.
|
||||
|
||||
// Package v1beta1 contains API Schema definitions for the app v1beta1 API group
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package,register
|
||||
// +k8s:conversion-gen=github.com/kubernetes-sigs/application/pkg/apis/app
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=app.k8s.io
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"sigs.k8s.io/controller-runtime/pkg/runtime/scheme"
|
||||
)
|
||||
|
||||
var (
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
SchemeGroupVersion = schema.GroupVersion{Group: "app.k8s.io", Version: "v1beta1"}
|
||||
|
||||
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
|
||||
SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion}
|
||||
|
||||
// AddToScheme is required by pkg/client/...
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
// Resource is required by pkg/client/listers/...
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
193
vendor/github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1/status.go
generated
vendored
193
vendor/github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1/status.go
generated
vendored
@@ -1,193 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 v1beta1
|
||||
|
||||
import (
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
policyv1 "k8s.io/api/policy/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// Constants defining labels
|
||||
const (
|
||||
StatusReady = "Ready"
|
||||
StatusInProgress = "InProgress"
|
||||
StatusDisabled = "Disabled"
|
||||
)
|
||||
|
||||
func (s *ObjectStatus) update(rsrc metav1.Object) {
|
||||
ro := rsrc.(runtime.Object)
|
||||
gvk := ro.GetObjectKind().GroupVersionKind()
|
||||
s.Link = rsrc.GetSelfLink()
|
||||
s.Name = rsrc.GetName()
|
||||
s.Group = gvk.GroupVersion().String()
|
||||
s.Kind = gvk.GroupKind().Kind
|
||||
s.Status = StatusReady
|
||||
}
|
||||
|
||||
// ResetComponentList - reset component list objects
|
||||
func (m *ApplicationStatus) ResetComponentList() {
|
||||
m.ComponentList.Objects = []ObjectStatus{}
|
||||
}
|
||||
|
||||
// UpdateStatus the component status
|
||||
func (m *ApplicationStatus) UpdateStatus(rsrcs []metav1.Object, err error) {
|
||||
var ready = true
|
||||
for _, r := range rsrcs {
|
||||
os := ObjectStatus{}
|
||||
os.update(r)
|
||||
switch r.(type) {
|
||||
case *appsv1.StatefulSet:
|
||||
os.Status = stsStatus(r.(*appsv1.StatefulSet))
|
||||
case *policyv1.PodDisruptionBudget:
|
||||
os.Status = pdbStatus(r.(*policyv1.PodDisruptionBudget))
|
||||
case *appsv1.Deployment:
|
||||
os.Status = deploymentStatus(r.(*appsv1.Deployment))
|
||||
case *appsv1.ReplicaSet:
|
||||
os.Status = replicasetStatus(r.(*appsv1.ReplicaSet))
|
||||
case *appsv1.DaemonSet:
|
||||
os.Status = daemonsetStatus(r.(*appsv1.DaemonSet))
|
||||
case *corev1.Pod:
|
||||
os.Status = podStatus(r.(*corev1.Pod))
|
||||
case *corev1.Service:
|
||||
os.Status = serviceStatus(r.(*corev1.Service))
|
||||
case *corev1.PersistentVolumeClaim:
|
||||
os.Status = pvcStatus(r.(*corev1.PersistentVolumeClaim))
|
||||
//case *corev1.ReplicationController:
|
||||
// Ingress
|
||||
default:
|
||||
os.Status = StatusReady
|
||||
}
|
||||
m.ComponentList.Objects = append(m.ComponentList.Objects, os)
|
||||
}
|
||||
for _, os := range m.ComponentList.Objects {
|
||||
if os.Status != StatusReady {
|
||||
ready = false
|
||||
}
|
||||
}
|
||||
|
||||
if ready {
|
||||
m.Ready("ComponentsReady", "all components ready")
|
||||
} else {
|
||||
m.NotReady("ComponentsNotReady", "some components not ready")
|
||||
}
|
||||
if err != nil {
|
||||
m.SetCondition(Error, "ErrorSeen", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// Resource specific logic -----------------------------------
|
||||
|
||||
// Statefulset
|
||||
func stsStatus(rsrc *appsv1.StatefulSet) string {
|
||||
if rsrc.Status.ReadyReplicas == *rsrc.Spec.Replicas && rsrc.Status.CurrentReplicas == *rsrc.Spec.Replicas {
|
||||
return StatusReady
|
||||
}
|
||||
return StatusInProgress
|
||||
}
|
||||
|
||||
// Deployment
|
||||
func deploymentStatus(rsrc *appsv1.Deployment) string {
|
||||
status := StatusInProgress
|
||||
progress := true
|
||||
available := true
|
||||
for _, c := range rsrc.Status.Conditions {
|
||||
switch c.Type {
|
||||
case appsv1.DeploymentProgressing:
|
||||
// https://github.com/kubernetes/kubernetes/blob/a3ccea9d8743f2ff82e41b6c2af6dc2c41dc7b10/pkg/controller/deployment/progress.go#L52
|
||||
if c.Status != corev1.ConditionTrue || c.Reason != "NewReplicaSetAvailable" {
|
||||
progress = false
|
||||
}
|
||||
case appsv1.DeploymentAvailable:
|
||||
if c.Status == corev1.ConditionFalse {
|
||||
available = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if progress && available {
|
||||
status = StatusReady
|
||||
}
|
||||
|
||||
return status
|
||||
}
|
||||
|
||||
// Replicaset
|
||||
func replicasetStatus(rsrc *appsv1.ReplicaSet) string {
|
||||
status := StatusInProgress
|
||||
failure := false
|
||||
for _, c := range rsrc.Status.Conditions {
|
||||
switch c.Type {
|
||||
// https://github.com/kubernetes/kubernetes/blob/a3ccea9d8743f2ff82e41b6c2af6dc2c41dc7b10/pkg/controller/replicaset/replica_set_utils.go
|
||||
case appsv1.ReplicaSetReplicaFailure:
|
||||
if c.Status == corev1.ConditionTrue {
|
||||
failure = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !failure && rsrc.Status.ReadyReplicas == rsrc.Status.Replicas && rsrc.Status.Replicas == rsrc.Status.AvailableReplicas {
|
||||
status = StatusReady
|
||||
}
|
||||
|
||||
return status
|
||||
}
|
||||
|
||||
// Daemonset
|
||||
func daemonsetStatus(rsrc *appsv1.DaemonSet) string {
|
||||
status := StatusInProgress
|
||||
if rsrc.Status.DesiredNumberScheduled == rsrc.Status.NumberAvailable && rsrc.Status.DesiredNumberScheduled == rsrc.Status.NumberReady {
|
||||
status = StatusReady
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
// PVC
|
||||
func pvcStatus(rsrc *corev1.PersistentVolumeClaim) string {
|
||||
status := StatusInProgress
|
||||
if rsrc.Status.Phase == corev1.ClaimBound {
|
||||
status = StatusReady
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
// Service
|
||||
func serviceStatus(rsrc *corev1.Service) string {
|
||||
status := StatusReady
|
||||
return status
|
||||
}
|
||||
|
||||
// Pod
|
||||
func podStatus(rsrc *corev1.Pod) string {
|
||||
status := StatusInProgress
|
||||
for i := range rsrc.Status.Conditions {
|
||||
if rsrc.Status.Conditions[i].Type == corev1.PodReady &&
|
||||
rsrc.Status.Conditions[i].Status == corev1.ConditionTrue {
|
||||
status = StatusReady
|
||||
break
|
||||
}
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
// PodDisruptionBudget
|
||||
func pdbStatus(rsrc *policyv1.PodDisruptionBudget) string {
|
||||
if rsrc.Status.CurrentHealthy >= rsrc.Status.DesiredHealthy {
|
||||
return StatusReady
|
||||
}
|
||||
return StatusInProgress
|
||||
}
|
||||
52
vendor/github.com/kubernetes-sigs/application/pkg/component/component.go
generated
vendored
52
vendor/github.com/kubernetes-sigs/application/pkg/component/component.go
generated
vendored
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 component
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Constants defining labels
|
||||
const (
|
||||
LabelCR = "custom-resource"
|
||||
LabelCRName = "custom-resource-name"
|
||||
LabelCRNamespace = "custom-resource-namespace"
|
||||
LabelComponent = "component"
|
||||
)
|
||||
|
||||
// Labels return
|
||||
func Labels(cr metav1.Object, component string) map[string]string {
|
||||
return map[string]string{
|
||||
LabelCR: strings.Trim(reflect.TypeOf(cr).String(), "*"),
|
||||
LabelCRName: cr.GetName(),
|
||||
LabelCRNamespace: cr.GetNamespace(),
|
||||
LabelComponent: component,
|
||||
}
|
||||
}
|
||||
|
||||
// Labels return the common labels for a resource
|
||||
func (c *Component) Labels() map[string]string {
|
||||
return Labels(c.CR, c.Name)
|
||||
}
|
||||
|
||||
// Merge is used to merge multiple maps into the target map
|
||||
func (out KVMap) Merge(kvmaps ...KVMap) {
|
||||
for _, kvmap := range kvmaps {
|
||||
for k, v := range kvmap {
|
||||
out[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
31
vendor/github.com/kubernetes-sigs/application/pkg/component/interface.go
generated
vendored
31
vendor/github.com/kubernetes-sigs/application/pkg/component/interface.go
generated
vendored
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 component
|
||||
|
||||
import (
|
||||
"github.com/kubernetes-sigs/application/pkg/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// Handle is an interface for operating on logical Components of a CR
|
||||
type Handle interface {
|
||||
DependentResources(rsrc interface{}) *resource.ObjectBag
|
||||
ExpectedResources(rsrc interface{}, labels map[string]string, dependent, aggregated *resource.ObjectBag) (*resource.ObjectBag, error)
|
||||
Observables(scheme *runtime.Scheme, rsrc interface{}, labels map[string]string, expected *resource.ObjectBag) []resource.Observable
|
||||
Mutate(rsrc interface{}, rsrclabels map[string]string, status interface{}, expected, dependent, observed *resource.ObjectBag) (*resource.ObjectBag, error)
|
||||
Differs(expected metav1.Object, observed metav1.Object) bool
|
||||
UpdateComponentStatus(rsrc, status interface{}, reconciled *resource.ObjectBag, err error)
|
||||
Finalize(rsrc, status interface{}, observed *resource.ObjectBag) error
|
||||
}
|
||||
35
vendor/github.com/kubernetes-sigs/application/pkg/component/types.go
generated
vendored
35
vendor/github.com/kubernetes-sigs/application/pkg/component/types.go
generated
vendored
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 component
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// Common const definitions
|
||||
const (
|
||||
LifecycleManaged = "managed"
|
||||
LifecycleReferred = "referred"
|
||||
)
|
||||
|
||||
// Component represents a logical collection of resources
|
||||
type Component struct {
|
||||
Handle
|
||||
Name string
|
||||
CR metav1.Object
|
||||
OwnerRef *metav1.OwnerReference
|
||||
}
|
||||
|
||||
// KVMap is a map[string]string
|
||||
type KVMap map[string]string
|
||||
31
vendor/github.com/kubernetes-sigs/application/pkg/customresource/customresource.go
generated
vendored
31
vendor/github.com/kubernetes-sigs/application/pkg/customresource/customresource.go
generated
vendored
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 customresource
|
||||
|
||||
import (
|
||||
component "github.com/kubernetes-sigs/application/pkg/component"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Labels return custom resource label
|
||||
func (hv *HandleValue) Labels() map[string]string {
|
||||
c := hv.Handle.(metav1.Object)
|
||||
return map[string]string{
|
||||
component.LabelCR: strings.Trim(reflect.TypeOf(c).String(), "*"),
|
||||
component.LabelCRName: c.GetName(),
|
||||
component.LabelCRNamespace: c.GetNamespace(),
|
||||
}
|
||||
}
|
||||
18
vendor/github.com/kubernetes-sigs/application/pkg/customresource/doc.go
generated
vendored
18
vendor/github.com/kubernetes-sigs/application/pkg/customresource/doc.go
generated
vendored
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 customresource contains component definition
|
||||
package customresource
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user