Skip to content

Commit a59d8ff

Browse files
committed
fix: Fix the issue of container compose log cleanup failure
1 parent f9a20ec commit a59d8ff

File tree

8 files changed

+151
-18
lines changed

8 files changed

+151
-18
lines changed

agent/app/api/v2/container.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,28 @@ func (b *BaseApi) CleanContainerLog(c *gin.Context) {
393393
helper.Success(c)
394394
}
395395

396+
// @Tags Container
397+
// @Summary Clean compose log
398+
// @Accept json
399+
// @Param request body dto.ComposeLogClean true "request"
400+
// @Success 200
401+
// @Security ApiKeyAuth
402+
// @Security Timestamp
403+
// @Router /containers/compose/clean/log [post]
404+
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清理容器编排 [name] 日志","formatEN":"clean compose [name] logs"}
405+
func (b *BaseApi) CleanComposeLog(c *gin.Context) {
406+
var req dto.ComposeLogClean
407+
if err := helper.CheckBindAndValidate(&req, c); err != nil {
408+
return
409+
}
410+
411+
if err := containerService.ComposeLogClean(req); err != nil {
412+
helper.InternalServer(c, err)
413+
return
414+
}
415+
helper.Success(c)
416+
}
417+
396418
// @Tags Container
397419
// @Summary Rename Container
398420
// @Accept json

agent/app/dto/container.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,10 @@ type ComposeUpdate struct {
291291
Content string `json:"content" validate:"required"`
292292
Env []string `json:"env"`
293293
}
294+
type ComposeLogClean struct {
295+
Name string `json:"name" validate:"required"`
296+
Path string `json:"path" validate:"required"`
297+
}
294298

