mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 16:29:17 +08:00
feat: 应用安装增加日志展示 (#5996)
This commit is contained in:
parent
82d8997217
commit
636e149b29
@ -19,6 +19,7 @@ type AppInstallCreate struct {
|
||||
Params map[string]interface{} `json:"params"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Services map[string]string `json:"services"`
|
||||
TaskID string `json:"taskID"`
|
||||
AppContainerConfig
|
||||
}
|
||||
|
||||
|
@ -129,6 +129,7 @@ type FileReadByLineReq struct {
|
||||
Name string `json:"name"`
|
||||
Latest bool `json:"latest"`
|
||||
TaskID string `json:"taskID"`
|
||||
TaskType string `json:"taskType"`
|
||||
}
|
||||
|
||||
type FileExistReq struct {
|
||||
|
@ -16,6 +16,8 @@ type ITaskRepo interface {
|
||||
Update(ctx context.Context, task *model.Task) error
|
||||
|
||||
WithByID(id string) DBOption
|
||||
WithType(taskType string) DBOption
|
||||
WithResourceID(id uint) DBOption
|
||||
}
|
||||
|
||||
func NewITaskRepo() ITaskRepo {
|
||||
@ -28,6 +30,18 @@ func (t TaskRepo) WithByID(id string) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func (t TaskRepo) WithType(taskType string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("type = ?", taskType)
|
||||
}
|
||||
}
|
||||
|
||||
func (t TaskRepo) WithResourceID(id uint) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("resource_id = ?", id)
|
||||
}
|
||||
}
|
||||
|
||||
func (t TaskRepo) Create(ctx context.Context, task *model.Task) error {
|
||||
return getTx(ctx).Create(&task).Error
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
http2 "github.com/1Panel-dev/1Panel/agent/utils/http"
|
||||
httpUtil "github.com/1Panel-dev/1Panel/agent/utils/http"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
|
||||
"github.com/google/uuid"
|
||||
"gopkg.in/yaml.v3"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -442,8 +441,7 @@ func (a AppService) Install(req request.AppInstallCreate) (appInstall *model.App
|
||||
return
|
||||
}
|
||||
|
||||
taskID := uuid.New().String()
|
||||
installTask, err := task.NewTaskWithOps(appInstall.Name, task.TaskCreate, task.TaskScopeApp, taskID)
|
||||
installTask, err := task.NewTaskWithOps(appInstall.Name, task.TaskCreate, task.TaskScopeApp, req.TaskID, appInstall.ID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
@ -467,11 +468,17 @@ func (f *FileService) ReadLogByLine(req request.FileReadByLineReq) (*response.Fi
|
||||
}
|
||||
}
|
||||
case constant.TypeTask:
|
||||
task, err := taskRepo.GetFirst(taskRepo.WithByID(req.TaskID))
|
||||
var opts []repo.DBOption
|
||||
if req.TaskID != "" {
|
||||
opts = append(opts, taskRepo.WithByID(req.TaskID))
|
||||
} else {
|
||||
opts = append(opts, taskRepo.WithType(req.TaskType), taskRepo.WithResourceID(req.ID))
|
||||
}
|
||||
taskModel, err := taskRepo.GetFirst(opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logFilePath = task.LogFile
|
||||
logFilePath = taskModel.LogFile
|
||||
case constant.TypeImagePull, constant.TypeImagePush, constant.TypeImageBuild, constant.TypeComposeCreate:
|
||||
logFilePath = path.Join(global.CONF.System.TmpDir, fmt.Sprintf("docker_logs/%s", req.Name))
|
||||
}
|
||||
|
@ -258,7 +258,7 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
|
||||
runtime *model.Runtime
|
||||
)
|
||||
|
||||
createTask, err := task.NewTaskWithOps(create.PrimaryDomain, task.TaskCreate, task.TaskScopeWebsite, create.TaskID)
|
||||
createTask, err := task.NewTaskWithOps(create.PrimaryDomain, task.TaskCreate, task.TaskScopeWebsite, create.TaskID, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -370,6 +370,7 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
|
||||
if err = websiteRepo.Create(ctx, website); err != nil {
|
||||
return err
|
||||
}
|
||||
t.Task.ResourceID = website.ID
|
||||
for i := range domains {
|
||||
domains[i].WebsiteID = website.ID
|
||||
}
|
||||
|
@ -66,20 +66,20 @@ func GetTaskName(resourceName, operate, scope string) string {
|
||||
return fmt.Sprintf("%s%s [%s]", i18n.GetMsgByKey(operate), i18n.GetMsgByKey(scope), resourceName)
|
||||
}
|
||||
|
||||
func NewTaskWithOps(resourceName, operate, scope, taskID string) (*Task, error) {
|
||||
return NewTask(GetTaskName(resourceName, operate, scope), scope, taskID)
|
||||
func NewTaskWithOps(resourceName, operate, scope, taskID string, resourceID uint) (*Task, error) {
|
||||
return NewTask(GetTaskName(resourceName, operate, scope), scope, taskID, resourceID)
|
||||
}
|
||||
|
||||
func NewChildTask(name, taskType, parentTaskID string) (*Task, error) {
|
||||
task, err := NewTask(name, taskType, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
task.ParentID = parentTaskID
|
||||
return task, nil
|
||||
}
|
||||
//func NewChildTask(name, taskType, parentTaskID string) (*Task, error) {
|
||||
// task, err := NewTask(name, taskType, "")
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// task.ParentID = parentTaskID
|
||||
// return task, nil
|
||||
//}
|
||||
|
||||
func NewTask(name, taskType, taskID string) (*Task, error) {
|
||||
func NewTask(name, taskType, taskID string, resourceID uint) (*Task, error) {
|
||||
if taskID == "" {
|
||||
taskID = uuid.New().String()
|
||||
}
|
||||
@ -101,6 +101,7 @@ func NewTask(name, taskType, taskID string) (*Task, error) {
|
||||
Type: taskType,
|
||||
LogFile: logPath,
|
||||
Status: constant.StatusRunning,
|
||||
ResourceID: resourceID,
|
||||
}
|
||||
taskRepo := repo.NewITaskRepo()
|
||||
task := &Task{Name: name, logFile: file, Logger: logger, taskRepo: taskRepo, Task: taskModel}
|
||||
|
@ -276,7 +276,7 @@ var InitPHPExtensions = &gormigrate.Migration{
|
||||
}
|
||||
|
||||
var AddTask = &gormigrate.Migration{
|
||||
ID: "20240724-add-task",
|
||||
ID: "20240801-add-task",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.AutoMigrate(
|
||||
&model.Task{})
|
||||
|
@ -94,6 +94,7 @@ export namespace App {
|
||||
export interface AppInstall {
|
||||
appDetailId: number;
|
||||
params: any;
|
||||
taskID: string;
|
||||
}
|
||||
|
||||
export interface AppInstallSearch extends ReqPage {
|
||||
|
@ -6,7 +6,7 @@
|
||||
:close-on-press-escape="false"
|
||||
:show-close="showClose"
|
||||
:before-close="handleClose"
|
||||
class="task-log-dialog"
|
||||
:width="width"
|
||||
>
|
||||
<div>
|
||||
<highlightjs ref="editorRef" language="JavaScript" :autodetect="false" :code="content"></highlightjs>
|
||||
@ -19,6 +19,17 @@ import { ReadByLine } from '@/api/modules/files';
|
||||
|
||||
const editorRef = ref();
|
||||
|
||||
defineProps({
|
||||
showClose: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '30%',
|
||||
},
|
||||
});
|
||||
|
||||
const data = ref({
|
||||
enable: false,
|
||||
content: '',
|
||||
@ -34,8 +45,6 @@ const scrollerElement = ref<HTMLElement | null>(null);
|
||||
const minPage = ref(1);
|
||||
const maxPage = ref(1);
|
||||
const open = ref(false);
|
||||
const taskID = ref('');
|
||||
const showClose = ref(false);
|
||||
|
||||
const readReq = reactive({
|
||||
taskID: '',
|
||||
@ -43,22 +52,30 @@ const readReq = reactive({
|
||||
page: 1,
|
||||
pageSize: 500,
|
||||
latest: false,
|
||||
taskType: '',
|
||||
id: 0,
|
||||
});
|
||||
|
||||
const stopSignals = ['[TASK-END]'];
|
||||
|
||||
const acceptParams = (id: string, closeShow: boolean) => {
|
||||
if (closeShow) {
|
||||
showClose.value = closeShow;
|
||||
}
|
||||
taskID.value = id;
|
||||
const initData = () => {
|
||||
open.value = true;
|
||||
initCodemirror();
|
||||
init();
|
||||
};
|
||||
|
||||
const openWithTaskID = (id: string) => {
|
||||
readReq.taskID = id;
|
||||
initData();
|
||||
};
|
||||
|
||||
const openWithResourceID = (taskType: string, resourceID: number) => {
|
||||
readReq.taskType = taskType;
|
||||
readReq.id = resourceID;
|
||||
initData();
|
||||
};
|
||||
|
||||
const getContent = (pre: boolean) => {
|
||||
readReq.taskID = taskID.value;
|
||||
if (readReq.page < 1) {
|
||||
readReq.page = 1;
|
||||
}
|
||||
@ -182,7 +199,7 @@ onUnmounted(() => {
|
||||
onCloseLog();
|
||||
});
|
||||
|
||||
defineExpose({ acceptParams, handleClose });
|
||||
defineExpose({ openWithResourceID, openWithTaskID });
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.task-log-dialog {
|
||||
|
@ -106,6 +106,7 @@
|
||||
</span>
|
||||
</template>
|
||||
</DrawerPro>
|
||||
<TaskLog ref="taskLogRef" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="appInstall">
|
||||
@ -121,6 +122,8 @@ import { MsgError } from '@/utils/message';
|
||||
import { Container } from '@/api/interface/container';
|
||||
import { loadResourceLimit } from '@/api/modules/container';
|
||||
import CodemirrorPro from '@/components/codemirror-pro/index.vue';
|
||||
import TaskLog from '@/components/task-log/index.vue';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@ -159,6 +162,7 @@ const initData = () => ({
|
||||
version: '',
|
||||
appID: '',
|
||||
pullImage: true,
|
||||
taskID: '',
|
||||
});
|
||||
const req = reactive(initData());
|
||||
const limits = ref<Container.ResourceLimit>({
|
||||
@ -176,6 +180,7 @@ const handleClose = () => {
|
||||
};
|
||||
const paramKey = ref(1);
|
||||
const isHostMode = ref(false);
|
||||
const taskLogRef = ref();
|
||||
|
||||
const changeUnit = () => {
|
||||
if (req.memoryUnit == 'M') {
|
||||
@ -258,12 +263,20 @@ const submit = async (formEl: FormInstance | undefined) => {
|
||||
});
|
||||
};
|
||||
|
||||
const openTaskLog = (taskID: string) => {
|
||||
taskLogRef.value.openWithTaskID(taskID);
|
||||
};
|
||||
|
||||
const install = () => {
|
||||
loading.value = true;
|
||||
const taskID = uuidv4();
|
||||
console.log(taskID);
|
||||
req.taskID = taskID;
|
||||
console.log(req);
|
||||
InstallApp(req)
|
||||
.then(() => {
|
||||
handleClose();
|
||||
router.push({ path: '/apps/installed' });
|
||||
openTaskLog(taskID);
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
|
@ -102,7 +102,7 @@
|
||||
<el-card class="e-card">
|
||||
<el-row :gutter="20">
|
||||
<el-col :xs="3" :sm="3" :md="3" :lg="4" :xl="4">
|
||||
<div class="icon" @click.stop="openDetail(installed.appKey)">
|
||||
<div class="icon">
|
||||
<el-avatar
|
||||
shape="square"
|
||||
:size="66"
|
||||
@ -313,7 +313,7 @@
|
||||
<PortJumpDialog ref="dialogPortJumpRef" />
|
||||
<AppIgnore ref="ignoreRef" @close="search" />
|
||||
<ComposeLogs ref="composeLogRef" />
|
||||
<AppDetail ref="appDetail" />
|
||||
<TaskLog ref="taskLogRef" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -335,7 +335,6 @@ import AppDelete from './delete/index.vue';
|
||||
import AppParams from './detail/index.vue';
|
||||
import AppUpgrade from './upgrade/index.vue';
|
||||
import AppIgnore from './ignore/index.vue';
|
||||
import AppDetail from '../detail/index.vue';
|
||||
import ComposeLogs from '@/components/compose-log/index.vue';
|
||||
import { App } from '@/api/interface/app';
|
||||
import Status from '@/components/status/index.vue';
|
||||
@ -343,6 +342,7 @@ import { getAge, getLanguage } from '@/utils/util';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { toFolder } from '@/global/business';
|
||||
import TaskLog from '@/components/task-log/index.vue';
|
||||
|
||||
const data = ref<any>();
|
||||
const loading = ref(false);
|
||||
@ -369,6 +369,7 @@ const upgradeRef = ref();
|
||||
const ignoreRef = ref();
|
||||
const dialogPortJumpRef = ref();
|
||||
const composeLogRef = ref();
|
||||
const taskLogRef = ref();
|
||||
const tags = ref<App.Tag[]>([]);
|
||||
const activeTag = ref('all');
|
||||
const searchReq = reactive({
|
||||
@ -384,7 +385,6 @@ const activeName = ref(i18n.global.t('app.installed'));
|
||||
const mode = ref('installed');
|
||||
const moreTag = ref('');
|
||||
const language = getLanguage();
|
||||
const appDetail = ref();
|
||||
const options = {
|
||||
modifiers: [
|
||||
{
|
||||
@ -453,10 +453,6 @@ const goDashboard = async (port: any, protocol: string) => {
|
||||
dialogPortJumpRef.value.acceptParams({ port: port, protocol: protocol });
|
||||
};
|
||||
|
||||
const openDetail = (appKey: string) => {
|
||||
appDetail.value.acceptParams(appKey, 'detail');
|
||||
};
|
||||
|
||||
const openOperate = (row: any, op: string) => {
|
||||
operateReq.installId = row.id;
|
||||
operateReq.operate = op;
|
||||
@ -623,7 +619,13 @@ const quickJump = () => {
|
||||
};
|
||||
|
||||
const openLog = (row: any) => {
|
||||
switch (row.status) {
|
||||
case 'Installing':
|
||||
taskLogRef.value.openWithResourceID('App', row.id);
|
||||
break;
|
||||
default:
|
||||
composeLogRef.value.acceptParams({ compose: row.path + '/docker-compose.yml', resource: row.name });
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user