Files
kubesphere/pkg/models/resources.go

233 lines
6.2 KiB
Go

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"`
}
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:
return controllers.ResourceControllers.Controllers[resource], nil
default:
return nil, fmt.Errorf("invalid resource Name '%s'", resource)
}
return nil, nil
}
func getConditions(str string) (map[string]string, map[string]string, error) {
match := make(map[string]string)
fuzzy := 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 \"=\"")
}
if strings.Count(item, "~") >= 2 {
return nil, nil, errors.New("invalid condition input, invalid character \"~\"")
}
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")
}
match[kvs[0]] = 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")
}
fuzzy[kvs[0]] = kvs[1]
continue
}
return nil, nil, errors.New("invalid condition input")
}
return match, fuzzy, nil
}
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, defautlPagingMap, nil
}
list := strings.Split(pagingStr, ",")
for _, item := range list {
kvs := strings.Split(item, "=")
if len(kvs) < 2 {
return nil, nil, errors.New("invalid Paging input")
}
value, err := strconv.Atoi(kvs[1])
if err != nil {
return nil, nil, errors.New("invalid Paging input")
}
pagingMap[kvs[0]] = value
}
if pagingMap[limit] <= 0 || pagingMap[page] <= 0 {
return nil, nil, errors.New("invalid Paging input")
}
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 ListResource(resourceName, conditonSrt, pagingStr string) (*ResourceList, error) {
match, fuzzy, err := getConditions(conditonSrt)
if err != nil {
return nil, err
}
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)
if err != nil {
return nil, err
}
return &ResourceList{Total: total, Items: items, Page: pagingMap[page], Limit: pagingMap[limit]}, nil
}
func generateConditionStr(match map[string]string, fuzzy map[string]string) string {
conditionStr := ""
for k, v := range 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 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)
}
}
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, conditions, pagingStr string) (*ResourceList, error) {
paging, pagingMap, err := getPaging(controllers.Applications, pagingStr)
if err != nil {
return nil, err
}
match, fuzzy, err := getConditions(conditions)
if err != nil {
glog.Error(err)
return nil, err
}
ctl := &controllers.ApplicationCtl{OpenpitrixAddr: options.ServerOptions.GetOpAddress()}
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: pagingMap[page], Limit: pagingMap[limit]}, nil
}