diff --git a/pkg/apis/v1alpha/components/components_handler.go b/pkg/apis/v1alpha/components/components_handler.go index f165be3ad..eb5566bab 100644 --- a/pkg/apis/v1alpha/components/components_handler.go +++ b/pkg/apis/v1alpha/components/components_handler.go @@ -31,6 +31,10 @@ func Register(ws *restful.WebService, subPath string) { Consumes(restful.MIME_JSON, restful.MIME_XML). Produces(restful.MIME_JSON) + ws.Route(ws.GET(subPath+"/{namespace}").To(handleGetComponentsByNamespace).Filter(route.RouteLogging)). + Consumes(restful.MIME_JSON, restful.MIME_XML). + Produces(restful.MIME_JSON) + } //get all components @@ -50,3 +54,22 @@ func handleGetComponents(request *restful.Request, response *restful.Response) { } } + +//get components from ns + +func handleGetComponentsByNamespace(request *restful.Request, response *restful.Response) { + + ns := request.PathParameter("namespace") + + result, err := models.GetComponentsByNamespace(ns) + 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 babf101b0..a4ae72e3f 100644 --- a/pkg/models/components.go +++ b/pkg/models/components.go @@ -17,7 +17,6 @@ limitations under the License. package models import ( - "strings" "time" "github.com/golang/glog" @@ -31,34 +30,151 @@ const OPENPITRIX = "openpitrix-system" const ISTIO = "istio-system" const KUBESPHERE = "kubesphere-system" +type ComponentsCount struct { + KubernetesCount int `json:"kubernetesCount"` + OpenpitrixCount int `json:"openpitrixCount"` + KubesphereCount int `json:"kubesphereCount"` + IstioCount int `json:"istioCount"` +} + type Components struct { Name string `json:"name"` - Version string `json:"version"` - Kind string `json:"kind"` Namespace string `json:"namespace"` - Label interface{} `json:"label"` - Replicas int `json:"replicas"` - HealthStatus string `json:"healthStatus"` SelfLink string `json:"selfLink"` - UpdateTime time.Time `json:"updateTime"` + Label interface{} `json:"label"` + HealthStatus string `json:"healthStatus"` + CreateTime time.Time `json:"updateTime"` } /*** -* get all components from k8s and kubesphere system, -* there are master component, node component,addons component , kubesphere component +* get all components from k8s and kubesphere system * */ -func GetComponents() ([]Components, error) { +func GetComponents() (map[string]interface{}, error) { - result := make([]Components, 0) + result := make(map[string]interface{}) + componentsList := make([]Components, 0) k8sClient := client.NewK8sClient() - label := "tier=control-plane" + var count ComponentsCount + var components Components + label := "kubernetes.io/cluster-service=true" option := meta_v1.ListOptions{ LabelSelector: label, } - podlists, err := k8sClient.CoreV1().Pods(KUBESYSTEM).List(option) + namespaces := []string{KUBESYSTEM, OPENPITRIX, ISTIO, KUBESPHERE} + for _, ns := range namespaces { + + if ns != KUBESYSTEM { + option.LabelSelector = "" + } + servicelists, err := k8sClient.CoreV1().Services(ns).List(option) + + if err != nil { + + glog.Error(err) + + return result, err + } + + if len(servicelists.Items) > 0 { + + for _, service := range servicelists.Items { + + switch ns { + + case KUBESYSTEM: + count.KubernetesCount++ + case OPENPITRIX: + count.OpenpitrixCount++ + case KUBESPHERE: + count.KubesphereCount++ + + default: + count.IstioCount++ + } + + 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 == "" { + + combination = labelstr + + } else { + + combination = combination + "," + labelstr + + } + + } + option := meta_v1.ListOptions{ + LabelSelector: combination, + } + podsList, err := k8sClient.CoreV1().Pods(ns).List(option) + + if err != nil { + + glog.Error(err) + return result, err + } + + if len(podsList.Items) > 0 { + + for _, pod := range podsList.Items { + + if pod.Status.Phase == "Running" { + + components.HealthStatus = "health" + + } else { + + components.HealthStatus = "unhealth" + + } + + } + + } + + componentsList = append(componentsList, components) + + } + + } + + } + result["count"] = count + result["item"] = componentsList + return result, nil + +} + +func GetComponentsByNamespace(ns string) ([]Components, error) { + + result := make([]Components, 0) + k8sClient := client.NewK8sClient() + var components Components + + label := "kubernetes.io/cluster-service=true" + option := meta_v1.ListOptions{ + + LabelSelector: label, + } + if ns != KUBESYSTEM { + option.LabelSelector = "" + } + + servicelists, err := k8sClient.CoreV1().Services(ns).List(option) if err != nil { @@ -67,35 +183,46 @@ func GetComponents() ([]Components, error) { return result, err } - var components Components + if len(servicelists.Items) > 0 { - templates := []string{"kube-apiserver", "etcd", "kube-scheduler", "kube-controller-manager", "cloud-controller-manager"} + for _, service := range servicelists.Items { - if len(podlists.Items) > 0 { + components.Name = service.Name + components.Namespace = service.Namespace + components.CreateTime = service.CreationTimestamp.Time + components.SelfLink = service.SelfLink + components.Label = service.Spec.Selector + label := service.Spec.Selector + combination := "" + for key, val := range label { - for _, pod := range podlists.Items { + labelstr := key + "=" + val - for _, template := range templates { + if combination == "" { - if strings.Contains(pod.Name, template) { + combination = labelstr - components.Name = template - components.Kind = "Pod" - components.SelfLink = pod.SelfLink - components.Label = pod.Labels - components.Namespace = pod.Namespace - version := strings.Split(pod.Spec.Containers[0].Image, ":") + } else { - if len(version) < 2 { + combination = combination + "," + labelstr - components.Version = "latest" + } - } else { + } + option := meta_v1.ListOptions{ + LabelSelector: combination, + } + podsList, err := k8sClient.CoreV1().Pods(ns).List(option) - components.Version = version[1] + if err != nil { - } - components.Replicas = 1 + glog.Error(err) + return result, err + } + + if len(podsList.Items) > 0 { + + for _, pod := range podsList.Items { if pod.Status.Phase == "Running" { @@ -106,190 +233,17 @@ func GetComponents() ([]Components, error) { components.HealthStatus = "unhealth" } - components.UpdateTime = pod.Status.Conditions[0].LastTransitionTime.Time - - result = append(result, components) } } - } - - } - - label = "component=kube-addon-manager" - option.LabelSelector = label - - kubeaddon, err := k8sClient.CoreV1().Pods(KUBESYSTEM).List(option) - - if err != nil { - - glog.Error(err) - - return result, err - } - - if len(kubeaddon.Items) > 0 { - - for _, pod := range kubeaddon.Items { - - components.Name = "kube-addon-manager" - components.Kind = "Pod" - components.SelfLink = pod.SelfLink - components.Label = pod.Labels - components.Namespace = pod.Namespace - version := strings.Split(pod.Spec.Containers[0].Image, ":") - - if len(version) < 2 { - - components.Version = "latest" - - } else { - - components.Version = version[1] - - } - components.Replicas = 1 - - if pod.Status.Phase == "Running" { - - components.HealthStatus = "health" - - } else { - - components.HealthStatus = "unhealth" - - } - components.UpdateTime = pod.Status.Conditions[0].LastTransitionTime.Time - result = append(result, components) } } - option.LabelSelector = "" - dsList, err := k8sClient.AppsV1beta2().DaemonSets(KUBESYSTEM).List(option) - - if err != nil { - - glog.Error(err) - - return result, err - } - - templates = []string{"flannel", "kube-proxy", "calico"} - - if len(dsList.Items) > 0 { - - for _, ds := range dsList.Items { - - for _, template := range templates { - - if strings.Contains(ds.Name, template) { - - components.Name = ds.Name - components.Kind = "Daemonset" - components.SelfLink = ds.SelfLink - components.Label = ds.Spec.Selector.MatchLabels - components.Namespace = ds.Namespace - version := strings.Split(ds.Spec.Template.Spec.Containers[0].Image, ":") - - if len(version) < 2 { - - components.Version = "latest" - - } else { - - components.Version = version[1] - - } - - components.UpdateTime = ds.CreationTimestamp.Time - components.Replicas = int(ds.Status.DesiredNumberScheduled) - - if ds.Status.NumberAvailable == ds.Status.DesiredNumberScheduled { - - components.HealthStatus = "health" - - } else { - - components.HealthStatus = "unhealth" - - } - result = append(result, components) - } - - } - - } - - } - - templates = []string{"kube-dns", "heapster", "monitoring-influxdb", "iam", "openpitrix", "istio", "kubesphere"} - namespaces := []string{KUBESYSTEM, OPENPITRIX, ISTIO, KUBESPHERE} - - for _, ns := range namespaces { - - deployList, err := k8sClient.AppsV1beta1().Deployments(ns).List(option) - - if err != nil { - - glog.Error(err) - - return result, err - } - - if len(deployList.Items) > 0 { - - for _, dm := range deployList.Items { - - for _, template := range templates { - - if strings.Contains(dm.Name, template) { - - components.Name = dm.Name - components.Kind = "Deployment" - components.SelfLink = dm.SelfLink - components.Label = dm.Spec.Selector.MatchLabels - components.Namespace = dm.Namespace - components.Replicas = int(dm.Status.Replicas) - version := strings.Split(dm.Spec.Template.Spec.Containers[0].Image, ":") - if len(version) < 2 { - - components.Version = "latest" - - } else { - - components.Version = version[1] - - } - - components.UpdateTime = dm.Status.Conditions[0].LastUpdateTime.Time - - if dm.Status.AvailableReplicas == dm.Status.Replicas { - - components.HealthStatus = "health" - - } else { - - components.HealthStatus = "unhealth" - - } - - result = append(result, components) - - } - - } - - } - - } - - } - return result, nil } diff --git a/pkg/models/controllers/clusterRoles.go b/pkg/models/controllers/clusterRoles.go index 8e41315ed..28b308534 100644 --- a/pkg/models/controllers/clusterRoles.go +++ b/pkg/models/controllers/clusterRoles.go @@ -91,7 +91,7 @@ func (ctl *ClusterRoleCtl) listAndWatch() { case event := <-clusterRoleWatcher.ResultChan(): var role ClusterRole if event.Object == nil { - break + panic("watch timeout, restart clusterRole controller") } object := event.Object.(*v1.ClusterRole) if event.Type == watch.Deleted { diff --git a/pkg/models/controllers/daemonsets.go b/pkg/models/controllers/daemonsets.go index 48e874d48..2792b1bae 100644 --- a/pkg/models/controllers/daemonsets.go +++ b/pkg/models/controllers/daemonsets.go @@ -22,7 +22,7 @@ import ( "github.com/golang/glog" "k8s.io/api/apps/v1beta2" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" "kubesphere.io/kubesphere/pkg/client" @@ -87,7 +87,7 @@ func (ctl *DaemonsetCtl) listAndWatch() { db = db.CreateTable(&Daemonset{}) k8sClient := client.NewK8sClient() - deoloyList, err := k8sClient.AppsV1beta2().DaemonSets("").List(meta_v1.ListOptions{}) + deoloyList, err := k8sClient.AppsV1beta2().DaemonSets("").List(metaV1.ListOptions{}) if err != nil { glog.Error(err) return @@ -98,7 +98,7 @@ func (ctl *DaemonsetCtl) listAndWatch() { db.Create(obj) } - watcher, err := k8sClient.AppsV1beta2().DaemonSets("").Watch(meta_v1.ListOptions{}) + watcher, err := k8sClient.AppsV1beta2().DaemonSets("").Watch(metaV1.ListOptions{}) if err != nil { glog.Error(err) return @@ -111,7 +111,7 @@ func (ctl *DaemonsetCtl) listAndWatch() { case event := <-watcher.ResultChan(): var ss Daemonset if event.Object == nil { - break + panic("watch timeout, restart daemonset controller") } object := event.Object.(*v1beta2.DaemonSet) if event.Type == watch.Deleted { diff --git a/pkg/models/controllers/deployments.go b/pkg/models/controllers/deployments.go index 3c96fd190..87f3b7892 100644 --- a/pkg/models/controllers/deployments.go +++ b/pkg/models/controllers/deployments.go @@ -24,8 +24,6 @@ import ( "k8s.io/api/apps/v1beta2" metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" - - "kubesphere.io/kubesphere/pkg/client" ) func (ctl *DeploymentCtl) generateObject(item v1beta2.Deployment) *Deployment { @@ -46,7 +44,7 @@ func (ctl *DeploymentCtl) generateObject(item v1beta2.Deployment) *Deployment { } for _, conditon := range item.Status.Conditions { - if conditon.Type == "Progressing" { + if conditon.Type == "Available" { updateTime = conditon.LastUpdateTime.Time } } @@ -86,7 +84,7 @@ func (ctl *DeploymentCtl) listAndWatch() { db = db.CreateTable(&Deployment{}) - k8sClient := client.NewK8sClient() + k8sClient := ctl.K8sClient deoloyList, err := k8sClient.AppsV1beta2().Deployments("").List(metaV1.ListOptions{}) if err != nil { glog.Error(err) @@ -96,6 +94,7 @@ func (ctl *DeploymentCtl) listAndWatch() { for _, item := range deoloyList.Items { obj := ctl.generateObject(item) db.Create(obj) + } watcher, err := k8sClient.AppsV1beta2().Deployments("").Watch(metaV1.ListOptions{}) @@ -105,13 +104,14 @@ func (ctl *DeploymentCtl) listAndWatch() { } for { + glog.Error("here") select { case <-ctl.stopChan: return case event := <-watcher.ResultChan(): var deploy Deployment if event.Object == nil { - break + panic("watch timeout, restart deployment controller") } object := event.Object.(*v1beta2.Deployment) if event.Type == watch.Deleted { @@ -123,6 +123,7 @@ func (ctl *DeploymentCtl) listAndWatch() { db.Save(obj) } } + } func (ctl *DeploymentCtl) CountWithConditions(conditions string) int { diff --git a/pkg/models/controllers/ingresses.go b/pkg/models/controllers/ingresses.go index cc70cc799..cd644cefb 100644 --- a/pkg/models/controllers/ingresses.go +++ b/pkg/models/controllers/ingresses.go @@ -98,7 +98,7 @@ func (ctl *IngressCtl) listAndWatch() { case event := <-watcher.ResultChan(): var ing Ingress if event.Object == nil { - break + panic("watch timeout, restart ingress controller") } object := event.Object.(*v1beta1.Ingress) if event.Type == watch.Deleted { diff --git a/pkg/models/controllers/namespaces.go b/pkg/models/controllers/namespaces.go index b17945ac1..f0d013420 100644 --- a/pkg/models/controllers/namespaces.go +++ b/pkg/models/controllers/namespaces.go @@ -35,12 +35,13 @@ import ( ) const ( - provider = "kubernetes" - admin = "admin" - normal = "normal" - view = "view" - kubectlNamespace = "kubesphere" - kubectlConfigKey = "config" + provider = "kubernetes" + admin = "admin" + normal = "normal" + view = "view" + kubectlNamespace = "kubesphere" + kubectlConfigKey = "config" + openpitrix_runtime = "openpitrix_runtime" ) var adminRules = []rbac.PolicyRule{rbac.PolicyRule{Verbs: []string{"*"}, APIGroups: []string{"*"}, Resources: []string{"*"}}} @@ -132,13 +133,26 @@ func (ctl *NamespaceCtl) createOpRuntime(namespace, user string) ([]byte, error) return makeHttpRequest("POST", url, string(body)) } -func (ctl *NamespaceCtl) createDefaultRole(ns string) error { - defer func() { - if err := recover(); err != nil { - glog.Error(err) - } - }() +func (ctl *NamespaceCtl) createDefaultRoleBinding(ns, user string) error { + rolebinding, _ := ctl.K8sClient.RbacV1().RoleBindings(ns).Get(admin, metaV1.GetOptions{}) + if rolebinding.Name != admin { + + roleBinding := &rbac.RoleBinding{ObjectMeta: metaV1.ObjectMeta{Name: admin, Namespace: ns}, + Subjects: []rbac.Subject{{Name: user, Kind: rbac.UserKind}}, RoleRef: rbac.RoleRef{Kind: "Role", Name: admin}} + + _, err := ctl.K8sClient.RbacV1().RoleBindings(ns).Create(roleBinding) + + if err != nil { + glog.Error(err) + return err + } + } + + return nil +} + +func (ctl *NamespaceCtl) createDefaultRole(ns string) error { adminRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: admin, Namespace: ns}, Rules: adminRules} normalRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: normal, Namespace: ns}, Rules: normalRules} viewRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: view, Namespace: ns}, Rules: viewRules} @@ -178,11 +192,17 @@ func (ctl *NamespaceCtl) createDefaultRole(ns string) error { func (ctl *NamespaceCtl) createRoleAndRuntime(item v1.Namespace) { user := item.Annotations["creator"] ns := item.Name - if len(user) > 0 && len(item.Annotations["openpitrix_runtime"]) == 0 { + if len(user) > 0 && len(item.Annotations[openpitrix_runtime]) == 0 { err := ctl.createDefaultRole(ns) if err != nil { return } + + err = ctl.createDefaultRoleBinding(ns, user) + if err != nil { + return + } + resp, err := ctl.createOpRuntime(ns, user) if err != nil { return @@ -194,7 +214,7 @@ func (ctl *NamespaceCtl) createRoleAndRuntime(item v1.Namespace) { return } - item.Annotations["openpitrix_runtime"] = runtime.RuntimeId + item.Annotations[openpitrix_runtime] = runtime.RuntimeId ctl.K8sClient.CoreV1().Namespaces().Update(&item) } } @@ -259,7 +279,7 @@ func (ctl *NamespaceCtl) listAndWatch() { case event := <-watcher.ResultChan(): var ns Namespace if event.Object == nil { - break + panic("watch timeout, restart namespace controller") } object := event.Object.(*v1.Namespace) if event.Type == watch.Deleted { diff --git a/pkg/models/controllers/pods.go b/pkg/models/controllers/pods.go index 32e043b27..666858282 100644 --- a/pkg/models/controllers/pods.go +++ b/pkg/models/controllers/pods.go @@ -106,7 +106,7 @@ func (ctl *PodCtl) listAndWatch() { case event := <-watcher.ResultChan(): var po Pod if event.Object == nil { - break + panic("watch timeout, restart pod controller") } object := event.Object.(*v1.Pod) if event.Type == watch.Deleted { diff --git a/pkg/models/controllers/pvcs.go b/pkg/models/controllers/pvcs.go index bc25c765f..8956c61ff 100644 --- a/pkg/models/controllers/pvcs.go +++ b/pkg/models/controllers/pvcs.go @@ -111,7 +111,7 @@ func (ctl *PvcCtl) listAndWatch() { case event := <-watcher.ResultChan(): var pvc Pvc if event.Object == nil { - break + panic("watch timeout, restart pvc controller") } object := event.Object.(*v1.PersistentVolumeClaim) if event.Type == watch.Deleted { diff --git a/pkg/models/controllers/roles.go b/pkg/models/controllers/roles.go index d032ccaa7..866b77f05 100644 --- a/pkg/models/controllers/roles.go +++ b/pkg/models/controllers/roles.go @@ -92,10 +92,10 @@ func (ctl *RoleCtl) listAndWatch() { return case event := <-roleWatcher.ResultChan(): var role Role - object := event.Object.(*v1.Role) if event.Object == nil { - break + panic("watch timeout, restart role controller") } + object := event.Object.(*v1.Role) if event.Type == watch.Deleted { db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&role) db.Delete(role) diff --git a/pkg/models/controllers/services.go b/pkg/models/controllers/services.go index 2865bd127..a20b2cf6c 100644 --- a/pkg/models/controllers/services.go +++ b/pkg/models/controllers/services.go @@ -167,10 +167,12 @@ func (ctl *ServiceCtl) listAndWatch() { return case event := <-watcher.ResultChan(): var svc Service - object := event.Object.(*v1.Service) + if event.Object == nil { - break + panic("watch timeout, restart service controller") } + object := event.Object.(*v1.Service) + if event.Type == watch.Deleted { db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&svc) db.Delete(svc) diff --git a/pkg/models/controllers/statefulsets.go b/pkg/models/controllers/statefulsets.go index ddbd832ba..babc211c2 100644 --- a/pkg/models/controllers/statefulsets.go +++ b/pkg/models/controllers/statefulsets.go @@ -106,7 +106,7 @@ func (ctl *StatefulsetCtl) listAndWatch() { case event := <-watcher.ResultChan(): var tmp Statefulset if event.Object == nil { - break + panic("watch timeout, restart statefulset controller") } object := event.Object.(*v1beta2.StatefulSet) if event.Type == watch.Deleted { diff --git a/pkg/models/controllers/storageclasses.go b/pkg/models/controllers/storageclasses.go index 64d922928..2d07843c2 100644 --- a/pkg/models/controllers/storageclasses.go +++ b/pkg/models/controllers/storageclasses.go @@ -90,7 +90,7 @@ func (ctl *StorageClassCtl) listAndWatch() { case event := <-watcher.ResultChan(): var sc StorageClass if event.Object == nil { - break + panic("watch timeout, restart storageClass controller") } object := event.Object.(*v1beta1.StorageClass) if event.Type == watch.Deleted { diff --git a/pkg/models/image_registries.go b/pkg/models/image_registries.go index 3f9fd88c4..6271b55d3 100644 --- a/pkg/models/image_registries.go +++ b/pkg/models/image_registries.go @@ -88,7 +88,7 @@ func RegistryLoginAuth(authinfo AuthInfo) ValidationMsg { datastr := []byte(authinfo.Username + ":" + authinfo.Password) auth := base64.StdEncoding.EncodeToString(datastr) ctx := context.Background() - cli, err := client.NewClientWithOpts() + cli, err := client.NewEnvClient() if err != nil { diff --git a/pkg/models/nodes.go b/pkg/models/nodes.go index a24f7dd2f..cfe006e80 100644 --- a/pkg/models/nodes.go +++ b/pkg/models/nodes.go @@ -27,6 +27,7 @@ import ( "k8s.io/api/core/v1" policy "k8s.io/api/policy/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" "kubesphere.io/kubesphere/pkg/client" kubeclient "kubesphere.io/kubesphere/pkg/client" @@ -265,9 +266,29 @@ func DrainNode(nodename string) (msg constants.MessageResponse, err error) { return msg, err } } + } + + data := []byte(" {\"spec\":{\"unschedulable\":true}}") + nodestatus, err := k8sclient.CoreV1().Nodes().Patch(nodename, types.StrategicMergePatchType, data) + + if err != nil { + + glog.Fatal(err) + return msg, err } - msg.Message = fmt.Sprintf("success") + + if nodestatus.Spec.Unschedulable { + + msg.Message = fmt.Sprintf("success") + + } else { + + glog.Fatal(err) + return msg, err + + } + return msg, nil }