Merge branch 'master' of https://gitlab.educg.net/wangmingjian/k8s-manager
Conflicts: install.yaml
This commit is contained in:
commit
93a7210db3
10
install.yaml
10
install.yaml
|
|
@ -33,11 +33,15 @@ spec:
|
||||||
value: "!bd832W0@CG"
|
value: "!bd832W0@CG"
|
||||||
- name: ASE_KEY
|
- name: ASE_KEY
|
||||||
value: A5es$&!0GeoEast
|
value: A5es$&!0GeoEast
|
||||||
|
- name: NFS_HOST
|
||||||
|
value: 192.168.252.250
|
||||||
|
- name: NFS_PATH
|
||||||
|
value: /mnt/CGdata/ms
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: persistent-storage
|
- name: k8s-manager-nfs-volume
|
||||||
mountPath: /nfs
|
mountPath: /mnt/CGdata/ms
|
||||||
volumes:
|
volumes:
|
||||||
- name: persistent-storage
|
- name: k8s-manager-nfs-volume
|
||||||
nfs:
|
nfs:
|
||||||
server: 192.168.252.250
|
server: 192.168.252.250
|
||||||
path: /mnt/CGdata/ms
|
path: /mnt/CGdata/ms
|
||||||
|
|
|
||||||
29
main.go
29
main.go
|
|
@ -21,21 +21,10 @@ import (
|
||||||
//go:embed template/* static/*
|
//go:embed template/* static/*
|
||||||
var f embed.FS
|
var f embed.FS
|
||||||
|
|
||||||
var jwtKey string
|
|
||||||
var aseKey string
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
m.InitConfig()
|
||||||
m.InitClient()
|
m.InitClient()
|
||||||
|
|
||||||
jwtKey = os.Getenv("JWT_KEY")
|
|
||||||
aseKey = os.Getenv("ASE_KEY")
|
|
||||||
if jwtKey == "" {
|
|
||||||
panic("No jwt key")
|
|
||||||
}
|
|
||||||
if aseKey == "" {
|
|
||||||
panic("No ase key")
|
|
||||||
}
|
|
||||||
|
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
|
|
||||||
fp, _ := fs.Sub(f, "static")
|
fp, _ := fs.Sub(f, "static")
|
||||||
|
|
@ -52,7 +41,9 @@ func main() {
|
||||||
r.POST("/dep", m.JWTAuthMiddleware, m.CreateDeleteDeployment)
|
r.POST("/dep", m.JWTAuthMiddleware, m.CreateDeleteDeployment)
|
||||||
r.DELETE("/dep", m.JWTAuthMiddleware, m.CreateDeleteDeployment)
|
r.DELETE("/dep", m.JWTAuthMiddleware, m.CreateDeleteDeployment)
|
||||||
|
|
||||||
r.GET("/login", Test)
|
r.GET("/pod", m.JWTAuthMiddleware, m.GetPodStatus)
|
||||||
|
|
||||||
|
r.GET("/login", LoginToken)
|
||||||
r.Any("/test_token", TestToken)
|
r.Any("/test_token", TestToken)
|
||||||
r.GET("/username", m.JWTAuthMiddleware, m.GetUsername)
|
r.GET("/username", m.JWTAuthMiddleware, m.GetUsername)
|
||||||
err := r.Run(":8000")
|
err := r.Run(":8000")
|
||||||
|
|
@ -76,10 +67,10 @@ func ParseCGToken(token string) (string, error) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
jwtString := AesDecryptECB(aesEncrypt, []byte(aseKey))
|
jwtString := AesDecryptECB(aesEncrypt, []byte(m.GetConfig().AseKey))
|
||||||
|
|
||||||
jwtResult, err := jwt.ParseWithClaims(string(jwtString), &CGJWTClaim{}, func(token *jwt.Token) (i interface{}, err error) {
|
jwtResult, err := jwt.ParseWithClaims(string(jwtString), &CGJWTClaim{}, func(token *jwt.Token) (i interface{}, err error) {
|
||||||
return []byte(jwtKey), nil
|
return []byte(m.GetConfig().JwtKey), nil
|
||||||
// return hmac.New(sha256.New, []byte(jwtKey)), nil
|
// return hmac.New(sha256.New, []byte(jwtKey)), nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -146,7 +137,7 @@ func AesDecrypt(data []byte, key []byte) ([]byte, error) {
|
||||||
return crypted, nil
|
return crypted, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test(c *gin.Context) {
|
func LoginToken(c *gin.Context) {
|
||||||
username := c.Request.URL.Query().Get("username")
|
username := c.Request.URL.Query().Get("username")
|
||||||
var err error
|
var err error
|
||||||
if username == "" {
|
if username == "" {
|
||||||
|
|
@ -158,6 +149,11 @@ func Test(c *gin.Context) {
|
||||||
"msg": "user name error",
|
"msg": "user name error",
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
Login(c, username)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Login(c *gin.Context, username string) {
|
||||||
token, err := m.GenerateToken(username)
|
token, err := m.GenerateToken(username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
|
|
@ -176,7 +172,6 @@ func Test(c *gin.Context) {
|
||||||
}
|
}
|
||||||
c.Redirect(http.StatusTemporaryRedirect, redirectUrl)
|
c.Redirect(http.StatusTemporaryRedirect, redirectUrl)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func TestToken(c *gin.Context) {
|
func TestToken(c *gin.Context) {
|
||||||
token := c.Request.URL.Query().Get("cgtoken")
|
token := c.Request.URL.Query().Get("cgtoken")
|
||||||
|
|
|
||||||
|
|
@ -37,21 +37,25 @@ func (a *AppModel) Fill() error {
|
||||||
return res.Error
|
return res.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AppModel) Update() error {
|
func (a *AppModel) fillDefaults() {
|
||||||
if a.SvcName == "" {
|
if a.SvcName == "" {
|
||||||
a.SvcName = "svc"
|
a.SvcName = "svc"
|
||||||
}
|
}
|
||||||
a.SvcName = strings.TrimPrefix(a.SvcName, a.NamePrefix()+"-")
|
a.SvcName = strings.TrimPrefix(a.SvcName, a.NamePrefix()+"-")
|
||||||
|
if a.PersistentPath == "" {
|
||||||
|
a.PersistentPath = "/data/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppModel) Update() error {
|
||||||
|
a.fillDefaults()
|
||||||
db := DB()
|
db := DB()
|
||||||
db.Save(a)
|
db.Save(a)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AppModel) Create() error {
|
func (a *AppModel) Create() error {
|
||||||
if a.SvcName == "" {
|
a.fillDefaults()
|
||||||
a.SvcName = "svc"
|
|
||||||
}
|
|
||||||
a.SvcName = strings.TrimPrefix(a.SvcName, a.NamePrefix()+"-")
|
|
||||||
db := DB()
|
db := DB()
|
||||||
db.Create(a)
|
db.Create(a)
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -156,7 +160,7 @@ func (a *AppModel) PersistentVolumeName() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AppModel) NFSPath() string {
|
func (a *AppModel) NFSPath() string {
|
||||||
return "/data/" + a.UserName
|
return GetConfig().NFSPath + "/" + a.UserName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AppModel) PersistentVolumeClaimName() string {
|
func (a *AppModel) PersistentVolumeClaimName() string {
|
||||||
|
|
@ -166,3 +170,7 @@ func (a *AppModel) PersistentVolumeClaimName() string {
|
||||||
func (a *AppModel) StorageClassName() string {
|
func (a *AppModel) StorageClassName() string {
|
||||||
return a.NamePrefix() + "-storage-class"
|
return a.NamePrefix() + "-storage-class"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *AppModel) PersistentVolumeMountName() string {
|
||||||
|
return a.NamePrefix() + "-pvm"
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
package k8s_manager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
JwtKey string
|
||||||
|
AseKey string
|
||||||
|
DBHost string
|
||||||
|
DBUser string
|
||||||
|
DBPassword string
|
||||||
|
NFSHost string
|
||||||
|
NFSPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
var config *Config
|
||||||
|
|
||||||
|
func getField(v *Config, field string) string {
|
||||||
|
r := reflect.ValueOf(v)
|
||||||
|
f := reflect.Indirect(r).FieldByName(field)
|
||||||
|
return f.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func setField(v *Config, field string, value string) {
|
||||||
|
r := reflect.ValueOf(v)
|
||||||
|
f := reflect.Indirect(r).FieldByName(field)
|
||||||
|
f.SetString(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitConfig() {
|
||||||
|
config = &Config{}
|
||||||
|
config.JwtKey = os.Getenv("JWT_KEY")
|
||||||
|
config.AseKey = os.Getenv("ASE_KEY")
|
||||||
|
config.DBHost = os.Getenv("DB_HOST")
|
||||||
|
config.DBUser = os.Getenv("DB_USER")
|
||||||
|
config.DBPassword = os.Getenv("DB_PASS")
|
||||||
|
config.NFSHost = os.Getenv("NFS_HOST")
|
||||||
|
config.NFSPath = os.Getenv("NFS_PATH")
|
||||||
|
|
||||||
|
mustFields := []string{"JwtKey", "AseKey", "DBHost", "DBUser", "DBPassword", "NFSHost", "NFSPath"}
|
||||||
|
optionalFields := map[string]string{}
|
||||||
|
for _, f := range mustFields {
|
||||||
|
if getField(config, f) == "" {
|
||||||
|
panic(fmt.Sprintf("field %s must be set.", f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for f, v := range optionalFields {
|
||||||
|
if getField(config, f) == "" {
|
||||||
|
setField(config, f, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetConfig() *Config {
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
@ -49,3 +49,20 @@ func CreateDeleteDeployment(c *gin.Context) {
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, gin.H{"msg": "ok"})
|
c.JSON(http.StatusOK, gin.H{"msg": "ok"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetPodStatus(c *gin.Context) {
|
||||||
|
id := c.Query("id")
|
||||||
|
if strings.TrimSpace(id) == "" {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"msg": "no app id"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
appId, err := strconv.Atoi(id)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"msg": "wrong id"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
app := AppModel{Id: appId}
|
||||||
|
app.Fill()
|
||||||
|
pod := K.GetPodFromDeployment(app.DeploymentName())
|
||||||
|
c.JSON(http.StatusOK, pod.Status)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,20 +72,27 @@ func (c *K8sClient) DeploymentExists(deploymentName string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *K8sClient) UpdateDeployment(app *AppModel) {
|
func (c *K8sClient) UpdateDeployment(app *AppModel) {
|
||||||
var rep int32 = 1
|
|
||||||
labelKey, labelValue := app.GetLabel()
|
labelKey, labelValue := app.GetLabel()
|
||||||
l := map[string]string{labelKey: labelValue}
|
l := map[string]string{labelKey: labelValue}
|
||||||
|
if _, err := os.Stat(app.NFSPath()); os.IsNotExist(err) {
|
||||||
|
os.MkdirAll(app.NFSPath(), os.ModeDir)
|
||||||
|
}
|
||||||
podLabels := map[string]string{
|
podLabels := map[string]string{
|
||||||
labelKey: labelValue,
|
labelKey: labelValue,
|
||||||
"cg-deployment": app.DeploymentName(),
|
"cg-deployment": app.DeploymentName(),
|
||||||
}
|
}
|
||||||
|
containerPorts := funk.Map(app.GetPorts(), func(port int32) v1.ContainerPort {
|
||||||
|
return v1.ContainerPort{
|
||||||
|
ContainerPort: port,
|
||||||
|
}
|
||||||
|
}).([]v1.ContainerPort)
|
||||||
deployment := &appv1.Deployment{
|
deployment := &appv1.Deployment{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: app.DeploymentName(),
|
Name: app.DeploymentName(),
|
||||||
Labels: l,
|
Labels: l,
|
||||||
},
|
},
|
||||||
Spec: appv1.DeploymentSpec{
|
Spec: appv1.DeploymentSpec{
|
||||||
Replicas: &rep,
|
Replicas: UnnamedPointer(int32(1)),
|
||||||
Selector: &metav1.LabelSelector{
|
Selector: &metav1.LabelSelector{
|
||||||
MatchLabels: l,
|
MatchLabels: l,
|
||||||
},
|
},
|
||||||
|
|
@ -102,14 +109,30 @@ func (c *K8sClient) UpdateDeployment(app *AppModel) {
|
||||||
Name: "URL_PREFIX",
|
Name: "URL_PREFIX",
|
||||||
Value: app.ServiceName(),
|
Value: app.ServiceName(),
|
||||||
}),
|
}),
|
||||||
VolumeMounts: nil,
|
//VolumeMounts: []v1.VolumeMount{
|
||||||
Ports: []v1.ContainerPort{
|
// {
|
||||||
{ContainerPort: 80},
|
// Name: app.PersistentVolumeMountName(),
|
||||||
},
|
// ReadOnly: false,
|
||||||
|
// MountPath: app.PersistentPath,
|
||||||
|
// },
|
||||||
|
//},
|
||||||
|
Ports: containerPorts,
|
||||||
SecurityContext: &v1.SecurityContext{
|
SecurityContext: &v1.SecurityContext{
|
||||||
RunAsUser: UnnamedPointer(int64(0)),
|
RunAsUser: UnnamedPointer(int64(0)),
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
|
//Volumes: []v1.Volume{
|
||||||
|
// {
|
||||||
|
// Name: app.PersistentVolumeMountName(),
|
||||||
|
// VolumeSource: v1.VolumeSource{
|
||||||
|
// NFS: &v1.NFSVolumeSource{
|
||||||
|
// Server: config.NFSHost,
|
||||||
|
// Path: app.NFSPath(),
|
||||||
|
// ReadOnly: false,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
//},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -362,7 +385,7 @@ func (c *K8sClient) CreatePersistentVolume(app *AppModel) {
|
||||||
StorageClassName: app.StorageClassName(),
|
StorageClassName: app.StorageClassName(),
|
||||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||||
NFS: &v1.NFSVolumeSource{
|
NFS: &v1.NFSVolumeSource{
|
||||||
Server: "192.168.1.1",
|
Server: GetConfig().NFSHost,
|
||||||
Path: app.NFSPath(),
|
Path: app.NFSPath(),
|
||||||
ReadOnly: false,
|
ReadOnly: false,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
19
src/orm.go
19
src/orm.go
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"gorm.io/driver/mysql"
|
"gorm.io/driver/mysql"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"os"
|
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -16,18 +15,9 @@ func opendb() *gorm.DB {
|
||||||
if instance == nil {
|
if instance == nil {
|
||||||
lock.Lock()
|
lock.Lock()
|
||||||
if instance == nil {
|
if instance == nil {
|
||||||
db_host, ok := os.LookupEnv("DB_HOST")
|
db_host := GetConfig().DBHost
|
||||||
if !ok {
|
db_user := GetConfig().DBUser
|
||||||
panic("DB_HOST NOT SET")
|
db_pass := GetConfig().DBPassword
|
||||||
}
|
|
||||||
db_user, ok := os.LookupEnv("DB_USER")
|
|
||||||
if !ok {
|
|
||||||
panic("DB_USER NOT SET")
|
|
||||||
}
|
|
||||||
db_pass, ok := os.LookupEnv("DB_PASS")
|
|
||||||
if !ok {
|
|
||||||
panic("DB_PASS NOT SET")
|
|
||||||
}
|
|
||||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:3306)/k8s?charset=utf8mb4&parseTime=True&loc=Local", db_user, db_pass, db_host)
|
dsn := fmt.Sprintf("%s:%s@tcp(%s:3306)/k8s?charset=utf8mb4&parseTime=True&loc=Local", db_user, db_pass, db_host)
|
||||||
var err error
|
var err error
|
||||||
instance, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
instance, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
||||||
|
|
@ -43,6 +33,9 @@ func opendb() *gorm.DB {
|
||||||
|
|
||||||
func checkdb(cnt int) *gorm.DB {
|
func checkdb(cnt int) *gorm.DB {
|
||||||
ans := opendb()
|
ans := opendb()
|
||||||
|
if ans == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
db, err := ans.DB()
|
db, err := ans.DB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).Error("Cannot get *sql.DB.")
|
logrus.WithError(err).Error("Cannot get *sql.DB.")
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,14 @@
|
||||||
<td> {{ item.Image }}</td>
|
<td> {{ item.Image }}</td>
|
||||||
<td> {{ item.Command }}</td>
|
<td> {{ item.Command }}</td>
|
||||||
<td> {{ item.Env }}</td>
|
<td> {{ item.Env }}</td>
|
||||||
<td> {{ item.Status }}</td>
|
<td>
|
||||||
|
<span v-if="item.Status == 'Halt'">
|
||||||
|
{{ item.Status }}
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
<a href="javascript:void(0)" @click="showPodStatus(item)">{{ item.Status }}</a>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
<td><a :href="'/' + item.ServiceDisplayName + '/'" target="_blank">{{ item.ServiceDisplayName }}</a></td>
|
<td><a :href="'/' + item.ServiceDisplayName + '/'" target="_blank">{{ item.ServiceDisplayName }}</a></td>
|
||||||
<td> {{ item.Ports }}</td>
|
<td> {{ item.Ports }}</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
@ -112,7 +119,14 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label for="app-ports" class="form-label">端口号</label>
|
<label for="app-ports" class="form-label">端口号</label>
|
||||||
<input type="text" id="app-ports" class="form-control" v-model="selectApp.Ports"
|
<input type="text" id="app-ports" class="form-control" v-model="selectApp.Ports"
|
||||||
placeholder="端口号,多个端口以逗号分隔"/>
|
placeholder="端口号"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<label for="app-ports" class="form-label">持久化路径</label>
|
||||||
|
<input type="text" id="app-persistent-path" class="form-control"
|
||||||
|
v-model="selectApp.PersistentPath"
|
||||||
|
placeholder="持久化路径"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
@ -136,13 +150,27 @@
|
||||||
<strong class="me-auto">请求失败</strong>
|
<strong class="me-auto">请求失败</strong>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="toast-body">
|
<div class="toast-body" v-html="toastText">
|
||||||
{{ toastText }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="modal" tabindex="-1" id="pod-status-modal">
|
||||||
|
<div class="modal-dialog modal-dialog-scrollable">
|
||||||
|
<div class="modal-header">
|
||||||
|
Pod详情
|
||||||
|
</div>
|
||||||
|
<div class="modal-content">{{ podStatus }}</div>
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|
@ -165,8 +193,11 @@
|
||||||
Comment: "",
|
Comment: "",
|
||||||
Env: "",
|
Env: "",
|
||||||
SvcName: "",
|
SvcName: "",
|
||||||
|
PersistentPath: "",
|
||||||
Ports: "",
|
Ports: "",
|
||||||
}
|
},
|
||||||
|
timer: null,
|
||||||
|
podStatus: ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -216,11 +247,22 @@
|
||||||
this.username = r.data.Username
|
this.username = r.data.Username
|
||||||
this.apps = r.data.Apps
|
this.apps = r.data.Apps
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
showPodStatus(app) {
|
||||||
|
axios.get("pod?id=" + app.Id).then(r => {
|
||||||
|
this.podStatus = JSON.stringify(r.data, null, 2);
|
||||||
|
(new bootstrap.Modal("#pod-status-modal")).show();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.blankApp = JSON.parse(JSON.stringify(this.selectApp))
|
this.blankApp = JSON.parse(JSON.stringify(this.selectApp))
|
||||||
this.refresh()
|
this.refresh()
|
||||||
|
if (this.timer) {
|
||||||
|
clearInterval(this.timer)
|
||||||
|
this.timer = null
|
||||||
|
}
|
||||||
|
setInterval(this.timer, this.refresh, 5000)
|
||||||
}
|
}
|
||||||
}).mount("#app")
|
}).mount("#app")
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue