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
|
// @Failure 500
|
||||||
// @Router /api/v1/cluster/list [get]
|
// @Router /api/v1/cluster/list [get]
|
||||||
func ListCluster(c *gin.Context) {
|
func ListCluster(c *gin.Context) {
|
||||||
|
clusterName := c.Query("cluster_name")
|
||||||
clusterName, _ := c.GetQuery("cluster_name")
|
|
||||||
clusterList := make([]Cluster, 0)
|
clusterList := make([]Cluster, 0)
|
||||||
clusters, err := KarmadaClient.ClusterV1alpha1().Clusters().List(context.TODO(), metav1.ListOptions{})
|
clusters, err := KarmadaClient.ClusterV1alpha1().Clusters().List(context.TODO(), metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -136,11 +135,9 @@ func ListCluster(c *gin.Context) {
|
||||||
total := len(clusterList)
|
total := len(clusterList)
|
||||||
page := &Page[Cluster]{}
|
page := &Page[Cluster]{}
|
||||||
page.List = clusterList
|
page.List = clusterList
|
||||||
pageNum, _ := c.GetQuery("pageNum")
|
pageNum := c.Query("pageNum")
|
||||||
pageSize, _ := c.GetQuery("pageSize")
|
pageSize := c.Query("pageSize")
|
||||||
num, _ := strconv.ParseInt(pageNum, 10, 64)
|
data := Paginator(page, int64(total), pageNum, pageSize)
|
||||||
size, _ := strconv.ParseInt(pageSize, 10, 64)
|
|
||||||
data := Paginator(page, int64(total), num, size)
|
|
||||||
Response(c, http.StatusOK, "success", data)
|
Response(c, http.StatusOK, "success", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +154,7 @@ func ListCluster(c *gin.Context) {
|
||||||
// @Router /api/v1/cluster/listWithLabel [get]
|
// @Router /api/v1/cluster/listWithLabel [get]
|
||||||
func ListClusterWithLabel(c *gin.Context) {
|
func ListClusterWithLabel(c *gin.Context) {
|
||||||
|
|
||||||
clusterName, _ := c.GetQuery("cluster_name")
|
clusterName := c.Query("cluster_name")
|
||||||
|
|
||||||
clusterList := make([]Cluster, 0)
|
clusterList := make([]Cluster, 0)
|
||||||
clusters, err := KarmadaClient.ClusterV1alpha1().Clusters().List(context.TODO(), metav1.ListOptions{})
|
clusters, err := KarmadaClient.ClusterV1alpha1().Clusters().List(context.TODO(), metav1.ListOptions{})
|
||||||
|
@ -204,11 +201,9 @@ func ListClusterWithLabel(c *gin.Context) {
|
||||||
total := len(clusterList)
|
total := len(clusterList)
|
||||||
page := &Page[Cluster]{}
|
page := &Page[Cluster]{}
|
||||||
page.List = clusterList
|
page.List = clusterList
|
||||||
pageNum, _ := c.GetQuery("pageNum")
|
pageNum := c.Query("pageNum")
|
||||||
pageSize, _ := c.GetQuery("pageSize")
|
pageSize := c.Query("pageSize")
|
||||||
num, _ := strconv.ParseInt(pageNum, 10, 64)
|
data := Paginator(page, int64(total), pageNum, pageSize)
|
||||||
size, _ := strconv.ParseInt(pageSize, 10, 64)
|
|
||||||
data := Paginator(page, int64(total), num, size)
|
|
||||||
Response(c, http.StatusOK, "success", data)
|
Response(c, http.StatusOK, "success", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,8 +219,8 @@ func ListClusterWithLabel(c *gin.Context) {
|
||||||
// @Router /api/v1/cluster/unJoin [delete]
|
// @Router /api/v1/cluster/unJoin [delete]
|
||||||
func UnJoin(c *gin.Context) {
|
func UnJoin(c *gin.Context) {
|
||||||
copyContext := c.Copy()
|
copyContext := c.Copy()
|
||||||
clusterName, _ := c.GetQuery("cluster_name")
|
clusterName := c.Query("cluster_name")
|
||||||
domainId, _ := c.GetQuery("domain_id")
|
domainId := c.Query("domain_id")
|
||||||
if clusterName == "" || domainId == "" {
|
if clusterName == "" || domainId == "" {
|
||||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||||
return
|
return
|
||||||
|
@ -426,7 +421,7 @@ func ClusterExist(c *gin.Context) {
|
||||||
glog.Info("failed to retrieve cluster(%s). error: %v", clusters, err)
|
glog.Info("failed to retrieve cluster(%s). error: %v", clusters, err)
|
||||||
Response(c, http.StatusBadRequest, "failed to retrieve cluster", 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++ {
|
for i := 0; i < len(clusters.Items); i++ {
|
||||||
if clusters.Items[i].Name == clusterName {
|
if clusters.Items[i].Name == clusterName {
|
||||||
|
@ -519,9 +514,9 @@ func deleteMaps(labels map[string]string, keys map[string]string) {
|
||||||
// @Failure 500
|
// @Failure 500
|
||||||
// @Router /api/v1/cluster/listByDomain [post]
|
// @Router /api/v1/cluster/listByDomain [post]
|
||||||
func ListByDomain(c *gin.Context) {
|
func ListByDomain(c *gin.Context) {
|
||||||
namespaceName, _ := c.GetQuery("namespace")
|
namespaceName := c.Query("namespace")
|
||||||
deploymentName, _ := c.GetQuery("deployment_name")
|
deploymentName := c.Query("deployment_name")
|
||||||
domainId, _ := c.GetQuery("domain_id")
|
domainId := c.Query("domain_id")
|
||||||
|
|
||||||
//
|
//
|
||||||
deployJson := GetDeployFromOS(namespaceName, deploymentName, "")
|
deployJson := GetDeployFromOS(namespaceName, deploymentName, "")
|
||||||
|
|
|
@ -2,6 +2,7 @@ package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
@ -14,12 +15,30 @@ type ConfigMap struct {
|
||||||
TemplateId string `json:"templateId"`
|
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) {
|
func CreateConfigMap(c *gin.Context) {
|
||||||
var cmRequest ConfigMap
|
var cmRequest ConfigMap
|
||||||
if err := c.BindJSON(&cmRequest); err != nil {
|
if err := c.BindJSON(&cmRequest); err != nil {
|
||||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
cmRequest.ConfigMap.Labels["jcce"] = "true"
|
||||||
ClientSet.CoreV1().ConfigMaps(cmRequest.ConfigMap.Namespace).Create(context.TODO(), &cmRequest.ConfigMap, metav1.CreateOptions{})
|
ClientSet.CoreV1().ConfigMaps(cmRequest.ConfigMap.Namespace).Create(context.TODO(), &cmRequest.ConfigMap, metav1.CreateOptions{})
|
||||||
// 创建调度策略实例
|
// 创建调度策略实例
|
||||||
CreatePropagationPolicies(PropagationPolicy{
|
CreatePropagationPolicies(PropagationPolicy{
|
||||||
|
@ -32,3 +51,25 @@ func CreateConfigMap(c *gin.Context) {
|
||||||
})
|
})
|
||||||
Response(c, http.StatusOK, "success", nil)
|
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
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
@ -16,11 +20,70 @@ type CRDRes struct {
|
||||||
Items []v1.CustomResourceDefinition `json:"items"`
|
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) {
|
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, "", "")
|
result := SearchObject(crdConst, clusterName, "", "")
|
||||||
raw, _ := result.Raw()
|
raw, _ := result.Raw()
|
||||||
var cRDRes CRDRes
|
var cRDRes CRDRes
|
||||||
json.Unmarshal(raw, &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 (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"github.com/bitly/go-simplejson"
|
"github.com/bitly/go-simplejson"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
appv1 "k8s.io/api/apps/v1"
|
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"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var deployMutex sync.Mutex
|
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 {
|
type DeploymentParam struct {
|
||||||
ClusterName []string `json:"clusterName"`
|
ClusterName []string `json:"clusterName"`
|
||||||
TemplateId string `json:"templateId"`
|
TemplateId string `json:"templateId"`
|
||||||
Deployment appv1.Deployment `json:"deployment"`
|
Deployment appv1.Deployment `json:"deployment"`
|
||||||
}
|
}
|
||||||
type DeploymentParamSwagger struct {
|
|
||||||
ClusterName []string `json:"clusterName"`
|
type HPAParam struct {
|
||||||
TemplateId string `json:"templateId"`
|
ClusterName []string `json:"clusterName"`
|
||||||
Deployment struct {
|
TemplateId string `json:"templateId"`
|
||||||
APIVersion string `json:"apiVersion"`
|
Hpa v12.HorizontalPodAutoscaler `json:"hpa"`
|
||||||
Kind string `json:"kind"`
|
}
|
||||||
Metadata struct {
|
|
||||||
Namespace string `json:"namespace"`
|
type StatefulSetParam struct {
|
||||||
Labels struct {
|
ClusterName []string `json:"clusterName"`
|
||||||
} `json:"labels"`
|
TemplateId string `json:"templateId"`
|
||||||
Name string `json:"name"`
|
StatefulSet appv1.StatefulSet `json:"statefulSet"`
|
||||||
Annotations struct {
|
}
|
||||||
KubesphereIoCreator string `json:"kubesphere.io/creator"`
|
|
||||||
} `json:"annotations"`
|
type DaemonSetParam struct {
|
||||||
} `json:"metadata"`
|
ClusterName []string `json:"clusterName"`
|
||||||
Spec struct {
|
TemplateId string `json:"templateId"`
|
||||||
Replicas int `json:"replicas"`
|
DaemonSet appv1.DaemonSet `json:"daemonSet"`
|
||||||
Selector struct {
|
}
|
||||||
MatchLabels struct {
|
|
||||||
} `json:"matchLabels"`
|
type RedeployParam struct {
|
||||||
} `json:"selector"`
|
ClusterName string `json:"clusterName"`
|
||||||
Template struct {
|
Namespace string `json:"namespace"`
|
||||||
Metadata struct {
|
DeploymentName string `json:"deploymentName"`
|
||||||
Labels struct {
|
Num string `json:"num"`
|
||||||
} `json:"labels"`
|
Type string `json:"type"`
|
||||||
} `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 DeploymentRes struct {
|
type DeploymentRes struct {
|
||||||
|
@ -82,12 +67,52 @@ type DeploymentRes struct {
|
||||||
Replicas int32 `json:"replicas"`
|
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 创建工作负载
|
// @Summary 创建工作负载
|
||||||
// @Description 创建工作负载
|
// @Description 创建工作负载
|
||||||
// @Tags deployment
|
// @Tags deployment
|
||||||
// @accept json
|
// @accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param param body DeploymentParamSwagger true "json"
|
|
||||||
// @Success 200
|
// @Success 200
|
||||||
// @Failure 400
|
// @Failure 400
|
||||||
// @Router /api/v1/deployment/create [post]
|
// @Router /api/v1/deployment/create [post]
|
||||||
|
@ -97,9 +122,10 @@ func CreateDeployment(c *gin.Context) {
|
||||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dpRequest.Deployment.Spec.Template.Labels = map[string]string{"jcce": "true"}
|
if dpRequest.Deployment.Labels == nil {
|
||||||
dpRequest.Deployment.Spec.Selector.MatchLabels = map[string]string{"jcce": "true"}
|
dpRequest.Deployment.Labels = map[string]string{}
|
||||||
dpRequest.Deployment.Labels = map[string]string{"jcce": "true"}
|
}
|
||||||
|
dpRequest.Deployment.Labels["jcce"] = "true"
|
||||||
deploymentList, err := ClientSet.AppsV1().Deployments(dpRequest.Deployment.Namespace).Create(context.TODO(), &dpRequest.Deployment, metav1.CreateOptions{})
|
deploymentList, err := ClientSet.AppsV1().Deployments(dpRequest.Deployment.Namespace).Create(context.TODO(), &dpRequest.Deployment, metav1.CreateOptions{})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -110,12 +136,64 @@ func CreateDeployment(c *gin.Context) {
|
||||||
ClusterName: dpRequest.ClusterName,
|
ClusterName: dpRequest.ClusterName,
|
||||||
TemplateId: dpRequest.TemplateId,
|
TemplateId: dpRequest.TemplateId,
|
||||||
ResourceName: dpRequest.Deployment.Name,
|
ResourceName: dpRequest.Deployment.Name,
|
||||||
Name: "DeploymentParam" + dpRequest.Deployment.Namespace + dpRequest.Deployment.Name,
|
Name: "Deployment" + "." + dpRequest.Deployment.Namespace + "." + dpRequest.Deployment.Name,
|
||||||
Namespace: dpRequest.Deployment.Namespace,
|
Namespace: dpRequest.Deployment.Namespace,
|
||||||
Kind: "DeploymentParam",
|
Kind: "Deployment",
|
||||||
})
|
})
|
||||||
Response(c, http.StatusOK, "success", deploymentList)
|
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 根据查询工作负载列表(控制平面)
|
// ListDeployment 根据查询工作负载列表(控制平面)
|
||||||
|
@ -132,7 +210,7 @@ func CreateDeployment(c *gin.Context) {
|
||||||
// @Router /api/v1/deployment/list [get]
|
// @Router /api/v1/deployment/list [get]
|
||||||
func ListDeployment(c *gin.Context) {
|
func ListDeployment(c *gin.Context) {
|
||||||
|
|
||||||
namespace, _ := c.GetQuery("namespace")
|
namespace := c.Query("namespace")
|
||||||
|
|
||||||
dpList := make([]DeploymentRes, 0)
|
dpList := make([]DeploymentRes, 0)
|
||||||
deploymentList, err := ClientSet.AppsV1().Deployments(namespace).List(context.TODO(), metav1.ListOptions{})
|
deploymentList, err := ClientSet.AppsV1().Deployments(namespace).List(context.TODO(), metav1.ListOptions{})
|
||||||
|
@ -163,17 +241,14 @@ func ListDeployment(c *gin.Context) {
|
||||||
total := len(dpList)
|
total := len(dpList)
|
||||||
page := &Page[DeploymentRes]{}
|
page := &Page[DeploymentRes]{}
|
||||||
page.List = dpList
|
page.List = dpList
|
||||||
pageNum, _ := c.GetQuery("pageNum")
|
pageNum := c.Query("pageNum")
|
||||||
pageSize, _ := c.GetQuery("pageSize")
|
pageSize := c.Query("pageSize")
|
||||||
num, _ := strconv.ParseInt(pageNum, 10, 64)
|
data := Paginator(page, int64(total), pageNum, pageSize)
|
||||||
size, _ := strconv.ParseInt(pageSize, 10, 64)
|
|
||||||
data := Paginator(page, int64(total), num, size)
|
|
||||||
Response(c, http.StatusOK, "success", data)
|
Response(c, http.StatusOK, "success", data)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListClusterDeployment 查询工作负载列表(所有集群)
|
// ListClusterDeployment 查询工作负载列表(所有集群)
|
||||||
|
|
||||||
func ListClusterDeployment(c *gin.Context) {
|
func ListClusterDeployment(c *gin.Context) {
|
||||||
//TODO 逻辑待完善
|
//TODO 逻辑待完善
|
||||||
ss, _ := KarmadaClient.SearchV1alpha1().ResourceRegistries().Get(context.TODO(), "clustercache-sample", metav1.GetOptions{})
|
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)
|
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 查询工作负载列表(所有集群)
|
// DescribeDeployment 查询工作负载列表(所有集群)
|
||||||
// @Summary 查询工作负载列表(所有集群)
|
// @Summary 查询工作负载列表(所有集群)
|
||||||
// @Description 查询工作负载列表(所有集群)
|
// @Description 查询工作负载列表(所有集群)
|
||||||
|
@ -194,8 +355,8 @@ func ListClusterDeployment(c *gin.Context) {
|
||||||
// @Router /api/v1/deployment/describe [get]
|
// @Router /api/v1/deployment/describe [get]
|
||||||
func DescribeDeployment(c *gin.Context) {
|
func DescribeDeployment(c *gin.Context) {
|
||||||
|
|
||||||
namespace, _ := c.GetQuery("namespace")
|
namespace := c.Query("namespace")
|
||||||
deployName, _ := c.GetQuery("deploy_name")
|
deployName := c.Query("deploy_name")
|
||||||
ClientSet.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})
|
ClientSet.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})
|
||||||
podList := make([]Pod, 0)
|
podList := make([]Pod, 0)
|
||||||
pods := GetPodFromOS(namespace, deployName)
|
pods := GetPodFromOS(namespace, deployName)
|
||||||
|
@ -268,14 +429,565 @@ func DescribeDeployment(c *gin.Context) {
|
||||||
// @Failure 400
|
// @Failure 400
|
||||||
// @Router /api/v1/deployment/delete/{namespace}/{name} [delete]
|
// @Router /api/v1/deployment/delete/{namespace}/{name} [delete]
|
||||||
func DeleteDeployment(c *gin.Context) {
|
func DeleteDeployment(c *gin.Context) {
|
||||||
|
clusterName := c.Param("clusterName")
|
||||||
namespace := c.Param("namespace")
|
namespace := c.Param("namespace")
|
||||||
name := c.Param("name")
|
name := c.Param("name")
|
||||||
err := ClientSet.AppsV1().Deployments(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})
|
label := c.Param("label")
|
||||||
if err != nil {
|
if strings.EqualFold(label, "jcce") {
|
||||||
Response(c, http.StatusInternalServerError, "delete deployment failed", err)
|
err := ClientSet.AppsV1().Deployments(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})
|
||||||
return
|
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)
|
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]
|
// @Router /api/v1/domain/list [get]
|
||||||
func ListDomain(c *gin.Context) {
|
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+"%")
|
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) {
|
func DescribeDomain(c *gin.Context) {
|
||||||
|
|
||||||
var domain Domain
|
var domain Domain
|
||||||
domainId, _ := c.GetQuery("domain_id")
|
domainId := c.Query("domain_id")
|
||||||
namespace, _ := c.GetQuery("namespace")
|
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)
|
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 domainName string
|
||||||
var longitude float64
|
var longitude float64
|
||||||
|
@ -247,8 +247,8 @@ func DescribeDomain(c *gin.Context) {
|
||||||
// @Router /api/v1/domain/listByDeployment [get]
|
// @Router /api/v1/domain/listByDeployment [get]
|
||||||
func ListByDeployment(c *gin.Context) {
|
func ListByDeployment(c *gin.Context) {
|
||||||
domainList := make([]Domain, 0)
|
domainList := make([]Domain, 0)
|
||||||
namespaceName, _ := c.GetQuery("namespace")
|
namespaceName := c.Query("namespace")
|
||||||
deploymentName, _ := c.GetQuery("deployment_name")
|
deploymentName := c.Query("deployment_name")
|
||||||
|
|
||||||
domainList = getDomainsByDeployment(namespaceName, deploymentName)
|
domainList = getDomainsByDeployment(namespaceName, deploymentName)
|
||||||
|
|
||||||
|
|
11
app/label.go
11
app/label.go
|
@ -3,7 +3,6 @@ package app
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -79,7 +78,7 @@ func DeleteLabel(c *gin.Context) {
|
||||||
// @Router /api/v1/label/list [post]
|
// @Router /api/v1/label/list [post]
|
||||||
func ListLabel(c *gin.Context) {
|
func ListLabel(c *gin.Context) {
|
||||||
|
|
||||||
labelName, _ := c.GetQuery("label_name")
|
labelName := c.Query("label_name")
|
||||||
|
|
||||||
LabelList := make([]Label, 0)
|
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+"%")
|
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)
|
total := len(LabelList)
|
||||||
page := &Page[Label]{}
|
page := &Page[Label]{}
|
||||||
page.List = LabelList
|
page.List = LabelList
|
||||||
pageNum, _ := c.GetQuery("pageNum")
|
pageNum := c.Query("pageNum")
|
||||||
pageSize, _ := c.GetQuery("pageSize")
|
pageSize := c.Query("pageSize")
|
||||||
num, _ := strconv.ParseInt(pageNum, 10, 64)
|
data := Paginator(page, int64(total), pageNum, pageSize)
|
||||||
size, _ := strconv.ParseInt(pageSize, 10, 64)
|
|
||||||
data := Paginator(page, int64(total), num, size)
|
|
||||||
Response(c, http.StatusOK, "success", data)
|
Response(c, http.StatusOK, "success", data)
|
||||||
//Response(c, http.StatusOK, "success", LabelList)
|
//Response(c, http.StatusOK, "success", LabelList)
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ package app
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type LabelType struct {
|
type LabelType struct {
|
||||||
|
@ -77,7 +76,7 @@ func DeleteLabelType(c *gin.Context) {
|
||||||
// @Router /api/v1/labelType/list [get]
|
// @Router /api/v1/labelType/list [get]
|
||||||
func ListLabelType(c *gin.Context) {
|
func ListLabelType(c *gin.Context) {
|
||||||
|
|
||||||
labelType, _ := c.GetQuery("label_type")
|
labelType := c.Query("label_type")
|
||||||
|
|
||||||
LabelTypeList := make([]LabelType, 0)
|
LabelTypeList := make([]LabelType, 0)
|
||||||
rows, err := DB.Query(`SELECT label_type_id,label_type,multi_check FROM label_type WHERE label_type like ?`, "%"+labelType+"%")
|
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)
|
total := len(LabelTypeList)
|
||||||
page := &Page[LabelType]{}
|
page := &Page[LabelType]{}
|
||||||
page.List = LabelTypeList
|
page.List = LabelTypeList
|
||||||
pageNum, _ := c.GetQuery("pageNum")
|
pageNum := c.Query("pageNum")
|
||||||
pageSize, _ := c.GetQuery("pageSize")
|
pageSize := c.Query("pageSize")
|
||||||
num, _ := strconv.ParseInt(pageNum, 10, 64)
|
data := Paginator(page, int64(total), pageNum, pageSize)
|
||||||
size, _ := strconv.ParseInt(pageSize, 10, 64)
|
|
||||||
data := Paginator(page, int64(total), num, size)
|
|
||||||
Response(c, http.StatusOK, "success", data)
|
Response(c, http.StatusOK, "success", data)
|
||||||
//Response(c, http.StatusOK, "success", LabelTypeList)
|
//Response(c, http.StatusOK, "success", LabelTypeList)
|
||||||
|
|
||||||
|
|
395
app/namespace.go
395
app/namespace.go
|
@ -2,15 +2,28 @@ package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/karmada-io/karmada/pkg/util"
|
"github.com/karmada-io/karmada/pkg/util"
|
||||||
|
v1 "k8s.io/api/batch/v1"
|
||||||
coreV1 "k8s.io/api/core/v1"
|
coreV1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"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 {
|
type Namespace struct {
|
||||||
NsName string `json:"ns_name"`
|
NsName string `json:"ns_name"`
|
||||||
State string `json:"state"`
|
State string `json:"state"`
|
||||||
|
@ -23,6 +36,13 @@ type Namespace struct {
|
||||||
AvailablePodNum int32 `json:"available_pod_num"`
|
AvailablePodNum int32 `json:"available_pod_num"`
|
||||||
Alias string `json:"alias"`
|
Alias string `json:"alias"`
|
||||||
Describe string `json:"describe"`
|
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 {
|
type DomainResult struct {
|
||||||
|
@ -30,6 +50,82 @@ type DomainResult struct {
|
||||||
Location [2]float64 `json:"location"`
|
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 创建命名空间(项目)
|
// @Summary 创建命名空间(项目)
|
||||||
// @Description 创建命名空间(项目)
|
// @Description 创建命名空间(项目)
|
||||||
// @Tags namespace
|
// @Tags namespace
|
||||||
|
@ -40,38 +136,125 @@ type DomainResult struct {
|
||||||
// @Failure 400
|
// @Failure 400
|
||||||
// @Router /api/v1/namespace/create [post]
|
// @Router /api/v1/namespace/create [post]
|
||||||
func CreateNamespace(c *gin.Context) {
|
func CreateNamespace(c *gin.Context) {
|
||||||
var j Namespace
|
var nsParam NamespaceParam
|
||||||
labels := make(map[string]string)
|
if nsParam.Namespace.Labels == nil {
|
||||||
labels["jcce"] = "true"
|
nsParam.Namespace.Labels = map[string]string{}
|
||||||
if err := c.BindJSON(&j); err != nil {
|
}
|
||||||
|
nsParam.Namespace.Labels["jcce"] = "true"
|
||||||
|
if err := c.BindJSON(&nsParam); err != nil {
|
||||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sqlStr1 := "INSERT INTO joint_domain.namespace (namespace_name, alias, `describe`) VALUES(?,?,?)"
|
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 {
|
if err != nil {
|
||||||
Response(c, http.StatusBadRequest, "query failed!", err)
|
Response(c, http.StatusBadRequest, "query failed!", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ns := coreV1.Namespace{
|
nsResult, err := ClientSet.CoreV1().Namespaces().Create(context.TODO(), &nsParam.Namespace, metav1.CreateOptions{})
|
||||||
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{})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
println(err)
|
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)
|
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列表
|
// @Summary 查询Namespace列表
|
||||||
// @Description 查询Namespace列表
|
// @Description 查询Namespace列表
|
||||||
// @Tags namespace
|
// @Tags namespace
|
||||||
|
@ -137,13 +320,21 @@ func ListNamespace(ctx *gin.Context) {
|
||||||
page.List = nsList
|
page.List = nsList
|
||||||
pageNum, _ := ctx.GetQuery("pageNum")
|
pageNum, _ := ctx.GetQuery("pageNum")
|
||||||
pageSize, _ := ctx.GetQuery("pageSize")
|
pageSize, _ := ctx.GetQuery("pageSize")
|
||||||
num, _ := strconv.ParseInt(pageNum, 10, 64)
|
data := Paginator(page, int64(total), pageNum, pageSize)
|
||||||
size, _ := strconv.ParseInt(pageSize, 10, 64)
|
|
||||||
data := Paginator(page, int64(total), num, size)
|
|
||||||
Response(ctx, http.StatusOK, "success", data)
|
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详情
|
// @Summary 查询Namespace详情
|
||||||
// @Description 查询Namespace详情
|
// @Description 查询Namespace详情
|
||||||
// @Tags namespace
|
// @Tags namespace
|
||||||
|
@ -155,7 +346,7 @@ func ListNamespace(ctx *gin.Context) {
|
||||||
// @Router /api/v1/namespace/describe [get]
|
// @Router /api/v1/namespace/describe [get]
|
||||||
func DescribeNamespace(c *gin.Context) {
|
func DescribeNamespace(c *gin.Context) {
|
||||||
|
|
||||||
namespace, _ := c.GetQuery("namespace")
|
namespace := c.Query("namespace")
|
||||||
|
|
||||||
optsGet := metav1.GetOptions{
|
optsGet := metav1.GetOptions{
|
||||||
TypeMeta: metav1.TypeMeta{},
|
TypeMeta: metav1.TypeMeta{},
|
||||||
|
@ -273,48 +464,146 @@ func DescribeNamespace(c *gin.Context) {
|
||||||
// @Failure 400
|
// @Failure 400
|
||||||
// @Router /api/v1/namespace/update [post]
|
// @Router /api/v1/namespace/update [post]
|
||||||
func UpdateNamespace(c *gin.Context) {
|
func UpdateNamespace(c *gin.Context) {
|
||||||
var j Namespace
|
clusterName := c.Query("clusterName")
|
||||||
if err := c.BindJSON(&j); err != nil {
|
var namespace coreV1.Namespace
|
||||||
|
if err := c.BindJSON(&namespace); err != nil {
|
||||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if len(namespace.Labels["jcce"]) != 0 {
|
||||||
ns := coreV1.Namespace{
|
_, err := ClientSet.CoreV1().Namespaces().Update(context.TODO(), &namespace, metav1.UpdateOptions{})
|
||||||
TypeMeta: metav1.TypeMeta{},
|
if err != nil {
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
Response(c, http.StatusInternalServerError, "update namespace failed", err)
|
||||||
Name: j.NsName,
|
return
|
||||||
},
|
}
|
||||||
Spec: coreV1.NamespaceSpec{},
|
} else {
|
||||||
Status: coreV1.NamespaceStatus{},
|
result := UpdateObject(detailNamespaceConst, clusterName, "", namespace.Name, namespace)
|
||||||
|
if result.Error() != nil {
|
||||||
|
Response(c, http.StatusInternalServerError, "update namespace failed", result.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Response(c, http.StatusOK, "success", "")
|
||||||
nsResult, err := ClientSet.CoreV1().Namespaces().Update(context.TODO(), &ns, metav1.UpdateOptions{})
|
|
||||||
if err != nil {
|
|
||||||
println(err)
|
|
||||||
}
|
|
||||||
Response(c, http.StatusOK, "success", nsResult)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteNamespace 删除命名空间(项目)
|
// DeleteNamespace 删除命名空间(项目)
|
||||||
func DeleteNamespace(c *gin.Context) {
|
func DeleteNamespace(c *gin.Context) {
|
||||||
var j Namespace
|
clusterName := c.Param("clusterName")
|
||||||
if err := c.BindJSON(&j); err != nil {
|
name := c.Param("name")
|
||||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
label := c.Param("label")
|
||||||
return
|
if strings.EqualFold(label, "jcce") {
|
||||||
}
|
err := ClientSet.CoreV1().Namespaces().Delete(context.TODO(), name, metav1.DeleteOptions{})
|
||||||
|
if err != nil {
|
||||||
err := ClientSet.CoreV1().Namespaces().Delete(context.TODO(), j.NsName, metav1.DeleteOptions{})
|
Response(c, http.StatusInternalServerError, "delete namespace "+name+"failed", "")
|
||||||
if err != nil {
|
return
|
||||||
Response(c, http.StatusInternalServerError, "delete namespace "+j.NsName+"failed", "")
|
}
|
||||||
println(err)
|
// 删除数据库记录policy实例
|
||||||
}
|
_, err = DB.Exec(`delete from joint_domain.namespace where namespace_name = ? `, name)
|
||||||
// 删除数据库记录policy实例
|
if err != nil {
|
||||||
_, err = DB.Exec(`delete from joint_domain.namespace where namespace_name = ? `, j.NsName)
|
Response(c, http.StatusInternalServerError, "delete db failed", err)
|
||||||
if err != nil {
|
return
|
||||||
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", "")
|
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
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
v1 "k8s.io/api/core/v1"
|
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"
|
"k8s.io/metrics/pkg/apis/metrics"
|
||||||
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NodeRes struct {
|
type NodeRes struct {
|
||||||
|
@ -30,6 +38,97 @@ type NodeExtendRes struct {
|
||||||
PodStatus v1.PodPhase `json:"podStatus"`
|
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 查询节点列表
|
// @Summary 查询节点列表
|
||||||
// @Description 查询节点列表
|
// @Description 查询节点列表
|
||||||
// @Tags node
|
// @Tags node
|
||||||
|
@ -40,12 +139,132 @@ type NodeExtendRes struct {
|
||||||
// @Failure 500
|
// @Failure 500
|
||||||
// @Router /api/v1/node/list/{clusterName} [get]
|
// @Router /api/v1/node/list/{clusterName} [get]
|
||||||
func ListNode(c *gin.Context) {
|
func ListNode(c *gin.Context) {
|
||||||
clusterName := c.Param("clusterName")
|
clusterName := c.Query("clusterName")
|
||||||
result := SearchObject(nodeConst, clusterName, "", "")
|
pageNum := c.Query("pageNum")
|
||||||
raw, _ := result.Raw()
|
pageSize := c.Query("pageSize")
|
||||||
|
queryType := c.Query("queryType")
|
||||||
|
nodeResult := SearchObject(nodeConst, clusterName, "", "")
|
||||||
|
raw, _ := nodeResult.Raw()
|
||||||
var nodeRes NodeRes
|
var nodeRes NodeRes
|
||||||
json.Unmarshal(raw, &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名称查询节点信息
|
// @Summary 根据集群名称 命名空间 pod名称查询节点信息
|
||||||
|
@ -60,9 +279,9 @@ func ListNode(c *gin.Context) {
|
||||||
// @Failure 500
|
// @Failure 500
|
||||||
// @Router /api/v1/node/detail/{clusterName}/{namespace}/{podName} [get]
|
// @Router /api/v1/node/detail/{clusterName}/{namespace}/{podName} [get]
|
||||||
func queryNodeInfo(c *gin.Context) {
|
func queryNodeInfo(c *gin.Context) {
|
||||||
clusterName := c.Param("clusterName")
|
clusterName := c.Query("clusterName")
|
||||||
namespace := c.Param("namespace")
|
namespace := c.Query("namespace")
|
||||||
podName := c.Param("podName")
|
podName := c.Query("podName")
|
||||||
var result NodeExtendRes
|
var result NodeExtendRes
|
||||||
// 查询节点信息
|
// 查询节点信息
|
||||||
nodeRes := SearchObject(nodeConst, clusterName, "", "")
|
nodeRes := SearchObject(nodeConst, clusterName, "", "")
|
||||||
|
@ -95,7 +314,7 @@ func queryNodeInfo(c *gin.Context) {
|
||||||
// @Failure 500
|
// @Failure 500
|
||||||
// @Router /api/v1/node/edge/{clusterName} [get]
|
// @Router /api/v1/node/edge/{clusterName} [get]
|
||||||
func ListEdgeNode(c *gin.Context) {
|
func ListEdgeNode(c *gin.Context) {
|
||||||
clusterName := c.Param("clusterName")
|
clusterName := c.Query("clusterName")
|
||||||
result := SearchObject(nodeConst, clusterName, "", "")
|
result := SearchObject(nodeConst, clusterName, "", "")
|
||||||
raw, _ := result.Raw()
|
raw, _ := result.Raw()
|
||||||
var nodeRes NodeRes
|
var nodeRes NodeRes
|
||||||
|
@ -120,10 +339,111 @@ func ListEdgeNode(c *gin.Context) {
|
||||||
// @Failure 500
|
// @Failure 500
|
||||||
// @Router /api/v1/node/metrics/{clusterName} [get]
|
// @Router /api/v1/node/metrics/{clusterName} [get]
|
||||||
func ListNodeMetrics(c *gin.Context) {
|
func ListNodeMetrics(c *gin.Context) {
|
||||||
clusterName := c.Param("clusterName")
|
clusterName := c.Query("clusterName")
|
||||||
result := SearchObject(nodeMetrics, clusterName, "", "")
|
result := SearchObject(nodeMetrics, clusterName, "", "")
|
||||||
raw, _ := result.Raw()
|
raw, _ := result.Raw()
|
||||||
var metricsRes MetricsRes
|
var metricsRes MetricsRes
|
||||||
json.Unmarshal(raw, &metricsRes)
|
json.Unmarshal(raw, &metricsRes)
|
||||||
Response(c, http.StatusOK, "success", metricsRes.Items)
|
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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/bitly/go-simplejson"
|
"github.com/bitly/go-simplejson"
|
||||||
"github.com/opensearch-project/opensearch-go/v2/opensearchapi"
|
"github.com/opensearch-project/opensearch-go/v2/opensearchapi"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -13,26 +15,77 @@ import (
|
||||||
const (
|
const (
|
||||||
clusterProxy = "/apis/cluster.karmada.io/v1alpha1/clusters/%s/proxy"
|
clusterProxy = "/apis/cluster.karmada.io/v1alpha1/clusters/%s/proxy"
|
||||||
|
|
||||||
nodeConst = "node"
|
nodeConst = "node"
|
||||||
deploymentConst = "deployment"
|
detailHPAConst = "hpa"
|
||||||
podDetailConst = "podDetail"
|
deploymentConst = "deployment"
|
||||||
podListConst = "podList"
|
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"
|
hpaListUrl = "/apis/autoscaling/v1/namespaces/%s/horizontalpodautoscalers"
|
||||||
pvConst = "pv"
|
detailHpaUrl = "/apis/autoscaling/v1/namespaces/%s/horizontalpodautoscalers/%s"
|
||||||
podMetrics = "podMetrics"
|
deploymentListUrl = "/apis/apps/v1/namespaces/%s/deployments"
|
||||||
nodeMetrics = "nodeMetrics"
|
daemonSetUrl = "/apis/apps/v1/namespaces/%s/daemonsets/%s"
|
||||||
crdConst = "crd"
|
statefulSetUrl = "/apis/apps/v1/namespaces/%s/statefulsets/%s"
|
||||||
|
statefulSetListUrl = "/apis/apps/v1/namespaces/%s/statefulsets"
|
||||||
pvUrl = "/api/v1/persistentvolumes"
|
daemonSetListUrl = "/apis/apps/v1/namespaces/%s/daemonsets"
|
||||||
pvcUrl = "/api/v1/namespaces/%s/persistentvolumeclaims"
|
replicaSetUrl = "/apis/apps/v1/namespaces/%s/replicasets"
|
||||||
nodeUrl = "/api/v1/nodes"
|
secretUrl = "/api/v1/namespaces/%s/secrets"
|
||||||
deploymentUrl = "/apis/apps/v1/namespaces/%s/deployments"
|
configMapUrl = "/api/v1/namespaces/%s/configmaps"
|
||||||
podListUrl = "/api/v1/namespaces/%s/pods"
|
scUrl = "/apis/storage.k8s.io/v1/storageclasses"
|
||||||
podDetailUrl = "/api/v1/namespaces/%s/pods/%s"
|
pvUrl = "/api/v1/persistentvolumes"
|
||||||
podMetricsUrl = "/apis/metrics.k8s.io/v1beta1/namespaces/%s/pods/%s"
|
pvcUrl = "/api/v1/persistentvolumeclaims"
|
||||||
nodeMetricsUrl = "/apis/metrics.k8s.io/v1beta1/nodes"
|
detailPvcUrl = "/api/v1/namespaces/%s/persistentvolumeclaims/%s"
|
||||||
crdUrl = "/apis/apiextensions.k8s.io/v1/customresourcedefinitions"
|
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 {
|
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":
|
case "node":
|
||||||
url.WriteString(nodeUrl)
|
url.WriteString(nodeUrl)
|
||||||
case "deployment":
|
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":
|
case "podList":
|
||||||
url.WriteString(fmt.Sprintf(podListUrl, namespace))
|
url.WriteString(fmt.Sprintf(podListUrl, namespace))
|
||||||
case "podDetail":
|
case "podDetail":
|
||||||
|
@ -54,10 +113,57 @@ func JointUrl(objectType string, clusterName string, namespace string, objectNam
|
||||||
case "pv":
|
case "pv":
|
||||||
url.WriteString(pvUrl)
|
url.WriteString(pvUrl)
|
||||||
case "pvc":
|
case "pvc":
|
||||||
url.WriteString(fmt.Sprintf(pvcUrl, namespace))
|
url.WriteString(pvcUrl)
|
||||||
case "crd":
|
case "crd":
|
||||||
url.WriteString(crdUrl)
|
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()
|
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())
|
return KarmadaClient.SearchV1alpha1().RESTClient().Get().AbsPath(url).Do(context.TODO())
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateObject(objectType string, clusterName string, namespace string, object interface{}) rest.Result {
|
func UpdateObject(objectType string, clusterName string, namespace string, objectName string, object interface{}) rest.Result {
|
||||||
url := JointUrl(objectType, clusterName, namespace, "")
|
url := JointUrl(objectType, clusterName, namespace, objectName)
|
||||||
return KarmadaClient.SearchV1alpha1().RESTClient().Post().Body(object).AbsPath(url).Do(context.TODO())
|
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 {
|
func PostObject(objectType string, clusterName string, namespace string, objectName string, object interface{}) rest.Result {
|
||||||
url := JointUrl(objectType, clusterName, namespace, "")
|
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())
|
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 {
|
func GetDeployFromOS(namespaceName string, deploymentName string, clusterName string) *simplejson.Json {
|
||||||
|
|
||||||
var content *strings.Reader
|
var content *strings.Reader
|
||||||
|
|
246
app/overview.go
246
app/overview.go
|
@ -6,6 +6,43 @@ import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"net/http"
|
"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 {
|
type Overview struct {
|
||||||
|
@ -14,6 +51,215 @@ type Overview struct {
|
||||||
Pod int32 `json:"podListConst"`
|
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) {
|
func ResourceCount(c *gin.Context) {
|
||||||
overview := &Overview{}
|
overview := &Overview{}
|
||||||
//纳管资源域、纳管集群总计、容器创建数量 资源域
|
//纳管资源域、纳管集群总计、容器创建数量 资源域
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package app
|
package app
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
type Page[T any] struct {
|
type Page[T any] struct {
|
||||||
// 当前页码
|
// 当前页码
|
||||||
PageNum int64 `json:"pageNum"`
|
PageNum int64 `json:"pageNum"`
|
||||||
|
@ -14,7 +16,9 @@ type Page[T any] struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paginator 生成新的分页数据对象
|
// 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 (
|
var (
|
||||||
pageStart int64
|
pageStart int64
|
||||||
pageEnd int64
|
pageEnd int64
|
||||||
|
|
306
app/pod.go
306
app/pod.go
|
@ -5,6 +5,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
|
v12 "k8s.io/api/apps/v1"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/metrics/pkg/apis/metrics"
|
"k8s.io/metrics/pkg/apis/metrics"
|
||||||
|
@ -12,11 +13,22 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"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 {
|
type Pod struct {
|
||||||
PageNum int64 `json:"page_num"`
|
PageNum string `json:"page_num"`
|
||||||
PageSize int64 `json:"page_size"`
|
PageSize string `json:"page_size"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
ClusterName string `json:"cluster_name"`
|
ClusterName string `json:"cluster_name"`
|
||||||
DomainName string `json:"domain_name"`
|
DomainName string `json:"domain_name"`
|
||||||
|
@ -34,7 +46,7 @@ type Pod struct {
|
||||||
TemplateId string `json:"template_id"`
|
TemplateId string `json:"template_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PodRes struct {
|
type PodObject struct {
|
||||||
Kind string `json:"kind"`
|
Kind string `json:"kind"`
|
||||||
ApiVersion string `json:"apiVersion"`
|
ApiVersion string `json:"apiVersion"`
|
||||||
Metadata string `json:"metadata"`
|
Metadata string `json:"metadata"`
|
||||||
|
@ -42,13 +54,27 @@ type PodRes struct {
|
||||||
Items []v1.Pod `json:"items"`
|
Items []v1.Pod `json:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//type MetricsRes struct {
|
type DeploymentPods struct {
|
||||||
// Kind string `json:"kind"`
|
Replicas int32 `json:"replicas"`
|
||||||
// ApiVersion string `json:"apiVersion"`
|
AvailableReplicas int32 `json:"availableReplicas"`
|
||||||
// Metadata string `json:"metadata"`
|
Pods []v1.Pod `json:"pods"`
|
||||||
// ResourceVersion string `json:"resourceVersion"`
|
}
|
||||||
// Items []metrics.PodMetrics `json:"items"`
|
|
||||||
//}
|
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使用率
|
// PodMetrics 根据集群名称、命名空间和pod名称查询pod使用率
|
||||||
// @Summary 根据集群名称、命名空间和pod名称查询pod使用率
|
// @Summary 根据集群名称、命名空间和pod名称查询pod使用率
|
||||||
|
@ -63,9 +89,9 @@ type PodRes struct {
|
||||||
// @Failure 500
|
// @Failure 500
|
||||||
// @Router /api/v1/pod/metrics/{clusterName}/{namespace}/{name} [get]
|
// @Router /api/v1/pod/metrics/{clusterName}/{namespace}/{name} [get]
|
||||||
func PodMetrics(c *gin.Context) {
|
func PodMetrics(c *gin.Context) {
|
||||||
clusterName := c.Param("clusterName")
|
clusterName := c.Query("clusterName")
|
||||||
namespace := c.Param("namespace")
|
namespace := c.Query("namespace")
|
||||||
name := c.Param("name")
|
name := c.Query("name")
|
||||||
result := SearchObject(podMetrics, clusterName, namespace, name)
|
result := SearchObject(podMetrics, clusterName, namespace, name)
|
||||||
var metrics metrics.PodMetrics
|
var metrics metrics.PodMetrics
|
||||||
raw, _ := result.Raw()
|
raw, _ := result.Raw()
|
||||||
|
@ -94,12 +120,13 @@ func PodMetrics(c *gin.Context) {
|
||||||
// @Success 200
|
// @Success 200
|
||||||
// @Failure 500
|
// @Failure 500
|
||||||
// @Router /api/v1/pod/detail/{clusterName}/{namespace}/{name} [get]
|
// @Router /api/v1/pod/detail/{clusterName}/{namespace}/{name} [get]
|
||||||
|
// PodDetail 根据指定集群查询Pod详情
|
||||||
func PodDetail(c *gin.Context) {
|
func PodDetail(c *gin.Context) {
|
||||||
clusterName := c.Param("clusterName")
|
clusterName := c.Query("clusterName")
|
||||||
namespace := c.Param("namespace")
|
namespace := c.Query("namespace")
|
||||||
name := c.Param("name")
|
name := c.Query("name")
|
||||||
result := SearchObject(podListConst, clusterName, namespace, "")
|
result := SearchObject(podListConst, clusterName, namespace, "")
|
||||||
var podRes PodRes
|
var podRes PodObject
|
||||||
raw, _ := result.Raw()
|
raw, _ := result.Raw()
|
||||||
json.Unmarshal(raw, &podRes)
|
json.Unmarshal(raw, &podRes)
|
||||||
for _, pod := range podRes.Items {
|
for _, pod := range podRes.Items {
|
||||||
|
@ -111,28 +138,46 @@ func PodDetail(c *gin.Context) {
|
||||||
Response(c, http.StatusOK, "success", nil)
|
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列表
|
// ListPod 根据指定集群查询Pod列表
|
||||||
// @Summary 根据指定集群查询Pod列表
|
// @Summary 根据指定集群查询Pod列表
|
||||||
// @Description 根据指定集群查询Pod列表
|
// @Description 根据指定集群查询Pod列表
|
||||||
// @Tags pod
|
// @Tags pod
|
||||||
// @accept json
|
// @accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param param body Pod true "json"
|
|
||||||
// @Success 200
|
// @Success 200
|
||||||
// @Failure 500
|
// @Failure 500
|
||||||
// @Router /api/v1/pod/list [get]
|
// @Router /api/v1/pod/list [get]
|
||||||
func ListPod(c *gin.Context) {
|
func ListPod(c *gin.Context) {
|
||||||
var param Pod
|
clusterName := c.Query("clusterName")
|
||||||
if err := c.BindJSON(¶m); err != nil {
|
namespace := c.Query("namespace")
|
||||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
pageNum := c.Query("pageNum")
|
||||||
return
|
pageSize := c.Query("pageSize")
|
||||||
}
|
result := SearchObject(podListConst, clusterName, namespace, "")
|
||||||
result := SearchObject(podListConst, param.ClusterName, param.Namespace, "")
|
|
||||||
if result.Error() != nil {
|
if result.Error() != nil {
|
||||||
Response(c, http.StatusInternalServerError, "failed", result.Error())
|
Response(c, http.StatusInternalServerError, "failed", result.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var podRes PodRes
|
var podRes PodObject
|
||||||
raw, _ := result.Raw()
|
raw, _ := result.Raw()
|
||||||
json.Unmarshal(raw, &podRes)
|
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)
|
return podRes.Items[i].CreationTimestamp.Time.After(podRes.Items[j].CreationTimestamp.Time)
|
||||||
})
|
})
|
||||||
page.List = podRes.Items
|
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)
|
Response(c, http.StatusOK, "success", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,20 +286,30 @@ func CreatePod(c *gin.Context) {
|
||||||
// @accept json
|
// @accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param namespace path string true "命名空间名"
|
// @Param namespace path string true "命名空间名"
|
||||||
//@param name path string true "Pod名"
|
// @param name path string true "Pod名"
|
||||||
// @Success 200
|
// @Success 200
|
||||||
// @Failure 400
|
// @Failure 400
|
||||||
// @Router /api/v1/pod/delete/{namespace}/{name} [delete]
|
// @Router /api/v1/pod/delete/{namespace}/{name} [delete]
|
||||||
func DeletePod(c *gin.Context) {
|
func DeletePod(c *gin.Context) {
|
||||||
|
clusterName := c.Param("clusterName")
|
||||||
namespace := c.Param("namespace")
|
namespace := c.Param("namespace")
|
||||||
name := c.Param("name")
|
name := c.Param("name")
|
||||||
err := ClientSet.CoreV1().Pods(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})
|
label := c.Param("label")
|
||||||
if err != nil {
|
if strings.EqualFold(label, "jcce") {
|
||||||
Response(c, http.StatusInternalServerError, "delete podListConst failed", err)
|
err := ClientSet.CoreV1().Pods(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})
|
||||||
return
|
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)
|
Response(c, http.StatusOK, "success", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,6 +349,90 @@ func UpdatePod(c *gin.Context) {
|
||||||
Response(c, http.StatusOK, "success", podResult)
|
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 获取容器组详情
|
// GetPodDetail 获取容器组详情
|
||||||
// @Summary 获取容器组详情
|
// @Summary 获取容器组详情
|
||||||
// @Description 获取容器组详情
|
// @Description 获取容器组详情
|
||||||
|
@ -269,21 +444,60 @@ func UpdatePod(c *gin.Context) {
|
||||||
// @Failure 400
|
// @Failure 400
|
||||||
// @Router /api/v1/pod/detail [put]
|
// @Router /api/v1/pod/detail [put]
|
||||||
func GetPodDetail(c *gin.Context) {
|
func GetPodDetail(c *gin.Context) {
|
||||||
var param Pod
|
clusterName := c.Query("clusterName")
|
||||||
if err := c.BindJSON(¶m); err != nil {
|
namespace := c.Query("namespace")
|
||||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
name := c.Query("name")
|
||||||
return
|
rsRes := SearchObject(detailPodConst, clusterName, namespace, name)
|
||||||
}
|
raw, _ := rsRes.Raw()
|
||||||
podResult, err := ClientSet.CoreV1().Pods(param.Namespace).Get(context.TODO(), param.Name, metav1.GetOptions{})
|
var pod v1.Pod
|
||||||
if err != nil {
|
json.Unmarshal(raw, &pod)
|
||||||
Response(c, http.StatusInternalServerError, "query podListConst failed", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err_ := AddTypeMetaToObject(podResult)
|
err_ := AddTypeMetaToObject(&pod)
|
||||||
if err_ != nil {
|
if err_ != nil {
|
||||||
log.Println(err_)
|
log.Println(err_)
|
||||||
}
|
}
|
||||||
|
Response(c, http.StatusOK, "success", pod)
|
||||||
Response(c, http.StatusOK, "success", podResult)
|
}
|
||||||
|
|
||||||
|
// @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"
|
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -119,9 +118,11 @@ func CreatePropagationPolicies(propagationPolicy PropagationPolicy) error {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
switch propagationPolicy.Kind {
|
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"
|
policy.Spec.ResourceSelectors[0].APIVersion = "v1"
|
||||||
case "DeploymentParam":
|
case "Deployment", "StatefulSet", "DaemonSet":
|
||||||
policy.Spec.ResourceSelectors[0].APIVersion = "apps/v1"
|
policy.Spec.ResourceSelectors[0].APIVersion = "apps/v1"
|
||||||
}
|
}
|
||||||
_, err := KarmadaClient.PolicyV1alpha1().PropagationPolicies(propagationPolicy.Namespace).Create(context.TODO(), policy, v1.CreateOptions{})
|
_, 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]
|
// @Router /api/v1/propagationPolicy/list [get]
|
||||||
func ListPropagationPolicies(c *gin.Context) {
|
func ListPropagationPolicies(c *gin.Context) {
|
||||||
|
|
||||||
labelKey, _ := c.GetQuery("label_key")
|
labelKey := c.Query("label_key")
|
||||||
labelValue, _ := c.GetQuery("label_value")
|
labelValue := c.Query("label_value")
|
||||||
policyName, _ := c.GetQuery("policy_name")
|
policyName := c.Query("policy_name")
|
||||||
|
|
||||||
opts := v1.ListOptions{
|
opts := v1.ListOptions{
|
||||||
TypeMeta: v1.TypeMeta{},
|
TypeMeta: v1.TypeMeta{},
|
||||||
|
@ -239,18 +240,21 @@ func ListPropagationPolicies(c *gin.Context) {
|
||||||
total := len(proPolicyList)
|
total := len(proPolicyList)
|
||||||
page := &Page[PropagationPolicy]{}
|
page := &Page[PropagationPolicy]{}
|
||||||
page.List = proPolicyList
|
page.List = proPolicyList
|
||||||
pageNum, _ := c.GetQuery("pageNum")
|
pageNum := c.Query("pageNum")
|
||||||
pageSize, _ := c.GetQuery("pageSize")
|
pageSize := c.Query("pageSize")
|
||||||
num, _ := strconv.ParseInt(pageNum, 10, 64)
|
data := Paginator(page, int64(total), pageNum, pageSize)
|
||||||
size, _ := strconv.ParseInt(pageSize, 10, 64)
|
|
||||||
data := Paginator(page, int64(total), num, size)
|
|
||||||
Response(c, http.StatusOK, "success", data)
|
Response(c, http.StatusOK, "success", data)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdatePropagationPolicies 更新集群分发策略
|
// UpdatePropagationPolicies 更新集群分发策略
|
||||||
func UpdatePropagationPolicies(c *gin.Context) {
|
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)
|
Response(c, http.StatusOK, "success", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ package app
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type PropagationPolicyTemplate struct {
|
type PropagationPolicyTemplate struct {
|
||||||
|
@ -79,7 +78,7 @@ func DeletePropagationPolicyTemplate(c *gin.Context) {
|
||||||
// @Router /api/v1/propagationPolicyTemplate/list [get]
|
// @Router /api/v1/propagationPolicyTemplate/list [get]
|
||||||
func ListPropagationPolicyTemplate(c *gin.Context) {
|
func ListPropagationPolicyTemplate(c *gin.Context) {
|
||||||
|
|
||||||
pptName, _ := c.GetQuery("template_name")
|
pptName := c.Query("template_name")
|
||||||
|
|
||||||
PptList := make([]PropagationPolicyTemplate, 0)
|
PptList := make([]PropagationPolicyTemplate, 0)
|
||||||
rows, err := DB.Query(`SELECT * FROM propagation_policy_template ppt where ppt.template_name like ?`, "%"+pptName+"%")
|
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)
|
total := len(PptList)
|
||||||
page := &Page[PropagationPolicyTemplate]{}
|
page := &Page[PropagationPolicyTemplate]{}
|
||||||
page.List = PptList
|
page.List = PptList
|
||||||
pageNum, _ := c.GetQuery("pageNum")
|
pageNum := c.Query("pageNum")
|
||||||
pageSize, _ := c.GetQuery("pageSize")
|
pageSize := c.Query("pageSize")
|
||||||
num, _ := strconv.ParseInt(pageNum, 10, 64)
|
data := Paginator(page, int64(total), pageNum, pageSize)
|
||||||
size, _ := strconv.ParseInt(pageSize, 10, 64)
|
|
||||||
data := Paginator(page, int64(total), num, size)
|
|
||||||
Response(c, http.StatusOK, "success", data)
|
Response(c, http.StatusOK, "success", data)
|
||||||
//Response(c, http.StatusOK, "success", PptList)
|
//Response(c, http.StatusOK, "success", PptList)
|
||||||
|
|
||||||
|
|
101
app/router.go
101
app/router.go
|
@ -12,6 +12,7 @@ import (
|
||||||
swaggerFiles "github.com/swaggo/files"
|
swaggerFiles "github.com/swaggo/files"
|
||||||
ginSwagger "github.com/swaggo/gin-swagger"
|
ginSwagger "github.com/swaggo/gin-swagger"
|
||||||
_ "jcc-schedule/docs"
|
_ "jcc-schedule/docs"
|
||||||
|
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
kubeclient "k8s.io/client-go/kubernetes"
|
kubeclient "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
|
@ -25,6 +26,7 @@ var KarmadaConfig karmadactl.KarmadaConfig
|
||||||
var ControlPlaneRestConfig *rest.Config
|
var ControlPlaneRestConfig *rest.Config
|
||||||
var ClientSet *kubeclient.Clientset
|
var ClientSet *kubeclient.Clientset
|
||||||
var OpenSearchClient *opensearch.Client
|
var OpenSearchClient *opensearch.Client
|
||||||
|
var CrDClient *clientset.Clientset
|
||||||
|
|
||||||
var ConfigNacos = GetNacosConfig()
|
var ConfigNacos = GetNacosConfig()
|
||||||
|
|
||||||
|
@ -47,7 +49,7 @@ func InitRouter() *gin.Engine {
|
||||||
ControlPlaneRestConfig, _ = KarmadaConfig.GetRestConfig("", dir+"/karmadaConfig/karmada-host")
|
ControlPlaneRestConfig, _ = KarmadaConfig.GetRestConfig("", dir+"/karmadaConfig/karmada-host")
|
||||||
KarmadaClient = karmadaclientset.NewForConfigOrDie(ControlPlaneRestConfig)
|
KarmadaClient = karmadaclientset.NewForConfigOrDie(ControlPlaneRestConfig)
|
||||||
ClientSet, _ = utils.NewClientSet(ControlPlaneRestConfig)
|
ClientSet, _ = utils.NewClientSet(ControlPlaneRestConfig)
|
||||||
|
CrDClient, _ = utils.NewCRDsClient(ControlPlaneRestConfig)
|
||||||
// 初始化OpenSearch客户端
|
// 初始化OpenSearch客户端
|
||||||
OpenSearchClient, _ = opensearch.NewClient(opensearch.Config{
|
OpenSearchClient, _ = opensearch.NewClient(opensearch.Config{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
|
@ -79,10 +81,17 @@ func InitRouter() *gin.Engine {
|
||||||
//Namespace
|
//Namespace
|
||||||
namespace := v1.Group("namespace")
|
namespace := v1.Group("namespace")
|
||||||
namespace.GET("/list", ListNamespace)
|
namespace.GET("/list", ListNamespace)
|
||||||
|
namespace.GET("/isExist", IsExistNamespace)
|
||||||
|
namespace.GET("/list/name", ListName)
|
||||||
|
namespace.GET("/listFromCluster", ListNamespaceFromCluster)
|
||||||
namespace.GET("/describe", DescribeNamespace)
|
namespace.GET("/describe", DescribeNamespace)
|
||||||
|
namespace.GET("/detail", DetailNamespace)
|
||||||
namespace.POST("/create", CreateNamespace)
|
namespace.POST("/create", CreateNamespace)
|
||||||
namespace.POST("/delete", DeleteNamespace)
|
namespace.DELETE("/delete/:clusterName/:name/:label", DeleteNamespace)
|
||||||
namespace.POST("/update", UpdateNamespace)
|
namespace.PUT("/update", UpdateNamespace)
|
||||||
|
namespace.GET("/getBatchMetrics", GetBatchNamespaceMetrics)
|
||||||
|
namespace.GET("/getMetrics", GetNamespaceMetrics)
|
||||||
|
namespace.GET("/resources", GetNamespaceResources)
|
||||||
|
|
||||||
//Domain
|
//Domain
|
||||||
domain := v1.Group("domain")
|
domain := v1.Group("domain")
|
||||||
|
@ -94,12 +103,18 @@ func InitRouter() *gin.Engine {
|
||||||
//Pod
|
//Pod
|
||||||
pod := v1.Group("pod")
|
pod := v1.Group("pod")
|
||||||
pod.GET("/list", ListPod)
|
pod.GET("/list", ListPod)
|
||||||
pod.GET("/detail/:clusterName/:namespace/:name", PodDetail)
|
pod.GET("/all", ALLPod)
|
||||||
pod.GET("/metrics/:clusterName/:namespace/:name", PodMetrics)
|
pod.GET("/isExist", IsExist)
|
||||||
|
pod.GET("/detail", PodDetail)
|
||||||
|
pod.GET("/cpuAndMemory", PodMetrics)
|
||||||
pod.POST("/create", CreatePod)
|
pod.POST("/create", CreatePod)
|
||||||
pod.DELETE("/delete/:namespace/:name", DeletePod)
|
pod.DELETE("/delete/:clusterName/:namespace/:name/:label", DeletePod)
|
||||||
pod.PUT("/updatePod", UpdatePod)
|
pod.PUT("/updatePod", UpdatePod)
|
||||||
pod.PUT("/detail", GetPodDetail)
|
pod.PUT("/detail", GetPodDetail)
|
||||||
|
pod.GET("/listFromDeployment", ListPodFromDeployment)
|
||||||
|
pod.GET("/listFromNode", ListPodFromNode)
|
||||||
|
pod.GET("/pod/metrics", ListPodFromNode)
|
||||||
|
pod.GET("/metrics", GetMetrics)
|
||||||
|
|
||||||
//Cluster
|
//Cluster
|
||||||
cluster := v1.Group("cluster")
|
cluster := v1.Group("cluster")
|
||||||
|
@ -117,37 +132,86 @@ func InitRouter() *gin.Engine {
|
||||||
|
|
||||||
//Node
|
//Node
|
||||||
node := v1.Group("node")
|
node := v1.Group("node")
|
||||||
node.GET("/list/:clusterName", ListNode)
|
node.PUT("/update", UpdateNode)
|
||||||
node.GET("/edge/:clusterName", ListEdgeNode)
|
node.GET("/list", ListNode)
|
||||||
node.GET("/metrics/:clusterName", ListNodeMetrics)
|
node.GET("/count", NodeCount)
|
||||||
node.GET("/detail/:clusterName/:namespace/:podName", queryNodeInfo)
|
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
|
//DeploymentParam
|
||||||
deployment := v1.Group("deployment")
|
deployment := v1.Group("deployments")
|
||||||
deployment.POST("/create", CreateDeployment)
|
deployment.POST("/create", CreateDeployment)
|
||||||
deployment.DELETE("/delete/:namespace/:name", DeleteDeployment)
|
deployment.DELETE("/delete/:clusterName/:namespace/:name/:label", DeleteDeployment)
|
||||||
deployment.GET("/list", ListDeployment)
|
deployment.GET("/list", ListDeployment)
|
||||||
|
deployment.GET("/listFromCluster", ListDeploymentFromCluster)
|
||||||
deployment.GET("/describe", DescribeDeployment)
|
deployment.GET("/describe", DescribeDeployment)
|
||||||
|
deployment.GET("/detail", DetailDeployment)
|
||||||
deployment.GET("/listGlobal", ListClusterDeployment)
|
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
|
||||||
storage := v1.Group("storage")
|
storage := v1.Group("storage")
|
||||||
storage.POST("/pv", CreatePV)
|
storage.POST("/pv", CreatePV)
|
||||||
storage.POST("/pvc", CreatePVC)
|
storage.POST("/pvc", CreatePVC)
|
||||||
storage.GET("/pv/:clusterName", ListPV)
|
storage.PUT("/pvc", UpdatePVC)
|
||||||
storage.GET("/pvc/:clusterName/:namespace", ListPVC)
|
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
|
// storage
|
||||||
crd := v1.Group("crd")
|
crd := v1.Group("crd")
|
||||||
crd.GET("/list/:clusterName", ListCRD)
|
crd.GET("/list/:clusterName", ListCRD)
|
||||||
|
crd.GET("/detail/:clusterName/:namespace/:kind", DetailCRD)
|
||||||
|
crd.GET("/create", CreateCRD)
|
||||||
|
|
||||||
// configMap
|
// configMap
|
||||||
configMap := v1.Group("configMap")
|
configMap := v1.Group("config")
|
||||||
configMap.POST("/create", CreateConfigMap)
|
configMap.POST("/configMap/create", CreateConfigMap)
|
||||||
|
configMap.GET("/secret/list", ListSecret)
|
||||||
|
configMap.GET("/configMap/list", ListConfigMap)
|
||||||
|
|
||||||
// service
|
// service
|
||||||
service := v1.Group("service")
|
service := v1.Group("service")
|
||||||
service.POST("/create", CreateService)
|
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
|
||||||
propagationPolicyTemplate := v1.Group("propagationPolicyTemplate")
|
propagationPolicyTemplate := v1.Group("propagationPolicyTemplate")
|
||||||
|
@ -171,6 +235,11 @@ func InitRouter() *gin.Engine {
|
||||||
//Overview
|
//Overview
|
||||||
overview := v1.Group("resource")
|
overview := v1.Group("resource")
|
||||||
overview.GET("/count", ResourceCount)
|
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 (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ServiceParam struct {
|
type ServiceParam struct {
|
||||||
|
@ -13,44 +16,21 @@ type ServiceParam struct {
|
||||||
TemplateId string `json:"templateId"`
|
TemplateId string `json:"templateId"`
|
||||||
ClusterName []string `json:"clusterName"`
|
ClusterName []string `json:"clusterName"`
|
||||||
}
|
}
|
||||||
type ServiceParam1 struct {
|
|
||||||
Service JSONData111 `json:"service"`
|
type ServiceObject struct {
|
||||||
TemplateId string `json:"templateId"`
|
Kind string `json:"kind"`
|
||||||
ClusterName []string `json:"clusterName"`
|
ApiVersion string `json:"apiVersion"`
|
||||||
}
|
Metadata string `json:"metadata"`
|
||||||
type JSONData111 struct {
|
ResourceVersion string `json:"resourceVersion"`
|
||||||
APIVersion string `json:"apiVersion"`
|
Items []v1.Service `json:"items"`
|
||||||
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"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateService 创建服务
|
||||||
// @Summary 创建服务
|
// @Summary 创建服务
|
||||||
// @Description 创建服务
|
// @Description 创建服务
|
||||||
// @Tags service
|
// @Tags service
|
||||||
// @accept json
|
// @accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param param body ServiceParam1 true "json"
|
|
||||||
// @Success 200
|
// @Success 200
|
||||||
// @Failure 500
|
// @Failure 500
|
||||||
// @Router /api/v1/service/create [post]
|
// @Router /api/v1/service/create [post]
|
||||||
|
@ -60,15 +40,135 @@ func CreateService(c *gin.Context) {
|
||||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||||
return
|
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,
|
ClusterName: sRequest.ClusterName,
|
||||||
TemplateId: sRequest.TemplateId,
|
TemplateId: sRequest.TemplateId,
|
||||||
ResourceName: sRequest.Service.Name,
|
ResourceName: sRequest.Service.Name,
|
||||||
Name: "Service" + sRequest.Service.Namespace + sRequest.Service.Name,
|
Name: "service" + "." + sRequest.Service.Namespace + "." + sRequest.Service.Name,
|
||||||
Namespace: sRequest.Service.Namespace,
|
Namespace: sRequest.Service.Namespace,
|
||||||
Kind: "Service",
|
Kind: "Service",
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
Response(c, http.StatusBadRequest, "create propagationPolicy error.", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
Response(c, http.StatusOK, "success", nil)
|
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"
|
"encoding/json"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/api/storage/v1beta1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PVRes struct {
|
type PVRes struct {
|
||||||
|
@ -17,7 +21,7 @@ type PVRes struct {
|
||||||
Items []v1.PersistentVolume `json:"items"`
|
Items []v1.PersistentVolume `json:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PVCRes struct {
|
type PVCObject struct {
|
||||||
Kind string `json:"kind"`
|
Kind string `json:"kind"`
|
||||||
ApiVersion string `json:"apiVersion"`
|
ApiVersion string `json:"apiVersion"`
|
||||||
Metadata string `json:"metadata"`
|
Metadata string `json:"metadata"`
|
||||||
|
@ -25,6 +29,14 @@ type PVCRes struct {
|
||||||
Items []v1.PersistentVolumeClaim `json:"items"`
|
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 {
|
type PersistentVolume struct {
|
||||||
TemplateId string `json:"templateId"`
|
TemplateId string `json:"templateId"`
|
||||||
ClusterName []string `json:"clusterName"`
|
ClusterName []string `json:"clusterName"`
|
||||||
|
@ -85,6 +97,7 @@ type PersistentVolumeClaim struct {
|
||||||
PersistentVolumeClaim v1.PersistentVolumeClaim `json:"persistentVolumeClaim"`
|
PersistentVolumeClaim v1.PersistentVolumeClaim `json:"persistentVolumeClaim"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreatePV 创建PV
|
||||||
type PersistentVolumeClaim1 struct {
|
type PersistentVolumeClaim1 struct {
|
||||||
TemplateId string `json:"templateId"`
|
TemplateId string `json:"templateId"`
|
||||||
ClusterName []string `json:"clusterName"`
|
ClusterName []string `json:"clusterName"`
|
||||||
|
@ -116,12 +129,102 @@ func CreatePV(c *gin.Context) {
|
||||||
ClusterName: pvRequest.ClusterName,
|
ClusterName: pvRequest.ClusterName,
|
||||||
TemplateId: pvRequest.TemplateId,
|
TemplateId: pvRequest.TemplateId,
|
||||||
ResourceName: pvRequest.PersistentVolume.Name,
|
ResourceName: pvRequest.PersistentVolume.Name,
|
||||||
Name: "PersistentVolume" + pvRequest.PersistentVolume.Name,
|
Name: "persistentVolume" + pvRequest.PersistentVolume.Name,
|
||||||
Kind: "PersistentVolume",
|
Kind: "PersistentVolume",
|
||||||
})
|
})
|
||||||
Response(c, http.StatusOK, "success", 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
|
// @Summary 创建PVC
|
||||||
// @Description 创建PVC
|
// @Description 创建PVC
|
||||||
// @Tags storage
|
// @Tags storage
|
||||||
|
@ -137,9 +240,13 @@ func CreatePVC(c *gin.Context) {
|
||||||
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
Response(c, http.StatusBadRequest, "invalid request params.", "")
|
||||||
return
|
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{})
|
persistentVolume, err := ClientSet.CoreV1().PersistentVolumeClaims(pvcRequest.PersistentVolumeClaim.Namespace).Create(context.TODO(), &pvcRequest.PersistentVolumeClaim, metav1.CreateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Response(c, http.StatusInternalServerError, "create persistentVolume failed", err)
|
Response(c, http.StatusInternalServerError, "Create PersistentVolumeClaim Failed", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 创建调度策略实例
|
// 创建调度策略实例
|
||||||
|
@ -147,7 +254,7 @@ func CreatePVC(c *gin.Context) {
|
||||||
ClusterName: pvcRequest.ClusterName,
|
ClusterName: pvcRequest.ClusterName,
|
||||||
TemplateId: pvcRequest.TemplateId,
|
TemplateId: pvcRequest.TemplateId,
|
||||||
ResourceName: pvcRequest.PersistentVolumeClaim.Name,
|
ResourceName: pvcRequest.PersistentVolumeClaim.Name,
|
||||||
Name: "PersistentVolumeClaim" + pvcRequest.PersistentVolumeClaim.Namespace + pvcRequest.PersistentVolumeClaim.Name,
|
Name: "persistentVolumeClaim" + "." + pvcRequest.PersistentVolumeClaim.Namespace + "." + pvcRequest.PersistentVolumeClaim.Name,
|
||||||
Namespace: pvcRequest.PersistentVolumeClaim.Namespace,
|
Namespace: pvcRequest.PersistentVolumeClaim.Namespace,
|
||||||
Kind: "PersistentVolumeClaim",
|
Kind: "PersistentVolumeClaim",
|
||||||
})
|
})
|
||||||
|
@ -165,7 +272,7 @@ func CreatePVC(c *gin.Context) {
|
||||||
// @Failure 500
|
// @Failure 500
|
||||||
// @Router /api/v1/storage/pv/{clusterName} [get]
|
// @Router /api/v1/storage/pv/{clusterName} [get]
|
||||||
func ListPV(c *gin.Context) {
|
func ListPV(c *gin.Context) {
|
||||||
clusterName := c.Param("clusterName")
|
clusterName := c.Query("clusterName")
|
||||||
result := SearchObject(pvConst, clusterName, "", "")
|
result := SearchObject(pvConst, clusterName, "", "")
|
||||||
if result.Error() != nil {
|
if result.Error() != nil {
|
||||||
Response(c, http.StatusInternalServerError, "failed", result.Error())
|
Response(c, http.StatusInternalServerError, "failed", result.Error())
|
||||||
|
@ -187,17 +294,86 @@ func ListPV(c *gin.Context) {
|
||||||
// @Param namespace path string true "命名空间"
|
// @Param namespace path string true "命名空间"
|
||||||
// @Success 200
|
// @Success 200
|
||||||
// @Failure 500
|
// @Failure 500
|
||||||
// @Router /api/v1/storage/pvc/{clusterName}/{namespace} [get]
|
// @Router /api/v1/storage/pvc [get]
|
||||||
func ListPVC(c *gin.Context) {
|
func ListPVC(c *gin.Context) {
|
||||||
clusterName := c.Param("clusterName")
|
clusterName := c.Query("clusterName")
|
||||||
namespace := c.Param("namespace")
|
pageNum := c.Query("pageNum")
|
||||||
result := SearchObject(pvcConst, clusterName, namespace, "")
|
pageSize := c.Query("pageSize")
|
||||||
|
name := c.Query("name")
|
||||||
|
status := c.Query("status")
|
||||||
|
result := SearchObject(pvcConst, clusterName, "", "")
|
||||||
if result.Error() != nil {
|
if result.Error() != nil {
|
||||||
Response(c, http.StatusInternalServerError, "failed", result.Error())
|
Response(c, http.StatusInternalServerError, "failed", result.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
raw, _ := result.Raw()
|
raw, _ := result.Raw()
|
||||||
var pvcRes PVCRes
|
var pvcResult PVCObject
|
||||||
json.Unmarshal(raw, &pvcRes)
|
json.Unmarshal(raw, &pvcResult)
|
||||||
Response(c, http.StatusOK, "success", pvcRes.Items)
|
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)
|
c.LastResult = string(buf)
|
||||||
return c.LastResult, err
|
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:
|
version:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
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:
|
app.Domain:
|
||||||
properties:
|
properties:
|
||||||
clusters:
|
clusters:
|
||||||
|
@ -172,6 +78,23 @@ definitions:
|
||||||
memory_rate:
|
memory_rate:
|
||||||
type: number
|
type: number
|
||||||
type: object
|
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:
|
app.JSONData:
|
||||||
properties:
|
properties:
|
||||||
apiVersion:
|
apiVersion:
|
||||||
|
@ -243,53 +166,6 @@ definitions:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
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:
|
app.Label:
|
||||||
properties:
|
properties:
|
||||||
create_time:
|
create_time:
|
||||||
|
@ -344,6 +220,8 @@ definitions:
|
||||||
type: integer
|
type: integer
|
||||||
state:
|
state:
|
||||||
type: string
|
type: string
|
||||||
|
templateId:
|
||||||
|
type: string
|
||||||
type: object
|
type: object
|
||||||
app.OverridePolicy:
|
app.OverridePolicy:
|
||||||
properties:
|
properties:
|
||||||
|
@ -411,9 +289,9 @@ definitions:
|
||||||
node:
|
node:
|
||||||
type: string
|
type: string
|
||||||
page_num:
|
page_num:
|
||||||
type: integer
|
type: string
|
||||||
page_size:
|
page_size:
|
||||||
type: integer
|
type: string
|
||||||
ready:
|
ready:
|
||||||
type: string
|
type: string
|
||||||
restarts:
|
restarts:
|
||||||
|
@ -449,15 +327,17 @@ definitions:
|
||||||
memberClusterIp:
|
memberClusterIp:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
app.ServiceParam1:
|
app.RedeployParam:
|
||||||
properties:
|
properties:
|
||||||
clusterName:
|
clusterName:
|
||||||
items:
|
type: string
|
||||||
type: string
|
deploymentName:
|
||||||
type: array
|
type: string
|
||||||
service:
|
namespace:
|
||||||
$ref: '#/definitions/app.JSONData111'
|
type: string
|
||||||
templateId:
|
num:
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
info:
|
info:
|
||||||
|
@ -777,18 +657,33 @@ paths:
|
||||||
summary: 集群删除标签
|
summary: 集群删除标签
|
||||||
tags:
|
tags:
|
||||||
- cluster
|
- cluster
|
||||||
/api/v1/deployment/create:
|
/api/v1/deployment/autoScaling:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: 创建工作负载
|
description: 弹性伸缩
|
||||||
parameters:
|
parameters:
|
||||||
- description: json
|
- description: json
|
||||||
in: body
|
in: body
|
||||||
name: param
|
name: param
|
||||||
required: true
|
required: true
|
||||||
schema:
|
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:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
|
@ -825,6 +720,28 @@ paths:
|
||||||
summary: 删除工作负载
|
summary: 删除工作负载
|
||||||
tags:
|
tags:
|
||||||
- deployment
|
- 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:
|
/api/v1/deployment/describe:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
|
@ -850,6 +767,73 @@ paths:
|
||||||
summary: 查询工作负载列表(所有集群)
|
summary: 查询工作负载列表(所有集群)
|
||||||
tags:
|
tags:
|
||||||
- deployment
|
- 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:
|
/api/v1/deployment/list:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
|
@ -1210,6 +1194,58 @@ paths:
|
||||||
summary: 查询Namespace详情
|
summary: 查询Namespace详情
|
||||||
tags:
|
tags:
|
||||||
- namespace
|
- 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:
|
/api/v1/namespace/list:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
|
@ -1310,6 +1346,58 @@ paths:
|
||||||
summary: 查询边缘节点列表
|
summary: 查询边缘节点列表
|
||||||
tags:
|
tags:
|
||||||
- node
|
- 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}:
|
/api/v1/node/list/{clusterName}:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
|
@ -1374,6 +1462,121 @@ paths:
|
||||||
summary: 查询重写策略列表
|
summary: 查询重写策略列表
|
||||||
tags:
|
tags:
|
||||||
- overridePolicy
|
- 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:
|
/api/v1/pod/create:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
|
@ -1480,13 +1683,6 @@ paths:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: 根据指定集群查询Pod列表
|
description: 根据指定集群查询Pod列表
|
||||||
parameters:
|
|
||||||
- description: json
|
|
||||||
in: body
|
|
||||||
name: param
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/app.Pod'
|
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
|
@ -1497,6 +1693,32 @@ paths:
|
||||||
summary: 根据指定集群查询Pod列表
|
summary: 根据指定集群查询Pod列表
|
||||||
tags:
|
tags:
|
||||||
- pod
|
- 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}:
|
/api/v1/pod/metrics/{clusterName}/{namespace}/{name}:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
|
@ -1689,13 +1911,6 @@ paths:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: 创建服务
|
description: 创建服务
|
||||||
parameters:
|
|
||||||
- description: json
|
|
||||||
in: body
|
|
||||||
name: param
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/app.ServiceParam1'
|
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
|
@ -1706,6 +1921,21 @@ paths:
|
||||||
summary: 创建服务
|
summary: 创建服务
|
||||||
tags:
|
tags:
|
||||||
- service
|
- 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:
|
/api/v1/storage/pv:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
|
@ -1750,28 +1980,6 @@ paths:
|
||||||
tags:
|
tags:
|
||||||
- storage
|
- storage
|
||||||
/api/v1/storage/pvc:
|
/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:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
|
@ -1797,4 +2005,25 @@ paths:
|
||||||
summary: 查询PVC列表
|
summary: 查询PVC列表
|
||||||
tags:
|
tags:
|
||||||
- storage
|
- 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"
|
swagger: "2.0"
|
||||||
|
|
Loading…
Reference in New Issue