diff --git a/pkg/apis/v1alpha/components/components_handler.go b/pkg/apis/v1alpha/components/components_handler.go index b4d16f548b4aa8beabd29cbcd3f662b71ff16daa..342de69e738479e5871494ff6381cf3985fedf2f 100644 --- a/pkg/apis/v1alpha/components/components_handler.go +++ b/pkg/apis/v1alpha/components/components_handler.go @@ -30,22 +30,33 @@ func Register(ws *restful.WebService, subPath string) { ws.Route(ws.GET(subPath).To(handleGetComponents).Filter(route.RouteLogging)). Consumes(restful.MIME_JSON, restful.MIME_XML). Produces(restful.MIME_JSON) + ws.Route(ws.GET(subPath+"/{namespace}/{componentName}").To(handleGetComponentStatus). + Filter(route.RouteLogging)). + Consumes(restful.MIME_JSON, restful.MIME_XML). + Produces(restful.MIME_JSON) } -//get all components +// get a specific component status +func handleGetComponentStatus(request *restful.Request, response *restful.Response) { + namespace := request.PathParameter("namespace") + componentName := request.PathParameter("componentName") + if component, err := models.GetComponentStatus(namespace, componentName); err != nil { + response.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()}) + } else { + response.WriteAsJson(component) + } +} + +// get all components func handleGetComponents(request *restful.Request, response *restful.Response) { - result, err := models.GetComponents() + result, err := models.GetAllComponentsStatus() if err != nil { - response.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()}) - } else { - response.WriteAsJson(result) - } } diff --git a/pkg/models/components.go b/pkg/models/components.go index d58fab4f22a3e3ee9f0a66b898cf1b33c0ea4608..2d3cb0cbc351170e346bd7d3567f6c68fb1e7eba 100644 --- a/pkg/models/components.go +++ b/pkg/models/components.go @@ -19,150 +19,119 @@ package models import ( "time" + "k8s.io/apimachinery/pkg/labels" + "github.com/golang/glog" meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "kubesphere.io/kubesphere/pkg/client" - "kubesphere.io/kubesphere/pkg/constants" ) -type ComponentsCount struct { - KubernetesCount int `json:"kubernetesCount"` - OpenpitrixCount int `json:"openpitrixCount"` - KubesphereCount int `json:"kubesphereCount"` -} - -type Components struct { - Name string `json:"name"` - Namespace string `json:"namespace"` - SelfLink string `json:"selfLink"` - Label interface{} `json:"label"` - HealthStatus string `json:"healthStatus"` - CreateTime time.Time `json:"createTime"` +// Namespaces need to watch +var SYSTEM_NAMESPACES = [...]string{"kubesphere-system", "openpitrix-system", "kube-system"} + +type Component struct { + Name string `json:"name"` + Namespace string `json:"namespace"` + SelfLink string `json:"selfLink"` + Label interface{} `json:"label"` + StartedAt time.Time `json:"startedAt"` + TotalBackends int `json:"totalBackends"` + HealthyBackends int `json:"healthyBackends"` } -/*** -* get all components from k8s and kubesphere system -* - */ -func GetComponents() (map[string]interface{}, error) { - - result := make(map[string]interface{}) - componentsList := make([]Components, 0) +func GetComponentStatus(namespace string, componentName string) (interface{}, error) { k8sClient := client.NewK8sClient() - var count ComponentsCount - var components Components - - label := "" - namespaces := []string{constants.KubeSystemNamespace, constants.OpenPitrixNamespace, constants.KubeSphereNamespace} - for _, ns := range namespaces { - if ns == constants.KubeSystemNamespace { - label = "kubernetes.io/cluster-service=true" - } else if ns == constants.OpenPitrixNamespace { - label = "app=openpitrix" - } else { - label = "app=kubesphere" + if service, err := k8sClient.CoreV1().Services(namespace).Get(componentName, meta_v1.GetOptions{}); err != nil { + glog.Error(err) + return nil, err + } else { + set := labels.Set(service.Spec.Selector) + + component := Component{ + Name: service.Name, + Namespace: service.Namespace, + SelfLink: service.SelfLink, + Label: service.Spec.Selector, + StartedAt: service.CreationTimestamp.Time, + HealthyBackends: 0, + TotalBackends: 0, } - option := meta_v1.ListOptions{ - - LabelSelector: label, - } - servicelists, err := k8sClient.CoreV1().Services(ns).List(option) - - if err != nil { + if pods, err := k8sClient.CoreV1().Pods(namespace).List(meta_v1.ListOptions{LabelSelector: set.AsSelector().String()}); err != nil { glog.Error(err) - - return result, err - } - - if len(servicelists.Items) > 0 { - - for _, service := range servicelists.Items { - - switch ns { - - case constants.KubeSystemNamespace: - count.KubernetesCount++ - case constants.OpenPitrixNamespace: - count.OpenpitrixCount++ - default: - count.KubesphereCount++ + return nil, err + } else { + for _, v := range pods.Items { + for _, c := range v.Status.ContainerStatuses { + component.TotalBackends++ + if c.Ready { + component.HealthyBackends++ + } } + } + } - components.Name = service.Name - components.Namespace = service.Namespace - components.CreateTime = service.CreationTimestamp.Time - components.Label = service.Spec.Selector - components.SelfLink = service.SelfLink - label := service.Spec.Selector - combination := "" - for key, val := range label { - - labelstr := key + "=" + val - - if combination == "" { + return component, nil + } - combination = labelstr +} - } else { +func GetAllComponentsStatus() (map[string]interface{}, error) { - combination = combination + "," + labelstr + status := make(map[string]interface{}) + var err error - } + k8sClient := client.NewK8sClient() - } - option := meta_v1.ListOptions{ - LabelSelector: combination, - } - podsList, err := k8sClient.CoreV1().Pods(ns).List(option) + for _, ns := range SYSTEM_NAMESPACES { - if err != nil { + nsStatus := make(map[string]interface{}) - glog.Error(err) - return result, err - } + services, err := k8sClient.CoreV1().Services(ns).List(meta_v1.ListOptions{}) + if err != nil { + glog.Error(err) + continue + } - if len(podsList.Items) > 0 { - var health bool - for _, pod := range podsList.Items { + for _, service := range services.Items { - for _, status := range pod.Status.ContainerStatuses { + set := labels.Set(service.Spec.Selector) - if status.Ready == false { - health = status.Ready - break - } else { - health = status.Ready - } + if len(set) == 0 { + continue + } - } + component := Component{ + Name: service.Name, + Namespace: service.Namespace, + SelfLink: service.SelfLink, + Label: service.Spec.Selector, + StartedAt: service.CreationTimestamp.Time, + HealthyBackends: 0, + TotalBackends: 0, + } - if health == false { - components.HealthStatus = "unhealth" - break + if pods, err := k8sClient.CoreV1().Pods(ns).List(meta_v1.ListOptions{LabelSelector: set.AsSelector().String()}); err != nil { + glog.Error(err) + continue + } else { + for _, v := range pods.Items { + for _, c := range v.Status.ContainerStatuses { + component.TotalBackends++ + if c.Ready { + component.HealthyBackends++ } - } - - if health == true { - components.HealthStatus = "health" - } - - } else { - components.HealthStatus = "unhealth" } - - componentsList = append(componentsList, components) - } + nsStatus[service.Name] = component } + status[ns] = nsStatus } - result["count"] = count - result["item"] = componentsList - return result, nil + return status, err }