295299
type ContainerLog struct {
296300
Container string `json:"container" validate:"required"`

agent/app/service/container.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ type IContainerService interface {
8585
CreateVolume(req dto.VolumeCreate) error
8686
TestCompose(req dto.ComposeCreate) (bool, error)
8787
ComposeUpdate(req dto.ComposeUpdate) error
88+
ComposeLogClean(req dto.ComposeLogClean) error
8889
Prune(req dto.ContainerPrune) error
8990

9091
LoadUsers(req dto.OperationWithName) []string

agent/app/service/container_compose.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"os"
88
"path"
9+
"path/filepath"
910
"sort"
1011
"strings"
1112
"time"
@@ -284,6 +285,57 @@ func (u *ContainerService) ComposeUpdate(req dto.ComposeUpdate) error {
284285
return nil
285286
}
286287

288+
func (u *ContainerService) ComposeLogClean(req dto.ComposeLogClean) error {
289+
client, err := docker.NewDockerClient()
290+
if err != nil {
291+
return err
292+
}
293+
defer client.Close()
294+
295+
options := container.ListOptions{All: true}
296+
options.Filters = filters.NewArgs()
297+
options.Filters.Add("label", composeProjectLabel)
298+
299+
list, err := client.ContainerList(context.Background(), options)
300+
if err != nil {
301+
return err
302+
}
303+
ctx := context.Background()
304+
for _, item := range list {
305+
if name, ok := item.Labels[composeProjectLabel]; ok {
306+
if name != req.Name {
307+
continue
308+
}
309+
containerItem, err := client.ContainerInspect(ctx, item.ID)
310+
if err != nil {
311+
return err
312+
}
313+
if err := client.ContainerStop(ctx, containerItem.ID, container.StopOptions{}); err != nil {
314+
return err
315+
}
316+
file, err := os.OpenFile(containerItem.LogPath, os.O_RDWR|os.O_CREATE, constant.FilePerm)
317+
if err != nil {
318+
return err
319+
}
320+
defer file.Close()
321+
if err = file.Truncate(0); err != nil {
322+
return err
323+
}
324+
_, _ = file.Seek(0, 0)
325+
326+
files, _ := filepath.Glob(fmt.Sprintf("%s.*", containerItem.LogPath))
327+
for _, file := range files {
328+
_ = os.Remove(file)
329+
}
330+
}
331+
}
332+
return u.ComposeOperation(dto.ComposeOperation{
333+
Name: req.Name,
334+
Path: req.Path,
335+
Operation: "restart",
336+
})
337+
}
338+
287339
func (u *ContainerService) loadPath(req *dto.ComposeCreate) error {
288340
if req.From == "template" || req.From == "edit" {
289341
dir := fmt.Sprintf("%s/docker/compose/%s", global.Dir.DataDir, req.Name)

agent/router/ro_container.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ func (s *ContainerRouter) InitRouter(Router *gin.RouterGroup) {
4848
baRouter.POST("/compose", baseApi.CreateCompose)
4949
baRouter.POST("/compose/test", baseApi.TestCompose)
5050
baRouter.POST("/compose/operate", baseApi.OperatorCompose)
51+
baRouter.POST("/compose/clean/log", baseApi.CleanComposeLog)
5152
baRouter.POST("/compose/update", baseApi.ComposeUpdate)
5253

5354
baRouter.GET("/template", baseApi.ListComposeTemplate)

frontend/src/api/modules/container.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,17 @@ export const commitContainer = (params: Container.ContainerCommit) => {
3939
export const loadContainerInfo = (name: string) => {
4040
return http.post<Container.ContainerHelper>(`/containers/info`, { name: name });
4141
};
42+
export const cleanComposeLog = (composeName: string, composePath: string, operateNode?: string) => {
43+
const params = operateNode ? `?operateNode=${operateNode}` : '';
44+
return http.post(
45+
`/containers/compose/clean/log${params}`,
46+
{ name: composeName, path: composePath },
47+
TimeoutEnum.T_60S,
48+
);
49+
};
4250
export const cleanContainerLog = (containerName: string, operateNode?: string) => {
4351
const params = operateNode ? `?operateNode=${operateNode}` : '';
44-
return http.post(`/containers/clean/log${params}`, { name: containerName });
52+
return http.post(`/containers/clean/log${params}`, { name: containerName }, TimeoutEnum.T_60S);
4553
};
4654
export const containerItemStats = (containerID: string) => {
4755
return http.post<Container.ContainerItemStats>(`/containers/item/stats`, { name: containerID }, TimeoutEnum.T_60S);

frontend/src/components/log/container/index.vue

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
</template>
3939

4040
<script lang="ts" setup>
41-
import { cleanContainerLog, DownloadFile } from '@/api/modules/container';
41+
import { cleanComposeLog, cleanContainerLog, DownloadFile } from '@/api/modules/container';
4242
import i18n from '@/lang';
4343
import { dateFormatForName } from '@/utils/util';
4444
import { computed, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue';
@@ -48,6 +48,8 @@ import hightlight from '@/components/log/custom-hightlight/index.vue';
4848
import { GlobalStore } from '@/store';
4949
const globalStore = GlobalStore();
5050
51+
const em = defineEmits(['update:loading']);
52+
5153
const props = defineProps({
5254
container: {
5355
type: String,
@@ -93,6 +95,7 @@ const logSearch = reactive({
9395
mode: 'all',
9496
tail: props.defaultFollow ? 0 : 100,
9597
compose: '',
98+
resource: '',
9699
});
97100
const logHeight = 20;
98101
const logCount = computed(() => logs.value.length);
@@ -215,6 +218,19 @@ const onClean = async () => {
215218
if (props.node && props.node !== '') {
216219
currentNode = props.node;
217220
}
221+
if (logSearch.compose !== '') {
222+
em('update:loading', true);
223+
await cleanComposeLog(logSearch.resource, logSearch.compose, currentNode)
224+
.then(() => {
225+
em('update:loading', false);
226+
searchLogs();
227+
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
228+
})
229+
.finally(() => {
230+
em('update:loading', false);
231+
});
232+
return;
233+
}
218234
await cleanContainerLog(logSearch.container, currentNode);
219235
searchLogs();
220236
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
@@ -240,6 +256,7 @@ const resizeObserver = ref<ResizeObserver | null>(null);
240256
onMounted(() => {
241257
logSearch.container = props.container;
242258
logSearch.compose = props.compose;
259+
logSearch.resource = props.resource;
243260
244261
logVisible.value = true;
245262
logSearch.tail = 100;

frontend/src/views/container/compose/index.vue

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,7 @@
9797
>
9898
{{ $t('commons.operate.restart') }}
9999
</el-button>
100-
<el-button
101-
:disabled="row.createdBy !== '1Panel'"
102-
plain
103-
round
104-
size="small"
105-
@click="onDelete(row)"
106-
>
100+
<el-button plain round size="small" @click="onDelete(row)">
107101
{{ $t('commons.operate.delete') }}
108102
</el-button>
109103
</div>
@@ -174,8 +168,7 @@
174168
<el-descriptions-item :label="$t('container.memTotal')">
175169
{{ computeSizeForDocker(row.memoryLimit) }}
176170
</el-descriptions-item>
177-
178-
<el-descriptions-item>
171+
<el-descriptions-item v-if="row.hasLoadSize">
179172
<template #label>
180173
{{ $t('container.sizeRw') }}
181174
<el-tooltip :content="$t('container.sizeRwHelper')">
@@ -184,7 +177,10 @@
184177
</template>
185178
{{ computeSize2(row.sizeRw) }}
186179
</el-descriptions-item>
187-
<el-descriptions-item :label="$t('container.sizeRootFs')">
180+
<el-descriptions-item
181+
:label="$t('container.sizeRootFs')"
182+
v-if="row.hasLoadSize"
183+
>
188184
<template #label>
189185
{{ $t('container.sizeRootFs') }}
190186
<el-tooltip :content="$t('container.sizeRootFsHelper')">
@@ -194,6 +190,17 @@
194190
{{ computeSize2(row.sizeRootFs) }}
195191
</el-descriptions-item>
196192
</el-descriptions>
193+
194+
<el-button
195+
class="mt-2"
196+
v-if="!row.hasLoadSize"
197+
size="small"
198+
link
199+
type="primary"
200+
@click="loadSize(row)"
201+
>
202+
{{ $t('container.loadSize') }}
203+
</el-button>
197204
</template>
198205
</el-popover>
199206
</div>
@@ -252,8 +259,10 @@
252259

253260
<div v-show="showType === 'log'">
254261
<ContainerLog
262+
v-model:loading="detailLoading"
255263
:key="currentCompose.path"
256264
:compose="currentCompose.path"
265+
:resource="currentCompose.name"
257266
:highlightDiff="450"
258267
:defaultFollow="true"
259268
/>
@@ -282,7 +291,14 @@ import TerminalDialog from '@/views/container/container/terminal/index.vue';
282291
import ContainerLogDialog from '@/components/log/container-drawer/index.vue';
283292
import CreateDialog from '@/views/container/compose/create/index.vue';
284293
import DeleteDialog from '@/views/container/compose/delete/index.vue';
285-
import { composeOperator, composeUpdate, containerListStats, inspect, searchCompose } from '@/api/modules/container';
294+
import {
295+
composeOperator,
296+
composeUpdate,
297+
containerItemStats,
298+
containerListStats,
299+
inspect,
300+
searchCompose,
301+
} from '@/api/modules/container';
286302
import DockerStatus from '@/views/container/docker-status/index.vue';
287303
import i18n from '@/lang';
288304
import { Container } from '@/api/interface/container';
@@ -381,11 +397,15 @@ const loadDetail = async (row: Container.ComposeInfo, withRefresh: boolean) => {
381397
detailLoading.value = true;
382398
currentCompose.value = row;
383399
composeContainers.value = row.containers || [];
384-
await inspect({ id: currentCompose.value.name, type: 'compose' }).then((res) => {
385-
composeContent.value = res.data;
386-
detailLoading.value = false;
387-
});
388-
loadContainerStats();
400+
await inspect({ id: currentCompose.value.name, type: 'compose' })
401+
.then((res) => {
402+
composeContent.value = res.data;
403+
detailLoading.value = false;
404+
})
405+
.finally(() => {
406+
loadContainerStats();
407+
detailLoading.value = false;
408+
});
389409
};
390410
391411
const loadContainerStats = async () => {
@@ -440,6 +460,14 @@ const handleComposeOperate = async (operation: 'up' | 'stop' | 'restart', row: a
440460
});
441461
};
442462
463+
const loadSize = async (row: any) => {
464+
containerItemStats(row.containerID).then((res) => {
465+
row.sizeRw = res.data.sizeRw || 0;
466+
row.sizeRootFs = res.data.sizeRootFs || 0;
467+
row.hasLoadSize = true;
468+
});
469+
};
470+
443471
const onSubmitEdit = async () => {
444472
const param = {
445473
name: currentCompose.value.name,

0 commit comments

Comments
 (0)