mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-24 11:09:16 +08:00
fix: 镜像操作状态获取、显示优化
This commit is contained in:
parent
bce1995969
commit
b0e23ec2c7
@ -86,7 +86,7 @@ func (u *CronjobService) HandleBackup(cronjob *model.Cronjob, startTime time.Tim
|
|||||||
}
|
}
|
||||||
baseDir = localDir
|
baseDir = localDir
|
||||||
} else {
|
} else {
|
||||||
baseDir = constant.TmpDir
|
baseDir = global.CONF.System.TmpDir
|
||||||
}
|
}
|
||||||
|
|
||||||
switch cronjob.Type {
|
switch cronjob.Type {
|
||||||
|
@ -659,7 +659,7 @@ func backupMysql(backupType, baseDir, backupDir, mysqlName, dbName, fileName str
|
|||||||
FileDir: backupDir,
|
FileDir: backupDir,
|
||||||
FileName: fileName,
|
FileName: fileName,
|
||||||
}
|
}
|
||||||
if baseDir != constant.TmpDir || backupType == "LOCAL" {
|
if baseDir != global.CONF.System.TmpDir || backupType == "LOCAL" {
|
||||||
record.Source = "LOCAL"
|
record.Source = "LOCAL"
|
||||||
record.FileDir = fullDir
|
record.FileDir = fullDir
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ import (
|
|||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/docker"
|
"github.com/1Panel-dev/1Panel/backend/utils/docker"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -41,10 +40,10 @@ type daemonJsonItem struct {
|
|||||||
|
|
||||||
func (u *DockerService) LoadDockerStatus() string {
|
func (u *DockerService) LoadDockerStatus() string {
|
||||||
status := constant.StatusRunning
|
status := constant.StatusRunning
|
||||||
stdout, err := cmd.Exec("systemctl is-active docker")
|
// stdout, err := cmd.Exec("systemctl is-active docker")
|
||||||
if string(stdout) != "active\n" || err != nil {
|
// if string(stdout) != "active\n" || err != nil {
|
||||||
status = constant.Stopped
|
// status = constant.Stopped
|
||||||
}
|
// }
|
||||||
|
|
||||||
return status
|
return status
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,6 @@ import (
|
|||||||
"github.com/docker/docker/pkg/archive"
|
"github.com/docker/docker/pkg/archive"
|
||||||
)
|
)
|
||||||
|
|
||||||
var dockerLogDir = constant.TmpDir + "/docker_logs"
|
|
||||||
|
|
||||||
type ImageService struct{}
|
type ImageService struct{}
|
||||||
|
|
||||||
type IImageService interface {
|
type IImageService interface {
|
||||||
@ -164,11 +162,13 @@ func (u *ImageService) ImageBuild(req dto.ImageBuild) (string, error) {
|
|||||||
res, err := client.ImageBuild(context.TODO(), tar, opts)
|
res, err := client.ImageBuild(context.TODO(), tar, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.LOG.Errorf("build image %s failed, err: %v", req.Name, err)
|
global.LOG.Errorf("build image %s failed, err: %v", req.Name, err)
|
||||||
|
_, _ = file.WriteString("image build failed!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
global.LOG.Infof("build image %s successful!", req.Name)
|
global.LOG.Infof("build image %s successful!", req.Name)
|
||||||
_, _ = io.Copy(file, res.Body)
|
_, _ = io.Copy(file, res.Body)
|
||||||
|
_, _ = file.WriteString("image build successful!")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return logName, nil
|
return logName, nil
|
||||||
@ -179,6 +179,7 @@ func (u *ImageService) ImagePull(req dto.ImagePull) (string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
dockerLogDir := global.CONF.System.TmpDir + "/docker_logs"
|
||||||
if _, err := os.Stat(dockerLogDir); err != nil && os.IsNotExist(err) {
|
if _, err := os.Stat(dockerLogDir); err != nil && os.IsNotExist(err) {
|
||||||
if err = os.MkdirAll(dockerLogDir, os.ModePerm); err != nil {
|
if err = os.MkdirAll(dockerLogDir, os.ModePerm); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -226,12 +227,14 @@ func (u *ImageService) ImagePull(req dto.ImagePull) (string, error) {
|
|||||||
defer file.Close()
|
defer file.Close()
|
||||||
out, err := client.ImagePull(context.TODO(), image, options)
|
out, err := client.ImagePull(context.TODO(), image, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
_, _ = file.WriteString("image pull failed!")
|
||||||
global.LOG.Errorf("image %s pull failed, err: %v", image, err)
|
global.LOG.Errorf("image %s pull failed, err: %v", image, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer out.Close()
|
defer out.Close()
|
||||||
global.LOG.Infof("pull image %s successful!", req.ImageName)
|
global.LOG.Infof("pull image %s successful!", req.ImageName)
|
||||||
_, _ = io.Copy(file, out)
|
_, _ = io.Copy(file, out)
|
||||||
|
_, _ = file.WriteString("image pull successful!")
|
||||||
}()
|
}()
|
||||||
return pathItem, nil
|
return pathItem, nil
|
||||||
}
|
}
|
||||||
@ -314,6 +317,8 @@ func (u *ImageService) ImagePush(req dto.ImagePush) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dockerLogDir := global.CONF.System.TmpDir + "/docker_logs"
|
||||||
if _, err := os.Stat(dockerLogDir); err != nil && os.IsNotExist(err) {
|
if _, err := os.Stat(dockerLogDir); err != nil && os.IsNotExist(err) {
|
||||||
if err = os.MkdirAll(dockerLogDir, os.ModePerm); err != nil {
|
if err = os.MkdirAll(dockerLogDir, os.ModePerm); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -330,11 +335,13 @@ func (u *ImageService) ImagePush(req dto.ImagePush) (string, error) {
|
|||||||
out, err := client.ImagePush(context.TODO(), newName, options)
|
out, err := client.ImagePush(context.TODO(), newName, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.LOG.Errorf("image %s push failed, err: %v", req.TagName, err)
|
global.LOG.Errorf("image %s push failed, err: %v", req.TagName, err)
|
||||||
|
_, _ = file.WriteString("image push failed!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer out.Close()
|
defer out.Close()
|
||||||
global.LOG.Infof("push image %s successful!", req.Name)
|
global.LOG.Infof("push image %s successful!", req.Name)
|
||||||
_, _ = io.Copy(file, out)
|
_, _ = io.Copy(file, out)
|
||||||
|
_, _ = file.WriteString("image push successful!")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return pathItem, nil
|
return pathItem, nil
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||||
"github.com/jinzhu/copier"
|
"github.com/jinzhu/copier"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -65,18 +66,16 @@ func (u *ImageRepoService) Create(req dto.ImageRepoCreate) error {
|
|||||||
}
|
}
|
||||||
if req.Protocol == "http" {
|
if req.Protocol == "http" {
|
||||||
_ = u.handleRegistries(req.DownloadUrl, "", "create")
|
_ = u.handleRegistries(req.DownloadUrl, "", "create")
|
||||||
|
stdout, err := cmd.Exec("systemctl restart docker")
|
||||||
|
if err != nil {
|
||||||
|
return errors.New(string(stdout))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := copier.Copy(&imageRepo, &req); err != nil {
|
if err := copier.Copy(&imageRepo, &req); err != nil {
|
||||||
return errors.WithMessage(constant.ErrStructTransform, err.Error())
|
return errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command("systemctl", "restart", "docker")
|
|
||||||
stdout, err := cmd.CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
return errors.New(string(stdout))
|
|
||||||
}
|
|
||||||
|
|
||||||
imageRepo.Status = constant.StatusSuccess
|
imageRepo.Status = constant.StatusSuccess
|
||||||
if err := u.checkConn(req.DownloadUrl, req.Username, req.Password); err != nil {
|
if err := u.checkConn(req.DownloadUrl, req.Username, req.Password); err != nil {
|
||||||
imageRepo.Status = constant.StatusFailed
|
imageRepo.Status = constant.StatusFailed
|
||||||
|
@ -14,7 +14,6 @@ import (
|
|||||||
|
|
||||||
"gitee.com/openeuler/go-gitee/gitee"
|
"gitee.com/openeuler/go-gitee/gitee"
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/global"
|
"github.com/1Panel-dev/1Panel/backend/global"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||||
@ -71,8 +70,8 @@ func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
|
|||||||
global.LOG.Info("start to upgrade now...")
|
global.LOG.Info("start to upgrade now...")
|
||||||
fileOp := files.NewFileOp()
|
fileOp := files.NewFileOp()
|
||||||
timeStr := time.Now().Format("20060102150405")
|
timeStr := time.Now().Format("20060102150405")
|
||||||
rootDir := fmt.Sprintf("%s/upgrade_%s/downloads", constant.TmpDir, timeStr)
|
rootDir := fmt.Sprintf("%s/upgrade_%s/downloads", global.CONF.System.TmpDir, timeStr)
|
||||||
originalDir := fmt.Sprintf("%s/upgrade_%s/original", constant.TmpDir, timeStr)
|
originalDir := fmt.Sprintf("%s/upgrade_%s/original", global.CONF.System.TmpDir, timeStr)
|
||||||
if err := os.MkdirAll(rootDir, os.ModePerm); err != nil {
|
if err := os.MkdirAll(rootDir, os.ModePerm); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
@ -12,6 +11,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||||
@ -459,7 +460,7 @@ func handleWebsiteBackup(backupType, baseDir, backupDir, domain, backupName stri
|
|||||||
FileDir: backupDir,
|
FileDir: backupDir,
|
||||||
FileName: fmt.Sprintf("%s.tar.gz", backupName),
|
FileName: fmt.Sprintf("%s.tar.gz", backupName),
|
||||||
}
|
}
|
||||||
if baseDir != constant.TmpDir || backupType == "LOCAL" {
|
if baseDir != global.CONF.System.TmpDir || backupType == "LOCAL" {
|
||||||
record.Source = "LOCAL"
|
record.Source = "LOCAL"
|
||||||
record.FileDir = fmt.Sprintf("%s/%s", baseDir, backupDir)
|
record.FileDir = fmt.Sprintf("%s/%s", baseDir, backupDir)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ type System struct {
|
|||||||
DbPath string `mapstructure:"db_path"`
|
DbPath string `mapstructure:"db_path"`
|
||||||
LogPath string `mapstructure:"log_path"`
|
LogPath string `mapstructure:"log_path"`
|
||||||
DataDir string `mapstructure:"data_dir"`
|
DataDir string `mapstructure:"data_dir"`
|
||||||
|
TmpDir string `mapstructure:"tmp_dir"`
|
||||||
Cache string `mapstructure:"cache"`
|
Cache string `mapstructure:"cache"`
|
||||||
Backup string `mapstructure:"backup"`
|
Backup string `mapstructure:"backup"`
|
||||||
AppRepoOwner string `mapstructure:"app_repo_owner"`
|
AppRepoOwner string `mapstructure:"app_repo_owner"`
|
||||||
|
@ -11,5 +11,4 @@ var (
|
|||||||
ResourceDir = path.Join(DataDir, "resource")
|
ResourceDir = path.Join(DataDir, "resource")
|
||||||
AppResourceDir = path.Join(ResourceDir, "apps")
|
AppResourceDir = path.Join(ResourceDir, "apps")
|
||||||
AppInstallDir = path.Join(DataDir, "apps")
|
AppInstallDir = path.Join(DataDir, "apps")
|
||||||
TmpDir = path.Join(DataDir, "tmp")
|
|
||||||
)
|
)
|
||||||
|
@ -15,7 +15,6 @@ func Init() {
|
|||||||
constant.ResourceDir = path.Join(constant.DataDir, "resource")
|
constant.ResourceDir = path.Join(constant.DataDir, "resource")
|
||||||
constant.AppResourceDir = path.Join(constant.ResourceDir, "apps")
|
constant.AppResourceDir = path.Join(constant.ResourceDir, "apps")
|
||||||
constant.AppInstallDir = path.Join(constant.DataDir, "apps")
|
constant.AppInstallDir = path.Join(constant.DataDir, "apps")
|
||||||
constant.TmpDir = path.Join(constant.DataDir, "tmp")
|
|
||||||
|
|
||||||
dirs := []string{constant.DataDir, constant.ResourceDir, constant.AppResourceDir, constant.AppInstallDir, global.CONF.System.Backup}
|
dirs := []string{constant.DataDir, constant.ResourceDir, constant.AppResourceDir, constant.AppInstallDir, global.CONF.System.Backup}
|
||||||
|
|
||||||
|
@ -3,18 +3,17 @@ package viper
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/configs"
|
"github.com/1Panel-dev/1Panel/backend/configs"
|
||||||
"github.com/1Panel-dev/1Panel/backend/global"
|
"github.com/1Panel-dev/1Panel/backend/global"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||||
"github.com/1Panel-dev/1Panel/cmd/server/conf"
|
"github.com/1Panel-dev/1Panel/cmd/server/conf"
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Init() {
|
func Init() {
|
||||||
@ -73,5 +72,6 @@ func Init() {
|
|||||||
global.CONF.System.Backup = global.CONF.System.DataDir + "/backup"
|
global.CONF.System.Backup = global.CONF.System.DataDir + "/backup"
|
||||||
global.CONF.System.DbPath = global.CONF.System.DataDir + "/db"
|
global.CONF.System.DbPath = global.CONF.System.DataDir + "/db"
|
||||||
global.CONF.System.LogPath = global.CONF.System.DataDir + "/log"
|
global.CONF.System.LogPath = global.CONF.System.DataDir + "/log"
|
||||||
|
global.CONF.System.TmpDir = global.CONF.System.DataDir + "/tmp"
|
||||||
global.Viper = v
|
global.Viper = v
|
||||||
}
|
}
|
||||||
|
37
frontend/src/api/modules/backup.ts
Normal file
37
frontend/src/api/modules/backup.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import http from '@/api';
|
||||||
|
import { Backup } from '../interface/backup';
|
||||||
|
import { ResPage } from '../interface';
|
||||||
|
|
||||||
|
export const getBackupList = () => {
|
||||||
|
return http.get<Array<Backup.BackupInfo>>(`/backups/search`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getFilesFromBackup = (type: string) => {
|
||||||
|
return http.post<Array<any>>(`/backups/search/files`, { type: type });
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addBackup = (params: Backup.BackupOperate) => {
|
||||||
|
return http.post<Backup.BackupOperate>(`/backups`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const editBackup = (params: Backup.BackupOperate) => {
|
||||||
|
return http.post(`/backups/update`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteBackup = (params: { ids: number[] }) => {
|
||||||
|
return http.post(`/backups/del`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const downloadBackupRecord = (params: Backup.RecordDownload) => {
|
||||||
|
return http.download<BlobPart>(`/backups/record/download`, params, { responseType: 'blob' });
|
||||||
|
};
|
||||||
|
export const deleteBackupRecord = (params: { ids: number[] }) => {
|
||||||
|
return http.post(`/backups/record/del`, params);
|
||||||
|
};
|
||||||
|
export const searchBackupRecords = (params: Backup.SearchBackupRecord) => {
|
||||||
|
return http.post<ResPage<Backup.RecordInfo>>(`/backups/record/search`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const listBucket = (params: Backup.ForBucket) => {
|
||||||
|
return http.post(`/backups/buckets`, params);
|
||||||
|
};
|
23
frontend/src/api/modules/command.ts
Normal file
23
frontend/src/api/modules/command.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import http from '@/api';
|
||||||
|
import { ResPage } from '../interface';
|
||||||
|
import { Command } from '../interface/command';
|
||||||
|
|
||||||
|
export const getCommandList = () => {
|
||||||
|
return http.get<Array<Command.CommandInfo>>(`/commands`, {});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getCommandPage = (params: Command.CommandSearch) => {
|
||||||
|
return http.post<ResPage<Command.CommandInfo>>(`/commands/search`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addCommand = (params: Command.CommandOperate) => {
|
||||||
|
return http.post<Command.CommandOperate>(`/commands`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const editCommand = (params: Command.CommandOperate) => {
|
||||||
|
return http.post(`/commands/update`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteCommand = (params: { ids: number[] }) => {
|
||||||
|
return http.post(`/commands/del`, params);
|
||||||
|
};
|
@ -49,9 +49,7 @@ export const useDeleteData = <P = any, R = any>(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {})
|
||||||
console.log('1111');
|
|
||||||
})
|
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
19
frontend/src/utils/docker.ts
Normal file
19
frontend/src/utils/docker.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { isJson } from './util';
|
||||||
|
|
||||||
|
export function formatImageStdout(stdout: string) {
|
||||||
|
let lines = stdout.split('\r\n');
|
||||||
|
for (let i = 0; i < lines.length; i++) {
|
||||||
|
if (isJson(lines[i])) {
|
||||||
|
const data = JSON.parse(lines[i]);
|
||||||
|
if (data.id) {
|
||||||
|
lines[i] = data.id + ': ' + data.status;
|
||||||
|
} else {
|
||||||
|
lines[i] = data.status;
|
||||||
|
}
|
||||||
|
if (data.progress) {
|
||||||
|
lines[i] = lines[i] + data.progress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lines.join('\r\n');
|
||||||
|
}
|
@ -1,3 +0,0 @@
|
|||||||
export function getAssetsFile(url: string) {
|
|
||||||
return new URL(`../assets/apps/${url}`, import.meta.url).href;
|
|
||||||
}
|
|
@ -208,3 +208,13 @@ export function getAge(d1: string): string {
|
|||||||
}
|
}
|
||||||
return i18n.global.t('app.less1Minute');
|
return i18n.global.t('app.less1Minute');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isJson(str: string) {
|
||||||
|
try {
|
||||||
|
if (typeof JSON.parse(str) === 'object') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -52,6 +52,7 @@ import { Base64 } from 'js-base64';
|
|||||||
import 'xterm/css/xterm.css';
|
import 'xterm/css/xterm.css';
|
||||||
import { FitAddon } from 'xterm-addon-fit';
|
import { FitAddon } from 'xterm-addon-fit';
|
||||||
import { Rules } from '@/global/form-rules';
|
import { Rules } from '@/global/form-rules';
|
||||||
|
import { isJson } from '@/utils/util';
|
||||||
|
|
||||||
const terminalVisiable = ref(false);
|
const terminalVisiable = ref(false);
|
||||||
const terminalOpen = ref(false);
|
const terminalOpen = ref(false);
|
||||||
@ -98,16 +99,6 @@ const onWSReceive = (message: any) => {
|
|||||||
term.write(data.Data);
|
term.write(data.Data);
|
||||||
};
|
};
|
||||||
|
|
||||||
function isJson(str: string) {
|
|
||||||
try {
|
|
||||||
if (typeof JSON.parse(str) === 'object') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const errorRealTerminal = (ex: any) => {
|
const errorRealTerminal = (ex: any) => {
|
||||||
let message = ex.message;
|
let message = ex.message;
|
||||||
if (!message) message = 'disconnected';
|
if (!message) message = 'disconnected';
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button :disabled="buttonDisabled" @click="drawerVisiable = false">
|
<el-button @click="drawerVisiable = false">
|
||||||
{{ $t('commons.button.cancel') }}
|
{{ $t('commons.button.cancel') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button :disabled="buttonDisabled" type="primary" @click="onSubmit(formRef)">
|
<el-button :disabled="buttonDisabled" type="primary" @click="onSubmit(formRef)">
|
||||||
@ -97,6 +97,7 @@ import i18n from '@/lang';
|
|||||||
import { ElForm, ElMessage } from 'element-plus';
|
import { ElForm, ElMessage } from 'element-plus';
|
||||||
import { imageBuild } from '@/api/modules/container';
|
import { imageBuild } from '@/api/modules/container';
|
||||||
import { LoadFile } from '@/api/modules/files';
|
import { LoadFile } from '@/api/modules/files';
|
||||||
|
import { formatImageStdout } from '@/utils/docker';
|
||||||
|
|
||||||
const logVisiable = ref<boolean>(false);
|
const logVisiable = ref<boolean>(false);
|
||||||
const logInfo = ref();
|
const logInfo = ref();
|
||||||
@ -166,7 +167,7 @@ const loadLogs = async (path: string) => {
|
|||||||
timer = setInterval(async () => {
|
timer = setInterval(async () => {
|
||||||
if (logVisiable.value) {
|
if (logVisiable.value) {
|
||||||
const res = await LoadFile({ path: path });
|
const res = await LoadFile({ path: path });
|
||||||
logInfo.value = res.data;
|
logInfo.value = formatImageStdout(res.data);
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const state = view.value.state;
|
const state = view.value.state;
|
||||||
view.value.dispatch({
|
view.value.dispatch({
|
||||||
@ -174,6 +175,11 @@ const loadLogs = async (path: string) => {
|
|||||||
scrollIntoView: true,
|
scrollIntoView: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
if (logInfo.value.endsWith('image build failed!') || logInfo.value.endsWith('image build successful!')) {
|
||||||
|
clearInterval(Number(timer));
|
||||||
|
timer = null;
|
||||||
|
buttonDisabled.value = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, 1000 * 3);
|
}, 1000 * 3);
|
||||||
};
|
};
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button :disabled="buttonDisabled" @click="drawerVisiable = false">
|
<el-button @click="drawerVisiable = false">
|
||||||
{{ $t('commons.button.cancel') }}
|
{{ $t('commons.button.cancel') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button :disabled="buttonDisabled" type="primary" @click="onSubmit(formRef)">
|
<el-button :disabled="buttonDisabled" type="primary" @click="onSubmit(formRef)">
|
||||||
@ -75,6 +75,7 @@ import { javascript } from '@codemirror/lang-javascript';
|
|||||||
import { oneDark } from '@codemirror/theme-one-dark';
|
import { oneDark } from '@codemirror/theme-one-dark';
|
||||||
import { LoadFile } from '@/api/modules/files';
|
import { LoadFile } from '@/api/modules/files';
|
||||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||||
|
import { formatImageStdout } from '@/utils/docker';
|
||||||
|
|
||||||
const drawerVisiable = ref(false);
|
const drawerVisiable = ref(false);
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
@ -132,7 +133,7 @@ const loadLogs = async (path: string) => {
|
|||||||
timer = setInterval(async () => {
|
timer = setInterval(async () => {
|
||||||
if (logVisiable.value) {
|
if (logVisiable.value) {
|
||||||
const res = await LoadFile({ path: path });
|
const res = await LoadFile({ path: path });
|
||||||
logInfo.value = res.data;
|
logInfo.value = formatImageStdout(res.data);
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const state = view.value.state;
|
const state = view.value.state;
|
||||||
view.value.dispatch({
|
view.value.dispatch({
|
||||||
@ -140,6 +141,11 @@ const loadLogs = async (path: string) => {
|
|||||||
scrollIntoView: true,
|
scrollIntoView: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
if (logInfo.value.endsWith('image pull failed!') || logInfo.value.endsWith('image pull successful!')) {
|
||||||
|
clearInterval(Number(timer));
|
||||||
|
timer = null;
|
||||||
|
buttonDisabled.value = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, 1000 * 3);
|
}, 1000 * 3);
|
||||||
};
|
};
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button :disabled="buttonDisabled" @click="drawerVisiable = false">
|
<el-button @click="drawerVisiable = false">
|
||||||
{{ $t('commons.button.cancel') }}
|
{{ $t('commons.button.cancel') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button :disabled="buttonDisabled" type="primary" @click="onSubmit(formRef)">
|
<el-button :disabled="buttonDisabled" type="primary" @click="onSubmit(formRef)">
|
||||||
@ -78,6 +78,7 @@ import { javascript } from '@codemirror/lang-javascript';
|
|||||||
import { oneDark } from '@codemirror/theme-one-dark';
|
import { oneDark } from '@codemirror/theme-one-dark';
|
||||||
import { LoadFile } from '@/api/modules/files';
|
import { LoadFile } from '@/api/modules/files';
|
||||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||||
|
import { formatImageStdout } from '@/utils/docker';
|
||||||
|
|
||||||
const drawerVisiable = ref(false);
|
const drawerVisiable = ref(false);
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
@ -137,7 +138,7 @@ const loadLogs = async (path: string) => {
|
|||||||
timer = setInterval(async () => {
|
timer = setInterval(async () => {
|
||||||
if (logVisiable.value) {
|
if (logVisiable.value) {
|
||||||
const res = await LoadFile({ path: path });
|
const res = await LoadFile({ path: path });
|
||||||
logInfo.value = res.data;
|
logInfo.value = formatImageStdout(res.data);
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const state = view.value.state;
|
const state = view.value.state;
|
||||||
view.value.dispatch({
|
view.value.dispatch({
|
||||||
@ -145,6 +146,11 @@ const loadLogs = async (path: string) => {
|
|||||||
scrollIntoView: true,
|
scrollIntoView: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
if (logInfo.value.endsWith('image push failed!') || logInfo.value.endsWith('image push successful!')) {
|
||||||
|
clearInterval(Number(timer));
|
||||||
|
timer = null;
|
||||||
|
buttonDisabled.value = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, 1000 * 3);
|
}, 1000 * 3);
|
||||||
};
|
};
|
||||||
|
@ -15,9 +15,6 @@
|
|||||||
<el-button type="primary" @click="onOpenDialog('add')">
|
<el-button type="primary" @click="onOpenDialog('add')">
|
||||||
{{ $t('container.createRepo') }}
|
{{ $t('container.createRepo') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" plain :disabled="selects.length === 0" @click="onBatchDelete(null)">
|
|
||||||
{{ $t('commons.button.delete') }}
|
|
||||||
</el-button>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<TableSetting @search="search()" />
|
<TableSetting @search="search()" />
|
||||||
@ -85,9 +82,10 @@ import DeleteDialog from '@/views/container/repo/delete/index.vue';
|
|||||||
import { reactive, onMounted, ref } from 'vue';
|
import { reactive, onMounted, ref } from 'vue';
|
||||||
import { dateFormatSimple } from '@/utils/util';
|
import { dateFormatSimple } from '@/utils/util';
|
||||||
import { Container } from '@/api/interface/container';
|
import { Container } from '@/api/interface/container';
|
||||||
import { loadDockerStatus, searchImageRepo } from '@/api/modules/container';
|
import { deleteImageRepo, loadDockerStatus, searchImageRepo } from '@/api/modules/container';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import router from '@/routers';
|
import router from '@/routers';
|
||||||
|
import { ElMessageBox } from 'element-plus';
|
||||||
|
|
||||||
const loading = ref();
|
const loading = ref();
|
||||||
const data = ref();
|
const data = ref();
|
||||||
@ -149,16 +147,18 @@ const onOpenDialog = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const dialogDeleteRef = ref();
|
const dialogDeleteRef = ref();
|
||||||
const onBatchDelete = async (row: Container.RepoInfo | null) => {
|
const onDelete = async (row: Container.RepoInfo) => {
|
||||||
let ids: Array<number> = [];
|
if (row.protocol === 'https') {
|
||||||
if (row) {
|
ElMessageBox.confirm(i18n.global.t('commons.msg.delete'), i18n.global.t('commons.button.delete'), {
|
||||||
ids.push(row.id);
|
confirmButtonText: i18n.global.t('commons.button.confirm'),
|
||||||
} else {
|
cancelButtonText: i18n.global.t('commons.button.cancel'),
|
||||||
selects.value.forEach((item: Container.RepoInfo) => {
|
}).then(async () => {
|
||||||
ids.push(item.id);
|
await deleteImageRepo({ ids: [row.id], deleteInsecure: false });
|
||||||
|
search();
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
dialogDeleteRef.value!.acceptParams({ ids: ids });
|
dialogDeleteRef.value!.acceptParams({ ids: [row.id] });
|
||||||
};
|
};
|
||||||
|
|
||||||
const buttons = [
|
const buttons = [
|
||||||
@ -177,7 +177,7 @@ const buttons = [
|
|||||||
return row.downloadUrl === 'docker.io';
|
return row.downloadUrl === 'docker.io';
|
||||||
},
|
},
|
||||||
click: (row: Container.RepoInfo) => {
|
click: (row: Container.RepoInfo) => {
|
||||||
onBatchDelete(row);
|
onDelete(row);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -121,7 +121,7 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
|
|||||||
formEl.validate(async (valid) => {
|
formEl.validate(async (valid) => {
|
||||||
if (!valid) return;
|
if (!valid) return;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
if (dialogData.value.title === 'create') {
|
if (dialogData.value.title === 'add') {
|
||||||
await createImageRepo(dialogData.value.rowData!)
|
await createImageRepo(dialogData.value.rowData!)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
|
@ -11,6 +11,7 @@ import { AttachAddon } from 'xterm-addon-attach';
|
|||||||
import { Base64 } from 'js-base64';
|
import { Base64 } from 'js-base64';
|
||||||
import 'xterm/css/xterm.css';
|
import 'xterm/css/xterm.css';
|
||||||
import { FitAddon } from 'xterm-addon-fit';
|
import { FitAddon } from 'xterm-addon-fit';
|
||||||
|
import { isJson } from '@/utils/util';
|
||||||
|
|
||||||
const fitAddon = new FitAddon();
|
const fitAddon = new FitAddon();
|
||||||
let terminalSocket = ref(null) as unknown as WebSocket;
|
let terminalSocket = ref(null) as unknown as WebSocket;
|
||||||
@ -47,16 +48,6 @@ const onWSReceive = (message: any) => {
|
|||||||
term.write(data.Data);
|
term.write(data.Data);
|
||||||
};
|
};
|
||||||
|
|
||||||
function isJson(str: string) {
|
|
||||||
try {
|
|
||||||
if (typeof JSON.parse(str) === 'object') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const errorRealTerminal = (ex: any) => {
|
const errorRealTerminal = (ex: any) => {
|
||||||
let message = ex.message;
|
let message = ex.message;
|
||||||
if (!message) message = 'disconnected';
|
if (!message) message = 'disconnected';
|
||||||
|
@ -9,6 +9,7 @@ import { AttachAddon } from 'xterm-addon-attach';
|
|||||||
import { Base64 } from 'js-base64';
|
import { Base64 } from 'js-base64';
|
||||||
import 'xterm/css/xterm.css';
|
import 'xterm/css/xterm.css';
|
||||||
import { FitAddon } from 'xterm-addon-fit';
|
import { FitAddon } from 'xterm-addon-fit';
|
||||||
|
import { isJson } from '@/utils/util';
|
||||||
|
|
||||||
const terminalID = ref();
|
const terminalID = ref();
|
||||||
const wsID = ref();
|
const wsID = ref();
|
||||||
@ -48,16 +49,6 @@ const onWSReceive = (message: any) => {
|
|||||||
term.write(data.Data);
|
term.write(data.Data);
|
||||||
};
|
};
|
||||||
|
|
||||||
function isJson(str: string) {
|
|
||||||
try {
|
|
||||||
if (typeof JSON.parse(str) === 'object') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const errorRealTerminal = (ex: any) => {
|
const errorRealTerminal = (ex: any) => {
|
||||||
let message = ex.message;
|
let message = ex.message;
|
||||||
if (!message) message = 'disconnected';
|
if (!message) message = 'disconnected';
|
||||||
|
@ -149,10 +149,9 @@ import { snapshotCreate, searchSnapshotPage, snapshotDelete, updateSnapshotDescr
|
|||||||
import { onMounted, reactive, ref } from 'vue';
|
import { onMounted, reactive, ref } from 'vue';
|
||||||
import { dateFormat } from '@/utils/util';
|
import { dateFormat } from '@/utils/util';
|
||||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||||
import { ElForm } from 'element-plus';
|
import { ElForm, ElMessage } from 'element-plus';
|
||||||
import { Rules } from '@/global/form-rules';
|
import { Rules } from '@/global/form-rules';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { ElMessage } from 'element-plus';
|
|
||||||
import { Setting } from '@/api/interface/setting';
|
import { Setting } from '@/api/interface/setting';
|
||||||
import LayoutContent from '@/layout/layout-content.vue';
|
import LayoutContent from '@/layout/layout-content.vue';
|
||||||
import RecoverStatus from '@/views/setting/snapshot/status/index.vue';
|
import RecoverStatus from '@/views/setting/snapshot/status/index.vue';
|
||||||
|
Loading…
Reference in New Issue
Block a user