Compare commits
14 Commits
advanced-1
...
express
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a479e6493 | ||
|
|
e1aed9f652 | ||
|
|
337d71d677 | ||
|
|
390491ee31 | ||
|
|
733bea4e74 | ||
|
|
484cc0ecbb | ||
|
|
e4aa866ca5 | ||
|
|
b3bfb549e0 | ||
|
|
bf6c3245e4 | ||
|
|
e803897d10 | ||
|
|
a4a48eb4fc | ||
|
|
5091a87c1e | ||
|
|
2b031861d6 | ||
|
|
88b5fb3186 |
5
Gopkg.lock
generated
5
Gopkg.lock
generated
@@ -775,9 +775,6 @@
|
||||
"gopkg.in/yaml.v2",
|
||||
"k8s.io/api/apps/v1",
|
||||
"k8s.io/api/apps/v1beta2",
|
||||
"k8s.io/api/autoscaling/v1",
|
||||
"k8s.io/api/batch/v1",
|
||||
"k8s.io/api/batch/v1beta1",
|
||||
"k8s.io/api/core/v1",
|
||||
"k8s.io/api/extensions/v1beta1",
|
||||
"k8s.io/api/policy/v1beta1",
|
||||
@@ -794,8 +791,6 @@
|
||||
"k8s.io/client-go/kubernetes",
|
||||
"k8s.io/client-go/kubernetes/scheme",
|
||||
"k8s.io/client-go/listers/apps/v1",
|
||||
"k8s.io/client-go/listers/batch/v1",
|
||||
"k8s.io/client-go/listers/batch/v1beta1",
|
||||
"k8s.io/client-go/listers/core/v1",
|
||||
"k8s.io/client-go/listers/extensions/v1beta1",
|
||||
"k8s.io/client-go/listers/rbac/v1",
|
||||
|
||||
@@ -19,8 +19,6 @@ package components
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
@@ -32,56 +30,22 @@ func Register(ws *restful.WebService, subPath string) {
|
||||
ws.Route(ws.GET(subPath).To(handleGetComponents).Filter(route.RouteLogging)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
ws.Route(ws.GET(subPath+"/{namespace}/{componentName}").To(handleGetComponentStatus).
|
||||
Filter(route.RouteLogging)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
ws.Route(ws.GET("/health").To(handleGetSystemHealthStatus).Filter(route.RouteLogging)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
}
|
||||
|
||||
func handleGetSystemHealthStatus(request *restful.Request, response *restful.Response) {
|
||||
//get all components
|
||||
|
||||
if status, err := models.GetSystemHealthStatus(); err != nil {
|
||||
err = response.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
}
|
||||
} else {
|
||||
err = response.WriteAsJson(status)
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get a specific component status
|
||||
func handleGetComponentStatus(request *restful.Request, response *restful.Response) {
|
||||
namespace := request.PathParameter("namespace")
|
||||
componentName := request.PathParameter("componentName")
|
||||
|
||||
if component, err := models.GetComponentStatus(namespace, componentName); err != nil {
|
||||
err = response.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
}
|
||||
} else {
|
||||
if err = response.WriteAsJson(component); err != nil {
|
||||
glog.Errorln(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get all components
|
||||
func handleGetComponents(request *restful.Request, response *restful.Response) {
|
||||
|
||||
result, err := models.GetAllComponentsStatus()
|
||||
result, err := models.GetComponents()
|
||||
|
||||
if err != nil {
|
||||
|
||||
response.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
|
||||
} else {
|
||||
|
||||
response.WriteAsJson(result)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package daemonsets
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/emicklei/go-restful-openapi"
|
||||
"k8s.io/api/apps/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
)
|
||||
|
||||
func Register(ws *restful.WebService, subPath string) {
|
||||
|
||||
tags := []string{"daemonsets"}
|
||||
|
||||
ws.Route(ws.GET(subPath).To(getDaemonSetRevision).Consumes("*/*").Metadata(restfulspec.KeyOpenAPITags, tags).Doc("Handle daemonset" +
|
||||
" operation").Param(ws.PathParameter("daemonset", "daemonset's name").DataType("string")).Param(ws.PathParameter("namespace",
|
||||
"daemonset's namespace").DataType("string")).Param(ws.PathParameter("revision", "daemonset's revision")).Writes(v1.DaemonSet{}))
|
||||
}
|
||||
|
||||
func getDaemonSetRevision(req *restful.Request, resp *restful.Response) {
|
||||
daemonset := req.PathParameter("daemonset")
|
||||
namespace := req.PathParameter("namespace")
|
||||
revision := req.PathParameter("revision")
|
||||
|
||||
res, err := models.GetDaemonSetRevision(namespace, daemonset, revision)
|
||||
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
resp.WriteHeaderAndEntity(http.StatusNotFound, constants.MessageResponse{Message: err.Error()})
|
||||
} else {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
}
|
||||
}
|
||||
|
||||
resp.WriteEntity(res)
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package deployments
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/emicklei/go-restful-openapi"
|
||||
"k8s.io/api/apps/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
)
|
||||
|
||||
func Register(ws *restful.WebService, subPath string) {
|
||||
|
||||
tags := []string{"deployments"}
|
||||
|
||||
ws.Route(ws.GET(subPath).To(getDeployRevision).Consumes("*/*").Metadata(restfulspec.KeyOpenAPITags, tags).Doc("Handle deployment" +
|
||||
" operation").Param(ws.PathParameter("deployment", "deployment's name").DataType("string")).Param(ws.PathParameter("namespace",
|
||||
"deployment's namespace").DataType("string")).Param(ws.PathParameter("deployment", "deployment's name")).Writes(v1.ReplicaSet{}))
|
||||
}
|
||||
|
||||
func getDeployRevision(req *restful.Request, resp *restful.Response) {
|
||||
deploy := req.PathParameter("deployment")
|
||||
namespace := req.PathParameter("namespace")
|
||||
revision := req.PathParameter("revision")
|
||||
|
||||
res, err := models.GetDeployRevision(namespace, deploy, revision)
|
||||
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
resp.WriteHeaderAndEntity(http.StatusNotFound, constants.MessageResponse{Message: err.Error()})
|
||||
} else {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
}
|
||||
}
|
||||
|
||||
resp.WriteEntity(res)
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package hpa
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/emicklei/go-restful-openapi"
|
||||
"k8s.io/api/autoscaling/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
func Register(ws *restful.WebService, subPath string) {
|
||||
|
||||
tags := []string{"horizontalpodautoscalers"}
|
||||
|
||||
ws.Route(ws.GET(subPath).To(getHpa).Consumes("*/*").Metadata(restfulspec.KeyOpenAPITags, tags).Doc(
|
||||
"get horizontalpodautoscalers").Param(ws.PathParameter("namespace",
|
||||
"horizontalpodautoscalers's namespace").DataType("string")).Param(ws.PathParameter(
|
||||
"horizontalpodautoscaler", "horizontalpodautoscaler's name")).Writes(v1.HorizontalPodAutoscaler{}))
|
||||
}
|
||||
|
||||
func getHpa(req *restful.Request, resp *restful.Response) {
|
||||
hpa := req.PathParameter("horizontalpodautoscaler")
|
||||
namespace := req.PathParameter("namespace")
|
||||
client := client.NewK8sClient()
|
||||
|
||||
res, err := client.AutoscalingV1().HorizontalPodAutoscalers(namespace).Get(hpa, metaV1.GetOptions{})
|
||||
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
resp.WriteHeaderAndEntity(http.StatusOK, nil)
|
||||
} else {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, nil)
|
||||
}
|
||||
}
|
||||
|
||||
resp.WriteEntity(res)
|
||||
}
|
||||
@@ -63,7 +63,7 @@ func userRolesHandler(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
username := req.PathParameter("username")
|
||||
|
||||
roles, err := iam.GetRoles("", username)
|
||||
roles, err := iam.GetRoles(username)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
@@ -206,7 +206,7 @@ func clusterRoleRulesHandler(req *restful.Request, resp *restful.Response) {
|
||||
var rules []iam.Rule
|
||||
|
||||
if name == "" {
|
||||
rules = iam.ClusterRoleRuleMapping
|
||||
rules = iam.ClusterRoleRuleGroup
|
||||
} else {
|
||||
var err error
|
||||
rules, err = iam.GetClusterRoleRules(name)
|
||||
@@ -227,7 +227,7 @@ func roleRulesHandler(req *restful.Request, resp *restful.Response) {
|
||||
var rules []iam.Rule
|
||||
|
||||
if namespace == "" && name == "" {
|
||||
rules = iam.RoleRuleMapping
|
||||
rules = iam.RoleRuleGroup
|
||||
} else {
|
||||
var err error
|
||||
rules, err = iam.GetRoleRules(namespace, name)
|
||||
|
||||
@@ -21,25 +21,18 @@ import (
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/components"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/containers"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/daemonsets"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/deployments"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/hpa"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/iam"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/jobs"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/monitoring"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/nodes"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/pods"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/quota"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/registries"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/resources"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/routes"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/statefulsets"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/storage"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/terminal"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/users"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/volumes"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/workloadstatus"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/workspaces"
|
||||
_ "kubesphere.io/kubesphere/pkg/filter/container"
|
||||
)
|
||||
|
||||
@@ -61,14 +54,8 @@ func init() {
|
||||
terminal.Register(ws, "/namespaces/{namespace}/pod/{pod}/shell/{container}")
|
||||
workloadstatus.Register(ws, "/status")
|
||||
quota.Register(ws, "/quota")
|
||||
hpa.Register(ws, "/namespaces/{namespace}/horizontalpodautoscalers/{horizontalpodautoscaler}")
|
||||
jobs.Register(ws, "/namespaces/{namespace}/jobs/{job}")
|
||||
deployments.Register(ws, "/namespaces/{namespace}/deployments/{deployment}/revisions/{revision}")
|
||||
daemonsets.Register(ws, "/namespaces/{namespace}/daemonsets/{daemonset}/revisions/{revision}")
|
||||
statefulsets.Register(ws, "/namespaces/{namespace}/statefulsets/{statefulset}/revisions/{revision}")
|
||||
resources.Register(ws, "/resources")
|
||||
monitoring.Register(ws, "/monitoring")
|
||||
workspaces.Register(ws, "/workspaces")
|
||||
|
||||
// add webservice to default container
|
||||
restful.Add(ws)
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package jobs
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
|
||||
"github.com/emicklei/go-restful-openapi"
|
||||
|
||||
"fmt"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/controllers"
|
||||
)
|
||||
|
||||
func Register(ws *restful.WebService, subPath string) {
|
||||
|
||||
tags := []string{"jobs"}
|
||||
|
||||
ws.Route(ws.POST(subPath).To(handleJob).Consumes("*/*").Metadata(restfulspec.KeyOpenAPITags, tags).Doc("Handle job" +
|
||||
" operation").Param(ws.PathParameter("job", "job name").DataType("string")).Param(ws.PathParameter("namespace",
|
||||
"job's namespace").DataType("string")).Param(ws.QueryParameter("a",
|
||||
"action").DataType("string")).Writes(""))
|
||||
}
|
||||
|
||||
func handleJob(req *restful.Request, resp *restful.Response) {
|
||||
var res interface{}
|
||||
var err error
|
||||
|
||||
job := req.PathParameter("job")
|
||||
namespace := req.PathParameter("namespace")
|
||||
action := req.QueryParameter("a")
|
||||
|
||||
switch action {
|
||||
case "rerun":
|
||||
res, err = controllers.JobReRun(namespace, job)
|
||||
default:
|
||||
resp.WriteHeaderAndEntity(http.StatusForbidden, constants.MessageResponse{Message: fmt.Sprintf("invalid operation %s", action)})
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteEntity(res)
|
||||
}
|
||||
@@ -1,443 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package monitoring
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/emicklei/go-restful-openapi"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/filter/route"
|
||||
"kubesphere.io/kubesphere/pkg/models/metrics"
|
||||
)
|
||||
|
||||
func (u Monitor) monitorPod(request *restful.Request, response *restful.Response) {
|
||||
requestParams := client.ParseMonitoringRequestParams(request)
|
||||
podName := requestParams.PodName
|
||||
metricName := requestParams.MetricsName
|
||||
if podName != "" {
|
||||
// single pod single metric
|
||||
queryType, params, nullRule := metrics.AssemblePodMetricRequestInfo(requestParams, metricName)
|
||||
var res *metrics.FormatedMetric
|
||||
if !nullRule {
|
||||
res = metrics.GetMetric(queryType, params, metricName)
|
||||
}
|
||||
response.WriteAsJson(res)
|
||||
|
||||
} else {
|
||||
// multiple
|
||||
rawMetrics := metrics.MonitorAllMetrics(requestParams, metrics.MetricLevelPod)
|
||||
// sorting
|
||||
sortedMetrics, maxMetricCount := metrics.Sort(requestParams.SortMetricName, requestParams.SortType, rawMetrics, metrics.MetricLevelPodName)
|
||||
// paging
|
||||
pagedMetrics := metrics.Page(requestParams.PageNum, requestParams.LimitNum, sortedMetrics, maxMetricCount)
|
||||
|
||||
response.WriteAsJson(pagedMetrics)
|
||||
}
|
||||
}
|
||||
|
||||
func (u Monitor) monitorContainer(request *restful.Request, response *restful.Response) {
|
||||
requestParams := client.ParseMonitoringRequestParams(request)
|
||||
metricName := requestParams.MetricsName
|
||||
if requestParams.MetricsFilter != "" {
|
||||
rawMetrics := metrics.MonitorAllMetrics(requestParams, metrics.MetricLevelContainer)
|
||||
// sorting
|
||||
sortedMetrics, maxMetricCount := metrics.Sort(requestParams.SortMetricName, requestParams.SortType, rawMetrics, metrics.MetricLevelContainerName)
|
||||
// paging
|
||||
pagedMetrics := metrics.Page(requestParams.PageNum, requestParams.LimitNum, sortedMetrics, maxMetricCount)
|
||||
|
||||
response.WriteAsJson(pagedMetrics)
|
||||
|
||||
} else {
|
||||
res := metrics.MonitorContainer(requestParams, metricName)
|
||||
response.WriteAsJson(res)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (u Monitor) monitorWorkload(request *restful.Request, response *restful.Response) {
|
||||
requestParams := client.ParseMonitoringRequestParams(request)
|
||||
|
||||
rawMetrics := metrics.MonitorAllMetrics(requestParams, metrics.MetricLevelWorkload)
|
||||
|
||||
var sortedMetrics *metrics.FormatedLevelMetric
|
||||
var maxMetricCount int
|
||||
|
||||
wlKind := requestParams.WorkloadKind
|
||||
|
||||
// sorting
|
||||
if wlKind == "" {
|
||||
|
||||
sortedMetrics, maxMetricCount = metrics.Sort(requestParams.SortMetricName, requestParams.SortType, rawMetrics, metrics.MetricLevelWorkload)
|
||||
} else {
|
||||
|
||||
sortedMetrics, maxMetricCount = metrics.Sort(requestParams.SortMetricName, requestParams.SortType, rawMetrics, metrics.MetricLevelPodName)
|
||||
}
|
||||
|
||||
// paging
|
||||
pagedMetrics := metrics.Page(requestParams.PageNum, requestParams.LimitNum, sortedMetrics, maxMetricCount)
|
||||
|
||||
response.WriteAsJson(pagedMetrics)
|
||||
|
||||
}
|
||||
|
||||
func (u Monitor) monitorAllWorkspaces(request *restful.Request, response *restful.Response) {
|
||||
|
||||
requestParams := client.ParseMonitoringRequestParams(request)
|
||||
|
||||
tp := requestParams.Tp
|
||||
if tp == "_statistics" {
|
||||
// merge multiple metric: all-devops, all-roles, all-projects...this api is designed for admin
|
||||
res := metrics.MonitorAllWorkspacesStatistics()
|
||||
|
||||
response.WriteAsJson(res)
|
||||
|
||||
} else if tp == "rank" {
|
||||
rawMetrics := metrics.MonitorAllWorkspaces(requestParams)
|
||||
// sorting
|
||||
sortedMetrics, maxMetricCount := metrics.Sort(requestParams.SortMetricName, requestParams.SortType, rawMetrics, metrics.MetricLevelWorkspace)
|
||||
// paging
|
||||
pagedMetrics := metrics.Page(requestParams.PageNum, requestParams.LimitNum, sortedMetrics, maxMetricCount)
|
||||
|
||||
response.WriteAsJson(pagedMetrics)
|
||||
} else {
|
||||
res := metrics.MonitorAllMetrics(requestParams, metrics.MetricLevelWorkspace)
|
||||
response.WriteAsJson(res)
|
||||
}
|
||||
}
|
||||
|
||||
func (u Monitor) monitorOneWorkspace(request *restful.Request, response *restful.Response) {
|
||||
requestParams := client.ParseMonitoringRequestParams(request)
|
||||
|
||||
tp := requestParams.Tp
|
||||
if tp == "rank" {
|
||||
// multiple
|
||||
rawMetrics := metrics.MonitorAllMetrics(requestParams, metrics.MetricLevelWorkspace)
|
||||
// sorting
|
||||
sortedMetrics, maxMetricCount := metrics.Sort(requestParams.SortMetricName, requestParams.SortType, rawMetrics, metrics.MetricLevelNamespace)
|
||||
// paging
|
||||
pagedMetrics := metrics.Page(requestParams.PageNum, requestParams.LimitNum, sortedMetrics, maxMetricCount)
|
||||
|
||||
response.WriteAsJson(pagedMetrics)
|
||||
|
||||
} else if tp == "_statistics" {
|
||||
wsName := requestParams.WsName
|
||||
|
||||
// merge multiple metric: devops, roles, projects...
|
||||
res := metrics.MonitorOneWorkspaceStatistics(wsName)
|
||||
response.WriteAsJson(res)
|
||||
} else {
|
||||
res := metrics.MonitorAllMetrics(requestParams, metrics.MetricLevelWorkspace)
|
||||
response.WriteAsJson(res)
|
||||
}
|
||||
}
|
||||
|
||||
func (u Monitor) monitorNamespace(request *restful.Request, response *restful.Response) {
|
||||
requestParams := client.ParseMonitoringRequestParams(request)
|
||||
metricName := requestParams.MetricsName
|
||||
nsName := requestParams.NsName
|
||||
if nsName != "" {
|
||||
// single
|
||||
queryType, params := metrics.AssembleNamespaceMetricRequestInfo(requestParams, metricName)
|
||||
res := metrics.GetMetric(queryType, params, metricName)
|
||||
response.WriteAsJson(res)
|
||||
} else {
|
||||
// multiple
|
||||
rawMetrics := metrics.MonitorAllMetrics(requestParams, metrics.MetricLevelNamespace)
|
||||
// sorting
|
||||
sortedMetrics, maxMetricCount := metrics.Sort(requestParams.SortMetricName, requestParams.SortType, rawMetrics, metrics.MetricLevelNamespace)
|
||||
// paging
|
||||
pagedMetrics := metrics.Page(requestParams.PageNum, requestParams.LimitNum, sortedMetrics, maxMetricCount)
|
||||
|
||||
response.WriteAsJson(pagedMetrics)
|
||||
}
|
||||
}
|
||||
|
||||
func (u Monitor) monitorCluster(request *restful.Request, response *restful.Response) {
|
||||
requestParams := client.ParseMonitoringRequestParams(request)
|
||||
|
||||
metricName := requestParams.MetricsName
|
||||
if metricName != "" {
|
||||
// single
|
||||
queryType, params := metrics.AssembleClusterMetricRequestInfo(requestParams, metricName)
|
||||
res := metrics.GetMetric(queryType, params, metricName)
|
||||
|
||||
response.WriteAsJson(res)
|
||||
} else {
|
||||
// multiple
|
||||
res := metrics.MonitorAllMetrics(requestParams, metrics.MetricLevelCluster)
|
||||
response.WriteAsJson(res)
|
||||
}
|
||||
}
|
||||
|
||||
func (u Monitor) monitorNode(request *restful.Request, response *restful.Response) {
|
||||
requestParams := client.ParseMonitoringRequestParams(request)
|
||||
|
||||
metricName := requestParams.MetricsName
|
||||
if metricName != "" {
|
||||
// single
|
||||
queryType, params := metrics.AssembleNodeMetricRequestInfo(requestParams, metricName)
|
||||
res := metrics.GetMetric(queryType, params, metricName)
|
||||
nodeAddress := metrics.GetNodeAddressInfo()
|
||||
metrics.AddNodeAddressMetric(res, nodeAddress)
|
||||
response.WriteAsJson(res)
|
||||
} else {
|
||||
// multiple
|
||||
rawMetrics := metrics.MonitorAllMetrics(requestParams, metrics.MetricLevelNode)
|
||||
nodeAddress := metrics.GetNodeAddressInfo()
|
||||
|
||||
for i := 0; i < len(rawMetrics.Results); i++ {
|
||||
metrics.AddNodeAddressMetric(&rawMetrics.Results[i], nodeAddress)
|
||||
}
|
||||
|
||||
// sorting
|
||||
sortedMetrics, maxMetricCount := metrics.Sort(requestParams.SortMetricName, requestParams.SortType, rawMetrics, metrics.MetricLevelNode)
|
||||
// paging
|
||||
pagedMetrics := metrics.Page(requestParams.PageNum, requestParams.LimitNum, sortedMetrics, maxMetricCount)
|
||||
|
||||
response.WriteAsJson(pagedMetrics)
|
||||
}
|
||||
}
|
||||
|
||||
// k8s component(controller, scheduler, etcd) status
|
||||
func (u Monitor) monitorComponentStatus(request *restful.Request, response *restful.Response) {
|
||||
requestParams := client.ParseMonitoringRequestParams(request)
|
||||
|
||||
status := metrics.MonitorComponentStatus(requestParams)
|
||||
response.WriteAsJson(status)
|
||||
}
|
||||
|
||||
type Monitor struct {
|
||||
}
|
||||
|
||||
func Register(ws *restful.WebService, subPath string) {
|
||||
tags := []string{"monitoring apis"}
|
||||
u := Monitor{}
|
||||
|
||||
ws.Route(ws.GET(subPath+"/clusters").To(u.monitorCluster).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor cluster level metrics").
|
||||
Param(ws.QueryParameter("metrics_filter", "metrics name cpu memory...in re2 regex").DataType("string").Required(false).DefaultValue("cluster_cpu_utilisation")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/nodes").To(u.monitorNode).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor nodes level metrics").
|
||||
Param(ws.QueryParameter("metrics_filter", "metrics name cpu memory...in re2 regex").DataType("string").Required(false).DefaultValue("node_cpu_utilisation")).
|
||||
Param(ws.QueryParameter("nodes_filter", "node re2 expression filter").DataType("string").Required(false).DefaultValue("")).
|
||||
Param(ws.QueryParameter("sort_metric", "sort metric").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("sort_type", "ascending descending order").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("page", "page number").DataType("string").Required(false).DefaultValue("1")).
|
||||
Param(ws.QueryParameter("limit", "metrics name cpu memory...in re2 regex").DataType("string").Required(false).DefaultValue("4")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/nodes/{node_id}").To(u.monitorNode).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor specific node level metrics").
|
||||
Param(ws.PathParameter("node_id", "specific node").DataType("string").Required(true).DefaultValue("")).
|
||||
Param(ws.QueryParameter("metrics_name", "metrics name cpu memory...").DataType("string").Required(true).DefaultValue("node_cpu_utilisation")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/namespaces").To(u.monitorNamespace).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor namespaces level metrics").
|
||||
Param(ws.QueryParameter("namespaces_filter", "namespaces re2 expression filter").DataType("string").Required(false).DefaultValue("")).
|
||||
Param(ws.QueryParameter("metrics_filter", "metrics name cpu memory...in re2 regex").DataType("string").Required(false).DefaultValue("namespace_memory_utilisation")).
|
||||
Param(ws.QueryParameter("sort_metric", "sort metric").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("sort_type", "ascending descending order").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("page", "page number").DataType("string").Required(false).DefaultValue("1")).
|
||||
Param(ws.QueryParameter("limit", "metrics name cpu memory...in re2 regex").DataType("string").Required(false).DefaultValue("4")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/namespaces/{ns_name}").To(u.monitorNamespace).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor specific namespace level metrics").
|
||||
Param(ws.PathParameter("ns_name", "specific namespace").DataType("string").Required(true).DefaultValue("monitoring")).
|
||||
Param(ws.QueryParameter("metrics_name", "metrics name cpu memory...").DataType("string").Required(true).DefaultValue("namespace_memory_utilisation")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/namespaces/{ns_name}/pods").To(u.monitorPod).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor pods level metrics").
|
||||
Param(ws.PathParameter("ns_name", "specific namespace").DataType("string").Required(true).DefaultValue("monitoring")).
|
||||
Param(ws.QueryParameter("metrics_filter", "metrics name cpu memory...in re2 regex").DataType("string").Required(false).DefaultValue("pod_memory_utilisation_wo_cache")).
|
||||
Param(ws.QueryParameter("pods_filter", "pod re2 expression filter").DataType("string").Required(false).DefaultValue("")).
|
||||
Param(ws.QueryParameter("sort_metric", "sort metric").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("sort_type", "ascending descending order").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("page", "page number").DataType("string").Required(false).DefaultValue("1")).
|
||||
Param(ws.QueryParameter("limit", "metrics name cpu memory...in re2 regex").DataType("string").Required(false).DefaultValue("4")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/namespaces/{ns_name}/pods/{pod_name}").To(u.monitorPod).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor specific pod level metrics").
|
||||
Param(ws.PathParameter("ns_name", "specific namespace").DataType("string").Required(true).DefaultValue("monitoring")).
|
||||
Param(ws.PathParameter("pod_name", "specific pod").DataType("string").Required(true).DefaultValue("")).
|
||||
Param(ws.QueryParameter("metrics_name", "metrics name cpu memory...").DataType("string").Required(true).DefaultValue("pod_memory_utilisation_wo_cache")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/nodes/{node_id}/pods").To(u.monitorPod).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor pods level metrics by nodeid").
|
||||
Param(ws.PathParameter("node_id", "specific node").DataType("string").Required(true).DefaultValue("i-k89a62il")).
|
||||
Param(ws.QueryParameter("metrics_filter", "metrics name cpu memory...in re2 regex").DataType("string").Required(false).DefaultValue("pod_memory_utilisation_wo_cache")).
|
||||
Param(ws.QueryParameter("pods_filter", "pod re2 expression filter").DataType("string").Required(false).DefaultValue("openpitrix.*")).
|
||||
Param(ws.QueryParameter("sort_metric", "sort metric").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("sort_type", "ascending descending order").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("page", "page number").DataType("string").Required(false).DefaultValue("1")).
|
||||
Param(ws.QueryParameter("limit", "metrics name cpu memory...in re2 regex").DataType("string").Required(false).DefaultValue("4")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/nodes/{node_id}/pods/{pod_name}").To(u.monitorPod).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor specific pod level metrics by nodeid").
|
||||
Param(ws.PathParameter("node_id", "specific node").DataType("string").Required(true).DefaultValue("i-k89a62il")).
|
||||
Param(ws.PathParameter("pod_name", "specific pod").DataType("string").Required(true).DefaultValue("")).
|
||||
Param(ws.QueryParameter("metrics_name", "metrics name cpu memory...").DataType("string").Required(true).DefaultValue("pod_memory_utilisation_wo_cache")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/nodes/{node_id}/pods/{pod_name}/containers").To(u.monitorContainer).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor specific pod level metrics by nodeid").
|
||||
Param(ws.PathParameter("node_id", "specific node").DataType("string").Required(true)).
|
||||
Param(ws.PathParameter("pod_name", "specific pod").DataType("string").Required(true)).
|
||||
Param(ws.QueryParameter("containers_filter", "container re2 expression filter").DataType("string").Required(false).DefaultValue("")).
|
||||
Param(ws.QueryParameter("metrics_filter", "metrics name cpu memory...").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("metrics_name", "metrics name cpu memory...").DataType("string").Required(true).DefaultValue("pod_memory_utilisation_wo_cache")).
|
||||
Param(ws.QueryParameter("sort_metric", "sort metric").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("sort_type", "ascending descending order").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("page", "page number").DataType("string").Required(false).DefaultValue("1")).
|
||||
Param(ws.QueryParameter("limit", "metrics name cpu memory...in re2 regex").DataType("string").Required(false).DefaultValue("4")).
|
||||
Param(ws.QueryParameter("type", "rank, statistic").DataType("string").Required(false).DefaultValue("rank")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/namespaces/{ns_name}/pods/{pod_name}/containers").To(u.monitorContainer).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor containers level metrics").
|
||||
Param(ws.PathParameter("ns_name", "specific namespace").DataType("string").Required(true).DefaultValue("monitoring")).
|
||||
Param(ws.PathParameter("pod_name", "specific pod").DataType("string").Required(true).DefaultValue("")).
|
||||
Param(ws.QueryParameter("containers_filter", "container re2 expression filter").DataType("string").Required(false).DefaultValue("")).
|
||||
Param(ws.QueryParameter("metrics_filter", "metrics name cpu memory...").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("metrics_name", "metrics name cpu memory...").DataType("string").Required(true).DefaultValue("container_memory_utilisation_wo_cache")).
|
||||
Param(ws.QueryParameter("sort_metric", "sort metric").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("sort_type", "ascending descending order").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("page", "page number").DataType("string").Required(false).DefaultValue("1")).
|
||||
Param(ws.QueryParameter("limit", "metrics name cpu memory...in re2 regex").DataType("string").Required(false).DefaultValue("4")).
|
||||
Param(ws.QueryParameter("type", "rank, statistic").DataType("string").Required(false).DefaultValue("rank")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/namespaces/{ns_name}/pods/{pod_name}/containers/{container_name}").To(u.monitorContainer).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor specific container level metrics").
|
||||
Param(ws.PathParameter("ns_name", "specific namespace").DataType("string").Required(true).DefaultValue("monitoring")).
|
||||
Param(ws.PathParameter("pod_name", "specific pod").DataType("string").Required(true).DefaultValue("")).
|
||||
Param(ws.PathParameter("container_name", "specific container").DataType("string").Required(true).DefaultValue("")).
|
||||
Param(ws.QueryParameter("metrics_name", "metrics name cpu memory...").DataType("string").Required(true).DefaultValue("container_memory_utilisation_wo_cache")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/namespaces/{ns_name}/workloads/{workload_kind}").To(u.monitorWorkload).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor specific workload level metrics").
|
||||
Param(ws.PathParameter("ns_name", "namespace").DataType("string").Required(true).DefaultValue("kube-system")).
|
||||
Param(ws.QueryParameter("metrics_filter", "metrics name cpu memory...").DataType("string").Required(false)).
|
||||
Param(ws.PathParameter("workload_kind", "workload kind").DataType("string").Required(false).DefaultValue("daemonset")).
|
||||
Param(ws.QueryParameter("workload_name", "workload name").DataType("string").Required(true).DefaultValue("")).
|
||||
Param(ws.QueryParameter("pods_filter", "pod re2 expression filter").DataType("string").Required(false).DefaultValue("openpitrix.*")).
|
||||
Param(ws.QueryParameter("sort_metric", "sort metric").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("sort_type", "ascending descending order").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("page", "page number").DataType("string").Required(false).DefaultValue("1")).
|
||||
Param(ws.QueryParameter("limit", "max metric items in a page").DataType("string").Required(false).DefaultValue("4")).
|
||||
Param(ws.QueryParameter("type", "rank, statistic").DataType("string").Required(false).DefaultValue("rank")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/namespaces/{ns_name}/workloads").To(u.monitorWorkload).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor all workload level metrics").
|
||||
Param(ws.PathParameter("ns_name", "namespace").DataType("string").Required(true).DefaultValue("kube-system")).
|
||||
Param(ws.QueryParameter("metrics_filter", "metrics name cpu memory...").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("workloads_filter", "pod re2 expression filter").DataType("string").Required(false).DefaultValue("")).
|
||||
Param(ws.QueryParameter("sort_metric", "sort metric").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("sort_type", "ascending descending order").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("page", "page number").DataType("string").Required(false).DefaultValue("1")).
|
||||
Param(ws.QueryParameter("limit", "metrics name cpu memory...in re2 regex").DataType("string").Required(false).DefaultValue("4")).
|
||||
Param(ws.QueryParameter("type", "rank, statistic").DataType("string").Required(false).DefaultValue("rank")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
// list all namespace in this workspace by selected metrics
|
||||
ws.Route(ws.GET(subPath+"/workspaces/{workspace_name}").To(u.monitorOneWorkspace).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor workspaces level metrics").
|
||||
Param(ws.PathParameter("workspace_name", "workspace name").DataType("string").Required(true)).
|
||||
Param(ws.QueryParameter("namespaces_filter", "namespaces filter").DataType("string").Required(false).DefaultValue("k.*")).
|
||||
Param(ws.QueryParameter("metrics_filter", "metrics name cpu memory...in re2 regex").DataType("string").Required(false).DefaultValue("namespace_memory_utilisation_wo_cache")).
|
||||
Param(ws.QueryParameter("sort_metric", "sort metric").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("sort_type", "ascending descending order").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("page", "page number").DataType("string").Required(false).DefaultValue("1")).
|
||||
Param(ws.QueryParameter("limit", "metrics name cpu memory...in re2 regex").DataType("string").Required(false).DefaultValue("4")).
|
||||
Param(ws.QueryParameter("type", "rank, statistic").DataType("string").Required(false).DefaultValue("rank")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/workspaces").To(u.monitorAllWorkspaces).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor workspaces level metrics").
|
||||
Param(ws.QueryParameter("metrics_filter", "metrics name cpu memory...in re2 regex").DataType("string").Required(false).DefaultValue("workspace_memory_utilisation")).
|
||||
Param(ws.QueryParameter("workspaces_filter", "workspaces re2 expression filter").DataType("string").Required(false).DefaultValue(".*")).
|
||||
Param(ws.QueryParameter("sort_metric", "sort metric").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("sort_type", "ascending descending order").DataType("string").Required(false)).
|
||||
Param(ws.QueryParameter("page", "page number").DataType("string").Required(false).DefaultValue("1")).
|
||||
Param(ws.QueryParameter("limit", "metrics name cpu memory...in re2 regex").DataType("string").Required(false).DefaultValue("4")).
|
||||
Param(ws.QueryParameter("type", "rank, statistic").DataType("string").Required(false).DefaultValue("rank")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath+"/components").To(u.monitorComponentStatus).
|
||||
Filter(route.RouteLogging).
|
||||
Doc("monitor k8s components status").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
}
|
||||
@@ -55,23 +55,6 @@ func Register(ws *restful.WebService, subPath string) {
|
||||
Consumes(restful.MIME_JSON).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET(subPath + "/{name}/namespaces/{namespace}/searchwords/{searchWord}").
|
||||
Param(ws.PathParameter("namespace", "registry secret's namespace")).
|
||||
Param(ws.PathParameter("name", "registry secret's name")).
|
||||
Param(ws.PathParameter("searchWord", "keyword use to search image")).
|
||||
To(handlerImageSearch).
|
||||
Filter(route.RouteLogging)).
|
||||
Consumes(restful.MIME_JSON).
|
||||
Produces(restful.MIME_JSON)
|
||||
ws.Route(ws.GET(subPath + "/{name}/namespaces/{namespace}/tags").
|
||||
Param(ws.QueryParameter("image", "imageName")).
|
||||
Param(ws.PathParameter("namespace", "registry secret's namespace")).
|
||||
Param(ws.PathParameter("name", "registry secret's name")).
|
||||
To(handlerGetImageTags).
|
||||
Filter(route.RouteLogging)).
|
||||
Consumes(restful.MIME_JSON).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
}
|
||||
|
||||
func handlerRegistryValidation(request *restful.Request, response *restful.Response) {
|
||||
@@ -94,30 +77,6 @@ func handlerRegistryValidation(request *restful.Request, response *restful.Respo
|
||||
|
||||
}
|
||||
|
||||
func handlerImageSearch(request *restful.Request, response *restful.Response) {
|
||||
|
||||
registry := request.PathParameter("name")
|
||||
searchWord := request.PathParameter("searchWord")
|
||||
namespace := request.PathParameter("namespace")
|
||||
|
||||
res := models.ImageSearch(namespace, registry, searchWord)
|
||||
|
||||
response.WriteEntity(res)
|
||||
|
||||
}
|
||||
|
||||
func handlerGetImageTags(request *restful.Request, response *restful.Response) {
|
||||
|
||||
registry := request.PathParameter("name")
|
||||
image := request.QueryParameter("image")
|
||||
namespace := request.PathParameter("namespace")
|
||||
|
||||
res := models.GetImageTags(namespace, registry, image)
|
||||
|
||||
response.WriteEntity(res)
|
||||
|
||||
}
|
||||
|
||||
func handleCreateRegistries(request *restful.Request, response *restful.Response) {
|
||||
|
||||
registries := models.Registries{}
|
||||
|
||||
@@ -23,9 +23,6 @@ import (
|
||||
|
||||
"github.com/emicklei/go-restful-openapi"
|
||||
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
)
|
||||
@@ -34,37 +31,15 @@ func Register(ws *restful.WebService, subPath string) {
|
||||
|
||||
tags := []string{"resources"}
|
||||
|
||||
ws.Route(ws.GET(subPath+"/{resource}").To(listResource).
|
||||
Produces(restful.MIME_JSON).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Doc("Get resource list").
|
||||
Param(ws.PathParameter("resource", "resource name").DataType("string")).
|
||||
Param(ws.QueryParameter("conditions", "search conditions").DataType("string")).
|
||||
Param(ws.QueryParameter("reverse", "support reverse ordering").DataType("bool").DefaultValue("false")).
|
||||
Param(ws.QueryParameter("order", "the field for sorting").DataType("string")).
|
||||
Param(ws.QueryParameter("paging", "support paging function").DataType("string")).
|
||||
Writes(models.ResourceList{}))
|
||||
ws.Route(ws.GET(subPath+"/{resource}").To(handleResource).Produces(restful.MIME_JSON).Metadata(restfulspec.KeyOpenAPITags, tags).Doc("Get resource" +
|
||||
" list").Param(ws.PathParameter("resource", "resource name").DataType(
|
||||
"string")).Param(ws.QueryParameter("conditions", "search "+
|
||||
"conditions").DataType("string")).Param(ws.QueryParameter("paging",
|
||||
"support paging function").DataType("string")).Writes(models.ResourceList{}))
|
||||
|
||||
}
|
||||
|
||||
func isInvalid(str string) bool {
|
||||
invalidList := []string{"exec", "insert", "select", "delete", "update", "count", "*", "%", "truncate", "drop"}
|
||||
str = strings.Replace(str, "=", " ", -1)
|
||||
str = strings.Replace(str, ",", " ", -1)
|
||||
str = strings.Replace(str, "~", " ", -1)
|
||||
items := strings.Split(str, " ")
|
||||
|
||||
for _, invalid := range invalidList {
|
||||
for _, item := range items {
|
||||
if item == invalid || strings.ToLower(item) == invalid {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func listResource(req *restful.Request, resp *restful.Response) {
|
||||
func handleResource(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
resource := req.PathParameter("resource")
|
||||
if resource == "applications" {
|
||||
@@ -73,23 +48,7 @@ func listResource(req *restful.Request, resp *restful.Response) {
|
||||
}
|
||||
conditions := req.QueryParameter("conditions")
|
||||
paging := req.QueryParameter("paging")
|
||||
orderField := req.QueryParameter("order")
|
||||
reverse := req.QueryParameter("reverse")
|
||||
|
||||
if len(orderField) > 0 {
|
||||
if reverse == "true" {
|
||||
orderField = fmt.Sprintf("%s %s", orderField, "desc")
|
||||
} else {
|
||||
orderField = fmt.Sprintf("%s %s", orderField, "asc")
|
||||
}
|
||||
}
|
||||
|
||||
if isInvalid(conditions) || isInvalid(paging) || isInvalid(orderField) {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, constants.MessageResponse{Message: "invalid input"})
|
||||
return
|
||||
}
|
||||
|
||||
res, err := models.ListResource(resource, conditions, paging, orderField)
|
||||
res, err := models.ListResource(resource, conditions, paging)
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
@@ -99,6 +58,7 @@ func listResource(req *restful.Request, resp *restful.Response) {
|
||||
}
|
||||
|
||||
func handleApplication(req *restful.Request, resp *restful.Response) {
|
||||
//searchWord := req.QueryParameter("search-word")
|
||||
paging := req.QueryParameter("paging")
|
||||
clusterId := req.QueryParameter("cluster_id")
|
||||
runtimeId := req.QueryParameter("runtime_id")
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package statefulsets
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/emicklei/go-restful-openapi"
|
||||
"k8s.io/api/apps/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
)
|
||||
|
||||
func Register(ws *restful.WebService, subPath string) {
|
||||
|
||||
tags := []string{"statefulsets"}
|
||||
|
||||
ws.Route(ws.GET(subPath).To(getDaemonSetRevision).Consumes("*/*").Metadata(restfulspec.KeyOpenAPITags, tags).Doc("Handle statefulset" +
|
||||
" operation").Param(ws.PathParameter("statefulset", "statefulset's name").DataType("string")).Param(ws.PathParameter("namespace",
|
||||
"statefulset's namespace").DataType("string")).Param(ws.PathParameter("revision", "statefulset's revision")).Writes(v1.StatefulSet{}))
|
||||
}
|
||||
|
||||
func getDaemonSetRevision(req *restful.Request, resp *restful.Response) {
|
||||
statefulset := req.PathParameter("statefulset")
|
||||
namespace := req.PathParameter("namespace")
|
||||
revision := req.PathParameter("revision")
|
||||
|
||||
res, err := models.GetStatefulSetRevision(namespace, statefulset, revision)
|
||||
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
resp.WriteHeaderAndEntity(http.StatusNotFound, constants.MessageResponse{Message: err.Error()})
|
||||
} else {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
}
|
||||
}
|
||||
|
||||
resp.WriteEntity(res)
|
||||
}
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
"kubesphere.io/kubesphere/pkg/models/kubectl"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam"
|
||||
)
|
||||
|
||||
func Register(ws *restful.WebService, subPath string) {
|
||||
@@ -55,6 +55,13 @@ func createUser(req *restful.Request, resp *restful.Response) {
|
||||
return
|
||||
}
|
||||
|
||||
err = models.CreateKubectlDeploy(user)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteEntity(constants.MessageResponse{Message: "successfully created"})
|
||||
}
|
||||
|
||||
@@ -62,7 +69,7 @@ func delUser(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
user := req.PathParameter("user")
|
||||
|
||||
err := kubectl.DelKubectlDeploy(user)
|
||||
err := models.DelKubectlDeploy(user)
|
||||
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
@@ -76,6 +83,13 @@ func delUser(req *restful.Request, resp *restful.Response) {
|
||||
return
|
||||
}
|
||||
|
||||
err = iam.DeleteRoleBindings(user)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteEntity(constants.MessageResponse{Message: "successfully deleted"})
|
||||
}
|
||||
|
||||
@@ -83,7 +97,7 @@ func getKubectl(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
user := req.PathParameter("user")
|
||||
|
||||
kubectlPod, err := kubectl.GetKubectlPod(user)
|
||||
kubectlPod, err := models.GetKubectlPod(user)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
|
||||
@@ -1,536 +0,0 @@
|
||||
package workspaces
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"k8s.io/api/core/v1"
|
||||
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kubernetes/pkg/util/slice"
|
||||
|
||||
"strconv"
|
||||
|
||||
"regexp"
|
||||
|
||||
"sort"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam"
|
||||
"kubesphere.io/kubesphere/pkg/models/metrics"
|
||||
"kubesphere.io/kubesphere/pkg/models/workspaces"
|
||||
)
|
||||
|
||||
const UserNameHeader = "X-Token-Username"
|
||||
|
||||
func Register(ws *restful.WebService, subPath string) {
|
||||
|
||||
ws.Route(ws.GET(subPath).To(UserWorkspaceListHandler))
|
||||
ws.Route(ws.POST(subPath).To(WorkspaceCreateHandler))
|
||||
ws.Route(ws.DELETE(subPath + "/{name}").To(DeleteWorkspaceHandler))
|
||||
ws.Route(ws.GET(subPath + "/{name}").To(WorkspaceDetailHandler))
|
||||
ws.Route(ws.PUT(subPath + "/{name}").To(WorkspaceEditHandler))
|
||||
ws.Route(ws.GET(subPath + "/{workspace}/namespaces").To(UserNamespaceListHandler))
|
||||
ws.Route(ws.GET(subPath + "/{workspace}/members/{username}/namespaces").To(UserNamespaceListHandler))
|
||||
ws.Route(ws.POST(subPath + "/{name}/namespaces").To(NamespaceCreateHandler))
|
||||
ws.Route(ws.DELETE(subPath + "/{name}/namespaces/{namespace}").To(NamespaceDeleteHandler))
|
||||
ws.Route(ws.GET(subPath + "/{name}/namespaces/{namespace}").To(NamespaceCheckHandler))
|
||||
ws.Route(ws.GET("/namespaces/{namespace}").To(NamespaceCheckHandler))
|
||||
ws.Route(ws.GET(subPath + "/{name}/devops").To(DevOpsProjectHandler))
|
||||
ws.Route(ws.GET(subPath + "/{name}/members/{username}/devops").To(DevOpsProjectHandler))
|
||||
ws.Route(ws.POST(subPath + "/{name}/devops").To(DevOpsProjectCreateHandler))
|
||||
ws.Route(ws.DELETE(subPath + "/{name}/devops/{id}").To(DevOpsProjectDeleteHandler))
|
||||
|
||||
ws.Route(ws.GET(subPath + "/{name}/members").To(MembersHandler))
|
||||
ws.Route(ws.GET(subPath + "/{name}/members/{member}").To(MemberHandler))
|
||||
ws.Route(ws.GET(subPath + "/{name}/roles").To(RolesHandler))
|
||||
ws.Route(ws.GET(subPath + "/{name}/roles/{role}").To(RoleHandler))
|
||||
ws.Route(ws.POST(subPath + "/{name}/members").To(MembersInviteHandler))
|
||||
ws.Route(ws.DELETE(subPath + "/{name}/members").To(MembersRemoveHandler))
|
||||
}
|
||||
|
||||
func RoleHandler(req *restful.Request, resp *restful.Response) {
|
||||
workspaceName := req.PathParameter("name")
|
||||
roleName := req.PathParameter("role")
|
||||
|
||||
if !slice.ContainsString(constants.WorkSpaceRoles, roleName, nil) {
|
||||
resp.WriteHeaderAndEntity(http.StatusNotFound, constants.MessageResponse{Message: fmt.Sprintf("role %s not found", roleName)})
|
||||
return
|
||||
}
|
||||
|
||||
role, rules, err := iam.WorkspaceRoleRules(workspaceName, roleName)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
users, err := iam.WorkspaceRoleUsers(workspaceName, roleName)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteEntity(map[string]interface{}{"role": role, "rules": rules, "users": users})
|
||||
}
|
||||
|
||||
func RolesHandler(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
name := req.PathParameter("name")
|
||||
|
||||
workspace, err := workspaces.Detail(name)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
roles, err := workspaces.Roles(workspace)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteEntity(roles)
|
||||
}
|
||||
|
||||
func MembersHandler(req *restful.Request, resp *restful.Response) {
|
||||
workspace := req.PathParameter("name")
|
||||
keyword := req.QueryParameter("keyword")
|
||||
|
||||
users, err := workspaces.GetWorkspaceMembers(workspace, keyword)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteEntity(users)
|
||||
}
|
||||
|
||||
func MemberHandler(req *restful.Request, resp *restful.Response) {
|
||||
workspace := req.PathParameter("name")
|
||||
username := req.PathParameter("member")
|
||||
|
||||
user, err := iam.GetUser(username)
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
namespaces, err := workspaces.Namespaces(workspace)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
user.WorkspaceRole = user.WorkspaceRoles[workspace]
|
||||
|
||||
roles := make(map[string]string)
|
||||
|
||||
for _, namespace := range namespaces {
|
||||
if role := user.Roles[namespace.Name]; role != "" {
|
||||
roles[namespace.Name] = role
|
||||
}
|
||||
}
|
||||
|
||||
user.Roles = roles
|
||||
user.Rules = nil
|
||||
user.WorkspaceRules = nil
|
||||
user.WorkspaceRoles = nil
|
||||
user.ClusterRules = nil
|
||||
resp.WriteEntity(user)
|
||||
}
|
||||
|
||||
func MembersInviteHandler(req *restful.Request, resp *restful.Response) {
|
||||
var users []workspaces.UserInvite
|
||||
workspace := req.PathParameter("name")
|
||||
err := req.ReadEntity(&users)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
err = workspaces.Invite(workspace, users)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteHeaderAndEntity(http.StatusOK, constants.MessageResponse{Message: "success"})
|
||||
}
|
||||
|
||||
func MembersRemoveHandler(req *restful.Request, resp *restful.Response) {
|
||||
query := req.QueryParameter("name")
|
||||
workspace := req.PathParameter("name")
|
||||
|
||||
names := strings.Split(query, ",")
|
||||
|
||||
err := workspaces.RemoveMembers(workspace, names)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteHeaderAndEntity(http.StatusOK, constants.MessageResponse{Message: "success"})
|
||||
}
|
||||
|
||||
func NamespaceCheckHandler(req *restful.Request, resp *restful.Response) {
|
||||
namespace := req.PathParameter("namespace")
|
||||
|
||||
exist, err := workspaces.NamespaceExistCheck(namespace)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteEntity(map[string]bool{"exist": exist})
|
||||
}
|
||||
|
||||
func NamespaceDeleteHandler(req *restful.Request, resp *restful.Response) {
|
||||
namespace := req.PathParameter("namespace")
|
||||
workspace := req.PathParameter("name")
|
||||
|
||||
err := workspaces.DeleteNamespace(workspace, namespace)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteHeaderAndEntity(http.StatusOK, constants.MessageResponse{Message: "success"})
|
||||
}
|
||||
|
||||
func DevOpsProjectDeleteHandler(req *restful.Request, resp *restful.Response) {
|
||||
devops := req.PathParameter("id")
|
||||
workspace := req.PathParameter("name")
|
||||
force := req.QueryParameter("force")
|
||||
username := req.HeaderParameter(UserNameHeader)
|
||||
|
||||
err := workspaces.UnBindDevopsProject(workspace, devops)
|
||||
|
||||
if err != nil && force != "true" {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
err = workspaces.DeleteDevopsProject(username, devops)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteEntity(constants.MessageResponse{Message: "success"})
|
||||
}
|
||||
|
||||
func DevOpsProjectCreateHandler(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
workspace := req.PathParameter("name")
|
||||
username := req.HeaderParameter(UserNameHeader)
|
||||
|
||||
var devops workspaces.DevopsProject
|
||||
|
||||
err := req.ReadEntity(&devops)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
project, err := workspaces.CreateDevopsProject(username, workspace, devops)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteEntity(project)
|
||||
|
||||
}
|
||||
|
||||
func NamespaceCreateHandler(req *restful.Request, resp *restful.Response) {
|
||||
workspace := req.PathParameter("name")
|
||||
username := req.HeaderParameter(UserNameHeader)
|
||||
|
||||
namespace := &v1.Namespace{}
|
||||
|
||||
err := req.ReadEntity(namespace)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if namespace.Annotations == nil {
|
||||
namespace.Annotations = make(map[string]string, 0)
|
||||
}
|
||||
|
||||
namespace.Annotations["creator"] = username
|
||||
namespace.Annotations["workspace"] = workspace
|
||||
|
||||
if namespace.Labels == nil {
|
||||
namespace.Labels = make(map[string]string, 0)
|
||||
}
|
||||
|
||||
namespace.Labels["kubesphere.io/workspace"] = workspace
|
||||
|
||||
namespace, err = workspaces.CreateNamespace(namespace)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteEntity(namespace)
|
||||
}
|
||||
|
||||
func DevOpsProjectHandler(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
workspace := req.PathParameter("name")
|
||||
username := req.PathParameter("username")
|
||||
keyword := req.QueryParameter("keyword")
|
||||
|
||||
if username == "" {
|
||||
username = req.HeaderParameter(UserNameHeader)
|
||||
}
|
||||
|
||||
limit := 65535
|
||||
offset := 0
|
||||
orderBy := "createTime"
|
||||
reverse := true
|
||||
|
||||
if groups := regexp.MustCompile(`^limit=(\d+),page=(\d+)$`).FindStringSubmatch(req.QueryParameter("paging")); len(groups) == 3 {
|
||||
limit, _ = strconv.Atoi(groups[1])
|
||||
page, _ := strconv.Atoi(groups[2])
|
||||
offset = (page - 1) * limit
|
||||
}
|
||||
|
||||
if groups := regexp.MustCompile(`^(createTime|name)$`).FindStringSubmatch(req.QueryParameter("order")); len(groups) == 2 {
|
||||
orderBy = groups[1]
|
||||
reverse = false
|
||||
}
|
||||
|
||||
if q := req.QueryParameter("reverse"); q != "" {
|
||||
b, err := strconv.ParseBool(q)
|
||||
if err == nil {
|
||||
reverse = b
|
||||
}
|
||||
}
|
||||
|
||||
total, devOpsProjects, err := workspaces.ListDevopsProjectsByUser(username, workspace, keyword, orderBy, reverse, limit, offset)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
result := constants.PageableResponse{}
|
||||
result.TotalCount = total
|
||||
result.Items = make([]interface{}, 0)
|
||||
for _, n := range devOpsProjects {
|
||||
result.Items = append(result.Items, n)
|
||||
}
|
||||
resp.WriteEntity(result)
|
||||
}
|
||||
|
||||
func WorkspaceCreateHandler(req *restful.Request, resp *restful.Response) {
|
||||
var workspace workspaces.Workspace
|
||||
username := req.HeaderParameter(UserNameHeader)
|
||||
err := req.ReadEntity(&workspace)
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
if workspace.Name == "" || strings.Contains(workspace.Name, ":") {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, constants.MessageResponse{Message: "invalid workspace name"})
|
||||
return
|
||||
}
|
||||
|
||||
workspace.Path = workspace.Name
|
||||
workspace.Members = nil
|
||||
|
||||
if workspace.Admin != "" {
|
||||
workspace.Creator = workspace.Admin
|
||||
} else {
|
||||
workspace.Creator = username
|
||||
}
|
||||
|
||||
created, err := workspaces.Create(&workspace)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteEntity(created)
|
||||
|
||||
}
|
||||
|
||||
func DeleteWorkspaceHandler(req *restful.Request, resp *restful.Response) {
|
||||
name := req.PathParameter("name")
|
||||
|
||||
if name == "" || strings.Contains(name, ":") {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, constants.MessageResponse{Message: "invalid workspace name"})
|
||||
return
|
||||
}
|
||||
|
||||
workspace, err := workspaces.Detail(name)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
err = workspaces.Delete(workspace)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteEntity(constants.MessageResponse{Message: "success"})
|
||||
}
|
||||
func WorkspaceEditHandler(req *restful.Request, resp *restful.Response) {
|
||||
var workspace workspaces.Workspace
|
||||
name := req.PathParameter("name")
|
||||
err := req.ReadEntity(&workspace)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if name != workspace.Name {
|
||||
resp.WriteError(http.StatusBadRequest, fmt.Errorf("the name of workspace (%s) does not match the name on the URL (%s)", workspace.Name, name))
|
||||
return
|
||||
}
|
||||
|
||||
if workspace.Name == "" || strings.Contains(workspace.Name, ":") {
|
||||
resp.WriteHeaderAndEntity(http.StatusBadRequest, constants.MessageResponse{Message: "invalid workspace name"})
|
||||
return
|
||||
}
|
||||
|
||||
workspace.Path = workspace.Name
|
||||
|
||||
workspace.Members = nil
|
||||
|
||||
edited, err := workspaces.Edit(&workspace)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteEntity(edited)
|
||||
}
|
||||
func WorkspaceDetailHandler(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
name := req.PathParameter("name")
|
||||
|
||||
workspace, err := workspaces.Detail(name)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteEntity(workspace)
|
||||
}
|
||||
|
||||
// List all workspaces for the current user
|
||||
func UserWorkspaceListHandler(req *restful.Request, resp *restful.Response) {
|
||||
keyword := req.QueryParameter("keyword")
|
||||
username := req.HeaderParameter(UserNameHeader)
|
||||
|
||||
ws, err := workspaces.ListWorkspaceByUser(username, keyword)
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
sort.Slice(ws, func(i, j int) bool {
|
||||
t1, err := ws[i].GetCreateTime()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
t2, err := ws[j].GetCreateTime()
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
return t1.After(t2)
|
||||
})
|
||||
|
||||
resp.WriteEntity(ws)
|
||||
}
|
||||
|
||||
func UserNamespaceListHandler(req *restful.Request, resp *restful.Response) {
|
||||
withMetrics, err := strconv.ParseBool(req.QueryParameter("metrics"))
|
||||
|
||||
if err != nil {
|
||||
withMetrics = false
|
||||
}
|
||||
|
||||
username := req.PathParameter("username")
|
||||
keyword := req.QueryParameter("keyword")
|
||||
if username == "" {
|
||||
username = req.HeaderParameter(UserNameHeader)
|
||||
}
|
||||
limit := 65535
|
||||
offset := 0
|
||||
orderBy := "createTime"
|
||||
reverse := true
|
||||
|
||||
if groups := regexp.MustCompile(`^limit=(\d+),page=(\d+)$`).FindStringSubmatch(req.QueryParameter("paging")); len(groups) == 3 {
|
||||
limit, _ = strconv.Atoi(groups[1])
|
||||
page, _ := strconv.Atoi(groups[2])
|
||||
if page < 0 {
|
||||
page = 1
|
||||
}
|
||||
offset = (page - 1) * limit
|
||||
}
|
||||
|
||||
if groups := regexp.MustCompile(`^(createTime|name)$`).FindStringSubmatch(req.QueryParameter("order")); len(groups) == 2 {
|
||||
orderBy = groups[1]
|
||||
reverse = false
|
||||
}
|
||||
|
||||
if q := req.QueryParameter("reverse"); q != "" {
|
||||
b, err := strconv.ParseBool(q)
|
||||
if err == nil {
|
||||
reverse = b
|
||||
}
|
||||
}
|
||||
|
||||
workspaceName := req.PathParameter("workspace")
|
||||
|
||||
total, namespaces, err := workspaces.ListNamespaceByUser(workspaceName, username, keyword, orderBy, reverse, limit, offset)
|
||||
|
||||
if withMetrics {
|
||||
namespaces = metrics.GetNamespacesWithMetrics(namespaces)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
result := constants.PageableResponse{}
|
||||
result.TotalCount = total
|
||||
result.Items = make([]interface{}, 0)
|
||||
for _, n := range namespaces {
|
||||
result.Items = append(result.Items, n)
|
||||
}
|
||||
|
||||
resp.WriteEntity(result)
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/core/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"net"
|
||||
@@ -32,20 +33,11 @@ import (
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
|
||||
"os"
|
||||
"os/signal"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
|
||||
_ "kubesphere.io/kubesphere/pkg/apis/v1alpha"
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
"kubesphere.io/kubesphere/pkg/models/controllers"
|
||||
"kubesphere.io/kubesphere/pkg/models/kubectl"
|
||||
"kubesphere.io/kubesphere/pkg/models/workspaces"
|
||||
"kubesphere.io/kubesphere/pkg/options"
|
||||
)
|
||||
|
||||
@@ -76,42 +68,26 @@ func newKubeSphereServer(options *options.ServerRunOptions) *kubeSphereServer {
|
||||
func preCheck() error {
|
||||
k8sClient := client.NewK8sClient()
|
||||
_, err := k8sClient.CoreV1().Namespaces().Get(constants.KubeSphereControlNamespace, metaV1.GetOptions{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
_, err = k8sClient.CoreV1().Namespaces().Create(&v1.Namespace{ObjectMeta: metaV1.ObjectMeta{Name: constants.KubeSphereControlNamespace}})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if errors.IsNotFound(err) {
|
||||
namespace := v1.Namespace{ObjectMeta: metaV1.ObjectMeta{Name: constants.KubeSphereControlNamespace}}
|
||||
_, err = k8sClient.CoreV1().Namespaces().Create(&namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = k8sClient.AppsV1().Deployments(constants.KubeSphereControlNamespace).Get(constants.AdminUserName, metaV1.GetOptions{})
|
||||
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
if err = models.CreateKubeConfig(constants.AdminUserName); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = kubectl.CreateKubectlDeploy(constants.AdminUserName); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
if errors.IsNotFound(err) {
|
||||
models.CreateKubeConfig(constants.AdminUserName)
|
||||
models.CreateKubectlDeploy(constants.AdminUserName)
|
||||
return nil
|
||||
}
|
||||
|
||||
db := client.NewSharedDBClient()
|
||||
defer db.Close()
|
||||
|
||||
if !db.HasTable(&workspaces.WorkspaceDPBinding{}) {
|
||||
if err := db.CreateTable(&workspaces.WorkspaceDPBinding{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
func registerSwagger() {
|
||||
@@ -142,10 +118,7 @@ func (server *kubeSphereServer) run() {
|
||||
return
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
stopChan := make(chan struct{})
|
||||
wg.Add(1)
|
||||
go controllers.Run(stopChan, &wg)
|
||||
go controllers.Run()
|
||||
|
||||
registerSwagger()
|
||||
|
||||
@@ -174,12 +147,7 @@ func (server *kubeSphereServer) run() {
|
||||
go func() { glog.Fatal(http.ListenAndServe(insecureAddr, nil)) }()
|
||||
}
|
||||
|
||||
sigs := make(chan os.Signal)
|
||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
<-sigs
|
||||
close(stopChan)
|
||||
wg.Wait()
|
||||
select {}
|
||||
}
|
||||
|
||||
func Run() {
|
||||
|
||||
@@ -15,12 +15,13 @@ package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/golang/glog"
|
||||
"github.com/jinzhu/gorm"
|
||||
|
||||
"log"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/logs"
|
||||
"kubesphere.io/kubesphere/pkg/options"
|
||||
)
|
||||
@@ -30,24 +31,6 @@ var dbClient *gorm.DB
|
||||
const database = "kubesphere"
|
||||
|
||||
func NewDBClient() *gorm.DB {
|
||||
user := options.ServerOptions.GetMysqlUser()
|
||||
passwd := options.ServerOptions.GetMysqlPassword()
|
||||
addr := options.ServerOptions.GetMysqlAddr()
|
||||
conn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", user, passwd, addr, database)
|
||||
|
||||
db, err := gorm.Open("mysql", conn)
|
||||
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
db.SetLogger(log.New(logs.GlogWriter{}, " ", 0))
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
func NewSharedDBClient() *gorm.DB {
|
||||
|
||||
if dbClient != nil {
|
||||
err := dbClient.DB().Ping()
|
||||
@@ -59,5 +42,23 @@ func NewSharedDBClient() *gorm.DB {
|
||||
}
|
||||
}
|
||||
|
||||
return NewDBClient()
|
||||
user := options.ServerOptions.GetMysqlUser()
|
||||
passwd := options.ServerOptions.GetMysqlPassword()
|
||||
addr := options.ServerOptions.GetMysqlAddr()
|
||||
if dbClient == nil {
|
||||
conn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", user, passwd, addr, database)
|
||||
glog.Info(conn)
|
||||
db, err := gorm.Open("mysql", conn)
|
||||
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
db.SetLogger(log.New(logs.GlogWriter{}, " ", 0))
|
||||
dbClient = db
|
||||
return dbClient
|
||||
}
|
||||
|
||||
return dbClient
|
||||
}
|
||||
|
||||
@@ -1,198 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package client
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"os"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultScheme = "http"
|
||||
DefaultPrometheusPort = "9090"
|
||||
PrometheusApiPath = "/api/v1/"
|
||||
DefaultQueryStep = "10m"
|
||||
DefaultQueryTimeout = "10s"
|
||||
RangeQueryType = "query_range?"
|
||||
DefaultQueryType = "query?"
|
||||
PrometheusAPIServerEnv = "PROMETHEUS_API_SERVER"
|
||||
)
|
||||
|
||||
var PrometheusAPIServer = "prometheus-k8s.kubesphere-monitoring-system.svc"
|
||||
var PrometheusEndpointUrl string
|
||||
|
||||
func init() {
|
||||
if env := os.Getenv(PrometheusAPIServerEnv); env != "" {
|
||||
PrometheusAPIServer = env
|
||||
}
|
||||
PrometheusEndpointUrl = DefaultScheme + "://" + PrometheusAPIServer + ":" + DefaultPrometheusPort + PrometheusApiPath
|
||||
}
|
||||
|
||||
type MonitoringRequestParams struct {
|
||||
Params url.Values
|
||||
QueryType string
|
||||
SortMetricName string
|
||||
SortType string
|
||||
PageNum string
|
||||
LimitNum string
|
||||
Tp string
|
||||
MetricsFilter string
|
||||
NodesFilter string
|
||||
WsFilter string
|
||||
NsFilter string
|
||||
PodsFilter string
|
||||
ContainersFilter string
|
||||
MetricsName string
|
||||
WorkloadName string
|
||||
WlFilter string
|
||||
NodeId string
|
||||
WsName string
|
||||
NsName string
|
||||
PodName string
|
||||
ContainerName string
|
||||
WorkloadKind string
|
||||
}
|
||||
|
||||
var client = &http.Client{}
|
||||
|
||||
func SendMonitoringRequest(queryType string, params string) string {
|
||||
epurl := PrometheusEndpointUrl + queryType + params
|
||||
response, err := client.Get(epurl)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
defer response.Body.Close()
|
||||
|
||||
contents, err := ioutil.ReadAll(response.Body)
|
||||
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
return string(contents)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func ParseMonitoringRequestParams(request *restful.Request) *MonitoringRequestParams {
|
||||
instantTime := strings.Trim(request.QueryParameter("time"), " ")
|
||||
start := strings.Trim(request.QueryParameter("start"), " ")
|
||||
end := strings.Trim(request.QueryParameter("end"), " ")
|
||||
step := strings.Trim(request.QueryParameter("step"), " ")
|
||||
timeout := strings.Trim(request.QueryParameter("timeout"), " ")
|
||||
|
||||
sortMetricName := strings.Trim(request.QueryParameter("sort_metric"), " ")
|
||||
sortType := strings.Trim(request.QueryParameter("sort_type"), " ")
|
||||
pageNum := strings.Trim(request.QueryParameter("page"), " ")
|
||||
limitNum := strings.Trim(request.QueryParameter("limit"), " ")
|
||||
tp := strings.Trim(request.QueryParameter("type"), " ")
|
||||
|
||||
metricsFilter := strings.Trim(request.QueryParameter("metrics_filter"), " ")
|
||||
nodesFilter := strings.Trim(request.QueryParameter("nodes_filter"), " ")
|
||||
wsFilter := strings.Trim(request.QueryParameter("workspaces_filter"), " ")
|
||||
nsFilter := strings.Trim(request.QueryParameter("namespaces_filter"), " ")
|
||||
wlFilter := strings.Trim(request.QueryParameter("workloads_filter"), " ")
|
||||
podsFilter := strings.Trim(request.QueryParameter("pods_filter"), " ")
|
||||
containersFilter := strings.Trim(request.QueryParameter("containers_filter"), " ")
|
||||
|
||||
metricsName := strings.Trim(request.QueryParameter("metrics_name"), " ")
|
||||
workloadName := strings.Trim(request.QueryParameter("workload_name"), " ")
|
||||
|
||||
nodeId := strings.Trim(request.PathParameter("node_id"), " ")
|
||||
wsName := strings.Trim(request.PathParameter("workspace_name"), " ")
|
||||
nsName := strings.Trim(request.PathParameter("ns_name"), " ")
|
||||
podName := strings.Trim(request.PathParameter("pod_name"), " ")
|
||||
containerName := strings.Trim(request.PathParameter("container_name"), " ")
|
||||
workloadKind := strings.Trim(request.PathParameter("workload_kind"), " ")
|
||||
|
||||
var requestParams = MonitoringRequestParams{
|
||||
SortMetricName: sortMetricName,
|
||||
SortType: sortType,
|
||||
PageNum: pageNum,
|
||||
LimitNum: limitNum,
|
||||
Tp: tp,
|
||||
MetricsFilter: metricsFilter,
|
||||
NodesFilter: nodesFilter,
|
||||
WsFilter: wsFilter,
|
||||
NsFilter: nsFilter,
|
||||
PodsFilter: podsFilter,
|
||||
ContainersFilter: containersFilter,
|
||||
MetricsName: metricsName,
|
||||
WorkloadName: workloadName,
|
||||
WlFilter: wlFilter,
|
||||
NodeId: nodeId,
|
||||
WsName: wsName,
|
||||
NsName: nsName,
|
||||
PodName: podName,
|
||||
ContainerName: containerName,
|
||||
WorkloadKind: workloadKind,
|
||||
}
|
||||
|
||||
if timeout == "" {
|
||||
timeout = DefaultQueryTimeout
|
||||
}
|
||||
if step == "" {
|
||||
step = DefaultQueryStep
|
||||
}
|
||||
// Whether query or query_range request
|
||||
u := url.Values{}
|
||||
|
||||
if start != "" && end != "" {
|
||||
u.Set("start", convertTimeGranularity(start))
|
||||
u.Set("end", convertTimeGranularity(end))
|
||||
u.Set("step", step)
|
||||
u.Set("timeout", timeout)
|
||||
requestParams.QueryType = RangeQueryType
|
||||
requestParams.Params = u
|
||||
return &requestParams
|
||||
}
|
||||
if instantTime != "" {
|
||||
u.Set("time", instantTime)
|
||||
u.Set("timeout", timeout)
|
||||
requestParams.QueryType = DefaultQueryType
|
||||
requestParams.Params = u
|
||||
return &requestParams
|
||||
} else {
|
||||
//u.Set("time", strconv.FormatInt(int64(time.Now().Unix()), 10))
|
||||
u.Set("timeout", timeout)
|
||||
requestParams.QueryType = DefaultQueryType
|
||||
requestParams.Params = u
|
||||
return &requestParams
|
||||
}
|
||||
|
||||
glog.Errorln("Parse request %s failed", u)
|
||||
requestParams.QueryType = DefaultQueryType
|
||||
requestParams.Params = u
|
||||
|
||||
return &requestParams
|
||||
}
|
||||
|
||||
func convertTimeGranularity(ts string) string {
|
||||
timeFloat, err := strconv.ParseFloat(ts, 64)
|
||||
if err != nil {
|
||||
glog.Errorf("convert second timestamp %s to minute timestamp failed", ts)
|
||||
return strconv.FormatInt(int64(time.Now().Unix()), 10)
|
||||
}
|
||||
timeInt := int64(timeFloat)
|
||||
// convert second timestamp to minute timestamp
|
||||
secondTime := time.Unix(timeInt, 0).Truncate(time.Minute).Unix()
|
||||
return strconv.FormatInt(secondTime, 10)
|
||||
}
|
||||
@@ -16,8 +16,6 @@ limitations under the License.
|
||||
|
||||
package constants
|
||||
|
||||
import "os"
|
||||
|
||||
type MessageResponse struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
@@ -40,38 +38,4 @@ const (
|
||||
DataHome = "/etc/kubesphere"
|
||||
IngressControllerFolder = DataHome + "/ingress-controller"
|
||||
IngressControllerPrefix = "kubesphere-router-"
|
||||
DevopsAPIServerEnv = "DEVOPS_API_SERVER"
|
||||
AccountAPIServerEnv = "ACCOUNT_API_SERVER"
|
||||
DevopsProxyTokenEnv = "DEVOPS_PROXY_TOKEN"
|
||||
OpenPitrixProxyTokenEnv = "OPENPITRIX_PROXY_TOKEN"
|
||||
WorkspaceLabelKey = "kubesphere.io/workspace"
|
||||
WorkspaceAdmin = "workspace-admin"
|
||||
ClusterAdmin = "cluster-admin"
|
||||
WorkspaceRegular = "workspace-regular"
|
||||
WorkspaceViewer = "workspace-viewer"
|
||||
DevopsOwner = "owner"
|
||||
DevopsReporter = "reporter"
|
||||
)
|
||||
|
||||
var (
|
||||
DevopsAPIServer = "ks-devops-apiserver.kubesphere-system.svc"
|
||||
AccountAPIServer = "ks-account.kubesphere-system.svc"
|
||||
DevopsProxyToken = ""
|
||||
OpenPitrixProxyToken = ""
|
||||
WorkSpaceRoles = []string{WorkspaceAdmin, WorkspaceRegular, WorkspaceViewer}
|
||||
)
|
||||
|
||||
func init() {
|
||||
if env := os.Getenv(DevopsAPIServerEnv); env != "" {
|
||||
DevopsAPIServer = env
|
||||
}
|
||||
if env := os.Getenv(AccountAPIServerEnv); env != "" {
|
||||
AccountAPIServer = env
|
||||
}
|
||||
if env := os.Getenv(DevopsProxyTokenEnv); env != "" {
|
||||
DevopsProxyToken = env
|
||||
}
|
||||
if env := os.Getenv(OpenPitrixProxyTokenEnv); env != "" {
|
||||
OpenPitrixProxyToken = env
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package container
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/golang/glog"
|
||||
@@ -26,16 +25,14 @@ import (
|
||||
|
||||
func logFilter() restful.FilterFunction {
|
||||
return func(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
|
||||
start := time.Now()
|
||||
chain.ProcessFilter(req, resp)
|
||||
glog.Infof("%s - \"%s %s %s\" %d %d in %dms",
|
||||
glog.Infof("%s - \"%s %s %s\" %d %d",
|
||||
strings.Split(req.Request.RemoteAddr, ":")[0],
|
||||
req.Request.Method,
|
||||
req.Request.URL.RequestURI(),
|
||||
req.Request.Proto,
|
||||
resp.StatusCode(),
|
||||
resp.ContentLength(),
|
||||
time.Since(start)/time.Millisecond,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,226 +19,150 @@ package models
|
||||
import (
|
||||
"time"
|
||||
|
||||
v13 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"github.com/golang/glog"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
|
||||
v12 "k8s.io/client-go/listers/core/v1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/models/controllers"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
)
|
||||
|
||||
// Namespaces need to watch
|
||||
var SYSTEM_NAMESPACES = [...]string{"kubesphere-system", "openpitrix-system", "kube-system"}
|
||||
|
||||
type Component struct {
|
||||
Name string `json:"name"`
|
||||
Namespace string `json:"namespace"`
|
||||
SelfLink string `json:"selfLink"`
|
||||
Label interface{} `json:"label"`
|
||||
StartedAt time.Time `json:"startedAt"`
|
||||
TotalBackends int `json:"totalBackends"`
|
||||
HealthyBackends int `json:"healthyBackends"`
|
||||
type ComponentsCount struct {
|
||||
KubernetesCount int `json:"kubernetesCount"`
|
||||
OpenpitrixCount int `json:"openpitrixCount"`
|
||||
KubesphereCount int `json:"kubesphereCount"`
|
||||
}
|
||||
|
||||
func GetComponentStatus(namespace string, componentName string) (interface{}, error) {
|
||||
lister, err := controllers.GetLister(controllers.Services)
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serviceLister := lister.(v12.ServiceLister)
|
||||
service, err := serviceLister.Services(namespace).Get(componentName)
|
||||
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lister, err = controllers.GetLister(controllers.Pods)
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
podLister := lister.(v12.PodLister)
|
||||
|
||||
set := labels.Set(service.Spec.Selector)
|
||||
|
||||
pods, err := podLister.Pods(namespace).List(set.AsSelector())
|
||||
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
return nil, err
|
||||
} else {
|
||||
component := Component{
|
||||
Name: service.Name,
|
||||
Namespace: service.Namespace,
|
||||
SelfLink: service.SelfLink,
|
||||
Label: service.Spec.Selector,
|
||||
StartedAt: service.CreationTimestamp.Time,
|
||||
HealthyBackends: 0,
|
||||
TotalBackends: 0,
|
||||
}
|
||||
|
||||
for _, v := range pods {
|
||||
component.TotalBackends++
|
||||
component.HealthyBackends++
|
||||
for _, c := range v.Status.ContainerStatuses {
|
||||
if !c.Ready {
|
||||
component.HealthyBackends--
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return component, nil
|
||||
}
|
||||
|
||||
type Components struct {
|
||||
Name string `json:"name"`
|
||||
Namespace string `json:"namespace"`
|
||||
SelfLink string `json:"selfLink"`
|
||||
Label interface{} `json:"label"`
|
||||
HealthStatus string `json:"healthStatus"`
|
||||
CreateTime time.Time `json:"createTime"`
|
||||
}
|
||||
|
||||
func GetSystemHealthStatus() (map[string]interface{}, error) {
|
||||
|
||||
status := make(map[string]interface{})
|
||||
/***
|
||||
* get all components from k8s and kubesphere system
|
||||
*
|
||||
*/
|
||||
func GetComponents() (map[string]interface{}, error) {
|
||||
|
||||
result := make(map[string]interface{})
|
||||
componentsList := make([]Components, 0)
|
||||
k8sClient := client.NewK8sClient()
|
||||
var count ComponentsCount
|
||||
var components Components
|
||||
|
||||
csList, err := k8sClient.Core().ComponentStatuses().List(v1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
label := ""
|
||||
namespaces := []string{constants.KubeSystemNamespace, constants.OpenPitrixNamespace, constants.KubeSphereNamespace}
|
||||
for _, ns := range namespaces {
|
||||
|
||||
for _, cs := range csList.Items {
|
||||
status[cs.Name] = cs.Conditions[0]
|
||||
}
|
||||
|
||||
// get kubesphere-system components
|
||||
|
||||
systemComponentStatus, err := GetAllComponentsStatus()
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
}
|
||||
|
||||
for k, v := range systemComponentStatus {
|
||||
status[k] = v
|
||||
}
|
||||
// get node status
|
||||
|
||||
lister, err := controllers.GetLister(controllers.Nodes)
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
return status, nil
|
||||
}
|
||||
|
||||
nodeLister := lister.(v12.NodeLister)
|
||||
|
||||
nodes, err := nodeLister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
return status, nil
|
||||
}
|
||||
|
||||
nodeStatus := make(map[string]int)
|
||||
totalNodes := 0
|
||||
healthyNodes := 0
|
||||
for _, nodes := range nodes {
|
||||
totalNodes++
|
||||
for _, condition := range nodes.Status.Conditions {
|
||||
if condition.Type == v13.NodeReady && condition.Status == v13.ConditionTrue {
|
||||
healthyNodes++
|
||||
}
|
||||
if ns == constants.KubeSystemNamespace {
|
||||
label = "kubernetes.io/cluster-service=true"
|
||||
} else if ns == constants.OpenPitrixNamespace {
|
||||
label = "app=openpitrix"
|
||||
} else {
|
||||
label = "app=kubesphere"
|
||||
}
|
||||
}
|
||||
nodeStatus["totalNodes"] = totalNodes
|
||||
nodeStatus["healthyNodes"] = healthyNodes
|
||||
option := meta_v1.ListOptions{
|
||||
|
||||
status["nodes"] = nodeStatus
|
||||
LabelSelector: label,
|
||||
}
|
||||
servicelists, err := k8sClient.CoreV1().Services(ns).List(option)
|
||||
|
||||
return status, nil
|
||||
|
||||
}
|
||||
|
||||
func GetAllComponentsStatus() (map[string]interface{}, error) {
|
||||
|
||||
status := make(map[string]interface{})
|
||||
var err error
|
||||
|
||||
lister, err := controllers.GetLister(controllers.Services)
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serviceLister := lister.(v12.ServiceLister)
|
||||
|
||||
lister, err = controllers.GetLister(controllers.Pods)
|
||||
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
podLister := lister.(v12.PodLister)
|
||||
|
||||
for _, ns := range SYSTEM_NAMESPACES {
|
||||
|
||||
nsStatus := make(map[string]interface{})
|
||||
|
||||
services, err := serviceLister.Services(ns).List(labels.Everything())
|
||||
if err != nil {
|
||||
|
||||
glog.Error(err)
|
||||
continue
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
for _, service := range services {
|
||||
if len(servicelists.Items) > 0 {
|
||||
|
||||
set := labels.Set(service.Spec.Selector)
|
||||
for _, service := range servicelists.Items {
|
||||
|
||||
if len(set) == 0 {
|
||||
continue
|
||||
}
|
||||
switch ns {
|
||||
|
||||
component := Component{
|
||||
Name: service.Name,
|
||||
Namespace: service.Namespace,
|
||||
SelfLink: service.SelfLink,
|
||||
Label: service.Spec.Selector,
|
||||
StartedAt: service.CreationTimestamp.Time,
|
||||
HealthyBackends: 0,
|
||||
TotalBackends: 0,
|
||||
}
|
||||
|
||||
pods, err := podLister.Pods(ns).List(set.AsSelector())
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, pod := range pods {
|
||||
component.TotalBackends++
|
||||
component.HealthyBackends++
|
||||
for _, c := range pod.Status.ContainerStatuses {
|
||||
if !c.Ready {
|
||||
component.HealthyBackends--
|
||||
break
|
||||
}
|
||||
case constants.KubeSystemNamespace:
|
||||
count.KubernetesCount++
|
||||
case constants.OpenPitrixNamespace:
|
||||
count.OpenpitrixCount++
|
||||
default:
|
||||
count.KubesphereCount++
|
||||
}
|
||||
|
||||
components.Name = service.Name
|
||||
components.Namespace = service.Namespace
|
||||
components.CreateTime = service.CreationTimestamp.Time
|
||||
components.Label = service.Spec.Selector
|
||||
components.SelfLink = service.SelfLink
|
||||
label := service.Spec.Selector
|
||||
combination := ""
|
||||
for key, val := range label {
|
||||
|
||||
labelstr := key + "=" + val
|
||||
|
||||
if combination == "" {
|
||||
|
||||
combination = labelstr
|
||||
|
||||
} else {
|
||||
|
||||
combination = combination + "," + labelstr
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
option := meta_v1.ListOptions{
|
||||
LabelSelector: combination,
|
||||
}
|
||||
podsList, err := k8sClient.CoreV1().Pods(ns).List(option)
|
||||
|
||||
if err != nil {
|
||||
|
||||
glog.Error(err)
|
||||
return result, err
|
||||
}
|
||||
|
||||
if len(podsList.Items) > 0 {
|
||||
var health bool
|
||||
for _, pod := range podsList.Items {
|
||||
|
||||
for _, status := range pod.Status.ContainerStatuses {
|
||||
|
||||
if status.Ready == false {
|
||||
health = status.Ready
|
||||
break
|
||||
} else {
|
||||
health = status.Ready
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if health == false {
|
||||
components.HealthStatus = "unhealth"
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if health == true {
|
||||
components.HealthStatus = "health"
|
||||
}
|
||||
|
||||
} else {
|
||||
components.HealthStatus = "unhealth"
|
||||
}
|
||||
|
||||
componentsList = append(componentsList, components)
|
||||
|
||||
}
|
||||
|
||||
nsStatus[service.Name] = component
|
||||
}
|
||||
|
||||
if len(nsStatus) > 0 {
|
||||
status[ns] = nsStatus
|
||||
}
|
||||
}
|
||||
result["count"] = count
|
||||
result["item"] = componentsList
|
||||
return result, nil
|
||||
|
||||
return status, err
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ func (ctl *ApplicationCtl) GetWorkLoads(namespace string, clusterRoles []cluster
|
||||
if strings.HasSuffix(workLoadName, deploySurffix) {
|
||||
name := strings.Split(workLoadName, deploySurffix)[0]
|
||||
ctl := ResourceControllers.Controllers[Deployments]
|
||||
_, items, _ := ctl.ListWithConditions(fmt.Sprintf("namespace='%s' and name = '%s'", namespace, name), nil, "")
|
||||
_, items, _ := ctl.ListWithConditions(fmt.Sprintf("namespace='%s' and name = '%s'", namespace, name), nil)
|
||||
works.Deployments = append(works.Deployments, items.([]Deployment)...)
|
||||
continue
|
||||
}
|
||||
@@ -248,7 +248,7 @@ func (ctl *ApplicationCtl) GetWorkLoads(namespace string, clusterRoles []cluster
|
||||
if strings.HasSuffix(workLoadName, daemonSurffix) {
|
||||
name := strings.Split(workLoadName, daemonSurffix)[0]
|
||||
ctl := ResourceControllers.Controllers[Daemonsets]
|
||||
_, items, _ := ctl.ListWithConditions(fmt.Sprintf("namespace='%s' and name = '%s'", namespace, name), nil, "")
|
||||
_, items, _ := ctl.ListWithConditions(fmt.Sprintf("namespace='%s' and name = '%s'", namespace, name), nil)
|
||||
works.Daemonsets = append(works.Daemonsets, items.([]Daemonset)...)
|
||||
continue
|
||||
}
|
||||
@@ -256,7 +256,7 @@ func (ctl *ApplicationCtl) GetWorkLoads(namespace string, clusterRoles []cluster
|
||||
if strings.HasSuffix(workLoadName, stateSurffix) {
|
||||
name := strings.Split(workLoadName, stateSurffix)[0]
|
||||
ctl := ResourceControllers.Controllers[Statefulsets]
|
||||
_, items, _ := ctl.ListWithConditions(fmt.Sprintf("namespace='%s' and name = '%s'", namespace, name), nil, "")
|
||||
_, items, _ := ctl.ListWithConditions(fmt.Sprintf("namespace='%s' and name = '%s'", namespace, name), nil)
|
||||
works.Statefulsets = append(works.Statefulsets, items.([]Statefulset)...)
|
||||
continue
|
||||
}
|
||||
@@ -265,6 +265,16 @@ func (ctl *ApplicationCtl) GetWorkLoads(namespace string, clusterRoles []cluster
|
||||
return &works
|
||||
}
|
||||
|
||||
//
|
||||
//func (ctl *ApplicationCtl) getCreator(desc string) string {
|
||||
// var dc description
|
||||
// err := json.Unmarshal([]byte(desc), &dc)
|
||||
// if err != nil {
|
||||
// return unknown
|
||||
// }
|
||||
// return dc.Creator
|
||||
//}
|
||||
|
||||
func (ctl *ApplicationCtl) getLabels(namespace string, workloads *workLoads) *[]map[string]string {
|
||||
k8sClient := client.NewK8sClient()
|
||||
|
||||
@@ -339,7 +349,7 @@ func (ctl *ApplicationCtl) getIng(namespace string, services *[]Service) *[]ing
|
||||
ingCtl := ResourceControllers.Controllers[Ingresses]
|
||||
var ings []ing
|
||||
for _, svc := range *services {
|
||||
_, items, err := ingCtl.ListWithConditions(fmt.Sprintf("namespace = '%s' and rules like '%%%s%%' ", namespace, svc.Name), nil, "")
|
||||
_, items, err := ingCtl.ListWithConditions(fmt.Sprintf("namespace = '%s' and rules like '%%%s%%' ", namespace, svc.Name), nil)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil
|
||||
@@ -427,7 +437,6 @@ func (ctl *ApplicationCtl) ListApplication(runtimeId string, match, fuzzy map[st
|
||||
appInfo, _, appId, _ := ctl.GetAppInfo(item.AppID)
|
||||
app.App = appInfo
|
||||
app.AppId = appId
|
||||
app.Description = item.Description
|
||||
|
||||
apps = append(apps, app)
|
||||
}
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/kubectl"
|
||||
)
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) Name() string {
|
||||
return ctl.CommonAttribute.Name
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) sync(stopChan chan struct{}) {
|
||||
ctl.initListerAndInformer()
|
||||
ctl.informer.Run(stopChan)
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) total() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) handleWorkspaceRoleChange(clusterRole *rbac.ClusterRoleBinding) {
|
||||
if groups := regexp.MustCompile(fmt.Sprintf(`^system:(\S+):(%s)$`, strings.Join(constants.WorkSpaceRoles, "|"))).FindStringSubmatch(clusterRole.Name); len(groups) == 3 {
|
||||
workspace := groups[1]
|
||||
go ctl.restNamespaceRoleBinding(workspace)
|
||||
}
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) restNamespaceRoleBinding(workspace string) {
|
||||
selector := labels.SelectorFromSet(labels.Set{"kubesphere.io/workspace": workspace})
|
||||
namespaces, err := ctl.K8sClient.CoreV1().Namespaces().List(meta_v1.ListOptions{LabelSelector: selector.String()})
|
||||
|
||||
if err != nil {
|
||||
glog.Warning("workspace roles sync failed", workspace, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, namespace := range namespaces.Items {
|
||||
pathJson := fmt.Sprintf(`{"metadata":{"annotations":{"%s":"%s"}}}`, initTimeAnnotateKey, "")
|
||||
_, err := ctl.K8sClient.CoreV1().Namespaces().Patch(namespace.Name, "application/strategic-merge-patch+json", []byte(pathJson))
|
||||
if err != nil {
|
||||
glog.Warning("workspace roles sync failed", workspace, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) initListerAndInformer() {
|
||||
informerFactory := informers.NewSharedInformerFactory(ctl.K8sClient, time.Second*resyncCircle)
|
||||
ctl.lister = informerFactory.Rbac().V1().ClusterRoleBindings().Lister()
|
||||
ctl.informer = informerFactory.Rbac().V1().ClusterRoleBindings().Informer()
|
||||
ctl.informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
clusterRoleBinding := obj.(*rbac.ClusterRoleBinding)
|
||||
ctl.handleTerminalCreate(clusterRoleBinding)
|
||||
},
|
||||
UpdateFunc: func(old, new interface{}) {
|
||||
oldValue := old.(*rbac.ClusterRoleBinding)
|
||||
newValue := new.(*rbac.ClusterRoleBinding)
|
||||
if !subjectsCompile(oldValue.Subjects, newValue.Subjects) {
|
||||
ctl.handleWorkspaceRoleChange(newValue)
|
||||
ctl.handleTerminalUpdate(oldValue, newValue)
|
||||
}
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
clusterRoleBinding := obj.(*rbac.ClusterRoleBinding)
|
||||
ctl.handleTerminalDelete(clusterRoleBinding)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) handleTerminalCreate(clusterRoleBinding *rbac.ClusterRoleBinding) {
|
||||
if clusterRoleBinding.RoleRef.Name == constants.ClusterAdmin {
|
||||
for _, subject := range clusterRoleBinding.Subjects {
|
||||
if subject.Kind == rbac.UserKind {
|
||||
err := kubectl.CreateKubectlDeploy(subject.Name)
|
||||
if err != nil {
|
||||
glog.Error(fmt.Sprintf("create %s's terminal pod failed:%s", subject.Name, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
func (ctl *ClusterRoleBindingCtl) handleTerminalUpdate(old *rbac.ClusterRoleBinding, new *rbac.ClusterRoleBinding) {
|
||||
if new.RoleRef.Name == constants.ClusterAdmin {
|
||||
for _, newSubject := range new.Subjects {
|
||||
isAdded := true
|
||||
for _, oldSubject := range old.Subjects {
|
||||
if oldSubject == newSubject {
|
||||
isAdded = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if isAdded && newSubject.Kind == rbac.UserKind {
|
||||
err := kubectl.CreateKubectlDeploy(newSubject.Name)
|
||||
if err != nil {
|
||||
glog.Error(fmt.Sprintf("create %s's terminal pod failed:%s", newSubject.Name, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, oldSubject := range old.Subjects {
|
||||
isDeleted := true
|
||||
for _, newSubject := range new.Subjects {
|
||||
if newSubject == oldSubject {
|
||||
isDeleted = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if isDeleted && oldSubject.Kind == rbac.UserKind {
|
||||
err := kubectl.DelKubectlDeploy(oldSubject.Name)
|
||||
if err != nil {
|
||||
glog.Error(fmt.Sprintf("delete %s's terminal pod failed:%s", oldSubject.Name, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) handleTerminalDelete(clusterRoleBinding *rbac.ClusterRoleBinding) {
|
||||
if clusterRoleBinding.RoleRef.Name == constants.ClusterAdmin {
|
||||
for _, subject := range clusterRoleBinding.Subjects {
|
||||
if subject.Kind == rbac.UserKind {
|
||||
err := kubectl.DelKubectlDeploy(subject.Name)
|
||||
if err != nil {
|
||||
glog.Error(fmt.Sprintf("delete %s's terminal pod failed:%s", subject.Name, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func subjectsCompile(s1 []rbac.Subject, s2 []rbac.Subject) bool {
|
||||
if len(s1) != len(s2) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, v := range s1 {
|
||||
if v.Name != s2[i].Name || v.Kind != s2[i].Kind {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) CountWithConditions(conditions string) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
return 0, nil, errors.New("not implement")
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleBindingCtl) Lister() interface{} {
|
||||
return ctl.lister
|
||||
}
|
||||
@@ -30,13 +30,8 @@ import (
|
||||
const systemPrefix = "system:"
|
||||
|
||||
func (ctl *ClusterRoleCtl) generateObject(item v1.ClusterRole) *ClusterRole {
|
||||
var displayName string
|
||||
if item.Annotations != nil && len(item.Annotations[DisplayName]) > 0 {
|
||||
displayName = item.Annotations[DisplayName]
|
||||
}
|
||||
|
||||
name := item.Name
|
||||
if strings.HasPrefix(name, systemPrefix) || item.Annotations == nil || len(item.Annotations[creator]) == 0 {
|
||||
if strings.HasPrefix(name, systemPrefix) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -45,7 +40,7 @@ func (ctl *ClusterRoleCtl) generateObject(item v1.ClusterRole) *ClusterRole {
|
||||
createTime = time.Now()
|
||||
}
|
||||
|
||||
object := &ClusterRole{Name: name, CreateTime: createTime, Annotation: MapString{item.Annotations}, DisplayName: displayName}
|
||||
object := &ClusterRole{Name: name, CreateTime: createTime, Annotation: Annotation{item.Annotations}}
|
||||
|
||||
return object
|
||||
}
|
||||
@@ -74,9 +69,7 @@ func (ctl *ClusterRoleCtl) sync(stopChan chan struct{}) {
|
||||
for _, item := range list {
|
||||
obj := ctl.generateObject(*item)
|
||||
if obj != nil {
|
||||
if err := db.Create(obj).Error; err != nil {
|
||||
glog.Error("cluster roles sync error", err)
|
||||
}
|
||||
db.Create(obj)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,13 +79,13 @@ func (ctl *ClusterRoleCtl) sync(stopChan chan struct{}) {
|
||||
func (ctl *ClusterRoleCtl) total() int {
|
||||
list, err := ctl.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Errorf("count %s failed, reason:%s", err, ctl.Name())
|
||||
glog.Errorf("count %s falied, reason:%s", err, ctl.Name())
|
||||
return 0
|
||||
}
|
||||
|
||||
count := 0
|
||||
for _, item := range list {
|
||||
if !strings.HasPrefix(item.Name, systemPrefix) && item.Annotations != nil && len(item.Annotations[creator]) > 0 {
|
||||
if !strings.HasPrefix(item.Name, systemPrefix) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
@@ -113,27 +106,22 @@ func (ctl *ClusterRoleCtl) initListerAndInformer() {
|
||||
object := obj.(*v1.ClusterRole)
|
||||
mysqlObject := ctl.generateObject(*object)
|
||||
if mysqlObject != nil {
|
||||
if err := db.Create(mysqlObject).Error; err != nil {
|
||||
glog.Error("cluster roles sync error", err)
|
||||
}
|
||||
db.Create(mysqlObject)
|
||||
}
|
||||
},
|
||||
UpdateFunc: func(old, new interface{}) {
|
||||
object := new.(*v1.ClusterRole)
|
||||
mysqlObject := ctl.generateObject(*object)
|
||||
if mysqlObject != nil {
|
||||
if err := db.Save(mysqlObject).Error; err != nil {
|
||||
glog.Error("cluster roles update error", err)
|
||||
}
|
||||
db.Save(mysqlObject)
|
||||
}
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
|
||||
var item ClusterRole
|
||||
object := obj.(*v1.ClusterRole)
|
||||
db.Where("name=?", object.Name).Find(&item)
|
||||
db.Delete(item)
|
||||
|
||||
if err := db.Delete(ClusterRole{}, "name=?", object.Name).Error; err != nil {
|
||||
glog.Error("cluster roles delete error", err)
|
||||
}
|
||||
},
|
||||
})
|
||||
ctl.informer = informer
|
||||
@@ -148,23 +136,15 @@ func (ctl *ClusterRoleCtl) CountWithConditions(conditions string) int {
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
func (ctl *ClusterRoleCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var object ClusterRole
|
||||
var list []ClusterRole
|
||||
var total int
|
||||
|
||||
if len(order) == 0 {
|
||||
order = "createTime desc"
|
||||
}
|
||||
|
||||
order := "createTime desc"
|
||||
db := ctl.DB
|
||||
|
||||
listWithConditions(db, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
|
||||
@@ -23,18 +23,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"sync"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
)
|
||||
|
||||
const (
|
||||
checkPeriod = 30 * time.Minute
|
||||
sleepPeriod = 15 * time.Second
|
||||
)
|
||||
|
||||
func listWithConditions(db *gorm.DB, total *int, object, list interface{}, conditions string, paging *Paging, order string) {
|
||||
@@ -80,8 +71,6 @@ func makeHttpRequest(method, url, data string) ([]byte, error) {
|
||||
req, err = http.NewRequest(method, url, strings.NewReader(data))
|
||||
}
|
||||
|
||||
req.Header.Add("Authorization", constants.OpenPitrixProxyToken)
|
||||
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil, err
|
||||
@@ -125,20 +114,13 @@ func hasSynced(ctl Controller) bool {
|
||||
|
||||
func checkAndResync(ctl Controller, stopChan chan struct{}) {
|
||||
defer close(stopChan)
|
||||
|
||||
lastTime := time.Now()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctl.chanStop():
|
||||
return
|
||||
default:
|
||||
if time.Now().Sub(lastTime) < checkPeriod {
|
||||
time.Sleep(sleepPeriod)
|
||||
break
|
||||
}
|
||||
time.Sleep(30 * time.Minute)
|
||||
|
||||
lastTime = time.Now()
|
||||
if !hasSynced(ctl) {
|
||||
glog.Errorf("the data in db and kubernetes is inconsistent, resync %s controller", ctl.Name())
|
||||
close(stopChan)
|
||||
@@ -149,10 +131,9 @@ func checkAndResync(ctl Controller, stopChan chan struct{}) {
|
||||
}
|
||||
}
|
||||
|
||||
func listAndWatch(ctl Controller, wg *sync.WaitGroup) {
|
||||
func listAndWatch(ctl Controller) {
|
||||
defer handleCrash(ctl)
|
||||
defer ctl.CloseDB()
|
||||
defer wg.Done()
|
||||
|
||||
stopChan := make(chan struct{})
|
||||
|
||||
go ctl.sync(stopChan)
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
func (ctl *ConfigMapCtl) generateObject(item v1.ConfigMap) *ConfigMap {
|
||||
var displayName string
|
||||
if item.Annotations != nil && len(item.Annotations[DisplayName]) > 0 {
|
||||
displayName = item.Annotations[DisplayName]
|
||||
}
|
||||
|
||||
createTime := item.CreationTimestamp.Time
|
||||
if createTime.IsZero() {
|
||||
createTime = time.Now()
|
||||
}
|
||||
|
||||
var entries []string
|
||||
|
||||
for entry := range item.Data {
|
||||
entries = append(entries, entry)
|
||||
}
|
||||
|
||||
object := &ConfigMap{
|
||||
Name: item.Name,
|
||||
Namespace: item.Namespace,
|
||||
CreateTime: createTime,
|
||||
Annotation: MapString{item.Annotations},
|
||||
DisplayName: displayName,
|
||||
Entries: strings.Join(entries, ","),
|
||||
}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (ctl *ConfigMapCtl) Name() string {
|
||||
return ctl.CommonAttribute.Name
|
||||
}
|
||||
|
||||
func (ctl *ConfigMapCtl) sync(stopChan chan struct{}) {
|
||||
db := ctl.DB
|
||||
|
||||
if db.HasTable(&ConfigMap{}) {
|
||||
db.DropTable(&ConfigMap{})
|
||||
}
|
||||
|
||||
db = db.CreateTable(&ConfigMap{})
|
||||
|
||||
ctl.initListerAndInformer()
|
||||
|
||||
list, err := ctl.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range list {
|
||||
obj := ctl.generateObject(*item)
|
||||
if obj != nil {
|
||||
db.Create(obj)
|
||||
}
|
||||
}
|
||||
|
||||
ctl.informer.Run(stopChan)
|
||||
}
|
||||
|
||||
func (ctl *ConfigMapCtl) total() int {
|
||||
list, err := ctl.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Errorf("count %s falied, reason:%s", err, ctl.Name())
|
||||
return 0
|
||||
}
|
||||
|
||||
return len(list)
|
||||
}
|
||||
|
||||
func (ctl *ConfigMapCtl) initListerAndInformer() {
|
||||
db := ctl.DB
|
||||
|
||||
informerFactory := informers.NewSharedInformerFactory(ctl.K8sClient, time.Second*resyncCircle)
|
||||
ctl.lister = informerFactory.Core().V1().ConfigMaps().Lister()
|
||||
|
||||
informer := informerFactory.Core().V1().ConfigMaps().Informer()
|
||||
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
|
||||
object := obj.(*v1.ConfigMap)
|
||||
mysqlObject := ctl.generateObject(*object)
|
||||
if mysqlObject != nil {
|
||||
db.Create(mysqlObject)
|
||||
}
|
||||
},
|
||||
UpdateFunc: func(old, new interface{}) {
|
||||
object := new.(*v1.ConfigMap)
|
||||
mysqlObject := ctl.generateObject(*object)
|
||||
if mysqlObject != nil {
|
||||
db.Save(mysqlObject)
|
||||
}
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
var item ConfigMap
|
||||
object := obj.(*v1.ConfigMap)
|
||||
db.Where("name=?", object.Name).Find(&item)
|
||||
db.Delete(item)
|
||||
|
||||
},
|
||||
})
|
||||
ctl.informer = informer
|
||||
}
|
||||
|
||||
func (ctl *ConfigMapCtl) CountWithConditions(conditions string) int {
|
||||
var object ConfigMap
|
||||
|
||||
if strings.Contains(conditions, "namespace") {
|
||||
conditions = ""
|
||||
}
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *ConfigMapCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
var object ConfigMap
|
||||
var list []ConfigMap
|
||||
var total int
|
||||
|
||||
if len(order) == 0 {
|
||||
order = "createTime desc"
|
||||
}
|
||||
|
||||
db := ctl.DB
|
||||
|
||||
listWithConditions(db, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *ConfigMapCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"k8s.io/client-go/informers"
|
||||
)
|
||||
|
||||
func (ctl *ControllerRevisionCtl) Name() string {
|
||||
return ctl.CommonAttribute.Name
|
||||
}
|
||||
|
||||
func (ctl *ControllerRevisionCtl) sync(stopChan chan struct{}) {
|
||||
|
||||
ctl.initListerAndInformer()
|
||||
ctl.informer.Run(stopChan)
|
||||
}
|
||||
|
||||
func (ctl *ControllerRevisionCtl) total() int {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (ctl *ControllerRevisionCtl) initListerAndInformer() {
|
||||
|
||||
informerFactory := informers.NewSharedInformerFactory(ctl.K8sClient, time.Second*resyncCircle)
|
||||
|
||||
ctl.lister = informerFactory.Apps().V1().ControllerRevisions().Lister()
|
||||
|
||||
informer := informerFactory.Apps().V1().ControllerRevisions().Informer()
|
||||
|
||||
ctl.informer = informer
|
||||
}
|
||||
|
||||
func (ctl *ControllerRevisionCtl) CountWithConditions(conditions string) int {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (ctl *ControllerRevisionCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
|
||||
return 0, nil, nil
|
||||
}
|
||||
|
||||
func (ctl *ControllerRevisionCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/batch/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
func (ctl *CronJobCtl) generateObject(item v1beta1.CronJob) *CronJob {
|
||||
var status, displayName string
|
||||
var lastScheduleTime *time.Time
|
||||
|
||||
if item.Annotations != nil && len(item.Annotations[DisplayName]) > 0 {
|
||||
displayName = item.Annotations[DisplayName]
|
||||
}
|
||||
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
|
||||
status = Running
|
||||
if *item.Spec.Suspend {
|
||||
status = Pause
|
||||
}
|
||||
|
||||
schedule := item.Spec.Schedule
|
||||
if item.Status.LastScheduleTime != nil {
|
||||
lastScheduleTime = &item.Status.LastScheduleTime.Time
|
||||
}
|
||||
|
||||
active := len(item.Status.Active)
|
||||
|
||||
object := &CronJob{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
DisplayName: displayName,
|
||||
LastScheduleTime: lastScheduleTime,
|
||||
Active: active,
|
||||
Schedule: schedule,
|
||||
Status: status,
|
||||
Annotation: MapString{item.Annotations},
|
||||
Labels: MapString{item.ObjectMeta.Labels},
|
||||
}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (ctl *CronJobCtl) Name() string {
|
||||
return ctl.CommonAttribute.Name
|
||||
}
|
||||
|
||||
func (ctl *CronJobCtl) sync(stopChan chan struct{}) {
|
||||
db := ctl.DB
|
||||
|
||||
if db.HasTable(&CronJob{}) {
|
||||
db.DropTable(&CronJob{})
|
||||
}
|
||||
|
||||
db = db.CreateTable(&CronJob{})
|
||||
|
||||
ctl.initListerAndInformer()
|
||||
list, err := ctl.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range list {
|
||||
obj := ctl.generateObject(*item)
|
||||
db.Create(obj)
|
||||
}
|
||||
|
||||
ctl.informer.Run(stopChan)
|
||||
}
|
||||
|
||||
func (ctl *CronJobCtl) total() int {
|
||||
list, err := ctl.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Errorf("count %s falied, reason:%s", err, ctl.Name())
|
||||
return 0
|
||||
}
|
||||
return len(list)
|
||||
}
|
||||
|
||||
func (ctl *CronJobCtl) initListerAndInformer() {
|
||||
db := ctl.DB
|
||||
|
||||
informerFactory := informers.NewSharedInformerFactory(ctl.K8sClient, time.Second*resyncCircle)
|
||||
ctl.lister = informerFactory.Batch().V1beta1().CronJobs().Lister()
|
||||
|
||||
informer := informerFactory.Batch().V1beta1().CronJobs().Informer()
|
||||
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
|
||||
object := obj.(*v1beta1.CronJob)
|
||||
mysqlObject := ctl.generateObject(*object)
|
||||
db.Create(mysqlObject)
|
||||
},
|
||||
UpdateFunc: func(old, new interface{}) {
|
||||
object := new.(*v1beta1.CronJob)
|
||||
mysqlObject := ctl.generateObject(*object)
|
||||
db.Save(mysqlObject)
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
var item CronJob
|
||||
object := obj.(*v1beta1.CronJob)
|
||||
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&item)
|
||||
db.Delete(item)
|
||||
|
||||
},
|
||||
})
|
||||
|
||||
ctl.informer = informer
|
||||
}
|
||||
|
||||
func (ctl *CronJobCtl) CountWithConditions(conditions string) int {
|
||||
var object CronJob
|
||||
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *CronJobCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
var list []CronJob
|
||||
var object CronJob
|
||||
var total int
|
||||
|
||||
if len(order) == 0 {
|
||||
order = "lastScheduleTime desc"
|
||||
}
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *CronJobCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
@@ -28,11 +28,8 @@ import (
|
||||
)
|
||||
|
||||
func (ctl *DaemonsetCtl) generateObject(item v1.DaemonSet) *Daemonset {
|
||||
var app, status, displayName string
|
||||
|
||||
if item.Annotations != nil && len(item.Annotations[DisplayName]) > 0 {
|
||||
displayName = item.Annotations[DisplayName]
|
||||
}
|
||||
var app string
|
||||
var status string
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
availablePodNum := item.Status.NumberAvailable
|
||||
@@ -58,19 +55,8 @@ func (ctl *DaemonsetCtl) generateObject(item v1.DaemonSet) *Daemonset {
|
||||
status = Updating
|
||||
}
|
||||
|
||||
object := &Daemonset{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
DisplayName: displayName,
|
||||
Available: availablePodNum,
|
||||
Desire: desirePodNum,
|
||||
App: app,
|
||||
CreateTime: createTime,
|
||||
Status: status,
|
||||
NodeSelector: string(nodeSelectorStr),
|
||||
Annotation: MapString{item.Annotations},
|
||||
Labels: MapString{item.Spec.Selector.MatchLabels},
|
||||
}
|
||||
object := &Daemonset{Namespace: namespace, Name: name, Available: availablePodNum, Desire: desirePodNum,
|
||||
App: app, CreateTime: createTime, Status: status, NodeSelector: string(nodeSelectorStr), Annotation: Annotation{item.Annotations}}
|
||||
|
||||
return object
|
||||
}
|
||||
@@ -149,21 +135,25 @@ func (ctl *DaemonsetCtl) CountWithConditions(conditions string) int {
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *DaemonsetCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
func (ctl *DaemonsetCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Daemonset
|
||||
var object Daemonset
|
||||
var total int
|
||||
|
||||
if len(order) == 0 {
|
||||
order = "createTime desc"
|
||||
}
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *DaemonsetCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
//func (ctl *DaemonsetCtl) Count(namespace string) int {
|
||||
// var count int
|
||||
// db := ctl.DB
|
||||
// if len(namespace) == 0 {
|
||||
// db.Model(&Daemonset{}).Count(&count)
|
||||
// } else {
|
||||
// db.Model(&Daemonset{}).Where("namespace = ?", namespace).Count(&count)
|
||||
// }
|
||||
// return count
|
||||
//}
|
||||
|
||||
@@ -27,13 +27,9 @@ import (
|
||||
)
|
||||
|
||||
func (ctl *DeploymentCtl) generateObject(item v1.Deployment) *Deployment {
|
||||
var app, status, displayName string
|
||||
var app string
|
||||
var status string
|
||||
var updateTime time.Time
|
||||
|
||||
if item.Annotations != nil && len(item.Annotations[DisplayName]) > 0 {
|
||||
displayName = item.Annotations[DisplayName]
|
||||
}
|
||||
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
availablePodNum := item.Status.AvailableReplicas
|
||||
@@ -45,13 +41,9 @@ func (ctl *DeploymentCtl) generateObject(item v1.Deployment) *Deployment {
|
||||
app = release + "/" + chart
|
||||
}
|
||||
|
||||
for _, condition := range item.Status.Conditions {
|
||||
if updateTime.IsZero() {
|
||||
updateTime = condition.LastUpdateTime.Time
|
||||
} else {
|
||||
if updateTime.Before(condition.LastUpdateTime.Time) {
|
||||
updateTime = condition.LastUpdateTime.Time
|
||||
}
|
||||
for _, conditon := range item.Status.Conditions {
|
||||
if conditon.Type == "Available" {
|
||||
updateTime = conditon.LastUpdateTime.Time
|
||||
}
|
||||
}
|
||||
if updateTime.IsZero() {
|
||||
@@ -68,18 +60,8 @@ func (ctl *DeploymentCtl) generateObject(item v1.Deployment) *Deployment {
|
||||
}
|
||||
}
|
||||
|
||||
return &Deployment{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
Available: availablePodNum,
|
||||
Desire: desirePodNum,
|
||||
App: app,
|
||||
UpdateTime: updateTime,
|
||||
Status: status,
|
||||
Annotation: MapString{item.Annotations},
|
||||
Labels: MapString{item.Spec.Selector.MatchLabels},
|
||||
DisplayName: displayName,
|
||||
}
|
||||
return &Deployment{Namespace: namespace, Name: name, Available: availablePodNum, Desire: desirePodNum,
|
||||
App: app, UpdateTime: updateTime, Status: status, Annotation: Annotation{item.Annotations}}
|
||||
}
|
||||
|
||||
func (ctl *DeploymentCtl) Name() string {
|
||||
@@ -156,21 +138,14 @@ func (ctl *DeploymentCtl) CountWithConditions(conditions string) int {
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *DeploymentCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
func (ctl *DeploymentCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Deployment
|
||||
var object Deployment
|
||||
var total int
|
||||
|
||||
if len(order) == 0 {
|
||||
order = "updateTime desc"
|
||||
}
|
||||
order := "updateTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *DeploymentCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
|
||||
@@ -30,16 +30,9 @@ import (
|
||||
)
|
||||
|
||||
func (ctl *IngressCtl) generateObject(item v1beta1.Ingress) *Ingress {
|
||||
|
||||
var ip, tls, displayName string
|
||||
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
|
||||
if item.Annotations != nil && len(item.Annotations[DisplayName]) > 0 {
|
||||
displayName = item.Annotations[DisplayName]
|
||||
}
|
||||
|
||||
var ip, tls string
|
||||
createTime := item.CreationTimestamp.Time
|
||||
if createTime.IsZero() {
|
||||
createTime = time.Now()
|
||||
@@ -70,17 +63,7 @@ func (ctl *IngressCtl) generateObject(item v1beta1.Ingress) *Ingress {
|
||||
|
||||
ruleStr, _ := json.Marshal(ingRules)
|
||||
|
||||
object := &Ingress{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
DisplayName: displayName,
|
||||
TlsTermination: tls,
|
||||
Ip: ip,
|
||||
CreateTime: createTime,
|
||||
Annotation: MapString{item.Annotations},
|
||||
Rules: string(ruleStr),
|
||||
Labels: MapString{item.Labels},
|
||||
}
|
||||
object := &Ingress{Namespace: namespace, Name: name, TlsTermination: tls, Ip: ip, CreateTime: createTime, Annotation: Annotation{item.Annotations}, Rules: string(ruleStr)}
|
||||
|
||||
return object
|
||||
}
|
||||
@@ -160,21 +143,25 @@ func (ctl *IngressCtl) CountWithConditions(conditions string) int {
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *IngressCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
func (ctl *IngressCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Ingress
|
||||
var object Ingress
|
||||
var total int
|
||||
|
||||
if len(order) == 0 {
|
||||
order = "createTime desc"
|
||||
}
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *IngressCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
//func (ctl *IngressCtl) Count(namespace string) int {
|
||||
// var count int
|
||||
// db := ctl.DB
|
||||
// if len(namespace) == 0 {
|
||||
// db.Model(&Ingress{}).Count(&count)
|
||||
// } else {
|
||||
// db.Model(&Ingress{}).Where("namespace = ?", namespace).Count(&count)
|
||||
// }
|
||||
// return count
|
||||
//}
|
||||
|
||||
@@ -1,318 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/batch/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
var k8sClient *kubernetes.Clientset
|
||||
|
||||
const retryTimes = 3
|
||||
|
||||
func (ctl *JobCtl) generateObject(item v1.Job) *Job {
|
||||
var status, displayName string
|
||||
|
||||
if item.Annotations != nil && len(item.Annotations[DisplayName]) > 0 {
|
||||
displayName = item.Annotations[DisplayName]
|
||||
}
|
||||
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
succeedPodNum := item.Status.Succeeded
|
||||
desirePodNum := *item.Spec.Completions
|
||||
createTime := item.CreationTimestamp.Time
|
||||
updteTime := createTime
|
||||
for _, condition := range item.Status.Conditions {
|
||||
if condition.Type == "Failed" && condition.Status == "True" {
|
||||
status = Failed
|
||||
}
|
||||
|
||||
if condition.Type == "Complete" && condition.Status == "True" {
|
||||
status = Completed
|
||||
}
|
||||
|
||||
if updteTime.Before(condition.LastProbeTime.Time) {
|
||||
updteTime = condition.LastProbeTime.Time
|
||||
}
|
||||
|
||||
if updteTime.Before(condition.LastTransitionTime.Time) {
|
||||
updteTime = condition.LastTransitionTime.Time
|
||||
}
|
||||
}
|
||||
|
||||
if desirePodNum > succeedPodNum && len(status) == 0 {
|
||||
status = Running
|
||||
}
|
||||
|
||||
object := &Job{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
DisplayName: displayName,
|
||||
Desire: desirePodNum,
|
||||
Completed: succeedPodNum,
|
||||
UpdateTime: updteTime,
|
||||
CreateTime: createTime,
|
||||
Status: status,
|
||||
Annotation: MapString{item.Annotations},
|
||||
Labels: MapString{item.Labels},
|
||||
}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (ctl *JobCtl) Name() string {
|
||||
return ctl.CommonAttribute.Name
|
||||
}
|
||||
|
||||
func (ctl *JobCtl) sync(stopChan chan struct{}) {
|
||||
db := ctl.DB
|
||||
|
||||
if db.HasTable(&Job{}) {
|
||||
db.DropTable(&Job{})
|
||||
}
|
||||
|
||||
db = db.CreateTable(&Job{})
|
||||
|
||||
ctl.initListerAndInformer()
|
||||
list, err := ctl.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range list {
|
||||
obj := ctl.generateObject(*item)
|
||||
db.Create(obj)
|
||||
}
|
||||
|
||||
ctl.informer.Run(stopChan)
|
||||
}
|
||||
|
||||
func (ctl *JobCtl) total() int {
|
||||
list, err := ctl.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Errorf("count %s falied, reason:%s", err, ctl.Name())
|
||||
return 0
|
||||
}
|
||||
return len(list)
|
||||
}
|
||||
|
||||
func (ctl *JobCtl) initListerAndInformer() {
|
||||
db := ctl.DB
|
||||
|
||||
informerFactory := informers.NewSharedInformerFactory(ctl.K8sClient, time.Second*resyncCircle)
|
||||
ctl.lister = informerFactory.Batch().V1().Jobs().Lister()
|
||||
|
||||
informer := informerFactory.Batch().V1().Jobs().Informer()
|
||||
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
|
||||
object := obj.(*v1.Job)
|
||||
mysqlObject := ctl.generateObject(*object)
|
||||
ctl.makeRevision(object)
|
||||
db.Create(mysqlObject)
|
||||
},
|
||||
UpdateFunc: func(old, new interface{}) {
|
||||
object := new.(*v1.Job)
|
||||
mysqlObject := ctl.generateObject(*object)
|
||||
ctl.makeRevision(object)
|
||||
db.Save(mysqlObject)
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
var item Job
|
||||
object := obj.(*v1.Job)
|
||||
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&item)
|
||||
db.Delete(item)
|
||||
|
||||
},
|
||||
})
|
||||
|
||||
ctl.informer = informer
|
||||
}
|
||||
|
||||
func (ctl *JobCtl) CountWithConditions(conditions string) int {
|
||||
var object Job
|
||||
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *JobCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
var list []Job
|
||||
var object Job
|
||||
var total int
|
||||
|
||||
if len(order) == 0 {
|
||||
order = "updateTime desc"
|
||||
}
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *JobCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
|
||||
func getRevisions(job v1.Job) (JobRevisions, error) {
|
||||
revisions := make(JobRevisions)
|
||||
|
||||
if _, exist := job.Annotations["revisions"]; exist {
|
||||
revisionsStr := job.Annotations["revisions"]
|
||||
|
||||
err := json.Unmarshal([]byte(revisionsStr), &revisions)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get job %s's revisions, reason: %s", job.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
return revisions, nil
|
||||
}
|
||||
|
||||
func getCurrentRevision(item *v1.Job) JobRevision {
|
||||
var revision JobRevision
|
||||
for _, condition := range item.Status.Conditions {
|
||||
if condition.Type == "Failed" && condition.Status == "True" {
|
||||
revision.Status = Failed
|
||||
revision.Reasons = append(revision.Reasons, condition.Reason)
|
||||
revision.Messages = append(revision.Messages, condition.Message)
|
||||
}
|
||||
|
||||
if condition.Type == "Complete" && condition.Status == "True" {
|
||||
revision.Status = Completed
|
||||
}
|
||||
}
|
||||
|
||||
if len(revision.Status) == 0 {
|
||||
revision.Status = Running
|
||||
}
|
||||
|
||||
revision.DesirePodNum = *item.Spec.Completions
|
||||
revision.Succeed = item.Status.Succeeded
|
||||
revision.Failed = item.Status.Failed
|
||||
revision.StartTime = item.CreationTimestamp.Time
|
||||
revision.Uid = string(item.UID)
|
||||
if item.Status.CompletionTime != nil {
|
||||
revision.CompletionTime = item.Status.CompletionTime.Time
|
||||
}
|
||||
|
||||
return revision
|
||||
}
|
||||
|
||||
func deleteJob(namespace, job string) error {
|
||||
deletePolicy := metav1.DeletePropagationBackground
|
||||
err := k8sClient.BatchV1().Jobs(namespace).Delete(job, &metav1.DeleteOptions{PropagationPolicy: &deletePolicy})
|
||||
return err
|
||||
}
|
||||
|
||||
func (ctl *JobCtl) makeRevision(job *v1.Job) {
|
||||
revisionIndex := -1
|
||||
revisions, err := getRevisions(*job)
|
||||
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
uid := job.UID
|
||||
for index, revision := range revisions {
|
||||
if revision.Uid == string(uid) {
|
||||
currentRevision := getCurrentRevision(job)
|
||||
if reflect.DeepEqual(currentRevision, revision) {
|
||||
return
|
||||
} else {
|
||||
revisionIndex = index
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if revisionIndex == -1 {
|
||||
revisionIndex = len(revisions) + 1
|
||||
}
|
||||
|
||||
revisions[revisionIndex] = getCurrentRevision(job)
|
||||
|
||||
revisionsByte, err := json.Marshal(revisions)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
|
||||
if job.Annotations == nil {
|
||||
job.Annotations = make(map[string]string)
|
||||
}
|
||||
|
||||
job.Annotations["revisions"] = string(revisionsByte)
|
||||
ctl.K8sClient.BatchV1().Jobs(job.Namespace).Update(job)
|
||||
|
||||
}
|
||||
|
||||
func JobReRun(namespace, jobName string) (string, error) {
|
||||
k8sClient = client.NewK8sClient()
|
||||
job, err := k8sClient.BatchV1().Jobs(namespace).Get(jobName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
newJob := *job
|
||||
newJob.ResourceVersion = ""
|
||||
newJob.Status = v1.JobStatus{}
|
||||
newJob.ObjectMeta.UID = ""
|
||||
newJob.Annotations["revisions"] = strings.Replace(job.Annotations["revisions"], Running, Unfinished, -1)
|
||||
|
||||
delete(newJob.Spec.Selector.MatchLabels, "controller-uid")
|
||||
delete(newJob.Spec.Template.ObjectMeta.Labels, "controller-uid")
|
||||
|
||||
err = deleteJob(namespace, jobName)
|
||||
if err != nil {
|
||||
glog.Errorf("failed to rerun job %s, reason: %s", jobName, err)
|
||||
return "", fmt.Errorf("failed to rerun job %s", jobName)
|
||||
}
|
||||
|
||||
for i := 0; i < retryTimes; i++ {
|
||||
_, err = k8sClient.BatchV1().Jobs(namespace).Create(&newJob)
|
||||
if err != nil {
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
glog.Errorf("failed to rerun job %s, reason: %s", jobName, err)
|
||||
return "", fmt.Errorf("failed to rerun job %s", jobName)
|
||||
}
|
||||
|
||||
return "succeed", nil
|
||||
}
|
||||
@@ -46,19 +46,17 @@ import (
|
||||
const (
|
||||
provider = "kubernetes"
|
||||
admin = "admin"
|
||||
operator = "operator"
|
||||
editor = "editor"
|
||||
viewer = "viewer"
|
||||
kubectlNamespace = constants.KubeSphereControlNamespace
|
||||
kubectlConfigKey = "config"
|
||||
openPitrixRuntimeAnnotateKey = "openpitrix_runtime"
|
||||
creatorAnnotateKey = "creator"
|
||||
initTimeAnnotateKey = "kubesphere.io/init-time"
|
||||
workspaceLabelKey = "kubesphere.io/workspace"
|
||||
)
|
||||
|
||||
var adminRules = []rbac.PolicyRule{{Verbs: []string{"*"}, APIGroups: []string{"*"}, Resources: []string{"*"}}}
|
||||
var editorRules = []rbac.PolicyRule{{Verbs: []string{"*"}, APIGroups: []string{"", "apps", "extensions", "batch", "kubesphere.io", "account.kubesphere.io"}, Resources: []string{"*"}}}
|
||||
var viewerRules = []rbac.PolicyRule{{Verbs: []string{"list", "get", "watch"}, APIGroups: []string{"", "apps", "extensions", "batch", "kubesphere.io", "account.kubesphere.io"}, Resources: []string{"*"}}}
|
||||
var editorRules = []rbac.PolicyRule{{Verbs: []string{"*"}, APIGroups: []string{"", "apps", "extensions", "batch"}, Resources: []string{"*"}}}
|
||||
var viewerRules = []rbac.PolicyRule{{Verbs: []string{"list", "get", "watch"}, APIGroups: []string{"", "apps", "extensions", "batch"}, Resources: []string{"*"}}}
|
||||
|
||||
type runTime struct {
|
||||
RuntimeId string `json:"runtime_id"`
|
||||
@@ -133,182 +131,101 @@ func (ctl *NamespaceCtl) createOpRuntime(namespace string) ([]byte, error) {
|
||||
return makeHttpRequest("POST", url, string(body))
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) updateSystemRoleBindings(namespace *v1.Namespace) error {
|
||||
func (ctl *NamespaceCtl) createDefaultRoleBinding(ns, user string) error {
|
||||
|
||||
workspace := ""
|
||||
roleBinding := &rbac.RoleBinding{ObjectMeta: metaV1.ObjectMeta{Name: admin, Namespace: ns},
|
||||
Subjects: []rbac.Subject{{Name: user, Kind: rbac.UserKind}}, RoleRef: rbac.RoleRef{Kind: "Role", Name: admin}}
|
||||
|
||||
if namespace.Labels != nil {
|
||||
workspace = namespace.Labels[workspaceLabelKey]
|
||||
_, err := ctl.K8sClient.RbacV1().RoleBindings(ns).Create(roleBinding)
|
||||
|
||||
if err != nil && !errors.IsAlreadyExists(err) {
|
||||
glog.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
adminBinding, err := ctl.K8sClient.RbacV1().RoleBindings(namespace.Name).Get(admin, metaV1.GetOptions{})
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
adminBinding = new(rbac.RoleBinding)
|
||||
adminBinding.Name = admin
|
||||
adminBinding.Namespace = namespace.Name
|
||||
adminBinding.RoleRef = rbac.RoleRef{Kind: "Role", Name: admin}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
func (ctl *NamespaceCtl) createDefaultRole(ns string) error {
|
||||
adminRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: admin, Namespace: ns}, Rules: adminRules}
|
||||
editorRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: editor, Namespace: ns}, Rules: editorRules}
|
||||
viewerRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: viewer, Namespace: ns}, Rules: viewerRules}
|
||||
|
||||
_, err := ctl.K8sClient.RbacV1().Roles(ns).Create(adminRole)
|
||||
|
||||
if err != nil && !errors.IsAlreadyExists(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
adminBinding.Subjects = make([]rbac.Subject, 0)
|
||||
_, err = ctl.K8sClient.RbacV1().Roles(ns).Create(editorRole)
|
||||
|
||||
if workspace != "" {
|
||||
workspaceAdmin, err := ctl.K8sClient.RbacV1().ClusterRoleBindings().Get(fmt.Sprintf("system:%s:%s", workspace, constants.WorkspaceAdmin), metaV1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
adminBinding.Subjects = append(adminBinding.Subjects, workspaceAdmin.Subjects...)
|
||||
if err != nil && !errors.IsAlreadyExists(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if adminBinding.ResourceVersion == "" {
|
||||
_, err = ctl.K8sClient.RbacV1().RoleBindings(namespace.Name).Create(adminBinding)
|
||||
_, err = ctl.K8sClient.RbacV1().Roles(ns).Create(viewerRole)
|
||||
|
||||
if err != nil && !errors.IsAlreadyExists(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) createRoleAndRuntime(item v1.Namespace) {
|
||||
var creator string
|
||||
var runtime string
|
||||
ns := item.Name
|
||||
|
||||
if item.Annotations == nil {
|
||||
creator = ""
|
||||
runtime = ""
|
||||
} else {
|
||||
_, err = ctl.K8sClient.RbacV1().RoleBindings(namespace.Name).Update(adminBinding)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
viewerBinding, err := ctl.K8sClient.RbacV1().RoleBindings(namespace.Name).Get(viewer, metaV1.GetOptions{})
|
||||
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
viewerBinding = new(rbac.RoleBinding)
|
||||
viewerBinding.Name = viewer
|
||||
viewerBinding.Namespace = namespace.Name
|
||||
viewerBinding.RoleRef = rbac.RoleRef{Kind: "Role", Name: viewer}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
viewerBinding.Subjects = make([]rbac.Subject, 0)
|
||||
|
||||
if workspace != "" {
|
||||
workspaceViewer, err := ctl.K8sClient.RbacV1().ClusterRoleBindings().Get(fmt.Sprintf("system:%s:%s", workspace, constants.WorkspaceViewer), metaV1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
viewerBinding.Subjects = append(viewerBinding.Subjects, workspaceViewer.Subjects...)
|
||||
}
|
||||
|
||||
if viewerBinding.ResourceVersion == "" {
|
||||
_, err = ctl.K8sClient.RbacV1().RoleBindings(namespace.Name).Create(viewerBinding)
|
||||
} else {
|
||||
_, err = ctl.K8sClient.RbacV1().RoleBindings(namespace.Name).Update(viewerBinding)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) createDefaultRoleBinding(namespace *v1.Namespace) error {
|
||||
creator := ""
|
||||
if namespace.Annotations != nil {
|
||||
creator = namespace.Annotations[creatorAnnotateKey]
|
||||
}
|
||||
// create once
|
||||
if creator != "" {
|
||||
creatorBindingName := fmt.Sprintf("%s-admin", creator)
|
||||
creatorBinding, err := ctl.K8sClient.RbacV1().RoleBindings(namespace.Name).Get(creatorBindingName, metaV1.GetOptions{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
creatorBinding = new(rbac.RoleBinding)
|
||||
creatorBinding.Name = creatorBindingName
|
||||
creatorBinding.Namespace = namespace.Name
|
||||
creatorBinding.RoleRef = rbac.RoleRef{Kind: "Role", Name: admin}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
creatorBinding.Subjects = []rbac.Subject{{Kind: rbac.UserKind, Name: creator}}
|
||||
|
||||
if creatorBinding.ResourceVersion == "" {
|
||||
_, err = ctl.K8sClient.RbacV1().RoleBindings(namespace.Name).Create(creatorBinding)
|
||||
} else {
|
||||
_, err = ctl.K8sClient.RbacV1().RoleBindings(namespace.Name).Update(creatorBinding)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) CreateDefaultRoleAndRoleBinding(namespace *v1.Namespace) error {
|
||||
adminRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: admin, Namespace: namespace.Name, Annotations: map[string]string{creatorAnnotateKey: "system"}}, Rules: adminRules}
|
||||
operatorRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: operator, Namespace: namespace.Name, Annotations: map[string]string{creatorAnnotateKey: "system"}}, Rules: editorRules}
|
||||
viewerRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: viewer, Namespace: namespace.Name, Annotations: map[string]string{creatorAnnotateKey: "system"}}, Rules: viewerRules}
|
||||
|
||||
_, err := ctl.K8sClient.RbacV1().Roles(namespace.Name).Create(adminRole)
|
||||
|
||||
if err != nil && !errors.IsAlreadyExists(err) {
|
||||
return err
|
||||
} else if err == nil {
|
||||
if err := ctl.createDefaultRoleBinding(namespace); err != nil {
|
||||
glog.Warning("default role binding create failed", namespace.Name)
|
||||
}
|
||||
}
|
||||
|
||||
_, err = ctl.K8sClient.RbacV1().Roles(namespace.Name).Create(operatorRole)
|
||||
|
||||
if err != nil && !errors.IsAlreadyExists(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = ctl.K8sClient.RbacV1().Roles(namespace.Name).Create(viewerRole)
|
||||
|
||||
if err != nil && !errors.IsAlreadyExists(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) createRoleAndRuntime(namespace *v1.Namespace) {
|
||||
runtime := ""
|
||||
initTime := ""
|
||||
if namespace.Annotations != nil {
|
||||
runtime = namespace.Annotations[openPitrixRuntimeAnnotateKey]
|
||||
initTime = namespace.Annotations[initTimeAnnotateKey]
|
||||
runtime = item.Annotations[openPitrixRuntimeAnnotateKey]
|
||||
creator = item.Annotations[creatorAnnotateKey]
|
||||
}
|
||||
|
||||
componentsNamespaces := []string{constants.KubeSystemNamespace, constants.OpenPitrixNamespace, constants.IstioNamespace, constants.KubeSphereNamespace}
|
||||
|
||||
if runtime == "" && !slice.ContainsString(componentsNamespaces, namespace.Name, nil) {
|
||||
_, runtimeCreateError := ctl.createOpRuntime(namespace.Name)
|
||||
if len(runtime) == 0 && !slice.ContainsString(componentsNamespaces, ns, nil) {
|
||||
glog.Infoln("create runtime:", ns)
|
||||
var runtimeCreateError error
|
||||
resp, runtimeCreateError := ctl.createOpRuntime(ns)
|
||||
|
||||
if runtimeCreateError == nil {
|
||||
var runtime runTime
|
||||
runtimeCreateError = json.Unmarshal(resp, &runtime)
|
||||
if runtimeCreateError == nil {
|
||||
|
||||
if item.Annotations == nil {
|
||||
item.Annotations = make(map[string]string, 0)
|
||||
}
|
||||
|
||||
item.Annotations[openPitrixRuntimeAnnotateKey] = runtime.RuntimeId
|
||||
_, runtimeCreateError = ctl.K8sClient.CoreV1().Namespaces().Update(&item)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if runtimeCreateError != nil {
|
||||
glog.Error("runtime create error:", runtimeCreateError)
|
||||
}
|
||||
}
|
||||
|
||||
if initTime == "" {
|
||||
err := ctl.CreateDefaultRoleAndRoleBinding(namespace)
|
||||
if err == nil {
|
||||
err = ctl.updateSystemRoleBindings(namespace)
|
||||
if err != nil {
|
||||
glog.Error("role binding update error:", err)
|
||||
}
|
||||
} else {
|
||||
glog.Error("default role create error:", err)
|
||||
}
|
||||
if err == nil {
|
||||
pathJson := fmt.Sprintf(`{"metadata":{"annotations":{"%s":"%s"}}}`, initTimeAnnotateKey, time.Now().UTC().Format("2006-01-02T15:04:05Z"))
|
||||
_, err = ctl.K8sClient.CoreV1().Namespaces().Patch(namespace.Name, "application/strategic-merge-patch+json", []byte(pathJson))
|
||||
if err != nil {
|
||||
glog.Error("annotations patch error init failed:", namespace.Name, err)
|
||||
if len(creator) > 0 {
|
||||
roleCreateError := ctl.createDefaultRole(ns)
|
||||
glog.Infoln("create default role:", ns)
|
||||
if roleCreateError == nil {
|
||||
|
||||
roleBindingError := ctl.createDefaultRoleBinding(ns, creator)
|
||||
glog.Infoln("create default role binding:", ns)
|
||||
if roleBindingError != nil {
|
||||
glog.Error("default role binding create error:", roleBindingError)
|
||||
}
|
||||
|
||||
} else {
|
||||
glog.Error("default role create error:", roleCreateError)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -376,12 +293,7 @@ func (ctl *NamespaceCtl) createCephSecretAfterNewNs(item v1.Namespace) {
|
||||
}
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) generateObject(item *v1.Namespace) *Namespace {
|
||||
var displayName string
|
||||
|
||||
if item.Annotations != nil && len(item.Annotations[DisplayName]) > 0 {
|
||||
displayName = item.Annotations[DisplayName]
|
||||
}
|
||||
func (ctl *NamespaceCtl) generateObject(item v1.Namespace) *Namespace {
|
||||
|
||||
name := item.Name
|
||||
createTime := item.CreationTimestamp.Time
|
||||
@@ -391,13 +303,7 @@ func (ctl *NamespaceCtl) generateObject(item *v1.Namespace) *Namespace {
|
||||
createTime = time.Now()
|
||||
}
|
||||
|
||||
object := &Namespace{
|
||||
Name: name,
|
||||
DisplayName: displayName,
|
||||
CreateTime: createTime,
|
||||
Status: status,
|
||||
Annotation: MapString{item.Annotations},
|
||||
}
|
||||
object := &Namespace{Name: name, CreateTime: createTime, Status: status, Annotation: Annotation{item.Annotations}}
|
||||
|
||||
return object
|
||||
}
|
||||
@@ -416,17 +322,17 @@ func (ctl *NamespaceCtl) sync(stopChan chan struct{}) {
|
||||
db = db.CreateTable(&Namespace{})
|
||||
|
||||
ctl.initListerAndInformer()
|
||||
//list, err := ctl.lister.List(labels.Everything())
|
||||
//if err != nil {
|
||||
// glog.Error(err)
|
||||
// return
|
||||
//}
|
||||
list, err := ctl.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
//for _, item := range list {
|
||||
// obj := ctl.generateObject(item)
|
||||
// db.Create(obj)
|
||||
// ctl.createRoleAndRuntime(item)
|
||||
//}
|
||||
for _, item := range list {
|
||||
obj := ctl.generateObject(*item)
|
||||
db.Create(obj)
|
||||
ctl.createRoleAndRuntime(*item)
|
||||
}
|
||||
|
||||
ctl.informer.Run(stopChan)
|
||||
}
|
||||
@@ -452,16 +358,16 @@ func (ctl *NamespaceCtl) initListerAndInformer() {
|
||||
AddFunc: func(obj interface{}) {
|
||||
|
||||
object := obj.(*v1.Namespace)
|
||||
mysqlObject := ctl.generateObject(object)
|
||||
mysqlObject := ctl.generateObject(*object)
|
||||
db.Create(mysqlObject)
|
||||
ctl.createRoleAndRuntime(object)
|
||||
ctl.createRoleAndRuntime(*object)
|
||||
ctl.createCephSecretAfterNewNs(*object)
|
||||
},
|
||||
UpdateFunc: func(old, new interface{}) {
|
||||
object := new.(*v1.Namespace)
|
||||
mysqlObject := ctl.generateObject(object)
|
||||
mysqlObject := ctl.generateObject(*object)
|
||||
db.Save(mysqlObject)
|
||||
ctl.createRoleAndRuntime(object)
|
||||
ctl.createRoleAndRuntime(*object)
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
var item Namespace
|
||||
@@ -469,6 +375,7 @@ func (ctl *NamespaceCtl) initListerAndInformer() {
|
||||
db.Where("name=?", object.Name).Find(&item)
|
||||
db.Delete(item)
|
||||
ctl.deleteOpRuntime(*object)
|
||||
|
||||
},
|
||||
})
|
||||
|
||||
@@ -481,14 +388,12 @@ func (ctl *NamespaceCtl) CountWithConditions(conditions string) int {
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
func (ctl *NamespaceCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Namespace
|
||||
var object Namespace
|
||||
var total int
|
||||
|
||||
if len(order) == 0 {
|
||||
order = "createTime desc"
|
||||
}
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
@@ -496,7 +401,7 @@ func (ctl *NamespaceCtl) ListWithConditions(conditions string, paging *Paging, o
|
||||
for index := range list {
|
||||
usage, err := ctl.GetNamespaceQuota(list[index].Name)
|
||||
if err == nil {
|
||||
list[index].Usage = usage
|
||||
list[index].Usaeg = usage
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -513,7 +418,7 @@ func (ctl *NamespaceCtl) GetNamespaceQuota(namespace string) (v1.ResourceList, e
|
||||
|
||||
usage := make(v1.ResourceList)
|
||||
|
||||
resourceList := []string{Daemonsets, Deployments, Ingresses, Roles, Services, Statefulsets, PersistentVolumeClaim, Pods, Jobs, Cronjobs}
|
||||
resourceList := []string{Daemonsets, Deployments, Ingresses, Roles, Services, Statefulsets, PersistentVolumeClaim, Pods}
|
||||
for _, resourceName := range resourceList {
|
||||
used := getUsage(namespace, resourceName)
|
||||
var quantity resource.Quantity
|
||||
@@ -528,8 +433,3 @@ func (ctl *NamespaceCtl) GetNamespaceQuota(namespace string) (v1.ResourceList, e
|
||||
usage["runningPods"] = quantity
|
||||
return usage, nil
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
const NodeRoleLabel = "node-role.kubernetes.io/"
|
||||
|
||||
func (ctl *NodeCtl) generateObject(item v1.Node) *Node {
|
||||
var status, ip, displayName, msgStr string
|
||||
var msg, role []string
|
||||
|
||||
if item.Annotations != nil && len(item.Annotations[DisplayName]) > 0 {
|
||||
displayName = item.Annotations[DisplayName]
|
||||
}
|
||||
|
||||
name := item.Name
|
||||
createTime := item.ObjectMeta.CreationTimestamp.Time
|
||||
annotation := item.Annotations
|
||||
|
||||
// in case of multiple roles
|
||||
for label, _ := range item.Labels {
|
||||
if strings.HasPrefix(label, NodeRoleLabel) {
|
||||
if parts := strings.Split(label, "/"); len(parts) == 2 {
|
||||
role = append(role, parts[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, condition := range item.Status.Conditions {
|
||||
if condition.Type == "Ready" {
|
||||
if condition.Status == "True" {
|
||||
status = Running
|
||||
} else {
|
||||
status = Error
|
||||
}
|
||||
|
||||
} else {
|
||||
if condition.Status == "True" {
|
||||
msg = append(msg, condition.Reason)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(msg) > 0 {
|
||||
msgStr = strings.Join(msg, ",")
|
||||
if status == Running {
|
||||
status = Warning
|
||||
}
|
||||
}
|
||||
|
||||
for _, address := range item.Status.Addresses {
|
||||
if address.Type == "InternalIP" {
|
||||
ip = address.Address
|
||||
}
|
||||
}
|
||||
|
||||
object := &Node{
|
||||
Name: name,
|
||||
DisplayName: displayName,
|
||||
Ip: ip,
|
||||
Status: status,
|
||||
CreateTime: createTime,
|
||||
Annotation: MapString{annotation},
|
||||
Taints: Taints{item.Spec.Taints},
|
||||
Msg: msgStr,
|
||||
Role: strings.Join(role, ","),
|
||||
Labels: MapString{item.Labels}}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (ctl *NodeCtl) Name() string {
|
||||
return ctl.CommonAttribute.Name
|
||||
}
|
||||
|
||||
func (ctl *NodeCtl) sync(stopChan chan struct{}) {
|
||||
db := ctl.DB
|
||||
|
||||
if db.HasTable(&Node{}) {
|
||||
db.DropTable(&Node{})
|
||||
}
|
||||
|
||||
db = db.CreateTable(&Node{})
|
||||
|
||||
ctl.initListerAndInformer()
|
||||
list, err := ctl.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range list {
|
||||
obj := ctl.generateObject(*item)
|
||||
db.Create(obj)
|
||||
}
|
||||
|
||||
ctl.informer.Run(stopChan)
|
||||
}
|
||||
|
||||
func (ctl *NodeCtl) total() int {
|
||||
list, err := ctl.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Errorf("count %s failed, reason:%s", err, ctl.Name())
|
||||
return 0
|
||||
}
|
||||
return len(list)
|
||||
}
|
||||
|
||||
func (ctl *NodeCtl) initListerAndInformer() {
|
||||
db := ctl.DB
|
||||
|
||||
informerFactory := informers.NewSharedInformerFactory(ctl.K8sClient, time.Second*resyncCircle)
|
||||
|
||||
ctl.lister = informerFactory.Core().V1().Nodes().Lister()
|
||||
|
||||
informer := informerFactory.Core().V1().Nodes().Informer()
|
||||
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
object := obj.(*v1.Node)
|
||||
mysqlObject := ctl.generateObject(*object)
|
||||
db.Create(mysqlObject)
|
||||
},
|
||||
UpdateFunc: func(old, new interface{}) {
|
||||
object := new.(*v1.Node)
|
||||
mysqlObject := ctl.generateObject(*object)
|
||||
db.Save(mysqlObject)
|
||||
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
var item Node
|
||||
object := obj.(*v1.Node)
|
||||
db.Where("name=? ", object.Name, object.Namespace).Find(&item)
|
||||
db.Delete(item)
|
||||
},
|
||||
})
|
||||
|
||||
ctl.informer = informer
|
||||
}
|
||||
|
||||
func (ctl *NodeCtl) CountWithConditions(conditions string) int {
|
||||
var object Node
|
||||
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *NodeCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
var list []Node
|
||||
var object Node
|
||||
var total int
|
||||
|
||||
if len(order) == 0 {
|
||||
order = "createTime desc"
|
||||
}
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *NodeCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
@@ -166,29 +166,35 @@ func getStatusAndRestartCount(pod v1.Pod) (string, int) {
|
||||
}
|
||||
|
||||
func (ctl *PodCtl) generateObject(item v1.Pod) *Pod {
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
podIp := item.Status.PodIP
|
||||
nodeName := item.Spec.NodeName
|
||||
nodeIp := item.Status.HostIP
|
||||
status, restartCount := getStatusAndRestartCount(item)
|
||||
createTime := item.CreationTimestamp.Time
|
||||
containerStatus := item.Status.ContainerStatuses
|
||||
containerSpecs := item.Spec.Containers
|
||||
|
||||
var ownerKind, ownerName string
|
||||
var containers Containers
|
||||
|
||||
// For ReplicaSet,ReplicaController,DaemonSet,StatefulSet,Job,CronJob, k8s will automatically
|
||||
// set ownerReference for pods, in case of setting ownerReference manually.
|
||||
if item.OwnerReferences != nil && len(item.OwnerReferences) > 0 {
|
||||
ownerKind = item.OwnerReferences[0].Kind
|
||||
ownerName = item.OwnerReferences[0].Name
|
||||
for _, containerSpec := range containerSpecs {
|
||||
var container Container
|
||||
container.Name = containerSpec.Name
|
||||
container.Image = containerSpec.Image
|
||||
container.Ports = containerSpec.Ports
|
||||
container.Resources = containerSpec.Resources
|
||||
for _, status := range containerStatus {
|
||||
if container.Name == status.Name {
|
||||
container.Ready = status.Ready
|
||||
}
|
||||
}
|
||||
|
||||
containers = append(containers, container)
|
||||
}
|
||||
|
||||
object := &Pod{
|
||||
Namespace: item.Namespace,
|
||||
Name: item.Name,
|
||||
Node: item.Spec.NodeName,
|
||||
Status: item.Status,
|
||||
CreateTime: item.CreationTimestamp.Time,
|
||||
OwnerKind: ownerKind,
|
||||
OwnerName: ownerName,
|
||||
Spec: item.Spec,
|
||||
Metadata: item.ObjectMeta,
|
||||
Kind: item.TypeMeta.Kind,
|
||||
APIVersion: item.TypeMeta.APIVersion,
|
||||
}
|
||||
object := &Pod{Namespace: namespace, Name: name, Node: nodeName, PodIp: podIp, Status: status, NodeIp: nodeIp,
|
||||
CreateTime: createTime, Annotation: Annotation{item.Annotations}, Containers: containers, RestartCount: restartCount}
|
||||
|
||||
return object
|
||||
}
|
||||
@@ -271,21 +277,25 @@ func (ctl *PodCtl) CountWithConditions(conditions string) int {
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *PodCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
func (ctl *PodCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Pod
|
||||
var object Pod
|
||||
var total int
|
||||
|
||||
if len(order) == 0 {
|
||||
order = "createTime desc"
|
||||
}
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *PodCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
//func (ctl *PodCtl) Count(namespace string) int {
|
||||
// var count int
|
||||
// db := ctl.DB
|
||||
// if len(namespace) == 0 {
|
||||
// db.Model(&Pod{}).Count(&count)
|
||||
// } else {
|
||||
// db.Model(&Pod{}).Where("namespace = ?", namespace).Count(&count)
|
||||
// }
|
||||
// return count
|
||||
//}
|
||||
|
||||
@@ -30,20 +30,10 @@ import (
|
||||
)
|
||||
|
||||
func (ctl *PvcCtl) generateObject(item *v1.PersistentVolumeClaim) *Pvc {
|
||||
var displayName string
|
||||
|
||||
if item.Annotations != nil && len(item.Annotations[DisplayName]) > 0 {
|
||||
displayName = item.Annotations[DisplayName]
|
||||
}
|
||||
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
createTime := item.CreationTimestamp.Time
|
||||
status := fmt.Sprintf("%s", item.Status.Phase)
|
||||
if item.DeletionTimestamp != nil {
|
||||
status = "Terminating"
|
||||
}
|
||||
|
||||
createTime := item.CreationTimestamp.Time
|
||||
var capacity, storageClass, accessModeStr string
|
||||
|
||||
if createTime.IsZero() {
|
||||
@@ -68,18 +58,8 @@ func (ctl *PvcCtl) generateObject(item *v1.PersistentVolumeClaim) *Pvc {
|
||||
|
||||
accessModeStr = strings.Join(accessModeList, ",")
|
||||
|
||||
object := &Pvc{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
DisplayName: displayName,
|
||||
Status: status,
|
||||
Capacity: capacity,
|
||||
AccessMode: accessModeStr,
|
||||
StorageClassName: storageClass,
|
||||
CreateTime: createTime,
|
||||
Annotation: MapString{item.Annotations},
|
||||
Labels: MapString{item.Labels},
|
||||
}
|
||||
object := &Pvc{Namespace: namespace, Name: name, Status: status, Capacity: capacity,
|
||||
AccessMode: accessModeStr, StorageClassName: storageClass, CreateTime: createTime, Annotation: Annotation{item.Annotations}}
|
||||
|
||||
return object
|
||||
}
|
||||
@@ -158,14 +138,12 @@ func (ctl *PvcCtl) CountWithConditions(conditions string) int {
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *PvcCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
func (ctl *PvcCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Pvc
|
||||
var object Pvc
|
||||
var total int
|
||||
|
||||
if len(order) == 0 {
|
||||
order = "createTime desc"
|
||||
}
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
@@ -185,7 +163,13 @@ func (ctl *PvcCtl) ListWithConditions(conditions string, paging *Paging, order s
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *PvcCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
//func (ctl *PvcCtl) Count(namespace string) int {
|
||||
// var count int
|
||||
// db := ctl.DB
|
||||
// if len(namespace) == 0 {
|
||||
// db.Model(&Pvc{}).Count(&count)
|
||||
// } else {
|
||||
// db.Model(&Pvc{}).Where("namespace = ?", namespace).Count(&count)
|
||||
// }
|
||||
// return count
|
||||
//}
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"k8s.io/client-go/informers"
|
||||
)
|
||||
|
||||
func (ctl *ReplicaSetCtl) Name() string {
|
||||
return ctl.CommonAttribute.Name
|
||||
}
|
||||
|
||||
func (ctl *ReplicaSetCtl) sync(stopChan chan struct{}) {
|
||||
|
||||
ctl.initListerAndInformer()
|
||||
ctl.informer.Run(stopChan)
|
||||
}
|
||||
|
||||
func (ctl *ReplicaSetCtl) total() int {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (ctl *ReplicaSetCtl) initListerAndInformer() {
|
||||
|
||||
informerFactory := informers.NewSharedInformerFactory(ctl.K8sClient, time.Second*resyncCircle)
|
||||
|
||||
ctl.lister = informerFactory.Apps().V1().ReplicaSets().Lister()
|
||||
|
||||
informer := informerFactory.Apps().V1().ReplicaSets().Informer()
|
||||
|
||||
ctl.informer = informer
|
||||
}
|
||||
|
||||
func (ctl *ReplicaSetCtl) CountWithConditions(conditions string) int {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (ctl *ReplicaSetCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
|
||||
return 0, nil, nil
|
||||
}
|
||||
|
||||
func (ctl *ReplicaSetCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/client-go/informers"
|
||||
)
|
||||
|
||||
func (ctl *RoleBindingCtl) Name() string {
|
||||
return ctl.CommonAttribute.Name
|
||||
}
|
||||
|
||||
func (ctl *RoleBindingCtl) sync(stopChan chan struct{}) {
|
||||
ctl.initListerAndInformer()
|
||||
ctl.informer.Run(stopChan)
|
||||
}
|
||||
|
||||
func (ctl *RoleBindingCtl) total() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (ctl *RoleBindingCtl) initListerAndInformer() {
|
||||
|
||||
informerFactory := informers.NewSharedInformerFactory(ctl.K8sClient, time.Second*resyncCircle)
|
||||
|
||||
ctl.lister = informerFactory.Rbac().V1().RoleBindings().Lister()
|
||||
ctl.informer = informerFactory.Rbac().V1().RoleBindings().Informer()
|
||||
}
|
||||
|
||||
func (ctl *RoleBindingCtl) CountWithConditions(conditions string) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (ctl *RoleBindingCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
return 0, nil, errors.New("not implement")
|
||||
}
|
||||
|
||||
func (ctl *RoleBindingCtl) Lister() interface{} {
|
||||
return ctl.lister
|
||||
}
|
||||
@@ -28,14 +28,8 @@ import (
|
||||
)
|
||||
|
||||
func (ctl *RoleCtl) generateObject(item v1.Role) *Role {
|
||||
var displayName string
|
||||
|
||||
if item.Annotations != nil && len(item.Annotations[DisplayName]) == 0 {
|
||||
displayName = item.Annotations[DisplayName]
|
||||
}
|
||||
|
||||
name := item.Name
|
||||
if strings.HasPrefix(name, systemPrefix) || item.Annotations == nil || len(item.Annotations[creator]) == 0 {
|
||||
if strings.HasPrefix(name, systemPrefix) {
|
||||
return nil
|
||||
}
|
||||
namespace := item.Namespace
|
||||
@@ -44,13 +38,7 @@ func (ctl *RoleCtl) generateObject(item v1.Role) *Role {
|
||||
createTime = time.Now()
|
||||
}
|
||||
|
||||
object := &Role{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
DisplayName: displayName,
|
||||
CreateTime: createTime,
|
||||
Annotation: MapString{item.Annotations},
|
||||
}
|
||||
object := &Role{Namespace: namespace, Name: name, CreateTime: createTime, Annotation: Annotation{item.Annotations}}
|
||||
|
||||
return object
|
||||
}
|
||||
@@ -88,13 +76,13 @@ func (ctl *RoleCtl) sync(stopChan chan struct{}) {
|
||||
func (ctl *RoleCtl) total() int {
|
||||
list, err := ctl.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Errorf("count %s failed, reason:%s", err, ctl.Name())
|
||||
glog.Errorf("count %s falied, reason:%s", err, ctl.Name())
|
||||
return 0
|
||||
}
|
||||
|
||||
count := 0
|
||||
for _, item := range list {
|
||||
if !strings.HasPrefix(item.Name, systemPrefix) && item.Annotations != nil && len(item.Annotations[creator]) > 0 {
|
||||
if !strings.HasPrefix(item.Name, systemPrefix) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
@@ -144,21 +132,21 @@ func (ctl *RoleCtl) CountWithConditions(conditions string) int {
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *RoleCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
func (ctl *RoleCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Role
|
||||
var object Role
|
||||
var total int
|
||||
|
||||
if len(order) == 0 {
|
||||
order = "createTime desc"
|
||||
}
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *RoleCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
//func (ctl *RoleCtl) Count(namespace string) int {
|
||||
// var count int
|
||||
// db := ctl.DB
|
||||
// db.Model(&Role{}).Where("namespace = ?", namespace).Count(&count)
|
||||
// return count
|
||||
//}
|
||||
|
||||
@@ -17,18 +17,12 @@ limitations under the License.
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/jinzhu/gorm"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"os"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
@@ -37,9 +31,10 @@ type resourceControllers struct {
|
||||
k8sClient *kubernetes.Clientset
|
||||
}
|
||||
|
||||
var stopChan chan struct{}
|
||||
var ResourceControllers resourceControllers
|
||||
|
||||
func (rec *resourceControllers) runController(name string, stopChan chan struct{}, wg *sync.WaitGroup) {
|
||||
func (rec *resourceControllers) runContoller(name string) {
|
||||
var ctl Controller
|
||||
attr := CommonAttribute{DB: client.NewDBClient(), K8sClient: rec.k8sClient, stopChan: stopChan,
|
||||
aliveChan: make(chan struct{}), Name: name}
|
||||
@@ -66,37 +61,16 @@ func (rec *resourceControllers) runController(name string, stopChan chan struct{
|
||||
ctl = &NamespaceCtl{CommonAttribute: attr}
|
||||
case StorageClasses:
|
||||
ctl = &StorageClassCtl{CommonAttribute: attr}
|
||||
case Jobs:
|
||||
ctl = &JobCtl{CommonAttribute: attr}
|
||||
case Cronjobs:
|
||||
ctl = &CronJobCtl{CommonAttribute: attr}
|
||||
case Nodes:
|
||||
ctl = &NodeCtl{CommonAttribute: attr}
|
||||
case Replicasets:
|
||||
ctl = &ReplicaSetCtl{CommonAttribute: attr}
|
||||
case ControllerRevisions:
|
||||
ctl = &ControllerRevisionCtl{CommonAttribute: attr}
|
||||
case ConfigMaps:
|
||||
ctl = &ConfigMapCtl{CommonAttribute: attr}
|
||||
case Secrets:
|
||||
ctl = &SecretCtl{CommonAttribute: attr}
|
||||
case ClusterRoleBindings:
|
||||
ctl = &ClusterRoleBindingCtl{CommonAttribute: attr}
|
||||
case RoleBindings:
|
||||
ctl = &RoleBindingCtl{CommonAttribute: attr}
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
rec.Controllers[name] = ctl
|
||||
wg.Add(1)
|
||||
go listAndWatch(ctl, wg)
|
||||
go listAndWatch(ctl)
|
||||
|
||||
}
|
||||
|
||||
func dbHealthCheck(db *gorm.DB) {
|
||||
defer db.Close()
|
||||
|
||||
for {
|
||||
count := 0
|
||||
var err error
|
||||
@@ -105,26 +79,27 @@ func dbHealthCheck(db *gorm.DB) {
|
||||
if err != nil {
|
||||
count++
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
if count > 3 {
|
||||
syscall.Kill(os.Getpid(), syscall.SIGTERM)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Run(stopChan chan struct{}, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
func Run() {
|
||||
|
||||
stopChan := make(chan struct{})
|
||||
defer close(stopChan)
|
||||
|
||||
k8sClient := client.NewK8sClient()
|
||||
ResourceControllers = resourceControllers{k8sClient: k8sClient, Controllers: make(map[string]Controller)}
|
||||
|
||||
for _, item := range []string{Deployments, Statefulsets, Daemonsets, PersistentVolumeClaim, Pods, Services,
|
||||
Ingresses, Roles, RoleBindings, ClusterRoles, ClusterRoleBindings, Namespaces, StorageClasses, Jobs, Cronjobs, Nodes, Replicasets,
|
||||
ControllerRevisions, ConfigMaps, Secrets} {
|
||||
ResourceControllers.runController(item, stopChan, wg)
|
||||
Ingresses, Roles, ClusterRoles, Namespaces, StorageClasses} {
|
||||
ResourceControllers.runContoller(item)
|
||||
}
|
||||
|
||||
go dbHealthCheck(client.NewDBClient())
|
||||
@@ -132,25 +107,14 @@ func Run(stopChan chan struct{}, wg *sync.WaitGroup) {
|
||||
for {
|
||||
for ctlName, controller := range ResourceControllers.Controllers {
|
||||
select {
|
||||
case <-stopChan:
|
||||
return
|
||||
case _, isClose := <-controller.chanAlive():
|
||||
if !isClose {
|
||||
glog.Errorf("controller %s have stopped, restart it", ctlName)
|
||||
ResourceControllers.runController(ctlName, stopChan, wg)
|
||||
ResourceControllers.runContoller(ctlName)
|
||||
}
|
||||
default:
|
||||
time.Sleep(3 * time.Second)
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetLister(controller string) (interface{}, error) {
|
||||
if ctl, ok := ResourceControllers.Controllers[controller]; ok {
|
||||
if ctl.Lister() != nil {
|
||||
return ctl.Lister(), nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New(fmt.Sprintf("lister of %s not alive", controller))
|
||||
}
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
func (ctl *SecretCtl) generateObject(item v1.Secret) *Secret {
|
||||
var displayName string
|
||||
if item.Annotations != nil && len(item.Annotations[DisplayName]) > 0 {
|
||||
displayName = item.Annotations[DisplayName]
|
||||
}
|
||||
|
||||
createTime := item.CreationTimestamp.Time
|
||||
if createTime.IsZero() {
|
||||
createTime = time.Now()
|
||||
}
|
||||
|
||||
object := &Secret{
|
||||
Name: item.Name,
|
||||
Namespace: item.Namespace,
|
||||
CreateTime: createTime,
|
||||
Annotation: MapString{item.Annotations},
|
||||
DisplayName: displayName,
|
||||
Entries: len(item.Data),
|
||||
Type: string(item.Type),
|
||||
}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (ctl *SecretCtl) Name() string {
|
||||
return ctl.CommonAttribute.Name
|
||||
}
|
||||
|
||||
func (ctl *SecretCtl) sync(stopChan chan struct{}) {
|
||||
db := ctl.DB
|
||||
|
||||
if db.HasTable(&Secret{}) {
|
||||
db.DropTable(&Secret{})
|
||||
}
|
||||
|
||||
db = db.CreateTable(&Secret{})
|
||||
|
||||
ctl.initListerAndInformer()
|
||||
|
||||
list, err := ctl.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range list {
|
||||
obj := ctl.generateObject(*item)
|
||||
if obj != nil {
|
||||
db.Create(obj)
|
||||
}
|
||||
}
|
||||
|
||||
ctl.informer.Run(stopChan)
|
||||
}
|
||||
|
||||
func (ctl *SecretCtl) total() int {
|
||||
list, err := ctl.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Errorf("count %s falied, reason:%s", err, ctl.Name())
|
||||
return 0
|
||||
}
|
||||
|
||||
return len(list)
|
||||
}
|
||||
|
||||
func (ctl *SecretCtl) initListerAndInformer() {
|
||||
db := ctl.DB
|
||||
|
||||
informerFactory := informers.NewSharedInformerFactory(ctl.K8sClient, time.Second*resyncCircle)
|
||||
ctl.lister = informerFactory.Core().V1().Secrets().Lister()
|
||||
|
||||
informer := informerFactory.Core().V1().Secrets().Informer()
|
||||
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
|
||||
object := obj.(*v1.Secret)
|
||||
mysqlObject := ctl.generateObject(*object)
|
||||
if mysqlObject != nil {
|
||||
db.Create(mysqlObject)
|
||||
}
|
||||
},
|
||||
UpdateFunc: func(old, new interface{}) {
|
||||
object := new.(*v1.Secret)
|
||||
mysqlObject := ctl.generateObject(*object)
|
||||
if mysqlObject != nil {
|
||||
db.Save(mysqlObject)
|
||||
}
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
var item Secret
|
||||
object := obj.(*v1.Secret)
|
||||
db.Where("name=?", object.Name).Find(&item)
|
||||
db.Delete(item)
|
||||
|
||||
},
|
||||
})
|
||||
ctl.informer = informer
|
||||
}
|
||||
|
||||
func (ctl *SecretCtl) CountWithConditions(conditions string) int {
|
||||
var object Secret
|
||||
|
||||
if strings.Contains(conditions, "namespace") {
|
||||
conditions = ""
|
||||
}
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *SecretCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
var object Secret
|
||||
var list []Secret
|
||||
var total int
|
||||
|
||||
if len(order) == 0 {
|
||||
order = "createTime desc"
|
||||
}
|
||||
|
||||
db := ctl.DB
|
||||
|
||||
listWithConditions(db, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *SecretCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
@@ -69,25 +69,12 @@ func getExternalIp(item v1.Service) string {
|
||||
}
|
||||
|
||||
func generateSvcObject(item v1.Service) *Service {
|
||||
var app string
|
||||
var displayName string
|
||||
|
||||
if item.Annotations != nil && len(item.Annotations[DisplayName]) > 0 {
|
||||
displayName = item.Annotations[DisplayName]
|
||||
}
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
createTime := item.CreationTimestamp.Time
|
||||
externalIp := getExternalIp(item)
|
||||
serviceType := item.Spec.Type
|
||||
vip := item.Spec.ClusterIP
|
||||
|
||||
release := item.ObjectMeta.Labels["release"]
|
||||
chart := item.ObjectMeta.Labels["chart"]
|
||||
|
||||
if len(release) > 0 && len(chart) > 0 {
|
||||
app = release + "/" + chart
|
||||
}
|
||||
ports := ""
|
||||
var nodePorts []string
|
||||
|
||||
@@ -95,8 +82,8 @@ func generateSvcObject(item v1.Service) *Service {
|
||||
createTime = time.Now()
|
||||
}
|
||||
|
||||
if len(item.Spec.ClusterIP) == 0 || item.Spec.ClusterIP == "None" {
|
||||
if len(item.Spec.Selector) != 0 {
|
||||
if len(item.Spec.ClusterIP) == 0 {
|
||||
if len(item.Spec.Selector) == 0 {
|
||||
serviceType = "Headless(Selector)"
|
||||
}
|
||||
|
||||
@@ -131,16 +118,13 @@ func generateSvcObject(item v1.Service) *Service {
|
||||
object := &Service{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
DisplayName: displayName,
|
||||
ServiceType: string(serviceType),
|
||||
ExternalIp: externalIp,
|
||||
VirtualIp: vip,
|
||||
CreateTime: createTime,
|
||||
Ports: ports,
|
||||
NodePorts: strings.Join(nodePorts, ","),
|
||||
Annotation: MapString{item.Annotations},
|
||||
Labels: MapString{item.Labels},
|
||||
App: app,
|
||||
Annotation: Annotation{item.Annotations},
|
||||
}
|
||||
|
||||
return object
|
||||
@@ -225,21 +209,14 @@ func (ctl *ServiceCtl) CountWithConditions(conditions string) int {
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *ServiceCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
func (ctl *ServiceCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Service
|
||||
var object Service
|
||||
var total int
|
||||
|
||||
if len(order) == 0 {
|
||||
order = "createTime desc"
|
||||
}
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *ServiceCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
|
||||
@@ -30,11 +30,6 @@ import (
|
||||
func (ctl *StatefulsetCtl) generateObject(item v1.StatefulSet) *Statefulset {
|
||||
var app string
|
||||
var status string
|
||||
var displayName string
|
||||
|
||||
if item.Annotations != nil && len(item.Annotations[DisplayName]) > 0 {
|
||||
displayName = item.Annotations[DisplayName]
|
||||
}
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
availablePodNum := item.Status.ReadyReplicas
|
||||
@@ -61,18 +56,8 @@ func (ctl *StatefulsetCtl) generateObject(item v1.StatefulSet) *Statefulset {
|
||||
}
|
||||
}
|
||||
|
||||
statefulSetObject := &Statefulset{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
DisplayName: displayName,
|
||||
Available: availablePodNum,
|
||||
Desire: desirePodNum,
|
||||
App: app,
|
||||
CreateTime: createTime,
|
||||
Status: status,
|
||||
Annotation: MapString{item.Annotations},
|
||||
Labels: MapString{item.Spec.Selector.MatchLabels},
|
||||
}
|
||||
statefulSetObject := &Statefulset{Namespace: namespace, Name: name, Available: availablePodNum, Desire: desirePodNum,
|
||||
App: app, CreateTime: createTime, Status: status, Annotation: Annotation{item.Annotations}}
|
||||
|
||||
return statefulSetObject
|
||||
}
|
||||
@@ -152,21 +137,14 @@ func (ctl *StatefulsetCtl) CountWithConditions(conditions string) int {
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *StatefulsetCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
func (ctl *StatefulsetCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Statefulset
|
||||
var object Statefulset
|
||||
var total int
|
||||
|
||||
if len(order) == 0 {
|
||||
order = "createTime desc"
|
||||
}
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *StatefulsetCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
|
||||
@@ -40,16 +40,9 @@ const (
|
||||
|
||||
func (ctl *StorageClassCtl) generateObject(item v1.StorageClass) *StorageClass {
|
||||
|
||||
var displayName string
|
||||
|
||||
if item.Annotations != nil && len(item.Annotations[DisplayName]) > 0 {
|
||||
displayName = item.Annotations[DisplayName]
|
||||
}
|
||||
|
||||
name := item.Name
|
||||
createTime := item.CreationTimestamp.Time
|
||||
isDefault := false
|
||||
provisioner := item.Provisioner
|
||||
if item.Annotations["storageclass.beta.kubernetes.io/is-default-class"] == "true" {
|
||||
isDefault = true
|
||||
}
|
||||
@@ -58,14 +51,7 @@ func (ctl *StorageClassCtl) generateObject(item v1.StorageClass) *StorageClass {
|
||||
createTime = time.Now()
|
||||
}
|
||||
|
||||
object := &StorageClass{
|
||||
Name: name,
|
||||
DisplayName: displayName,
|
||||
CreateTime: createTime,
|
||||
IsDefault: isDefault,
|
||||
Annotation: MapString{item.Annotations},
|
||||
Provisioner: provisioner,
|
||||
}
|
||||
object := &StorageClass{Name: name, CreateTime: createTime, IsDefault: isDefault, Annotation: Annotation{item.Annotations}}
|
||||
|
||||
return object
|
||||
}
|
||||
@@ -234,14 +220,12 @@ func (ctl *StorageClassCtl) CountWithConditions(conditions string) int {
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *StorageClassCtl) ListWithConditions(conditions string, paging *Paging, order string) (int, interface{}, error) {
|
||||
func (ctl *StorageClassCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []StorageClass
|
||||
var object StorageClass
|
||||
var total int
|
||||
|
||||
if len(order) == 0 {
|
||||
order = "createTime desc"
|
||||
}
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
@@ -254,8 +238,3 @@ func (ctl *StorageClassCtl) ListWithConditions(conditions string, paging *Paging
|
||||
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *StorageClassCtl) Lister() interface{} {
|
||||
|
||||
return ctl.lister
|
||||
}
|
||||
|
||||
@@ -19,9 +19,6 @@ package controllers
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@@ -30,8 +27,6 @@ import (
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
appV1 "k8s.io/client-go/listers/apps/v1"
|
||||
batchv1 "k8s.io/client-go/listers/batch/v1"
|
||||
batchv1beta1 "k8s.io/client-go/listers/batch/v1beta1"
|
||||
coreV1 "k8s.io/client-go/listers/core/v1"
|
||||
"k8s.io/client-go/listers/extensions/v1beta1"
|
||||
rbacV1 "k8s.io/client-go/listers/rbac/v1"
|
||||
@@ -40,19 +35,22 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
resyncCircle = 600
|
||||
Stopped = "stopped"
|
||||
PvcPending = "pending"
|
||||
Running = "running"
|
||||
Updating = "updating"
|
||||
Failed = "failed"
|
||||
Unfinished = "unfinished"
|
||||
Completed = "completed"
|
||||
Pause = "pause"
|
||||
Warning = "warning"
|
||||
Error = "error"
|
||||
DisplayName = "displayName"
|
||||
creator = "creator"
|
||||
resyncCircle = 600
|
||||
Stopped = "stopped"
|
||||
PvcPending = "Pending"
|
||||
Running = "running"
|
||||
Updating = "updating"
|
||||
tablePods = "pods"
|
||||
tableDeployments = "deployments"
|
||||
tableDaemonsets = "daemonsets"
|
||||
tableStatefulsets = "statefulsets"
|
||||
tableNamespaces = "namespaces"
|
||||
tableIngresses = "ingresses"
|
||||
tablePersistentVolumeClaim = "pvcs"
|
||||
tableRoles = "roles"
|
||||
tableClusterRoles = "cluster_roles"
|
||||
tableServices = "services"
|
||||
tableStorageClasses = "storage_classes"
|
||||
|
||||
Pods = "pods"
|
||||
Deployments = "deployments"
|
||||
@@ -62,26 +60,17 @@ const (
|
||||
Ingresses = "ingresses"
|
||||
PersistentVolumeClaim = "persistent-volume-claims"
|
||||
Roles = "roles"
|
||||
RoleBindings = "role-bindings"
|
||||
ClusterRoles = "cluster-roles"
|
||||
ClusterRoleBindings = "cluster-role-bindings"
|
||||
Services = "services"
|
||||
StorageClasses = "storage-classes"
|
||||
Applications = "applications"
|
||||
Jobs = "jobs"
|
||||
Cronjobs = "cronjobs"
|
||||
Nodes = "nodes"
|
||||
Replicasets = "replicasets"
|
||||
ControllerRevisions = "controllerrevisions"
|
||||
ConfigMaps = "configmaps"
|
||||
Secrets = "secrets"
|
||||
)
|
||||
|
||||
type MapString struct {
|
||||
Values map[string]string `json:"values" gorm:"type:TEXT"`
|
||||
type Annotation struct {
|
||||
Values map[string]string `gorm:"type:TEXT"`
|
||||
}
|
||||
|
||||
func (annotation *MapString) Scan(val interface{}) error {
|
||||
func (annotation *Annotation) Scan(val interface{}) error {
|
||||
switch val := val.(type) {
|
||||
case string:
|
||||
return json.Unmarshal([]byte(val), annotation)
|
||||
@@ -93,104 +82,92 @@ func (annotation *MapString) Scan(val interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (annotation MapString) Value() (driver.Value, error) {
|
||||
func (annotation Annotation) Value() (driver.Value, error) {
|
||||
bytes, err := json.Marshal(annotation)
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
type Taints struct {
|
||||
Values []v1.Taint `json:"values" gorm:"type:TEXT"`
|
||||
}
|
||||
|
||||
func (taints *Taints) Scan(val interface{}) error {
|
||||
switch val := val.(type) {
|
||||
case string:
|
||||
return json.Unmarshal([]byte(val), taints)
|
||||
case []byte:
|
||||
return json.Unmarshal(val, taints)
|
||||
default:
|
||||
return errors.New("not support")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (taints Taints) Value() (driver.Value, error) {
|
||||
bytes, err := json.Marshal(taints)
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
type Deployment struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
DisplayName string `json:"displayName,omitempty" gorm:"column:displayName"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
App string `json:"app,omitempty"`
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
App string `json:"app,omitempty"`
|
||||
|
||||
Available int32 `json:"available"`
|
||||
Desire int32 `json:"desire"`
|
||||
Status string `json:"status"`
|
||||
Labels MapString `json:"labels"`
|
||||
Annotation MapString `json:"annotations"`
|
||||
UpdateTime time.Time `gorm:"column:updateTime" json:"updateTime,omitempty"`
|
||||
Available int32 `json:"available"`
|
||||
Desire int32 `json:"desire"`
|
||||
Status string `json:"status"`
|
||||
Annotation Annotation `json:"annotations"`
|
||||
UpdateTime time.Time `gorm:"column:updateTime" json:"updateTime,omitempty"`
|
||||
}
|
||||
|
||||
func (Deployment) TableName() string {
|
||||
return tableDeployments
|
||||
}
|
||||
|
||||
type Statefulset struct {
|
||||
Name string `gorm:"primary_key" json:"name,omitempty"`
|
||||
DisplayName string `json:"displayName,omitempty" gorm:"column:displayName"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace,omitempty"`
|
||||
App string `json:"app,omitempty"`
|
||||
Name string `gorm:"primary_key" json:"name,omitempty"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace,omitempty"`
|
||||
App string `json:"app,omitempty"`
|
||||
|
||||
Available int32 `json:"available"`
|
||||
Desire int32 `json:"desire"`
|
||||
Status string `json:"status"`
|
||||
Annotation MapString `json:"annotations"`
|
||||
Labels MapString `json:"labels"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
Available int32 `json:"available"`
|
||||
Desire int32 `json:"desire"`
|
||||
Status string `json:"status"`
|
||||
Annotation Annotation `json:"annotations"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
func (Statefulset) TableName() string {
|
||||
return tableStatefulsets
|
||||
}
|
||||
|
||||
type Daemonset struct {
|
||||
Name string `gorm:"primary_key" json:"name,omitempty"`
|
||||
DisplayName string `json:"displayName,omitempty" gorm:"column:displayName"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace,omitempty"`
|
||||
App string `json:"app,omitempty"`
|
||||
Name string `gorm:"primary_key" json:"name,omitempty"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace,omitempty"`
|
||||
App string `json:"app,omitempty"`
|
||||
|
||||
Available int32 `json:"available"`
|
||||
Desire int32 `json:"desire"`
|
||||
Status string `json:"status"`
|
||||
NodeSelector string `json:"nodeSelector, omitempty"`
|
||||
Annotation MapString `json:"annotations"`
|
||||
Labels MapString `json:"labels"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
Available int32 `json:"available"`
|
||||
Desire int32 `json:"desire"`
|
||||
Status string `json:"status"`
|
||||
NodeSelector string `json:"nodeSelector, omitempty"`
|
||||
Annotation Annotation `json:"annotations"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
func (Daemonset) TableName() string {
|
||||
return tableDaemonsets
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
DisplayName string `json:"displayName,omitempty" gorm:"column:displayName"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
ServiceType string `gorm:"column:type" json:"type,omitempty"`
|
||||
ServiceType string `json:"type,omitempty"`
|
||||
|
||||
App string `json:"app,omitempty"`
|
||||
VirtualIp string `gorm:"column:virtualIp" json:"virtualIp,omitempty"`
|
||||
ExternalIp string `gorm:"column:externalIp" json:"externalIp,omitempty"`
|
||||
VirtualIp string `json:"virtualIp,omitempty"`
|
||||
ExternalIp string `json:"externalIp,omitempty"`
|
||||
|
||||
Ports string `json:"ports,omitempty"`
|
||||
NodePorts string `gorm:"column:nodePorts" json:"nodePorts,omitempty"`
|
||||
Annotation MapString `json:"annotations"`
|
||||
Labels MapString `json:"labels"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
Ports string `json:"ports,omitempty"`
|
||||
NodePorts string `json:"nodePorts,omitempty"`
|
||||
Annotation Annotation `json:"annotations"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
func (Service) TableName() string {
|
||||
return tableServices
|
||||
}
|
||||
|
||||
type Pvc struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
DisplayName string `json:"displayName,omitempty" gorm:"column:displayName"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Capacity string `json:"capacity,omitempty"`
|
||||
AccessMode string `gorm:"column:accessMode" json:"accessMode,omitempty"`
|
||||
Annotation MapString `json:"annotations"`
|
||||
Labels MapString `json:"labels"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
StorageClassName string `gorm:"column:storage_class" json:"storage_class,omitempty"`
|
||||
InUse bool `gorm:"column:inUse" json:"inUse"`
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Capacity string `json:"capacity,omitempty"`
|
||||
AccessMode string `json:"accessMode,omitempty"`
|
||||
Annotation Annotation `json:"annotations"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
StorageClassName string `gorm:"column:storage_class" json:"storage_class,omitempty"`
|
||||
InUse bool `gorm:"-" json:"inUse"`
|
||||
}
|
||||
|
||||
func (Pvc) TableName() string {
|
||||
return tablePersistentVolumeClaim
|
||||
}
|
||||
|
||||
type ingressRule struct {
|
||||
@@ -201,77 +178,30 @@ type ingressRule struct {
|
||||
}
|
||||
|
||||
type Ingress struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
DisplayName string `json:"displayName,omitempty" gorm:"column:displayName"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
Ip string `json:"ip,omitempty"`
|
||||
Rules string `gorm:"type:text" json:"rules, omitempty"`
|
||||
TlsTermination string `gorm:"column:tlsTermination" json:"tlsTermination,omitempty"`
|
||||
Annotation MapString `json:"annotations"`
|
||||
Labels MapString `json:"labels"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
Ip string `json:"ip,omitempty"`
|
||||
Rules string `gorm:"type:text" json:"rules, omitempty"`
|
||||
TlsTermination string `json:"tlsTermination,omitempty"`
|
||||
Annotation Annotation `json:"annotations"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
func (Ingress) TableName() string {
|
||||
return tableIngresses
|
||||
}
|
||||
|
||||
type Pod struct {
|
||||
// search and sort field, not seen in response
|
||||
Name string `gorm:"primary_key" json:"-"`
|
||||
Namespace string `gorm:"primary_key" json:"-"`
|
||||
Node string `json:"-"`
|
||||
OwnerKind string `gorm:"column:ownerKind" json:"-"`
|
||||
OwnerName string `gorm:"column:ownerName" json:"-"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"-"`
|
||||
|
||||
// Kubernetes Standard Pod Specification
|
||||
Kind string `json:"kind,omitempty"`
|
||||
APIVersion string `gorm:"column:apiVersion" json:"apiVersion,omitempty"`
|
||||
Spec v1.PodSpec `sql:"-" json:"spec,omitempty"`
|
||||
Metadata v12.ObjectMeta `sql:"-" json:"metadata,omitempty"`
|
||||
Status v1.PodStatus `sql:"-" json:"status,omitempty"`
|
||||
|
||||
// shadow field, used only for database
|
||||
MetadataString string `gorm:"column:metadata;type:text" json:"-"`
|
||||
SpecString string `gorm:"column:podSpec;type:text" json:"-"`
|
||||
StatusString string `gorm:"column:status;type:text" json:"-"`
|
||||
}
|
||||
|
||||
func (pod *Pod) AfterFind(scope *gorm.Scope) (err error) {
|
||||
|
||||
if err = json.Unmarshal([]byte(pod.SpecString), &pod.Spec); err != nil {
|
||||
glog.Errorln(err)
|
||||
}
|
||||
|
||||
if err = json.Unmarshal([]byte(pod.MetadataString), &pod.Metadata); err != nil {
|
||||
glog.Errorln(err)
|
||||
}
|
||||
|
||||
if err = json.Unmarshal([]byte(pod.StatusString), &pod.Status); err != nil {
|
||||
glog.Errorln(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pod *Pod) BeforeSave(scope *gorm.Scope) (err error) {
|
||||
|
||||
if bytes, err := json.Marshal(pod.Spec); err == nil {
|
||||
pod.SpecString = string(bytes)
|
||||
} else {
|
||||
glog.Errorln(err)
|
||||
}
|
||||
|
||||
if bytes, err := json.Marshal(pod.Metadata); err == nil {
|
||||
pod.MetadataString = string(bytes)
|
||||
} else {
|
||||
glog.Errorln(err)
|
||||
}
|
||||
|
||||
if bytes, err := json.Marshal(pod.Status); err == nil {
|
||||
pod.StatusString = string(bytes)
|
||||
} else {
|
||||
glog.Errorln(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Node string `json:"node,omitempty"`
|
||||
NodeIp string `json:"nodeIp,omitempty"`
|
||||
PodIp string `json:"podIp,omitempty"`
|
||||
Containers Containers `gorm:"type:text" json:"containers,omitempty"`
|
||||
Annotation Annotation `json:"annotations"`
|
||||
RestartCount int `json:"restartCount"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
type Container struct {
|
||||
@@ -300,119 +230,61 @@ func (containers Containers) Value() (driver.Value, error) {
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
func (Pod) TableName() string {
|
||||
return tablePods
|
||||
}
|
||||
|
||||
type Role struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
DisplayName string `json:"displayName,omitempty" gorm:"column:displayName"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
Annotation MapString `json:"annotations"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
Annotation Annotation `json:"annotations"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
func (Role) TableName() string {
|
||||
return tableRoles
|
||||
}
|
||||
|
||||
type ClusterRole struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
DisplayName string `json:"displayName,omitempty" gorm:"column:displayName"`
|
||||
Annotation MapString `json:"annotations"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Annotation Annotation `json:"annotations"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
func (ClusterRole) TableName() string {
|
||||
return tableClusterRoles
|
||||
}
|
||||
|
||||
type Namespace struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
DisplayName string `json:"displayName,omitempty" gorm:"column:displayName"`
|
||||
Creator string `json:"creator,omitempty"`
|
||||
Status string `json:"status"`
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Creator string `json:"creator,omitempty"`
|
||||
Status string `json:"status"`
|
||||
|
||||
Descrition string `json:"description,omitempty"`
|
||||
Annotation MapString `json:"annotations"`
|
||||
Annotation Annotation `json:"annotations"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
Usage v1.ResourceList `gorm:"-" json:"usage,omitempty"`
|
||||
Usaeg v1.ResourceList `gorm:"-" json:"usage,omitempty"`
|
||||
}
|
||||
|
||||
func (Namespace) TableName() string {
|
||||
return tableNamespaces
|
||||
}
|
||||
|
||||
type StorageClass struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
DisplayName string `json:"displayName,omitempty" gorm:"column:displayName"`
|
||||
Creator string `json:"creator,omitempty"`
|
||||
Annotation MapString `json:"annotations"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
IsDefault bool `json:"default"`
|
||||
Count int `json:"count"`
|
||||
Provisioner string `json:"provisioner"`
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Creator string `json:"creator,omitempty"`
|
||||
Annotation Annotation `json:"annotations"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
IsDefault bool `json:"default"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
type JobRevisions map[int]JobRevision
|
||||
|
||||
type JobRevision struct {
|
||||
Status string `json:"status"`
|
||||
Reasons []string `json:"reasons"`
|
||||
Messages []string `json:"messages"`
|
||||
Succeed int32 `json:"succeed"`
|
||||
DesirePodNum int32 `json:"desire"`
|
||||
Failed int32 `json:"failed"`
|
||||
Uid string `json:"uid"`
|
||||
StartTime time.Time `json:"start-time"`
|
||||
CompletionTime time.Time `json:"completion-time"`
|
||||
}
|
||||
|
||||
type Job struct {
|
||||
Name string `gorm:"primary_key" json:"name,omitempty"`
|
||||
DisplayName string `json:"displayName,omitempty" gorm:"column:displayName"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace,omitempty"`
|
||||
|
||||
Completed int32 `json:"completed"`
|
||||
Desire int32 `json:"desire"`
|
||||
Status string `json:"status"`
|
||||
Annotation MapString `json:"annotations"`
|
||||
Labels MapString `json:"labels"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
UpdateTime time.Time `gorm:"column:updateTime" json:"updateTime,omitempty"`
|
||||
}
|
||||
|
||||
type CronJob struct {
|
||||
Name string `gorm:"primary_key" json:"name,omitempty"`
|
||||
DisplayName string `json:"displayName,omitempty" gorm:"column:displayName"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace,omitempty"`
|
||||
|
||||
Active int `json:"active"`
|
||||
Schedule string `json:"schedule"`
|
||||
Status string `json:"status"`
|
||||
Annotation MapString `json:"annotations"`
|
||||
Labels MapString `json:"labels"`
|
||||
LastScheduleTime *time.Time `gorm:"column:lastScheduleTime" json:"lastScheduleTime,omitempty"`
|
||||
}
|
||||
|
||||
type Node struct {
|
||||
Name string `gorm:"primary_key" json:"name,omitempty"`
|
||||
DisplayName string `json:"displayName,omitempty" gorm:"column:displayName"`
|
||||
Ip string `json:"ip"`
|
||||
Status string `json:"status"`
|
||||
Annotation MapString `json:"annotations"`
|
||||
Labels MapString `json:"labels"`
|
||||
Taints Taints `json:"taints"`
|
||||
Msg string `json:"msg"`
|
||||
Role string `json:"role"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
type ConfigMap struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
DisplayName string `json:"displayName,omitempty" gorm:"column:displayName"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
Annotation MapString `json:"annotations"`
|
||||
Entries string `gorm:"type:text" json:"entries"`
|
||||
}
|
||||
|
||||
type Secret struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
DisplayName string `json:"displayName,omitempty" gorm:"column:displayName"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
Annotation MapString `json:"annotations"`
|
||||
Entries int `json:"entries"`
|
||||
Type string `json:"type"`
|
||||
func (StorageClass) TableName() string {
|
||||
return tableStorageClasses
|
||||
}
|
||||
|
||||
type Paging struct {
|
||||
Limit, Offset, Page int
|
||||
Limit, Offset int
|
||||
}
|
||||
|
||||
type Controller interface {
|
||||
@@ -423,9 +295,7 @@ type Controller interface {
|
||||
initListerAndInformer()
|
||||
sync(stopChan chan struct{})
|
||||
Name() string
|
||||
CloseDB()
|
||||
Lister() interface{}
|
||||
ListWithConditions(condition string, paging *Paging, order string) (int, interface{}, error)
|
||||
ListWithConditions(condition string, paging *Paging) (int, interface{}, error)
|
||||
}
|
||||
|
||||
type CommonAttribute struct {
|
||||
@@ -446,11 +316,6 @@ func (ca *CommonAttribute) chanAlive() chan struct{} {
|
||||
return ca.aliveChan
|
||||
}
|
||||
|
||||
func (ca *CommonAttribute) CloseDB() {
|
||||
|
||||
ca.DB.Close()
|
||||
}
|
||||
|
||||
type DeploymentCtl struct {
|
||||
CommonAttribute
|
||||
lister appV1.DeploymentLister
|
||||
@@ -516,56 +381,3 @@ type ClusterRoleCtl struct {
|
||||
informer cache.SharedIndexInformer
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type ClusterRoleBindingCtl struct {
|
||||
lister rbacV1.ClusterRoleBindingLister
|
||||
informer cache.SharedIndexInformer
|
||||
CommonAttribute
|
||||
}
|
||||
type RoleBindingCtl struct {
|
||||
lister rbacV1.RoleBindingLister
|
||||
informer cache.SharedIndexInformer
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type JobCtl struct {
|
||||
lister batchv1.JobLister
|
||||
informer cache.SharedIndexInformer
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type CronJobCtl struct {
|
||||
lister batchv1beta1.CronJobLister
|
||||
informer cache.SharedIndexInformer
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type NodeCtl struct {
|
||||
lister coreV1.NodeLister
|
||||
informer cache.SharedIndexInformer
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type ReplicaSetCtl struct {
|
||||
lister appV1.ReplicaSetLister
|
||||
informer cache.SharedIndexInformer
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type ControllerRevisionCtl struct {
|
||||
lister appV1.ControllerRevisionLister
|
||||
informer cache.SharedIndexInformer
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type ConfigMapCtl struct {
|
||||
lister coreV1.ConfigMapLister
|
||||
informer cache.SharedIndexInformer
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type SecretCtl struct {
|
||||
lister coreV1.SecretLister
|
||||
informer cache.SharedIndexInformer
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
@@ -1,162 +1,18 @@
|
||||
package iam
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/rbac/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
v12 "k8s.io/client-go/listers/rbac/v1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"k8s.io/kubernetes/pkg/util/slice"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/controllers"
|
||||
ksErr "kubesphere.io/kubesphere/pkg/util/errors"
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
const ClusterRoleKind = "ClusterRole"
|
||||
|
||||
// Get user list based on workspace role
|
||||
func WorkspaceRoleUsers(workspace string, roleName string) ([]User, error) {
|
||||
|
||||
lister, err := controllers.GetLister(controllers.ClusterRoleBindings)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clusterRoleBindingLister := lister.(v12.ClusterRoleBindingLister)
|
||||
|
||||
workspaceRoleBinding, err := clusterRoleBindingLister.Get(fmt.Sprintf("system:%s:%s", workspace, roleName))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
names := make([]string, 0)
|
||||
|
||||
for _, subject := range workspaceRoleBinding.Subjects {
|
||||
if subject.Kind == v1.UserKind {
|
||||
names = append(names, subject.Name)
|
||||
}
|
||||
}
|
||||
|
||||
users, err := GetUsers(names)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := 0; i < len(users); i++ {
|
||||
users[i].WorkspaceRole = roleName
|
||||
}
|
||||
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func GetUsers(names []string) ([]User, error) {
|
||||
var users []User
|
||||
|
||||
if names == nil || len(names) == 0 {
|
||||
return make([]User, 0), nil
|
||||
}
|
||||
|
||||
result, err := http.Get(fmt.Sprintf("http://%s/apis/account.kubesphere.io/v1alpha1/users?name=%s", constants.AccountAPIServer, strings.Join(names, ",")))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer result.Body.Close()
|
||||
data, err := ioutil.ReadAll(result.Body)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if result.StatusCode > 200 {
|
||||
return nil, ksErr.Wrap(data)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(data, &users)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func GetUser(name string) (*User, error) {
|
||||
|
||||
result, err := http.Get(fmt.Sprintf("http://%s/apis/account.kubesphere.io/v1alpha1/users/%s", constants.AccountAPIServer, name))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer result.Body.Close()
|
||||
data, err := ioutil.ReadAll(result.Body)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if result.StatusCode > 200 {
|
||||
return nil, ksErr.Wrap(data)
|
||||
}
|
||||
|
||||
var user User
|
||||
|
||||
err = json.Unmarshal(data, &user)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
// Get rules
|
||||
func WorkspaceRoleRules(workspace string, roleName string) (*v1.ClusterRole, []Rule, error) {
|
||||
|
||||
clusterRoleName := fmt.Sprintf("system:%s:%s", workspace, roleName)
|
||||
|
||||
workspaceRole, err := GetClusterRole(clusterRoleName)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
for i := 0; i < len(workspaceRole.Rules); i++ {
|
||||
workspaceRole.Rules[i].ResourceNames = nil
|
||||
}
|
||||
|
||||
rules := make([]Rule, 0)
|
||||
for i := 0; i < len(WorkspaceRoleRuleMapping); i++ {
|
||||
rule := Rule{Name: WorkspaceRoleRuleMapping[i].Name}
|
||||
rule.Actions = make([]Action, 0)
|
||||
for j := 0; j < len(WorkspaceRoleRuleMapping[i].Actions); j++ {
|
||||
if rulesMatchesAction(workspaceRole.Rules, WorkspaceRoleRuleMapping[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, WorkspaceRoleRuleMapping[i].Actions[j])
|
||||
}
|
||||
}
|
||||
if len(rule.Actions) > 0 {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
}
|
||||
|
||||
workspaceRole.Name = roleName
|
||||
|
||||
return workspaceRole, rules, nil
|
||||
}
|
||||
|
||||
func GetUserNamespaces(username string, requiredRule v1.PolicyRule) (allNamespace bool, namespaces []string, err error) {
|
||||
|
||||
clusterRoles, err := GetClusterRoles(username)
|
||||
@@ -171,22 +27,18 @@ func GetUserNamespaces(username string, requiredRule v1.PolicyRule) (allNamespac
|
||||
}
|
||||
|
||||
if requiredRule.Size() == 0 {
|
||||
if RulesMatchesRequired(clusterRules, v1.PolicyRule{
|
||||
Verbs: []string{"get"},
|
||||
APIGroups: []string{"kubesphere.io"},
|
||||
Resources: []string{"workspaces/namespaces"},
|
||||
if ruleValidate(clusterRules, v1.PolicyRule{
|
||||
Verbs: []string{"get", "list"},
|
||||
APIGroups: []string{""},
|
||||
Resources: []string{"namespaces"},
|
||||
}) {
|
||||
return true, nil, nil
|
||||
}
|
||||
} else {
|
||||
|
||||
if RulesMatchesRequired(clusterRules, requiredRule) {
|
||||
return true, nil, nil
|
||||
}
|
||||
|
||||
} else if ruleValidate(clusterRules, requiredRule) {
|
||||
return true, nil, nil
|
||||
}
|
||||
|
||||
roles, err := GetRoles("", username)
|
||||
roles, err := GetRoles(username)
|
||||
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
@@ -206,7 +58,7 @@ func GetUserNamespaces(username string, requiredRule v1.PolicyRule) (allNamespac
|
||||
namespaces = make([]string, 0)
|
||||
|
||||
for namespace, rules := range rulesMapping {
|
||||
if requiredRule.Size() == 0 || RulesMatchesRequired(rules, requiredRule) {
|
||||
if requiredRule.Size() == 0 || ruleValidate(rules, requiredRule) {
|
||||
namespaces = append(namespaces, namespace)
|
||||
}
|
||||
}
|
||||
@@ -214,55 +66,70 @@ func GetUserNamespaces(username string, requiredRule v1.PolicyRule) (allNamespac
|
||||
return false, namespaces, nil
|
||||
}
|
||||
|
||||
func GetRole(namespace string, name string) (*v1.Role, error) {
|
||||
lister, err := controllers.GetLister(controllers.Roles)
|
||||
func DeleteRoleBindings(username string) error {
|
||||
k8s := client.NewK8sClient()
|
||||
|
||||
roleBindings, err := k8s.RbacV1().RoleBindings("").List(meta_v1.ListOptions{})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
roleLister := lister.(v12.RoleLister)
|
||||
role, err := roleLister.Roles(namespace).Get(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return role.DeepCopy(), nil
|
||||
}
|
||||
func GetWorkspaceUsers(workspace string, workspaceRole string) ([]string, error) {
|
||||
for _, roleBinding := range roleBindings.Items {
|
||||
|
||||
lister, err := controllers.GetLister(controllers.ClusterRoleBindings)
|
||||
length1 := len(roleBinding.Subjects)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for index, subject := range roleBinding.Subjects {
|
||||
if subject.Kind == v1.UserKind && subject.Name == username {
|
||||
roleBinding.Subjects = append(roleBinding.Subjects[:index], roleBinding.Subjects[index+1:]...)
|
||||
index--
|
||||
}
|
||||
}
|
||||
|
||||
clusterRoleBindingLister := lister.(v12.ClusterRoleBindingLister)
|
||||
clusterRoleBinding, err := clusterRoleBindingLister.Get(fmt.Sprintf("system:%s:%s", workspace, workspaceRole))
|
||||
length2 := len(roleBinding.Subjects)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
users := make([]string, 0)
|
||||
|
||||
for _, s := range clusterRoleBinding.Subjects {
|
||||
if s.Kind == v1.UserKind && !slice.ContainsString(users, s.Name, nil) {
|
||||
users = append(users, s.Name)
|
||||
if length2 == 0 {
|
||||
k8s.RbacV1().RoleBindings(roleBinding.Namespace).Delete(roleBinding.Name, &meta_v1.DeleteOptions{})
|
||||
} else if length2 < length1 {
|
||||
k8s.RbacV1().RoleBindings(roleBinding.Namespace).Update(&roleBinding)
|
||||
}
|
||||
}
|
||||
return users, nil
|
||||
|
||||
clusterRoleBindingList, err := k8s.RbacV1().ClusterRoleBindings().List(meta_v1.ListOptions{})
|
||||
|
||||
for _, roleBinding := range clusterRoleBindingList.Items {
|
||||
length1 := len(roleBinding.Subjects)
|
||||
|
||||
for index, subject := range roleBinding.Subjects {
|
||||
if subject.Kind == v1.UserKind && subject.Name == username {
|
||||
roleBinding.Subjects = append(roleBinding.Subjects[:index], roleBinding.Subjects[index+1:]...)
|
||||
index--
|
||||
}
|
||||
}
|
||||
|
||||
length2 := len(roleBinding.Subjects)
|
||||
if length2 == 0 {
|
||||
k8s.RbacV1().ClusterRoleBindings().Delete(roleBinding.Name, &meta_v1.DeleteOptions{})
|
||||
} else if length2 < length1 {
|
||||
k8s.RbacV1().ClusterRoleBindings().Update(&roleBinding)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetRole(namespace string, name string) (*v1.Role, error) {
|
||||
k8s := client.NewK8sClient()
|
||||
role, err := k8s.RbacV1().Roles(namespace).Get(name, meta_v1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return role, nil
|
||||
}
|
||||
|
||||
func GetClusterRoleBindings(name string) ([]v1.ClusterRoleBinding, error) {
|
||||
lister, err := controllers.GetLister(controllers.ClusterRoleBindings)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clusterRoleBindingLister := lister.(v12.ClusterRoleBindingLister)
|
||||
|
||||
clusterRoleBindings, err := clusterRoleBindingLister.List(labels.Everything())
|
||||
k8s := client.NewK8sClient()
|
||||
roleBindingList, err := k8s.RbacV1().ClusterRoleBindings().List(meta_v1.ListOptions{})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -270,9 +137,9 @@ func GetClusterRoleBindings(name string) ([]v1.ClusterRoleBinding, error) {
|
||||
|
||||
items := make([]v1.ClusterRoleBinding, 0)
|
||||
|
||||
for _, clusterRoleBinding := range clusterRoleBindings {
|
||||
if clusterRoleBinding.RoleRef.Name == name {
|
||||
items = append(items, *clusterRoleBinding)
|
||||
for _, roleBinding := range roleBindingList.Items {
|
||||
if roleBinding.RoleRef.Name == name {
|
||||
items = append(items, roleBinding)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,15 +147,9 @@ func GetClusterRoleBindings(name string) ([]v1.ClusterRoleBinding, error) {
|
||||
}
|
||||
|
||||
func GetRoleBindings(namespace string, name string) ([]v1.RoleBinding, error) {
|
||||
lister, err := controllers.GetLister(controllers.RoleBindings)
|
||||
k8s := client.NewK8sClient()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
roleBindingLister := lister.(v12.RoleBindingLister)
|
||||
|
||||
roleBindings, err := roleBindingLister.RoleBindings(namespace).List(labels.Everything())
|
||||
roleBindingList, err := k8s.RbacV1().RoleBindings(namespace).List(meta_v1.ListOptions{})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -296,9 +157,9 @@ func GetRoleBindings(namespace string, name string) ([]v1.RoleBinding, error) {
|
||||
|
||||
items := make([]v1.RoleBinding, 0)
|
||||
|
||||
for _, roleBinding := range roleBindings {
|
||||
for _, roleBinding := range roleBindingList.Items {
|
||||
if roleBinding.RoleRef.Name == name {
|
||||
items = append(items, *roleBinding)
|
||||
items = append(items, roleBinding)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,61 +167,30 @@ func GetRoleBindings(namespace string, name string) ([]v1.RoleBinding, error) {
|
||||
}
|
||||
|
||||
func GetClusterRole(name string) (*v1.ClusterRole, error) {
|
||||
lister, err := controllers.GetLister(controllers.ClusterRoles)
|
||||
|
||||
k8s := client.NewK8sClient()
|
||||
role, err := k8s.RbacV1().ClusterRoles().Get(name, meta_v1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clusterRoleLister := lister.(v12.ClusterRoleLister)
|
||||
|
||||
role, err := clusterRoleLister.Get(name)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return role.DeepCopy(), nil
|
||||
return role, nil
|
||||
}
|
||||
|
||||
func GetRoles(namespace string, username string) ([]v1.Role, error) {
|
||||
lister, err := controllers.GetLister(controllers.RoleBindings)
|
||||
func GetRoles(username string) ([]v1.Role, error) {
|
||||
k8s := client.NewK8sClient()
|
||||
|
||||
roleBindings, err := k8s.RbacV1().RoleBindings("").List(meta_v1.ListOptions{})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
roleBindingLister := lister.(v12.RoleBindingLister)
|
||||
|
||||
lister, err = controllers.GetLister(controllers.Roles)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
roleLister := lister.(v12.RoleLister)
|
||||
|
||||
lister, err = controllers.GetLister(controllers.ClusterRoles)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clusterRoleLister := lister.(v12.ClusterRoleLister)
|
||||
|
||||
roleBindings, err := roleBindingLister.RoleBindings(namespace).List(labels.Everything())
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
roles := make([]v1.Role, 0)
|
||||
|
||||
for _, roleBinding := range roleBindings {
|
||||
for _, roleBinding := range roleBindings.Items {
|
||||
|
||||
for _, subject := range roleBinding.Subjects {
|
||||
if subject.Kind == v1.UserKind && subject.Name == username {
|
||||
if roleBinding.RoleRef.Kind == ClusterRoleKind {
|
||||
clusterRole, err := clusterRoleLister.Get(roleBinding.RoleRef.Name)
|
||||
clusterRole, err := k8s.RbacV1().ClusterRoles().Get(roleBinding.RoleRef.Name, meta_v1.GetOptions{})
|
||||
if err == nil {
|
||||
var role = v1.Role{TypeMeta: (*clusterRole).TypeMeta, ObjectMeta: (*clusterRole).ObjectMeta, Rules: (*clusterRole).Rules}
|
||||
role.Namespace = roleBinding.Namespace
|
||||
@@ -375,9 +205,9 @@ func GetRoles(namespace string, username string) ([]v1.Role, error) {
|
||||
|
||||
} else {
|
||||
if subject.Kind == v1.UserKind && subject.Name == username {
|
||||
role, err := roleLister.Roles(roleBinding.Namespace).Get(roleBinding.RoleRef.Name)
|
||||
rule, err := k8s.RbacV1().Roles(roleBinding.Namespace).Get(roleBinding.RoleRef.Name, meta_v1.GetOptions{})
|
||||
if err == nil {
|
||||
roles = append(roles, *role)
|
||||
roles = append(roles, *rule)
|
||||
break
|
||||
} else if apierrors.IsNotFound(err) {
|
||||
glog.Infoln(err.Error())
|
||||
@@ -397,26 +227,10 @@ func GetRoles(namespace string, username string) ([]v1.Role, error) {
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
// Get cluster roles by username
|
||||
func GetClusterRoles(username string) ([]v1.ClusterRole, error) {
|
||||
k8s := client.NewK8sClient()
|
||||
|
||||
lister, err := controllers.GetLister(controllers.ClusterRoleBindings)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clusterRoleBindingLister := lister.(v12.ClusterRoleBindingLister)
|
||||
|
||||
lister, err = controllers.GetLister(controllers.ClusterRoles)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clusterRoleLister := lister.(v12.ClusterRoleLister)
|
||||
|
||||
clusterRoleBindings, err := clusterRoleBindingLister.List(labels.Everything())
|
||||
clusterRoleBindings, err := k8s.RbacV1().ClusterRoleBindings().List(meta_v1.ListOptions{})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -424,25 +238,20 @@ func GetClusterRoles(username string) ([]v1.ClusterRole, error) {
|
||||
|
||||
roles := make([]v1.ClusterRole, 0)
|
||||
|
||||
for _, roleBinding := range clusterRoleBindings {
|
||||
for _, roleBinding := range clusterRoleBindings.Items {
|
||||
for _, subject := range roleBinding.Subjects {
|
||||
if subject.Kind == v1.UserKind && subject.Name == username {
|
||||
if roleBinding.RoleRef.Kind == ClusterRoleKind {
|
||||
role, err := clusterRoleLister.Get(roleBinding.RoleRef.Name)
|
||||
role, err := k8s.RbacV1().ClusterRoles().Get(roleBinding.RoleRef.Name, meta_v1.GetOptions{})
|
||||
if err == nil {
|
||||
role = role.DeepCopy()
|
||||
if role.Annotations == nil {
|
||||
role.Annotations = make(map[string]string, 0)
|
||||
}
|
||||
role.Annotations["rbac.authorization.k8s.io/clusterrolebinding"] = roleBinding.Name
|
||||
if roleBinding.Annotations != nil &&
|
||||
roleBinding.Annotations["rbac.authorization.k8s.io/clusterrole"] == roleBinding.RoleRef.Name {
|
||||
role.Annotations["rbac.authorization.k8s.io/clusterrole"] = "true"
|
||||
}
|
||||
roles = append(roles, *role)
|
||||
break
|
||||
} else if apierrors.IsNotFound(err) {
|
||||
glog.Warning(err)
|
||||
glog.Infoln(err.Error())
|
||||
break
|
||||
} else {
|
||||
return nil, err
|
||||
@@ -455,189 +264,34 @@ func GetClusterRoles(username string) ([]v1.ClusterRole, error) {
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
func GetUserRules(username string) (map[string][]Rule, error) {
|
||||
func ruleValidate(rules []v1.PolicyRule, rule v1.PolicyRule) bool {
|
||||
|
||||
items := make(map[string][]Rule, 0)
|
||||
userRoles, err := GetRoles("", username)
|
||||
for _, apiGroup := range rule.APIGroups {
|
||||
if len(rule.NonResourceURLs) == 0 {
|
||||
for _, resource := range rule.Resources {
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//if len(Rule.ResourceNames) == 0 {
|
||||
|
||||
rulesMapping := make(map[string][]v1.PolicyRule, 0)
|
||||
|
||||
for _, role := range userRoles {
|
||||
rules := rulesMapping[role.Namespace]
|
||||
if rules == nil {
|
||||
rules = make([]v1.PolicyRule, 0)
|
||||
}
|
||||
rules = append(rules, role.Rules...)
|
||||
rulesMapping[role.Namespace] = rules
|
||||
}
|
||||
|
||||
for namespace, policyRules := range rulesMapping {
|
||||
rules := convertToRules(policyRules)
|
||||
if len(rules) > 0 {
|
||||
items[namespace] = rules
|
||||
}
|
||||
}
|
||||
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func convertToRules(policyRules []v1.PolicyRule) []Rule {
|
||||
rules := make([]Rule, 0)
|
||||
|
||||
for i := 0; i < (len(RoleRuleMapping)); i++ {
|
||||
rule := Rule{Name: RoleRuleMapping[i].Name}
|
||||
rule.Actions = make([]Action, 0)
|
||||
for j := 0; j < (len(RoleRuleMapping[i].Actions)); j++ {
|
||||
if rulesMatchesAction(policyRules, RoleRuleMapping[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, RoleRuleMapping[i].Actions[j])
|
||||
}
|
||||
}
|
||||
|
||||
if len(rule.Actions) > 0 {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
}
|
||||
|
||||
return rules
|
||||
}
|
||||
|
||||
func GetUserClusterRules(username string) ([]Rule, error) {
|
||||
|
||||
rules := make([]Rule, 0)
|
||||
|
||||
clusterRoles, err := GetClusterRoles(username)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clusterRules := make([]v1.PolicyRule, 0)
|
||||
|
||||
for _, role := range clusterRoles {
|
||||
clusterRules = append(clusterRules, role.Rules...)
|
||||
}
|
||||
|
||||
for i := 0; i < (len(ClusterRoleRuleMapping)); i++ {
|
||||
rule := Rule{Name: ClusterRoleRuleMapping[i].Name}
|
||||
rule.Actions = make([]Action, 0)
|
||||
for j := 0; j < (len(ClusterRoleRuleMapping[i].Actions)); j++ {
|
||||
if rulesMatchesAction(clusterRules, ClusterRoleRuleMapping[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, ClusterRoleRuleMapping[i].Actions[j])
|
||||
}
|
||||
}
|
||||
if len(rule.Actions) > 0 {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
}
|
||||
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func GetClusterRoleRules(name string) ([]Rule, error) {
|
||||
|
||||
clusterRole, err := GetClusterRole(name)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rules := make([]Rule, 0)
|
||||
|
||||
for i := 0; i < len(ClusterRoleRuleMapping); i++ {
|
||||
rule := Rule{Name: ClusterRoleRuleMapping[i].Name}
|
||||
rule.Actions = make([]Action, 0)
|
||||
for j := 0; j < (len(ClusterRoleRuleMapping[i].Actions)); j++ {
|
||||
if rulesMatchesAction(clusterRole.Rules, ClusterRoleRuleMapping[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, ClusterRoleRuleMapping[i].Actions[j])
|
||||
}
|
||||
}
|
||||
if len(rule.Actions) > 0 {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
}
|
||||
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func GetRoleRules(namespace string, name string) ([]Rule, error) {
|
||||
role, err := GetRole(namespace, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rules := make([]Rule, 0)
|
||||
for i := 0; i < len(RoleRuleMapping); i++ {
|
||||
rule := Rule{Name: RoleRuleMapping[i].Name}
|
||||
rule.Actions = make([]Action, 0)
|
||||
for j := 0; j < len(RoleRuleMapping[i].Actions); j++ {
|
||||
if rulesMatchesAction(role.Rules, RoleRuleMapping[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, RoleRuleMapping[i].Actions[j])
|
||||
}
|
||||
}
|
||||
if len(rule.Actions) > 0 {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
}
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func rulesMatchesAction(rules []v1.PolicyRule, action Action) bool {
|
||||
|
||||
for _, rule := range action.Rules {
|
||||
if !RulesMatchesRequired(rules, rule) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func RulesMatchesRequired(rules []v1.PolicyRule, required v1.PolicyRule) bool {
|
||||
for _, rule := range rules {
|
||||
if ruleMatchesRequired(rule, required) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func ruleMatchesRequired(rule v1.PolicyRule, required v1.PolicyRule) bool {
|
||||
|
||||
if len(required.NonResourceURLs) == 0 {
|
||||
for _, apiGroup := range required.APIGroups {
|
||||
for _, resource := range required.Resources {
|
||||
resources := strings.Split(resource, "/")
|
||||
resource = resources[0]
|
||||
var subsource string
|
||||
if len(resources) > 1 {
|
||||
subsource = resources[1]
|
||||
}
|
||||
|
||||
if len(required.ResourceNames) == 0 {
|
||||
for _, verb := range required.Verbs {
|
||||
if !ruleMatchesRequest(rule, apiGroup, "", resource, subsource, "", verb) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, resourceName := range required.ResourceNames {
|
||||
for _, verb := range required.Verbs {
|
||||
if !ruleMatchesRequest(rule, apiGroup, "", resource, subsource, resourceName, verb) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for _, verb := range rule.Verbs {
|
||||
if !verbValidate(rules, apiGroup, "", resource, "", verb) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
//} else {
|
||||
// for _, resourceName := range Rule.ResourceNames {
|
||||
// for _, verb := range Rule.Verbs {
|
||||
// if !verbValidate(rules, apiGroup, "", resource, resourceName, verb) {
|
||||
// return false
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, apiGroup := range required.APIGroups {
|
||||
for _, nonResourceURL := range required.NonResourceURLs {
|
||||
for _, verb := range required.Verbs {
|
||||
if !ruleMatchesRequest(rule, apiGroup, nonResourceURL, "", "", "", verb) {
|
||||
} else {
|
||||
for _, nonResourceURL := range rule.NonResourceURLs {
|
||||
for _, verb := range rule.Verbs {
|
||||
if !verbValidate(rules, apiGroup, nonResourceURL, "", "", verb) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -647,94 +301,22 @@ func ruleMatchesRequired(rule v1.PolicyRule, required v1.PolicyRule) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func ruleMatchesResources(rule v1.PolicyRule, apiGroup string, resource string, subresource string, resourceName string) bool {
|
||||
|
||||
if resource == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
if !hasString(rule.APIGroups, apiGroup) && !hasString(rule.APIGroups, v1.ResourceAll) {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(rule.ResourceNames) > 0 && !hasString(rule.ResourceNames, resourceName) {
|
||||
return false
|
||||
}
|
||||
|
||||
combinedResource := resource
|
||||
|
||||
if subresource != "" {
|
||||
combinedResource = combinedResource + "/" + subresource
|
||||
}
|
||||
|
||||
for _, res := range rule.Resources {
|
||||
|
||||
// match "*"
|
||||
if res == v1.ResourceAll || res == combinedResource {
|
||||
return true
|
||||
}
|
||||
|
||||
// match "*/subresource"
|
||||
if len(subresource) > 0 && strings.HasPrefix(res, "*/") && subresource == strings.TrimLeft(res, "*/") {
|
||||
return true
|
||||
}
|
||||
// match "resource/*"
|
||||
if strings.HasSuffix(res, "/*") && resource == strings.TrimRight(res, "/*") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func ruleMatchesRequest(rule v1.PolicyRule, apiGroup string, nonResourceURL string, resource string, subresource string, resourceName string, verb string) bool {
|
||||
|
||||
if !hasString(rule.Verbs, verb) && !hasString(rule.Verbs, v1.VerbAll) {
|
||||
return false
|
||||
}
|
||||
|
||||
if nonResourceURL == "" {
|
||||
return ruleMatchesResources(rule, apiGroup, resource, subresource, resourceName)
|
||||
} else {
|
||||
return ruleMatchesNonResource(rule, nonResourceURL)
|
||||
}
|
||||
}
|
||||
|
||||
func ruleMatchesNonResource(rule v1.PolicyRule, nonResourceURL string) bool {
|
||||
|
||||
if nonResourceURL == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, spec := range rule.NonResourceURLs {
|
||||
if pathMatches(nonResourceURL, spec) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func pathMatches(path, spec string) bool {
|
||||
// Allow wildcard match
|
||||
if spec == "*" {
|
||||
return true
|
||||
}
|
||||
// Allow exact match
|
||||
if spec == path {
|
||||
return true
|
||||
}
|
||||
// Allow a trailing * subpath match
|
||||
if strings.HasSuffix(spec, "*") && strings.HasPrefix(path, strings.TrimRight(spec, "*")) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func hasString(slice []string, value string) bool {
|
||||
for _, s := range slice {
|
||||
if s == value {
|
||||
return true
|
||||
func verbValidate(rules []v1.PolicyRule, apiGroup string, nonResourceURL string, resource string, resourceName string, verb string) bool {
|
||||
for _, rule := range rules {
|
||||
if slice.ContainsString(rule.APIGroups, apiGroup, nil) || slice.ContainsString(rule.APIGroups, v1.APIGroupAll, nil) {
|
||||
if slice.ContainsString(rule.Verbs, verb, nil) || slice.ContainsString(rule.Verbs, v1.VerbAll, nil) {
|
||||
if nonResourceURL == "" {
|
||||
if slice.ContainsString(rule.Resources, resource, nil) || slice.ContainsString(rule.Resources, v1.ResourceAll, nil) {
|
||||
if resourceName == "" {
|
||||
return true
|
||||
} else if slice.ContainsString(rule.ResourceNames, resourceName, nil) || slice.ContainsString(rule.Resources, v1.ResourceAll, nil) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
} else if slice.ContainsString(rule.NonResourceURLs, nonResourceURL, nil) || slice.ContainsString(rule.NonResourceURLs, v1.NonResourceAll, nil) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
161
pkg/models/iam/tools.go
Normal file
161
pkg/models/iam/tools.go
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
package iam
|
||||
|
||||
import (
|
||||
"k8s.io/api/rbac/v1"
|
||||
)
|
||||
|
||||
func GetUserRules(username string) (map[string][]Rule, error) {
|
||||
|
||||
items := make(map[string][]Rule, 0)
|
||||
userRoles, err := GetRoles(username)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rulesMapping := make(map[string][]v1.PolicyRule, 0)
|
||||
|
||||
for _, role := range userRoles {
|
||||
rules := rulesMapping[role.Namespace]
|
||||
if rules == nil {
|
||||
rules = make([]v1.PolicyRule, 0)
|
||||
}
|
||||
rules = append(rules, role.Rules...)
|
||||
rulesMapping[role.Namespace] = rules
|
||||
}
|
||||
|
||||
for namespace, policyRules := range rulesMapping {
|
||||
rules := convertToRules(policyRules)
|
||||
if len(rules) > 0 {
|
||||
items[namespace] = rules
|
||||
}
|
||||
}
|
||||
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func convertToRules(policyRules []v1.PolicyRule) []Rule {
|
||||
rules := make([]Rule, 0)
|
||||
|
||||
for i := 0; i < (len(RoleRuleGroup)); i++ {
|
||||
rule := Rule{Name: RoleRuleGroup[i].Name}
|
||||
rule.Actions = make([]Action, 0)
|
||||
for j := 0; j < (len(RoleRuleGroup[i].Actions)); j++ {
|
||||
if actionValidate(policyRules, RoleRuleGroup[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, RoleRuleGroup[i].Actions[j])
|
||||
}
|
||||
}
|
||||
|
||||
if len(rule.Actions) > 0 {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
}
|
||||
|
||||
return rules
|
||||
}
|
||||
|
||||
func GetUserClusterRules(username string) ([]Rule, error) {
|
||||
|
||||
rules := make([]Rule, 0)
|
||||
|
||||
clusterRoles, err := GetClusterRoles(username)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clusterRules := make([]v1.PolicyRule, 0)
|
||||
|
||||
for _, role := range clusterRoles {
|
||||
clusterRules = append(clusterRules, role.Rules...)
|
||||
}
|
||||
|
||||
for i := 0; i < (len(ClusterRoleRuleGroup)); i++ {
|
||||
rule := Rule{Name: ClusterRoleRuleGroup[i].Name}
|
||||
rule.Actions = make([]Action, 0)
|
||||
for j := 0; j < (len(ClusterRoleRuleGroup[i].Actions)); j++ {
|
||||
if actionValidate(clusterRules, ClusterRoleRuleGroup[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, ClusterRoleRuleGroup[i].Actions[j])
|
||||
}
|
||||
}
|
||||
if len(rule.Actions) > 0 {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
}
|
||||
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func GetClusterRoleRules(name string) ([]Rule, error) {
|
||||
|
||||
clusterRole, err := GetClusterRole(name)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rules := make([]Rule, 0)
|
||||
|
||||
for i := 0; i < len(ClusterRoleRuleGroup); i++ {
|
||||
rule := Rule{Name: ClusterRoleRuleGroup[i].Name}
|
||||
rule.Actions = make([]Action, 0)
|
||||
for j := 0; j < (len(ClusterRoleRuleGroup[i].Actions)); j++ {
|
||||
if actionValidate(clusterRole.Rules, ClusterRoleRuleGroup[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, ClusterRoleRuleGroup[i].Actions[j])
|
||||
}
|
||||
}
|
||||
if len(rule.Actions) > 0 {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
}
|
||||
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func GetRoleRules(namespace string, name string) ([]Rule, error) {
|
||||
role, err := GetRole(namespace, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rules := make([]Rule, 0)
|
||||
for i := 0; i < len(RoleRuleGroup); i++ {
|
||||
rule := Rule{Name: RoleRuleGroup[i].Name}
|
||||
rule.Actions = make([]Action, 0)
|
||||
for j := 0; j < len(RoleRuleGroup[i].Actions); j++ {
|
||||
if actionValidate(role.Rules, RoleRuleGroup[i].Actions[j]) {
|
||||
rule.Actions = append(rule.Actions, RoleRuleGroup[i].Actions[j])
|
||||
}
|
||||
}
|
||||
if len(rule.Actions) > 0 {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
}
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func actionValidate(rules []v1.PolicyRule, action Action) bool {
|
||||
for _, rule := range action.Rules {
|
||||
if !ruleValidate(rules, rule) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package iam
|
||||
|
||||
import (
|
||||
"k8s.io/api/rbac/v1"
|
||||
)
|
||||
|
||||
type Action struct {
|
||||
Name string `json:"name"`
|
||||
Rules []v1.PolicyRule `json:"rules"`
|
||||
}
|
||||
|
||||
type Rule struct {
|
||||
Name string `json:"name"`
|
||||
Actions []Action `json:"actions"`
|
||||
}
|
||||
|
||||
type SimpleRule struct {
|
||||
Name string `json:"name"`
|
||||
Actions []string `json:"actions"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Username string `json:"username"`
|
||||
Groups []string `json:"groups"`
|
||||
Password string `json:"password,omitempty"`
|
||||
AvatarUrl string `json:"avatar_url"`
|
||||
Description string `json:"description"`
|
||||
Email string `json:"email"`
|
||||
LastLoginTime string `json:"last_login_time"`
|
||||
Status int `json:"status"`
|
||||
ClusterRole string `json:"cluster_role"`
|
||||
ClusterRules []SimpleRule `json:"cluster_rules,omitempty"`
|
||||
Roles map[string]string `json:"roles,omitempty"`
|
||||
Rules map[string][]SimpleRule `json:"rules,omitempty"`
|
||||
Role string `json:"role,omitempty"`
|
||||
WorkspaceRoles map[string]string `json:"workspace_roles,omitempty"`
|
||||
WorkspaceRole string `json:"workspace_role,omitempty"`
|
||||
WorkspaceRules map[string][]SimpleRule `json:"workspace_rules,omitempty"`
|
||||
}
|
||||
@@ -29,23 +29,15 @@ import (
|
||||
"k8s.io/api/core/v1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"crypto/tls"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
kubeclient "kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
)
|
||||
|
||||
const (
|
||||
TYPE = "kubernetes.io/dockerconfigjson"
|
||||
SECRET = "Secret"
|
||||
APIVERSION = "v1"
|
||||
TYPEHARBOR = "harbor"
|
||||
TYPEDOCKERHUB = "dockerhub"
|
||||
TYPEDOCKERREGISTRY = "docker-registry"
|
||||
)
|
||||
const TYPE = "kubernetes.io/dockerconfigjson"
|
||||
|
||||
const SECRET = "Secret"
|
||||
|
||||
const APIVERSION = "v1"
|
||||
|
||||
type AuthInfo struct {
|
||||
Username string `json:"username"`
|
||||
@@ -53,50 +45,6 @@ type AuthInfo struct {
|
||||
ServerHost string `json:"serverhost"`
|
||||
}
|
||||
|
||||
type DockerConfigEntry struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Auth string `json:"auth"`
|
||||
}
|
||||
|
||||
type RegistryInfo struct {
|
||||
user, password, registryType, url string
|
||||
}
|
||||
|
||||
type dockerConfig map[string]map[string]DockerConfigEntry
|
||||
|
||||
type harborRepo struct {
|
||||
RepoName string `json:"repository_name"`
|
||||
}
|
||||
|
||||
type harborRepos struct {
|
||||
Repos []harborRepo `json:"repository"`
|
||||
}
|
||||
|
||||
type registryRepos struct {
|
||||
Repositories []string
|
||||
}
|
||||
|
||||
type registryTags struct {
|
||||
Name string `json:"name"`
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
type dockerhubRepo struct {
|
||||
RepoName string `json:"repo_name"`
|
||||
}
|
||||
type dockerhubRepos struct {
|
||||
Repositories []dockerhubRepo `json:"results"`
|
||||
}
|
||||
|
||||
type dockerhubTag struct {
|
||||
TagName string `json:"name"`
|
||||
}
|
||||
|
||||
type dockerhubTags struct {
|
||||
Tags []dockerhubTag `json:"results"`
|
||||
}
|
||||
|
||||
func NewAuthInfo(para Registries) *AuthInfo {
|
||||
|
||||
return &AuthInfo{
|
||||
@@ -492,237 +440,3 @@ func GetReisgtries(name string) (Registries, error) {
|
||||
return reg, nil
|
||||
|
||||
}
|
||||
|
||||
// by image secret to get registry'info, like username, password, registry url ...
|
||||
func getRegistryInfo(namespace, registryName string) *RegistryInfo {
|
||||
|
||||
var registry RegistryInfo
|
||||
k8sClient := kubeclient.NewK8sClient()
|
||||
secret, err := k8sClient.CoreV1().Secrets(namespace).Get(registryName, meta_v1.GetOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
registry.registryType = secret.Annotations["type"]
|
||||
|
||||
data := secret.Data[v1.DockerConfigJsonKey]
|
||||
|
||||
authsMap := make(dockerConfig)
|
||||
err = json.Unmarshal(data, &authsMap)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
for url, config := range authsMap["auths"] {
|
||||
registry.url = url
|
||||
registry.user = config.Username
|
||||
registry.password = config.Password
|
||||
break
|
||||
}
|
||||
|
||||
return ®istry
|
||||
}
|
||||
|
||||
func ImageSearch(namespace, registryName, searchWord string) []string {
|
||||
registry := getRegistryInfo(namespace, registryName)
|
||||
if registry == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch registry.registryType {
|
||||
case TYPEDOCKERHUB:
|
||||
return searchDockerHub(registry.url, searchWord)
|
||||
case TYPEDOCKERREGISTRY:
|
||||
return searchDockerRegistry(registry.url, searchWord)
|
||||
case TYPEHARBOR:
|
||||
return searchHarbor(registry.url, registry.user, registry.password, searchWord)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetImageTags(namespace, registryName, imageName string) []string {
|
||||
registry := getRegistryInfo(namespace, registryName)
|
||||
if registry == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch registry.registryType {
|
||||
case TYPEDOCKERHUB:
|
||||
return getTagInDockerHub(registry.url, imageName)
|
||||
case TYPEDOCKERREGISTRY:
|
||||
return getTagInDockerRegistry(registry.url, imageName)
|
||||
case TYPEHARBOR:
|
||||
return getTagInHarbor(registry.url, registry.user, registry.password, imageName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func httpGet(url, username, password string, insecure bool) ([]byte, error) {
|
||||
var httpClient *http.Client
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if insecure {
|
||||
httpClient = &http.Client{}
|
||||
} else {
|
||||
req.SetBasicAuth(username, password)
|
||||
tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
|
||||
httpClient = &http.Client{Timeout: 20 * time.Second, Transport: tr}
|
||||
}
|
||||
|
||||
resp, err := httpClient.Do(req)
|
||||
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Request to %s failed reason: %s ", url, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode >= http.StatusBadRequest || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
|
||||
func searchHarbor(url, username, password, searchWord string) []string {
|
||||
url = strings.TrimSuffix(url, "/") + fmt.Sprintf("/api/search?q=%s", searchWord)
|
||||
|
||||
body, err := httpGet(url, username, password, false)
|
||||
if err != nil || len(body) == 0 {
|
||||
glog.Error(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
var repos harborRepos
|
||||
repoList := make([]string, 0, 100)
|
||||
err = json.Unmarshal(body, &repos)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, repo := range repos.Repos {
|
||||
repoList = append(repoList, repo.RepoName)
|
||||
}
|
||||
|
||||
return repoList
|
||||
}
|
||||
|
||||
func searchDockerRegistry(url, searchword string) []string {
|
||||
url = strings.TrimSuffix(url, "/") + "/v2/_catalog"
|
||||
body, err := httpGet(url, "", "", true)
|
||||
if err != nil || len(body) == 0 {
|
||||
glog.Error(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
var repos registryRepos
|
||||
err = json.Unmarshal(body, &repos)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
repoList := make([]string, 0, 100)
|
||||
for _, repo := range repos.Repositories {
|
||||
if strings.HasPrefix(repo, searchword) {
|
||||
repoList = append(repoList, repo)
|
||||
}
|
||||
}
|
||||
|
||||
return repoList
|
||||
}
|
||||
|
||||
func searchDockerHub(url, searchWord string) []string {
|
||||
url = fmt.Sprintf("https://hub.docker.com/v2/search/repositories/?page=1&query=%s&page_size=50", searchWord)
|
||||
body, err := httpGet(url, "", "", true)
|
||||
if err != nil || len(body) == 0 {
|
||||
glog.Error(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
var repos dockerhubRepos
|
||||
err = json.Unmarshal(body, &repos)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
repoList := make([]string, 0, 50)
|
||||
for _, repo := range repos.Repositories {
|
||||
repoList = append(repoList, repo.RepoName)
|
||||
}
|
||||
|
||||
return repoList
|
||||
}
|
||||
|
||||
func getTagInHarbor(url, username, password, imageName string) []string {
|
||||
url = strings.TrimSuffix(url, "/") + fmt.Sprintf("/api/repositories/%s/tags", imageName)
|
||||
body, err := httpGet(url, username, password, false)
|
||||
if err != nil || len(body) == 0 {
|
||||
glog.Error(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
var tagList []string
|
||||
err = json.Unmarshal(body, &tagList)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
return tagList
|
||||
}
|
||||
|
||||
func getTagInDockerRegistry(url, imageName string) []string {
|
||||
url = strings.TrimSuffix(url, "/") + fmt.Sprintf("/v2/%s/tags/list", imageName)
|
||||
body, err := httpGet(url, "", "", true)
|
||||
if err != nil || len(body) == 0 {
|
||||
glog.Error(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
var tags registryTags
|
||||
err = json.Unmarshal(body, &tags)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
return tags.Tags
|
||||
}
|
||||
|
||||
func getTagInDockerHub(url, imageName string) []string {
|
||||
if !strings.Contains(imageName, "/") {
|
||||
imageName = fmt.Sprintf("library/%s", imageName)
|
||||
}
|
||||
url = fmt.Sprintf("https://hub.docker.com/v2/repositories/%s/tags/?page=1&page_size=200", imageName)
|
||||
|
||||
body, err := httpGet(url, "", "", true)
|
||||
if err != nil || len(body) == 0 {
|
||||
glog.Error(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
var tags dockerhubTags
|
||||
err = json.Unmarshal(body, &tags)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
tagList := make([]string, 0, 200)
|
||||
for _, tag := range tags.Tags {
|
||||
tagList = append(tagList, tag.TagName)
|
||||
}
|
||||
|
||||
return tagList
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package kubectl
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
0
pkg/models/metrics/containers.go
Executable file → Normal file
0
pkg/models/metrics/containers.go
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,200 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func MakeWorkloadPromQL(metricName, nsName, wlFilter string) string {
|
||||
if wlFilter == "" {
|
||||
wlFilter = ".*"
|
||||
}
|
||||
|
||||
var promql = RulePromQLTmplMap[metricName]
|
||||
promql = strings.Replace(promql, "$2", nsName, -1)
|
||||
promql = strings.Replace(promql, "$3", wlFilter, -1)
|
||||
return promql
|
||||
}
|
||||
|
||||
func MakeSpecificWorkloadRule(wkKind, wkName, namespace string) string {
|
||||
var rule = PodInfoRule
|
||||
if namespace == "" {
|
||||
namespace = ".*"
|
||||
}
|
||||
// alertnatives values: Deployment StatefulSet ReplicaSet DaemonSet
|
||||
wkKind = strings.ToLower(wkKind)
|
||||
|
||||
switch wkKind {
|
||||
case "deployment":
|
||||
wkKind = ReplicaSet
|
||||
if wkName != "" {
|
||||
wkName = "~\"^" + wkName + `-(\\w)+$"`
|
||||
} else {
|
||||
wkName = "~\".*\""
|
||||
}
|
||||
rule = strings.Replace(rule, "$1", wkKind, -1)
|
||||
rule = strings.Replace(rule, "$2", wkName, -1)
|
||||
rule = strings.Replace(rule, "$3", namespace, -1)
|
||||
return rule
|
||||
case "replicaset":
|
||||
wkKind = ReplicaSet
|
||||
case "statefulset":
|
||||
wkKind = StatefulSet
|
||||
case "daemonset":
|
||||
wkKind = DaemonSet
|
||||
}
|
||||
|
||||
if wkName == "" {
|
||||
wkName = "~\".*\""
|
||||
} else {
|
||||
wkName = "\"" + wkName + "\""
|
||||
}
|
||||
|
||||
rule = strings.Replace(rule, "$1", wkKind, -1)
|
||||
rule = strings.Replace(rule, "$2", wkName, -1)
|
||||
rule = strings.Replace(rule, "$3", namespace, -1)
|
||||
return rule
|
||||
}
|
||||
|
||||
func MakeAllWorkspacesPromQL(metricsName, nsFilter string) string {
|
||||
|
||||
var promql = RulePromQLTmplMap[metricsName]
|
||||
nsFilter = "!~\"" + nsFilter + "\""
|
||||
promql = strings.Replace(promql, "$1", nsFilter, -1)
|
||||
return promql
|
||||
}
|
||||
|
||||
func MakeSpecificWorkspacePromQL(metricsName, nsFilter string) string {
|
||||
|
||||
var promql = RulePromQLTmplMap[metricsName]
|
||||
nsFilter = "=~\"" + nsFilter + "\""
|
||||
promql = strings.Replace(promql, "$1", nsFilter, -1)
|
||||
return promql
|
||||
}
|
||||
|
||||
func MakeContainerPromQL(nsName, nodeId, podName, containerName, metricName, containerFilter string) string {
|
||||
var promql string
|
||||
|
||||
if nsName != "" {
|
||||
// get container metrics from namespace-pod
|
||||
promql = RulePromQLTmplMap[metricName]
|
||||
promql = strings.Replace(promql, "$1", nsName, -1)
|
||||
} else {
|
||||
// get container metrics from node-pod
|
||||
promql = RulePromQLTmplMap[metricName+"_node"]
|
||||
promql = strings.Replace(promql, "$1", nodeId, -1)
|
||||
}
|
||||
|
||||
promql = strings.Replace(promql, "$2", podName, -1)
|
||||
|
||||
if containerName == "" {
|
||||
|
||||
if containerFilter == "" {
|
||||
containerFilter = ".*"
|
||||
}
|
||||
promql = strings.Replace(promql, "$3", containerFilter, -1)
|
||||
} else {
|
||||
promql = strings.Replace(promql, "$3", containerName, -1)
|
||||
}
|
||||
|
||||
return promql
|
||||
}
|
||||
|
||||
func MakePodPromQL(metricName, nsName, nodeID, podName, podFilter string) string {
|
||||
|
||||
if podFilter == "" {
|
||||
podFilter = ".*"
|
||||
}
|
||||
|
||||
var promql = ""
|
||||
if nsName != "" {
|
||||
// get pod metrics by namespace
|
||||
if podName != "" {
|
||||
// specific pod
|
||||
promql = RulePromQLTmplMap[metricName]
|
||||
promql = strings.Replace(promql, "$1", nsName, -1)
|
||||
promql = strings.Replace(promql, "$2", podName, -1)
|
||||
|
||||
} else {
|
||||
// all pods
|
||||
metricName += "_all"
|
||||
promql = RulePromQLTmplMap[metricName]
|
||||
|
||||
promql = strings.Replace(promql, "$1", nsName, -1)
|
||||
promql = strings.Replace(promql, "$2", podFilter, -1)
|
||||
}
|
||||
} else if nodeID != "" {
|
||||
// get pod metrics by nodeid
|
||||
metricName += "_node"
|
||||
promql = RulePromQLTmplMap[metricName]
|
||||
promql = strings.Replace(promql, "$3", nodeID, -1)
|
||||
if podName != "" {
|
||||
// specific pod
|
||||
promql = strings.Replace(promql, "$2", podName, -1)
|
||||
} else {
|
||||
promql = strings.Replace(promql, "$2", podFilter, -1)
|
||||
}
|
||||
}
|
||||
return promql
|
||||
}
|
||||
|
||||
func MakeNamespacePromQL(nsName string, nsFilter string, metricsName string) string {
|
||||
var recordingRule = RulePromQLTmplMap[metricsName]
|
||||
|
||||
if nsName != "" {
|
||||
nsFilter = nsName
|
||||
} else {
|
||||
if nsFilter == "" {
|
||||
nsFilter = ".*"
|
||||
}
|
||||
}
|
||||
recordingRule = strings.Replace(recordingRule, "$1", nsFilter, -1)
|
||||
return recordingRule
|
||||
}
|
||||
|
||||
// cluster rule
|
||||
func MakeClusterRule(metricsName string) string {
|
||||
var rule = RulePromQLTmplMap[metricsName]
|
||||
return rule
|
||||
}
|
||||
|
||||
// node rule
|
||||
func MakeNodeRule(nodeID string, nodesFilter string, metricsName string) string {
|
||||
var rule = RulePromQLTmplMap[metricsName]
|
||||
|
||||
if nodesFilter == "" {
|
||||
nodesFilter = ".*"
|
||||
}
|
||||
if strings.Contains(metricsName, "disk_size") || strings.Contains(metricsName, "pod") || strings.Contains(metricsName, "usage") || strings.Contains(metricsName, "inode") || strings.Contains(metricsName, "load") {
|
||||
// disk size promql
|
||||
if nodeID != "" {
|
||||
nodesFilter = "{" + "node" + "=" + "\"" + nodeID + "\"" + "}"
|
||||
} else {
|
||||
nodesFilter = "{" + "node" + "=~" + "\"" + nodesFilter + "\"" + "}"
|
||||
}
|
||||
rule = strings.Replace(rule, "$1", nodesFilter, -1)
|
||||
} else {
|
||||
// cpu, memory, network, disk_iops rules
|
||||
if nodeID != "" {
|
||||
// specific node
|
||||
rule = rule + "{" + "node" + "=" + "\"" + nodeID + "\"" + "}"
|
||||
} else {
|
||||
// all nodes or specific nodes filted with re2 syntax
|
||||
rule = rule + "{" + "node" + "=~" + "\"" + nodesFilter + "\"" + "}"
|
||||
}
|
||||
}
|
||||
|
||||
return rule
|
||||
}
|
||||
@@ -1,579 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
const (
|
||||
ResultTypeVector = "vector"
|
||||
ResultTypeMatrix = "matrix"
|
||||
MetricStatus = "status"
|
||||
MetricStatusError = "error"
|
||||
MetricStatusSuccess = "success"
|
||||
ResultItemMetric = "metric"
|
||||
ResultItemMetricResource = "resource"
|
||||
ResultItemValue = "value"
|
||||
ResultItemValues = "values"
|
||||
ResultSortTypeDesc = "desc"
|
||||
ResultSortTypeAsce = "asce"
|
||||
)
|
||||
|
||||
const (
|
||||
MetricNameWorkloadCount = "workload_count"
|
||||
MetricNameNamespacePodCount = "namespace_pod_count"
|
||||
|
||||
MetricNameWorkspaceAllOrganizationCount = "workspace_all_organization_count"
|
||||
MetricNameWorkspaceAllAccountCount = "workspace_all_account_count"
|
||||
MetricNameWorkspaceAllProjectCount = "workspace_all_project_count"
|
||||
MetricNameWorkspaceAllDevopsCount = "workspace_all_devops_project_count"
|
||||
MetricNameClusterAllProjectCount = "cluster_namespace_count"
|
||||
|
||||
MetricNameWorkspaceNamespaceCount = "workspace_namespace_count"
|
||||
MetricNameWorkspaceDevopsCount = "workspace_devops_project_count"
|
||||
MetricNameWorkspaceMemberCount = "workspace_member_count"
|
||||
MetricNameWorkspaceRoleCount = "workspace_role_count"
|
||||
MetricNameComponentOnLine = "component_online_count"
|
||||
MetricNameComponentLine = "component_count"
|
||||
)
|
||||
|
||||
const (
|
||||
WorkspaceResourceKindOrganization = "organization"
|
||||
WorkspaceResourceKindAccount = "account"
|
||||
WorkspaceResourceKindNamespace = "namespace"
|
||||
WorkspaceResourceKindDevops = "devops"
|
||||
WorkspaceResourceKindMember = "member"
|
||||
WorkspaceResourceKindRole = "role"
|
||||
)
|
||||
|
||||
const (
|
||||
MetricLevelCluster = "cluster"
|
||||
MetricLevelClusterWorkspace = "cluster_workspace"
|
||||
MetricLevelNode = "node"
|
||||
MetricLevelWorkspace = "workspace"
|
||||
MetricLevelNamespace = "namespace"
|
||||
MetricLevelPod = "pod"
|
||||
MetricLevelPodName = "pod_name"
|
||||
MetricLevelContainer = "container"
|
||||
MetricLevelContainerName = "container_name"
|
||||
MetricLevelWorkload = "workload"
|
||||
)
|
||||
|
||||
const (
|
||||
ReplicaSet = "ReplicaSet"
|
||||
StatefulSet = "StatefulSet"
|
||||
DaemonSet = "DaemonSet"
|
||||
Deployment = "Deployment"
|
||||
)
|
||||
|
||||
const (
|
||||
NodeStatusRule = `kube_node_status_condition{condition="Ready"} > 0`
|
||||
PodInfoRule = `kube_pod_info{created_by_kind="$1",created_by_name=$2,namespace="$3"}`
|
||||
NamespaceLabelRule = `kube_namespace_labels`
|
||||
WorkloadReplicaSetOwnerRule = `kube_pod_owner{namespace="$1", owner_name!="<none>", owner_kind="ReplicaSet"}`
|
||||
WorkspaceNamespaceLabelRule = `sum(kube_namespace_labels{label_kubesphere_io_workspace != ""}) by (label_kubesphere_io_workspace)`
|
||||
ExcludedVirtualNetworkInterfaces = `interface!~"^(cali.+|tunl.+|dummy.+|kube.+|flannel.+|cni.+|docker.+|veth.+|lo.*)"`
|
||||
)
|
||||
|
||||
const (
|
||||
WorkspaceJoinedKey = "label_kubesphere_io_workspace"
|
||||
)
|
||||
|
||||
type MetricMap map[string]string
|
||||
|
||||
var ClusterMetricsNames = []string{
|
||||
"cluster_cpu_utilisation",
|
||||
"cluster_cpu_usage",
|
||||
"cluster_cpu_total",
|
||||
"cluster_memory_utilisation",
|
||||
"cluster_memory_available",
|
||||
"cluster_memory_total",
|
||||
"cluster_memory_usage_wo_cache",
|
||||
"cluster_net_utilisation",
|
||||
"cluster_net_bytes_transmitted",
|
||||
"cluster_net_bytes_received",
|
||||
"cluster_disk_read_iops",
|
||||
"cluster_disk_write_iops",
|
||||
"cluster_disk_read_throughput",
|
||||
"cluster_disk_write_throughput",
|
||||
"cluster_disk_size_usage",
|
||||
"cluster_disk_size_utilisation",
|
||||
"cluster_disk_size_capacity",
|
||||
"cluster_disk_size_available",
|
||||
"cluster_disk_inode_total",
|
||||
"cluster_disk_inode_usage",
|
||||
"cluster_disk_inode_utilisation",
|
||||
|
||||
"cluster_node_online",
|
||||
"cluster_node_offline",
|
||||
"cluster_node_total",
|
||||
|
||||
"cluster_pod_count",
|
||||
"cluster_pod_quota",
|
||||
"cluster_pod_utilisation",
|
||||
"cluster_pod_running_count",
|
||||
"cluster_pod_succeeded_count",
|
||||
"cluster_pod_abnormal_count",
|
||||
"cluster_ingresses_extensions_count",
|
||||
"cluster_cronjob_count",
|
||||
"cluster_pvc_count",
|
||||
"cluster_daemonset_count",
|
||||
"cluster_deployment_count",
|
||||
"cluster_endpoint_count",
|
||||
"cluster_hpa_count",
|
||||
"cluster_job_count",
|
||||
"cluster_statefulset_count",
|
||||
"cluster_replicaset_count",
|
||||
"cluster_service_count",
|
||||
"cluster_secret_count",
|
||||
|
||||
"cluster_namespace_count",
|
||||
|
||||
"cluster_load1",
|
||||
"cluster_load5",
|
||||
"cluster_load15",
|
||||
}
|
||||
var NodeMetricsNames = []string{
|
||||
"node_cpu_utilisation",
|
||||
"node_cpu_total",
|
||||
"node_cpu_usage",
|
||||
"node_memory_utilisation",
|
||||
"node_memory_usage_wo_cache",
|
||||
"node_memory_available",
|
||||
"node_memory_total",
|
||||
|
||||
"node_net_utilisation",
|
||||
"node_net_bytes_transmitted",
|
||||
"node_net_bytes_received",
|
||||
"node_disk_read_iops",
|
||||
"node_disk_write_iops",
|
||||
"node_disk_read_throughput",
|
||||
"node_disk_write_throughput",
|
||||
"node_disk_size_capacity",
|
||||
"node_disk_size_available",
|
||||
"node_disk_size_usage",
|
||||
"node_disk_size_utilisation",
|
||||
|
||||
"node_disk_inode_total",
|
||||
"node_disk_inode_usage",
|
||||
"node_disk_inode_utilisation",
|
||||
|
||||
"node_pod_count",
|
||||
"node_pod_quota",
|
||||
"node_pod_utilisation",
|
||||
"node_pod_running_count",
|
||||
"node_pod_succeeded_count",
|
||||
"node_pod_abnormal_count",
|
||||
|
||||
"node_load1",
|
||||
"node_load5",
|
||||
"node_load15",
|
||||
}
|
||||
var WorkspaceMetricsNames = []string{
|
||||
"workspace_cpu_usage",
|
||||
"workspace_memory_usage",
|
||||
"workspace_memory_usage_wo_cache",
|
||||
"workspace_net_bytes_transmitted",
|
||||
"workspace_net_bytes_received",
|
||||
"workspace_pod_count",
|
||||
"workspace_pod_running_count",
|
||||
"workspace_pod_succeeded_count",
|
||||
"workspace_pod_abnormal_count",
|
||||
"workspace_ingresses_extensions_count",
|
||||
|
||||
"workspace_cronjob_count",
|
||||
"workspace_pvc_count",
|
||||
"workspace_daemonset_count",
|
||||
"workspace_deployment_count",
|
||||
"workspace_endpoint_count",
|
||||
"workspace_hpa_count",
|
||||
"workspace_job_count",
|
||||
"workspace_statefulset_count",
|
||||
"workspace_replicaset_count",
|
||||
"workspace_service_count",
|
||||
"workspace_secret_count",
|
||||
|
||||
"workspace_all_project_count",
|
||||
}
|
||||
var NamespaceMetricsNames = []string{
|
||||
"namespace_cpu_usage",
|
||||
"namespace_memory_usage",
|
||||
"namespace_memory_usage_wo_cache",
|
||||
"namespace_net_bytes_transmitted",
|
||||
"namespace_net_bytes_received",
|
||||
"namespace_pod_count",
|
||||
"namespace_pod_running_count",
|
||||
"namespace_pod_succeeded_count",
|
||||
"namespace_pod_abnormal_count",
|
||||
|
||||
"namespace_configmap_count_used",
|
||||
"namespace_jobs_batch_count_used",
|
||||
"namespace_roles_count_used",
|
||||
"namespace_memory_limit_used",
|
||||
"namespace_pvc_used",
|
||||
"namespace_memory_request_used",
|
||||
"namespace_pvc_count_used",
|
||||
"namespace_cronjobs_batch_count_used",
|
||||
"namespace_ingresses_extensions_count_used",
|
||||
"namespace_cpu_limit_used",
|
||||
"namespace_storage_request_used",
|
||||
"namespace_deployment_count_used",
|
||||
"namespace_pod_count_used",
|
||||
"namespace_statefulset_count_used",
|
||||
"namespace_daemonset_count_used",
|
||||
"namespace_secret_count_used",
|
||||
"namespace_service_count_used",
|
||||
"namespace_cpu_request_used",
|
||||
"namespace_service_loadbalancer_used",
|
||||
|
||||
"namespace_configmap_count_hard",
|
||||
"namespace_jobs_batch_count_hard",
|
||||
"namespace_roles_count_hard",
|
||||
"namespace_memory_limit_hard",
|
||||
"namespace_pvc_hard",
|
||||
"namespace_memory_request_hard",
|
||||
"namespace_pvc_count_hard",
|
||||
"namespace_cronjobs_batch_count_hard",
|
||||
"namespace_ingresses_extensions_count_hard",
|
||||
"namespace_cpu_limit_hard",
|
||||
"namespace_storage_request_hard",
|
||||
"namespace_deployment_count_hard",
|
||||
"namespace_pod_count_hard",
|
||||
"namespace_statefulset_count_hard",
|
||||
"namespace_daemonset_count_hard",
|
||||
"namespace_secret_count_hard",
|
||||
"namespace_service_count_hard",
|
||||
"namespace_cpu_request_hard",
|
||||
"namespace_service_loadbalancer_hard",
|
||||
|
||||
"namespace_cronjob_count",
|
||||
"namespace_pvc_count",
|
||||
"namespace_daemonset_count",
|
||||
"namespace_deployment_count",
|
||||
"namespace_endpoint_count",
|
||||
"namespace_hpa_count",
|
||||
"namespace_job_count",
|
||||
"namespace_statefulset_count",
|
||||
"namespace_replicaset_count",
|
||||
"namespace_service_count",
|
||||
"namespace_secret_count",
|
||||
|
||||
"namespace_ingresses_extensions_count",
|
||||
}
|
||||
|
||||
var PodMetricsNames = []string{
|
||||
"pod_cpu_usage",
|
||||
"pod_memory_usage",
|
||||
"pod_memory_usage_wo_cache",
|
||||
"pod_net_bytes_transmitted",
|
||||
"pod_net_bytes_received",
|
||||
}
|
||||
|
||||
var WorkloadMetricsNames = []string{
|
||||
"workload_pod_cpu_usage",
|
||||
"workload_pod_memory_usage",
|
||||
"workload_pod_memory_usage_wo_cache",
|
||||
"workload_pod_net_bytes_transmitted",
|
||||
"workload_pod_net_bytes_received",
|
||||
|
||||
"workload_deployment_replica",
|
||||
"workload_deployment_replica_available",
|
||||
"workload_statefulset_replica",
|
||||
"workload_statefulset_replica_available",
|
||||
"workload_daemonset_replica",
|
||||
"workload_daemonset_replica_available",
|
||||
}
|
||||
|
||||
var ContainerMetricsNames = []string{
|
||||
"container_cpu_usage",
|
||||
"container_memory_usage",
|
||||
"container_memory_usage_wo_cache",
|
||||
//"container_net_bytes_transmitted",
|
||||
//"container_net_bytes_received",
|
||||
}
|
||||
|
||||
var RulePromQLTmplMap = MetricMap{
|
||||
//cluster
|
||||
"cluster_cpu_utilisation": ":node_cpu_utilisation:avg1m",
|
||||
"cluster_cpu_usage": `:node_cpu_utilisation:avg1m * sum(node:node_num_cpu:sum)`,
|
||||
"cluster_cpu_total": "sum(node:node_num_cpu:sum)",
|
||||
"cluster_memory_utilisation": ":node_memory_utilisation:",
|
||||
"cluster_memory_available": "sum(node:node_memory_bytes_available:sum)",
|
||||
"cluster_memory_total": "sum(node:node_memory_bytes_total:sum)",
|
||||
"cluster_memory_usage_wo_cache": "sum(node:node_memory_bytes_total:sum) - sum(node:node_memory_bytes_available:sum)",
|
||||
|
||||
"cluster_net_utilisation": ":node_net_utilisation:sum_irate",
|
||||
"cluster_net_bytes_transmitted": "sum(node:node_net_bytes_transmitted:sum_irate)",
|
||||
"cluster_net_bytes_received": "sum(node:node_net_bytes_received:sum_irate)",
|
||||
"cluster_disk_read_iops": "sum(node:data_volume_iops_reads:sum)",
|
||||
"cluster_disk_write_iops": "sum(node:data_volume_iops_writes:sum)",
|
||||
"cluster_disk_read_throughput": "sum(node:data_volume_throughput_bytes_read:sum)",
|
||||
"cluster_disk_write_throughput": "sum(node:data_volume_throughput_bytes_written:sum)",
|
||||
|
||||
"cluster_disk_size_usage": `sum(max((node_filesystem_size{device=~"/dev/.+", job="node-exporter"} - node_filesystem_avail{device=~"/dev/.+", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:) by (node))`,
|
||||
"cluster_disk_size_utilisation": `1 - sum(max(node_filesystem_avail{device=~"/dev/.+", job="node-exporter"} * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:) by (node)) / sum(max(node_filesystem_size{device=~"/dev/.+", job="node-exporter"} * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:) by (node))`,
|
||||
"cluster_disk_size_capacity": `sum(max(node_filesystem_size{device=~"/dev/.+", job="node-exporter"} * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:) by (node))`,
|
||||
"cluster_disk_size_available": `sum(max(node_filesystem_avail{device=~"/dev/.+", job="node-exporter"} * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:) by (node))`,
|
||||
|
||||
"cluster_disk_inode_total": `sum(node:disk_inodes_total:)`,
|
||||
"cluster_disk_inode_usage": `sum(node:disk_inodes_total:) - sum(node:disk_inodes_free:)`,
|
||||
"cluster_disk_inode_utilisation": `1 - sum(node:disk_inodes_free:) / sum(node:disk_inodes_total:)`,
|
||||
|
||||
"cluster_namespace_count": `count(kube_namespace_annotations)`,
|
||||
|
||||
// cluster_pod_count = cluster_pod_running_count + cluster_pod_succeeded_count + cluster_pod_abnormal_count
|
||||
"cluster_pod_count": `sum((kube_pod_status_scheduled{condition="true"} > 0) * on (pod) group_left(node) (sum by (node, pod) (kube_pod_info)) unless on (node) (kube_node_status_condition{condition="Ready",status=~"unknown|false"} > 0))`,
|
||||
"cluster_pod_quota": `sum(kube_node_status_capacity_pods unless on (node) (kube_node_status_condition{condition="Ready",status=~"unknown|false"} > 0))`,
|
||||
"cluster_pod_utilisation": `sum(kube_pod_info unless on (node) (kube_node_status_condition{condition="Ready",status=~"unknown|false"} > 0)) / sum(kube_node_status_capacity_pods unless on (node) (kube_node_status_condition{condition="Ready",status=~"unknown|false"} > 0))`,
|
||||
"cluster_pod_running_count": `count(kube_pod_info unless on (pod) (kube_pod_status_phase{phase=~"Failed|Pending|Unknown|Succeeded"} > 0) unless on (node) (kube_node_status_condition{condition="Ready",status=~"unknown|false"} > 0))`,
|
||||
"cluster_pod_succeeded_count": `count(kube_pod_info unless on (pod) (kube_pod_status_phase{phase=~"Failed|Pending|Unknown|Running"} > 0) unless on (node) (kube_node_status_condition{condition="Ready",status=~"unknown|false"} > 0))`,
|
||||
"cluster_pod_abnormal_count": `count(kube_pod_info unless on (pod) (kube_pod_status_phase{phase=~"Succeeded|Running"} > 0) unless on (node) (kube_node_status_condition{condition="Ready",status=~"unknown|false"} > 0))`,
|
||||
|
||||
"cluster_node_online": `sum(kube_node_status_condition{condition="Ready",status="true"})`,
|
||||
"cluster_node_offline": `sum(kube_node_status_condition{condition="Ready",status=~"unknown|false"})`,
|
||||
"cluster_node_total": `sum(kube_node_status_condition{condition="Ready"})`,
|
||||
|
||||
"cluster_ingresses_extensions_count": `sum(kube_ingress_labels)`,
|
||||
|
||||
"cluster_configmap_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="count/configmaps"}) by (resource, type)`,
|
||||
"cluster_jobs_batch_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="count/jobs.batch"}) by (resource, type)`,
|
||||
"cluster_roles_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="count/roles.rbac.authorization.k8s.io"}) by (resource, type)`,
|
||||
"cluster_memory_limit_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="limits.memory"}) by (resource, type)`,
|
||||
"cluster_pvc_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="persistentvolumeclaims"}) by (resource, type)`,
|
||||
"cluster_memory_request_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="requests.memory"}) by (resource, type)`,
|
||||
"cluster_pvc_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="count/persistentvolumeclaims"}) by (resource, type)`,
|
||||
"cluster_cronjobs_batch_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="count/cronjobs.batch"}) by (resource, type)`,
|
||||
"cluster_ingresses_extensions_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="count/ingresses.extensions"}) by (resource, type)`,
|
||||
"cluster_cpu_limit_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="limits.cpu"}) by (resource, type)`,
|
||||
"cluster_storage_request_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="requests.storage"}) by (resource, type)`,
|
||||
"cluster_deployment_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="count/deployments.apps"}) by (resource, type)`,
|
||||
"cluster_pod_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="count/pods"}) by (resource, type)`,
|
||||
"cluster_statefulset_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="count/statefulsets.apps"}) by (resource, type)`,
|
||||
"cluster_daemonset_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="count/daemonsets.apps"}) by (resource, type)`,
|
||||
"cluster_secret_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="count/secrets"}) by (resource, type)`,
|
||||
"cluster_service_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="count/services"}) by (resource, type)`,
|
||||
"cluster_cpu_request_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="requests.cpu"}) by (resource, type)`,
|
||||
"cluster_service_loadbalancer_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", resource="services.loadbalancers"}) by (resource, type)`,
|
||||
|
||||
"cluster_cronjob_count": `sum(kube_cronjob_labels)`,
|
||||
"cluster_pvc_count": `sum(kube_persistentvolumeclaim_info)`,
|
||||
"cluster_daemonset_count": `sum(kube_daemonset_labels)`,
|
||||
"cluster_deployment_count": `sum(kube_deployment_labels)`,
|
||||
"cluster_endpoint_count": `sum(kube_endpoint_labels)`,
|
||||
"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_service_count": `sum(kube_service_info)`,
|
||||
"cluster_secret_count": `sum(kube_secret_info)`,
|
||||
"cluster_pv_count": `sum(kube_persistentvolume_labels)`,
|
||||
|
||||
"cluster_load1": `sum(node_load1{job="node-exporter"}) / sum(node:node_num_cpu:sum)`,
|
||||
"cluster_load5": `sum(node_load5{job="node-exporter"}) / sum(node:node_num_cpu:sum)`,
|
||||
"cluster_load15": `sum(node_load15{job="node-exporter"}) / sum(node:node_num_cpu:sum)`,
|
||||
|
||||
//node
|
||||
"node_cpu_utilisation": "node:node_cpu_utilisation:avg1m",
|
||||
"node_cpu_total": "node:node_num_cpu:sum",
|
||||
"node_memory_utilisation": "node:node_memory_utilisation:",
|
||||
"node_memory_available": "node:node_memory_bytes_available:sum",
|
||||
"node_memory_total": "node:node_memory_bytes_total:sum",
|
||||
"node_memory_usage_wo_cache": "node:node_memory_bytes_total:sum$1 - node:node_memory_bytes_available:sum$1",
|
||||
|
||||
"node_net_utilisation": "node:node_net_utilisation:sum_irate",
|
||||
"node_net_bytes_transmitted": "node:node_net_bytes_transmitted:sum_irate",
|
||||
"node_net_bytes_received": "node:node_net_bytes_received:sum_irate",
|
||||
"node_disk_read_iops": "node:data_volume_iops_reads:sum",
|
||||
"node_disk_write_iops": "node:data_volume_iops_writes:sum",
|
||||
"node_disk_read_throughput": "node:data_volume_throughput_bytes_read:sum",
|
||||
"node_disk_write_throughput": "node:data_volume_throughput_bytes_written:sum",
|
||||
|
||||
"node_disk_size_capacity": `max(node_filesystem_size{device=~"/dev/.+", job="node-exporter"} * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1) by (node)`,
|
||||
"node_disk_size_available": `max(node_filesystem_avail{device=~"/dev/.+", job="node-exporter"} * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1) by (node)`,
|
||||
"node_disk_size_usage": `max((node_filesystem_size{device=~"/dev/.+", job="node-exporter"} - node_filesystem_avail{device=~"/dev/.+", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1) by (node)`,
|
||||
"node_disk_size_utilisation": `max(((node_filesystem_size{device=~"/dev/.+", job="node-exporter"} - node_filesystem_avail{device=~"/dev/.+", job="node-exporter"}) / node_filesystem_size{device=~"/dev/.+", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1) by (node)`,
|
||||
|
||||
"node_disk_inode_total": `node:disk_inodes_total:$1`,
|
||||
"node_disk_inode_usage": `node:disk_inodes_total:$1 - node:disk_inodes_free:$1`,
|
||||
"node_disk_inode_utilisation": `(1 - (node:disk_inodes_free:$1 / node:disk_inodes_total:$1))`,
|
||||
|
||||
"node_pod_count": `sum by (node) ((kube_pod_status_scheduled{condition="true"} > 0) * on (pod) group_left(node) kube_pod_info$1 unless on (node) (kube_node_status_condition{condition="Ready",status=~"unknown|false"} > 0))`,
|
||||
"node_pod_quota": `sum(kube_node_status_capacity_pods$1) by (node) unless on (node) (kube_node_status_condition{condition="Ready",status=~"unknown|false"} > 0)`,
|
||||
"node_pod_utilisation": `(sum(kube_pod_info$1) by (node) / sum(kube_node_status_capacity_pods$1) by (node)) unless on (node) (kube_node_status_condition{condition="Ready",status=~"unknown|false"} > 0)`,
|
||||
"node_pod_running_count": `count(kube_pod_info$1 unless on (pod) (kube_pod_status_phase{phase=~"Failed|Pending|Unknown|Succeeded"} > 0)) by (node) unless on (node) (kube_node_status_condition{condition="Ready",status=~"unknown|false"} > 0)`,
|
||||
"node_pod_succeeded_count": `count(kube_pod_info$1 unless on (pod) (kube_pod_status_phase{phase=~"Failed|Pending|Unknown|Running"} > 0)) by (node) unless on (node) (kube_node_status_condition{condition="Ready",status=~"unknown|false"} > 0)`,
|
||||
"node_pod_abnormal_count": `count(kube_pod_info$1 unless on (pod) (kube_pod_status_phase{phase=~"Succeeded|Running"} > 0)) by (node) unless on (node) (kube_node_status_condition{condition="Ready",status=~"unknown|false"} > 0)`,
|
||||
|
||||
// without log node: unless on(node) kube_node_labels{label_role="log"}
|
||||
"node_cpu_usage": `node:node_cpu_utilisation:avg1m$1 * node:node_num_cpu:sum$1`,
|
||||
|
||||
"node_load1": `sum by (node) (node_load1{job="node-exporter"} * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1) / node:node_num_cpu:sum`,
|
||||
"node_load5": `sum by (node) (node_load5{job="node-exporter"} * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1) / node:node_num_cpu:sum`,
|
||||
"node_load15": `sum by (node) (node_load15{job="node-exporter"} * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1) / node:node_num_cpu:sum`,
|
||||
|
||||
//namespace
|
||||
"namespace_cpu_usage": `namespace:container_cpu_usage_seconds_total:sum_rate{namespace!="", namespace=~"$1"} * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_memory_usage": `namespace:container_memory_usage_bytes:sum{namespace!="", namespace=~"$1"} * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_memory_usage_wo_cache": `namespace:container_memory_usage_bytes_wo_cache:sum{namespace!="", namespace=~"$1"}* on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_net_bytes_transmitted": `sum by (namespace) (irate(container_network_transmit_bytes_total{namespace!="", namespace=~"$1", pod_name!="", ` + ExcludedVirtualNetworkInterfaces + `, job="kubelet"}[5m]))* on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_net_bytes_received": `sum by (namespace) (irate(container_network_receive_bytes_total{namespace!="", namespace=~"$1", pod_name!="", ` + ExcludedVirtualNetworkInterfaces + `, job="kubelet"}[5m])) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_pod_count": `sum(kube_pod_status_phase{phase!~"Failed|Succeeded", namespace!="", namespace=~"$1"}) by (namespace) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_pod_running_count": `sum(kube_pod_status_phase{phase="Running", namespace!="", namespace=~"$1"}) by (namespace) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_pod_succeeded_count": `sum(kube_pod_status_phase{phase="Succeeded", namespace!="", namespace=~"$1"}) by (namespace) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_pod_abnormal_count": `sum(kube_pod_status_phase{phase=~"Failed|Pending|Unknown", namespace!="", namespace=~"$1"}) by (namespace) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
|
||||
"namespace_configmap_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="count/configmaps"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_jobs_batch_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="count/jobs.batch"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_roles_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="count/roles.rbac.authorization.k8s.io"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_memory_limit_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="limits.memory"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_pvc_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="persistentvolumeclaims"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_memory_request_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="requests.memory"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_pvc_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="count/persistentvolumeclaims"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_cronjobs_batch_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="count/cronjobs.batch"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_ingresses_extensions_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="count/ingresses.extensions"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_cpu_limit_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="limits.cpu"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_storage_request_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="requests.storage"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_deployment_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="count/deployments.apps"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_pod_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="count/pods"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_statefulset_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="count/statefulsets.apps"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_daemonset_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="count/daemonsets.apps"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_secret_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="count/secrets"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_service_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="count/services"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_cpu_request_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="requests.cpu"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_service_loadbalancer_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace=~"$1", resource="services.loadbalancers"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
|
||||
"namespace_configmap_count_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="count/configmaps"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_jobs_batch_count_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="count/jobs.batch"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_roles_count_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="count/roles.rbac.authorization.k8s.io"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_memory_limit_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="limits.memory"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_pvc_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="persistentvolumeclaims"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_memory_request_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="requests.memory"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_pvc_count_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="count/persistentvolumeclaims"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_cronjobs_batch_count_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="count/cronjobs.batch"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_ingresses_extensions_count_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="count/ingresses.extensions"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_cpu_limit_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="limits.cpu"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_storage_request_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="requests.storage"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_deployment_count_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="count/deployments.apps"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_pod_count_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="count/pods"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_statefulset_count_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="count/statefulsets.apps"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_daemonset_count_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="count/daemonsets.apps"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_secret_count_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="count/secrets"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_service_count_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="count/services"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_cpu_request_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="requests.cpu"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_service_loadbalancer_hard": `sum(kube_resourcequota{resourcequota!="quota", type="hard", namespace!="", namespace=~"$1", resource="services.loadbalancers"}) by (namespace, resource, type) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
|
||||
"namespace_cronjob_count": `sum(kube_cronjob_labels{namespace!="", namespace=~"$1"}) by (namespace) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_pvc_count": `sum(kube_persistentvolumeclaim_info{namespace!="", namespace=~"$1"}) by (namespace) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_daemonset_count": `sum(kube_daemonset_labels{namespace!="", namespace=~"$1"}) by (namespace) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_deployment_count": `sum(kube_deployment_labels{namespace!="", namespace=~"$1"}) by (namespace) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_endpoint_count": `sum(kube_endpoint_labels{namespace!="", namespace=~"$1"}) by (namespace) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_hpa_count": `sum(kube_hpa_labels{namespace!="", namespace=~"$1"}) by (namespace) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_job_count": `sum(kube_job_labels{namespace!="", namespace=~"$1"}) by (namespace) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_statefulset_count": `sum(kube_statefulset_labels{namespace!="", namespace=~"$1"}) by (namespace) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_replicaset_count": `count(kube_replicaset_created{namespace!="", namespace=~"$1"}) by (namespace) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_service_count": `sum(kube_service_info{namespace!="", namespace=~"$1"}) by (namespace) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
"namespace_secret_count": `sum(kube_secret_info{namespace!="", namespace=~"$1"}) by (namespace) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
|
||||
"namespace_ingresses_extensions_count": `sum(kube_ingress_labels{namespace!="", namespace=~"$1"}) by (namespace) * on (namespace) group_left(label_kubesphere_io_workspace)(kube_namespace_labels)`,
|
||||
|
||||
// pod
|
||||
"pod_cpu_usage": `sum(irate(container_cpu_usage_seconds_total{job="kubelet", namespace="$1", pod_name!="", pod_name="$2", image!=""}[5m])) by (namespace, pod_name)`,
|
||||
"pod_memory_usage": `sum(container_memory_usage_bytes{job="kubelet", namespace="$1", pod_name!="", pod_name="$2", image!=""}) by (namespace, pod_name)`,
|
||||
"pod_memory_usage_wo_cache": `sum(container_memory_usage_bytes{job="kubelet", namespace="$1", pod_name!="", pod_name="$2", image!=""} - container_memory_cache{job="kubelet", namespace="$1", pod_name!="", pod_name="$2",image!=""}) by (namespace, pod_name)`,
|
||||
"pod_net_bytes_transmitted": `sum by (namespace, pod_name) (irate(container_network_transmit_bytes_total{namespace="$1", pod_name!="", pod_name="$2", ` + ExcludedVirtualNetworkInterfaces + `, job="kubelet"}[5m]))`,
|
||||
"pod_net_bytes_received": `sum by (namespace, pod_name) (irate(container_network_receive_bytes_total{namespace="$1", pod_name!="", pod_name="$2", ` + ExcludedVirtualNetworkInterfaces + `, job="kubelet"}[5m]))`,
|
||||
|
||||
"pod_cpu_usage_all": `sum(irate(container_cpu_usage_seconds_total{job="kubelet", namespace="$1", pod_name!="", pod_name=~"$2", image!=""}[5m])) by (namespace, pod_name)`,
|
||||
"pod_memory_usage_all": `sum(container_memory_usage_bytes{job="kubelet", namespace="$1", pod_name!="", pod_name=~"$2", image!=""}) by (namespace, pod_name)`,
|
||||
"pod_memory_usage_wo_cache_all": `sum(container_memory_usage_bytes{job="kubelet", namespace="$1", pod_name!="", pod_name=~"$2", image!=""} - container_memory_cache{job="kubelet", namespace="$1", pod_name!="", pod_name=~"$2", image!=""}) by (namespace, pod_name)`,
|
||||
"pod_net_bytes_transmitted_all": `sum by (namespace, pod_name) (irate(container_network_transmit_bytes_total{namespace="$1", pod_name!="", pod_name=~"$2", ` + ExcludedVirtualNetworkInterfaces + `, job="kubelet"}[5m]))`,
|
||||
"pod_net_bytes_received_all": `sum by (namespace, pod_name) (irate(container_network_receive_bytes_total{namespace="$1", pod_name!="", pod_name=~"$2", ` + ExcludedVirtualNetworkInterfaces + `, job="kubelet"}[5m]))`,
|
||||
|
||||
"pod_cpu_usage_node": `sum by (node, pod_name) (irate(container_cpu_usage_seconds_total{job="kubelet",pod_name!="", pod_name=~"$2", image!=""}[5m]) * on (namespace, pod_name) group_left(node) label_join(node_namespace_pod:kube_pod_info:{node="$3"}, "pod_name", "", "pod", "_name"))`,
|
||||
"pod_memory_usage_node": `sum by (node, pod_name) (container_memory_usage_bytes{job="kubelet",pod_name!="", pod_name=~"$2", image!=""} * on (namespace, pod_name) group_left(node) label_join(node_namespace_pod:kube_pod_info:{node="$3"}, "pod_name", "", "pod", "_name"))`,
|
||||
"pod_memory_usage_wo_cache_node": `sum by (node, pod_name) ((container_memory_usage_bytes{job="kubelet",pod_name!="", pod_name=~"$2", image!=""} - container_memory_cache{job="kubelet",pod_name!="", pod_name=~"$2", image!=""}) * on (namespace, pod_name) group_left(node) label_join(node_namespace_pod:kube_pod_info:{node="$3"}, "pod_name", "", "pod", "_name"))`,
|
||||
"pod_net_bytes_transmitted_node": `sum by (node, pod_name) (irate(container_network_transmit_bytes_total{pod_name!="", pod_name=~"$2", ` + ExcludedVirtualNetworkInterfaces + `, job="kubelet"}[5m]) * on (pod_name) group_left(node) label_join(node_namespace_pod:kube_pod_info:{node="$3"}, "pod_name", "", "pod", "_name"))`,
|
||||
"pod_net_bytes_received_node": `sum by (node, pod_name) (irate(container_network_receive_bytes_total{pod_name!="", pod_name=~"$2", ` + ExcludedVirtualNetworkInterfaces + `, job="kubelet"}[5m]) * on (pod_name) group_left(node) label_join(node_namespace_pod:kube_pod_info:{node="$3"}, "pod_name", "", "pod", "_name"))`,
|
||||
|
||||
// workload
|
||||
"workload_pod_cpu_usage": `label_join(sum(label_replace(label_replace(label_replace(label_join(label_join(label_replace(sum(irate(container_cpu_usage_seconds_total{job="kubelet", namespace="$2", pod_name!="", pod_name=~"$3", image!=""}[5m])) by (namespace, pod_name) * on (pod_name) group_left(owner_kind) label_join(label_replace(kube_pod_owner{namespace="$2", pod=~".*"}, "owner_kind", "POD", "owner_kind", "<none>"), "pod_name", "", "pod", "_name") , "postfix", "-POD", "owner_kind", "POD"), "pod_name", "", "pod_name", "postfix"), "dist", "-", "owner_kind", "pod_name"), "pod_name", "$1", "dist", "ReplicaSet-(.+)-(.+)"), "workload", "$1", "pod_name", "(.+)-(.+)"), "owner_kind", "Deployment", "owner_kind", "ReplicaSet.*")) by (namespace, workload, owner_kind), "workload", ":", "owner_kind", "workload")`,
|
||||
"workload_pod_memory_usage": `label_join(sum(label_replace(label_replace(label_replace(label_join(label_join(label_replace(sum(container_memory_usage_bytes{job="kubelet", namespace="$2", pod_name!="", pod_name=~"$3", image!=""}) by (namespace, pod_name) * on (pod_name) group_left(owner_kind) label_join(label_replace(kube_pod_owner{namespace="$2", pod=~".*"}, "owner_kind", "POD", "owner_kind", "<none>"), "pod_name", "", "pod", "_name") , "postfix", "-POD", "owner_kind", "POD"), "pod_name", "", "pod_name", "postfix"), "dist", "-", "owner_kind", "pod_name"), "pod_name", "$1", "dist", "ReplicaSet-(.+)-(.+)"), "workload", "$1", "pod_name", "(.+)-(.+)"), "owner_kind", "Deployment", "owner_kind", "ReplicaSet.*")) by (namespace, workload, owner_kind), "workload", ":", "owner_kind", "workload")`,
|
||||
"workload_pod_memory_usage_wo_cache": `label_join(sum(label_replace(label_replace(label_replace(label_join(label_join(label_replace(sum(container_memory_usage_bytes{job="kubelet", namespace="$2", pod_name!="", pod_name=~"$3", image!=""} - container_memory_cache{job="kubelet", namespace="$2", pod_name!="", pod_name=~"$3", image!=""}) by (namespace, pod_name) * on (pod_name) group_left(owner_kind) label_join(label_replace(kube_pod_owner{namespace="$2", pod=~".*"}, "owner_kind", "POD", "owner_kind", "<none>"), "pod_name", "", "pod", "_name") , "postfix", "-POD", "owner_kind", "POD"), "pod_name", "", "pod_name", "postfix"), "dist", "-", "owner_kind", "pod_name"), "pod_name", "$1", "dist", "ReplicaSet-(.+)-(.+)"), "workload", "$1", "pod_name", "(.+)-(.+)"), "owner_kind", "Deployment", "owner_kind", "ReplicaSet.*")) by (namespace, workload, owner_kind), "workload", ":", "owner_kind", "workload")`,
|
||||
"workload_pod_net_bytes_transmitted": `label_join(sum(label_replace(label_replace(label_replace(label_join(label_join(label_replace(sum(irate(container_network_transmit_bytes_total{namespace="$2", pod_name!="", pod_name=~"$3", ` + ExcludedVirtualNetworkInterfaces + `, job="kubelet"}[5m])) by (namespace, pod_name) * on (pod_name) group_left(owner_kind) label_join(label_replace(kube_pod_owner{namespace="$2", pod=~".*"}, "owner_kind", "POD", "owner_kind", "<none>"), "pod_name", "", "pod", "_name") , "postfix", "-POD", "owner_kind", "POD"), "pod_name", "", "pod_name", "postfix"), "dist", "-", "owner_kind", "pod_name"), "pod_name", "$1", "dist", "ReplicaSet-(.+)-(.+)"), "workload", "$1", "pod_name", "(.+)-(.+)"), "owner_kind", "Deployment", "owner_kind", "ReplicaSet.*")) by (namespace, workload, owner_kind), "workload", ":", "owner_kind", "workload")`,
|
||||
"workload_pod_net_bytes_received": `label_join(sum(label_replace(label_replace(label_replace(label_join(label_join(label_replace(sum(irate(container_network_receive_bytes_total{namespace="$2", pod_name!="", pod_name=~"$3", ` + ExcludedVirtualNetworkInterfaces + `, job="kubelet"}[5m])) by (namespace, pod_name) * on (pod_name) group_left(owner_kind) label_join(label_replace(kube_pod_owner{namespace="$2", pod=~".*"}, "owner_kind", "POD", "owner_kind", "<none>"), "pod_name", "", "pod", "_name") , "postfix", "-POD", "owner_kind", "POD"), "pod_name", "", "pod_name", "postfix"), "dist", "-", "owner_kind", "pod_name"), "pod_name", "$1", "dist", "ReplicaSet-(.+)-(.+)"), "workload", "$1", "pod_name", "(.+)-(.+)"), "owner_kind", "Deployment", "owner_kind", "ReplicaSet.*")) by (namespace, workload, owner_kind), "workload", ":", "owner_kind", "workload")`,
|
||||
|
||||
"workload_deployment_replica": `label_join(sum (label_join(label_replace(kube_deployment_spec_replicas{namespace="$2", deployment=~"$3"}, "owner_kind", "Deployment", "", ""), "workload", "", "deployment")) by (namespace, owner_kind, workload), "workload", ":", "owner_kind", "workload")`,
|
||||
"workload_deployment_replica_available": `label_join(sum (label_join(label_replace(kube_deployment_status_replicas_available{namespace="$2", deployment=~"$3"}, "owner_kind", "Deployment", "", ""), "workload", "", "deployment")) by (namespace, owner_kind, workload), "workload", ":", "owner_kind", "workload")`,
|
||||
"workload_statefulset_replica": `label_join(sum (label_join(label_replace(kube_statefulset_replicas{namespace="$2", statefulset=~"$3"}, "owner_kind", "StatefulSet", "", ""), "workload", "", "statefulset")) by (namespace, owner_kind, workload), "workload", ":", "owner_kind", "workload")`,
|
||||
"workload_statefulset_replica_available": `label_join(sum (label_join(label_replace(kube_statefulset_status_replicas_current{namespace="$2", statefulset=~"$3"}, "owner_kind", "StatefulSet", "", ""), "workload", "", "statefulset")) by (namespace, owner_kind, workload), "workload", ":", "owner_kind", "workload")`,
|
||||
"workload_daemonset_replica": `label_join(sum (label_join(label_replace(kube_daemonset_status_desired_number_scheduled{namespace="$2", daemonset=~"$3"}, "owner_kind", "DaemonSet", "", ""), "workload", "", "daemonset")) by (namespace, owner_kind, workload), "workload", ":", "owner_kind", "workload")`,
|
||||
"workload_daemonset_replica_available": `label_join(sum (label_join(label_replace(kube_daemonset_status_number_available{namespace="$2", daemonset=~"$3"}, "owner_kind", "DaemonSet", "", ""), "workload", "", "daemonset")) by (namespace, owner_kind, workload), "workload", ":", "owner_kind", "workload")`,
|
||||
|
||||
// container
|
||||
"container_cpu_usage": `sum(irate(container_cpu_usage_seconds_total{namespace="$1", pod_name="$2", container_name!="POD", container_name=~"$3"}[5m])) by (namespace, pod_name, container_name)`,
|
||||
"container_memory_usage": `sum(container_memory_usage_bytes{namespace="$1", pod_name="$2", container_name!="POD", container_name=~"$3"}) by (namespace, pod_name, container_name)`,
|
||||
"container_memory_usage_wo_cache": `container_memory_usage_bytes{namespace="$1", pod_name="$2", container_name!="POD", container_name=~"$3"} - ignoring(id, image, endpoint, instance, job, name, service) container_memory_cache{namespace="$1", pod_name="$2", container_name!="POD", container_name=~"$3"}`,
|
||||
"container_net_bytes_transmitted": `sum(irate(container_network_transmit_bytes_total{job="kubelet", namespace="$1", pod_name="$2", container_name="POD", ` + ExcludedVirtualNetworkInterfaces + `}[5m])) by (namespace, pod_name, container_name)`,
|
||||
"container_net_bytes_received": `sum(irate(container_network_receive_bytes_total{job="kubelet", namespace="$1", pod_name="$2", container_name="POD", ` + ExcludedVirtualNetworkInterfaces + `}[5m])) by (namespace, pod_name, container_name)`,
|
||||
|
||||
"container_cpu_usage_node": `sum by (node, pod_name, container_name) (irate(container_cpu_usage_seconds_total{job="kubelet", pod_name="$2", container_name!="POD", container_name!="", container_name=~"$3", image!=""}[5m]) * on (pod_name) group_left(node) label_join(node_namespace_pod:kube_pod_info:{node="$1"}, "pod_name", "", "pod", "_name"))`,
|
||||
"container_memory_usage_node": `sum by (node, pod_name, container_name) (container_memory_usage_bytes{job="kubelet", pod_name="$2", container_name!="POD", container_name!="", container_name=~"$3", image!=""} * on (pod_name) group_left(node) label_join(node_namespace_pod:kube_pod_info:{node="$1"}, "pod_name", "", "pod", "_name"))`,
|
||||
"container_memory_usage_wo_cache_node": `sum by (node, pod_name, container_name) ((container_memory_usage_bytes{job="kubelet", pod_name="$2", container_name!="POD", container_name!="", container_name=~"$3", image!=""} - container_memory_cache{job="kubelet", pod_name="$2", container_name!="POD", container_name!="", container_name=~"$3", image!=""}) * on (pod_name) group_left(node) label_join(node_namespace_pod:kube_pod_info:{node="$1"}, "pod_name", "", "pod", "_name"))`,
|
||||
"container_net_bytes_transmitted_node": `sum by (node, pod_name, container_name) (irate(container_network_transmit_bytes_total{job="kubelet", ` + ExcludedVirtualNetworkInterfaces + `, pod_name="$2", container_name="POD", container_name!="", image!=""}[5m]) * on (pod_name) group_left(node) label_join(node_namespace_pod:kube_pod_info:{node="$1"}, "pod_name", "", "pod", "_name"))`,
|
||||
"container_net_bytes_received_node": `sum by (node, pod_name, container_name) (irate(container_network_receive_bytes_total{job="kubelet", ` + ExcludedVirtualNetworkInterfaces + `, pod_name="$2", container_name="POD", container_name!="", image!=""}[5m]) * on (pod_name) group_left(node) label_join(node_namespace_pod:kube_pod_info:{node="$1"}, "pod_name", "", "pod", "_name"))`,
|
||||
|
||||
// workspace
|
||||
"workspace_cpu_usage": `sum(namespace:container_cpu_usage_seconds_total:sum_rate{namespace!="", namespace$1})`,
|
||||
"workspace_memory_usage": `sum(namespace:container_memory_usage_bytes:sum{namespace!="", namespace$1})`,
|
||||
"workspace_memory_usage_wo_cache": `sum(namespace:container_memory_usage_bytes_wo_cache:sum{namespace!="", namespace$1})`,
|
||||
"workspace_net_bytes_transmitted": `sum(sum by (namespace) (irate(container_network_transmit_bytes_total{namespace!="", namespace$1, pod_name!="", ` + ExcludedVirtualNetworkInterfaces + `, job="kubelet"}[5m])))`,
|
||||
"workspace_net_bytes_received": `sum(sum by (namespace) (irate(container_network_receive_bytes_total{namespace!="", namespace$1, pod_name!="", ` + ExcludedVirtualNetworkInterfaces + `, job="kubelet"}[5m])))`,
|
||||
"workspace_pod_count": `sum(kube_pod_status_phase{phase!~"Failed|Succeeded", namespace!="", namespace$1})`,
|
||||
"workspace_pod_running_count": `sum(kube_pod_status_phase{phase="Running", namespace!="", namespace$1})`,
|
||||
"workspace_pod_succeeded_count": `sum(kube_pod_status_phase{phase="Succeeded", namespace!="", namespace$1})`,
|
||||
"workspace_pod_abnormal_count": `sum(kube_pod_status_phase{phase=~"Failed|Pending|Unknown", namespace!="", namespace$1})`,
|
||||
|
||||
"workspace_configmap_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="count/configmaps"}) by (resource, type)`,
|
||||
"workspace_jobs_batch_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="count/jobs.batch"}) by (resource, type)`,
|
||||
"workspace_roles_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="count/roles.rbac.authorization.k8s.io"}) by (resource, type)`,
|
||||
"workspace_memory_limit_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="limits.memory"}) by (resource, type)`,
|
||||
"workspace_pvc_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="persistentvolumeclaims"}) by (resource, type)`,
|
||||
"workspace_memory_request_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="requests.memory"}) by (resource, type)`,
|
||||
"workspace_pvc_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="count/persistentvolumeclaims"}) by (resource, type)`,
|
||||
"workspace_cronjobs_batch_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="count/cronjobs.batch"}) by (resource, type)`,
|
||||
"workspace_ingresses_extensions_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="count/ingresses.extensions"}) by (resource, type)`,
|
||||
"workspace_cpu_limit_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="limits.cpu"}) by (resource, type)`,
|
||||
"workspace_storage_request_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="requests.storage"}) by (resource, type)`,
|
||||
"workspace_deployment_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="count/deployments.apps"}) by (resource, type)`,
|
||||
"workspace_pod_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="count/pods"}) by (resource, type)`,
|
||||
"workspace_statefulset_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="count/statefulsets.apps"}) by (resource, type)`,
|
||||
"workspace_daemonset_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="count/daemonsets.apps"}) by (resource, type)`,
|
||||
"workspace_secret_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="count/secrets"}) by (resource, type)`,
|
||||
"workspace_service_count_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="count/services"}) by (resource, type)`,
|
||||
"workspace_cpu_request_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="requests.cpu"}) by (resource, type)`,
|
||||
"workspace_service_loadbalancer_used": `sum(kube_resourcequota{resourcequota!="quota", type="used", namespace!="", namespace$1, resource="services.loadbalancers"}) by (resource, type)`,
|
||||
|
||||
"workspace_ingresses_extensions_count": `sum(kube_ingress_labels{namespace!="", namespace$1})`,
|
||||
|
||||
"workspace_cronjob_count": `sum(kube_cronjob_labels{namespace!="", namespace$1})`,
|
||||
"workspace_pvc_count": `sum(kube_persistentvolumeclaim_info{namespace!="", namespace$1})`,
|
||||
"workspace_daemonset_count": `sum(kube_daemonset_labels{namespace!="", namespace$1})`,
|
||||
"workspace_deployment_count": `sum(kube_deployment_labels{namespace!="", namespace$1})`,
|
||||
"workspace_endpoint_count": `sum(kube_endpoint_labels{namespace!="", namespace$1})`,
|
||||
"workspace_hpa_count": `sum(kube_hpa_labels{namespace!="", namespace$1})`,
|
||||
"workspace_job_count": `sum(kube_job_labels{namespace!="", namespace$1})`,
|
||||
"workspace_statefulset_count": `sum(kube_statefulset_labels{namespace!="", namespace$1})`,
|
||||
"workspace_replicaset_count": `count(kube_replicaset_created{namespace!="", namespace$1})`,
|
||||
"workspace_service_count": `sum(kube_service_info{namespace!="", namespace$1})`,
|
||||
"workspace_secret_count": `sum(kube_secret_info{namespace!="", namespace$1})`,
|
||||
|
||||
"workspace_all_project_count": `count(kube_namespace_annotations)`,
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
func GetNamespacesWithMetrics(namespaces []*v1.Namespace) []*v1.Namespace {
|
||||
var nsNameList []string
|
||||
for i := range namespaces {
|
||||
nsNameList = append(nsNameList, namespaces[i].Name)
|
||||
}
|
||||
nsFilter := "^(" + strings.Join(nsNameList, "|") + ")$"
|
||||
var timeRelateParams = make(url.Values)
|
||||
|
||||
params := client.MonitoringRequestParams{
|
||||
NsFilter: nsFilter,
|
||||
Params: timeRelateParams,
|
||||
QueryType: client.DefaultQueryType,
|
||||
MetricsFilter: "namespace_cpu_usage|namespace_memory_usage_wo_cache|namespace_pod_count",
|
||||
}
|
||||
|
||||
rawMetrics := MonitorAllMetrics(¶ms, MetricLevelNamespace)
|
||||
|
||||
for _, result := range rawMetrics.Results {
|
||||
for _, data := range result.Data.Result {
|
||||
metricDescMap, ok := data["metric"].(map[string]interface{})
|
||||
if ok {
|
||||
if ns, exist := metricDescMap["namespace"]; exist {
|
||||
timeAndValue, ok := data["value"].([]interface{})
|
||||
if ok && len(timeAndValue) == 2 {
|
||||
for i := 0; i < len(namespaces); i++ {
|
||||
if namespaces[i].Name == ns {
|
||||
if namespaces[i].Annotations == nil {
|
||||
namespaces[i].Annotations = make(map[string]string, 0)
|
||||
}
|
||||
namespaces[i].Annotations[result.MetricName] = timeAndValue[1].(string)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return namespaces
|
||||
}
|
||||
0
pkg/models/metrics/nodes.go
Executable file → Normal file
0
pkg/models/metrics/nodes.go
Executable file → Normal file
0
pkg/models/metrics/pods.go
Executable file → Normal file
0
pkg/models/metrics/pods.go
Executable file → Normal file
@@ -1,298 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sort"
|
||||
"strconv"
|
||||
"unicode"
|
||||
|
||||
"runtime/debug"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultPageLimit = 5
|
||||
DefaultPage = 1
|
||||
)
|
||||
|
||||
type FormatedMetricDataWrapper struct {
|
||||
fmtMetricData FormatedMetricData
|
||||
by func(p, q *map[string]interface{}) bool
|
||||
}
|
||||
|
||||
func (wrapper FormatedMetricDataWrapper) Len() int {
|
||||
return len(wrapper.fmtMetricData.Result)
|
||||
}
|
||||
|
||||
func (wrapper FormatedMetricDataWrapper) Less(i, j int) bool {
|
||||
return wrapper.by(&wrapper.fmtMetricData.Result[i], &wrapper.fmtMetricData.Result[j])
|
||||
}
|
||||
|
||||
func (wrapper FormatedMetricDataWrapper) Swap(i, j int) {
|
||||
wrapper.fmtMetricData.Result[i], wrapper.fmtMetricData.Result[j] = wrapper.fmtMetricData.Result[j], wrapper.fmtMetricData.Result[i]
|
||||
}
|
||||
|
||||
// sorted metric by ascending or descending order
|
||||
func Sort(sortMetricName string, sortType string, fmtLevelMetric *FormatedLevelMetric, resourceType string) (*FormatedLevelMetric, int) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
glog.Errorln(err)
|
||||
debug.PrintStack()
|
||||
}
|
||||
}()
|
||||
|
||||
if sortMetricName == "" {
|
||||
return fmtLevelMetric, -1
|
||||
}
|
||||
|
||||
// default sort type is descending order
|
||||
if sortType == "" {
|
||||
sortType = ResultSortTypeDesc
|
||||
}
|
||||
|
||||
var currentResourceMap = make(map[string]int)
|
||||
|
||||
// indexMap store sorted index for each node/namespace/pod
|
||||
var indexMap = make(map[string]int)
|
||||
i := 0
|
||||
for _, metricItem := range fmtLevelMetric.Results {
|
||||
if metricItem.Data.ResultType == ResultTypeVector && metricItem.Status == MetricStatusSuccess {
|
||||
if metricItem.MetricName == sortMetricName {
|
||||
if sortType == ResultSortTypeAsce {
|
||||
// desc
|
||||
sort.Sort(FormatedMetricDataWrapper{metricItem.Data, func(p, q *map[string]interface{}) bool {
|
||||
value1 := (*p)[ResultItemValue].([]interface{})
|
||||
value2 := (*q)[ResultItemValue].([]interface{})
|
||||
v1, _ := strconv.ParseFloat(value1[len(value1)-1].(string), 64)
|
||||
v2, _ := strconv.ParseFloat(value2[len(value2)-1].(string), 64)
|
||||
if v1 == v2 {
|
||||
resourceName1 := (*p)[ResultItemMetric].(map[string]interface{})[resourceType]
|
||||
resourceName2 := (*q)[ResultItemMetric].(map[string]interface{})[resourceType]
|
||||
return resourceName1.(string) < resourceName2.(string)
|
||||
}
|
||||
|
||||
return v1 < v2
|
||||
}})
|
||||
} else {
|
||||
// desc
|
||||
sort.Sort(FormatedMetricDataWrapper{metricItem.Data, func(p, q *map[string]interface{}) bool {
|
||||
value1 := (*p)[ResultItemValue].([]interface{})
|
||||
value2 := (*q)[ResultItemValue].([]interface{})
|
||||
v1, _ := strconv.ParseFloat(value1[len(value1)-1].(string), 64)
|
||||
v2, _ := strconv.ParseFloat(value2[len(value2)-1].(string), 64)
|
||||
|
||||
if v1 == v2 {
|
||||
resourceName1 := (*p)[ResultItemMetric].(map[string]interface{})[resourceType]
|
||||
resourceName2 := (*q)[ResultItemMetric].(map[string]interface{})[resourceType]
|
||||
return resourceName1.(string) > resourceName2.(string)
|
||||
}
|
||||
|
||||
return v1 > v2
|
||||
}})
|
||||
}
|
||||
|
||||
for _, r := range metricItem.Data.Result {
|
||||
// for some reasons, 'metric' may not contain `resourceType` field
|
||||
// example: {"metric":{},"value":[1541142931.731,"3"]}
|
||||
k, exist := r[ResultItemMetric].(map[string]interface{})[resourceType]
|
||||
key := k.(string)
|
||||
if exist {
|
||||
if _, exist := indexMap[key]; !exist {
|
||||
indexMap[key] = i
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// iterator all metric to find max metricItems length
|
||||
for _, r := range metricItem.Data.Result {
|
||||
k, ok := r[ResultItemMetric].(map[string]interface{})[resourceType]
|
||||
if ok {
|
||||
currentResourceMap[k.(string)] = 1
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var keys []string
|
||||
for k := range currentResourceMap {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, resource := range keys {
|
||||
if _, exist := indexMap[resource]; !exist {
|
||||
indexMap[resource] = i
|
||||
i = i + 1
|
||||
}
|
||||
}
|
||||
|
||||
// sort other metric
|
||||
for i := 0; i < len(fmtLevelMetric.Results); i++ {
|
||||
re := fmtLevelMetric.Results[i]
|
||||
if re.Data.ResultType == ResultTypeVector && re.Status == MetricStatusSuccess {
|
||||
sortedMetric := make([]map[string]interface{}, len(indexMap))
|
||||
for j := 0; j < len(re.Data.Result); j++ {
|
||||
r := re.Data.Result[j]
|
||||
k, exist := r[ResultItemMetric].(map[string]interface{})[resourceType]
|
||||
if exist {
|
||||
index, exist := indexMap[k.(string)]
|
||||
if exist {
|
||||
sortedMetric[index] = r
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmtLevelMetric.Results[i].Data.Result = sortedMetric
|
||||
}
|
||||
}
|
||||
|
||||
return fmtLevelMetric, len(indexMap)
|
||||
}
|
||||
|
||||
func Page(pageNum string, limitNum string, fmtLevelMetric *FormatedLevelMetric, maxLength int) interface{} {
|
||||
if maxLength <= 0 {
|
||||
return fmtLevelMetric
|
||||
}
|
||||
// matrix type can not be sorted
|
||||
for _, metricItem := range fmtLevelMetric.Results {
|
||||
if metricItem.Data.ResultType != ResultTypeVector {
|
||||
return fmtLevelMetric
|
||||
}
|
||||
}
|
||||
|
||||
var page = DefaultPage
|
||||
|
||||
if pageNum != "" {
|
||||
p, err := strconv.Atoi(pageNum)
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
} else {
|
||||
if p > 0 {
|
||||
page = p
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// the default mode is none paging
|
||||
return fmtLevelMetric
|
||||
}
|
||||
|
||||
var limit = DefaultPageLimit
|
||||
|
||||
if limitNum != "" {
|
||||
l, err := strconv.Atoi(limitNum)
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
} else {
|
||||
if l > 0 {
|
||||
limit = l
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the i page: [(page-1) * limit, (page) * limit - 1]
|
||||
start := (page - 1) * limit
|
||||
end := (page)*limit - 1
|
||||
|
||||
for i := 0; i < len(fmtLevelMetric.Results); i++ {
|
||||
// only pageing when result type is `vector` and result status is `success`
|
||||
if fmtLevelMetric.Results[i].Data.ResultType != ResultTypeVector || fmtLevelMetric.Results[i].Status != MetricStatusSuccess {
|
||||
continue
|
||||
}
|
||||
resultLen := len(fmtLevelMetric.Results[i].Data.Result)
|
||||
if start >= resultLen {
|
||||
fmtLevelMetric.Results[i].Data.Result = nil
|
||||
continue
|
||||
}
|
||||
if end >= resultLen {
|
||||
end = resultLen - 1
|
||||
}
|
||||
slice := fmtLevelMetric.Results[i].Data.Result[start : end+1]
|
||||
fmtLevelMetric.Results[i].Data.Result = slice
|
||||
}
|
||||
|
||||
allPage := int(math.Ceil(float64(maxLength) / float64(limit)))
|
||||
|
||||
return &PagedFormatedLevelMetric{
|
||||
Message: "paged",
|
||||
TotalPage: allPage,
|
||||
TotalItem: maxLength,
|
||||
CurrentPage: page,
|
||||
Metric: *fmtLevelMetric,
|
||||
}
|
||||
}
|
||||
|
||||
// maybe this function is time consuming
|
||||
func ReformatJson(metric string, metricsName string, needDelParams ...string) *FormatedMetric {
|
||||
var formatMetric FormatedMetric
|
||||
|
||||
err := jsonIter.Unmarshal([]byte(metric), &formatMetric)
|
||||
if err != nil {
|
||||
glog.Errorln("Unmarshal metric json failed", err.Error(), metric)
|
||||
}
|
||||
if formatMetric.MetricName == "" {
|
||||
if metricsName != "" {
|
||||
formatMetric.MetricName = metricsName
|
||||
}
|
||||
}
|
||||
// retrive metrics success
|
||||
if formatMetric.Status == MetricStatusSuccess {
|
||||
result := formatMetric.Data.Result
|
||||
for _, res := range result {
|
||||
metric, exist := res[ResultItemMetric]
|
||||
metricMap, sure := metric.(map[string]interface{})
|
||||
if exist && sure {
|
||||
delete(metricMap, "__name__")
|
||||
}
|
||||
if len(needDelParams) > 0 {
|
||||
for _, p := range needDelParams {
|
||||
delete(metricMap, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &formatMetric
|
||||
}
|
||||
|
||||
func ReformatNodeStatusField(nodeMetric *FormatedMetric) *FormatedMetric {
|
||||
metricCount := len(nodeMetric.Data.Result)
|
||||
for i := 0; i < metricCount; i++ {
|
||||
metric, exist := nodeMetric.Data.Result[i][ResultItemMetric]
|
||||
if exist {
|
||||
status, exist := metric.(map[string]interface{})[MetricStatus]
|
||||
if exist {
|
||||
status = UpperFirstLetter(status.(string))
|
||||
metric.(map[string]interface{})[MetricStatus] = status
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodeMetric
|
||||
}
|
||||
|
||||
func UpperFirstLetter(str string) string {
|
||||
for i, ch := range str {
|
||||
return string(unicode.ToUpper(ch)) + str[i+1:]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -40,15 +40,12 @@ const (
|
||||
persistentvolumeclaimsKey = "persistentvolumeclaims"
|
||||
storageClassesKey = "count/storageClass"
|
||||
namespaceKey = "count/namespace"
|
||||
jobsKey = "count/jobs.batch"
|
||||
cronJobsKey = "count/cronjobs.batch"
|
||||
)
|
||||
|
||||
var resourceMap = map[string]string{daemonsetsKey: controllers.Daemonsets, deploymentsKey: controllers.Deployments,
|
||||
ingressKey: controllers.Ingresses, rolesKey: controllers.Roles, servicesKey: controllers.Services,
|
||||
statefulsetsKey: controllers.Statefulsets, persistentvolumeclaimsKey: controllers.PersistentVolumeClaim, podsKey: controllers.Pods,
|
||||
namespaceKey: controllers.Namespaces, storageClassesKey: controllers.StorageClasses, clusterRolesKey: controllers.ClusterRoles,
|
||||
jobsKey: controllers.Jobs, cronJobsKey: controllers.Cronjobs}
|
||||
namespaceKey: controllers.Namespaces, storageClassesKey: controllers.StorageClasses, clusterRolesKey: controllers.ClusterRoles}
|
||||
|
||||
type ResourceQuota struct {
|
||||
NameSpace string `json:"namespace"`
|
||||
|
||||
@@ -1,19 +1,3 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
@@ -40,19 +24,11 @@ type ResourceList struct {
|
||||
Items interface{} `json:"items,omitempty"`
|
||||
}
|
||||
|
||||
type searchConditions struct {
|
||||
match map[string]string
|
||||
fuzzy map[string]string
|
||||
matchOr map[string]string
|
||||
fuzzyOr map[string]string
|
||||
}
|
||||
|
||||
func getController(resource string) (controllers.Controller, error) {
|
||||
switch resource {
|
||||
case controllers.Deployments, controllers.Statefulsets, controllers.Daemonsets, controllers.Ingresses,
|
||||
controllers.PersistentVolumeClaim, controllers.Roles, controllers.ClusterRoles, controllers.Services,
|
||||
controllers.Pods, controllers.Namespaces, controllers.StorageClasses, controllers.Jobs, controllers.Cronjobs,
|
||||
controllers.Nodes, controllers.Secrets, controllers.ConfigMaps:
|
||||
controllers.Pods, controllers.Namespaces, controllers.StorageClasses:
|
||||
|
||||
return controllers.ResourceControllers.Controllers[resource], nil
|
||||
default:
|
||||
@@ -62,21 +38,20 @@ func getController(resource string) (controllers.Controller, error) {
|
||||
|
||||
}
|
||||
|
||||
func getConditions(str string) (*searchConditions, map[string]string, error) {
|
||||
func getConditions(str string) (map[string]string, map[string]string, error) {
|
||||
match := make(map[string]string)
|
||||
fuzzy := make(map[string]string)
|
||||
matchOr := make(map[string]string)
|
||||
fuzzyOr := make(map[string]string)
|
||||
orderField := make(map[string]string)
|
||||
|
||||
if len(str) == 0 {
|
||||
return nil, nil, nil
|
||||
}
|
||||
list := strings.Split(str, ",")
|
||||
for _, item := range list {
|
||||
if strings.Count(item, "=") >= 2 {
|
||||
return nil, nil, errors.New("invalid condition input, invalid character \"=\"")
|
||||
}
|
||||
|
||||
conditions := strings.Split(str, ",")
|
||||
for _, item := range conditions {
|
||||
if strings.Count(item, "=") >= 2 || strings.Count(item, "~") >= 2 {
|
||||
return nil, nil, errors.New("invalid condition input")
|
||||
if strings.Count(item, "~") >= 2 {
|
||||
return nil, nil, errors.New("invalid condition input, invalid character \"~\"")
|
||||
}
|
||||
|
||||
if strings.Count(item, "=") == 1 {
|
||||
@@ -84,17 +59,7 @@ func getConditions(str string) (*searchConditions, map[string]string, error) {
|
||||
if len(kvs) < 2 || len(kvs[1]) == 0 {
|
||||
return nil, nil, errors.New("invalid condition input")
|
||||
}
|
||||
|
||||
if !strings.Contains(kvs[0], "|") {
|
||||
match[kvs[0]] = kvs[1]
|
||||
} else {
|
||||
multiFields := strings.Split(kvs[0], "|")
|
||||
for _, filed := range multiFields {
|
||||
if len(filed) > 0 {
|
||||
matchOr[filed] = kvs[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
match[kvs[0]] = kvs[1]
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -103,132 +68,86 @@ func getConditions(str string) (*searchConditions, map[string]string, error) {
|
||||
if len(kvs) < 2 || len(kvs[1]) == 0 {
|
||||
return nil, nil, errors.New("invalid condition input")
|
||||
}
|
||||
if !strings.Contains(kvs[0], "|") {
|
||||
fuzzy[kvs[0]] = kvs[1]
|
||||
} else {
|
||||
multiFields := strings.Split(kvs[0], "|")
|
||||
if len(multiFields) > 1 && len(multiFields[1]) > 0 {
|
||||
orderField[multiFields[0]] = kvs[1]
|
||||
}
|
||||
for _, filed := range multiFields {
|
||||
if len(filed) > 0 {
|
||||
fuzzyOr[filed] = kvs[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
fuzzy[kvs[0]] = kvs[1]
|
||||
continue
|
||||
}
|
||||
|
||||
return nil, nil, errors.New("invalid condition input")
|
||||
}
|
||||
|
||||
return &searchConditions{match: match, fuzzyOr: fuzzyOr, matchOr: matchOr, fuzzy: fuzzy}, orderField, nil
|
||||
}
|
||||
return match, fuzzy, nil
|
||||
}
|
||||
|
||||
func getPaging(resourceName, pagingStr string) (*controllers.Paging, error) {
|
||||
defaultPaging := &controllers.Paging{Limit: 10, Offset: 0, Page: 1}
|
||||
paging := controllers.Paging{}
|
||||
|
||||
func getPaging(resourceName, pagingStr string) (*controllers.Paging, map[string]int, error) {
|
||||
defaultPaging := &controllers.Paging{Limit: 10, Offset: 0}
|
||||
defautlPagingMap := map[string]int{"page": 1, "limit": 10}
|
||||
if resourceName == controllers.Namespaces {
|
||||
defaultPaging = nil
|
||||
defautlPagingMap = map[string]int{"page": 0, "limit": 0}
|
||||
}
|
||||
pagingMap := make(map[string]int)
|
||||
|
||||
if len(pagingStr) == 0 {
|
||||
return defaultPaging, nil
|
||||
return defaultPaging, defautlPagingMap, nil
|
||||
}
|
||||
|
||||
list := strings.Split(pagingStr, ",")
|
||||
for _, item := range list {
|
||||
kvs := strings.Split(item, "=")
|
||||
if len(kvs) < 2 {
|
||||
return nil, errors.New("invalid Paging input")
|
||||
return nil, nil, errors.New("invalid Paging input")
|
||||
}
|
||||
|
||||
value, err := strconv.Atoi(kvs[1])
|
||||
if err != nil || value <= 0 {
|
||||
return nil, errors.New("invalid Paging input")
|
||||
if err != nil {
|
||||
return nil, nil, errors.New("invalid Paging input")
|
||||
}
|
||||
|
||||
if kvs[0] == limit {
|
||||
paging.Limit = value
|
||||
}
|
||||
|
||||
if kvs[0] == page {
|
||||
paging.Page = value
|
||||
}
|
||||
pagingMap[kvs[0]] = value
|
||||
}
|
||||
|
||||
if paging.Limit > 0 && paging.Page > 0 {
|
||||
paging.Offset = (paging.Page - 1) * paging.Limit
|
||||
return &paging, nil
|
||||
if pagingMap[limit] <= 0 || pagingMap[page] <= 0 {
|
||||
return nil, nil, errors.New("invalid Paging input")
|
||||
}
|
||||
|
||||
return defaultPaging, nil
|
||||
if pagingMap[limit] > 0 && pagingMap[page] > 0 {
|
||||
offset := (pagingMap[page] - 1) * pagingMap[limit]
|
||||
return &controllers.Paging{Limit: pagingMap[limit], Offset: offset}, pagingMap, nil
|
||||
}
|
||||
|
||||
return defaultPaging, defautlPagingMap, nil
|
||||
}
|
||||
|
||||
func generateOrder(orderField map[string]string, order string) string {
|
||||
if len(orderField) == 0 {
|
||||
return order
|
||||
}
|
||||
|
||||
var str string
|
||||
for k, v := range orderField {
|
||||
if len(str) > 0 {
|
||||
str = fmt.Sprintf("%s, (%s like '%%%s%%')", str, k, v)
|
||||
} else {
|
||||
str = fmt.Sprintf("(%s like '%%%s%%')", k, v)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if len(order) == 0 {
|
||||
return fmt.Sprintf("%s desc", str)
|
||||
} else {
|
||||
return fmt.Sprintf("%s, %s", str, order)
|
||||
}
|
||||
}
|
||||
|
||||
func ListResource(resourceName, conditonSrt, pagingStr, order string) (*ResourceList, error) {
|
||||
conditions, OrderFields, err := getConditions(conditonSrt)
|
||||
func ListResource(resourceName, conditonSrt, pagingStr string) (*ResourceList, error) {
|
||||
match, fuzzy, err := getConditions(conditonSrt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
order = generateOrder(OrderFields, order)
|
||||
conditionStr := generateConditionStr(conditions)
|
||||
|
||||
paging, err := getPaging(resourceName, pagingStr)
|
||||
paging, pagingMap, err := getPaging(resourceName, pagingStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
conditionStr := generateConditionStr(match, fuzzy)
|
||||
|
||||
ctl, err := getController(resourceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
total, items, err := ctl.ListWithConditions(conditionStr, paging, order)
|
||||
total, items, err := ctl.ListWithConditions(conditionStr, paging)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if paging != nil {
|
||||
return &ResourceList{Total: total, Items: items, Page: paging.Page, Limit: paging.Limit}, nil
|
||||
} else {
|
||||
return &ResourceList{Total: total, Items: items}, nil
|
||||
}
|
||||
return &ResourceList{Total: total, Items: items, Page: pagingMap[page], Limit: pagingMap[limit]}, nil
|
||||
}
|
||||
|
||||
func generateConditionStr(conditions *searchConditions) string {
|
||||
shouldUseAnd := false
|
||||
shouldUseBrackets := false
|
||||
func generateConditionStr(match map[string]string, fuzzy map[string]string) string {
|
||||
conditionStr := ""
|
||||
|
||||
if conditions == nil {
|
||||
return conditionStr
|
||||
}
|
||||
|
||||
for k, v := range conditions.match {
|
||||
for k, v := range match {
|
||||
if len(conditionStr) == 0 {
|
||||
conditionStr = fmt.Sprintf("%s = \"%s\" ", k, v)
|
||||
} else {
|
||||
@@ -236,7 +155,7 @@ func generateConditionStr(conditions *searchConditions) string {
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range conditions.fuzzy {
|
||||
for k, v := range fuzzy {
|
||||
if len(conditionStr) == 0 {
|
||||
conditionStr = fmt.Sprintf("%s like '%%%s%%' ", k, v)
|
||||
} else {
|
||||
@@ -244,42 +163,6 @@ func generateConditionStr(conditions *searchConditions) string {
|
||||
}
|
||||
}
|
||||
|
||||
if len(conditionStr) > 0 {
|
||||
shouldUseAnd = true
|
||||
}
|
||||
|
||||
for k, v := range conditions.matchOr {
|
||||
if len(conditionStr) == 0 {
|
||||
conditionStr = fmt.Sprintf("%s = \"%s\" ", k, v)
|
||||
} else {
|
||||
if shouldUseAnd {
|
||||
conditionStr = fmt.Sprintf("%s And (%s = \"%s\" ", conditionStr, k, v)
|
||||
shouldUseBrackets = true
|
||||
shouldUseAnd = false
|
||||
} else {
|
||||
conditionStr = fmt.Sprintf("%s OR %s = \"%s\" ", conditionStr, k, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range conditions.fuzzyOr {
|
||||
if len(conditionStr) == 0 {
|
||||
conditionStr = fmt.Sprintf("%s like '%%%s%%' ", k, v)
|
||||
} else {
|
||||
if shouldUseAnd {
|
||||
conditionStr = fmt.Sprintf("%s And (%s like '%%%s%%' ", conditionStr, k, v)
|
||||
shouldUseAnd = false
|
||||
shouldUseBrackets = true
|
||||
} else {
|
||||
conditionStr = fmt.Sprintf("%s OR %s like '%%%s%%' ", conditionStr, k, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if shouldUseBrackets {
|
||||
conditionStr = fmt.Sprintf("%s )", conditionStr)
|
||||
}
|
||||
|
||||
return conditionStr
|
||||
}
|
||||
|
||||
@@ -299,9 +182,9 @@ func GetNamespacesResourceStatus(namespace string) (*workLoadStatus, error) {
|
||||
notReadyStatus = controllers.PvcPending
|
||||
}
|
||||
if len(namespace) > 0 {
|
||||
status, err = ListResource(resource, fmt.Sprintf("status=%s,namespace=%s", notReadyStatus, namespace), "", "")
|
||||
status, err = ListResource(resource, fmt.Sprintf("status=%s,namespace=%s", notReadyStatus, namespace), "")
|
||||
} else {
|
||||
status, err = ListResource(resource, fmt.Sprintf("status=%s", notReadyStatus), "", "")
|
||||
status, err = ListResource(resource, fmt.Sprintf("status=%s", notReadyStatus), "")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -325,30 +208,25 @@ func GetApplication(clusterId string) (interface{}, error) {
|
||||
return ctl.GetApp(clusterId)
|
||||
}
|
||||
|
||||
func ListApplication(runtimeId, conditionStr, pagingStr string) (*ResourceList, error) {
|
||||
paging, err := getPaging(controllers.Applications, pagingStr)
|
||||
func ListApplication(runtimeId, conditions, pagingStr string) (*ResourceList, error) {
|
||||
paging, pagingMap, err := getPaging(controllers.Applications, pagingStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
conditions, _, err := getConditions(conditionStr)
|
||||
match, fuzzy, err := getConditions(conditions)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if conditions == nil {
|
||||
conditions = &searchConditions{}
|
||||
}
|
||||
|
||||
ctl := &controllers.ApplicationCtl{OpenpitrixAddr: options.ServerOptions.GetOpAddress()}
|
||||
|
||||
total, items, err := ctl.ListApplication(runtimeId, conditions.match, conditions.fuzzy, paging)
|
||||
total, items, err := ctl.ListApplication(runtimeId, match, fuzzy, paging)
|
||||
|
||||
if err != nil {
|
||||
glog.Errorf("get application list failed, reason: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ResourceList{Total: total, Items: items, Page: paging.Page, Limit: paging.Limit}, nil
|
||||
return &ResourceList{Total: total, Items: items, Page: pagingMap[page], Limit: pagingMap[limit]}, nil
|
||||
}
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/apps/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
appsV1 "k8s.io/client-go/listers/apps/v1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/models/controllers"
|
||||
)
|
||||
|
||||
func GetDeployRevision(namespace, name, revision string) (*v1.ReplicaSet, error) {
|
||||
deployLister := controllers.ResourceControllers.Controllers[controllers.Deployments].Lister().(appsV1.DeploymentLister)
|
||||
deploy, err := deployLister.Deployments(namespace).Get(name)
|
||||
if err != nil {
|
||||
glog.Errorf("get deployment %s failed, reason: %s", name, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
labelMap := deploy.Spec.Template.Labels
|
||||
labelSelector := labels.Set(labelMap).AsSelector()
|
||||
|
||||
rsLister := controllers.ResourceControllers.Controllers[controllers.Replicasets].Lister().(appsV1.ReplicaSetLister)
|
||||
rsList, err := rsLister.ReplicaSets(namespace).List(labelSelector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, rs := range rsList {
|
||||
if rs.Annotations["deployment.kubernetes.io/revision"] == revision {
|
||||
return rs, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.NewNotFound(v1.Resource("deployment revision"), fmt.Sprintf("%s#%s", name, revision))
|
||||
}
|
||||
|
||||
func GetDaemonSetRevision(namespace, name, revision string) (*v1.ControllerRevision, error) {
|
||||
revisionInt, err := strconv.Atoi(revision)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dsLister := controllers.ResourceControllers.Controllers[controllers.Daemonsets].Lister().(appsV1.DaemonSetLister)
|
||||
ds, err := dsLister.DaemonSets(namespace).Get(name)
|
||||
if err != nil {
|
||||
glog.Errorf("get Daemonset %s failed, reason: %s", name, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
labels := ds.Spec.Template.Labels
|
||||
|
||||
return getControllerRevision(namespace, name, labels, revisionInt)
|
||||
}
|
||||
|
||||
func GetStatefulSetRevision(namespace, name, revision string) (*v1.ControllerRevision, error) {
|
||||
revisionInt, err := strconv.Atoi(revision)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stLister := controllers.ResourceControllers.Controllers[controllers.Statefulsets].Lister().(appsV1.StatefulSetLister)
|
||||
st, err := stLister.StatefulSets(namespace).Get(name)
|
||||
if err != nil {
|
||||
glog.Errorf("get Daemonset %s failed, reason: %s", name, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
labels := st.Spec.Template.Labels
|
||||
|
||||
return getControllerRevision(namespace, name, labels, revisionInt)
|
||||
}
|
||||
|
||||
func getControllerRevision(namespace, name string, labelMap map[string]string, revision int) (*v1.ControllerRevision, error) {
|
||||
|
||||
labelSelector := labels.Set(labelMap).AsSelector()
|
||||
|
||||
revisionLister := controllers.ResourceControllers.Controllers[controllers.ControllerRevisions].Lister().(appsV1.ControllerRevisionLister)
|
||||
revisions, err := revisionLister.ControllerRevisions(namespace).List(labelSelector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, controllerRevision := range revisions {
|
||||
if controllerRevision.Revision == int64(revision) {
|
||||
return controllerRevision, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.NewNotFound(v1.Resource("revision"), fmt.Sprintf("%s#%s", name, revision))
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package workspaces
|
||||
|
||||
import "time"
|
||||
|
||||
type Workspace struct {
|
||||
Group `json:",inline"`
|
||||
Admin string `json:"admin,omitempty"`
|
||||
Namespaces []string `json:"namespaces"`
|
||||
DevopsProjects []string `json:"devops_projects"`
|
||||
}
|
||||
|
||||
type UserInvite struct {
|
||||
Username string `json:"username"`
|
||||
Role string `json:"role"`
|
||||
}
|
||||
|
||||
type Group struct {
|
||||
Path string `json:"path"`
|
||||
Name string `json:"name"`
|
||||
Gid string `json:"gid"`
|
||||
Members []string `json:"members"`
|
||||
Logo string `json:"logo"`
|
||||
Creator string `json:"creator"`
|
||||
CreateTime string `json:"create_time"`
|
||||
ChildGroups []string `json:"child_groups,omitempty"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
func (g Group) GetCreateTime() (time.Time, error) {
|
||||
return time.Parse("2006-01-02T15:04:05Z", g.CreateTime)
|
||||
}
|
||||
|
||||
type WorkspaceDPBinding struct {
|
||||
Workspace string `gorm:"primary_key"`
|
||||
DevOpsProject string `gorm:"primary_key"`
|
||||
}
|
||||
|
||||
type DevopsProject struct {
|
||||
ProjectId *string `json:"project_id,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Creator string `json:"creator"`
|
||||
CreateTime *time.Time `json:"create_time,omitempty"`
|
||||
Status *string `json:"status"`
|
||||
Visibility *string `json:"visibility,omitempty"`
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,20 +0,0 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
)
|
||||
|
||||
func Wrap(data []byte) error {
|
||||
var j map[string]string
|
||||
err := json.Unmarshal(data, &j)
|
||||
if err != nil {
|
||||
return errors.New(string(data))
|
||||
} else if message := j["message"]; message != "" {
|
||||
return errors.New(message)
|
||||
} else if message := j["Error"]; message != "" {
|
||||
return errors.New(message)
|
||||
} else {
|
||||
return errors.New(string(data))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user