add namespace's resource usage Statistics and fix some bugs

This commit is contained in:
richardxz
2018-06-19 14:15:07 +08:00
parent 894f45d7e6
commit 07bef0475a
18 changed files with 724 additions and 670 deletions

View File

@@ -1,12 +1,9 @@
/* /*
Copyright 2018 The KubeSphere Authors. Copyright 2018 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,13 +14,15 @@ limitations under the License.
package client package client
import ( import (
"github.com/jinzhu/gorm"
//_ "github.com/jinzhu/gorm/dialects/mysql"
"fmt" "fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/golang/glog" "github.com/golang/glog"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"log"
"kubesphere.io/kubesphere/pkg/logs"
"kubesphere.io/kubesphere/pkg/options" "kubesphere.io/kubesphere/pkg/options"
) )
@@ -34,12 +33,19 @@ const database = "kubesphere"
func NewDBClient() *gorm.DB { func NewDBClient() *gorm.DB {
if dbClient != nil { if dbClient != nil {
err := dbClient.DB().Ping()
if err == nil {
return dbClient return dbClient
} else {
glog.Error(err)
panic(err)
}
} }
user := options.ServerOptions.GetMysqlUser() user := options.ServerOptions.GetMysqlUser()
passwd := options.ServerOptions.GetMysqlPassword() passwd := options.ServerOptions.GetMysqlPassword()
addr := options.ServerOptions.GetMysqlAddr() addr := options.ServerOptions.GetMysqlAddr()
if dbClient == nil {
conn := fmt.Sprintf("%s:%s@tcp(%s)/mysql?charset=utf8mb4&parseTime=True&loc=Local", user, passwd, addr) conn := fmt.Sprintf("%s:%s@tcp(%s)/mysql?charset=utf8mb4&parseTime=True&loc=Local", user, passwd, addr)
db, err := gorm.Open("mysql", conn) db, err := gorm.Open("mysql", conn)
@@ -49,14 +55,18 @@ func NewDBClient() *gorm.DB {
} }
db.Exec(fmt.Sprintf("create database if not exists %s;", database)) db.Exec(fmt.Sprintf("create database if not exists %s;", database))
db.Close()
}
conn = fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", user, passwd, addr, database) conn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", user, passwd, addr, database)
db, err = gorm.Open("mysql", conn) db, err := gorm.Open("mysql", conn)
if err != nil { if err != nil {
glog.Error(err) glog.Error(err)
panic(err) panic(err)
} }
db.SetLogger(log.New(logs.GlogWriter{}, " ", 0))
dbClient = db dbClient = db
return dbClient return dbClient
} }

View File

@@ -1,12 +1,9 @@
/* /*
Copyright 2018 The KubeSphere Authors. Copyright 2018 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -19,43 +16,18 @@ package client
import ( import (
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"kubesphere.io/kubesphere/pkg/options" "kubesphere.io/kubesphere/pkg/options"
) )
var k8sClient *kubernetes.Clientset var k8sClient *kubernetes.Clientset
func getKubeConfig() (kubeConfig *rest.Config, err error) {
kubeConfigFile := options.ServerOptions.GetKubeConfigFile()
if len(kubeConfigFile) > 0 {
kubeConfig, err = clientcmd.BuildConfigFromFlags("", kubeConfigFile)
if err != nil {
return nil, err
}
} else {
kubeConfig, err = rest.InClusterConfig()
if err != nil {
return nil, err
}
}
return kubeConfig, nil
}
func NewK8sClient() *kubernetes.Clientset { func NewK8sClient() *kubernetes.Clientset {
if k8sClient != nil { if k8sClient != nil {
return k8sClient return k8sClient
} }
kubeConfig, err := getKubeConfig() kubeConfig, err := options.ServerOptions.GetKubeConfig()
if err != nil { if err != nil {
glog.Error(err) glog.Error(err)
panic(err) panic(err)

View File

@@ -17,17 +17,17 @@ limitations under the License.
package controllers package controllers
import ( import (
"encoding/json"
"strings" "strings"
"time" "time"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/api/rbac/v1" "k8s.io/api/rbac/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/informers"
"k8s.io/client-go/tools/cache"
) )
func (ctl *ClusterRoleCtl) generateObjec(item v1.ClusterRole) *ClusterRole { func (ctl *ClusterRoleCtl) generateObject(item v1.ClusterRole) *ClusterRole {
name := item.Name name := item.Name
if strings.HasPrefix(name, "system:") { if strings.HasPrefix(name, "system:") {
return nil return nil
@@ -38,9 +38,7 @@ func (ctl *ClusterRoleCtl) generateObjec(item v1.ClusterRole) *ClusterRole {
createTime = time.Now() createTime = time.Now()
} }
annotation, _ := json.Marshal(item.Annotations) object := &ClusterRole{Name: name, CreateTime: createTime, Annotation: Annotation{item.Annotations}}
object := &ClusterRole{Name: name, CreateTime: createTime, AnnotationStr: string(annotation)}
return object return object
} }
@@ -64,47 +62,48 @@ func (ctl *ClusterRoleCtl) listAndWatch() {
db = db.CreateTable(&ClusterRole{}) db = db.CreateTable(&ClusterRole{})
k8sClient := ctl.K8sClient k8sClient := ctl.K8sClient
kubeInformerFactory := informers.NewSharedInformerFactory(k8sClient, time.Second*resyncCircle)
informer := kubeInformerFactory.Rbac().V1().ClusterRoles().Informer()
lister := kubeInformerFactory.Rbac().V1().ClusterRoles().Lister()
clusterRoleList, err := k8sClient.RbacV1().ClusterRoles().List(metaV1.ListOptions{}) list, err := lister.List(labels.Everything())
if err != nil { if err != nil {
glog.Error(err) glog.Error(err)
return return
} }
for _, item := range clusterRoleList.Items { for _, item := range list {
obj := ctl.generateObjec(item) obj := ctl.generateObject(*item)
if obj != nil {
db.Create(obj) db.Create(obj)
}
} }
clusterRoleWatcher, err := k8sClient.RbacV1().ClusterRoles().Watch(metaV1.ListOptions{}) informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
if err != nil { AddFunc: func(obj interface{}) {
glog.Error(err)
return
}
for { object := obj.(*v1.ClusterRole)
select { mysqlObject := ctl.generateObject(*object)
case <-ctl.stopChan: if mysqlObject != nil {
return db.Create(mysqlObject)
case event := <-clusterRoleWatcher.ResultChan():
var role ClusterRole
if event.Object == nil {
panic("watch timeout, restart clusterRole controller")
}
object := event.Object.(*v1.ClusterRole)
if event.Type == watch.Deleted {
db.Where("name=? And namespace=?", object.Name, "\"\"").Find(&role)
db.Delete(role)
break
}
obj := ctl.generateObjec(*object)
if obj != nil {
db.Save(obj)
}
} }
},
UpdateFunc: func(old, new interface{}) {
object := new.(*v1.ClusterRole)
mysqlObject := ctl.generateObject(*object)
if mysqlObject != nil {
db.Save(mysqlObject)
} }
},
DeleteFunc: func(obj interface{}) {
var item ClusterRole
object := obj.(*v1.ClusterRole)
db.Where("name=?", object.Name).Find(&item)
db.Delete(item)
},
})
informer.Run(ctl.stopChan)
} }
func (ctl *ClusterRoleCtl) CountWithConditions(conditions string) int { func (ctl *ClusterRoleCtl) CountWithConditions(conditions string) int {
@@ -123,12 +122,6 @@ func (ctl *ClusterRoleCtl) ListWithConditions(conditions string, paging *Paging)
listWithConditions(db, &total, &object, &list, conditions, paging, order) listWithConditions(db, &total, &object, &list, conditions, paging, order)
for index, item := range list {
annotation := make(map[string]string)
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
list[index].Annotation = annotation
list[index].AnnotationStr = ""
}
return total, list, nil return total, list, nil
} }

View File

@@ -0,0 +1,52 @@
/*
Copyright 2018 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controllers
import "github.com/jinzhu/gorm"
func listWithConditions(db *gorm.DB, total *int, object, list interface{}, conditions string, paging *Paging, order string) {
if len(conditions) == 0 {
db.Model(object).Count(total)
} else {
db.Model(object).Where(conditions).Count(total)
}
if paging != nil {
if len(conditions) > 0 {
db.Where(conditions).Order(order).Limit(paging.Limit).Offset(paging.Offset).Find(list)
} else {
db.Order(order).Limit(paging.Limit).Offset(paging.Offset).Find(list)
}
} else {
if len(conditions) > 0 {
db.Where(conditions).Order(order).Find(list)
} else {
db.Order(order).Find(list)
}
}
}
func countWithConditions(db *gorm.DB, conditions string, object interface{}) int {
var count int
if len(conditions) == 0 {
db.Model(object).Count(&count)
} else {
db.Model(object).Where(conditions).Count(&count)
}
return count
}

View File

@@ -21,14 +21,13 @@ import (
"time" "time"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/api/apps/v1beta2" "k8s.io/api/apps/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/informers"
"k8s.io/client-go/tools/cache"
"kubesphere.io/kubesphere/pkg/client"
) )
func (ctl *DaemonsetCtl) generateObject(item v1beta2.DaemonSet) *Daemonset { func (ctl *DaemonsetCtl) generateObject(item v1.DaemonSet) *Daemonset {
var app string var app string
var status string var status string
name := item.Name name := item.Name
@@ -53,24 +52,20 @@ func (ctl *DaemonsetCtl) generateObject(item v1beta2.DaemonSet) *Daemonset {
} }
if availablePodNum >= desirePodNum { if availablePodNum >= desirePodNum {
status = running status = Running
} else { } else {
status = updating status = Updating
} }
annotation, _ := json.Marshal(item.Annotations)
object := &Daemonset{Namespace: namespace, Name: name, Available: availablePodNum, Desire: desirePodNum, object := &Daemonset{Namespace: namespace, Name: name, Available: availablePodNum, Desire: desirePodNum,
App: app, CreateTime: createTime, Status: status, NodeSelector: string(nodeSelectorStr), AnnotationStr: string(annotation)} App: app, CreateTime: createTime, Status: status, NodeSelector: string(nodeSelectorStr), Annotation: Annotation{item.Annotations}}
return object return object
} }
func (ctl *DaemonsetCtl) listAndWatch() { func (ctl *DaemonsetCtl) listAndWatch() {
defer func() { defer func() {
close(ctl.aliveChan) close(ctl.aliveChan)
if err := recover(); err != nil { if err := recover(); err != nil {
glog.Error(err) glog.Error(err)
return return
@@ -86,43 +81,45 @@ func (ctl *DaemonsetCtl) listAndWatch() {
db = db.CreateTable(&Daemonset{}) db = db.CreateTable(&Daemonset{})
k8sClient := client.NewK8sClient() k8sClient := ctl.K8sClient
deoloyList, err := k8sClient.AppsV1beta2().DaemonSets("").List(metaV1.ListOptions{}) kubeInformerFactory := informers.NewSharedInformerFactory(k8sClient, time.Second*resyncCircle)
informer := kubeInformerFactory.Apps().V1().DaemonSets().Informer()
lister := kubeInformerFactory.Apps().V1().DaemonSets().Lister()
list, err := lister.List(labels.Everything())
if err != nil { if err != nil {
glog.Error(err) glog.Error(err)
return return
} }
for _, item := range deoloyList.Items { for _, item := range list {
obj := ctl.generateObject(item) obj := ctl.generateObject(*item)
db.Create(obj) db.Create(obj)
} }
watcher, err := k8sClient.AppsV1beta2().DaemonSets("").Watch(metaV1.ListOptions{}) informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
if err != nil { AddFunc: func(obj interface{}) {
glog.Error(err)
return
}
for { object := obj.(*v1.DaemonSet)
select { mysqlObject := ctl.generateObject(*object)
case <-ctl.stopChan: db.Create(mysqlObject)
return },
case event := <-watcher.ResultChan(): UpdateFunc: func(old, new interface{}) {
var ss Daemonset object := new.(*v1.DaemonSet)
if event.Object == nil { mysqlObject := ctl.generateObject(*object)
panic("watch timeout, restart daemonset controller") db.Save(mysqlObject)
} },
object := event.Object.(*v1beta2.DaemonSet) DeleteFunc: func(obj interface{}) {
if event.Type == watch.Deleted { var item Daemonset
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&ss) object := obj.(*v1.DaemonSet)
db.Delete(ss) db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&item)
break db.Delete(item)
}
obj := ctl.generateObject(*object) },
db.Save(obj) })
}
} informer.Run(ctl.stopChan)
} }
func (ctl *DaemonsetCtl) CountWithConditions(conditions string) int { func (ctl *DaemonsetCtl) CountWithConditions(conditions string) int {
@@ -140,12 +137,6 @@ func (ctl *DaemonsetCtl) ListWithConditions(conditions string, paging *Paging) (
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order) listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
for index, item := range list {
annotation := make(map[string]string)
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
list[index].Annotation = annotation
list[index].AnnotationStr = ""
}
return total, list, nil return total, list, nil
} }

View File

@@ -17,16 +17,17 @@ limitations under the License.
package controllers package controllers
import ( import (
"encoding/json"
"time" "time"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/api/apps/v1beta2" "k8s.io/api/apps/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/informers"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
) )
func (ctl *DeploymentCtl) generateObject(item v1beta2.Deployment) *Deployment { func (ctl *DeploymentCtl) generateObject(item v1.Deployment) *Deployment {
var app string var app string
var status string var status string
var updateTime time.Time var updateTime time.Time
@@ -53,19 +54,17 @@ func (ctl *DeploymentCtl) generateObject(item v1beta2.Deployment) *Deployment {
} }
if item.Annotations["state"] == "stop" { if item.Annotations["state"] == "stop" {
status = stopping status = Stopped
} else { } else {
if availablePodNum >= desirePodNum { if availablePodNum >= desirePodNum {
status = running status = Running
} else { } else {
status = updating status = Updating
} }
} }
annotation, _ := json.Marshal(item.Annotations)
return &Deployment{Namespace: namespace, Name: name, Available: availablePodNum, Desire: desirePodNum, return &Deployment{Namespace: namespace, Name: name, Available: availablePodNum, Desire: desirePodNum,
App: app, UpdateTime: updateTime, Status: status, AnnotationStr: string(annotation)} App: app, UpdateTime: updateTime, Status: status, Annotation: Annotation{item.Annotations}}
} }
func (ctl *DeploymentCtl) listAndWatch() { func (ctl *DeploymentCtl) listAndWatch() {
@@ -85,45 +84,44 @@ func (ctl *DeploymentCtl) listAndWatch() {
db = db.CreateTable(&Deployment{}) db = db.CreateTable(&Deployment{})
k8sClient := ctl.K8sClient k8sClient := ctl.K8sClient
deoloyList, err := k8sClient.AppsV1beta2().Deployments("").List(metaV1.ListOptions{}) kubeInformerFactory := informers.NewSharedInformerFactory(k8sClient, time.Second*resyncCircle)
informer := kubeInformerFactory.Apps().V1().Deployments().Informer()
lister := kubeInformerFactory.Apps().V1().Deployments().Lister()
list, err := lister.List(labels.Everything())
if err != nil { if err != nil {
glog.Error(err) glog.Error(err)
return return
} }
for _, item := range deoloyList.Items { for _, item := range list {
obj := ctl.generateObject(item) obj := ctl.generateObject(*item)
db.Create(obj) db.Create(obj)
} }
watcher, err := k8sClient.AppsV1beta2().Deployments("").Watch(metaV1.ListOptions{}) informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
if err != nil { AddFunc: func(obj interface{}) {
glog.Error(err)
return
}
for { object := obj.(*v1.Deployment)
glog.Error("here") mysqlObject := ctl.generateObject(*object)
select { db.Create(mysqlObject)
case <-ctl.stopChan: },
return UpdateFunc: func(old, new interface{}) {
case event := <-watcher.ResultChan(): object := new.(*v1.Deployment)
mysqlObject := ctl.generateObject(*object)
db.Save(mysqlObject)
},
DeleteFunc: func(obj interface{}) {
var deploy Deployment var deploy Deployment
if event.Object == nil { object := obj.(*v1.Deployment)
panic("watch timeout, restart deployment controller")
}
object := event.Object.(*v1beta2.Deployment)
if event.Type == watch.Deleted {
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&deploy) db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&deploy)
db.Delete(deploy) db.Delete(deploy)
break
}
obj := ctl.generateObject(*object)
db.Save(obj)
}
}
},
})
informer.Run(ctl.stopChan)
} }
func (ctl *DeploymentCtl) CountWithConditions(conditions string) int { func (ctl *DeploymentCtl) CountWithConditions(conditions string) int {
@@ -141,12 +139,6 @@ func (ctl *DeploymentCtl) ListWithConditions(conditions string, paging *Paging)
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order) listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
for index, item := range list {
annotation := make(map[string]string)
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
list[index].Annotation = annotation
list[index].AnnotationStr = ""
}
return total, list, nil return total, list, nil
} }

View File

@@ -17,16 +17,14 @@ limitations under the License.
package controllers package controllers
import ( import (
"encoding/json"
"strings" "strings"
"time" "time"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/api/extensions/v1beta1" "k8s.io/api/extensions/v1beta1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/informers"
"k8s.io/client-go/tools/cache"
"kubesphere.io/kubesphere/pkg/client"
) )
func (ctl *IngressCtl) generateObject(item v1beta1.Ingress) *Ingress { func (ctl *IngressCtl) generateObject(item v1beta1.Ingress) *Ingress {
@@ -49,15 +47,14 @@ func (ctl *IngressCtl) generateObject(item v1beta1.Ingress) *Ingress {
ip = strings.Join(ipList, ",") ip = strings.Join(ipList, ",")
} }
annotation, _ := json.Marshal(item.Annotations) object := &Ingress{Namespace: namespace, Name: name, TlsTermination: tls, Ip: ip, CreateTime: createTime, Annotation: Annotation{item.Annotations}}
object := &Ingress{Namespace: namespace, Name: name, TlsTermination: tls, Ip: ip, CreateTime: createTime, AnnotationStr: string(annotation)}
return object return object
} }
func (ctl *IngressCtl) listAndWatch() { func (ctl *IngressCtl) listAndWatch() {
defer func() { defer func() {
defer close(ctl.aliveChan) close(ctl.aliveChan)
if err := recover(); err != nil { if err := recover(); err != nil {
glog.Error(err) glog.Error(err)
return return
@@ -73,43 +70,45 @@ func (ctl *IngressCtl) listAndWatch() {
db = db.CreateTable(&Ingress{}) db = db.CreateTable(&Ingress{})
k8sClient := client.NewK8sClient() k8sClient := ctl.K8sClient
list, err := k8sClient.ExtensionsV1beta1().Ingresses("").List(metaV1.ListOptions{}) kubeInformerFactory := informers.NewSharedInformerFactory(k8sClient, time.Second*resyncCircle)
informer := kubeInformerFactory.Extensions().V1beta1().Ingresses().Informer()
lister := kubeInformerFactory.Extensions().V1beta1().Ingresses().Lister()
list, err := lister.List(labels.Everything())
if err != nil { if err != nil {
glog.Error(err) glog.Error(err)
return return
} }
for _, item := range list.Items { for _, item := range list {
obj := ctl.generateObject(item) obj := ctl.generateObject(*item)
db.Create(obj) db.Create(obj)
} }
watcher, err := k8sClient.ExtensionsV1beta1().Ingresses("").Watch(metaV1.ListOptions{}) informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
if err != nil { AddFunc: func(obj interface{}) {
glog.Error(err)
return
}
for { object := obj.(*v1beta1.Ingress)
select { mysqlObject := ctl.generateObject(*object)
case <-ctl.stopChan: db.Create(mysqlObject)
return },
case event := <-watcher.ResultChan(): UpdateFunc: func(old, new interface{}) {
var ing Ingress object := new.(*v1beta1.Ingress)
if event.Object == nil { mysqlObject := ctl.generateObject(*object)
panic("watch timeout, restart ingress controller") db.Save(mysqlObject)
} },
object := event.Object.(*v1beta1.Ingress) DeleteFunc: func(obj interface{}) {
if event.Type == watch.Deleted { var item Ingress
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&ing) object := obj.(*v1beta1.Ingress)
db.Delete(ing) db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&item)
break db.Delete(item)
}
obj := ctl.generateObject(*object) },
db.Save(obj) })
}
} informer.Run(ctl.stopChan)
} }
func (ctl *IngressCtl) CountWithConditions(conditions string) int { func (ctl *IngressCtl) CountWithConditions(conditions string) int {
@@ -127,12 +126,6 @@ func (ctl *IngressCtl) ListWithConditions(conditions string, paging *Paging) (in
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order) listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
for index, item := range list {
annotation := make(map[string]string)
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
list[index].Annotation = annotation
list[index].AnnotationStr = ""
}
return total, list, nil return total, list, nil
} }

View File

@@ -27,8 +27,11 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
rbac "k8s.io/api/rbac/v1" rbac "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/resource"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers"
"k8s.io/client-go/tools/cache"
"kubesphere.io/kubesphere/pkg/client" "kubesphere.io/kubesphere/pkg/client"
"kubesphere.io/kubesphere/pkg/options" "kubesphere.io/kubesphere/pkg/options"
@@ -229,15 +232,14 @@ func (ctl *NamespaceCtl) generateObject(item v1.Namespace) *Namespace {
createTime = time.Now() createTime = time.Now()
} }
annotation, _ := json.Marshal(item.Annotations) object := &Namespace{Name: name, CreateTime: createTime, Status: status, Annotation: Annotation{item.Annotations}}
object := &Namespace{Name: name, CreateTime: createTime, Status: status, AnnotationStr: string(annotation)}
return object return object
} }
func (ctl *NamespaceCtl) listAndWatch() { func (ctl *NamespaceCtl) listAndWatch() {
defer func() { defer func() {
defer close(ctl.aliveChan) close(ctl.aliveChan)
if err := recover(); err != nil { if err := recover(); err != nil {
glog.Error(err) glog.Error(err)
return return
@@ -252,50 +254,45 @@ func (ctl *NamespaceCtl) listAndWatch() {
db = db.CreateTable(&Namespace{}) db = db.CreateTable(&Namespace{})
k8sClient := client.NewK8sClient() k8sClient := ctl.K8sClient
list, err := k8sClient.CoreV1().Namespaces().List(metaV1.ListOptions{}) kubeInformerFactory := informers.NewSharedInformerFactory(k8sClient, time.Second*resyncCircle)
informer := kubeInformerFactory.Core().V1().Namespaces().Informer()
lister := kubeInformerFactory.Core().V1().Namespaces().Lister()
list, err := lister.List(labels.Everything())
if err != nil { if err != nil {
glog.Error(err) glog.Error(err)
return return
} }
for _, item := range list.Items { for _, item := range list {
obj := ctl.generateObject(item) obj := ctl.generateObject(*item)
db.Create(obj) db.Create(obj)
ctl.createRoleAndRuntime(item)
} }
watcher, err := k8sClient.CoreV1().Namespaces().Watch(metaV1.ListOptions{}) informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
if err != nil { AddFunc: func(obj interface{}) {
glog.Error(err)
return
}
for { object := obj.(*v1.Namespace)
select { mysqlObject := ctl.generateObject(*object)
case <-ctl.stopChan: db.Create(mysqlObject)
return },
case event := <-watcher.ResultChan(): UpdateFunc: func(old, new interface{}) {
var ns Namespace object := new.(*v1.Namespace)
if event.Object == nil { mysqlObject := ctl.generateObject(*object)
panic("watch timeout, restart namespace controller") db.Save(mysqlObject)
} },
object := event.Object.(*v1.Namespace) DeleteFunc: func(obj interface{}) {
if event.Type == watch.Deleted { var item Namespace
db.Where("name=?", object.Name).Find(&ns) object := obj.(*v1.Namespace)
db.Delete(ns) db.Where("name=?", object.Name).Find(&item)
db.Delete(item)
ctl.deleteOpRuntime(*object) },
break })
}
ctl.createRoleAndRuntime(*object) informer.Run(ctl.stopChan)
obj := ctl.generateObject(*object)
db.Save(obj)
}
}
} }
func (ctl *NamespaceCtl) CountWithConditions(conditions string) int { func (ctl *NamespaceCtl) CountWithConditions(conditions string) int {
@@ -313,11 +310,12 @@ func (ctl *NamespaceCtl) ListWithConditions(conditions string, paging *Paging) (
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order) listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
for index, item := range list { for index := range list {
annotation := make(map[string]string) usage, err := ctl.GetNamespaceQuota(list[index].Name)
json.Unmarshal([]byte(item.AnnotationStr), &annotation) if err == nil {
list[index].Annotation = annotation list[index].Usaeg = usage
list[index].AnnotationStr = "" }
} }
return total, list, nil return total, list, nil
} }
@@ -328,3 +326,28 @@ func (ctl *NamespaceCtl) Count(namespace string) int {
db.Model(&Namespace{}).Count(&count) db.Model(&Namespace{}).Count(&count)
return count return count
} }
func getUsage(namespace, resource string) int {
ctl := rec.controllers[resource]
return ctl.Count(namespace)
}
func (ctl *NamespaceCtl) GetNamespaceQuota(namespace string) (v1.ResourceList, error) {
usage := make(v1.ResourceList)
resourceList := []string{Daemonsets, Deployments, Ingresses, Roles, Services, Statefulsets, PersistentVolumeClaim, Pods}
for _, resourceName := range resourceList {
used := getUsage(namespace, resourceName)
var quantity resource.Quantity
quantity.Set(int64(used))
usage[v1.ResourceName(resourceName)] = quantity
}
podCtl := rec.controllers[Pods]
var quantity resource.Quantity
used := podCtl.CountWithConditions(fmt.Sprintf("status=\"%s\" And namespace=\"%s\"", "Running", namespace))
quantity.Set(int64(used))
usage["runningPods"] = quantity
return usage, nil
}

View File

@@ -18,15 +18,75 @@ package controllers
import ( import (
"encoding/json" "encoding/json"
"time"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/client" "k8s.io/client-go/tools/cache"
) )
const inUse = "in_use_pods"
func (ctl *PodCtl) addAnnotationToPvc(item v1.Pod) {
volumes := item.Spec.Volumes
for _, volume := range volumes {
pvc := volume.PersistentVolumeClaim
if pvc != nil {
name := pvc.ClaimName
Pvc, _ := ctl.K8sClient.CoreV1().PersistentVolumeClaims(item.Namespace).Get(name, metaV1.GetOptions{})
if Pvc.Annotations == nil {
Pvc.Annotations = make(map[string]string)
}
annotation := Pvc.Annotations
if len(annotation[inUse]) == 0 {
pods := []string{item.Name}
str, _ := json.Marshal(pods)
annotation[inUse] = string(str)
} else {
var pods []string
json.Unmarshal([]byte(annotation[inUse]), pods)
for _, pod := range pods {
if pod == item.Name {
return
}
pods = append(pods, item.Name)
str, _ := json.Marshal(pods)
annotation[inUse] = string(str)
}
}
ctl.K8sClient.CoreV1().PersistentVolumeClaims(item.Namespace).Update(Pvc)
}
}
}
func (ctl *PodCtl) delAnnotationFromPvc(item v1.Pod) {
volumes := item.Spec.Volumes
for _, volume := range volumes {
pvc := volume.PersistentVolumeClaim
if pvc != nil {
name := pvc.ClaimName
Pvc, _ := ctl.K8sClient.CoreV1().PersistentVolumeClaims(item.Namespace).Get(name, metaV1.GetOptions{})
annotation := Pvc.Annotations
var pods []string
json.Unmarshal([]byte(annotation[inUse]), pods)
for index, pod := range pods {
if pod == item.Name {
pods = append(pods[:index], pods[index+1:]...)
}
}
str, _ := json.Marshal(pods)
annotation[inUse] = string(str)
ctl.K8sClient.CoreV1().PersistentVolumeClaims(item.Namespace).Update(Pvc)
}
}
}
func (ctl *PodCtl) generateObject(item v1.Pod) *Pod { func (ctl *PodCtl) generateObject(item v1.Pod) *Pod {
name := item.Name name := item.Name
namespace := item.Namespace namespace := item.Namespace
@@ -37,13 +97,15 @@ func (ctl *PodCtl) generateObject(item v1.Pod) *Pod {
createTime := item.CreationTimestamp.Time createTime := item.CreationTimestamp.Time
containerStatus := item.Status.ContainerStatuses containerStatus := item.Status.ContainerStatuses
containerSpecs := item.Spec.Containers containerSpecs := item.Spec.Containers
var containers []Container
var containers Containers
for _, containerSpec := range containerSpecs { for _, containerSpec := range containerSpecs {
var container Container var container Container
container.Name = containerSpec.Name container.Name = containerSpec.Name
container.Image = containerSpec.Image container.Image = containerSpec.Image
container.Ports = containerSpec.Ports container.Ports = containerSpec.Ports
container.Resources = containerSpec.Resources
for _, status := range containerStatus { for _, status := range containerStatus {
if container.Name == status.Name { if container.Name == status.Name {
container.Ready = status.Ready container.Ready = status.Ready
@@ -53,25 +115,13 @@ func (ctl *PodCtl) generateObject(item v1.Pod) *Pod {
containers = append(containers, container) containers = append(containers, container)
} }
containerStr, _ := json.Marshal(containers)
annotation, _ := json.Marshal(item.Annotations)
object := &Pod{Namespace: namespace, Name: name, Node: nodeName, PodIp: podIp, Status: status, NodeIp: nodeIp, object := &Pod{Namespace: namespace, Name: name, Node: nodeName, PodIp: podIp, Status: status, NodeIp: nodeIp,
CreateTime: createTime, ContainerStr: string(containerStr), AnnotationStr: string(annotation)} CreateTime: createTime, Annotation: Annotation{item.Annotations}, Containers: containers}
return object return object
} }
func (ctl *PodCtl) listAndWatch() { func (ctl *PodCtl) listAndWatch() {
defer func() {
defer close(ctl.aliveChan)
if err := recover(); err != nil {
glog.Error(err)
return
}
}()
db := ctl.DB db := ctl.DB
if db.HasTable(&Pod{}) { if db.HasTable(&Pod{}) {
@@ -81,43 +131,47 @@ func (ctl *PodCtl) listAndWatch() {
db = db.CreateTable(&Pod{}) db = db.CreateTable(&Pod{})
k8sClient := client.NewK8sClient() k8sClient := ctl.K8sClient
list, err := k8sClient.CoreV1().Pods("").List(meta_v1.ListOptions{}) kubeInformerFactory := informers.NewSharedInformerFactory(k8sClient, time.Second*resyncCircle)
informer := kubeInformerFactory.Core().V1().Pods().Informer()
lister := kubeInformerFactory.Core().V1().Pods().Lister()
list, err := lister.List(labels.Everything())
if err != nil { if err != nil {
glog.Error(err) glog.Error(err)
return panic(err)
} }
for _, item := range list.Items { for _, item := range list {
obj := ctl.generateObject(item) obj := ctl.generateObject(*item)
db.Create(obj) db.Create(obj)
} }
watcher, err := k8sClient.CoreV1().Pods("").Watch(meta_v1.ListOptions{}) informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
if err != nil { AddFunc: func(obj interface{}) {
glog.Error(err) object := obj.(*v1.Pod)
return mysqlObject := ctl.generateObject(*object)
} db.Create(mysqlObject)
for { ctl.addAnnotationToPvc(*object)
select { },
case <-ctl.stopChan: UpdateFunc: func(old, new interface{}) {
return object := new.(*v1.Pod)
case event := <-watcher.ResultChan(): mysqlObject := ctl.generateObject(*object)
var po Pod
if event.Object == nil { db.Save(mysqlObject)
panic("watch timeout, restart pod controller")
} },
object := event.Object.(*v1.Pod) DeleteFunc: func(obj interface{}) {
if event.Type == watch.Deleted { var item Pod
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&po) object := obj.(*v1.Pod)
db.Delete(po) db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&item)
break ctl.delAnnotationFromPvc(*object)
} db.Delete(item)
obj := ctl.generateObject(*object) },
db.Save(obj) })
}
} informer.Run(ctl.stopChan)
} }
func (ctl *PodCtl) CountWithConditions(conditions string) int { func (ctl *PodCtl) CountWithConditions(conditions string) int {
@@ -135,17 +189,6 @@ func (ctl *PodCtl) ListWithConditions(conditions string, paging *Paging) (int, i
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order) listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
for index, item := range list {
var containers []Container
json.Unmarshal([]byte(item.ContainerStr), &containers)
list[index].Containers = containers
list[index].ContainerStr = ""
annotation := make(Annotation)
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
list[index].Annotation = annotation
list[index].AnnotationStr = ""
}
return total, list, nil return total, list, nil
} }

View File

@@ -24,10 +24,9 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/informers"
"k8s.io/client-go/tools/cache"
"kubesphere.io/kubesphere/pkg/client"
) )
const creator = "creator" const creator = "creator"
@@ -60,17 +59,16 @@ func (ctl *PvcCtl) generateObject(item *v1.PersistentVolumeClaim) *Pvc {
} }
accessModeStr = strings.Join(accessModeList, ",") accessModeStr = strings.Join(accessModeList, ",")
annotation, _ := json.Marshal(item.Annotations)
object := &Pvc{Namespace: namespace, Name: name, Status: status, Capacity: capacity, object := &Pvc{Namespace: namespace, Name: name, Status: status, Capacity: capacity,
AccessMode: accessModeStr, StorageClassName: storageClass, CreateTime: createTime, AnnotationStr: string(annotation)} AccessMode: accessModeStr, StorageClassName: storageClass, CreateTime: createTime, Annotation: Annotation{item.Annotations}}
return object return object
} }
func (ctl *PvcCtl) listAndWatch() { func (ctl *PvcCtl) listAndWatch() {
defer func() { defer func() {
defer close(ctl.aliveChan) close(ctl.aliveChan)
if err := recover(); err != nil { if err := recover(); err != nil {
glog.Error(err) glog.Error(err)
return return
@@ -86,43 +84,44 @@ func (ctl *PvcCtl) listAndWatch() {
db = db.CreateTable(&Pvc{}) db = db.CreateTable(&Pvc{})
k8sClient := client.NewK8sClient() k8sClient := ctl.K8sClient
pvcList, err := k8sClient.CoreV1().PersistentVolumeClaims("").List(metaV1.ListOptions{}) kubeInformerFactory := informers.NewSharedInformerFactory(k8sClient, time.Second*resyncCircle)
informer := kubeInformerFactory.Core().V1().PersistentVolumeClaims().Informer()
lister := kubeInformerFactory.Core().V1().PersistentVolumeClaims().Lister()
list, err := lister.List(labels.Everything())
if err != nil { if err != nil {
glog.Error(err) glog.Error(err)
return return
} }
for _, item := range pvcList.Items { for _, item := range list {
obj := ctl.generateObject(&item) obj := ctl.generateObject(item)
db.Create(obj) db.Create(obj)
} }
watcher, err := k8sClient.CoreV1().PersistentVolumeClaims("").Watch(metaV1.ListOptions{}) informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
if err != nil { AddFunc: func(obj interface{}) {
glog.Error(err)
return
}
for { object := obj.(*v1.PersistentVolumeClaim)
select { mysqlObject := ctl.generateObject(object)
case <-ctl.stopChan: db.Create(mysqlObject)
return },
case event := <-watcher.ResultChan(): UpdateFunc: func(old, new interface{}) {
var pvc Pvc object := new.(*v1.PersistentVolumeClaim)
if event.Object == nil { mysqlObject := ctl.generateObject(object)
panic("watch timeout, restart pvc controller") db.Save(mysqlObject)
} },
object := event.Object.(*v1.PersistentVolumeClaim) DeleteFunc: func(obj interface{}) {
if event.Type == watch.Deleted { var item Pvc
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&pvc) object := obj.(*v1.PersistentVolumeClaim)
db.Delete(pvc) db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&item)
break db.Delete(item)
} },
obj := ctl.generateObject(object) })
db.Save(obj)
} informer.Run(ctl.stopChan)
}
} }
func (ctl *PvcCtl) CountWithConditions(conditions string) int { func (ctl *PvcCtl) CountWithConditions(conditions string) int {
@@ -140,11 +139,17 @@ func (ctl *PvcCtl) ListWithConditions(conditions string, paging *Paging) (int, i
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order) listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
for index, item := range list { for index := range list {
annotation := make(map[string]string) inUsePods := list[index].Annotation.Values[inUse]
json.Unmarshal([]byte(item.AnnotationStr), &annotation) var pods []string
list[index].Annotation = annotation
list[index].AnnotationStr = "" json.Unmarshal([]byte(inUsePods), &pods)
if len(pods) > 0 {
list[index].InUse = true
} else {
list[index].InUse = false
}
} }
return total, list, nil return total, list, nil

View File

@@ -17,16 +17,14 @@ limitations under the License.
package controllers package controllers
import ( import (
"encoding/json"
"strings" "strings"
"time" "time"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/api/rbac/v1" "k8s.io/api/rbac/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/informers"
"k8s.io/client-go/tools/cache"
"kubesphere.io/kubesphere/pkg/client"
) )
func (ctl *RoleCtl) generateObject(item v1.Role) *Role { func (ctl *RoleCtl) generateObject(item v1.Role) *Role {
@@ -40,9 +38,7 @@ func (ctl *RoleCtl) generateObject(item v1.Role) *Role {
createTime = time.Now() createTime = time.Now()
} }
annotation, _ := json.Marshal(item.Annotations) object := &Role{Namespace: namespace, Name: name, CreateTime: createTime, Annotation: Annotation{item.Annotations}}
object := &Role{Namespace: namespace, Name: name, CreateTime: createTime, AnnotationStr: string(annotation)}
return object return object
} }
@@ -65,49 +61,49 @@ func (ctl *RoleCtl) listAndWatch() {
db = db.CreateTable(&Role{}) db = db.CreateTable(&Role{})
k8sClient := client.NewK8sClient() k8sClient := ctl.K8sClient
roleList, err := k8sClient.RbacV1().Roles("").List(metaV1.ListOptions{}) kubeInformerFactory := informers.NewSharedInformerFactory(k8sClient, time.Second*resyncCircle)
informer := kubeInformerFactory.Rbac().V1().Roles().Informer()
lister := kubeInformerFactory.Rbac().V1().Roles().Lister()
list, err := lister.List(labels.Everything())
if err != nil { if err != nil {
glog.Error(err) glog.Error(err)
return return
} }
for _, item := range roleList.Items { for _, item := range list {
obj := ctl.generateObject(item) obj := ctl.generateObject(*item)
if obj != nil {
db.Create(obj) db.Create(obj)
}
} }
roleWatcher, err := k8sClient.RbacV1().Roles("").Watch(metaV1.ListOptions{}) informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
if err != nil { AddFunc: func(obj interface{}) {
glog.Error(err)
return
}
for { object := obj.(*v1.Role)
select { mysqlObject := ctl.generateObject(*object)
case <-ctl.stopChan: if mysqlObject != nil {
return db.Create(mysqlObject)
case event := <-roleWatcher.ResultChan():
var role Role
if event.Object == nil {
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)
break
}
obj := ctl.generateObject(*object)
if obj != nil {
db.Save(obj)
}
break
} }
},
UpdateFunc: func(old, new interface{}) {
object := new.(*v1.Role)
mysqlObject := ctl.generateObject(*object)
if mysqlObject != nil {
db.Save(mysqlObject)
} }
},
DeleteFunc: func(obj interface{}) {
var item Role
object := obj.(*v1.Role)
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&item)
db.Delete(item)
},
})
informer.Run(ctl.stopChan)
} }
func (ctl *RoleCtl) CountWithConditions(conditions string) int { func (ctl *RoleCtl) CountWithConditions(conditions string) int {
@@ -125,12 +121,6 @@ func (ctl *RoleCtl) ListWithConditions(conditions string, paging *Paging) (int,
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order) listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
for index, item := range list {
annotation := make(map[string]string)
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
list[index].Annotation = annotation
list[index].AnnotationStr = ""
}
return total, list, nil return total, list, nil
} }

View File

@@ -28,15 +28,15 @@ import (
type resourceControllers struct { type resourceControllers struct {
controllers map[string]Controller controllers map[string]Controller
db *gorm.DB
k8sClient *kubernetes.Clientset k8sClient *kubernetes.Clientset
} }
var stopChan chan struct{} var stopChan chan struct{}
var rec resourceControllers
func (rec *resourceControllers) runContoller(name string) { func (rec *resourceControllers) runContoller(name string) {
var ctl Controller var ctl Controller
attr := CommonAttribute{DB: rec.db, K8sClient: rec.k8sClient, stopChan: stopChan, aliveChan: make(chan struct{})} attr := CommonAttribute{DB: client.NewDBClient(), K8sClient: rec.k8sClient, stopChan: stopChan, aliveChan: make(chan struct{})}
switch name { switch name {
case Deployments: case Deployments:
ctl = &DeploymentCtl{attr} ctl = &DeploymentCtl{attr}
@@ -69,21 +69,39 @@ func (rec *resourceControllers) runContoller(name string) {
} }
func dbHealthCheck(db *gorm.DB) {
for {
count := 0
var err error
for k := 0; k < 5; k++ {
err = db.DB().Ping()
if err != nil {
count++
}
time.Sleep(1 * time.Second)
}
if count > 3 {
panic(err)
}
}
}
func Run() { func Run() {
db := client.NewDBClient()
stopChan := make(chan struct{}) stopChan := make(chan struct{})
defer db.Commit()
defer db.Close()
defer close(stopChan) defer close(stopChan)
rec := resourceControllers{k8sClient: client.NewK8sClient(), db: db, controllers: make(map[string]Controller)} rec = resourceControllers{k8sClient: client.NewK8sClient(), controllers: make(map[string]Controller)}
for _, item := range []string{Deployments, Statefulsets, Daemonsets, PersistentVolumeClaim, Pods, Services, for _, item := range []string{Deployments, Statefulsets, Daemonsets, PersistentVolumeClaim, Pods, Services,
Ingresses, Roles, ClusterRoles, Namespaces, StorageClasses} { Ingresses, Roles, ClusterRoles, Namespaces, StorageClasses} {
rec.runContoller(item) rec.runContoller(item)
} }
go dbHealthCheck(client.NewDBClient())
for { for {
for ctlName, controller := range rec.controllers { for ctlName, controller := range rec.controllers {
select { select {

View File

@@ -17,18 +17,16 @@ limitations under the License.
package controllers package controllers
import ( import (
"encoding/json"
"fmt" "fmt"
"strings" "strings"
"time" "time"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/informers"
"k8s.io/client-go/tools/cache"
"kubesphere.io/kubesphere/pkg/client"
) )
const ( const (
@@ -119,16 +117,15 @@ func (ctl *ServiceCtl) generateObject(item v1.Service) *Service {
ports = ports[0 : len(ports)-1] ports = ports[0 : len(ports)-1]
} }
annotation, _ := json.Marshal(item.Annotations)
object := &Service{Namespace: namespace, Name: name, ServiceType: serviceType, ExternalIp: externalIp, object := &Service{Namespace: namespace, Name: name, ServiceType: serviceType, ExternalIp: externalIp,
VirtualIp: vip, CreateTime: createTime, Ports: ports, AnnotationStr: string(annotation)} VirtualIp: vip, CreateTime: createTime, Ports: ports, Annotation: Annotation{item.Annotations}}
return object return object
} }
func (ctl *ServiceCtl) listAndWatch() { func (ctl *ServiceCtl) listAndWatch() {
defer func() { defer func() {
defer close(ctl.aliveChan) close(ctl.aliveChan)
if err := recover(); err != nil { if err := recover(); err != nil {
glog.Error(err) glog.Error(err)
return return
@@ -143,45 +140,45 @@ func (ctl *ServiceCtl) listAndWatch() {
db = db.CreateTable(&Service{}) db = db.CreateTable(&Service{})
k8sClient := client.NewK8sClient() k8sClient := ctl.K8sClient
svcList, err := k8sClient.CoreV1().Services("").List(metaV1.ListOptions{}) kubeInformerFactory := informers.NewSharedInformerFactory(k8sClient, time.Second*resyncCircle)
informer := kubeInformerFactory.Core().V1().Services().Informer()
lister := kubeInformerFactory.Core().V1().Services().Lister()
list, err := lister.List(labels.Everything())
if err != nil { if err != nil {
glog.Error(err) glog.Error(err)
return return
} }
for _, item := range svcList.Items { for _, item := range list {
obj := ctl.generateObject(item) obj := ctl.generateObject(*item)
db.Create(obj) db.Create(obj)
} }
watcher, err := k8sClient.CoreV1().Services("").Watch(metaV1.ListOptions{}) informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
if err != nil { AddFunc: func(obj interface{}) {
glog.Error(err)
return
}
for { object := obj.(*v1.Service)
select { mysqlObject := ctl.generateObject(*object)
case <-ctl.stopChan: db.Create(mysqlObject)
return },
case event := <-watcher.ResultChan(): UpdateFunc: func(old, new interface{}) {
var svc Service object := new.(*v1.Service)
mysqlObject := ctl.generateObject(*object)
db.Save(mysqlObject)
},
DeleteFunc: func(obj interface{}) {
var item Service
object := obj.(*v1.Service)
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&item)
db.Delete(item)
if event.Object == nil { },
panic("watch timeout, restart service controller") })
}
object := event.Object.(*v1.Service)
if event.Type == watch.Deleted { informer.Run(ctl.stopChan)
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&svc)
db.Delete(svc)
break
}
obj := ctl.generateObject(*object)
db.Save(obj)
}
}
} }
func (ctl *ServiceCtl) CountWithConditions(conditions string) int { func (ctl *ServiceCtl) CountWithConditions(conditions string) int {
@@ -199,12 +196,6 @@ func (ctl *ServiceCtl) ListWithConditions(conditions string, paging *Paging) (in
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order) listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
for index, item := range list {
annotation := make(map[string]string)
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
list[index].Annotation = annotation
list[index].AnnotationStr = ""
}
return total, list, nil return total, list, nil
} }

View File

@@ -17,18 +17,17 @@ limitations under the License.
package controllers package controllers
import ( import (
"encoding/json"
"time" "time"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/api/apps/v1beta2"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/watch"
"kubesphere.io/kubesphere/pkg/client" "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers"
"k8s.io/client-go/tools/cache"
) )
func (ctl *StatefulsetCtl) generateObject(item v1beta2.StatefulSet) *Statefulset { func (ctl *StatefulsetCtl) generateObject(item v1.StatefulSet) *Statefulset {
var app string var app string
var status string var status string
name := item.Name name := item.Name
@@ -50,26 +49,24 @@ func (ctl *StatefulsetCtl) generateObject(item v1beta2.StatefulSet) *Statefulset
} }
if item.Annotations["state"] == "stop" { if item.Annotations["state"] == "stop" {
status = stopping status = Stopped
} else { } else {
if availablePodNum >= desirePodNum { if availablePodNum >= desirePodNum {
status = running status = Running
} else { } else {
status = updating status = Updating
} }
} }
annotation, _ := json.Marshal(item.Annotations)
statefulSetObject := &Statefulset{Namespace: namespace, Name: name, Available: availablePodNum, Desire: desirePodNum, statefulSetObject := &Statefulset{Namespace: namespace, Name: name, Available: availablePodNum, Desire: desirePodNum,
App: app, CreateTime: createTime, Status: status, AnnotationStr: string(annotation)} App: app, CreateTime: createTime, Status: status, Annotation: Annotation{item.Annotations}}
return statefulSetObject return statefulSetObject
} }
func (ctl *StatefulsetCtl) listAndWatch() { func (ctl *StatefulsetCtl) listAndWatch() {
defer func() { defer func() {
defer close(ctl.aliveChan) close(ctl.aliveChan)
if err := recover(); err != nil { if err := recover(); err != nil {
glog.Error(err) glog.Error(err)
return return
@@ -82,42 +79,45 @@ func (ctl *StatefulsetCtl) listAndWatch() {
} }
db = db.CreateTable(&Statefulset{}) db = db.CreateTable(&Statefulset{})
k8sClient := client.NewK8sClient() k8sClient := ctl.K8sClient
deoloyList, err := k8sClient.AppsV1beta2().StatefulSets("").List(metaV1.ListOptions{}) kubeInformerFactory := informers.NewSharedInformerFactory(k8sClient, time.Second*resyncCircle)
informer := kubeInformerFactory.Apps().V1().StatefulSets().Informer()
lister := kubeInformerFactory.Apps().V1().StatefulSets().Lister()
list, err := lister.List(labels.Everything())
if err != nil { if err != nil {
glog.Error(err) glog.Error(err)
return
} }
for _, item := range deoloyList.Items { for _, item := range list {
obj := ctl.generateObject(item) obj := ctl.generateObject(*item)
db.Create(obj) db.Create(obj)
} }
watcher, err := k8sClient.AppsV1beta2().StatefulSets("").Watch(metaV1.ListOptions{}) informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
if err != nil { AddFunc: func(obj interface{}) {
glog.Error(err)
return
}
for { object := obj.(*v1.StatefulSet)
select { mysqlObject := ctl.generateObject(*object)
case <-ctl.stopChan: db.Create(mysqlObject)
return },
case event := <-watcher.ResultChan(): UpdateFunc: func(old, new interface{}) {
var tmp Statefulset object := new.(*v1.StatefulSet)
if event.Object == nil { mysqlObject := ctl.generateObject(*object)
panic("watch timeout, restart statefulset controller") db.Save(mysqlObject)
} },
object := event.Object.(*v1beta2.StatefulSet) DeleteFunc: func(obj interface{}) {
if event.Type == watch.Deleted { var item Statefulset
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&tmp) object := obj.(*v1.StatefulSet)
db.Delete(tmp) db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&item)
break db.Delete(item)
}
obj := ctl.generateObject(*object) },
db.Save(obj) })
}
} informer.Run(ctl.stopChan)
} }
func (ctl *StatefulsetCtl) CountWithConditions(conditions string) int { func (ctl *StatefulsetCtl) CountWithConditions(conditions string) int {
@@ -135,12 +135,6 @@ func (ctl *StatefulsetCtl) ListWithConditions(conditions string, paging *Paging)
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order) listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
for index, item := range list {
annotation := make(map[string]string)
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
list[index].Annotation = annotation
list[index].AnnotationStr = ""
}
return total, list, nil return total, list, nil
} }

View File

@@ -17,19 +17,18 @@ limitations under the License.
package controllers package controllers
import ( import (
"encoding/json"
"fmt" "fmt"
"time" "time"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/api/storage/v1beta1" "k8s.io/api/storage/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/watch"
"kubesphere.io/kubesphere/pkg/client" "k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers"
"k8s.io/client-go/tools/cache"
) )
func (ctl *StorageClassCtl) generateObject(item v1beta1.StorageClass) *StorageClass { func (ctl *StorageClassCtl) generateObject(item v1.StorageClass) *StorageClass {
name := item.Name name := item.Name
createTime := item.CreationTimestamp.Time createTime := item.CreationTimestamp.Time
@@ -42,15 +41,14 @@ func (ctl *StorageClassCtl) generateObject(item v1beta1.StorageClass) *StorageCl
createTime = time.Now() createTime = time.Now()
} }
annotation, _ := json.Marshal(item.Annotations) object := &StorageClass{Name: name, CreateTime: createTime, IsDefault: isDefault, Annotation: Annotation{item.Annotations}}
object := &StorageClass{Name: name, CreateTime: createTime, IsDefault: isDefault, AnnotationStr: string(annotation)}
return object return object
} }
func (ctl *StorageClassCtl) listAndWatch() { func (ctl *StorageClassCtl) listAndWatch() {
defer func() { defer func() {
defer close(ctl.aliveChan) close(ctl.aliveChan)
if err := recover(); err != nil { if err := recover(); err != nil {
glog.Error(err) glog.Error(err)
return return
@@ -65,43 +63,46 @@ func (ctl *StorageClassCtl) listAndWatch() {
db = db.CreateTable(&StorageClass{}) db = db.CreateTable(&StorageClass{})
k8sClient := client.NewK8sClient() k8sClient := ctl.K8sClient
list, err := k8sClient.StorageV1beta1().StorageClasses().List(meta_v1.ListOptions{}) kubeInformerFactory := informers.NewSharedInformerFactory(k8sClient, time.Second*resyncCircle)
informer := kubeInformerFactory.Storage().V1().StorageClasses().Informer()
lister := kubeInformerFactory.Storage().V1().StorageClasses().Lister()
list, err := lister.List(labels.Everything())
if err != nil { if err != nil {
glog.Error(err) glog.Error(err)
return return
} }
for _, item := range list.Items { for _, item := range list {
obj := ctl.generateObject(item) obj := ctl.generateObject(*item)
db.Create(obj) db.Create(obj)
} }
watcher, err := k8sClient.StorageV1beta1().StorageClasses().Watch(meta_v1.ListOptions{}) informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
if err != nil { AddFunc: func(obj interface{}) {
glog.Error(err)
return object := obj.(*v1.StorageClass)
} mysqlObject := ctl.generateObject(*object)
db.Create(mysqlObject)
},
UpdateFunc: func(old, new interface{}) {
object := new.(*v1.StorageClass)
mysqlObject := ctl.generateObject(*object)
db.Save(mysqlObject)
},
DeleteFunc: func(obj interface{}) {
var item StorageClass
object := obj.(*v1.StorageClass)
db.Where("name=?", object.Name).Find(&item)
db.Delete(item)
},
})
informer.Run(ctl.stopChan)
for {
select {
case <-ctl.stopChan:
return
case event := <-watcher.ResultChan():
var sc StorageClass
if event.Object == nil {
panic("watch timeout, restart storageClass controller")
}
object := event.Object.(*v1beta1.StorageClass)
if event.Type == watch.Deleted {
db.Where("name=?", object.Name).Find(&sc)
db.Delete(sc)
break
}
obj := ctl.generateObject(*object)
db.Save(obj)
}
}
} }
func (ctl *StorageClassCtl) CountWithConditions(conditions string) int { func (ctl *StorageClassCtl) CountWithConditions(conditions string) int {
@@ -121,10 +122,6 @@ func (ctl *StorageClassCtl) ListWithConditions(conditions string, paging *Paging
for index, storageClass := range list { for index, storageClass := range list {
name := storageClass.Name name := storageClass.Name
annotation := make(map[string]string)
json.Unmarshal([]byte(storageClass.AnnotationStr), &annotation)
list[index].Annotation = annotation
list[index].AnnotationStr = ""
pvcCtl := PvcCtl{CommonAttribute{K8sClient: ctl.K8sClient, DB: ctl.DB}} pvcCtl := PvcCtl{CommonAttribute{K8sClient: ctl.K8sClient, DB: ctl.DB}}
list[index].Count = pvcCtl.CountWithConditions(fmt.Sprintf("storage_class=\"%s\"", name)) list[index].Count = pvcCtl.CountWithConditions(fmt.Sprintf("storage_class=\"%s\"", name))

View File

@@ -19,15 +19,20 @@ package controllers
import ( import (
"time" "time"
"database/sql/driver"
"encoding/json"
"errors"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
) )
const ( const (
stopping = "stopped" resyncCircle = 180
running = "running" Stopped = "stopped"
updating = "updating" Running = "running"
Updating = "updating"
tablePods = "pods" tablePods = "pods"
tableDeployments = "deployments" tableDeployments = "deployments"
tableDaemonsets = "daemonsets" tableDaemonsets = "daemonsets"
@@ -53,29 +58,26 @@ const (
StorageClasses = "storage-classes" StorageClasses = "storage-classes"
) )
var ResourceTable = map[string]string{Deployments: tableDeployments, Statefulsets: tableStatefulsets, Daemonsets: tableDaemonsets, type Annotation struct {
Pods: tablePods, Namespaces: tableNamespaces, Ingresses: tableIngresses, PersistentVolumeClaim: tablePersistentVolumeClaim, Roles: tableRoles, Values map[string]string `gorm:"type:TEXT"`
Services: tableServices, StorageClasses: tableStorageClasses, ClusterRoles: tableClusterRoles} }
type Annotation map[string]string func (annotation *Annotation) Scan(val interface{}) error {
switch val := val.(type) {
case string:
return json.Unmarshal([]byte(val), annotation)
case []byte:
return json.Unmarshal(val, annotation)
default:
return errors.New("not support")
}
return nil
}
// func (annotation Annotation) Value() (driver.Value, error) {
//func (annotation *Annotation)Scan(val interface{}) error{ bytes, err := json.Marshal(annotation)
// switch val := val.(type){ return string(bytes), err
// case string: }
// return json.Unmarshal([]byte(val), annotation)
// case []byte:
// return json.Unmarshal(val, annotation)
// default:
// return errors.New("not support")
// }
// return nil
//}
//
//func (annotation *Annotation)Value() (driver.Value, error){
// bytes, err := json.Marshal(annotation)
// return string(bytes), err
//}
type Deployment struct { type Deployment struct {
Name string `gorm:"primary_key" json:"name"` Name string `gorm:"primary_key" json:"name"`
@@ -85,8 +87,7 @@ type Deployment struct {
Available int32 `json:"available"` Available int32 `json:"available"`
Desire int32 `json:"desire"` Desire int32 `json:"desire"`
Status string `json:"status"` Status string `json:"status"`
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"` Annotation Annotation `json:"annotations"`
Annotation Annotation `gorm:"-" json:"annotation"`
UpdateTime time.Time `gorm:"column:updateTime" json:"updateTime,omitempty"` UpdateTime time.Time `gorm:"column:updateTime" json:"updateTime,omitempty"`
} }
@@ -102,8 +103,7 @@ type Statefulset struct {
Available int32 `json:"available"` Available int32 `json:"available"`
Desire int32 `json:"desire"` Desire int32 `json:"desire"`
Status string `json:"status"` Status string `json:"status"`
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"` Annotation Annotation `json:"annotations"`
Annotation Annotation `gorm:"-" json:"annotation"`
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"` CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
} }
@@ -120,8 +120,7 @@ type Daemonset struct {
Desire int32 `json:"desire"` Desire int32 `json:"desire"`
Status string `json:"status"` Status string `json:"status"`
NodeSelector string `json:"nodeSelector, omitempty"` NodeSelector string `json:"nodeSelector, omitempty"`
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"` Annotation Annotation `json:"annotations"`
Annotation Annotation `gorm:"-" json:"annotation"`
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"` CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
} }
@@ -138,8 +137,7 @@ type Service struct {
ExternalIp string `json:"externalIp,omitempty"` ExternalIp string `json:"externalIp,omitempty"`
Ports string `json:"ports,omitempty"` Ports string `json:"ports,omitempty"`
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"` Annotation Annotation `json:"annotations"`
Annotation Annotation `gorm:"-" json:"annotation"`
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"` CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
} }
@@ -153,10 +151,10 @@ type Pvc struct {
Status string `json:"status,omitempty"` Status string `json:"status,omitempty"`
Capacity string `json:"capacity,omitempty"` Capacity string `json:"capacity,omitempty"`
AccessMode string `json:"accessMode,omitempty"` AccessMode string `json:"accessMode,omitempty"`
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"` Annotation Annotation `json:"annotations"`
Annotation Annotation `gorm:"-" json:"annotation"`
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"` CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
StorageClassName string `gorm:"column:storage_class" json:"storage_class,omitempty"` StorageClassName string `gorm:"column:storage_class" json:"storage_class,omitempty"`
InUse bool `gorm:"-" json:"inUse"`
} }
func (Pvc) TableName() string { func (Pvc) TableName() string {
@@ -168,8 +166,7 @@ type Ingress struct {
Namespace string `gorm:"primary_key" json:"namespace"` Namespace string `gorm:"primary_key" json:"namespace"`
Ip string `json:"ip,omitempty"` Ip string `json:"ip,omitempty"`
TlsTermination string `json:"tlsTermination,omitempty"` TlsTermination string `json:"tlsTermination,omitempty"`
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"` Annotation Annotation `json:"annotations"`
Annotation Annotation `gorm:"-" json:"annotation"`
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"` CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
} }
@@ -184,10 +181,8 @@ type Pod struct {
Node string `json:"node,omitempty"` Node string `json:"node,omitempty"`
NodeIp string `json:"nodeIp,omitempty"` NodeIp string `json:"nodeIp,omitempty"`
PodIp string `json:"podIp,omitempty"` PodIp string `json:"podIp,omitempty"`
ContainerStr string `gorm:"type:text" json:",omitempty"` Containers Containers `gorm:"type:text" json:"containers,omitempty"`
Containers []Container `json:"containers,omitempty"` Annotation Annotation `json:"annotations"`
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"`
Annotation Annotation `gorm:"-" json:"annotation"`
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"` CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
} }
@@ -195,8 +190,27 @@ type Container struct {
Name string `json:"name"` Name string `json:"name"`
Ready bool `json:"ready,omitempty"` Ready bool `json:"ready,omitempty"`
Image string `json:"image"` Image string `json:"image"`
Resources v1.ResourceRequirements `json:"resources"`
Ports []v1.ContainerPort `json:"ports"` Ports []v1.ContainerPort `json:"ports"`
} }
type Containers []Container
func (containers *Containers) Scan(val interface{}) error {
switch val := val.(type) {
case string:
return json.Unmarshal([]byte(val), containers)
case []byte:
return json.Unmarshal(val, containers)
default:
return errors.New("not support")
}
return nil
}
func (containers Containers) Value() (driver.Value, error) {
bytes, err := json.Marshal(containers)
return string(bytes), err
}
func (Pod) TableName() string { func (Pod) TableName() string {
return tablePods return tablePods
@@ -205,8 +219,7 @@ func (Pod) TableName() string {
type Role struct { type Role struct {
Name string `gorm:"primary_key" json:"name"` Name string `gorm:"primary_key" json:"name"`
Namespace string `gorm:"primary_key" json:"namespace"` Namespace string `gorm:"primary_key" json:"namespace"`
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"` Annotation Annotation `json:"annotations"`
Annotation Annotation `gorm:"-" json:"annotation"`
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"` CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
} }
@@ -216,8 +229,7 @@ func (Role) TableName() string {
type ClusterRole struct { type ClusterRole struct {
Name string `gorm:"primary_key" json:"name"` Name string `gorm:"primary_key" json:"name"`
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"` Annotation Annotation `json:"annotations"`
Annotation Annotation `gorm:"-" json:"annotation"`
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"` CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
} }
@@ -231,9 +243,9 @@ type Namespace struct {
Status string `json:"status"` Status string `json:"status"`
Descrition string `json:"description,omitempty"` Descrition string `json:"description,omitempty"`
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"` Annotation Annotation `json:"annotations"`
Annotation Annotation `gorm:"-" json:"annotation"`
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"` CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
Usaeg v1.ResourceList `gorm:"-" json:"usage,omitempty"`
} }
func (Namespace) TableName() string { func (Namespace) TableName() string {
@@ -243,8 +255,7 @@ func (Namespace) TableName() string {
type StorageClass struct { type StorageClass struct {
Name string `gorm:"primary_key" json:"name"` Name string `gorm:"primary_key" json:"name"`
Creator string `json:"creator,omitempty"` Creator string `json:"creator,omitempty"`
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"` Annotation Annotation `json:"annotations"`
Annotation Annotation `gorm:"-" json:"annotation"`
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"` CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
IsDefault bool `json:"default"` IsDefault bool `json:"default"`
Count int `json:"count"` Count int `json:"count"`
@@ -262,7 +273,8 @@ type Controller interface {
listAndWatch() listAndWatch()
chanStop() chan struct{} chanStop() chan struct{}
chanAlive() chan struct{} chanAlive() chan struct{}
Count(conditions string) int Count(namespace string) int
CountWithConditions(condition string) int
ListWithConditions(condition string, paging *Paging) (int, interface{}, error) ListWithConditions(condition string, paging *Paging) (int, interface{}, error)
} }
@@ -326,36 +338,3 @@ type RoleCtl struct {
type ClusterRoleCtl struct { type ClusterRoleCtl struct {
CommonAttribute CommonAttribute
} }
func listWithConditions(db *gorm.DB, total *int, object, list interface{}, conditions string, paging *Paging, order string) {
if len(conditions) == 0 {
db.Model(object).Count(total)
} else {
db.Model(object).Where(conditions).Count(total)
}
if paging != nil {
if len(conditions) > 0 {
db.Where(conditions).Order(order).Limit(paging.Limit).Offset(paging.Offset).Find(list)
} else {
db.Order(order).Limit(paging.Limit).Offset(paging.Offset).Find(list)
}
} else {
if len(conditions) > 0 {
db.Where(conditions).Order(order).Find(list)
} else {
db.Order(order).Find(list)
}
}
}
func countWithConditions(db *gorm.DB, conditions string, object interface{}) int {
var count int
if len(conditions) == 0 {
db.Model(object).Count(&count)
} else {
db.Model(object).Where(conditions).Count(&count)
}
return count
}

View File

@@ -136,22 +136,29 @@ func generateConditionAndPaging(conditions map[string]string, paging map[string]
type workLoadStatus struct { type workLoadStatus struct {
NameSpace string `json:"namespace"` NameSpace string `json:"namespace"`
Count map[string]int `json:"data"` Count map[string]int `json:"data"`
Items map[string]interface{} Items map[string]interface{} `json:"items,omitempty"`
} }
func GetNamespacesResourceStatus(namespace string) (*workLoadStatus, error) { func GetNamespacesResourceStatus(namespace string) (*workLoadStatus, error) {
res := workLoadStatus{Count: make(map[string]int), NameSpace: namespace, Items: make(map[string]interface{})} res := workLoadStatus{Count: make(map[string]int), NameSpace: namespace, Items: make(map[string]interface{})}
var status *ResourceList
var err error
for _, resource := range []string{controllers.Deployments, controllers.Statefulsets, controllers.Daemonsets} { for _, resource := range []string{controllers.Deployments, controllers.Statefulsets, controllers.Daemonsets} {
status, err := ListResource(resource, "status=updating", "") if len(namespace) > 0 {
status, err = ListResource(resource, fmt.Sprintf("status=%s,namespace=%s", controllers.Updating, namespace), "")
} else {
status, err = ListResource(resource, fmt.Sprintf("status=%s", controllers.Updating), "")
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
count := status.Total count := status.Total
items := status.Items //items := status.Items
res.Count[resource] = count res.Count[resource] = count
res.Items[resource] = items //res.Items[resource] = items
} }
return &res, nil return &res, nil

View File

@@ -11,6 +11,10 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
//
// the code is mainly from:
// https://github.com/kubernetes/dashboard/blob/master/src/app/backend/handler/terminal.go
// thanks to the related developer
package models package models