Merge pull request #113 from zryfish/fix_routers_list

fix routers list
This commit is contained in:
zryfish
2018-06-25 21:52:26 +08:00
committed by GitHub
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)).
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")

View File

@@ -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) {

View File

@@ -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{

View File

@@ -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"`
}

View File

@@ -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")

View File

@@ -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)