333 lines
8.4 KiB
Go
333 lines
8.4 KiB
Go
/*
|
|
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 (
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/golang/glog"
|
|
|
|
"kubesphere.io/kubesphere/pkg/models/controllers"
|
|
"kubesphere.io/kubesphere/pkg/options"
|
|
)
|
|
|
|
const (
|
|
limit = "limit"
|
|
page = "page"
|
|
)
|
|
|
|
type ResourceList struct {
|
|
Total int `json:"total,omitempty"`
|
|
Page int `json:"page,omitempty"`
|
|
Limit int `json:"limit,omitempty"`
|
|
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:
|
|
|
|
return controllers.ResourceControllers.Controllers[resource], nil
|
|
default:
|
|
return nil, fmt.Errorf("invalid resource Name '%s'", resource)
|
|
}
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
func getConditions(str string) (*searchConditions, 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
|
|
}
|
|
|
|
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, "=") == 1 {
|
|
kvs := strings.Split(item, "=")
|
|
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]
|
|
}
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
|
|
if strings.Count(item, "~") == 1 {
|
|
kvs := strings.Split(item, "~")
|
|
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]
|
|
}
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
|
|
return nil, nil, errors.New("invalid condition input")
|
|
}
|
|
|
|
return &searchConditions{match: match, fuzzyOr: fuzzyOr, matchOr: matchOr, fuzzy: fuzzy}, orderField, nil
|
|
}
|
|
|
|
func getPaging(resourceName, pagingStr string) (*controllers.Paging, error) {
|
|
defaultPaging := &controllers.Paging{Limit: 10, Offset: 0, Page: 1}
|
|
paging := controllers.Paging{}
|
|
|
|
if resourceName == controllers.Namespaces {
|
|
defaultPaging = nil
|
|
}
|
|
|
|
if len(pagingStr) == 0 {
|
|
return defaultPaging, nil
|
|
}
|
|
|
|
list := strings.Split(pagingStr, ",")
|
|
for _, item := range list {
|
|
kvs := strings.Split(item, "=")
|
|
if len(kvs) < 2 {
|
|
return 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 kvs[0] == limit {
|
|
paging.Limit = value
|
|
}
|
|
|
|
if kvs[0] == page {
|
|
paging.Page = value
|
|
}
|
|
}
|
|
|
|
if paging.Limit > 0 && paging.Page > 0 {
|
|
paging.Offset = (paging.Page - 1) * paging.Limit
|
|
return &paging, nil
|
|
}
|
|
|
|
return defaultPaging, 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)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
order = generateOrder(OrderFields, order)
|
|
conditionStr := generateConditionStr(conditions)
|
|
|
|
paging, err := getPaging(resourceName, pagingStr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ctl, err := getController(resourceName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
total, items, err := ctl.ListWithConditions(conditionStr, paging, order)
|
|
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
|
|
}
|
|
}
|
|
|
|
func generateConditionStr(conditions *searchConditions) string {
|
|
conditionStr := ""
|
|
|
|
if conditions == nil {
|
|
return conditionStr
|
|
}
|
|
|
|
for k, v := range conditions.match {
|
|
if len(conditionStr) == 0 {
|
|
conditionStr = fmt.Sprintf("%s = \"%s\" ", k, v)
|
|
} else {
|
|
conditionStr = fmt.Sprintf("%s AND %s = \"%s\" ", conditionStr, k, v)
|
|
}
|
|
}
|
|
|
|
for k, v := range conditions.fuzzy {
|
|
if len(conditionStr) == 0 {
|
|
conditionStr = fmt.Sprintf("%s like '%%%s%%' ", k, v)
|
|
} else {
|
|
conditionStr = fmt.Sprintf("%s AND %s like '%%%s%%' ", conditionStr, k, v)
|
|
}
|
|
}
|
|
|
|
for k, v := range conditions.matchOr {
|
|
if len(conditionStr) == 0 {
|
|
conditionStr = fmt.Sprintf("%s = \"%s\" ", k, v)
|
|
} 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 {
|
|
conditionStr = fmt.Sprintf("%s OR %s like '%%%s%%' ", conditionStr, k, v)
|
|
}
|
|
}
|
|
|
|
return conditionStr
|
|
}
|
|
|
|
type workLoadStatus struct {
|
|
NameSpace string `json:"namespace"`
|
|
Count map[string]int `json:"data"`
|
|
Items map[string]interface{} `json:"items,omitempty"`
|
|
}
|
|
|
|
func GetNamespacesResourceStatus(namespace string) (*workLoadStatus, error) {
|
|
res := workLoadStatus{Count: make(map[string]int), NameSpace: namespace, Items: make(map[string]interface{})}
|
|
var status *ResourceList
|
|
var err error
|
|
for _, resource := range []string{controllers.Deployments, controllers.Statefulsets, controllers.Daemonsets, controllers.PersistentVolumeClaim} {
|
|
notReadyStatus := controllers.Updating
|
|
if resource == controllers.PersistentVolumeClaim {
|
|
notReadyStatus = controllers.PvcPending
|
|
}
|
|
if len(namespace) > 0 {
|
|
status, err = ListResource(resource, fmt.Sprintf("status=%s,namespace=%s", notReadyStatus, namespace), "", "")
|
|
} else {
|
|
status, err = ListResource(resource, fmt.Sprintf("status=%s", notReadyStatus), "", "")
|
|
}
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
count := status.Total
|
|
res.Count[resource] = count
|
|
}
|
|
|
|
return &res, nil
|
|
}
|
|
|
|
func GetClusterResourceStatus() (*workLoadStatus, error) {
|
|
|
|
return GetNamespacesResourceStatus("")
|
|
}
|
|
|
|
func GetApplication(clusterId string) (interface{}, error) {
|
|
ctl := &controllers.ApplicationCtl{OpenpitrixAddr: options.ServerOptions.GetOpAddress()}
|
|
return ctl.GetApp(clusterId)
|
|
}
|
|
|
|
func ListApplication(runtimeId, conditionStr, pagingStr string) (*ResourceList, error) {
|
|
paging, err := getPaging(controllers.Applications, pagingStr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
conditions, _, err := getConditions(conditionStr)
|
|
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)
|
|
|
|
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
|
|
}
|