Merge branch 'develop-zw' into develop
# Conflicts: # app/nacos.go # main.go
This commit is contained in:
commit
ac2caf1293
|
@ -94,8 +94,7 @@ type ProxyCluster struct {
|
|||
// @Failure 500
|
||||
// @Router /api/v1/cluster/list [get]
|
||||
func ListCluster(c *gin.Context) {
|
||||
|
||||
clusterName, _ := c.GetQuery("cluster_name")
|
||||
clusterName := c.Query("cluster_name")
|
||||
clusterList := make([]Cluster, 0)
|
||||
clusters, err := KarmadaClient.ClusterV1alpha1().Clusters().List(context.TODO(), metav1.ListOptions{})
|
||||
if err != nil {
|
||||
|
@ -136,11 +135,9 @@ func ListCluster(c *gin.Context) {
|
|||
total := len(clusterList)
|
||||
page := &Page[Cluster]{}
|
||||
page.List = clusterList
|
||||
pageNum, _ := c.GetQuery("pageNum")
|
||||
pageSize, _ := c.GetQuery("pageSize")
|
||||
num, _ := strconv.ParseInt(pageNum, 10, 64)
|
||||
size, _ := strconv.ParseInt(pageSize, 10, 64)
|
||||
data := Paginator(page, int64(total), num, size)
|
||||
pageNum := c.Query("pageNum")
|
||||
pageSize := c.Query("pageSize")
|
||||
data := Paginator(page, int64(total), pageNum, pageSize)
|
||||
Response(c, http.StatusOK, "success", data)
|
||||
}
|
||||
|
||||
|
@ -157,7 +154,7 @@ func ListCluster(c *gin.Context) {
|
|||
// @Router /api/v1/cluster/listWithLabel [get]
|
||||
func ListClusterWithLabel(c *gin.Context) {
|
||||
|
||||
clusterName, _ := c.GetQuery("cluster_name")
|
||||
clusterName := c.Query("cluster_name")
|
||||
|
||||
clusterList := make([]Cluster, 0)
|
||||
clusters, err := KarmadaClient.ClusterV1alpha1().Clusters().List(context.TODO(), metav1.ListOptions{})
|
||||
|
@ -204,11 +201,9 @@ func ListClusterWithLabel(c *gin.Context) {
|
|||
total := len(clusterList)
|
||||
page := &Page[Cluster]{}
|
||||
page.List = clusterList
|
||||
pageNum, _ := c.GetQuery("pageNum")
|
||||
pageSize, _ := c.GetQuery("pageSize")
|
||||
num, _ := strconv.ParseInt(pageNum, 10, 64)
|
||||
size, _ := strconv.ParseInt(pageSize, 10, 64)
|
||||
data := Paginator(page, int64(total), num, size)
|
||||
pageNum := c.Query("pageNum")
|
||||
pageSize := c.Query("pageSize")
|
||||
data := Paginator(page, int64(total), pageNum, pageSize)
|
||||
Response(c, http.StatusOK, "success", data)
|
||||
}
|
||||
|
||||
|
@ -224,8 +219,8 @@ func ListClusterWithLabel(c *gin.Context) {
|
|||
// @Router /api/v1/cluster/unJoin [delete]
|
||||
func UnJoin(c *gin.Context) {
|
||||
copyContext := c.Copy()
|
||||
clusterName, _ := c.GetQuery("cluster_name")
|
||||
domainId, _ := c.GetQuery("domain_id")
|
||||
clusterName := c.Query("cluster_name")
|
||||
domainId := c.Query("domain_id")
|
||||
if clusterName == "" || domainId == "" {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
|
@ -426,7 +421,7 @@ func ClusterExist(c *gin.Context) {
|
|||
glog.Info("failed to retrieve cluster(%s). error: %v", clusters, err)
|
||||
Response(c, http.StatusBadRequest, "failed to retrieve cluster", err)
|
||||
}
|
||||
clusterName := c.Param("clusterName")
|
||||
clusterName := c.Query("clusterName")
|
||||
//遍历集群
|
||||
for i := 0; i < len(clusters.Items); i++ {
|
||||
if clusters.Items[i].Name == clusterName {
|
||||
|
@ -519,9 +514,9 @@ func deleteMaps(labels map[string]string, keys map[string]string) {
|
|||
// @Failure 500
|
||||
// @Router /api/v1/cluster/listByDomain [post]
|
||||
func ListByDomain(c *gin.Context) {
|
||||
namespaceName, _ := c.GetQuery("namespace")
|
||||
deploymentName, _ := c.GetQuery("deployment_name")
|
||||
domainId, _ := c.GetQuery("domain_id")
|
||||
namespaceName := c.Query("namespace")
|
||||
deploymentName := c.Query("deployment_name")
|
||||
domainId := c.Query("domain_id")
|
||||
|
||||
//
|
||||
deployJson := GetDeployFromOS(namespaceName, deploymentName, "")
|
||||
|
|
|
@ -2,6 +2,7 @@ package app
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/gin-gonic/gin"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -14,12 +15,30 @@ type ConfigMap struct {
|
|||
TemplateId string `json:"templateId"`
|
||||
}
|
||||
|
||||
type SecretRes struct {
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Metadata string `json:"metadata"`
|
||||
ResourceVersion string `json:"resourceVersion"`
|
||||
Items []v1.Secret `json:"items"`
|
||||
}
|
||||
|
||||
type ConfigMaoObject struct {
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Metadata string `json:"metadata"`
|
||||
ResourceVersion string `json:"resourceVersion"`
|
||||
Items []v1.ConfigMap `json:"items"`
|
||||
}
|
||||
|
||||
// CreateConfigMap 创建configMap
|
||||
func CreateConfigMap(c *gin.Context) {
|
||||
var cmRequest ConfigMap
|
||||
if err := c.BindJSON(&cmRequest); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
cmRequest.ConfigMap.Labels["jcce"] = "true"
|
||||
ClientSet.CoreV1().ConfigMaps(cmRequest.ConfigMap.Namespace).Create(context.TODO(), &cmRequest.ConfigMap, metav1.CreateOptions{})
|
||||
// 创建调度策略实例
|
||||
CreatePropagationPolicies(PropagationPolicy{
|
||||
|
@ -32,3 +51,25 @@ func CreateConfigMap(c *gin.Context) {
|
|||
})
|
||||
Response(c, http.StatusOK, "success", nil)
|
||||
}
|
||||
|
||||
// ListSecret 查询命名空间下的secret
|
||||
func ListSecret(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
result := SearchObject(secretConst, clusterName, namespace, "")
|
||||
raw, _ := result.Raw()
|
||||
var secretRes SecretRes
|
||||
json.Unmarshal(raw, &secretRes)
|
||||
Response(c, http.StatusOK, "success", secretRes.Items)
|
||||
}
|
||||
|
||||
// ListConfigMap 查询命名空间下的configMap
|
||||
func ListConfigMap(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
result := SearchObject(configMapConst, clusterName, namespace, "")
|
||||
raw, _ := result.Raw()
|
||||
var configMaoObject ConfigMaoObject
|
||||
json.Unmarshal(raw, &configMaoObject)
|
||||
Response(c, http.StatusOK, "success", configMaoObject.Items)
|
||||
}
|
||||
|
|
67
app/crd.go
67
app/crd.go
|
@ -1,9 +1,13 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"strings"
|
||||
|
||||
"net/http"
|
||||
)
|
||||
|
@ -16,11 +20,70 @@ type CRDRes struct {
|
|||
Items []v1.CustomResourceDefinition `json:"items"`
|
||||
}
|
||||
|
||||
type CRDParam struct {
|
||||
ClusterName []string `json:"clusterName"`
|
||||
Domain string `json:"domain"`
|
||||
TemplateId string `json:"templateId"`
|
||||
CustomResourceDefinition v1.CustomResourceDefinition `json:"CustomResourceDefinition"`
|
||||
}
|
||||
|
||||
func ListCRD(c *gin.Context) {
|
||||
clusterName := c.Param("clusterName")
|
||||
clusterName := c.Query("clusterName")
|
||||
Response(c, http.StatusOK, "success", queryCRD(clusterName))
|
||||
}
|
||||
|
||||
func queryCRD(clusterName string) []v1.CustomResourceDefinition {
|
||||
result := SearchObject(crdConst, clusterName, "", "")
|
||||
raw, _ := result.Raw()
|
||||
var cRDRes CRDRes
|
||||
json.Unmarshal(raw, &cRDRes)
|
||||
Response(c, http.StatusOK, "success", cRDRes.Items)
|
||||
return cRDRes.Items
|
||||
}
|
||||
|
||||
const crUrl = "/apis/cluster.karmada.io/v1alpha1/clusters/%s/proxy/apis/%s/namespaces/%s/%s"
|
||||
|
||||
func CreateCRD(c *gin.Context) {
|
||||
var param CRDParam
|
||||
if err := c.BindJSON(¶m); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
|
||||
crdList, err := CrDClient.ApiextensionsV1().CustomResourceDefinitions().Create(context.TODO(), ¶m.CustomResourceDefinition, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// 创建调度实例
|
||||
CreatePropagationPolicies(PropagationPolicy{
|
||||
ClusterName: param.ClusterName,
|
||||
TemplateId: param.TemplateId,
|
||||
ResourceName: param.CustomResourceDefinition.Name,
|
||||
Name: "CustomResourceDefinition" + param.CustomResourceDefinition.Namespace + param.CustomResourceDefinition.Name,
|
||||
Namespace: param.CustomResourceDefinition.Namespace,
|
||||
Kind: "CustomResourceDefinition",
|
||||
})
|
||||
Response(c, http.StatusOK, "success", crdList)
|
||||
}
|
||||
|
||||
func DetailCRD(c *gin.Context) {
|
||||
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
kind := c.Query("kind")
|
||||
customResourceDefinitions := queryCRD(clusterName)
|
||||
for _, crd := range customResourceDefinitions {
|
||||
if strings.EqualFold(crd.Spec.Names.Plural, kind) || strings.EqualFold(crd.Spec.Names.Singular, kind) {
|
||||
url := fmt.Sprintf(crUrl, clusterName, crd.Spec.Group+"/"+crd.Spec.Versions[0].Name, namespace, crd.Spec.Names.Plural)
|
||||
result := KarmadaClient.SearchV1alpha1().RESTClient().Get().AbsPath(url).Do(context.TODO())
|
||||
|
||||
raw, _ := result.Raw()
|
||||
|
||||
Response(c, http.StatusOK, "success", raw)
|
||||
}
|
||||
}
|
||||
|
||||
//if err != nil {
|
||||
// return
|
||||
//}
|
||||
//Response(c, http.StatusOK, "success", crdList)
|
||||
}
|
||||
|
|
|
@ -2,75 +2,60 @@ package app
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/bitly/go-simplejson"
|
||||
"github.com/gin-gonic/gin"
|
||||
appv1 "k8s.io/api/apps/v1"
|
||||
v12 "k8s.io/api/autoscaling/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var deployMutex sync.Mutex
|
||||
|
||||
type HPAResult struct {
|
||||
MinReplicas int32 `json:"minReplicas"`
|
||||
MaxReplicas int32 `json:"maxReplicas"`
|
||||
MemoryTargetValue string `json:"memoryTargetValue"`
|
||||
CpuTargetUtilization string `json:"cpuTargetUtilization"`
|
||||
}
|
||||
|
||||
type DeploymentParam struct {
|
||||
ClusterName []string `json:"clusterName"`
|
||||
TemplateId string `json:"templateId"`
|
||||
Deployment appv1.Deployment `json:"deployment"`
|
||||
}
|
||||
type DeploymentParamSwagger struct {
|
||||
ClusterName []string `json:"clusterName"`
|
||||
TemplateId string `json:"templateId"`
|
||||
Deployment struct {
|
||||
APIVersion string `json:"apiVersion"`
|
||||
Kind string `json:"kind"`
|
||||
Metadata struct {
|
||||
Namespace string `json:"namespace"`
|
||||
Labels struct {
|
||||
} `json:"labels"`
|
||||
Name string `json:"name"`
|
||||
Annotations struct {
|
||||
KubesphereIoCreator string `json:"kubesphere.io/creator"`
|
||||
} `json:"annotations"`
|
||||
} `json:"metadata"`
|
||||
Spec struct {
|
||||
Replicas int `json:"replicas"`
|
||||
Selector struct {
|
||||
MatchLabels struct {
|
||||
} `json:"matchLabels"`
|
||||
} `json:"selector"`
|
||||
Template struct {
|
||||
Metadata struct {
|
||||
Labels struct {
|
||||
} `json:"labels"`
|
||||
} `json:"metadata"`
|
||||
Spec struct {
|
||||
Containers []struct {
|
||||
Name string `json:"name"`
|
||||
ImagePullPolicy string `json:"imagePullPolicy"`
|
||||
Image string `json:"image"`
|
||||
Ports []struct {
|
||||
Name string `json:"name"`
|
||||
Protocol string `json:"protocol"`
|
||||
ContainerPort int `json:"containerPort"`
|
||||
} `json:"ports"`
|
||||
} `json:"containers"`
|
||||
ServiceAccount string `json:"serviceAccount"`
|
||||
InitContainers []interface{} `json:"initContainers"`
|
||||
Volumes []interface{} `json:"volumes"`
|
||||
ImagePullSecrets interface{} `json:"imagePullSecrets"`
|
||||
} `json:"spec"`
|
||||
} `json:"template"`
|
||||
Strategy struct {
|
||||
Type string `json:"type"`
|
||||
RollingUpdate struct {
|
||||
MaxUnavailable string `json:"maxUnavailable"`
|
||||
MaxSurge string `json:"maxSurge"`
|
||||
} `json:"rollingUpdate"`
|
||||
} `json:"strategy"`
|
||||
} `json:"spec"`
|
||||
} `json:"deployment"`
|
||||
|
||||
type HPAParam struct {
|
||||
ClusterName []string `json:"clusterName"`
|
||||
TemplateId string `json:"templateId"`
|
||||
Hpa v12.HorizontalPodAutoscaler `json:"hpa"`
|
||||
}
|
||||
|
||||
type StatefulSetParam struct {
|
||||
ClusterName []string `json:"clusterName"`
|
||||
TemplateId string `json:"templateId"`
|
||||
StatefulSet appv1.StatefulSet `json:"statefulSet"`
|
||||
}
|
||||
|
||||
type DaemonSetParam struct {
|
||||
ClusterName []string `json:"clusterName"`
|
||||
TemplateId string `json:"templateId"`
|
||||
DaemonSet appv1.DaemonSet `json:"daemonSet"`
|
||||
}
|
||||
|
||||
type RedeployParam struct {
|
||||
ClusterName string `json:"clusterName"`
|
||||
Namespace string `json:"namespace"`
|
||||
DeploymentName string `json:"deploymentName"`
|
||||
Num string `json:"num"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type DeploymentRes struct {
|
||||
|
@ -82,12 +67,52 @@ type DeploymentRes struct {
|
|||
Replicas int32 `json:"replicas"`
|
||||
}
|
||||
|
||||
type DeploymentObject struct {
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Metadata string `json:"metadata"`
|
||||
ResourceVersion string `json:"resourceVersion"`
|
||||
Items []appv1.Deployment `json:"items"`
|
||||
}
|
||||
|
||||
type ControllerRevisionObject struct {
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Metadata string `json:"metadata"`
|
||||
ResourceVersion string `json:"resourceVersion"`
|
||||
Items []appv1.ControllerRevision `json:"items"`
|
||||
}
|
||||
|
||||
type ReplicaSetObject struct {
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Metadata string `json:"metadata"`
|
||||
ResourceVersion string `json:"resourceVersion"`
|
||||
Items []appv1.ReplicaSet `json:"items"`
|
||||
}
|
||||
|
||||
type StatefulSetObject struct {
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Metadata string `json:"metadata"`
|
||||
ResourceVersion string `json:"resourceVersion"`
|
||||
Items []appv1.StatefulSet `json:"items"`
|
||||
}
|
||||
|
||||
type DaemonSetObject struct {
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Metadata string `json:"metadata"`
|
||||
ResourceVersion string `json:"resourceVersion"`
|
||||
Items []appv1.DaemonSet `json:"items"`
|
||||
}
|
||||
|
||||
// CreateDeployment 创建工作负载
|
||||
// @Summary 创建工作负载
|
||||
// @Description 创建工作负载
|
||||
// @Tags deployment
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Param param body DeploymentParamSwagger true "json"
|
||||
// @Success 200
|
||||
// @Failure 400
|
||||
// @Router /api/v1/deployment/create [post]
|
||||
|
@ -97,9 +122,10 @@ func CreateDeployment(c *gin.Context) {
|
|||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
dpRequest.Deployment.Spec.Template.Labels = map[string]string{"jcce": "true"}
|
||||
dpRequest.Deployment.Spec.Selector.MatchLabels = map[string]string{"jcce": "true"}
|
||||
dpRequest.Deployment.Labels = map[string]string{"jcce": "true"}
|
||||
if dpRequest.Deployment.Labels == nil {
|
||||
dpRequest.Deployment.Labels = map[string]string{}
|
||||
}
|
||||
dpRequest.Deployment.Labels["jcce"] = "true"
|
||||
deploymentList, err := ClientSet.AppsV1().Deployments(dpRequest.Deployment.Namespace).Create(context.TODO(), &dpRequest.Deployment, metav1.CreateOptions{})
|
||||
|
||||
if err != nil {
|
||||
|
@ -110,12 +136,64 @@ func CreateDeployment(c *gin.Context) {
|
|||
ClusterName: dpRequest.ClusterName,
|
||||
TemplateId: dpRequest.TemplateId,
|
||||
ResourceName: dpRequest.Deployment.Name,
|
||||
Name: "DeploymentParam" + dpRequest.Deployment.Namespace + dpRequest.Deployment.Name,
|
||||
Name: "Deployment" + "." + dpRequest.Deployment.Namespace + "." + dpRequest.Deployment.Name,
|
||||
Namespace: dpRequest.Deployment.Namespace,
|
||||
Kind: "DeploymentParam",
|
||||
Kind: "Deployment",
|
||||
})
|
||||
Response(c, http.StatusOK, "success", deploymentList)
|
||||
}
|
||||
|
||||
// ListDeploymentFromCluster 查询指定集群下的命名空间
|
||||
func ListDeploymentFromCluster(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
state := c.Query("state")
|
||||
pageNum := c.Query("pageNum")
|
||||
pageSize := c.Query("pageSize")
|
||||
searchObject := SearchObject(allDeploymentConst, clusterName, "", "")
|
||||
raw, _ := searchObject.Raw()
|
||||
var deploymentObject DeploymentObject
|
||||
json.Unmarshal(raw, &deploymentObject)
|
||||
deployments := deploymentObject.Items
|
||||
// 根据条件过滤
|
||||
count := 0
|
||||
for i := range deployments {
|
||||
if len(namespace) != 0 && !strings.EqualFold(deployments[i-count].Namespace, namespace) {
|
||||
deployments = append(deployments[:i-count], deployments[i-count+1:]...)
|
||||
count = count + 1
|
||||
continue
|
||||
}
|
||||
if len(name) != 0 && !strings.Contains(deployments[i-count].Name, name) {
|
||||
deployments = append(deployments[:i-count], deployments[i-count+1:]...)
|
||||
count = count + 1
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(state, "updating") && deployments[i-count].Status.UnavailableReplicas == 0 {
|
||||
deployments = append(deployments[:i-count], deployments[i-count+1:]...)
|
||||
count = count + 1
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(state, "running") && deployments[i-count].Status.ReadyReplicas != deployments[i-count].Status.Replicas {
|
||||
deployments = append(deployments[:i-count], deployments[i-count+1:]...)
|
||||
count = count + 1
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(state, "stopped") && deployments[i-count].Status.Replicas != 0 {
|
||||
deployments = append(deployments[:i-count], deployments[i-count+1:]...)
|
||||
count = count + 1
|
||||
continue
|
||||
}
|
||||
}
|
||||
// 分页
|
||||
page := &Page[appv1.Deployment]{}
|
||||
// 排序
|
||||
sort.SliceStable(deployments, func(i, j int) bool {
|
||||
return deployments[i].CreationTimestamp.Time.After(deployments[j].CreationTimestamp.Time)
|
||||
})
|
||||
page.List = deployments
|
||||
data := Paginator(page, int64(len(deployments)), pageNum, pageSize)
|
||||
Response(c, http.StatusOK, "success", data)
|
||||
}
|
||||
|
||||
// ListDeployment 根据查询工作负载列表(控制平面)
|
||||
|
@ -132,7 +210,7 @@ func CreateDeployment(c *gin.Context) {
|
|||
// @Router /api/v1/deployment/list [get]
|
||||
func ListDeployment(c *gin.Context) {
|
||||
|
||||
namespace, _ := c.GetQuery("namespace")
|
||||
namespace := c.Query("namespace")
|
||||
|
||||
dpList := make([]DeploymentRes, 0)
|
||||
deploymentList, err := ClientSet.AppsV1().Deployments(namespace).List(context.TODO(), metav1.ListOptions{})
|
||||
|
@ -163,17 +241,14 @@ func ListDeployment(c *gin.Context) {
|
|||
total := len(dpList)
|
||||
page := &Page[DeploymentRes]{}
|
||||
page.List = dpList
|
||||
pageNum, _ := c.GetQuery("pageNum")
|
||||
pageSize, _ := c.GetQuery("pageSize")
|
||||
num, _ := strconv.ParseInt(pageNum, 10, 64)
|
||||
size, _ := strconv.ParseInt(pageSize, 10, 64)
|
||||
data := Paginator(page, int64(total), num, size)
|
||||
pageNum := c.Query("pageNum")
|
||||
pageSize := c.Query("pageSize")
|
||||
data := Paginator(page, int64(total), pageNum, pageSize)
|
||||
Response(c, http.StatusOK, "success", data)
|
||||
|
||||
}
|
||||
|
||||
// ListClusterDeployment 查询工作负载列表(所有集群)
|
||||
|
||||
func ListClusterDeployment(c *gin.Context) {
|
||||
//TODO 逻辑待完善
|
||||
ss, _ := KarmadaClient.SearchV1alpha1().ResourceRegistries().Get(context.TODO(), "clustercache-sample", metav1.GetOptions{})
|
||||
|
@ -181,6 +256,92 @@ func ListClusterDeployment(c *gin.Context) {
|
|||
Response(c, http.StatusOK, "success", ss)
|
||||
}
|
||||
|
||||
// DetailDeployment 根据Deployment名查询Deployment详情
|
||||
func DetailDeployment(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
searchObject := SearchObject(deploymentConst, clusterName, namespace, name)
|
||||
raw, _ := searchObject.Raw()
|
||||
var deployment appv1.Deployment
|
||||
json.Unmarshal(raw, &deployment)
|
||||
Response(c, http.StatusOK, "success", deployment)
|
||||
}
|
||||
|
||||
func DetailDaemonSet(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
searchObject := SearchObject(daemonSetConst, clusterName, namespace, name)
|
||||
raw, _ := searchObject.Raw()
|
||||
var daemonSet appv1.DaemonSet
|
||||
json.Unmarshal(raw, &daemonSet)
|
||||
Response(c, http.StatusOK, "success", daemonSet)
|
||||
}
|
||||
|
||||
func ListStatefulSetFromCluster(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
state := c.Query("state")
|
||||
pageNum := c.Query("pageNum")
|
||||
pageSize := c.Query("pageSize")
|
||||
searchObject := SearchObject(allStatefulSetConst, clusterName, "", "")
|
||||
raw, _ := searchObject.Raw()
|
||||
var statefulSetObject StatefulSetObject
|
||||
json.Unmarshal(raw, &statefulSetObject)
|
||||
statefulSets := statefulSetObject.Items
|
||||
// 根据条件过滤
|
||||
count := 0
|
||||
for i := range statefulSets {
|
||||
if len(namespace) != 0 && !strings.EqualFold(statefulSets[i-count].Namespace, namespace) {
|
||||
statefulSets = append(statefulSets[:i-count], statefulSets[i-count+1:]...)
|
||||
count = count + 1
|
||||
continue
|
||||
}
|
||||
if len(name) != 0 && !strings.Contains(statefulSets[i-count].Name, name) {
|
||||
statefulSets = append(statefulSets[:i-count], statefulSets[i-count+1:]...)
|
||||
count = count + 1
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(state, "updating") && statefulSets[i-count].Status.UpdatedReplicas == 0 {
|
||||
statefulSets = append(statefulSets[:i-count], statefulSets[i-count+1:]...)
|
||||
count = count + 1
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(state, "running") && statefulSets[i-count].Status.ReadyReplicas != statefulSets[i-count].Status.Replicas {
|
||||
statefulSets = append(statefulSets[:i-count], statefulSets[i-count+1:]...)
|
||||
count = count + 1
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(state, "stopped") && statefulSets[i-count].Status.Replicas != 0 {
|
||||
statefulSets = append(statefulSets[:i-count], statefulSets[i-count+1:]...)
|
||||
count = count + 1
|
||||
continue
|
||||
}
|
||||
}
|
||||
// 分页
|
||||
page := &Page[appv1.StatefulSet]{}
|
||||
// 排序
|
||||
sort.SliceStable(statefulSets, func(i, j int) bool {
|
||||
return statefulSets[i].CreationTimestamp.Time.After(statefulSets[j].CreationTimestamp.Time)
|
||||
})
|
||||
page.List = statefulSets
|
||||
data := Paginator(page, int64(len(statefulSets)), pageNum, pageSize)
|
||||
Response(c, http.StatusOK, "success", data)
|
||||
}
|
||||
|
||||
func DetailStatefulSet(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
searchObject := SearchObject(statefulSetConst, clusterName, namespace, name)
|
||||
raw, _ := searchObject.Raw()
|
||||
var statefulSet appv1.StatefulSet
|
||||
json.Unmarshal(raw, &statefulSet)
|
||||
Response(c, http.StatusOK, "success", statefulSet)
|
||||
}
|
||||
|
||||
// DescribeDeployment 查询工作负载列表(所有集群)
|
||||
// @Summary 查询工作负载列表(所有集群)
|
||||
// @Description 查询工作负载列表(所有集群)
|
||||
|
@ -194,8 +355,8 @@ func ListClusterDeployment(c *gin.Context) {
|
|||
// @Router /api/v1/deployment/describe [get]
|
||||
func DescribeDeployment(c *gin.Context) {
|
||||
|
||||
namespace, _ := c.GetQuery("namespace")
|
||||
deployName, _ := c.GetQuery("deploy_name")
|
||||
namespace := c.Query("namespace")
|
||||
deployName := c.Query("deploy_name")
|
||||
ClientSet.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})
|
||||
podList := make([]Pod, 0)
|
||||
pods := GetPodFromOS(namespace, deployName)
|
||||
|
@ -268,14 +429,565 @@ func DescribeDeployment(c *gin.Context) {
|
|||
// @Failure 400
|
||||
// @Router /api/v1/deployment/delete/{namespace}/{name} [delete]
|
||||
func DeleteDeployment(c *gin.Context) {
|
||||
clusterName := c.Param("clusterName")
|
||||
namespace := c.Param("namespace")
|
||||
name := c.Param("name")
|
||||
err := ClientSet.AppsV1().Deployments(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete deployment failed", err)
|
||||
return
|
||||
label := c.Param("label")
|
||||
if strings.EqualFold(label, "jcce") {
|
||||
err := ClientSet.AppsV1().Deployments(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete deployment failed", err)
|
||||
return
|
||||
}
|
||||
// 删除调度策略
|
||||
DeletePropagationPolicies(namespace, "Deployment"+"."+namespace+"."+name)
|
||||
} else {
|
||||
result := DeleteObject(deploymentConst, clusterName, namespace, name)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete deployment failed", result.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
// 删除调度策略
|
||||
DeletePropagationPolicies(namespace, "pod"+namespace+name)
|
||||
|
||||
Response(c, http.StatusOK, "success", nil)
|
||||
}
|
||||
|
||||
func ListDaemonSetFromCluster(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
state := c.Query("state")
|
||||
pageNum := c.Query("pageNum")
|
||||
pageSize := c.Query("pageSize")
|
||||
searchObject := SearchObject(allDaemonSetConst, clusterName, "", "")
|
||||
raw, _ := searchObject.Raw()
|
||||
var daemonSetObject DaemonSetObject
|
||||
json.Unmarshal(raw, &daemonSetObject)
|
||||
daemonSets := daemonSetObject.Items
|
||||
// 根据条件过滤
|
||||
count := 0
|
||||
for i := range daemonSets {
|
||||
if len(namespace) != 0 && !strings.EqualFold(daemonSets[i-count].Namespace, namespace) {
|
||||
daemonSets = append(daemonSets[:i-count], daemonSets[i-count+1:]...)
|
||||
count = count + 1
|
||||
continue
|
||||
}
|
||||
if len(name) != 0 && !strings.Contains(daemonSets[i-count].Name, name) {
|
||||
daemonSets = append(daemonSets[:i-count], daemonSets[i-count+1:]...)
|
||||
count = count + 1
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(state, "updating") && daemonSets[i-count].Status.UpdatedNumberScheduled == 0 {
|
||||
daemonSets = append(daemonSets[:i-count], daemonSets[i-count+1:]...)
|
||||
count = count + 1
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(state, "running") && daemonSets[i-count].Status.CurrentNumberScheduled != daemonSets[i-count].Status.NumberReady {
|
||||
daemonSets = append(daemonSets[:i-count], daemonSets[i-count+1:]...)
|
||||
count = count + 1
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(state, "stopped") && daemonSets[i-count].Status.CurrentNumberScheduled != 0 {
|
||||
daemonSets = append(daemonSets[:i-count], daemonSets[i-count+1:]...)
|
||||
count = count + 1
|
||||
continue
|
||||
}
|
||||
}
|
||||
// 分页
|
||||
page := &Page[appv1.DaemonSet]{}
|
||||
// 排序
|
||||
sort.SliceStable(daemonSets, func(i, j int) bool {
|
||||
return daemonSets[i].CreationTimestamp.Time.After(daemonSets[j].CreationTimestamp.Time)
|
||||
})
|
||||
page.List = daemonSets
|
||||
data := Paginator(page, int64(len(daemonSets)), pageNum, pageSize)
|
||||
Response(c, http.StatusOK, "success", data)
|
||||
}
|
||||
|
||||
func IsExistDaemonSet(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
result := SearchObject(daemonSetConst, clusterName, namespace, name)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusOK, "success", false)
|
||||
return
|
||||
}
|
||||
raw, _ := result.Raw()
|
||||
var daemonSet appv1.DaemonSet
|
||||
json.Unmarshal(raw, &daemonSet)
|
||||
if len(daemonSet.Name) == 0 {
|
||||
Response(c, http.StatusOK, "success", false)
|
||||
return
|
||||
}
|
||||
Response(c, http.StatusOK, "success", true)
|
||||
}
|
||||
|
||||
func IsExistStatefulSet(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
result := SearchObject(statefulSetConst, clusterName, namespace, name)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusOK, "success", false)
|
||||
return
|
||||
}
|
||||
raw, _ := result.Raw()
|
||||
var statefulSet appv1.StatefulSet
|
||||
json.Unmarshal(raw, &statefulSet)
|
||||
if len(statefulSet.Name) == 0 {
|
||||
Response(c, http.StatusOK, "success", false)
|
||||
return
|
||||
}
|
||||
Response(c, http.StatusOK, "success", true)
|
||||
}
|
||||
|
||||
// @Summary 获取弹性伸缩信息
|
||||
// @Description 获取弹性伸缩信息
|
||||
// @Tags deployment
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Param clusterName query string true "集群名称"
|
||||
// @Param namespace query string true "命名空间"
|
||||
// @Param deployName query string true "deployName"
|
||||
// @Success 200
|
||||
// @Failure 400
|
||||
// @Router /api/v1/deployment/hpa [get]
|
||||
func getHpa(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
var hpa v12.HorizontalPodAutoscaler
|
||||
result := SearchObject(detailHPAConst, clusterName, namespace, name)
|
||||
raw, err := result.Raw()
|
||||
if err != nil {
|
||||
Response(c, http.StatusOK, "the server could not find the requested resource", "")
|
||||
return
|
||||
}
|
||||
json.Unmarshal(raw, &hpa)
|
||||
Response(c, http.StatusOK, "success", hpa)
|
||||
}
|
||||
|
||||
// @Summary 弹性伸缩
|
||||
// @Description 弹性伸缩
|
||||
// @Tags deployment
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Param param body HPAParam true "json"
|
||||
// @Success 200
|
||||
// @Failure 400
|
||||
// @Router /api/v1/deployment/autoScaling [post]
|
||||
func AutoScaling(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
var hpa v12.HorizontalPodAutoscaler
|
||||
if err := c.BindJSON(&hpa); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
if len(hpa.Labels["jcce"]) != 0 {
|
||||
_, err := ClientSet.AutoscalingV1().HorizontalPodAutoscalers(hpa.Namespace).Update(context.TODO(), &hpa, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "update hpa failed", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
result := UpdateObject(detailHPAConst, clusterName, hpa.Namespace, hpa.Name, hpa)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "update hpa failed", result.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
Response(c, http.StatusOK, "success", "")
|
||||
}
|
||||
|
||||
// @Summary 创建弹性伸缩
|
||||
func CreateHpa(c *gin.Context) {
|
||||
var param HPAParam
|
||||
if err := c.BindJSON(¶m); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
// 查询deployment来源
|
||||
searchObject := SearchObject(deploymentConst, param.ClusterName[0], param.Hpa.Namespace, param.Hpa.Spec.ScaleTargetRef.Name)
|
||||
raw, _ := searchObject.Raw()
|
||||
var deployment appv1.Deployment
|
||||
json.Unmarshal(raw, &deployment)
|
||||
if len(deployment.Labels["jcce"]) != 0 {
|
||||
if param.Hpa.Labels == nil {
|
||||
param.Hpa.Labels = map[string]string{}
|
||||
}
|
||||
param.Hpa.Labels["jcce"] = "true"
|
||||
_, err := ClientSet.AutoscalingV1().HorizontalPodAutoscalers(param.Hpa.Namespace).Create(context.TODO(), ¶m.Hpa, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "create hpa failed.", err)
|
||||
return
|
||||
}
|
||||
CreatePropagationPolicies(PropagationPolicy{
|
||||
ClusterName: param.ClusterName,
|
||||
TemplateId: param.TemplateId,
|
||||
ResourceName: param.Hpa.Name,
|
||||
Name: "hpa" + "." + param.Hpa.Namespace + "." + param.Hpa.Name,
|
||||
Namespace: param.Hpa.Namespace,
|
||||
Kind: "HorizontalPodAutoscaler",
|
||||
})
|
||||
} else {
|
||||
postObject := PostObject(hpaListConst, param.ClusterName[0], param.Hpa.Namespace, "", param.Hpa)
|
||||
if postObject.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "create hpa failed.", postObject.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
Response(c, http.StatusOK, "success", "")
|
||||
}
|
||||
|
||||
func UpdateDeployment(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
var deployment appv1.Deployment
|
||||
if err := c.BindJSON(&deployment); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
if len(deployment.Labels["jcce"]) != 0 {
|
||||
_, err := ClientSet.AppsV1().Deployments(deployment.Namespace).Update(context.TODO(), &deployment, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
result := UpdateObject(deploymentConst, clusterName, deployment.Namespace, deployment.Name, deployment)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "update deployment failed", result.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
Response(c, http.StatusOK, "success", "")
|
||||
}
|
||||
|
||||
// @Summary 重新部署
|
||||
// @Description 重新部署
|
||||
// @Tags deployment
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Param param body RedeployParam true "json"
|
||||
// @Success 200
|
||||
// @Failure 500
|
||||
// @Router /api/v1/deployment/deployments/redeploy [patch]
|
||||
func Redeploy(c *gin.Context) {
|
||||
var param RedeployParam
|
||||
if err := c.BindJSON(¶m); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
if param.Type == "deploy" {
|
||||
deployment, err := ClientSet.AppsV1().Deployments(param.Namespace).Get(context.TODO(), param.DeploymentName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", err)
|
||||
return
|
||||
}
|
||||
deployment.Spec.Template.Spec.Containers[0].Env = append(deployment.Spec.Template.Spec.Containers[0].Env, v1.EnvVar{Name: "RESTART_TIME", Value: time.Now().String()})
|
||||
ClientSet.AppsV1().Deployments(param.Namespace).Update(context.TODO(), deployment, metav1.UpdateOptions{})
|
||||
} else if param.Type == "sts" {
|
||||
statefulSet, err := ClientSet.AppsV1().StatefulSets(param.Namespace).Get(context.TODO(), param.DeploymentName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", err)
|
||||
return
|
||||
}
|
||||
statefulSet.Spec.Template.Spec.Containers[0].Env = append(statefulSet.Spec.Template.Spec.Containers[0].Env, v1.EnvVar{Name: "RESTART_TIME", Value: time.Now().String()})
|
||||
ClientSet.AppsV1().StatefulSets(param.Namespace).Update(context.TODO(), statefulSet, metav1.UpdateOptions{})
|
||||
} else if param.Type == "ds" {
|
||||
daemonSet, err := ClientSet.AppsV1().DaemonSets(param.Namespace).Get(context.TODO(), param.DeploymentName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", err)
|
||||
return
|
||||
}
|
||||
daemonSet.Spec.Template.Spec.Containers[0].Env = append(daemonSet.Spec.Template.Spec.Containers[0].Env, v1.EnvVar{Name: "RESTART_TIME", Value: time.Now().String()})
|
||||
ClientSet.AppsV1().DaemonSets(param.Namespace).Update(context.TODO(), daemonSet, metav1.UpdateOptions{})
|
||||
}
|
||||
|
||||
Response(c, http.StatusOK, "success", nil)
|
||||
}
|
||||
|
||||
func CreateStatefulSet(c *gin.Context) {
|
||||
var param StatefulSetParam
|
||||
if err := c.BindJSON(¶m); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
if param.StatefulSet.Labels == nil {
|
||||
param.StatefulSet.Labels = map[string]string{}
|
||||
}
|
||||
param.StatefulSet.Labels["jcce"] = "true"
|
||||
ssResult, err := ClientSet.AppsV1().StatefulSets(param.StatefulSet.Namespace).Create(context.TODO(), ¶m.StatefulSet, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", err)
|
||||
return
|
||||
}
|
||||
CreatePropagationPolicies(PropagationPolicy{
|
||||
ClusterName: param.ClusterName,
|
||||
TemplateId: param.TemplateId,
|
||||
ResourceName: param.StatefulSet.Name,
|
||||
Name: "StatefulSet" + "." + param.StatefulSet.Namespace + "." + param.StatefulSet.Name,
|
||||
Namespace: param.StatefulSet.Namespace,
|
||||
Kind: "StatefulSet",
|
||||
})
|
||||
Response(c, http.StatusOK, "success", ssResult)
|
||||
}
|
||||
|
||||
// UpdateStatefulSet 更新statefulSet
|
||||
func UpdateStatefulSet(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
var statefulSet appv1.StatefulSet
|
||||
if err := c.BindJSON(&statefulSet); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
if len(statefulSet.Labels["jcce"]) != 0 {
|
||||
_, err := ClientSet.AppsV1().StatefulSets(statefulSet.Namespace).Update(context.TODO(), &statefulSet, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "update statefulSet failed", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
result := UpdateObject(statefulSetConst, clusterName, statefulSet.Namespace, statefulSet.Name, statefulSet)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "update statefulSet failed", result.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Response(c, http.StatusOK, "success", "")
|
||||
}
|
||||
|
||||
func UpdateDaemonSet(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
var daemonSet appv1.DaemonSet
|
||||
if err := c.BindJSON(&daemonSet); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
if len(daemonSet.Labels["jcce"]) != 0 {
|
||||
_, err := ClientSet.AppsV1().DaemonSets(daemonSet.Namespace).Update(context.TODO(), &daemonSet, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
result := UpdateObject(daemonSetConst, clusterName, daemonSet.Namespace, daemonSet.Name, daemonSet)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "update daemonSet failed", result.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
Response(c, http.StatusOK, "success", "")
|
||||
}
|
||||
|
||||
func CreateDaemonSet(c *gin.Context) {
|
||||
var param DaemonSetParam
|
||||
if err := c.BindJSON(¶m); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
if param.DaemonSet.Labels == nil {
|
||||
param.DaemonSet.Labels = map[string]string{}
|
||||
}
|
||||
param.DaemonSet.Labels["jcce"] = "true"
|
||||
deResult, err := ClientSet.AppsV1().DaemonSets(param.DaemonSet.Namespace).Create(context.TODO(), ¶m.DaemonSet, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", err)
|
||||
return
|
||||
}
|
||||
CreatePropagationPolicies(PropagationPolicy{
|
||||
ClusterName: param.ClusterName,
|
||||
TemplateId: param.TemplateId,
|
||||
ResourceName: param.DaemonSet.Name,
|
||||
Name: "DaemonSet" + "." + param.DaemonSet.Namespace + "." + param.DaemonSet.Name,
|
||||
Namespace: param.DaemonSet.Namespace,
|
||||
Kind: "DaemonSet",
|
||||
})
|
||||
Response(c, http.StatusOK, "success", deResult)
|
||||
}
|
||||
|
||||
func DeleteDaemonSet(c *gin.Context) {
|
||||
clusterName := c.Param("clusterName")
|
||||
namespace := c.Param("namespace")
|
||||
name := c.Param("name")
|
||||
label := c.Param("label")
|
||||
if strings.EqualFold(label, "jcce") {
|
||||
err := ClientSet.AppsV1().DaemonSets(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete deployment failed", err)
|
||||
return
|
||||
}
|
||||
// 删除调度策略
|
||||
DeletePropagationPolicies(namespace, "DaemonSet"+"."+namespace+"."+name)
|
||||
} else {
|
||||
result := DeleteObject(daemonSetConst, clusterName, namespace, name)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete daemonSet failed", result.Error())
|
||||
return
|
||||
}
|
||||
Response(c, http.StatusOK, "success", nil)
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteStatefulSet(c *gin.Context) {
|
||||
clusterName := c.Param("clusterName")
|
||||
namespace := c.Param("namespace")
|
||||
name := c.Param("name")
|
||||
label := c.Param("label")
|
||||
if strings.EqualFold(label, "jcce") {
|
||||
err := ClientSet.AppsV1().StatefulSets(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete deployment failed", err)
|
||||
return
|
||||
}
|
||||
// 删除调度策略
|
||||
DeletePropagationPolicies(namespace, "StatefulSet"+"."+namespace+"."+name)
|
||||
} else {
|
||||
result := DeleteObject(statefulSetConst, clusterName, namespace, name)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete statefulSet failed", result.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Response(c, http.StatusOK, "success", nil)
|
||||
}
|
||||
|
||||
func IsExistDeployment(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
searchObject := SearchObject(deploymentConst, clusterName, namespace, name)
|
||||
if searchObject.Error() != nil {
|
||||
Response(c, http.StatusOK, "success", false)
|
||||
return
|
||||
}
|
||||
raw, _ := searchObject.Raw()
|
||||
var deploymentRes appv1.Deployment
|
||||
json.Unmarshal(raw, &deploymentRes)
|
||||
if len(deploymentRes.Name) == 0 {
|
||||
Response(c, http.StatusOK, "success", false)
|
||||
return
|
||||
}
|
||||
Response(c, http.StatusOK, "success", true)
|
||||
}
|
||||
|
||||
// @Summary 获取部署监控
|
||||
// @Description 获取部署监控
|
||||
// @Tags deployment
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Param clusterName query string true "集群名称"
|
||||
// @Param namespace query string true "namespace"
|
||||
// @Param deployment query string true "部署名称"
|
||||
// @Param queryType query string true "类型"
|
||||
// @Success 200
|
||||
// @Failure 500
|
||||
// @Router /api/v1/deployment/getMetrics [get]
|
||||
func GetDeploymentMetrics(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
label := c.Query("label")
|
||||
// 将label拼接成label集合
|
||||
var labelMap = make(map[string]string)
|
||||
labelArray := strings.Split(label, ",")
|
||||
for _, label := range labelArray {
|
||||
labelKV := strings.Split(label, "=")
|
||||
labelMap[labelKV[0]] = labelKV[1]
|
||||
}
|
||||
podList := GetPodForDeployment(clusterName, namespace, labelMap)
|
||||
|
||||
metricUrls := make([][]MetricUrl, 4)
|
||||
for _, item := range podList {
|
||||
imap := map[string]string{
|
||||
ClusterName: clusterName,
|
||||
PodName: item.ObjectMeta.Name,
|
||||
}
|
||||
metricUrls[0] = append(metricUrls[0], MetricUrl{PodName, item.ObjectMeta.Name, GetMetricUrl(pod_net_bytes_transmitted, imap, PodName, metric_range_8h, steps_8h)})
|
||||
metricUrls[1] = append(metricUrls[1], MetricUrl{PodName, item.ObjectMeta.Name, GetMetricUrl(pod_memery_usage_wo_cache, imap, PodName, metric_range_8h, steps_8h)})
|
||||
metricUrls[2] = append(metricUrls[2], MetricUrl{PodName, item.ObjectMeta.Name, GetMetricUrl(pod_net_bytes_received, imap, PodName, metric_range_8h, steps_8h)})
|
||||
metricUrls[3] = append(metricUrls[3], MetricUrl{PodName, item.ObjectMeta.Name, GetMetricUrl(pod_cpu_usage, imap, PodName, metric_range_8h, steps_8h)})
|
||||
}
|
||||
|
||||
metricMap := map[string][]MetricUrl{
|
||||
"pod_net_bytes_transmitted": metricUrls[0],
|
||||
"pod_memory_usage_wo_cache": metricUrls[1],
|
||||
"pod_net_bytes_received": metricUrls[2],
|
||||
"pod_cpu_usage": metricUrls[3],
|
||||
}
|
||||
|
||||
ch := make(chan MetricResult, len(metricMap))
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for k, v := range metricMap {
|
||||
wg.Add(1)
|
||||
go HttpGetMetrics(k, v, &wg, ch)
|
||||
}
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
|
||||
mr := []MetricResult{}
|
||||
for v := range ch {
|
||||
mr = append(mr, v)
|
||||
}
|
||||
|
||||
Response(c, http.StatusOK, "success", mr)
|
||||
}
|
||||
|
||||
func ListReplicaSets(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
label := c.Query("label")
|
||||
// 将label拼接到map
|
||||
var labelMap = make(map[string]string)
|
||||
labelArray := strings.Split(label, ",")
|
||||
for _, label := range labelArray {
|
||||
labelKV := strings.Split(label, "=")
|
||||
labelMap[labelKV[0]] = labelKV[1]
|
||||
}
|
||||
// 查询replicaSet
|
||||
var replicaSetObject ReplicaSetObject
|
||||
searchResult := SearchObject(replicaSetConst, clusterName, namespace, "")
|
||||
raw, err := searchResult.Raw()
|
||||
json.Unmarshal(raw, &replicaSetObject)
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "query controllerRevisions failed", err)
|
||||
return
|
||||
}
|
||||
var result []appv1.ReplicaSet
|
||||
// 根据标签匹配
|
||||
for _, replicaSet := range replicaSetObject.Items {
|
||||
for k, v := range labelMap {
|
||||
if replicaSet.Labels[k] != v {
|
||||
goto loop
|
||||
}
|
||||
}
|
||||
result = append(result, replicaSet)
|
||||
loop:
|
||||
}
|
||||
Response(c, http.StatusOK, "success", result)
|
||||
}
|
||||
|
||||
func ControllerRevisions(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
queryType := c.Query("queryType")
|
||||
var controllerRevisions []appv1.ControllerRevision
|
||||
var controllerRevisionObject ControllerRevisionObject
|
||||
result := SearchObject(controllerVersionConst, clusterName, namespace, "")
|
||||
raw, err := result.Raw()
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "query controllerRevisions failed", err)
|
||||
return
|
||||
}
|
||||
json.Unmarshal(raw, &controllerRevisionObject)
|
||||
for i := range controllerRevisionObject.Items {
|
||||
if controllerRevisionObject.Items[i].OwnerReferences[0].Kind == queryType && controllerRevisionObject.Items[i].OwnerReferences[0].Name == name {
|
||||
controllerRevisions = append(controllerRevisions, controllerRevisionObject.Items[i])
|
||||
}
|
||||
|
||||
}
|
||||
Response(c, http.StatusOK, "success", controllerRevisions)
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ func CreateDomain(c *gin.Context) {
|
|||
// @Router /api/v1/domain/list [get]
|
||||
func ListDomain(c *gin.Context) {
|
||||
|
||||
domainName, _ := c.GetQuery("domain_name")
|
||||
domainName := c.Query("domain_name")
|
||||
|
||||
//获取域列表
|
||||
rows, _ := DB.Query("select domain_id,domain_name,longitude,latitude from domain where domain_name like ?", "%"+domainName+"%")
|
||||
|
@ -185,8 +185,8 @@ func ListDomain(c *gin.Context) {
|
|||
func DescribeDomain(c *gin.Context) {
|
||||
|
||||
var domain Domain
|
||||
domainId, _ := c.GetQuery("domain_id")
|
||||
namespace, _ := c.GetQuery("namespace")
|
||||
domainId := c.Query("domain_id")
|
||||
namespace := c.Query("namespace")
|
||||
rows, _ := DB.Query("select d.domain_name,dc.cluster_name,d.longitude,d.latitude from domain_cluster dc,domain d where dc.domain_id = d.domain_id and dc.domain_id = ?", domainId)
|
||||
var domainName string
|
||||
var longitude float64
|
||||
|
@ -247,8 +247,8 @@ func DescribeDomain(c *gin.Context) {
|
|||
// @Router /api/v1/domain/listByDeployment [get]
|
||||
func ListByDeployment(c *gin.Context) {
|
||||
domainList := make([]Domain, 0)
|
||||
namespaceName, _ := c.GetQuery("namespace")
|
||||
deploymentName, _ := c.GetQuery("deployment_name")
|
||||
namespaceName := c.Query("namespace")
|
||||
deploymentName := c.Query("deployment_name")
|
||||
|
||||
domainList = getDomainsByDeployment(namespaceName, deploymentName)
|
||||
|
||||
|
|
11
app/label.go
11
app/label.go
|
@ -3,7 +3,6 @@ package app
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -79,7 +78,7 @@ func DeleteLabel(c *gin.Context) {
|
|||
// @Router /api/v1/label/list [post]
|
||||
func ListLabel(c *gin.Context) {
|
||||
|
||||
labelName, _ := c.GetQuery("label_name")
|
||||
labelName := c.Query("label_name")
|
||||
|
||||
LabelList := make([]Label, 0)
|
||||
rows, err := DB.Query(`SELECT l.label_id,l.label_type_id ,lt.label_type ,l.label_name, l.create_time,l.update_time FROM label l,label_type lt WHERE l.label_type_id = lt.label_type_id and l.label_name like ?`, "%"+labelName+"%")
|
||||
|
@ -108,11 +107,9 @@ func ListLabel(c *gin.Context) {
|
|||
total := len(LabelList)
|
||||
page := &Page[Label]{}
|
||||
page.List = LabelList
|
||||
pageNum, _ := c.GetQuery("pageNum")
|
||||
pageSize, _ := c.GetQuery("pageSize")
|
||||
num, _ := strconv.ParseInt(pageNum, 10, 64)
|
||||
size, _ := strconv.ParseInt(pageSize, 10, 64)
|
||||
data := Paginator(page, int64(total), num, size)
|
||||
pageNum := c.Query("pageNum")
|
||||
pageSize := c.Query("pageSize")
|
||||
data := Paginator(page, int64(total), pageNum, pageSize)
|
||||
Response(c, http.StatusOK, "success", data)
|
||||
//Response(c, http.StatusOK, "success", LabelList)
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package app
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type LabelType struct {
|
||||
|
@ -77,7 +76,7 @@ func DeleteLabelType(c *gin.Context) {
|
|||
// @Router /api/v1/labelType/list [get]
|
||||
func ListLabelType(c *gin.Context) {
|
||||
|
||||
labelType, _ := c.GetQuery("label_type")
|
||||
labelType := c.Query("label_type")
|
||||
|
||||
LabelTypeList := make([]LabelType, 0)
|
||||
rows, err := DB.Query(`SELECT label_type_id,label_type,multi_check FROM label_type WHERE label_type like ?`, "%"+labelType+"%")
|
||||
|
@ -99,11 +98,9 @@ func ListLabelType(c *gin.Context) {
|
|||
total := len(LabelTypeList)
|
||||
page := &Page[LabelType]{}
|
||||
page.List = LabelTypeList
|
||||
pageNum, _ := c.GetQuery("pageNum")
|
||||
pageSize, _ := c.GetQuery("pageSize")
|
||||
num, _ := strconv.ParseInt(pageNum, 10, 64)
|
||||
size, _ := strconv.ParseInt(pageSize, 10, 64)
|
||||
data := Paginator(page, int64(total), num, size)
|
||||
pageNum := c.Query("pageNum")
|
||||
pageSize := c.Query("pageSize")
|
||||
data := Paginator(page, int64(total), pageNum, pageSize)
|
||||
Response(c, http.StatusOK, "success", data)
|
||||
//Response(c, http.StatusOK, "success", LabelTypeList)
|
||||
|
||||
|
|
395
app/namespace.go
395
app/namespace.go
|
@ -2,15 +2,28 @@ package app
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/karmada-io/karmada/pkg/util"
|
||||
v1 "k8s.io/api/batch/v1"
|
||||
coreV1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
namespace_memory_usage_wo_cache = "namespace:container_memory_usage_bytes_wo_cache:sum{cluster_name='clusterName',namespace='nameSpace', prometheus_replica='prometheus-k8s-0'}"
|
||||
namespace_cpu_usage = "sum by (namespace) (namespace:workload_cpu_usage:sum{cluster_name='clusterName',namespace='nameSpace', prometheus_replica='prometheus-k8s-0'})"
|
||||
namespace_pod_count = "count(sum by (pod) (kube_pod_container_info{cluster_name='clusterName', namespace='nameSpace', prometheus_replica='prometheus-k8s-0'}))"
|
||||
metric_range_12h = "12h"
|
||||
steps_namespace = 1080
|
||||
)
|
||||
|
||||
type Namespace struct {
|
||||
NsName string `json:"ns_name"`
|
||||
State string `json:"state"`
|
||||
|
@ -23,6 +36,13 @@ type Namespace struct {
|
|||
AvailablePodNum int32 `json:"available_pod_num"`
|
||||
Alias string `json:"alias"`
|
||||
Describe string `json:"describe"`
|
||||
TemplateId string `json:"templateId"`
|
||||
}
|
||||
|
||||
type NamespaceParam struct {
|
||||
Namespace coreV1.Namespace `json:"namespace"`
|
||||
TemplateId string `json:"templateId"`
|
||||
ClusterName []string `json:"clusterName"`
|
||||
}
|
||||
|
||||
type DomainResult struct {
|
||||
|
@ -30,6 +50,82 @@ type DomainResult struct {
|
|||
Location [2]float64 `json:"location"`
|
||||
}
|
||||
|
||||
type NamespaceObject struct {
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Metadata string `json:"metadata"`
|
||||
ResourceVersion string `json:"resourceVersion"`
|
||||
Items []coreV1.Namespace `json:"items"`
|
||||
}
|
||||
|
||||
type JobObject struct {
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Metadata string `json:"metadata"`
|
||||
ResourceVersion string `json:"resourceVersion"`
|
||||
Items []v1.Job `json:"items"`
|
||||
}
|
||||
|
||||
type NsResources struct {
|
||||
PodCount int `json:"podCount"`
|
||||
DeploymentCount int `json:"deploymentCount"`
|
||||
StatefulSetCount int `json:"statefulSetCount"`
|
||||
DaemonSetCount int `json:"daemonSetCount"`
|
||||
JobCount int `json:"jobCount"`
|
||||
PvcCount int `json:"pvcCount"`
|
||||
ServiceCount int `json:"serviceCount"`
|
||||
}
|
||||
|
||||
func GetNamespaceResources(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
// 查询pod
|
||||
podResult := SearchObject(podListConst, clusterName, namespace, "")
|
||||
var podObject PodObject
|
||||
podRaw, _ := podResult.Raw()
|
||||
json.Unmarshal(podRaw, &podObject)
|
||||
// 查询deployment
|
||||
deploymentResult := SearchObject(deploymentListConst, clusterName, namespace, "")
|
||||
var deploymentObject DeploymentObject
|
||||
deploymentRaw, _ := deploymentResult.Raw()
|
||||
json.Unmarshal(deploymentRaw, &deploymentObject)
|
||||
// 查询statefulSet
|
||||
statefulSetResult := SearchObject(statefulSetListConst, clusterName, namespace, "")
|
||||
var statefulSetObject StatefulSetObject
|
||||
statefulSetRaw, _ := statefulSetResult.Raw()
|
||||
json.Unmarshal(statefulSetRaw, &statefulSetObject)
|
||||
// 查询daemonSet
|
||||
daemonSetResult := SearchObject(daemonSetListConst, clusterName, namespace, "")
|
||||
var daemonSetObject DaemonSetObject
|
||||
daemonSetRaw, _ := daemonSetResult.Raw()
|
||||
json.Unmarshal(daemonSetRaw, &daemonSetObject)
|
||||
// 查询job
|
||||
jobResult := SearchObject(jobListConst, clusterName, namespace, "")
|
||||
var jobObject JobObject
|
||||
jobRaw, _ := jobResult.Raw()
|
||||
json.Unmarshal(jobRaw, &jobObject)
|
||||
// 查询pvc
|
||||
pvcResult := SearchObject(pvcListConst, clusterName, namespace, "")
|
||||
var pvcObject PVCObject
|
||||
pvcRaw, _ := pvcResult.Raw()
|
||||
json.Unmarshal(pvcRaw, &pvcObject)
|
||||
// 查询service
|
||||
serviceResult := SearchObject(serviceConst, clusterName, namespace, "")
|
||||
var serviceObject ServiceObject
|
||||
serviceRaw, _ := serviceResult.Raw()
|
||||
json.Unmarshal(serviceRaw, &serviceObject)
|
||||
Response(c, http.StatusOK, "success", NsResources{
|
||||
PodCount: len(podObject.Items),
|
||||
DeploymentCount: len(deploymentObject.Items),
|
||||
StatefulSetCount: len(statefulSetObject.Items),
|
||||
DaemonSetCount: len(daemonSetObject.Items),
|
||||
JobCount: len(jobObject.Items),
|
||||
PvcCount: len(pvcObject.Items),
|
||||
ServiceCount: len(serviceObject.Items),
|
||||
})
|
||||
}
|
||||
|
||||
// CreateNamespace 创建命名空间(项目)
|
||||
// @Summary 创建命名空间(项目)
|
||||
// @Description 创建命名空间(项目)
|
||||
// @Tags namespace
|
||||
|
@ -40,38 +136,125 @@ type DomainResult struct {
|
|||
// @Failure 400
|
||||
// @Router /api/v1/namespace/create [post]
|
||||
func CreateNamespace(c *gin.Context) {
|
||||
var j Namespace
|
||||
labels := make(map[string]string)
|
||||
labels["jcce"] = "true"
|
||||
if err := c.BindJSON(&j); err != nil {
|
||||
var nsParam NamespaceParam
|
||||
if nsParam.Namespace.Labels == nil {
|
||||
nsParam.Namespace.Labels = map[string]string{}
|
||||
}
|
||||
nsParam.Namespace.Labels["jcce"] = "true"
|
||||
if err := c.BindJSON(&nsParam); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
sqlStr1 := "INSERT INTO joint_domain.namespace (namespace_name, alias, `describe`) VALUES(?,?,?)"
|
||||
_, err := DB.Exec(sqlStr1, j.NsName, j.Alias, j.Describe)
|
||||
_, err := DB.Exec(sqlStr1, nsParam.Namespace.Name, nsParam.Namespace.Annotations["kubesphere.io/alias-name"], nsParam.Namespace.Annotations["kubesphere.io/description"])
|
||||
if err != nil {
|
||||
Response(c, http.StatusBadRequest, "query failed!", err)
|
||||
return
|
||||
}
|
||||
|
||||
ns := coreV1.Namespace{
|
||||
TypeMeta: metav1.TypeMeta{},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: j.NsName,
|
||||
Labels: labels,
|
||||
},
|
||||
Spec: coreV1.NamespaceSpec{},
|
||||
Status: coreV1.NamespaceStatus{},
|
||||
}
|
||||
|
||||
nsResult, err := ClientSet.CoreV1().Namespaces().Create(context.TODO(), &ns, metav1.CreateOptions{})
|
||||
nsResult, err := ClientSet.CoreV1().Namespaces().Create(context.TODO(), &nsParam.Namespace, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
println(err)
|
||||
}
|
||||
// 创建调度策略实例
|
||||
CreatePropagationPolicies(PropagationPolicy{
|
||||
ClusterName: nsParam.ClusterName,
|
||||
TemplateId: nsParam.TemplateId,
|
||||
ResourceName: nsParam.Namespace.Name,
|
||||
Name: "Namespace" + "." + nsParam.Namespace.Name,
|
||||
Kind: "Namespace",
|
||||
})
|
||||
Response(c, http.StatusOK, "success", nsResult)
|
||||
|
||||
}
|
||||
|
||||
// ListNamespaceFromCluster 根据指定集群查询命名空间
|
||||
func ListNamespaceFromCluster(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
name := c.Query("name")
|
||||
pageNum := c.Query("pageNum")
|
||||
pageSize := c.Query("pageSize")
|
||||
queryType := c.Query("queryType")
|
||||
searchObject := SearchObject(namespaceConst, clusterName, "", "")
|
||||
raw, _ := searchObject.Raw()
|
||||
var namespaceObject NamespaceObject
|
||||
json.Unmarshal(raw, &namespaceObject)
|
||||
var result []coreV1.Namespace
|
||||
// 查询用户项目or系统项目
|
||||
if strings.EqualFold(queryType, "system") {
|
||||
for i := range namespaceObject.Items {
|
||||
value, ok := namespaceObject.Items[i].Labels["kubesphere.io/workspace"]
|
||||
if ok && strings.Contains(value, "system-workspace") {
|
||||
result = append(result, namespaceObject.Items[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
if strings.EqualFold(queryType, "user") {
|
||||
for i := range namespaceObject.Items {
|
||||
value, ok := namespaceObject.Items[i].Labels["kubesphere.io/workspace"]
|
||||
if !(ok && strings.Contains(value, "system-workspace")) {
|
||||
result = append(result, namespaceObject.Items[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
var nameQueryResult []coreV1.Namespace
|
||||
// 模糊查询
|
||||
if len(name) != 0 {
|
||||
for i := range result {
|
||||
if strings.Contains(result[i].Name, name) {
|
||||
nameQueryResult = append(nameQueryResult, result[i])
|
||||
}
|
||||
}
|
||||
result = nameQueryResult
|
||||
}
|
||||
if result == nil {
|
||||
Response(c, http.StatusOK, "success", nil)
|
||||
return
|
||||
}
|
||||
// 分页
|
||||
page := &Page[coreV1.Namespace]{}
|
||||
page.List = result
|
||||
// 排序
|
||||
sort.SliceStable(result, func(i, j int) bool {
|
||||
return result[i].CreationTimestamp.Time.After(result[j].CreationTimestamp.Time)
|
||||
})
|
||||
data := Paginator(page, int64(len(result)), pageNum, pageSize)
|
||||
Response(c, http.StatusOK, "success", data)
|
||||
}
|
||||
|
||||
// ListName 获取所有项目名
|
||||
func ListName(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
result := SearchObject(namespaceConst, clusterName, "", "")
|
||||
raw, _ := result.Raw()
|
||||
var namespaceObject NamespaceObject
|
||||
json.Unmarshal(raw, &namespaceObject)
|
||||
var namespaceList []string
|
||||
for _, namespace := range namespaceObject.Items {
|
||||
namespaceList = append(namespaceList, namespace.Name)
|
||||
}
|
||||
Response(c, http.StatusOK, "success", namespaceList)
|
||||
}
|
||||
|
||||
func IsExistNamespace(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
name := c.Query("name")
|
||||
result := SearchObject(detailNamespaceConst, clusterName, "", name)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusOK, "success", false)
|
||||
return
|
||||
}
|
||||
raw, _ := result.Raw()
|
||||
var namespace coreV1.Namespace
|
||||
json.Unmarshal(raw, &namespace)
|
||||
if len(namespace.Name) == 0 {
|
||||
Response(c, http.StatusOK, "success", false)
|
||||
return
|
||||
}
|
||||
Response(c, http.StatusOK, "success", true)
|
||||
}
|
||||
|
||||
// ListNamespace 查询Namespace列表
|
||||
// @Summary 查询Namespace列表
|
||||
// @Description 查询Namespace列表
|
||||
// @Tags namespace
|
||||
|
@ -137,13 +320,21 @@ func ListNamespace(ctx *gin.Context) {
|
|||
page.List = nsList
|
||||
pageNum, _ := ctx.GetQuery("pageNum")
|
||||
pageSize, _ := ctx.GetQuery("pageSize")
|
||||
num, _ := strconv.ParseInt(pageNum, 10, 64)
|
||||
size, _ := strconv.ParseInt(pageSize, 10, 64)
|
||||
data := Paginator(page, int64(total), num, size)
|
||||
data := Paginator(page, int64(total), pageNum, pageSize)
|
||||
Response(ctx, http.StatusOK, "success", data)
|
||||
|
||||
}
|
||||
|
||||
func DetailNamespace(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
name := c.Query("name")
|
||||
result := SearchObject(detailNamespaceConst, clusterName, "", name)
|
||||
raw, _ := result.Raw()
|
||||
var namespace coreV1.Namespace
|
||||
json.Unmarshal(raw, &namespace)
|
||||
Response(c, http.StatusOK, "success", namespace)
|
||||
}
|
||||
|
||||
// @Summary 查询Namespace详情
|
||||
// @Description 查询Namespace详情
|
||||
// @Tags namespace
|
||||
|
@ -155,7 +346,7 @@ func ListNamespace(ctx *gin.Context) {
|
|||
// @Router /api/v1/namespace/describe [get]
|
||||
func DescribeNamespace(c *gin.Context) {
|
||||
|
||||
namespace, _ := c.GetQuery("namespace")
|
||||
namespace := c.Query("namespace")
|
||||
|
||||
optsGet := metav1.GetOptions{
|
||||
TypeMeta: metav1.TypeMeta{},
|
||||
|
@ -273,48 +464,146 @@ func DescribeNamespace(c *gin.Context) {
|
|||
// @Failure 400
|
||||
// @Router /api/v1/namespace/update [post]
|
||||
func UpdateNamespace(c *gin.Context) {
|
||||
var j Namespace
|
||||
if err := c.BindJSON(&j); err != nil {
|
||||
clusterName := c.Query("clusterName")
|
||||
var namespace coreV1.Namespace
|
||||
if err := c.BindJSON(&namespace); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
|
||||
ns := coreV1.Namespace{
|
||||
TypeMeta: metav1.TypeMeta{},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: j.NsName,
|
||||
},
|
||||
Spec: coreV1.NamespaceSpec{},
|
||||
Status: coreV1.NamespaceStatus{},
|
||||
if len(namespace.Labels["jcce"]) != 0 {
|
||||
_, err := ClientSet.CoreV1().Namespaces().Update(context.TODO(), &namespace, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "update namespace failed", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
result := UpdateObject(detailNamespaceConst, clusterName, "", namespace.Name, namespace)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "update namespace failed", result.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
nsResult, err := ClientSet.CoreV1().Namespaces().Update(context.TODO(), &ns, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
println(err)
|
||||
}
|
||||
Response(c, http.StatusOK, "success", nsResult)
|
||||
Response(c, http.StatusOK, "success", "")
|
||||
|
||||
}
|
||||
|
||||
// DeleteNamespace 删除命名空间(项目)
|
||||
func DeleteNamespace(c *gin.Context) {
|
||||
var j Namespace
|
||||
if err := c.BindJSON(&j); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
|
||||
err := ClientSet.CoreV1().Namespaces().Delete(context.TODO(), j.NsName, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete namespace "+j.NsName+"failed", "")
|
||||
println(err)
|
||||
}
|
||||
// 删除数据库记录policy实例
|
||||
_, err = DB.Exec(`delete from joint_domain.namespace where namespace_name = ? `, j.NsName)
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete db failed", err)
|
||||
return
|
||||
clusterName := c.Param("clusterName")
|
||||
name := c.Param("name")
|
||||
label := c.Param("label")
|
||||
if strings.EqualFold(label, "jcce") {
|
||||
err := ClientSet.CoreV1().Namespaces().Delete(context.TODO(), name, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete namespace "+name+"failed", "")
|
||||
return
|
||||
}
|
||||
// 删除数据库记录policy实例
|
||||
_, err = DB.Exec(`delete from joint_domain.namespace where namespace_name = ? `, name)
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete db failed", err)
|
||||
return
|
||||
}
|
||||
// 删除调度策略
|
||||
DeletePropagationPolicies(name, "Namespace"+"."+name)
|
||||
} else {
|
||||
result := DeleteObject(detailNamespaceConst, clusterName, "", name)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete persistentVolumeClaim failed", result.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
Response(c, http.StatusOK, "success", "")
|
||||
|
||||
}
|
||||
|
||||
// @Summary namespace监控
|
||||
// @Description namespace监控
|
||||
// @Tags namespace
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Param clusterName query string true "集群名"
|
||||
// @Param namespace query string true "命名空间名称"
|
||||
// @Success 200
|
||||
// @Failure 400
|
||||
// @Router /api/v1/namespace/getMetrics [get]
|
||||
func GetNamespaceMetrics(c *gin.Context) {
|
||||
clusterName, _ := c.GetQuery("clusterName")
|
||||
namespace, _ := c.GetQuery("namespace")
|
||||
|
||||
replaceMap := make(map[string]string)
|
||||
replaceMap[ClusterName] = clusterName
|
||||
replaceMap["nameSpace"] = namespace
|
||||
|
||||
metricMap := map[string][]MetricUrl{
|
||||
"namespace_memory_usage_wo_cache": {{"nameSpace", namespace, GetMetricUrl(namespace_memory_usage_wo_cache, replaceMap, "nameSpace", metric_range_12h, steps_namespace)}},
|
||||
"namespace_cpu_usage": {{"nameSpace", namespace, GetMetricUrl(namespace_cpu_usage, replaceMap, "nameSpace", metric_range_12h, steps_namespace)}},
|
||||
}
|
||||
|
||||
ch := make(chan MetricResult, len(metricMap))
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for k, v := range metricMap {
|
||||
wg.Add(1)
|
||||
go HttpGetMetrics(k, v, &wg, ch)
|
||||
}
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
|
||||
mr := []MetricResult{}
|
||||
for v := range ch {
|
||||
mr = append(mr, v)
|
||||
}
|
||||
|
||||
Response(c, http.StatusOK, "success", mr)
|
||||
}
|
||||
|
||||
// @Summary 批量获取namespace监控
|
||||
// @Description 批量获取namespace监控
|
||||
// @Tags namespace
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Param clusterName query string true "集群名"
|
||||
// @Param namespaces query string true "逗号分隔多个命名空间名称"
|
||||
// @Success 200
|
||||
// @Failure 400
|
||||
// @Router /api/v1/namespace/getBatchMetrics [get]
|
||||
func GetBatchNamespaceMetrics(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespaces := c.Query("namespaces")
|
||||
|
||||
namespace := strings.Split(namespaces, ",")
|
||||
|
||||
metricUrls := make([][]MetricUrl, 3)
|
||||
for _, name := range namespace {
|
||||
imap := map[string]string{
|
||||
ClusterName: clusterName,
|
||||
"nameSpace": name,
|
||||
}
|
||||
metricUrls[0] = append(metricUrls[0], MetricUrl{"nameSpace", name, GetMetricUrl(namespace_memory_usage_wo_cache, imap, "nameSpace", metric_range_1s, steps_1s)})
|
||||
metricUrls[1] = append(metricUrls[1], MetricUrl{"nameSpace", name, GetMetricUrl(namespace_cpu_usage, imap, "nameSpace", metric_range_1s, steps_1s)})
|
||||
metricUrls[2] = append(metricUrls[2], MetricUrl{"nameSpace", name, GetMetricUrl(namespace_pod_count, imap, "nameSpace", metric_range_1s, steps_1s)})
|
||||
}
|
||||
|
||||
metricMap := map[string][]MetricUrl{
|
||||
"namespace_memory_usage_wo_cache": metricUrls[0],
|
||||
"namespace_cpu_usage": metricUrls[1],
|
||||
"namespace_pod_count": metricUrls[2],
|
||||
}
|
||||
|
||||
ch := make(chan MetricResult, len(metricMap))
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for k, v := range metricMap {
|
||||
wg.Add(1)
|
||||
go HttpGetMetrics(k, v, &wg, ch)
|
||||
}
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
|
||||
mr := []MetricResult{}
|
||||
for v := range ch {
|
||||
mr = append(mr, v)
|
||||
}
|
||||
|
||||
Response(c, http.StatusOK, "success", mr)
|
||||
}
|
||||
|
|
338
app/node.go
338
app/node.go
|
@ -1,12 +1,20 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/metrics/pkg/apis/metrics"
|
||||
"math"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type NodeRes struct {
|
||||
|
@ -30,6 +38,97 @@ type NodeExtendRes struct {
|
|||
PodStatus v1.PodPhase `json:"podStatus"`
|
||||
}
|
||||
|
||||
type NodeCountResult struct {
|
||||
MasterCount int `json:"masterCount"`
|
||||
AllCount int `json:"allCount"`
|
||||
WorkCount int `json:"workCount"`
|
||||
}
|
||||
|
||||
const (
|
||||
node_cpu_utilisation_1h = "node:node_cpu_utilisation:avg1m{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_pod_utilisation_1h = "node:pod_utilization:ratio{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_memory_utilisation_1h = "node:node_memory_utilisation:{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_disk_size_utilisation_1h = "node:disk_space_utilization:ratio{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
|
||||
node_load15_8h = "node:load15:ratio{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_disk_write_iops_8h = "node:data_volume_iops_writes:sum{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_cpu_utilisation_8h = "node:node_cpu_utilisation:avg1m{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_net_bytes_transmitted_8h = "node:node_net_bytes_transmitted:sum_irate{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_disk_inode_total_8h = "node:node_inodes_total:{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_disk_read_throughput_8h = "node:data_volume_throughput_bytes_read:sum{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_net_bytes_received_8h = "node:node_net_bytes_received:sum_irate{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_memory_utilisation_8h = "node:node_memory_utilisation:{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_disk_write_throughput_8h = "node:data_volume_throughput_bytes_written:sum{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_load5_8h = "node:load5:ratio{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_disk_inode_usage_8h = "node:node_inodes_total:{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'} * node:disk_inode_utilization:ratio{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_disk_read_iops_8h = "node:data_volume_iops_reads:sum{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_disk_size_utilisation_8h = "node:disk_space_utilization:ratio{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_disk_inode_utilisation_8h = "node:disk_inode_utilization:ratio{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_load1_8h = "node:load1:ratio{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'}"
|
||||
|
||||
node_cpu_limits = "sum by (node) (kube_pod_container_resource_limits_cpu_cores{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'})"
|
||||
node_cpu_requests = "sum by (node) (kube_pod_container_resource_requests_cpu_cores{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'})"
|
||||
node_memory_limits = "sum by (node) (kube_pod_container_resource_limits_memory_bytes{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'})"
|
||||
node_memory_requests = "sum by (node) (kube_pod_container_resource_requests_memory_bytes{cluster_name='clusterName',node='nodeName', prometheus_replica='prometheus-k8s-0'})"
|
||||
|
||||
NodeName = "nodeName"
|
||||
metric_range_1h = "1h"
|
||||
steps_1h = 180
|
||||
metric_range_8h = "8.333h"
|
||||
steps_8h = 600
|
||||
max = 10
|
||||
)
|
||||
|
||||
// NodeCount 查询节点数量
|
||||
func NodeCount(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
result := SearchObject(nodeConst, clusterName, "", "")
|
||||
raw, _ := result.Raw()
|
||||
var nodeRes NodeRes
|
||||
json.Unmarshal(raw, &nodeRes)
|
||||
var masterCount int
|
||||
var edgerCount int
|
||||
for i := range nodeRes.Items {
|
||||
if _, ok := nodeRes.Items[i].Labels["node-role.kubernetes.io/master"]; ok {
|
||||
masterCount++
|
||||
}
|
||||
if _, ok := nodeRes.Items[i].Labels["node-role.kubernetes.io/edge"]; ok {
|
||||
edgerCount++
|
||||
}
|
||||
}
|
||||
Response(c, http.StatusOK, "success", NodeCountResult{
|
||||
AllCount: len(nodeRes.Items) - edgerCount,
|
||||
MasterCount: masterCount,
|
||||
WorkCount: len(nodeRes.Items) - masterCount - edgerCount,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// UpdateNode 更新节点信息
|
||||
func UpdateNode(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
var node v1.Node
|
||||
if err := c.BindJSON(&node); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
if len(node.Labels["jcce"]) != 0 {
|
||||
_, err := ClientSet.CoreV1().Nodes().Update(context.TODO(), &node, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusBadRequest, "update node error.", "")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
result := UpdateObject(detailNodeConst, clusterName, "", node.Name, node)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "update persistentVolumeClaim failed", result.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
Response(c, http.StatusOK, "success", "")
|
||||
}
|
||||
|
||||
// ListNode 查询节点列表
|
||||
// @Summary 查询节点列表
|
||||
// @Description 查询节点列表
|
||||
// @Tags node
|
||||
|
@ -40,12 +139,132 @@ type NodeExtendRes struct {
|
|||
// @Failure 500
|
||||
// @Router /api/v1/node/list/{clusterName} [get]
|
||||
func ListNode(c *gin.Context) {
|
||||
clusterName := c.Param("clusterName")
|
||||
result := SearchObject(nodeConst, clusterName, "", "")
|
||||
raw, _ := result.Raw()
|
||||
clusterName := c.Query("clusterName")
|
||||
pageNum := c.Query("pageNum")
|
||||
pageSize := c.Query("pageSize")
|
||||
queryType := c.Query("queryType")
|
||||
nodeResult := SearchObject(nodeConst, clusterName, "", "")
|
||||
raw, _ := nodeResult.Raw()
|
||||
var nodeRes NodeRes
|
||||
json.Unmarshal(raw, &nodeRes)
|
||||
Response(c, http.StatusOK, "success", nodeRes.Items)
|
||||
var result []v1.Node
|
||||
if strings.EqualFold(queryType, "edge") {
|
||||
for i := range nodeRes.Items {
|
||||
if _, ok := nodeRes.Items[i].Labels["node-role.kubernetes.io/edge"]; ok {
|
||||
result = append(result, nodeRes.Items[i])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i := range nodeRes.Items {
|
||||
if _, ok := nodeRes.Items[i].Labels["node-role.kubernetes.io/edge"]; !ok {
|
||||
result = append(result, nodeRes.Items[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
// 分页
|
||||
page := &Page[v1.Node]{}
|
||||
page.List = result
|
||||
// 排序
|
||||
sort.SliceStable(page.List, func(i, j int) bool {
|
||||
return page.List[i].CreationTimestamp.Time.After(page.List[j].CreationTimestamp.Time)
|
||||
})
|
||||
data := Paginator(page, int64(len(page.List)), pageNum, pageSize)
|
||||
Response(c, http.StatusOK, "success", data)
|
||||
}
|
||||
|
||||
// DetailNode 查询节点详情
|
||||
func DetailNode(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
name := c.Query("name")
|
||||
// 查询节点信息
|
||||
nodeRes := SearchObject(detailNodeConst, clusterName, "", name)
|
||||
nodeRaw, _ := nodeRes.Raw()
|
||||
var node v1.Node
|
||||
json.Unmarshal(nodeRaw, &node)
|
||||
|
||||
cpu_capacity, _ := node.Status.Capacity.Cpu().AsInt64()
|
||||
cpu_capacity_float := float64(cpu_capacity)
|
||||
ephemeral_storage, _ := node.Status.Capacity.StorageEphemeral().AsInt64()
|
||||
ephemeral_storage_float := float64(ephemeral_storage)
|
||||
|
||||
replaceMap := make(map[string]string)
|
||||
replaceMap[ClusterName] = clusterName
|
||||
replaceMap[NodeName] = name
|
||||
|
||||
metricMap := map[string][]MetricUrl{
|
||||
"node_cpu_limits": {{NodeName, name, GetMetricUrl(node_cpu_limits, replaceMap, NodeName, metric_range_1s, steps_1s)}},
|
||||
"node_cpu_requests": {{NodeName, name, GetMetricUrl(node_cpu_requests, replaceMap, NodeName, metric_range_1s, steps_1s)}},
|
||||
"node_memory_limits": {{NodeName, name, GetMetricUrl(node_memory_limits, replaceMap, NodeName, metric_range_1s, steps_1s)}},
|
||||
"node_memory_requests": {{NodeName, name, GetMetricUrl(node_memory_requests, replaceMap, NodeName, metric_range_1s, steps_1s)}},
|
||||
}
|
||||
|
||||
ch := make(chan MetricResult, len(metricMap))
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for k, v := range metricMap {
|
||||
wg.Add(1)
|
||||
go HttpGetMetrics(k, v, &wg, ch)
|
||||
}
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
|
||||
aMap := map[string]string{}
|
||||
for v := range ch {
|
||||
if len(v.MetricData.Result) == 0 {
|
||||
continue
|
||||
}
|
||||
format := v.MetricData.Result[0]["values"]
|
||||
valStr := fmt.Sprintf("%v", format)
|
||||
vals := strings.Split(valStr, " ")
|
||||
val := strings.Trim(vals[1], "]]")
|
||||
|
||||
switch v.MetricName {
|
||||
case "node_cpu_limits":
|
||||
aMap["node_cpu_limits"] = val
|
||||
ival, _ := strconv.ParseFloat(val, 64)
|
||||
fraction := ival / cpu_capacity_float
|
||||
aMap["node_cpu_limits_fraction"] = fmt.Sprintf("%.0f%%", math.Round(fraction*100))
|
||||
case "node_cpu_requests":
|
||||
aMap["node_cpu_requests"] = val
|
||||
ival, _ := strconv.ParseFloat(val, 64)
|
||||
fraction := ival / cpu_capacity_float
|
||||
aMap["node_cpu_requests_fraction"] = fmt.Sprintf("%.0f%%", math.Round(fraction*100))
|
||||
case "node_memory_limits":
|
||||
aMap["node_memory_limits"] = val
|
||||
ival, _ := strconv.ParseFloat(val, 64)
|
||||
fraction := ival / ephemeral_storage_float
|
||||
aMap["node_memory_limits_fraction"] = fmt.Sprintf("%.0f%%", math.Round(fraction*100))
|
||||
case "node_memory_requests":
|
||||
aMap["node_memory_requests"] = val
|
||||
ival, _ := strconv.ParseFloat(val, 64)
|
||||
fraction := ival / ephemeral_storage_float
|
||||
aMap["node_memory_requests_fraction"] = fmt.Sprintf("%.0f%%", math.Round(fraction*100))
|
||||
}
|
||||
}
|
||||
|
||||
nodeMetricLength := 8
|
||||
if len(aMap) != nodeMetricLength {
|
||||
Response(c, http.StatusOK, "query node list success", node)
|
||||
return
|
||||
}
|
||||
|
||||
formatted_str := fmt.Sprintf(`[{"op":"replace","path":"/metadata/annotations/node.kubesphere.io~1cpu-limits", "value": "%s"},
|
||||
{"op":"replace","path":"/metadata/annotations/node.kubesphere.io~1cpu-limits-fraction", "value": "%s"},
|
||||
{"op":"replace","path":"/metadata/annotations/node.kubesphere.io~1cpu_requests", "value": "%s"},
|
||||
{"op":"replace","path":"/metadata/annotations/node.kubesphere.io~1cpu_requests-fraction", "value": "%s"},
|
||||
{"op":"replace","path":"/metadata/annotations/node.kubesphere.io~1memory_limits", "value": "%s"},
|
||||
{"op":"replace","path":"/metadata/annotations/node.kubesphere.io~1memory_limits-fraction", "value": "%s"},
|
||||
{"op":"replace","path":"/metadata/annotations/node.kubesphere.io~1memory_requests", "value": "%s"},
|
||||
{"op":"replace","path":"/metadata/annotations/node.kubesphere.io~1memory_requests-fraction", "value": "%s"}]`,
|
||||
aMap["node_cpu_limits"], aMap["node_cpu_limits_fraction"], aMap["node_cpu_requests"],
|
||||
aMap["node_cpu_requests_fraction"], aMap["node_memory_limits"], aMap["node_memory_limits_fraction"],
|
||||
aMap["node_memory_requests"], aMap["node_memory_requests_fraction"])
|
||||
aliasJson := []byte(formatted_str)
|
||||
|
||||
PatchObject(detailNodeConst, clusterName, "", node.Name, aliasJson, types.JSONPatchType)
|
||||
|
||||
Response(c, http.StatusOK, "query node list success", node)
|
||||
}
|
||||
|
||||
// @Summary 根据集群名称 命名空间 pod名称查询节点信息
|
||||
|
@ -60,9 +279,9 @@ func ListNode(c *gin.Context) {
|
|||
// @Failure 500
|
||||
// @Router /api/v1/node/detail/{clusterName}/{namespace}/{podName} [get]
|
||||
func queryNodeInfo(c *gin.Context) {
|
||||
clusterName := c.Param("clusterName")
|
||||
namespace := c.Param("namespace")
|
||||
podName := c.Param("podName")
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
podName := c.Query("podName")
|
||||
var result NodeExtendRes
|
||||
// 查询节点信息
|
||||
nodeRes := SearchObject(nodeConst, clusterName, "", "")
|
||||
|
@ -95,7 +314,7 @@ func queryNodeInfo(c *gin.Context) {
|
|||
// @Failure 500
|
||||
// @Router /api/v1/node/edge/{clusterName} [get]
|
||||
func ListEdgeNode(c *gin.Context) {
|
||||
clusterName := c.Param("clusterName")
|
||||
clusterName := c.Query("clusterName")
|
||||
result := SearchObject(nodeConst, clusterName, "", "")
|
||||
raw, _ := result.Raw()
|
||||
var nodeRes NodeRes
|
||||
|
@ -120,10 +339,111 @@ func ListEdgeNode(c *gin.Context) {
|
|||
// @Failure 500
|
||||
// @Router /api/v1/node/metrics/{clusterName} [get]
|
||||
func ListNodeMetrics(c *gin.Context) {
|
||||
clusterName := c.Param("clusterName")
|
||||
clusterName := c.Query("clusterName")
|
||||
result := SearchObject(nodeMetrics, clusterName, "", "")
|
||||
raw, _ := result.Raw()
|
||||
var metricsRes MetricsRes
|
||||
json.Unmarshal(raw, &metricsRes)
|
||||
Response(c, http.StatusOK, "success", metricsRes.Items)
|
||||
}
|
||||
|
||||
// @Summary 获取集群节点1h监控
|
||||
// @Description 获取集群节点1h监控
|
||||
// @Tags node
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Param clusterName query string true "集群名称"
|
||||
// @Param nodeName query string true "节点名称"
|
||||
// @Success 200
|
||||
// @Failure 400
|
||||
// @Router /api/v1/node/getNodeMetrics1h [get]
|
||||
func GetNodeMetrics1h(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
nodeName := c.Query("nodeName")
|
||||
|
||||
replaceMap := make(map[string]string)
|
||||
replaceMap[ClusterName] = clusterName
|
||||
replaceMap[NodeName] = nodeName
|
||||
|
||||
metricMap := map[string][]MetricUrl{
|
||||
"node_cpu_utilisation": {{NodeName, nodeName, GetMetricUrl(node_cpu_utilisation_1h, replaceMap, NodeName, metric_range_1h, steps_1h)}},
|
||||
"node_pod_utilisation": {{NodeName, nodeName, GetMetricUrl(node_pod_utilisation_1h, replaceMap, NodeName, metric_range_1h, steps_1h)}},
|
||||
"node_memory_utilisation": {{NodeName, nodeName, GetMetricUrl(node_memory_utilisation_1h, replaceMap, NodeName, metric_range_1h, steps_1h)}},
|
||||
"node_disk_size_utilisation": {{NodeName, nodeName, GetMetricUrl(node_disk_size_utilisation_1h, replaceMap, NodeName, metric_range_1h, steps_1h)}},
|
||||
}
|
||||
|
||||
ch := make(chan MetricResult, len(metricMap))
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for k, v := range metricMap {
|
||||
wg.Add(1)
|
||||
go HttpGetMetrics(k, v, &wg, ch)
|
||||
}
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
|
||||
mr := []MetricResult{}
|
||||
for v := range ch {
|
||||
mr = append(mr, v)
|
||||
}
|
||||
|
||||
Response(c, http.StatusOK, "success", mr)
|
||||
}
|
||||
|
||||
// @Summary 获取集群节点8h监控
|
||||
// @Description 获取集群节点8h监控
|
||||
// @Tags node
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Param clusterName query string true "集群名称"
|
||||
// @Param nodeName query string true "节点名称"
|
||||
// @Success 200
|
||||
// @Failure 400
|
||||
// @Router /api/v1/node/getNodeMetrics8h [get]
|
||||
func GetNodeMetrics8h(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
nodeName := c.Query("nodeName")
|
||||
|
||||
replaceMap := make(map[string]string)
|
||||
replaceMap[ClusterName] = clusterName
|
||||
replaceMap[NodeName] = nodeName
|
||||
|
||||
metricMap := map[string][]MetricUrl{
|
||||
"node_load15": {{NodeName, nodeName, GetMetricUrl(node_load15_8h, replaceMap, NodeName, metric_range_8h, steps_8h)}},
|
||||
"node_disk_write_iops": {{NodeName, nodeName, GetMetricUrl(node_disk_write_iops_8h, replaceMap, NodeName, metric_range_8h, steps_8h)}},
|
||||
"node_cpu_utilisation": {{NodeName, nodeName, GetMetricUrl(node_cpu_utilisation_8h, replaceMap, NodeName, metric_range_8h, steps_8h)}},
|
||||
"node_net_bytes_transmitted": {{NodeName, nodeName, GetMetricUrl(node_net_bytes_transmitted_8h, replaceMap, NodeName, metric_range_8h, steps_8h)}},
|
||||
"node_disk_inode_total": {{NodeName, nodeName, GetMetricUrl(node_disk_inode_total_8h, replaceMap, NodeName, metric_range_8h, steps_8h)}},
|
||||
"node_disk_read_throughput": {{NodeName, nodeName, GetMetricUrl(node_disk_read_throughput_8h, replaceMap, NodeName, metric_range_8h, steps_8h)}},
|
||||
"node_net_bytes_received": {{NodeName, nodeName, GetMetricUrl(node_net_bytes_received_8h, replaceMap, NodeName, metric_range_8h, steps_8h)}},
|
||||
"node_memory_utilisation": {{NodeName, nodeName, GetMetricUrl(node_memory_utilisation_8h, replaceMap, NodeName, metric_range_8h, steps_8h)}},
|
||||
"node_disk_write_throughput": {{NodeName, nodeName, GetMetricUrl(node_disk_write_throughput_8h, replaceMap, NodeName, metric_range_8h, steps_8h)}},
|
||||
"node_load5": {{NodeName, nodeName, GetMetricUrl(node_load5_8h, replaceMap, NodeName, metric_range_8h, steps_8h)}},
|
||||
"node_disk_inode_usage": {{NodeName, nodeName, GetMetricUrl(node_disk_inode_usage_8h, replaceMap, NodeName, metric_range_8h, steps_8h)}},
|
||||
"node_disk_read_iops": {{NodeName, nodeName, GetMetricUrl(node_disk_read_iops_8h, replaceMap, NodeName, metric_range_8h, steps_8h)}},
|
||||
"node_disk_size_utilisation": {{NodeName, nodeName, GetMetricUrl(node_disk_size_utilisation_8h, replaceMap, NodeName, metric_range_8h, steps_8h)}},
|
||||
"node_disk_inode_utilisation": {{NodeName, nodeName, GetMetricUrl(node_disk_inode_utilisation_8h, replaceMap, NodeName, metric_range_8h, steps_8h)}},
|
||||
"node_load1": {{NodeName, nodeName, GetMetricUrl(node_load1_8h, replaceMap, NodeName, metric_range_8h, steps_8h)}},
|
||||
}
|
||||
|
||||
ch := make(chan MetricResult, len(metricMap))
|
||||
limit := make(chan bool, max)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for k, v := range metricMap {
|
||||
limit <- true
|
||||
wg.Add(1)
|
||||
go HttpGetMetrics(k, v, &wg, ch)
|
||||
<-limit
|
||||
}
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
|
||||
mr := []MetricResult{}
|
||||
for v := range ch {
|
||||
mr = append(mr, v)
|
||||
}
|
||||
|
||||
Response(c, http.StatusOK, "success", mr)
|
||||
}
|
||||
|
|
|
@ -3,9 +3,11 @@ package app
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/bitly/go-simplejson"
|
||||
"github.com/opensearch-project/opensearch-go/v2/opensearchapi"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/rest"
|
||||
"strings"
|
||||
)
|
||||
|
@ -13,26 +15,77 @@ import (
|
|||
const (
|
||||
clusterProxy = "/apis/cluster.karmada.io/v1alpha1/clusters/%s/proxy"
|
||||
|
||||
nodeConst = "node"
|
||||
deploymentConst = "deployment"
|
||||
podDetailConst = "podDetail"
|
||||
podListConst = "podList"
|
||||
nodeConst = "node"
|
||||
detailHPAConst = "hpa"
|
||||
deploymentConst = "deployment"
|
||||
deploymentListConst = "deploymentList"
|
||||
namespaceConst = "namespace"
|
||||
detailNamespaceConst = "detailNamespace"
|
||||
podDetailConst = "podDetail"
|
||||
podListConst = "podList"
|
||||
detailPvcConst = "detailPvc"
|
||||
pvcListConst = "pvcList"
|
||||
serviceConst = "service"
|
||||
detailServiceConst = "detailService"
|
||||
allServiceConst = "allService"
|
||||
scConst = "sc"
|
||||
pvcConst = "pvc"
|
||||
pvConst = "pv"
|
||||
podMetrics = "podMetrics"
|
||||
nodeMetrics = "nodeMetrics"
|
||||
crdConst = "crd"
|
||||
secretConst = "secret"
|
||||
configMapConst = "configMap"
|
||||
statefulSetConst = "statefulSet"
|
||||
daemonSetConst = "daemonSet"
|
||||
allPodConst = "allPod"
|
||||
detailPodConst = "detailPod"
|
||||
detailNodeConst = "detailNode"
|
||||
statefulSetListConst = "statefulSetList"
|
||||
daemonSetListConst = "daemonSetList"
|
||||
jobListConst = "jobList"
|
||||
allDeploymentConst = "allDeployment"
|
||||
allDaemonSetConst = "allDaemonSet"
|
||||
allStatefulSetConst = "allStatefulSet"
|
||||
controllerVersionConst = "controllerVersion"
|
||||
hpaListConst = "hpaList"
|
||||
replicaSetConst = "replicaSet"
|
||||
|
||||
pvcConst = "pvc"
|
||||
pvConst = "pv"
|
||||
podMetrics = "podMetrics"
|
||||
nodeMetrics = "nodeMetrics"
|
||||
crdConst = "crd"
|
||||
|
||||
pvUrl = "/api/v1/persistentvolumes"
|
||||
pvcUrl = "/api/v1/namespaces/%s/persistentvolumeclaims"
|
||||
nodeUrl = "/api/v1/nodes"
|
||||
deploymentUrl = "/apis/apps/v1/namespaces/%s/deployments"
|
||||
podListUrl = "/api/v1/namespaces/%s/pods"
|
||||
podDetailUrl = "/api/v1/namespaces/%s/pods/%s"
|
||||
podMetricsUrl = "/apis/metrics.k8s.io/v1beta1/namespaces/%s/pods/%s"
|
||||
nodeMetricsUrl = "/apis/metrics.k8s.io/v1beta1/nodes"
|
||||
crdUrl = "/apis/apiextensions.k8s.io/v1/customresourcedefinitions"
|
||||
hpaListUrl = "/apis/autoscaling/v1/namespaces/%s/horizontalpodautoscalers"
|
||||
detailHpaUrl = "/apis/autoscaling/v1/namespaces/%s/horizontalpodautoscalers/%s"
|
||||
deploymentListUrl = "/apis/apps/v1/namespaces/%s/deployments"
|
||||
daemonSetUrl = "/apis/apps/v1/namespaces/%s/daemonsets/%s"
|
||||
statefulSetUrl = "/apis/apps/v1/namespaces/%s/statefulsets/%s"
|
||||
statefulSetListUrl = "/apis/apps/v1/namespaces/%s/statefulsets"
|
||||
daemonSetListUrl = "/apis/apps/v1/namespaces/%s/daemonsets"
|
||||
replicaSetUrl = "/apis/apps/v1/namespaces/%s/replicasets"
|
||||
secretUrl = "/api/v1/namespaces/%s/secrets"
|
||||
configMapUrl = "/api/v1/namespaces/%s/configmaps"
|
||||
scUrl = "/apis/storage.k8s.io/v1/storageclasses"
|
||||
pvUrl = "/api/v1/persistentvolumes"
|
||||
pvcUrl = "/api/v1/persistentvolumeclaims"
|
||||
detailPvcUrl = "/api/v1/namespaces/%s/persistentvolumeclaims/%s"
|
||||
nodeUrl = "/api/v1/nodes"
|
||||
detailNodeUrl = "/api/v1/nodes/%s"
|
||||
namespaceUrl = "/api/v1/namespaces"
|
||||
deploymentUrl = "/apis/apps/v1/namespaces/%s/deployments/%s"
|
||||
allDeploymentUrl = "/apis/apps/v1/deployments"
|
||||
allStatefulSetUrl = "/apis/apps/v1/statefulsets"
|
||||
allDaemonSetUrl = "/apis/apps/v1/daemonsets"
|
||||
podListUrl = "/api/v1/namespaces/%s/pods"
|
||||
allPodUrl = "/api/v1/pods"
|
||||
detailPodUrl = "/api/v1/namespaces/%s/pods/%s"
|
||||
podDetailUrl = "/api/v1/namespaces/%s/pods/%s"
|
||||
serviceUrl = "/api/v1/namespaces/%s/services"
|
||||
allServiceUrl = "/api/v1/services"
|
||||
detailServiceUrl = "/api/v1/namespaces/%s/services/%s"
|
||||
podMetricsUrl = "/apis/metrics.k8s.io/v1beta1/namespaces/%s/pods/%s"
|
||||
nodeMetricsUrl = "/apis/metrics.k8s.io/v1beta1/nodes"
|
||||
crdUrl = "/apis/apiextensions.k8s.io/v1/customresourcedefinitions"
|
||||
detailNamespaceUrl = "/api/v1/namespaces/%s"
|
||||
jobListUrl = "/apis/batch/v1/namespaces/%s/jobs"
|
||||
pvcListUrl = "/api/v1/namespaces/%s/persistentvolumeclaims"
|
||||
controllerVersionUrl = "/apis/apps/v1/namespaces/%s/controllerrevisions"
|
||||
)
|
||||
|
||||
func JointUrl(objectType string, clusterName string, namespace string, objectName string) string {
|
||||
|
@ -46,7 +99,13 @@ func JointUrl(objectType string, clusterName string, namespace string, objectNam
|
|||
case "node":
|
||||
url.WriteString(nodeUrl)
|
||||
case "deployment":
|
||||
url.WriteString(fmt.Sprintf(deploymentUrl, namespace))
|
||||
url.WriteString(fmt.Sprintf(deploymentUrl, namespace, objectName))
|
||||
case "allStatefulSet":
|
||||
url.WriteString(allStatefulSetUrl)
|
||||
case "allDaemonSet":
|
||||
url.WriteString(allDaemonSetUrl)
|
||||
case "allDeployment":
|
||||
url.WriteString(allDeploymentUrl)
|
||||
case "podList":
|
||||
url.WriteString(fmt.Sprintf(podListUrl, namespace))
|
||||
case "podDetail":
|
||||
|
@ -54,10 +113,57 @@ func JointUrl(objectType string, clusterName string, namespace string, objectNam
|
|||
case "pv":
|
||||
url.WriteString(pvUrl)
|
||||
case "pvc":
|
||||
url.WriteString(fmt.Sprintf(pvcUrl, namespace))
|
||||
url.WriteString(pvcUrl)
|
||||
case "crd":
|
||||
url.WriteString(crdUrl)
|
||||
case "namespace":
|
||||
url.WriteString(namespaceUrl)
|
||||
case "sc":
|
||||
url.WriteString(scUrl)
|
||||
case "service":
|
||||
url.WriteString(fmt.Sprintf(serviceUrl, namespace))
|
||||
case "allService":
|
||||
url.WriteString(allServiceUrl)
|
||||
case "detailService":
|
||||
url.WriteString(fmt.Sprintf(detailServiceUrl, namespace, objectName))
|
||||
case "secret":
|
||||
url.WriteString(fmt.Sprintf(secretUrl, namespace))
|
||||
case "replicaSet":
|
||||
url.WriteString(fmt.Sprintf(replicaSetUrl, namespace))
|
||||
case "statefulSet":
|
||||
url.WriteString(fmt.Sprintf(statefulSetUrl, namespace, objectName))
|
||||
case "daemonSet":
|
||||
url.WriteString(fmt.Sprintf(daemonSetUrl, namespace, objectName))
|
||||
case "detailPvc":
|
||||
url.WriteString(fmt.Sprintf(detailPvcUrl, namespace, objectName))
|
||||
case "configMap":
|
||||
url.WriteString(fmt.Sprintf(configMapUrl, namespace))
|
||||
case "allPod":
|
||||
url.WriteString(fmt.Sprintf(allPodUrl))
|
||||
case "detailPod":
|
||||
url.WriteString(fmt.Sprintf(detailPodUrl, namespace, objectName))
|
||||
case "detailNode":
|
||||
url.WriteString(fmt.Sprintf(detailNodeUrl, objectName))
|
||||
case "detailNamespace":
|
||||
url.WriteString(fmt.Sprintf(detailNamespaceUrl, objectName))
|
||||
case "deploymentList":
|
||||
url.WriteString(fmt.Sprintf(deploymentListUrl, namespace))
|
||||
case "statefulSetList":
|
||||
url.WriteString(fmt.Sprintf(statefulSetListUrl, namespace))
|
||||
case "daemonSetList":
|
||||
url.WriteString(fmt.Sprintf(daemonSetListUrl, namespace))
|
||||
case "jobList":
|
||||
url.WriteString(fmt.Sprintf(jobListUrl, namespace))
|
||||
case "pvcList":
|
||||
url.WriteString(fmt.Sprintf(pvcListUrl, namespace))
|
||||
case "controllerVersion":
|
||||
url.WriteString(fmt.Sprintf(controllerVersionUrl, namespace))
|
||||
case "hpa":
|
||||
url.WriteString(fmt.Sprintf(detailHpaUrl, namespace, objectName))
|
||||
case "hpaList":
|
||||
url.WriteString(fmt.Sprintf(hpaListUrl, namespace))
|
||||
}
|
||||
|
||||
return url.String()
|
||||
}
|
||||
|
||||
|
@ -66,16 +172,28 @@ func SearchObject(objectType string, clusterName string, namespace string, objec
|
|||
return KarmadaClient.SearchV1alpha1().RESTClient().Get().AbsPath(url).Do(context.TODO())
|
||||
}
|
||||
|
||||
func CreateObject(objectType string, clusterName string, namespace string, object interface{}) rest.Result {
|
||||
url := JointUrl(objectType, clusterName, namespace, "")
|
||||
return KarmadaClient.SearchV1alpha1().RESTClient().Post().Body(object).AbsPath(url).Do(context.TODO())
|
||||
func UpdateObject(objectType string, clusterName string, namespace string, objectName string, object interface{}) rest.Result {
|
||||
url := JointUrl(objectType, clusterName, namespace, objectName)
|
||||
objectParam, _ := json.Marshal(object)
|
||||
return KarmadaClient.SearchV1alpha1().RESTClient().Put().Body(objectParam).AbsPath(url).Do(context.TODO())
|
||||
}
|
||||
|
||||
func DeleteObject(objectType string, clusterName string, namespace string) rest.Result {
|
||||
url := JointUrl(objectType, clusterName, namespace, "")
|
||||
func PostObject(objectType string, clusterName string, namespace string, objectName string, object interface{}) rest.Result {
|
||||
url := JointUrl(objectType, clusterName, namespace, objectName)
|
||||
objectParam, _ := json.Marshal(object)
|
||||
return KarmadaClient.SearchV1alpha1().RESTClient().Post().Body(objectParam).AbsPath(url).Do(context.TODO())
|
||||
}
|
||||
|
||||
func DeleteObject(objectType string, clusterName string, namespace string, objectName string) rest.Result {
|
||||
url := JointUrl(objectType, clusterName, namespace, objectName)
|
||||
return KarmadaClient.SearchV1alpha1().RESTClient().Delete().AbsPath(url).Do(context.TODO())
|
||||
}
|
||||
|
||||
func PatchObject(objectType string, clusterName string, namespace string, objectName string, object interface{}, pt types.PatchType) rest.Result {
|
||||
url := JointUrl(objectType, clusterName, namespace, objectName)
|
||||
return KarmadaClient.SearchV1alpha1().RESTClient().Patch(pt).Body(object).AbsPath(url).Do(context.TODO())
|
||||
}
|
||||
|
||||
func GetDeployFromOS(namespaceName string, deploymentName string, clusterName string) *simplejson.Json {
|
||||
|
||||
var content *strings.Reader
|
||||
|
|
246
app/overview.go
246
app/overview.go
|
@ -6,6 +6,43 @@ import (
|
|||
"github.com/golang/glog"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"net/http"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
apiserver_request_rate = "apiserver:apiserver_request_total:sum_irate{cluster_name='clusterName', prometheus_replica='prometheus-k8s-0'}"
|
||||
apiserver_request_latencies = "apiserver:apiserver_request_duration:avg{cluster_name='clusterName', prometheus_replica='prometheus-k8s-0'}"
|
||||
|
||||
Schedule = "Schedule"
|
||||
scheduler_schedule_attempts = "scheduler:scheduler_schedule_attempts:sum{cluster_name='clusterName', result='Schedule', prometheus_replica='prometheus-k8s-0'}"
|
||||
|
||||
cluster_pod_running_count = "cluster:pod_running:count{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'}"
|
||||
cluster_memory_total = "sum by (cluster) (node:node_memory_bytes_total:sum{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'})"
|
||||
cluster_cpu_total = "sum by (cluster) (node:node_num_cpu:sum{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'})"
|
||||
cluster_disk_size_capacity = "sum by (cluster) (node:disk_space_available:{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'} / (1 - node:disk_space_utilization:ratio{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'}))"
|
||||
cluster_cpu_usage = "sum by (cluster) (node:node_num_cpu:sum{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'} * node:node_cpu_utilisation:avg1m{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'})"
|
||||
cluster_pod_quota = "sum by (cluster) (node:pod_capacity:sum{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'})"
|
||||
cluster_memory_usage_wo_cache = "sum by (cluster) (node:node_memory_bytes_total:sum{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'} - node:node_memory_bytes_available:sum{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'})"
|
||||
cluster_disk_size_usage = "(sum by (cluster) (node:disk_space_available:{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'}) / (1 - cluster:disk_utilization:ratio{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'})) * cluster:disk_utilization:ratio{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'}"
|
||||
|
||||
node_cpu_total = "node:node_num_cpu:sum{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'}"
|
||||
node_cpu_usage = "node:node_num_cpu:sum{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'} * node:node_cpu_utilisation:avg1m{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'}"
|
||||
node_cpu_utilisation = "node:node_cpu_utilisation:avg1m{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'}"
|
||||
node_load1 = "node:load1:ratio{cluster_name='clusterName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_load15 = "node:load15:ratio{cluster_name='clusterName', prometheus_replica='prometheus-k8s-0'}"
|
||||
node_memory_total = "node:node_memory_bytes_total:sum{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'}"
|
||||
node_memory_usage_wo_cache = "node:node_memory_bytes_total:sum{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'} - node:node_memory_bytes_available:sum{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'}"
|
||||
node_memory_utilisation = "node:node_memory_utilisation:{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'}"
|
||||
node_pod_quota = "node:pod_capacity:sum{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'}"
|
||||
node_pod_running_count = "node:pod_running:count{cluster_name='clusterName', prometheus_replica='prometheus-k8s-0'}"
|
||||
|
||||
nvidia_smi_utilization_gpu_ratio = "nvidia_smi_utilization_gpu_ratio{cluster_name='clusterName'}"
|
||||
nvidia_smi_utilization_memory_ratio = "nvidia_smi_utilization_memory_ratio{cluster_name='clusterName'}"
|
||||
|
||||
ClusterName = "clusterName"
|
||||
metric_range_1s = "1s"
|
||||
steps_1s = 100
|
||||
buffer = 5
|
||||
)
|
||||
|
||||
type Overview struct {
|
||||
|
@ -14,6 +51,215 @@ type Overview struct {
|
|||
Pod int32 `json:"podListConst"`
|
||||
}
|
||||
|
||||
// @Summary 获取容器集群调度器监控
|
||||
// @Description 获取容器集群调度器监控
|
||||
// @Tags overview
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Param clusterName query string true "集群名称"
|
||||
// @Success 200
|
||||
// @Failure 400
|
||||
// @Router /api/v1/overview/getScheduleMetrics [get]
|
||||
func GetScheduleMetrics(c *gin.Context) {
|
||||
clusterName := c.Query(ClusterName)
|
||||
|
||||
scheduleSlice := []string{"error", "scheduled", "unschedulable"}
|
||||
var metricUrls []MetricUrl
|
||||
for _, s := range scheduleSlice {
|
||||
imap := map[string]string{
|
||||
ClusterName: clusterName,
|
||||
Schedule: s,
|
||||
}
|
||||
metricUrls = append(metricUrls, MetricUrl{Schedule, s, GetMetricUrl(scheduler_schedule_attempts, imap, Schedule, metric_range_1s, steps_1s)})
|
||||
}
|
||||
|
||||
metricMap := map[string][]MetricUrl{
|
||||
"scheduler_schedule_attempts": metricUrls,
|
||||
}
|
||||
|
||||
ch := make(chan MetricResult, len(metricMap))
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for k, v := range metricMap {
|
||||
wg.Add(1)
|
||||
go HttpGetMetrics(k, v, &wg, ch)
|
||||
}
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
|
||||
mr := []MetricResult{}
|
||||
for v := range ch {
|
||||
mr = append(mr, v)
|
||||
}
|
||||
|
||||
Response(c, http.StatusOK, "success", mr)
|
||||
}
|
||||
|
||||
// @Summary 获取容器集群资源监控
|
||||
// @Description 获取容器集群资源监控
|
||||
// @Tags overview
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Param clusterName query string true "集群名称"
|
||||
// @Success 200
|
||||
// @Failure 400
|
||||
// @Router /api/v1/overview/getClusterMetrics [get]
|
||||
func GetClusterMetrics(c *gin.Context) {
|
||||
clusterName := c.Query(ClusterName)
|
||||
|
||||
replaceMap := make(map[string]string)
|
||||
replaceMap[ClusterName] = clusterName
|
||||
|
||||
metricMap := map[string][]MetricUrl{
|
||||
"cluster_pod_running_count": {{ClusterName, clusterName, GetMetricUrl(cluster_pod_running_count, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"cluster_memory_total": {{ClusterName, clusterName, GetMetricUrl(cluster_memory_total, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"cluster_cpu_total": {{ClusterName, clusterName, GetMetricUrl(cluster_cpu_total, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"cluster_disk_size_capacity": {{ClusterName, clusterName, GetMetricUrl(cluster_disk_size_capacity, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"cluster_cpu_usage": {{ClusterName, clusterName, GetMetricUrl(cluster_cpu_usage, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"cluster_pod_quota": {{ClusterName, clusterName, GetMetricUrl(cluster_pod_quota, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"cluster_memory_usage_wo_cache": {{ClusterName, clusterName, GetMetricUrl(cluster_memory_usage_wo_cache, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"cluster_disk_size_usage": {{ClusterName, clusterName, GetMetricUrl(cluster_disk_size_usage, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
}
|
||||
|
||||
mr := []MetricResult{}
|
||||
ch := make(chan MetricResult, len(metricMap))
|
||||
limit := make(chan bool, buffer)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for k, v := range metricMap {
|
||||
limit <- true
|
||||
wg.Add(1)
|
||||
go HttpGetMetrics(k, v, &wg, ch)
|
||||
<-limit
|
||||
}
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
|
||||
for v := range ch {
|
||||
mr = append(mr, v)
|
||||
}
|
||||
|
||||
Response(c, http.StatusOK, "success", mr)
|
||||
|
||||
}
|
||||
|
||||
// @Summary 获取容器节点资源监控
|
||||
// @Description 获取容器节点资源监控
|
||||
// @Tags overview
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Param clusterName query string true "集群名称"
|
||||
// @Success 200
|
||||
// @Failure 400
|
||||
// @Router /api/v1/overview/getNodeMetrics [get]
|
||||
func GetNodeMetrics(c *gin.Context) {
|
||||
clusterName := c.Query(ClusterName)
|
||||
|
||||
//client, err := clientSet.GetClientSet(clusterName)
|
||||
//if err != nil {
|
||||
// log.Fatalln(err)
|
||||
//}
|
||||
//nodeList, err := client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
|
||||
//if err != nil {
|
||||
// log.Fatalln(err)
|
||||
//}
|
||||
//
|
||||
//nodes := []string{}
|
||||
//for i := range nodeList.Items {
|
||||
// nodes = append(nodes, nodeList.Items[i].Name)
|
||||
//}
|
||||
replaceMap := make(map[string]string)
|
||||
replaceMap[ClusterName] = clusterName
|
||||
|
||||
mr := []MetricResult{}
|
||||
//node_rs := []map[string]interface{}{}
|
||||
//rd := ResultData {
|
||||
// Status: "success",
|
||||
// Data: MetricData{
|
||||
// Result: node_rs,
|
||||
// ResultType: "",
|
||||
// },
|
||||
//}
|
||||
//nodes_mr := MetricResult{
|
||||
// MetricName: "node",
|
||||
// ResultData: rd,
|
||||
//}
|
||||
//mr = append(mr, nodes_mr)
|
||||
|
||||
metricMap := map[string][]MetricUrl{
|
||||
"node_cpu_total": {{ClusterName, clusterName, GetMetricUrl(node_cpu_total, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"node_cpu_usage": {{ClusterName, clusterName, GetMetricUrl(node_cpu_usage, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"node_cpu_utilisation": {{ClusterName, clusterName, GetMetricUrl(node_cpu_utilisation, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"node_load1": {{ClusterName, clusterName, GetMetricUrl(node_load1, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"node_load15": {{ClusterName, clusterName, GetMetricUrl(node_load15, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"node_memory_total": {{ClusterName, clusterName, GetMetricUrl(node_memory_total, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"node_memory_usage_wo_cache": {{ClusterName, clusterName, GetMetricUrl(node_memory_usage_wo_cache, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"node_memory_utilisation": {{ClusterName, clusterName, GetMetricUrl(node_memory_utilisation, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"node_pod_quota": {{ClusterName, clusterName, GetMetricUrl(node_pod_quota, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"node_pod_running_count": {{ClusterName, clusterName, GetMetricUrl(node_pod_running_count, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"nvidia_smi_utilization_gpu_ratio": {{ClusterName, clusterName, GetMetricUrl(nvidia_smi_utilization_gpu_ratio, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"nvidia_smi_utilization_memory_ratio": {{ClusterName, clusterName, GetMetricUrl(nvidia_smi_utilization_memory_ratio, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
}
|
||||
|
||||
ch := make(chan MetricResult, len(metricMap))
|
||||
limit := make(chan bool, buffer)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for k, v := range metricMap {
|
||||
limit <- true
|
||||
wg.Add(1)
|
||||
go HttpGetMetrics(k, v, &wg, ch)
|
||||
<-limit
|
||||
}
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
|
||||
for v := range ch {
|
||||
mr = append(mr, v)
|
||||
}
|
||||
|
||||
Response(c, http.StatusOK, "success", mr)
|
||||
|
||||
}
|
||||
|
||||
// @Summary 获取ApiServer请求数和请求延迟
|
||||
// @Description 获取ApiServer请求数和请求延迟
|
||||
// @Tags overview
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Param clusterName query string true "集群名称"
|
||||
// @Success 200
|
||||
// @Failure 400
|
||||
// @Router /api/v1/overview/getApiServerMetrics [get]
|
||||
func GetApiServerMetrics(c *gin.Context) {
|
||||
clusterName := c.Query(ClusterName)
|
||||
|
||||
replaceMap := make(map[string]string)
|
||||
replaceMap[ClusterName] = clusterName
|
||||
|
||||
metricMap := map[string][]MetricUrl{
|
||||
"apiserver_request_rate": {{ClusterName, clusterName, GetMetricUrl(apiserver_request_rate, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
"apiserver_request_latencies": {{ClusterName, clusterName, GetMetricUrl(apiserver_request_latencies, replaceMap, ClusterName, metric_range_1s, steps_1s)}},
|
||||
}
|
||||
|
||||
ch := make(chan MetricResult, len(metricMap))
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for k, v := range metricMap {
|
||||
wg.Add(1)
|
||||
go HttpGetMetrics(k, v, &wg, ch)
|
||||
}
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
|
||||
mr := []MetricResult{}
|
||||
for v := range ch {
|
||||
mr = append(mr, v)
|
||||
}
|
||||
|
||||
Response(c, http.StatusOK, "success", mr)
|
||||
}
|
||||
|
||||
func ResourceCount(c *gin.Context) {
|
||||
overview := &Overview{}
|
||||
//纳管资源域、纳管集群总计、容器创建数量 资源域
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package app
|
||||
|
||||
import "strconv"
|
||||
|
||||
type Page[T any] struct {
|
||||
// 当前页码
|
||||
PageNum int64 `json:"pageNum"`
|
||||
|
@ -14,7 +16,9 @@ type Page[T any] struct {
|
|||
}
|
||||
|
||||
// Paginator 生成新的分页数据对象
|
||||
func Paginator[T any](items *Page[T], total, pageNum, pageSize int64) *Page[T] {
|
||||
func Paginator[T any](items *Page[T], total int64, pageNumParam, pageSizeParam string) *Page[T] {
|
||||
pageNum, _ := strconv.ParseInt(pageNumParam, 10, 64)
|
||||
pageSize, _ := strconv.ParseInt(pageSizeParam, 10, 64)
|
||||
var (
|
||||
pageStart int64
|
||||
pageEnd int64
|
||||
|
|
306
app/pod.go
306
app/pod.go
|
@ -5,6 +5,7 @@ import (
|
|||
"encoding/json"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/shopspring/decimal"
|
||||
v12 "k8s.io/api/apps/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/metrics/pkg/apis/metrics"
|
||||
|
@ -12,11 +13,22 @@ import (
|
|||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
pod_cpu_usage = "irate(container_cpu_usage_seconds_total{cluster_name='clusterName', pod='podName', container='', prometheus_replica='prometheus-k8s-0'}[10m])"
|
||||
pod_memery_usage_wo_cache = "container_memory_working_set_bytes{cluster_name='clusterName', pod='podName', container='', prometheus_replica='prometheus-k8s-0'}"
|
||||
pod_net_bytes_transmitted = "irate(container_network_transmit_bytes_total{cluster_name='clusterName', pod='podName', interface='eth0', prometheus_replica='prometheus-k8s-0'}[10m])"
|
||||
pod_net_bytes_received = "irate(container_network_receive_bytes_total{cluster_name='clusterName', pod='podName', interface='eth0',prometheus_replica='prometheus-k8s-0'}[10m])"
|
||||
PodName = "podName"
|
||||
pod_metric_range = "8.333h"
|
||||
steps_pod = 600
|
||||
)
|
||||
|
||||
type Pod struct {
|
||||
PageNum int64 `json:"page_num"`
|
||||
PageSize int64 `json:"page_size"`
|
||||
PageNum string `json:"page_num"`
|
||||
PageSize string `json:"page_size"`
|
||||
Name string `json:"name"`
|
||||
ClusterName string `json:"cluster_name"`
|
||||
DomainName string `json:"domain_name"`
|
||||
|
@ -34,7 +46,7 @@ type Pod struct {
|
|||
TemplateId string `json:"template_id"`
|
||||
}
|
||||
|
||||
type PodRes struct {
|
||||
type PodObject struct {
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Metadata string `json:"metadata"`
|
||||
|
@ -42,13 +54,27 @@ type PodRes struct {
|
|||
Items []v1.Pod `json:"items"`
|
||||
}
|
||||
|
||||
//type MetricsRes struct {
|
||||
// Kind string `json:"kind"`
|
||||
// ApiVersion string `json:"apiVersion"`
|
||||
// Metadata string `json:"metadata"`
|
||||
// ResourceVersion string `json:"resourceVersion"`
|
||||
// Items []metrics.PodMetrics `json:"items"`
|
||||
//}
|
||||
type DeploymentPods struct {
|
||||
Replicas int32 `json:"replicas"`
|
||||
AvailableReplicas int32 `json:"availableReplicas"`
|
||||
Pods []v1.Pod `json:"pods"`
|
||||
}
|
||||
|
||||
type ReplicaSetRes struct {
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Metadata string `json:"metadata"`
|
||||
ResourceVersion string `json:"resourceVersion"`
|
||||
Items []v12.ReplicaSet `json:"items"`
|
||||
}
|
||||
|
||||
type StatefulSetRes struct {
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Metadata string `json:"metadata"`
|
||||
ResourceVersion string `json:"resourceVersion"`
|
||||
Items []v12.StatefulSet `json:"items"`
|
||||
}
|
||||
|
||||
// PodMetrics 根据集群名称、命名空间和pod名称查询pod使用率
|
||||
// @Summary 根据集群名称、命名空间和pod名称查询pod使用率
|
||||
|
@ -63,9 +89,9 @@ type PodRes struct {
|
|||
// @Failure 500
|
||||
// @Router /api/v1/pod/metrics/{clusterName}/{namespace}/{name} [get]
|
||||
func PodMetrics(c *gin.Context) {
|
||||
clusterName := c.Param("clusterName")
|
||||
namespace := c.Param("namespace")
|
||||
name := c.Param("name")
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
result := SearchObject(podMetrics, clusterName, namespace, name)
|
||||
var metrics metrics.PodMetrics
|
||||
raw, _ := result.Raw()
|
||||
|
@ -94,12 +120,13 @@ func PodMetrics(c *gin.Context) {
|
|||
// @Success 200
|
||||
// @Failure 500
|
||||
// @Router /api/v1/pod/detail/{clusterName}/{namespace}/{name} [get]
|
||||
// PodDetail 根据指定集群查询Pod详情
|
||||
func PodDetail(c *gin.Context) {
|
||||
clusterName := c.Param("clusterName")
|
||||
namespace := c.Param("namespace")
|
||||
name := c.Param("name")
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
result := SearchObject(podListConst, clusterName, namespace, "")
|
||||
var podRes PodRes
|
||||
var podRes PodObject
|
||||
raw, _ := result.Raw()
|
||||
json.Unmarshal(raw, &podRes)
|
||||
for _, pod := range podRes.Items {
|
||||
|
@ -111,28 +138,46 @@ func PodDetail(c *gin.Context) {
|
|||
Response(c, http.StatusOK, "success", nil)
|
||||
}
|
||||
|
||||
// IsExist 判断名称是否重复
|
||||
func IsExist(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
result := SearchObject(podDetailConst, clusterName, namespace, name)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusOK, "success", false)
|
||||
return
|
||||
}
|
||||
var pod v1.Pod
|
||||
raw, _ := result.Raw()
|
||||
json.Unmarshal(raw, &pod)
|
||||
if len(pod.Name) == 0 {
|
||||
Response(c, http.StatusOK, "success", false)
|
||||
return
|
||||
}
|
||||
Response(c, http.StatusOK, "success", true)
|
||||
}
|
||||
|
||||
// ListPod 根据指定集群查询Pod列表
|
||||
// @Summary 根据指定集群查询Pod列表
|
||||
// @Description 根据指定集群查询Pod列表
|
||||
// @Tags pod
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Param param body Pod true "json"
|
||||
// @Success 200
|
||||
// @Failure 500
|
||||
// @Router /api/v1/pod/list [get]
|
||||
func ListPod(c *gin.Context) {
|
||||
var param Pod
|
||||
if err := c.BindJSON(¶m); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
result := SearchObject(podListConst, param.ClusterName, param.Namespace, "")
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
pageNum := c.Query("pageNum")
|
||||
pageSize := c.Query("pageSize")
|
||||
result := SearchObject(podListConst, clusterName, namespace, "")
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", result.Error())
|
||||
return
|
||||
}
|
||||
var podRes PodRes
|
||||
var podRes PodObject
|
||||
raw, _ := result.Raw()
|
||||
json.Unmarshal(raw, &podRes)
|
||||
|
||||
|
@ -143,7 +188,43 @@ func ListPod(c *gin.Context) {
|
|||
return podRes.Items[i].CreationTimestamp.Time.After(podRes.Items[j].CreationTimestamp.Time)
|
||||
})
|
||||
page.List = podRes.Items
|
||||
data := Paginator(page, int64(len(podRes.Items)), param.PageNum, param.PageSize)
|
||||
data := Paginator(page, int64(len(podRes.Items)), pageNum, pageSize)
|
||||
Response(c, http.StatusOK, "success", data)
|
||||
}
|
||||
|
||||
// ListPod 根据指定集群查询Pod列表
|
||||
// @Summary 根据指定集群查询Pod列表
|
||||
// @Description 根据指定集群查询Pod列表
|
||||
// @Param clusterName query string true "集群名称"
|
||||
// @Param pageNum query int true "pageNum"
|
||||
// @Param pageSize query int true "pageSize"
|
||||
// @Tags pod
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Success 200
|
||||
// @Failure 500
|
||||
// @Router /api/v1/pod/all [get]
|
||||
func ALLPod(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
pageNum := c.Query("pageNum")
|
||||
pageSize := c.Query("pageSize")
|
||||
result := SearchObject(allPodConst, clusterName, "", "")
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", result.Error())
|
||||
return
|
||||
}
|
||||
var podRes PodObject
|
||||
raw, _ := result.Raw()
|
||||
json.Unmarshal(raw, &podRes)
|
||||
|
||||
// 分页
|
||||
page := &Page[v1.Pod]{}
|
||||
// 排序
|
||||
sort.SliceStable(podRes.Items, func(i, j int) bool {
|
||||
return podRes.Items[i].CreationTimestamp.Time.After(podRes.Items[j].CreationTimestamp.Time)
|
||||
})
|
||||
page.List = podRes.Items
|
||||
data := Paginator(page, int64(len(podRes.Items)), pageNum, pageSize)
|
||||
Response(c, http.StatusOK, "success", data)
|
||||
}
|
||||
|
||||
|
@ -205,20 +286,30 @@ func CreatePod(c *gin.Context) {
|
|||
// @accept json
|
||||
// @Produce json
|
||||
// @Param namespace path string true "命名空间名"
|
||||
//@param name path string true "Pod名"
|
||||
// @param name path string true "Pod名"
|
||||
// @Success 200
|
||||
// @Failure 400
|
||||
// @Router /api/v1/pod/delete/{namespace}/{name} [delete]
|
||||
func DeletePod(c *gin.Context) {
|
||||
clusterName := c.Param("clusterName")
|
||||
namespace := c.Param("namespace")
|
||||
name := c.Param("name")
|
||||
err := ClientSet.CoreV1().Pods(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete podListConst failed", err)
|
||||
return
|
||||
label := c.Param("label")
|
||||
if strings.EqualFold(label, "jcce") {
|
||||
err := ClientSet.CoreV1().Pods(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete pod failed", err)
|
||||
return
|
||||
}
|
||||
// 删除调度策略
|
||||
DeletePropagationPolicies(namespace, "Pod"+namespace+name)
|
||||
} else {
|
||||
result := DeleteObject(detailPodConst, clusterName, namespace, name)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete pod failed", result.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
// 删除调度策略
|
||||
DeletePropagationPolicies(namespace, "pod"+namespace+name)
|
||||
Response(c, http.StatusOK, "success", nil)
|
||||
}
|
||||
|
||||
|
@ -258,6 +349,90 @@ func UpdatePod(c *gin.Context) {
|
|||
Response(c, http.StatusOK, "success", podResult)
|
||||
}
|
||||
|
||||
// ListPodFromNode 获取节点下的pod
|
||||
func ListPodFromNode(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
nodeName := c.Query("nodeName")
|
||||
podResult := SearchObject(allPodConst, clusterName, "", "")
|
||||
if podResult.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", podResult.Error())
|
||||
return
|
||||
}
|
||||
var podRes PodObject
|
||||
raw, _ := podResult.Raw()
|
||||
json.Unmarshal(raw, &podRes)
|
||||
var result []v1.Pod
|
||||
for i := range podRes.Items {
|
||||
if strings.EqualFold(podRes.Items[i].Spec.NodeName, nodeName) {
|
||||
result = append(result, podRes.Items[i])
|
||||
}
|
||||
}
|
||||
Response(c, http.StatusOK, "success", result)
|
||||
}
|
||||
|
||||
func GetPodForDeployment(clusterName string, namespace string, labelMap map[string]string) []v1.Pod {
|
||||
|
||||
// 查询pod当前命名空间下的列表
|
||||
podResult := SearchObject(podListConst, clusterName, namespace, "")
|
||||
var podObject PodObject
|
||||
podRaw, _ := podResult.Raw()
|
||||
json.Unmarshal(podRaw, &podObject)
|
||||
// 查询label匹配的pod
|
||||
var podsResult []v1.Pod
|
||||
for _, pod := range podObject.Items {
|
||||
for k, v := range labelMap {
|
||||
if pod.Labels[k] != v {
|
||||
goto loop
|
||||
}
|
||||
}
|
||||
podsResult = append(podsResult, pod)
|
||||
loop:
|
||||
}
|
||||
return podsResult
|
||||
}
|
||||
|
||||
// ListPodFromDeployment 获取deployment下的pod
|
||||
func ListPodFromDeployment(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
label := c.Query("label")
|
||||
var labelMap = make(map[string]string)
|
||||
labelArray := strings.Split(label, ",")
|
||||
for _, label := range labelArray {
|
||||
labelKV := strings.Split(label, "=")
|
||||
labelMap[labelKV[0]] = labelKV[1]
|
||||
}
|
||||
|
||||
podList := GetPodForDeployment(clusterName, namespace, labelMap)
|
||||
|
||||
var replicas, availableReplicas int32
|
||||
// 查询replicaSet
|
||||
var replicaSetObject ReplicaSetObject
|
||||
searchResult := SearchObject(replicaSetConst, clusterName, namespace, "")
|
||||
raw, _ := searchResult.Raw()
|
||||
json.Unmarshal(raw, &replicaSetObject)
|
||||
for _, replicaSet := range replicaSetObject.Items {
|
||||
for k, v := range labelMap {
|
||||
if replicaSet.Labels[k] != v {
|
||||
goto loop1
|
||||
}
|
||||
}
|
||||
if replicaSet.Status.Replicas != 0 {
|
||||
replicas = replicas + 1
|
||||
if replicaSet.Status.AvailableReplicas != 0 {
|
||||
availableReplicas = availableReplicas + 1
|
||||
}
|
||||
}
|
||||
loop1:
|
||||
}
|
||||
|
||||
Response(c, http.StatusOK, "success", DeploymentPods{
|
||||
Pods: podList,
|
||||
Replicas: replicas,
|
||||
AvailableReplicas: availableReplicas,
|
||||
})
|
||||
}
|
||||
|
||||
// GetPodDetail 获取容器组详情
|
||||
// @Summary 获取容器组详情
|
||||
// @Description 获取容器组详情
|
||||
|
@ -269,21 +444,60 @@ func UpdatePod(c *gin.Context) {
|
|||
// @Failure 400
|
||||
// @Router /api/v1/pod/detail [put]
|
||||
func GetPodDetail(c *gin.Context) {
|
||||
var param Pod
|
||||
if err := c.BindJSON(¶m); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
podResult, err := ClientSet.CoreV1().Pods(param.Namespace).Get(context.TODO(), param.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "query podListConst failed", err)
|
||||
return
|
||||
}
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
rsRes := SearchObject(detailPodConst, clusterName, namespace, name)
|
||||
raw, _ := rsRes.Raw()
|
||||
var pod v1.Pod
|
||||
json.Unmarshal(raw, &pod)
|
||||
|
||||
err_ := AddTypeMetaToObject(podResult)
|
||||
err_ := AddTypeMetaToObject(&pod)
|
||||
if err_ != nil {
|
||||
log.Println(err_)
|
||||
}
|
||||
|
||||
Response(c, http.StatusOK, "success", podResult)
|
||||
Response(c, http.StatusOK, "success", pod)
|
||||
}
|
||||
|
||||
// @Summary 获取容器组监控
|
||||
// @Description 获取容器组监控
|
||||
// @Tags pod
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Param clusterName query string true "集群名称"
|
||||
// @Param podName query string true "容器组名称"
|
||||
// @Success 200
|
||||
// @Failure 400
|
||||
// @Router /api/v1/pod/metrics [get]
|
||||
func GetMetrics(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
podName := c.Query("podName")
|
||||
|
||||
replaceMap := make(map[string]string)
|
||||
replaceMap[ClusterName] = clusterName
|
||||
replaceMap[PodName] = podName
|
||||
|
||||
metricMap := map[string][]MetricUrl{
|
||||
"pod_cpu_usage": {{PodName, podName, GetMetricUrl(pod_cpu_usage, replaceMap, PodName, pod_metric_range, steps_pod)}},
|
||||
"pod_memory_usage_wo_cache": {{PodName, podName, GetMetricUrl(pod_memery_usage_wo_cache, replaceMap, PodName, pod_metric_range, steps_pod)}},
|
||||
"pod_net_bytes_transmitted": {{PodName, podName, GetMetricUrl(pod_net_bytes_transmitted, replaceMap, PodName, pod_metric_range, steps_pod)}},
|
||||
"pod_net_bytes_received": {{PodName, podName, GetMetricUrl(pod_net_bytes_received, replaceMap, PodName, pod_metric_range, steps_pod)}},
|
||||
}
|
||||
|
||||
ch := make(chan MetricResult, len(metricMap))
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for k, v := range metricMap {
|
||||
wg.Add(1)
|
||||
go HttpGetMetrics(k, v, &wg, ch)
|
||||
}
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
|
||||
mr := []MetricResult{}
|
||||
for v := range ch {
|
||||
mr = append(mr, v)
|
||||
}
|
||||
|
||||
Response(c, http.StatusOK, "success", mr)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -119,9 +118,11 @@ func CreatePropagationPolicies(propagationPolicy PropagationPolicy) error {
|
|||
},
|
||||
}
|
||||
switch propagationPolicy.Kind {
|
||||
case "Pod", "Service", "PersistentVolumeClaim", "ConfigMap":
|
||||
case "HorizontalPodAutoscaler":
|
||||
policy.Spec.ResourceSelectors[0].APIVersion = "autoscaling/v1"
|
||||
case "Pod", "Service", "PersistentVolumeClaim", "ConfigMap", "Namespace":
|
||||
policy.Spec.ResourceSelectors[0].APIVersion = "v1"
|
||||
case "DeploymentParam":
|
||||
case "Deployment", "StatefulSet", "DaemonSet":
|
||||
policy.Spec.ResourceSelectors[0].APIVersion = "apps/v1"
|
||||
}
|
||||
_, err := KarmadaClient.PolicyV1alpha1().PropagationPolicies(propagationPolicy.Namespace).Create(context.TODO(), policy, v1.CreateOptions{})
|
||||
|
@ -153,9 +154,9 @@ func CreatePropagationPolicies(propagationPolicy PropagationPolicy) error {
|
|||
// @Router /api/v1/propagationPolicy/list [get]
|
||||
func ListPropagationPolicies(c *gin.Context) {
|
||||
|
||||
labelKey, _ := c.GetQuery("label_key")
|
||||
labelValue, _ := c.GetQuery("label_value")
|
||||
policyName, _ := c.GetQuery("policy_name")
|
||||
labelKey := c.Query("label_key")
|
||||
labelValue := c.Query("label_value")
|
||||
policyName := c.Query("policy_name")
|
||||
|
||||
opts := v1.ListOptions{
|
||||
TypeMeta: v1.TypeMeta{},
|
||||
|
@ -239,18 +240,21 @@ func ListPropagationPolicies(c *gin.Context) {
|
|||
total := len(proPolicyList)
|
||||
page := &Page[PropagationPolicy]{}
|
||||
page.List = proPolicyList
|
||||
pageNum, _ := c.GetQuery("pageNum")
|
||||
pageSize, _ := c.GetQuery("pageSize")
|
||||
num, _ := strconv.ParseInt(pageNum, 10, 64)
|
||||
size, _ := strconv.ParseInt(pageSize, 10, 64)
|
||||
data := Paginator(page, int64(total), num, size)
|
||||
pageNum := c.Query("pageNum")
|
||||
pageSize := c.Query("pageSize")
|
||||
data := Paginator(page, int64(total), pageNum, pageSize)
|
||||
Response(c, http.StatusOK, "success", data)
|
||||
|
||||
}
|
||||
|
||||
// UpdatePropagationPolicies 更新集群分发策略
|
||||
func UpdatePropagationPolicies(c *gin.Context) {
|
||||
|
||||
var propagationPolicy policyv1alpha1.PropagationPolicy
|
||||
_, err := KarmadaClient.PolicyV1alpha1().PropagationPolicies(propagationPolicy.Namespace).Update(context.TODO(), &propagationPolicy, v1.UpdateOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "update propagationPolicy failed", err)
|
||||
return
|
||||
}
|
||||
Response(c, http.StatusOK, "success", nil)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package app
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type PropagationPolicyTemplate struct {
|
||||
|
@ -79,7 +78,7 @@ func DeletePropagationPolicyTemplate(c *gin.Context) {
|
|||
// @Router /api/v1/propagationPolicyTemplate/list [get]
|
||||
func ListPropagationPolicyTemplate(c *gin.Context) {
|
||||
|
||||
pptName, _ := c.GetQuery("template_name")
|
||||
pptName := c.Query("template_name")
|
||||
|
||||
PptList := make([]PropagationPolicyTemplate, 0)
|
||||
rows, err := DB.Query(`SELECT * FROM propagation_policy_template ppt where ppt.template_name like ?`, "%"+pptName+"%")
|
||||
|
@ -102,11 +101,9 @@ func ListPropagationPolicyTemplate(c *gin.Context) {
|
|||
total := len(PptList)
|
||||
page := &Page[PropagationPolicyTemplate]{}
|
||||
page.List = PptList
|
||||
pageNum, _ := c.GetQuery("pageNum")
|
||||
pageSize, _ := c.GetQuery("pageSize")
|
||||
num, _ := strconv.ParseInt(pageNum, 10, 64)
|
||||
size, _ := strconv.ParseInt(pageSize, 10, 64)
|
||||
data := Paginator(page, int64(total), num, size)
|
||||
pageNum := c.Query("pageNum")
|
||||
pageSize := c.Query("pageSize")
|
||||
data := Paginator(page, int64(total), pageNum, pageSize)
|
||||
Response(c, http.StatusOK, "success", data)
|
||||
//Response(c, http.StatusOK, "success", PptList)
|
||||
|
||||
|
|
101
app/router.go
101
app/router.go
|
@ -12,6 +12,7 @@ import (
|
|||
swaggerFiles "github.com/swaggo/files"
|
||||
ginSwagger "github.com/swaggo/gin-swagger"
|
||||
_ "jcc-schedule/docs"
|
||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
kubeclient "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
|
@ -25,6 +26,7 @@ var KarmadaConfig karmadactl.KarmadaConfig
|
|||
var ControlPlaneRestConfig *rest.Config
|
||||
var ClientSet *kubeclient.Clientset
|
||||
var OpenSearchClient *opensearch.Client
|
||||
var CrDClient *clientset.Clientset
|
||||
|
||||
var ConfigNacos = GetNacosConfig()
|
||||
|
||||
|
@ -47,7 +49,7 @@ func InitRouter() *gin.Engine {
|
|||
ControlPlaneRestConfig, _ = KarmadaConfig.GetRestConfig("", dir+"/karmadaConfig/karmada-host")
|
||||
KarmadaClient = karmadaclientset.NewForConfigOrDie(ControlPlaneRestConfig)
|
||||
ClientSet, _ = utils.NewClientSet(ControlPlaneRestConfig)
|
||||
|
||||
CrDClient, _ = utils.NewCRDsClient(ControlPlaneRestConfig)
|
||||
// 初始化OpenSearch客户端
|
||||
OpenSearchClient, _ = opensearch.NewClient(opensearch.Config{
|
||||
Transport: &http.Transport{
|
||||
|
@ -79,10 +81,17 @@ func InitRouter() *gin.Engine {
|
|||
//Namespace
|
||||
namespace := v1.Group("namespace")
|
||||
namespace.GET("/list", ListNamespace)
|
||||
namespace.GET("/isExist", IsExistNamespace)
|
||||
namespace.GET("/list/name", ListName)
|
||||
namespace.GET("/listFromCluster", ListNamespaceFromCluster)
|
||||
namespace.GET("/describe", DescribeNamespace)
|
||||
namespace.GET("/detail", DetailNamespace)
|
||||
namespace.POST("/create", CreateNamespace)
|
||||
namespace.POST("/delete", DeleteNamespace)
|
||||
namespace.POST("/update", UpdateNamespace)
|
||||
namespace.DELETE("/delete/:clusterName/:name/:label", DeleteNamespace)
|
||||
namespace.PUT("/update", UpdateNamespace)
|
||||
namespace.GET("/getBatchMetrics", GetBatchNamespaceMetrics)
|
||||
namespace.GET("/getMetrics", GetNamespaceMetrics)
|
||||
namespace.GET("/resources", GetNamespaceResources)
|
||||
|
||||
//Domain
|
||||
domain := v1.Group("domain")
|
||||
|
@ -94,12 +103,18 @@ func InitRouter() *gin.Engine {
|
|||
//Pod
|
||||
pod := v1.Group("pod")
|
||||
pod.GET("/list", ListPod)
|
||||
pod.GET("/detail/:clusterName/:namespace/:name", PodDetail)
|
||||
pod.GET("/metrics/:clusterName/:namespace/:name", PodMetrics)
|
||||
pod.GET("/all", ALLPod)
|
||||
pod.GET("/isExist", IsExist)
|
||||
pod.GET("/detail", PodDetail)
|
||||
pod.GET("/cpuAndMemory", PodMetrics)
|
||||
pod.POST("/create", CreatePod)
|
||||
pod.DELETE("/delete/:namespace/:name", DeletePod)
|
||||
pod.DELETE("/delete/:clusterName/:namespace/:name/:label", DeletePod)
|
||||
pod.PUT("/updatePod", UpdatePod)
|
||||
pod.PUT("/detail", GetPodDetail)
|
||||
pod.GET("/listFromDeployment", ListPodFromDeployment)
|
||||
pod.GET("/listFromNode", ListPodFromNode)
|
||||
pod.GET("/pod/metrics", ListPodFromNode)
|
||||
pod.GET("/metrics", GetMetrics)
|
||||
|
||||
//Cluster
|
||||
cluster := v1.Group("cluster")
|
||||
|
@ -117,37 +132,86 @@ func InitRouter() *gin.Engine {
|
|||
|
||||
//Node
|
||||
node := v1.Group("node")
|
||||
node.GET("/list/:clusterName", ListNode)
|
||||
node.GET("/edge/:clusterName", ListEdgeNode)
|
||||
node.GET("/metrics/:clusterName", ListNodeMetrics)
|
||||
node.GET("/detail/:clusterName/:namespace/:podName", queryNodeInfo)
|
||||
node.PUT("/update", UpdateNode)
|
||||
node.GET("/list", ListNode)
|
||||
node.GET("/count", NodeCount)
|
||||
node.GET("/edge", ListEdgeNode)
|
||||
node.GET("/metrics", ListNodeMetrics)
|
||||
node.GET("/detail/pod", queryNodeInfo)
|
||||
node.GET("/detail", DetailNode)
|
||||
node.GET("/getNodeMetrics1h", GetNodeMetrics1h)
|
||||
node.GET("/getNodeMetrics8h", GetNodeMetrics8h)
|
||||
|
||||
//DeploymentParam
|
||||
deployment := v1.Group("deployment")
|
||||
deployment := v1.Group("deployments")
|
||||
deployment.POST("/create", CreateDeployment)
|
||||
deployment.DELETE("/delete/:namespace/:name", DeleteDeployment)
|
||||
deployment.DELETE("/delete/:clusterName/:namespace/:name/:label", DeleteDeployment)
|
||||
deployment.GET("/list", ListDeployment)
|
||||
deployment.GET("/listFromCluster", ListDeploymentFromCluster)
|
||||
deployment.GET("/describe", DescribeDeployment)
|
||||
deployment.GET("/detail", DetailDeployment)
|
||||
deployment.GET("/listGlobal", ListClusterDeployment)
|
||||
deployment.PUT("/redeploy", Redeploy)
|
||||
deployment.PUT("/update", UpdateDeployment)
|
||||
deployment.GET("/hpa", getHpa)
|
||||
deployment.PUT("/autoScaling", AutoScaling)
|
||||
deployment.POST("/hpa/create", CreateHpa)
|
||||
deployment.GET("/getMetrics", GetDeploymentMetrics)
|
||||
deployment.GET("isExist", IsExistDeployment)
|
||||
deployment.GET("/controllerVersions", ControllerRevisions)
|
||||
deployment.GET("/replicaSets", ListReplicaSets)
|
||||
|
||||
//daemonSet
|
||||
daemonSet := v1.Group("daemonsets")
|
||||
daemonSet.GET("/detail", DetailDaemonSet)
|
||||
daemonSet.POST("/create", CreateDaemonSet)
|
||||
daemonSet.DELETE("/delete/:clusterName/:namespace/:name/:label", DeleteDaemonSet)
|
||||
daemonSet.PUT("/update", UpdateDaemonSet)
|
||||
daemonSet.GET("isExist", IsExistDaemonSet)
|
||||
daemonSet.GET("/listFromCluster", ListDaemonSetFromCluster)
|
||||
|
||||
//statefulSet
|
||||
statefulSet := v1.Group("statefulsets")
|
||||
statefulSet.GET("/listFromCluster", ListStatefulSetFromCluster)
|
||||
statefulSet.GET("/detail", DetailStatefulSet)
|
||||
statefulSet.DELETE("/delete/:clusterName/:namespace/:name/:label", DeleteStatefulSet)
|
||||
statefulSet.POST("/create", CreateStatefulSet)
|
||||
statefulSet.PUT("/update", UpdateStatefulSet)
|
||||
statefulSet.GET("/isExist", IsExistStatefulSet)
|
||||
|
||||
// storage
|
||||
storage := v1.Group("storage")
|
||||
storage.POST("/pv", CreatePV)
|
||||
storage.POST("/pvc", CreatePVC)
|
||||
storage.GET("/pv/:clusterName", ListPV)
|
||||
storage.GET("/pvc/:clusterName/:namespace", ListPVC)
|
||||
storage.PUT("/pvc", UpdatePVC)
|
||||
storage.DELETE("/pvc/:clusterName/:namespace/:name/:label", DeletePVC)
|
||||
storage.GET("/pvc/detail", DetailPVC)
|
||||
storage.GET("/pvc/isExist", IsExistPVC)
|
||||
storage.GET("/pv", ListPV)
|
||||
storage.GET("/pvc", ListPVC)
|
||||
storage.GET("/list", ListStorageClass)
|
||||
|
||||
// storage
|
||||
crd := v1.Group("crd")
|
||||
crd.GET("/list/:clusterName", ListCRD)
|
||||
crd.GET("/detail/:clusterName/:namespace/:kind", DetailCRD)
|
||||
crd.GET("/create", CreateCRD)
|
||||
|
||||
// configMap
|
||||
configMap := v1.Group("configMap")
|
||||
configMap.POST("/create", CreateConfigMap)
|
||||
configMap := v1.Group("config")
|
||||
configMap.POST("/configMap/create", CreateConfigMap)
|
||||
configMap.GET("/secret/list", ListSecret)
|
||||
configMap.GET("/configMap/list", ListConfigMap)
|
||||
|
||||
// service
|
||||
service := v1.Group("service")
|
||||
service.POST("/create", CreateService)
|
||||
service.PUT("/update", UpdateService)
|
||||
service.DELETE("/delete/:clusterName/:namespace/:name/:label", DeleteService)
|
||||
service.GET("/all", AllService)
|
||||
service.GET("/list", ListService)
|
||||
service.GET("/isExist", IsExistService)
|
||||
service.GET("/detail", DetailService)
|
||||
|
||||
//PropagationPolicyTemplate
|
||||
propagationPolicyTemplate := v1.Group("propagationPolicyTemplate")
|
||||
|
@ -171,6 +235,11 @@ func InitRouter() *gin.Engine {
|
|||
//Overview
|
||||
overview := v1.Group("resource")
|
||||
overview.GET("/count", ResourceCount)
|
||||
overview.GET("/getApiServerMetrics", GetApiServerMetrics)
|
||||
overview.GET("/getNodeMetrics", GetNodeMetrics)
|
||||
overview.GET("/getClusterMetrics", GetClusterMetrics)
|
||||
overview.GET("/getScheduleMetrics", GetScheduleMetrics)
|
||||
overview.GET("/getOverallMetrics", GetOverallMetrics)
|
||||
|
||||
}
|
||||
|
||||
|
|
168
app/service.go
168
app/service.go
|
@ -2,10 +2,13 @@ package app
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/gin-gonic/gin"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ServiceParam struct {
|
||||
|
@ -13,44 +16,21 @@ type ServiceParam struct {
|
|||
TemplateId string `json:"templateId"`
|
||||
ClusterName []string `json:"clusterName"`
|
||||
}
|
||||
type ServiceParam1 struct {
|
||||
Service JSONData111 `json:"service"`
|
||||
TemplateId string `json:"templateId"`
|
||||
ClusterName []string `json:"clusterName"`
|
||||
}
|
||||
type JSONData111 struct {
|
||||
APIVersion string `json:"apiVersion"`
|
||||
Kind string `json:"kind"`
|
||||
Metadata struct {
|
||||
Namespace string `json:"namespace"`
|
||||
Labels struct {
|
||||
App string `json:"app"`
|
||||
} `json:"labels"`
|
||||
Name string `json:"name"`
|
||||
Annotations struct {
|
||||
KubesphereIoCreator string `json:"kubesphere.io/creator"`
|
||||
} `json:"annotations"`
|
||||
} `json:"metadata"`
|
||||
Spec struct {
|
||||
SessionAffinity string `json:"sessionAffinity"`
|
||||
Selector struct {
|
||||
Jcce string `json:"jcce"`
|
||||
} `json:"selector"`
|
||||
Ports []struct {
|
||||
Name string `json:"name"`
|
||||
Protocol string `json:"protocol"`
|
||||
TargetPort int `json:"targetPort"`
|
||||
Port int `json:"port"`
|
||||
} `json:"ports"`
|
||||
} `json:"spec"`
|
||||
|
||||
type ServiceObject struct {
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Metadata string `json:"metadata"`
|
||||
ResourceVersion string `json:"resourceVersion"`
|
||||
Items []v1.Service `json:"items"`
|
||||
}
|
||||
|
||||
// CreateService 创建服务
|
||||
// @Summary 创建服务
|
||||
// @Description 创建服务
|
||||
// @Tags service
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Param param body ServiceParam1 true "json"
|
||||
// @Success 200
|
||||
// @Failure 500
|
||||
// @Router /api/v1/service/create [post]
|
||||
|
@ -60,15 +40,135 @@ func CreateService(c *gin.Context) {
|
|||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
ClientSet.CoreV1().Services(sRequest.Service.Namespace).Create(context.TODO(), &sRequest.Service, metav1.CreateOptions{})
|
||||
if sRequest.Service.Labels == nil {
|
||||
sRequest.Service.Labels = map[string]string{}
|
||||
}
|
||||
sRequest.Service.Labels["jcce"] = "true"
|
||||
_, serviceErr := ClientSet.CoreV1().Services(sRequest.Service.Namespace).Create(context.TODO(), &sRequest.Service, metav1.CreateOptions{})
|
||||
if serviceErr != nil {
|
||||
Response(c, http.StatusBadRequest, "create service error.", serviceErr)
|
||||
return
|
||||
}
|
||||
// 创建调度策略实例
|
||||
CreatePropagationPolicies(PropagationPolicy{
|
||||
err := CreatePropagationPolicies(PropagationPolicy{
|
||||
ClusterName: sRequest.ClusterName,
|
||||
TemplateId: sRequest.TemplateId,
|
||||
ResourceName: sRequest.Service.Name,
|
||||
Name: "Service" + sRequest.Service.Namespace + sRequest.Service.Name,
|
||||
Name: "service" + "." + sRequest.Service.Namespace + "." + sRequest.Service.Name,
|
||||
Namespace: sRequest.Service.Namespace,
|
||||
Kind: "Service",
|
||||
})
|
||||
if err != nil {
|
||||
Response(c, http.StatusBadRequest, "create propagationPolicy error.", err)
|
||||
return
|
||||
}
|
||||
Response(c, http.StatusOK, "success", nil)
|
||||
}
|
||||
|
||||
// UpdateService 更新服务
|
||||
func UpdateService(c *gin.Context) {
|
||||
var sevice v1.Service
|
||||
if err := c.BindJSON(&sevice); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
ClientSet.CoreV1().Services(sevice.Namespace).Update(context.TODO(), &sevice, metav1.UpdateOptions{})
|
||||
Response(c, http.StatusOK, "success", nil)
|
||||
}
|
||||
|
||||
// DeleteService 删除服务
|
||||
func DeleteService(c *gin.Context) {
|
||||
clusterName := c.Param("clusterName")
|
||||
namespace := c.Param("namespace")
|
||||
name := c.Param("name")
|
||||
label := c.Param("label")
|
||||
if strings.EqualFold(label, "jcce") {
|
||||
err := ClientSet.CoreV1().Services(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete service failed", err)
|
||||
return
|
||||
}
|
||||
// 删除调度策略
|
||||
DeletePropagationPolicies(namespace, "service"+"."+namespace+"."+name)
|
||||
} else {
|
||||
result := DeleteObject(detailServiceConst, clusterName, namespace, name)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete service failed", result.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
Response(c, http.StatusOK, "success", nil)
|
||||
}
|
||||
|
||||
// IsExistService 判断输入service名称是否重复
|
||||
func IsExistService(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
result := SearchObject(detailServiceConst, clusterName, namespace, name)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusOK, "success", false)
|
||||
return
|
||||
}
|
||||
raw, _ := result.Raw()
|
||||
var service v1.Service
|
||||
json.Unmarshal(raw, &service)
|
||||
if len(service.Name) == 0 {
|
||||
Response(c, http.StatusOK, "success", false)
|
||||
return
|
||||
}
|
||||
Response(c, http.StatusOK, "success", true)
|
||||
}
|
||||
|
||||
// DetailService 查询service详情
|
||||
func DetailService(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
result := SearchObject(detailServiceConst, clusterName, namespace, name)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", result.Error())
|
||||
return
|
||||
}
|
||||
raw, _ := result.Raw()
|
||||
var service v1.Service
|
||||
json.Unmarshal(raw, &service)
|
||||
Response(c, http.StatusOK, "success", service)
|
||||
}
|
||||
|
||||
// ListService 查询命名空间下的service列表
|
||||
func ListService(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
result := SearchObject(serviceConst, clusterName, namespace, "")
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", result.Error())
|
||||
return
|
||||
}
|
||||
raw, _ := result.Raw()
|
||||
var scRes SCRes
|
||||
json.Unmarshal(raw, &scRes)
|
||||
Response(c, http.StatusOK, "success", scRes.Items)
|
||||
}
|
||||
|
||||
// AllService 查询service列表
|
||||
func AllService(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
pageNum := c.Query("pageNum")
|
||||
pageSize := c.Query("pageSize")
|
||||
result := SearchObject(allServiceConst, clusterName, "", "")
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", result.Error())
|
||||
return
|
||||
}
|
||||
raw, _ := result.Raw()
|
||||
var serviceRes ServiceObject
|
||||
json.Unmarshal(raw, &serviceRes)
|
||||
page := &Page[v1.Service]{}
|
||||
page.List = serviceRes.Items
|
||||
sort.SliceStable(serviceRes.Items, func(i, j int) bool {
|
||||
return serviceRes.Items[i].CreationTimestamp.Time.After(serviceRes.Items[j].CreationTimestamp.Time)
|
||||
})
|
||||
data := Paginator(page, int64(len(serviceRes.Items)), pageNum, pageSize)
|
||||
Response(c, http.StatusOK, "success", data)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
cpu_avg_usage = "avg_over_time(sum by (cluster) (node:node_num_cpu:sum{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'} * node:node_cpu_utilisation:avg1m{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'})[7d])"
|
||||
mem_avg_usage = "avg_over_time(sum by (cluster) (node:node_memory_bytes_total:sum{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'} - node:node_memory_bytes_available:sum{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'})[7d])"
|
||||
cpu_total_usage = "round(:node_cpu_utilisation:avg1m{cluster_name='clusterName'} * sum(node:node_num_cpu:sum{cluster_name='clusterName'}), 0.001) "
|
||||
mem_total_usage = "sum(node:node_memory_bytes_total:sum{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'}) - sum(node:node_memory_bytes_available:sum{cluster_name='clusterName',prometheus_replica='prometheus-k8s-0'})"
|
||||
clusters_test = "host,member-01,member-02,member-05"
|
||||
//clusters_test = "host,member-01,member-02,member-04-ali,member-05,zhijiang-gpu7,zhijiang-gpu8,zhijiang-gpu9"
|
||||
clusters_prod = "host,fedjcce-fx001,fedjcce-zj002,fedjcce-zj003,fedjcce-zj004,fedjcce-zj005,fedjcce-zj006,zhijiang-gpu5,zhijiang-hw2,zhijiang-gpu4,member-04-ali-zj"
|
||||
metric_range_7d = "168h"
|
||||
steps_7d = 90000
|
||||
)
|
||||
|
||||
// @Summary 获取大球监控数据
|
||||
// @Description 获取大球监控数据
|
||||
// @Tags namespace
|
||||
// @accept json
|
||||
// @Produce json
|
||||
// @Success 200
|
||||
// @Failure 400
|
||||
// @Router /api/v1/sphere/getOverallMetrics [get]
|
||||
func GetOverallMetrics(c *gin.Context) {
|
||||
|
||||
imap := make(map[string]string)
|
||||
clusters := strings.Split(clusters_test, ",")
|
||||
for _, cluster := range clusters {
|
||||
replaceMap := map[string]string{
|
||||
ClusterName: cluster,
|
||||
}
|
||||
imap["cpu_avg_usage"] += replacePromql(cpu_avg_usage, replaceMap, ClusterName) + "+"
|
||||
imap["mem_avg_usage"] += replacePromql(mem_avg_usage, replaceMap, ClusterName) + "+"
|
||||
imap["cpu_total_usage"] += replacePromql(cpu_total_usage, replaceMap, ClusterName) + "+"
|
||||
imap["mem_total_usage"] += replacePromql(mem_total_usage, replaceMap, ClusterName) + "+"
|
||||
}
|
||||
|
||||
metricMap := map[string][]MetricUrl{
|
||||
"cpu_avg_usage": {{ClusterName, "", GetMetricUrl(strings.TrimRight(imap["cpu_avg_usage"], "+"), nil, "", metric_range_7d, steps_7d)}},
|
||||
"mem_avg_usage": {{ClusterName, "", GetMetricUrl(strings.TrimRight(imap["mem_avg_usage"], "+"), nil, "", metric_range_7d, steps_7d)}},
|
||||
"cpu_total_usage": {{ClusterName, "", GetMetricUrl(strings.TrimRight(imap["cpu_total_usage"], "+"), nil, "", metric_range_7d, steps_7d)}},
|
||||
"mem_total_usage": {{ClusterName, "", GetMetricUrl(strings.TrimRight(imap["mem_total_usage"], "+"), nil, "", metric_range_7d, steps_7d)}},
|
||||
}
|
||||
|
||||
ch := make(chan MetricResult, len(metricMap))
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for k, v := range metricMap {
|
||||
wg.Add(1)
|
||||
go HttpGetMetrics(k, v, &wg, ch)
|
||||
}
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
|
||||
mr := []MetricResult{}
|
||||
for v := range ch {
|
||||
mr = append(mr, v)
|
||||
}
|
||||
|
||||
Response(c, http.StatusOK, "success", mr)
|
||||
}
|
200
app/storage.go
200
app/storage.go
|
@ -5,8 +5,12 @@ import (
|
|||
"encoding/json"
|
||||
"github.com/gin-gonic/gin"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/api/storage/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type PVRes struct {
|
||||
|
@ -17,7 +21,7 @@ type PVRes struct {
|
|||
Items []v1.PersistentVolume `json:"items"`
|
||||
}
|
||||
|
||||
type PVCRes struct {
|
||||
type PVCObject struct {
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Metadata string `json:"metadata"`
|
||||
|
@ -25,6 +29,14 @@ type PVCRes struct {
|
|||
Items []v1.PersistentVolumeClaim `json:"items"`
|
||||
}
|
||||
|
||||
type SCRes struct {
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Metadata string `json:"metadata"`
|
||||
ResourceVersion string `json:"resourceVersion"`
|
||||
Items []v1beta1.StorageClass `json:"items"`
|
||||
}
|
||||
|
||||
type PersistentVolume struct {
|
||||
TemplateId string `json:"templateId"`
|
||||
ClusterName []string `json:"clusterName"`
|
||||
|
@ -85,6 +97,7 @@ type PersistentVolumeClaim struct {
|
|||
PersistentVolumeClaim v1.PersistentVolumeClaim `json:"persistentVolumeClaim"`
|
||||
}
|
||||
|
||||
// CreatePV 创建PV
|
||||
type PersistentVolumeClaim1 struct {
|
||||
TemplateId string `json:"templateId"`
|
||||
ClusterName []string `json:"clusterName"`
|
||||
|
@ -116,12 +129,102 @@ func CreatePV(c *gin.Context) {
|
|||
ClusterName: pvRequest.ClusterName,
|
||||
TemplateId: pvRequest.TemplateId,
|
||||
ResourceName: pvRequest.PersistentVolume.Name,
|
||||
Name: "PersistentVolume" + pvRequest.PersistentVolume.Name,
|
||||
Name: "persistentVolume" + pvRequest.PersistentVolume.Name,
|
||||
Kind: "PersistentVolume",
|
||||
})
|
||||
Response(c, http.StatusOK, "success", persistentVolume)
|
||||
}
|
||||
|
||||
// IsExistPVC 查询pvc是否存在
|
||||
func IsExistPVC(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
result := SearchObject(detailPvcConst, clusterName, namespace, name)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusOK, "success", false)
|
||||
return
|
||||
}
|
||||
raw, _ := result.Raw()
|
||||
var pvc v1.PersistentVolumeClaim
|
||||
json.Unmarshal(raw, &pvc)
|
||||
if len(pvc.Name) == 0 {
|
||||
Response(c, http.StatusOK, "success", false)
|
||||
return
|
||||
}
|
||||
Response(c, http.StatusOK, "success", true)
|
||||
}
|
||||
|
||||
// DetailPVC 查询PVC详情
|
||||
func DetailPVC(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
namespace := c.Query("namespace")
|
||||
name := c.Query("name")
|
||||
result := SearchObject(detailPvcConst, clusterName, namespace, name)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", result.Error())
|
||||
return
|
||||
}
|
||||
raw, _ := result.Raw()
|
||||
var pvc v1.PersistentVolumeClaim
|
||||
json.Unmarshal(raw, &pvc)
|
||||
err_ := AddTypeMetaToObject(&pvc)
|
||||
if err_ != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", result.Error())
|
||||
}
|
||||
Response(c, http.StatusOK, "success", pvc)
|
||||
}
|
||||
|
||||
// DeletePVC 删除存储卷
|
||||
func DeletePVC(c *gin.Context) {
|
||||
clusterName := c.Param("clusterName")
|
||||
namespace := c.Param("namespace")
|
||||
name := c.Param("name")
|
||||
label := c.Param("label")
|
||||
if strings.EqualFold(label, "jcce") {
|
||||
err := ClientSet.CoreV1().PersistentVolumeClaims(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete persistentVolumeClaim failed", err)
|
||||
return
|
||||
}
|
||||
// 删除调度策略实例
|
||||
DeletePropagationPolicies(namespace, "PersistentVolumeClaim"+"."+name)
|
||||
} else {
|
||||
result := DeleteObject(detailPvcConst, clusterName, namespace, name)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "delete persistentVolumeClaim failed", result.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Response(c, http.StatusOK, "success", "")
|
||||
}
|
||||
|
||||
// UpdatePVC 更新存储卷信息
|
||||
func UpdatePVC(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
var pvc v1.PersistentVolumeClaim
|
||||
if err := c.BindJSON(&pvc); err != nil {
|
||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
if len(pvc.Labels["jcce"]) != 0 {
|
||||
_, err := ClientSet.CoreV1().PersistentVolumeClaims(pvc.Namespace).Update(context.TODO(), &pvc, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "update persistentVolumeClaim failed", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
result := UpdateObject(detailPvcConst, clusterName, pvc.Namespace, pvc.Name, pvc)
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "update persistentVolumeClaim failed", result.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
Response(c, http.StatusOK, "success", "")
|
||||
|
||||
}
|
||||
|
||||
// @Summary 创建PVC
|
||||
// @Description 创建PVC
|
||||
// @Tags storage
|
||||
|
@ -137,9 +240,13 @@ func CreatePVC(c *gin.Context) {
|
|||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||
return
|
||||
}
|
||||
if pvcRequest.PersistentVolumeClaim.Labels == nil {
|
||||
pvcRequest.PersistentVolumeClaim.Labels = map[string]string{}
|
||||
}
|
||||
pvcRequest.PersistentVolumeClaim.Labels["jcce"] = "true"
|
||||
persistentVolume, err := ClientSet.CoreV1().PersistentVolumeClaims(pvcRequest.PersistentVolumeClaim.Namespace).Create(context.TODO(), &pvcRequest.PersistentVolumeClaim, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
Response(c, http.StatusInternalServerError, "create persistentVolume failed", err)
|
||||
Response(c, http.StatusInternalServerError, "Create PersistentVolumeClaim Failed", err)
|
||||
return
|
||||
}
|
||||
// 创建调度策略实例
|
||||
|
@ -147,7 +254,7 @@ func CreatePVC(c *gin.Context) {
|
|||
ClusterName: pvcRequest.ClusterName,
|
||||
TemplateId: pvcRequest.TemplateId,
|
||||
ResourceName: pvcRequest.PersistentVolumeClaim.Name,
|
||||
Name: "PersistentVolumeClaim" + pvcRequest.PersistentVolumeClaim.Namespace + pvcRequest.PersistentVolumeClaim.Name,
|
||||
Name: "persistentVolumeClaim" + "." + pvcRequest.PersistentVolumeClaim.Namespace + "." + pvcRequest.PersistentVolumeClaim.Name,
|
||||
Namespace: pvcRequest.PersistentVolumeClaim.Namespace,
|
||||
Kind: "PersistentVolumeClaim",
|
||||
})
|
||||
|
@ -165,7 +272,7 @@ func CreatePVC(c *gin.Context) {
|
|||
// @Failure 500
|
||||
// @Router /api/v1/storage/pv/{clusterName} [get]
|
||||
func ListPV(c *gin.Context) {
|
||||
clusterName := c.Param("clusterName")
|
||||
clusterName := c.Query("clusterName")
|
||||
result := SearchObject(pvConst, clusterName, "", "")
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", result.Error())
|
||||
|
@ -187,17 +294,86 @@ func ListPV(c *gin.Context) {
|
|||
// @Param namespace path string true "命名空间"
|
||||
// @Success 200
|
||||
// @Failure 500
|
||||
// @Router /api/v1/storage/pvc/{clusterName}/{namespace} [get]
|
||||
// @Router /api/v1/storage/pvc [get]
|
||||
func ListPVC(c *gin.Context) {
|
||||
clusterName := c.Param("clusterName")
|
||||
namespace := c.Param("namespace")
|
||||
result := SearchObject(pvcConst, clusterName, namespace, "")
|
||||
clusterName := c.Query("clusterName")
|
||||
pageNum := c.Query("pageNum")
|
||||
pageSize := c.Query("pageSize")
|
||||
name := c.Query("name")
|
||||
status := c.Query("status")
|
||||
result := SearchObject(pvcConst, clusterName, "", "")
|
||||
if result.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", result.Error())
|
||||
return
|
||||
}
|
||||
raw, _ := result.Raw()
|
||||
var pvcRes PVCRes
|
||||
json.Unmarshal(raw, &pvcRes)
|
||||
Response(c, http.StatusOK, "success", pvcRes.Items)
|
||||
var pvcResult PVCObject
|
||||
json.Unmarshal(raw, &pvcResult)
|
||||
if len(name) != 0 {
|
||||
count := 0
|
||||
for i := range pvcResult.Items {
|
||||
if !strings.Contains(pvcResult.Items[i-count].Name, name) {
|
||||
pvcResult.Items = append(pvcResult.Items[:i-count], pvcResult.Items[i-count+1:]...)
|
||||
count = count + 1
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if len(status) != 0 {
|
||||
count := 0
|
||||
for i := range pvcResult.Items {
|
||||
if !strings.EqualFold(reflect.ValueOf(pvcResult.Items[i-count].Status.Phase).String(), status) {
|
||||
pvcResult.Items = append(pvcResult.Items[:i-count], pvcResult.Items[i-count+1:]...)
|
||||
count = count + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(pvcResult.Items) == 0 {
|
||||
Response(c, http.StatusOK, "success", pvcResult.Items)
|
||||
return
|
||||
}
|
||||
page := &Page[v1.PersistentVolumeClaim]{}
|
||||
page.List = pvcResult.Items
|
||||
sort.SliceStable(pvcResult.Items, func(i, j int) bool {
|
||||
return page.List[i].CreationTimestamp.Time.After(page.List[j].CreationTimestamp.Time)
|
||||
})
|
||||
data := Paginator(page, int64(len(page.List)), pageNum, pageSize)
|
||||
// 查询是否有pod挂载到当前pvc下
|
||||
podResult := SearchObject(allPodConst, clusterName, "", "")
|
||||
if podResult.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", podResult.Error())
|
||||
return
|
||||
}
|
||||
var podRes PodObject
|
||||
podRaw, _ := podResult.Raw()
|
||||
json.Unmarshal(podRaw, &podRes)
|
||||
for _, pvc := range data.List {
|
||||
for _, pod := range podRes.Items {
|
||||
for _, podPvc := range pod.Spec.Volumes {
|
||||
if podPvc.PersistentVolumeClaim != nil && pvc.Annotations != nil && podPvc.PersistentVolumeClaim.ClaimName == pvc.Name {
|
||||
pvc.Annotations["in-use"] = "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Response(c, http.StatusOK, "success", data)
|
||||
}
|
||||
|
||||
// ListStorageClass 查询StorageClass名称列表
|
||||
func ListStorageClass(c *gin.Context) {
|
||||
clusterName := c.Query("clusterName")
|
||||
scResult := SearchObject(scConst, clusterName, "", "")
|
||||
if scResult.Error() != nil {
|
||||
Response(c, http.StatusInternalServerError, "failed", scResult.Error())
|
||||
return
|
||||
}
|
||||
raw, _ := scResult.Raw()
|
||||
var scRes SCRes
|
||||
json.Unmarshal(raw, &scRes)
|
||||
// 遍历获取名称集合
|
||||
var result []string
|
||||
for i := range scRes.Items {
|
||||
result = append(result, scRes.Items[i].Name)
|
||||
}
|
||||
Response(c, http.StatusOK, "success", result)
|
||||
}
|
||||
|
|
|
@ -48,3 +48,12 @@ func (c Cli) Run(shell string) (string, error) {
|
|||
c.LastResult = string(buf)
|
||||
return c.LastResult, err
|
||||
}
|
||||
|
||||
func stringInclude(items []string, item string) bool {
|
||||
for _, eachItem := range items {
|
||||
if eachItem == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
930
docs/docs.go
930
docs/docs.go
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -41,100 +41,6 @@ definitions:
|
|||
version:
|
||||
type: string
|
||||
type: object
|
||||
app.DeploymentParamSwagger:
|
||||
properties:
|
||||
clusterName:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
deployment:
|
||||
properties:
|
||||
apiVersion:
|
||||
type: string
|
||||
kind:
|
||||
type: string
|
||||
metadata:
|
||||
properties:
|
||||
annotations:
|
||||
properties:
|
||||
kubesphere.io/creator:
|
||||
type: string
|
||||
type: object
|
||||
labels:
|
||||
type: object
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
type: object
|
||||
spec:
|
||||
properties:
|
||||
replicas:
|
||||
type: integer
|
||||
selector:
|
||||
properties:
|
||||
matchLabels:
|
||||
type: object
|
||||
type: object
|
||||
strategy:
|
||||
properties:
|
||||
rollingUpdate:
|
||||
properties:
|
||||
maxSurge:
|
||||
type: string
|
||||
maxUnavailable:
|
||||
type: string
|
||||
type: object
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
template:
|
||||
properties:
|
||||
metadata:
|
||||
properties:
|
||||
labels:
|
||||
type: object
|
||||
type: object
|
||||
spec:
|
||||
properties:
|
||||
containers:
|
||||
items:
|
||||
properties:
|
||||
image:
|
||||
type: string
|
||||
imagePullPolicy:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
ports:
|
||||
items:
|
||||
properties:
|
||||
containerPort:
|
||||
type: integer
|
||||
name:
|
||||
type: string
|
||||
protocol:
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
type: array
|
||||
imagePullSecrets: {}
|
||||
initContainers:
|
||||
items: {}
|
||||
type: array
|
||||
serviceAccount:
|
||||
type: string
|
||||
volumes:
|
||||
items: {}
|
||||
type: array
|
||||
type: object
|
||||
type: object
|
||||
type: object
|
||||
type: object
|
||||
templateId:
|
||||
type: string
|
||||
type: object
|
||||
app.Domain:
|
||||
properties:
|
||||
clusters:
|
||||
|
@ -172,6 +78,23 @@ definitions:
|
|||
memory_rate:
|
||||
type: number
|
||||
type: object
|
||||
app.HPAParam:
|
||||
properties:
|
||||
HPAName:
|
||||
type: string
|
||||
clusterName:
|
||||
type: string
|
||||
cpuTargetUtilization:
|
||||
type: string
|
||||
maxReplicas:
|
||||
type: integer
|
||||
memoryTargetValue:
|
||||
type: string
|
||||
minReplicas:
|
||||
type: integer
|
||||
namespace:
|
||||
type: string
|
||||
type: object
|
||||
app.JSONData:
|
||||
properties:
|
||||
apiVersion:
|
||||
|
@ -243,53 +166,6 @@ definitions:
|
|||
type: string
|
||||
type: object
|
||||
type: object
|
||||
app.JSONData111:
|
||||
properties:
|
||||
apiVersion:
|
||||
type: string
|
||||
kind:
|
||||
type: string
|
||||
metadata:
|
||||
properties:
|
||||
annotations:
|
||||
properties:
|
||||
kubesphere.io/creator:
|
||||
type: string
|
||||
type: object
|
||||
labels:
|
||||
properties:
|
||||
app:
|
||||
type: string
|
||||
type: object
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
type: object
|
||||
spec:
|
||||
properties:
|
||||
ports:
|
||||
items:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
port:
|
||||
type: integer
|
||||
protocol:
|
||||
type: string
|
||||
targetPort:
|
||||
type: integer
|
||||
type: object
|
||||
type: array
|
||||
selector:
|
||||
properties:
|
||||
jcce:
|
||||
type: string
|
||||
type: object
|
||||
sessionAffinity:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
app.Label:
|
||||
properties:
|
||||
create_time:
|
||||
|
@ -344,6 +220,8 @@ definitions:
|
|||
type: integer
|
||||
state:
|
||||
type: string
|
||||
templateId:
|
||||
type: string
|
||||
type: object
|
||||
app.OverridePolicy:
|
||||
properties:
|
||||
|
@ -411,9 +289,9 @@ definitions:
|
|||
node:
|
||||
type: string
|
||||
page_num:
|
||||
type: integer
|
||||
type: string
|
||||
page_size:
|
||||
type: integer
|
||||
type: string
|
||||
ready:
|
||||
type: string
|
||||
restarts:
|
||||
|
@ -449,15 +327,17 @@ definitions:
|
|||
memberClusterIp:
|
||||
type: string
|
||||
type: object
|
||||
app.ServiceParam1:
|
||||
app.RedeployParam:
|
||||
properties:
|
||||
clusterName:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
service:
|
||||
$ref: '#/definitions/app.JSONData111'
|
||||
templateId:
|
||||
type: string
|
||||
deploymentName:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
num:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
info:
|
||||
|
@ -777,18 +657,33 @@ paths:
|
|||
summary: 集群删除标签
|
||||
tags:
|
||||
- cluster
|
||||
/api/v1/deployment/create:
|
||||
/api/v1/deployment/autoScaling:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 创建工作负载
|
||||
description: 弹性伸缩
|
||||
parameters:
|
||||
- description: json
|
||||
in: body
|
||||
name: param
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/app.DeploymentParamSwagger'
|
||||
$ref: '#/definitions/app.HPAParam'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"400":
|
||||
description: Bad Request
|
||||
summary: 弹性伸缩
|
||||
tags:
|
||||
- deployment
|
||||
/api/v1/deployment/create:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 创建工作负载
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
|
@ -825,6 +720,28 @@ paths:
|
|||
summary: 删除工作负载
|
||||
tags:
|
||||
- deployment
|
||||
/api/v1/deployment/deployments/redeploy:
|
||||
patch:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 重新部署
|
||||
parameters:
|
||||
- description: json
|
||||
in: body
|
||||
name: param
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/app.RedeployParam'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
summary: 重新部署
|
||||
tags:
|
||||
- deployment
|
||||
/api/v1/deployment/describe:
|
||||
get:
|
||||
consumes:
|
||||
|
@ -850,6 +767,73 @@ paths:
|
|||
summary: 查询工作负载列表(所有集群)
|
||||
tags:
|
||||
- deployment
|
||||
/api/v1/deployment/getMetrics:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取部署监控
|
||||
parameters:
|
||||
- description: 集群名称
|
||||
in: query
|
||||
name: clusterName
|
||||
required: true
|
||||
type: string
|
||||
- description: namespace
|
||||
in: query
|
||||
name: namespace
|
||||
required: true
|
||||
type: string
|
||||
- description: 部署名称
|
||||
in: query
|
||||
name: deployment
|
||||
required: true
|
||||
type: string
|
||||
- description: 类型
|
||||
in: query
|
||||
name: queryType
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
summary: 获取部署监控
|
||||
tags:
|
||||
- deployment
|
||||
/api/v1/deployment/hpa:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取弹性伸缩信息
|
||||
parameters:
|
||||
- description: 集群名称
|
||||
in: query
|
||||
name: clusterName
|
||||
required: true
|
||||
type: string
|
||||
- description: 命名空间
|
||||
in: query
|
||||
name: namespace
|
||||
required: true
|
||||
type: string
|
||||
- description: deployName
|
||||
in: query
|
||||
name: deployName
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"400":
|
||||
description: Bad Request
|
||||
summary: 获取弹性伸缩信息
|
||||
tags:
|
||||
- deployment
|
||||
/api/v1/deployment/list:
|
||||
get:
|
||||
consumes:
|
||||
|
@ -1210,6 +1194,58 @@ paths:
|
|||
summary: 查询Namespace详情
|
||||
tags:
|
||||
- namespace
|
||||
/api/v1/namespace/getBatchMetrics:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 批量获取namespace监控
|
||||
parameters:
|
||||
- description: 集群名
|
||||
in: query
|
||||
name: clusterName
|
||||
required: true
|
||||
type: string
|
||||
- description: 逗号分隔多个命名空间名称
|
||||
in: query
|
||||
name: namespaces
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"400":
|
||||
description: Bad Request
|
||||
summary: 批量获取namespace监控
|
||||
tags:
|
||||
- namespace
|
||||
/api/v1/namespace/getMetrics:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: namespace监控
|
||||
parameters:
|
||||
- description: 集群名
|
||||
in: query
|
||||
name: clusterName
|
||||
required: true
|
||||
type: string
|
||||
- description: 命名空间名称
|
||||
in: query
|
||||
name: namespace
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"400":
|
||||
description: Bad Request
|
||||
summary: namespace监控
|
||||
tags:
|
||||
- namespace
|
||||
/api/v1/namespace/list:
|
||||
get:
|
||||
consumes:
|
||||
|
@ -1310,6 +1346,58 @@ paths:
|
|||
summary: 查询边缘节点列表
|
||||
tags:
|
||||
- node
|
||||
/api/v1/node/getNodeMetrics1h:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取集群节点1h监控
|
||||
parameters:
|
||||
- description: 集群名称
|
||||
in: query
|
||||
name: clusterName
|
||||
required: true
|
||||
type: string
|
||||
- description: 节点名称
|
||||
in: query
|
||||
name: nodeName
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"400":
|
||||
description: Bad Request
|
||||
summary: 获取集群节点1h监控
|
||||
tags:
|
||||
- node
|
||||
/api/v1/node/getNodeMetrics8h:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取集群节点8h监控
|
||||
parameters:
|
||||
- description: 集群名称
|
||||
in: query
|
||||
name: clusterName
|
||||
required: true
|
||||
type: string
|
||||
- description: 节点名称
|
||||
in: query
|
||||
name: nodeName
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"400":
|
||||
description: Bad Request
|
||||
summary: 获取集群节点8h监控
|
||||
tags:
|
||||
- node
|
||||
/api/v1/node/list/{clusterName}:
|
||||
get:
|
||||
consumes:
|
||||
|
@ -1374,6 +1462,121 @@ paths:
|
|||
summary: 查询重写策略列表
|
||||
tags:
|
||||
- overridePolicy
|
||||
/api/v1/overview/getApiServerMetrics:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取ApiServer请求数和请求延迟
|
||||
parameters:
|
||||
- description: 集群名称
|
||||
in: query
|
||||
name: clusterName
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"400":
|
||||
description: Bad Request
|
||||
summary: 获取ApiServer请求数和请求延迟
|
||||
tags:
|
||||
- overview
|
||||
/api/v1/overview/getClusterMetrics:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取容器集群资源监控
|
||||
parameters:
|
||||
- description: 集群名称
|
||||
in: query
|
||||
name: clusterName
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"400":
|
||||
description: Bad Request
|
||||
summary: 获取容器集群资源监控
|
||||
tags:
|
||||
- overview
|
||||
/api/v1/overview/getNodeMetrics:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取容器节点资源监控
|
||||
parameters:
|
||||
- description: 集群名称
|
||||
in: query
|
||||
name: clusterName
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"400":
|
||||
description: Bad Request
|
||||
summary: 获取容器节点资源监控
|
||||
tags:
|
||||
- overview
|
||||
/api/v1/overview/getScheduleMetrics:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取容器集群调度器监控
|
||||
parameters:
|
||||
- description: 集群名称
|
||||
in: query
|
||||
name: clusterName
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"400":
|
||||
description: Bad Request
|
||||
summary: 获取容器集群调度器监控
|
||||
tags:
|
||||
- overview
|
||||
/api/v1/pod/all:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 根据指定集群查询Pod列表
|
||||
parameters:
|
||||
- description: 集群名称
|
||||
in: query
|
||||
name: clusterName
|
||||
required: true
|
||||
type: string
|
||||
- description: pageNum
|
||||
in: query
|
||||
name: pageNum
|
||||
required: true
|
||||
type: integer
|
||||
- description: pageSize
|
||||
in: query
|
||||
name: pageSize
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
summary: 根据指定集群查询Pod列表
|
||||
tags:
|
||||
- pod
|
||||
/api/v1/pod/create:
|
||||
post:
|
||||
consumes:
|
||||
|
@ -1480,13 +1683,6 @@ paths:
|
|||
consumes:
|
||||
- application/json
|
||||
description: 根据指定集群查询Pod列表
|
||||
parameters:
|
||||
- description: json
|
||||
in: body
|
||||
name: param
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/app.Pod'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
|
@ -1497,6 +1693,32 @@ paths:
|
|||
summary: 根据指定集群查询Pod列表
|
||||
tags:
|
||||
- pod
|
||||
/api/v1/pod/metrics:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取容器组监控
|
||||
parameters:
|
||||
- description: 集群名称
|
||||
in: query
|
||||
name: clusterName
|
||||
required: true
|
||||
type: string
|
||||
- description: 容器组名称
|
||||
in: query
|
||||
name: podName
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"400":
|
||||
description: Bad Request
|
||||
summary: 获取容器组监控
|
||||
tags:
|
||||
- pod
|
||||
/api/v1/pod/metrics/{clusterName}/{namespace}/{name}:
|
||||
get:
|
||||
consumes:
|
||||
|
@ -1689,13 +1911,6 @@ paths:
|
|||
consumes:
|
||||
- application/json
|
||||
description: 创建服务
|
||||
parameters:
|
||||
- description: json
|
||||
in: body
|
||||
name: param
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/app.ServiceParam1'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
|
@ -1706,6 +1921,21 @@ paths:
|
|||
summary: 创建服务
|
||||
tags:
|
||||
- service
|
||||
/api/v1/sphere/getOverallMetrics:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取大球监控数据
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"400":
|
||||
description: Bad Request
|
||||
summary: 获取大球监控数据
|
||||
tags:
|
||||
- namespace
|
||||
/api/v1/storage/pv:
|
||||
post:
|
||||
consumes:
|
||||
|
@ -1750,28 +1980,6 @@ paths:
|
|||
tags:
|
||||
- storage
|
||||
/api/v1/storage/pvc:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 创建PVC
|
||||
parameters:
|
||||
- description: json
|
||||
in: body
|
||||
name: param
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/app.PersistentVolumeClaim1'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
summary: 创建PVC
|
||||
tags:
|
||||
- storage
|
||||
/api/v1/storage/pvc/{clusterName}/{namespace}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
|
@ -1797,4 +2005,25 @@ paths:
|
|||
summary: 查询PVC列表
|
||||
tags:
|
||||
- storage
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 创建PVC
|
||||
parameters:
|
||||
- description: json
|
||||
in: body
|
||||
name: param
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/app.PersistentVolumeClaim1'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
summary: 创建PVC
|
||||
tags:
|
||||
- storage
|
||||
swagger: "2.0"
|
||||
|
|
Loading…
Reference in New Issue