@@ -33,6 +33,25 @@ func Register(ws *restful.WebService) {
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/pods/{pod}").To(handlePodUnderNameSpace).Filter(route.RouteLogging)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/deployments/{deployment}/pods").
|
||||
To(handleGetDeploymentPodsMetrics).
|
||||
Filter(route.RouteLogging).
|
||||
Consumes(restful.MIME_JSON).
|
||||
Produces(restful.MIME_JSON))
|
||||
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/daemonsets/{daemonset}/pods").
|
||||
To(handleGetDaemonsetPodsMetrics).
|
||||
Filter(route.RouteLogging).
|
||||
Consumes(restful.MIME_JSON).
|
||||
Produces(restful.MIME_JSON))
|
||||
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/statefulsets/{statefulset}/pods").
|
||||
To(handleGetStatefulsetPodsMetrics).
|
||||
Filter(route.RouteLogging).
|
||||
Consumes(restful.MIME_JSON).
|
||||
Produces(restful.MIME_JSON))
|
||||
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/pods").To(handlePodsUnderNameSpace).Filter(route.RouteLogging)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
@@ -44,30 +63,59 @@ func Register(ws *restful.WebService) {
|
||||
Produces(restful.MIME_JSON)
|
||||
}
|
||||
|
||||
func handleAllPods(request *restful.Request, response *restful.Response) {
|
||||
// Get all pods metrics in cluster
|
||||
func handleAllPods(_ *restful.Request, response *restful.Response) {
|
||||
var result constants.PageableResponse
|
||||
result = metrics.GetAllPodMetrics()
|
||||
response.WriteAsJson(result)
|
||||
}
|
||||
|
||||
// Get pods metrics in namespace
|
||||
func handlePodsUnderNameSpace(request *restful.Request, response *restful.Response) {
|
||||
var result constants.PageableResponse
|
||||
result = metrics.GetPodMetricsInNamespace(request.PathParameter("namespace"))
|
||||
response.WriteAsJson(result)
|
||||
}
|
||||
|
||||
// Get pods metrics in a deployment
|
||||
func handleGetDeploymentPodsMetrics(request *restful.Request, response *restful.Response) {
|
||||
namespace := request.PathParameter("namespace")
|
||||
deployment := request.PathParameter("deployment")
|
||||
result := metrics.GetPodMetricsInDeployment(namespace, deployment)
|
||||
response.WriteAsJson(result)
|
||||
}
|
||||
|
||||
// Get pods metrics in daemonset deployment
|
||||
func handleGetDaemonsetPodsMetrics(request *restful.Request, response *restful.Response) {
|
||||
namespace := request.PathParameter("namespace")
|
||||
daemonset := request.PathParameter("daemonset")
|
||||
result := metrics.GetPodMetricsInDaemonset(namespace, daemonset)
|
||||
response.WriteAsJson(result)
|
||||
}
|
||||
|
||||
// Get pods metrics in statefulset deployment
|
||||
func handleGetStatefulsetPodsMetrics(request *restful.Request, response *restful.Response) {
|
||||
namespace := request.PathParameter("namespace")
|
||||
statefulset := request.PathParameter("statefulset")
|
||||
result := metrics.GetPodMetricsInStatefulSet(namespace, statefulset)
|
||||
response.WriteAsJson(result)
|
||||
}
|
||||
|
||||
// Get all pods metrics located in node
|
||||
func handlePodsUnderNode(request *restful.Request, response *restful.Response) {
|
||||
var result constants.PageableResponse
|
||||
result = metrics.GetPodMetricsInNode(request.PathParameter("node"))
|
||||
response.WriteAsJson(result)
|
||||
}
|
||||
|
||||
// Get a specific pod metrics
|
||||
func handlePodUnderNameSpace(request *restful.Request, response *restful.Response) {
|
||||
var resultPod metrics.PodMetrics
|
||||
resultPod = metrics.FormatPodMetrics(request.PathParameter("namespace"), request.PathParameter("pod"))
|
||||
response.WriteAsJson(resultPod)
|
||||
}
|
||||
|
||||
// Get pod metrics in a namespace located in deployment
|
||||
func handlePodsUnderNodeAndNameSpace(request *restful.Request, response *restful.Response) {
|
||||
var result constants.PageableResponse
|
||||
nodeName := request.PathParameter("node")
|
||||
|
||||
@@ -36,26 +36,31 @@ func Register(ws *restful.WebService) {
|
||||
Filter(route.RouteLogging).
|
||||
Produces(restful.MIME_JSON))
|
||||
|
||||
ws.Route(ws.GET("/{namespace}/router").To(GetRouter).
|
||||
ws.Route(ws.GET("/users/{user}/routers").To(GetAllRoutersOfUser).
|
||||
Doc("Get routers for user").
|
||||
Filter(route.RouteLogging).
|
||||
Produces(restful.MIME_JSON))
|
||||
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/router").To(GetRouter).
|
||||
Doc("Get router of a specified project").
|
||||
Param(ws.PathParameter("namespace", "name of the project").DataType("string")).
|
||||
Filter(route.RouteLogging).
|
||||
Produces(restful.MIME_JSON))
|
||||
|
||||
ws.Route(ws.DELETE("/{namespace}/router").To(DeleteRouter).
|
||||
ws.Route(ws.DELETE("/namespaces/{namespace}/router").To(DeleteRouter).
|
||||
Doc("Get router of a specified project").
|
||||
Param(ws.PathParameter("namespace", "name of the project").DataType("string")).
|
||||
Filter(route.RouteLogging).
|
||||
Produces(restful.MIME_JSON))
|
||||
|
||||
ws.Route(ws.POST("/{namespace}/router").To(CreateRouter).
|
||||
ws.Route(ws.POST("/namespaces/{namespace}/router").To(CreateRouter).
|
||||
Doc("Create a router for a specified project").
|
||||
Param(ws.PathParameter("namespace", "name of the project").DataType("string")).
|
||||
Filter(route.RouteLogging).
|
||||
Consumes(restful.MIME_JSON).
|
||||
Produces(restful.MIME_JSON))
|
||||
|
||||
ws.Route(ws.PUT("/{namespace}/router").To(UpdateRouter).
|
||||
ws.Route(ws.PUT("/namespaces/{namespace}/router").To(UpdateRouter).
|
||||
Doc("Update a router for a specified project").
|
||||
Param(ws.PathParameter("namespace", "name of the project").DataType("string")).
|
||||
Filter(route.RouteLogging).
|
||||
@@ -81,6 +86,20 @@ func GetAllRouters(request *restful.Request, response *restful.Response) {
|
||||
}
|
||||
}
|
||||
|
||||
// Get all namespace ingress controller services for user
|
||||
func GetAllRoutersOfUser(request *restful.Request, response *restful.Response) {
|
||||
username := request.PathParameter("user")
|
||||
|
||||
routers, err := models.GetAllRoutersOfUser(username)
|
||||
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
response.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
} else {
|
||||
response.WriteAsJson(routers)
|
||||
}
|
||||
}
|
||||
|
||||
// Get ingress controller service for specified namespace
|
||||
func GetRouter(request *restful.Request, response *restful.Response) {
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"strconv"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
@@ -74,7 +76,7 @@ func (ctl *ServiceCtl) getExternalIp(item v1.Service) string {
|
||||
}
|
||||
return "<pending>"
|
||||
}
|
||||
return "-"
|
||||
return ""
|
||||
}
|
||||
|
||||
func (ctl *ServiceCtl) generateObject(item v1.Service) *Service {
|
||||
@@ -86,6 +88,7 @@ func (ctl *ServiceCtl) generateObject(item v1.Service) *Service {
|
||||
serviceType := virtualIp
|
||||
vip := item.Spec.ClusterIP
|
||||
ports := ""
|
||||
var nodePorts []string
|
||||
|
||||
if createTime.IsZero() {
|
||||
createTime = time.Now()
|
||||
@@ -93,12 +96,10 @@ func (ctl *ServiceCtl) generateObject(item v1.Service) *Service {
|
||||
|
||||
if item.Spec.ClusterIP == "None" {
|
||||
serviceType = headlessSelector
|
||||
vip = "-"
|
||||
}
|
||||
|
||||
if len(item.Spec.ExternalName) > 0 {
|
||||
serviceType = headlessExternal
|
||||
vip = "-"
|
||||
}
|
||||
|
||||
if len(item.Spec.ExternalIPs) > 0 {
|
||||
@@ -110,15 +111,29 @@ func (ctl *ServiceCtl) generateObject(item v1.Service) *Service {
|
||||
targetPort := portItem.TargetPort.String()
|
||||
protocol := portItem.Protocol
|
||||
ports += fmt.Sprintf("%d:%s/%s,", port, targetPort, protocol)
|
||||
|
||||
if portItem.NodePort != 0 {
|
||||
nodePorts = append(nodePorts, strconv.FormatInt(int64(portItem.NodePort), 10))
|
||||
}
|
||||
}
|
||||
|
||||
if len(ports) == 0 {
|
||||
ports = "-"
|
||||
} else {
|
||||
ports = ports[0 : len(ports)-1]
|
||||
}
|
||||
|
||||
object := &Service{Namespace: namespace, Name: name, ServiceType: serviceType, ExternalIp: externalIp,
|
||||
VirtualIp: vip, CreateTime: createTime, Ports: ports, Annotation: Annotation{item.Annotations}}
|
||||
object := &Service{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
ServiceType: serviceType,
|
||||
ExternalIp: externalIp,
|
||||
VirtualIp: vip,
|
||||
CreateTime: createTime,
|
||||
Ports: ports,
|
||||
NodePorts: strings.Join(nodePorts, ","),
|
||||
Annotation: Annotation{item.Annotations},
|
||||
}
|
||||
|
||||
return object
|
||||
}
|
||||
@@ -154,7 +169,6 @@ func (ctl *ServiceCtl) listAndWatch() {
|
||||
for _, item := range list {
|
||||
obj := ctl.generateObject(*item)
|
||||
db.Create(obj)
|
||||
|
||||
}
|
||||
|
||||
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
|
||||
@@ -140,6 +140,7 @@ type Service struct {
|
||||
ExternalIp string `json:"externalIp,omitempty"`
|
||||
|
||||
Ports string `json:"ports,omitempty"`
|
||||
NodePorts string `json:"nodePorts,omitempty"`
|
||||
Annotation Annotation `json:"annotations"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
@@ -38,20 +38,6 @@ type PodMemoryMetrics struct {
|
||||
|
||||
const Inf = "inf"
|
||||
|
||||
/*
|
||||
Get all namespaces in default cluster
|
||||
*/
|
||||
func GetNameSpaces() []string {
|
||||
namespacesList := client.GetHeapsterMetrics("/namespaces")
|
||||
var namespaces []string
|
||||
dec := json.NewDecoder(strings.NewReader(namespacesList))
|
||||
err := dec.Decode(&namespaces)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
return namespaces
|
||||
}
|
||||
|
||||
/*
|
||||
Get all pods under specified namespace in default cluster
|
||||
*/
|
||||
@@ -73,14 +59,14 @@ func GetSinglePodMetrics(namespace string, podName string, ch chan PodMetrics) {
|
||||
}
|
||||
|
||||
func GetPodsMetrics(podList *coreV1.PodList) []PodMetrics {
|
||||
var items []PodMetrics
|
||||
items := make([]PodMetrics, 0)
|
||||
|
||||
ch := make(chan PodMetrics)
|
||||
for _, pod := range podList.Items {
|
||||
go GetSinglePodMetrics(pod.Namespace, pod.Name, ch)
|
||||
}
|
||||
|
||||
for _, _ = range podList.Items {
|
||||
for range podList.Items {
|
||||
items = append(items, <-ch)
|
||||
}
|
||||
|
||||
@@ -102,6 +88,96 @@ func GetPodMetricsInNamespace(namespace string) constants.PageableResponse {
|
||||
return podMetrics
|
||||
}
|
||||
|
||||
func GetPodMetricsInDeployment(namespace string, deployment string) constants.PageableResponse {
|
||||
|
||||
var podMetrics constants.PageableResponse
|
||||
|
||||
k8sClient := client.NewK8sClient()
|
||||
|
||||
deploy, err := k8sClient.ExtensionsV1beta1().Deployments(namespace).Get(deployment, v1.GetOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
|
||||
labels := make([]string, 0)
|
||||
for k, v := range deploy.Spec.Selector.MatchLabels {
|
||||
labels = append(labels, k+"="+v)
|
||||
}
|
||||
|
||||
options := v1.ListOptions{
|
||||
LabelSelector: strings.Join(labels, ","),
|
||||
}
|
||||
|
||||
podList, err := k8sClient.CoreV1().Pods(namespace).List(options)
|
||||
for _, podMetric := range GetPodsMetrics(podList) {
|
||||
podMetrics.Items = append(podMetrics.Items, podMetric)
|
||||
}
|
||||
podMetrics.TotalCount = len(podMetrics.Items)
|
||||
|
||||
return podMetrics
|
||||
|
||||
}
|
||||
|
||||
func GetPodMetricsInStatefulSet(namespace string, statefulSet string) constants.PageableResponse {
|
||||
|
||||
var podMetrics constants.PageableResponse
|
||||
|
||||
k8sClient := client.NewK8sClient()
|
||||
|
||||
deploy, err := k8sClient.AppsV1().StatefulSets(namespace).Get(statefulSet, v1.GetOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
|
||||
labels := make([]string, 0)
|
||||
for k, v := range deploy.Spec.Selector.MatchLabels {
|
||||
labels = append(labels, k+"="+v)
|
||||
}
|
||||
|
||||
options := v1.ListOptions{
|
||||
LabelSelector: strings.Join(labels, ","),
|
||||
}
|
||||
|
||||
podList, err := k8sClient.CoreV1().Pods(namespace).List(options)
|
||||
for _, podMetric := range GetPodsMetrics(podList) {
|
||||
podMetrics.Items = append(podMetrics.Items, podMetric)
|
||||
}
|
||||
podMetrics.TotalCount = len(podMetrics.Items)
|
||||
|
||||
return podMetrics
|
||||
|
||||
}
|
||||
|
||||
func GetPodMetricsInDaemonset(namespace string, daemonset string) constants.PageableResponse {
|
||||
|
||||
var podMetrics constants.PageableResponse
|
||||
|
||||
k8sClient := client.NewK8sClient()
|
||||
|
||||
deploy, err := k8sClient.ExtensionsV1beta1().DaemonSets(namespace).Get(daemonset, v1.GetOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
|
||||
labels := make([]string, 0)
|
||||
for k, v := range deploy.Spec.Selector.MatchLabels {
|
||||
labels = append(labels, k+"="+v)
|
||||
}
|
||||
|
||||
options := v1.ListOptions{
|
||||
LabelSelector: strings.Join(labels, ","),
|
||||
}
|
||||
|
||||
podList, err := k8sClient.CoreV1().Pods(namespace).List(options)
|
||||
for _, podMetric := range GetPodsMetrics(podList) {
|
||||
podMetrics.Items = append(podMetrics.Items, podMetric)
|
||||
}
|
||||
podMetrics.TotalCount = len(podMetrics.Items)
|
||||
|
||||
return podMetrics
|
||||
|
||||
}
|
||||
|
||||
func GetPodMetricsInNode(nodeName string) constants.PageableResponse {
|
||||
var podMetrics constants.PageableResponse
|
||||
k8sClient := client.NewK8sClient()
|
||||
@@ -191,7 +267,9 @@ func FormatPodMetrics(namespace string, pod string) PodMetrics {
|
||||
resultPod.MemoryRequest = Inf
|
||||
} else {
|
||||
data, _ := memoryRequestMetrics[0].GetNumber("value")
|
||||
resultPod.MemoryRequest = data.String()
|
||||
memoryReq, _ := data.Float64()
|
||||
memoryReq = memoryReq / 1024 / 1024
|
||||
resultPod.MemoryRequest = fmt.Sprintf("%.1f", memoryReq)
|
||||
}
|
||||
|
||||
memoryLimit := client.GetHeapsterMetricsJson("/namespaces/" + namespace + "/pods/" + pod + "/metrics/memory/limit")
|
||||
@@ -200,7 +278,9 @@ func FormatPodMetrics(namespace string, pod string) PodMetrics {
|
||||
resultPod.MemoryLimit = Inf
|
||||
} else {
|
||||
data, _ := memoryLimitMetrics[0].GetNumber("value")
|
||||
resultPod.MemoryLimit = data.String()
|
||||
memoryLim, _ := data.Float64()
|
||||
memoryLim = memoryLim / 1024 / 1024
|
||||
resultPod.MemoryLimit = fmt.Sprintf("%.1f", memoryLim)
|
||||
}
|
||||
|
||||
cpuUsageRate := client.GetHeapsterMetricsJson("/namespaces/" + namespace + "/pods/" + pod + "/metrics/cpu/usage_rate")
|
||||
|
||||
@@ -25,6 +25,10 @@ import (
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
|
||||
"k8s.io/api/rbac/v1"
|
||||
|
||||
"reflect"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
)
|
||||
@@ -47,6 +51,64 @@ func GetAllRouters() ([]coreV1.Service, error) {
|
||||
return services.Items, nil
|
||||
}
|
||||
|
||||
func inArray(val interface{}, array interface{}) (exists bool) {
|
||||
exists = false
|
||||
|
||||
switch reflect.TypeOf(array).Kind() {
|
||||
case reflect.Slice:
|
||||
s := reflect.ValueOf(array)
|
||||
|
||||
for i := 0; i < s.Len(); i++ {
|
||||
if reflect.DeepEqual(val, s.Index(i).Interface()) == true {
|
||||
exists = true
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return exists
|
||||
}
|
||||
|
||||
func GetAllRoutersOfUser(username string) ([]coreV1.Service, error) {
|
||||
|
||||
routers := make([]coreV1.Service, 0)
|
||||
clusterRoles, err := GetClusterRoles(username)
|
||||
|
||||
// return by cluster role
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return routers, err
|
||||
} else {
|
||||
for _, clusterRole := range clusterRoles {
|
||||
for _, rulePolicy := range clusterRole.Rules {
|
||||
if (inArray(v1.VerbAll, rulePolicy.Verbs) || inArray("view", rulePolicy.Verbs)) &&
|
||||
(inArray(v1.ResourceAll, rulePolicy.Resources) || inArray("namespaces", rulePolicy.Resources)) {
|
||||
return GetAllRouters()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return by role
|
||||
roles, err := GetRoles(username)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return routers, err
|
||||
} else {
|
||||
for _, projectRole := range roles {
|
||||
router, err := GetRouter(projectRole.Namespace)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return routers, err
|
||||
} else if router != nil {
|
||||
routers = append(routers, *router)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return routers, nil
|
||||
|
||||
}
|
||||
|
||||
// Get router from a namespace
|
||||
func GetRouter(namespace string) (*coreV1.Service, error) {
|
||||
k8sClient := client.NewK8sClient()
|
||||
@@ -131,6 +193,7 @@ func CreateRouter(namespace string, routerType coreV1.ServiceType, annotations m
|
||||
|
||||
// Add project selector
|
||||
service.Labels["project"] = namespace
|
||||
|
||||
service.Spec.Selector["project"] = namespace
|
||||
|
||||
service, err := k8sClient.CoreV1().Services(constants.IngressControllerNamespace).Create(service)
|
||||
|
||||
Reference in New Issue
Block a user