1
0
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:
zhengkunwang 2024-08-01 15:31:44 +08:00 committed by GitHub
parent 82d8997217
commit 636e149b29
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 99 additions and 43 deletions

View File

@ -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
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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
}

View File

@ -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))
}

View File

@ -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
}

View File

@ -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()
}
@ -96,11 +96,12 @@ func NewTask(name, taskType, taskID string) (*Task, error) {
}
logger := log.New(file, "", log.LstdFlags)
taskModel := &model.Task{
ID: taskID,
Name: name,
Type: taskType,
LogFile: logPath,
Status: constant.StatusRunning,
ID: taskID,
Name: name,
Type: taskType,
LogFile: logPath,
Status: constant.StatusRunning,
ResourceID: resourceID,
}
taskRepo := repo.NewITaskRepo()
task := &Task{Name: name, logFile: file, Logger: logger, taskRepo: taskRepo, Task: taskModel}

View File

@ -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{})

View File

@ -94,6 +94,7 @@ export namespace App {
export interface AppInstall {
appDetailId: number;
params: any;
taskID: string;
}
export interface AppInstallSearch extends ReqPage {

View File

@ -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 {

View File

@ -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;

View File

@ -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) => {
composeLogRef.value.acceptParams({ compose: row.path + '/docker-compose.yml', resource: row.name });
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(() => {