add namespace's resource usage Statistics and fix some bugs
This commit is contained in:
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
52
pkg/models/controllers/common.go
Normal file
52
pkg/models/controllers/common.go
Normal 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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user