fix router list

This commit is contained in:
jeff
2018-06-25 20:28:15 +08:00
parent 5c762e48c3
commit 57ad2171b6
6 changed files with 254 additions and 29 deletions

View File

@@ -33,6 +33,25 @@ func Register(ws *restful.WebService) {
ws.Route(ws.GET("/namespaces/{namespace}/pods/{pod}").To(handlePodUnderNameSpace).Filter(route.RouteLogging)). ws.Route(ws.GET("/namespaces/{namespace}/pods/{pod}").To(handlePodUnderNameSpace).Filter(route.RouteLogging)).
Consumes(restful.MIME_JSON, restful.MIME_XML). Consumes(restful.MIME_JSON, restful.MIME_XML).
Produces(restful.MIME_JSON) 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)). ws.Route(ws.GET("/namespaces/{namespace}/pods").To(handlePodsUnderNameSpace).Filter(route.RouteLogging)).
Consumes(restful.MIME_JSON, restful.MIME_XML). Consumes(restful.MIME_JSON, restful.MIME_XML).
Produces(restful.MIME_JSON) Produces(restful.MIME_JSON)
@@ -44,30 +63,59 @@ func Register(ws *restful.WebService) {
Produces(restful.MIME_JSON) 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 var result constants.PageableResponse
result = metrics.GetAllPodMetrics() result = metrics.GetAllPodMetrics()
response.WriteAsJson(result) response.WriteAsJson(result)
} }
// Get pods metrics in namespace
func handlePodsUnderNameSpace(request *restful.Request, response *restful.Response) { func handlePodsUnderNameSpace(request *restful.Request, response *restful.Response) {
var result constants.PageableResponse var result constants.PageableResponse
result = metrics.GetPodMetricsInNamespace(request.PathParameter("namespace")) result = metrics.GetPodMetricsInNamespace(request.PathParameter("namespace"))
response.WriteAsJson(result) 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) { func handlePodsUnderNode(request *restful.Request, response *restful.Response) {
var result constants.PageableResponse var result constants.PageableResponse
result = metrics.GetPodMetricsInNode(request.PathParameter("node")) result = metrics.GetPodMetricsInNode(request.PathParameter("node"))
response.WriteAsJson(result) response.WriteAsJson(result)
} }
// Get a specific pod metrics
func handlePodUnderNameSpace(request *restful.Request, response *restful.Response) { func handlePodUnderNameSpace(request *restful.Request, response *restful.Response) {
var resultPod metrics.PodMetrics var resultPod metrics.PodMetrics
resultPod = metrics.FormatPodMetrics(request.PathParameter("namespace"), request.PathParameter("pod")) resultPod = metrics.FormatPodMetrics(request.PathParameter("namespace"), request.PathParameter("pod"))
response.WriteAsJson(resultPod) response.WriteAsJson(resultPod)
} }
// Get pod metrics in a namespace located in deployment
func handlePodsUnderNodeAndNameSpace(request *restful.Request, response *restful.Response) { func handlePodsUnderNodeAndNameSpace(request *restful.Request, response *restful.Response) {
var result constants.PageableResponse var result constants.PageableResponse
nodeName := request.PathParameter("node") nodeName := request.PathParameter("node")

View File

@@ -36,26 +36,31 @@ func Register(ws *restful.WebService) {
Filter(route.RouteLogging). Filter(route.RouteLogging).
Produces(restful.MIME_JSON)) 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"). Doc("Get router of a specified project").
Param(ws.PathParameter("namespace", "name of the project").DataType("string")). Param(ws.PathParameter("namespace", "name of the project").DataType("string")).
Filter(route.RouteLogging). Filter(route.RouteLogging).
Produces(restful.MIME_JSON)) 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"). Doc("Get router of a specified project").
Param(ws.PathParameter("namespace", "name of the project").DataType("string")). Param(ws.PathParameter("namespace", "name of the project").DataType("string")).
Filter(route.RouteLogging). Filter(route.RouteLogging).
Produces(restful.MIME_JSON)) 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"). Doc("Create a router for a specified project").
Param(ws.PathParameter("namespace", "name of the project").DataType("string")). Param(ws.PathParameter("namespace", "name of the project").DataType("string")).
Filter(route.RouteLogging). Filter(route.RouteLogging).
Consumes(restful.MIME_JSON). Consumes(restful.MIME_JSON).
Produces(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"). Doc("Update a router for a specified project").
Param(ws.PathParameter("namespace", "name of the project").DataType("string")). Param(ws.PathParameter("namespace", "name of the project").DataType("string")).
Filter(route.RouteLogging). 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 // Get ingress controller service for specified namespace
func GetRouter(request *restful.Request, response *restful.Response) { func GetRouter(request *restful.Request, response *restful.Response) {

View File

@@ -21,6 +21,8 @@ import (
"strings" "strings"
"time" "time"
"strconv"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
@@ -74,7 +76,7 @@ func (ctl *ServiceCtl) getExternalIp(item v1.Service) string {
} }
return "<pending>" return "<pending>"
} }
return "-" return ""
} }
func (ctl *ServiceCtl) generateObject(item v1.Service) *Service { func (ctl *ServiceCtl) generateObject(item v1.Service) *Service {
@@ -86,6 +88,7 @@ func (ctl *ServiceCtl) generateObject(item v1.Service) *Service {
serviceType := virtualIp serviceType := virtualIp
vip := item.Spec.ClusterIP vip := item.Spec.ClusterIP
ports := "" ports := ""
var nodePorts []string
if createTime.IsZero() { if createTime.IsZero() {
createTime = time.Now() createTime = time.Now()
@@ -93,12 +96,10 @@ func (ctl *ServiceCtl) generateObject(item v1.Service) *Service {
if item.Spec.ClusterIP == "None" { if item.Spec.ClusterIP == "None" {
serviceType = headlessSelector serviceType = headlessSelector
vip = "-"
} }
if len(item.Spec.ExternalName) > 0 { if len(item.Spec.ExternalName) > 0 {
serviceType = headlessExternal serviceType = headlessExternal
vip = "-"
} }
if len(item.Spec.ExternalIPs) > 0 { if len(item.Spec.ExternalIPs) > 0 {
@@ -110,15 +111,29 @@ func (ctl *ServiceCtl) generateObject(item v1.Service) *Service {
targetPort := portItem.TargetPort.String() targetPort := portItem.TargetPort.String()
protocol := portItem.Protocol protocol := portItem.Protocol
ports += fmt.Sprintf("%d:%s/%s,", port, targetPort, 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 { if len(ports) == 0 {
ports = "-" ports = "-"
} else { } else {
ports = ports[0 : len(ports)-1] ports = ports[0 : len(ports)-1]
} }
object := &Service{Namespace: namespace, Name: name, ServiceType: serviceType, ExternalIp: externalIp, object := &Service{
VirtualIp: vip, CreateTime: createTime, Ports: ports, Annotation: Annotation{item.Annotations}} Namespace: namespace,
Name: name,
ServiceType: serviceType,
ExternalIp: externalIp,
VirtualIp: vip,
CreateTime: createTime,
Ports: ports,
NodePorts: strings.Join(nodePorts, ","),
Annotation: Annotation{item.Annotations},
}
return object return object
} }
@@ -154,7 +169,6 @@ func (ctl *ServiceCtl) listAndWatch() {
for _, item := range list { for _, item := range list {
obj := ctl.generateObject(*item) obj := ctl.generateObject(*item)
db.Create(obj) db.Create(obj)
} }
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{ informer.AddEventHandler(cache.ResourceEventHandlerFuncs{

View File

@@ -140,6 +140,7 @@ type Service struct {
ExternalIp string `json:"externalIp,omitempty"` ExternalIp string `json:"externalIp,omitempty"`
Ports string `json:"ports,omitempty"` Ports string `json:"ports,omitempty"`
NodePorts string `json:"nodePorts,omitempty"`
Annotation Annotation `json:"annotations"` Annotation Annotation `json:"annotations"`
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"` CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
} }

View File

@@ -38,20 +38,6 @@ type PodMemoryMetrics struct {
const Inf = "inf" 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 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 { func GetPodsMetrics(podList *coreV1.PodList) []PodMetrics {
var items []PodMetrics items := make([]PodMetrics, 0)
ch := make(chan PodMetrics) ch := make(chan PodMetrics)
for _, pod := range podList.Items { for _, pod := range podList.Items {
go GetSinglePodMetrics(pod.Namespace, pod.Name, ch) go GetSinglePodMetrics(pod.Namespace, pod.Name, ch)
} }
for _, _ = range podList.Items { for range podList.Items {
items = append(items, <-ch) items = append(items, <-ch)
} }
@@ -102,6 +88,96 @@ func GetPodMetricsInNamespace(namespace string) constants.PageableResponse {
return podMetrics 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 { func GetPodMetricsInNode(nodeName string) constants.PageableResponse {
var podMetrics constants.PageableResponse var podMetrics constants.PageableResponse
k8sClient := client.NewK8sClient() k8sClient := client.NewK8sClient()
@@ -191,7 +267,9 @@ func FormatPodMetrics(namespace string, pod string) PodMetrics {
resultPod.MemoryRequest = Inf resultPod.MemoryRequest = Inf
} else { } else {
data, _ := memoryRequestMetrics[0].GetNumber("value") 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") memoryLimit := client.GetHeapsterMetricsJson("/namespaces/" + namespace + "/pods/" + pod + "/metrics/memory/limit")
@@ -200,7 +278,9 @@ func FormatPodMetrics(namespace string, pod string) PodMetrics {
resultPod.MemoryLimit = Inf resultPod.MemoryLimit = Inf
} else { } else {
data, _ := memoryLimitMetrics[0].GetNumber("value") 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") cpuUsageRate := client.GetHeapsterMetricsJson("/namespaces/" + namespace + "/pods/" + pod + "/metrics/cpu/usage_rate")

View File

@@ -25,6 +25,10 @@ import (
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/kubernetes/scheme"
"k8s.io/api/rbac/v1"
"reflect"
"kubesphere.io/kubesphere/pkg/client" "kubesphere.io/kubesphere/pkg/client"
"kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/constants"
) )
@@ -47,6 +51,64 @@ func GetAllRouters() ([]coreV1.Service, error) {
return services.Items, nil 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 // Get router from a namespace
func GetRouter(namespace string) (*coreV1.Service, error) { func GetRouter(namespace string) (*coreV1.Service, error) {
k8sClient := client.NewK8sClient() k8sClient := client.NewK8sClient()
@@ -131,6 +193,7 @@ func CreateRouter(namespace string, routerType coreV1.ServiceType, annotations m
// Add project selector // Add project selector
service.Labels["project"] = namespace service.Labels["project"] = namespace
service.Spec.Selector["project"] = namespace service.Spec.Selector["project"] = namespace
service, err := k8sClient.CoreV1().Services(constants.IngressControllerNamespace).Create(service) service, err := k8sClient.CoreV1().Services(constants.IngressControllerNamespace).Create(service)