Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions agent/app/api/v2/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,28 @@
helper.Success(c)
}

// @Tags Container
// @Summary Clean compose log
// @Accept json
// @Param request body dto.ComposeLogClean true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/compose/clean/log [post]
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清理容器编排 [name] 日志","formatEN":"clean compose [name] logs"}
func (b *BaseApi) CleanComposeLog(c *gin.Context) {
var req dto.ComposeLogClean
if err := helper.CheckBindAndValidate(&req, c); err != nil {

Check warning on line 407 in agent/app/api/v2/container.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unnecessary variable declaration and use the expression directly in the condition.

See more on https://sonarcloud.io/project/issues?id=1Panel-dev_1Panel&issues=AZr8B-HX3o0ylQCwB-Cd&open=AZr8B-HX3o0ylQCwB-Cd&pullRequest=11238
return
}

if err := containerService.ComposeLogClean(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}

// @Tags Container
// @Summary Rename Container
// @Accept json
Expand Down
4 changes: 4 additions & 0 deletions agent/app/dto/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ type ComposeUpdate struct {
Content string `json:"content" validate:"required"`
Env []string `json:"env"`
}
type ComposeLogClean struct {
Name string `json:"name" validate:"required"`
Path string `json:"path" validate:"required"`
}

type ContainerLog struct {
Container string `json:"container" validate:"required"`
Expand Down
1 change: 1 addition & 0 deletions agent/app/service/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ type IContainerService interface {
CreateVolume(req dto.VolumeCreate) error
TestCompose(req dto.ComposeCreate) (bool, error)
ComposeUpdate(req dto.ComposeUpdate) error
ComposeLogClean(req dto.ComposeLogClean) error
Prune(req dto.ContainerPrune) error

LoadUsers(req dto.OperationWithName) []string
Expand Down
52 changes: 52 additions & 0 deletions agent/app/service/container_compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"fmt"
"os"
"path"
"path/filepath"
"sort"
"strings"
"time"
Expand Down Expand Up @@ -284,6 +285,57 @@
return nil
}

func (u *ContainerService) ComposeLogClean(req dto.ComposeLogClean) error {

Check failure on line 288 in agent/app/service/container_compose.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 23 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=1Panel-dev_1Panel&issues=AZr8B-CC3o0ylQCwB-Ca&open=AZr8B-CC3o0ylQCwB-Ca&pullRequest=11238
client, err := docker.NewDockerClient()
if err != nil {
return err
}
defer client.Close()

options := container.ListOptions{All: true}
options.Filters = filters.NewArgs()
options.Filters.Add("label", composeProjectLabel)

list, err := client.ContainerList(context.Background(), options)
if err != nil {
return err
}
ctx := context.Background()
for _, item := range list {
if name, ok := item.Labels[composeProjectLabel]; ok {
if name != req.Name {
continue
}
containerItem, err := client.ContainerInspect(ctx, item.ID)
if err != nil {
return err
}
if err := client.ContainerStop(ctx, containerItem.ID, container.StopOptions{}); err != nil {
return err
}
file, err := os.OpenFile(containerItem.LogPath, os.O_RDWR|os.O_CREATE, constant.FilePerm)
if err != nil {
return err
}
defer file.Close()
if err = file.Truncate(0); err != nil {
return err
}
_, _ = file.Seek(0, 0)

Check failure on line 324 in agent/app/service/container_compose.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Handle this error explicitly or document why it can be safely ignored.

See more on https://sonarcloud.io/project/issues?id=1Panel-dev_1Panel&issues=AZr8B-CC3o0ylQCwB-Cb&open=AZr8B-CC3o0ylQCwB-Cb&pullRequest=11238

files, _ := filepath.Glob(fmt.Sprintf("%s.*", containerItem.LogPath))

Check failure on line 326 in agent/app/service/container_compose.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Handle this error explicitly or document why it can be safely ignored.

See more on https://sonarcloud.io/project/issues?id=1Panel-dev_1Panel&issues=AZr8B-CC3o0ylQCwB-Cc&open=AZr8B-CC3o0ylQCwB-Cc&pullRequest=11238
for _, file := range files {
_ = os.Remove(file)
}
}
}
return u.ComposeOperation(dto.ComposeOperation{
Name: req.Name,
Path: req.Path,
Operation: "restart",
})
}

func (u *ContainerService) loadPath(req *dto.ComposeCreate) error {
if req.From == "template" || req.From == "edit" {
dir := fmt.Sprintf("%s/docker/compose/%s", global.Dir.DataDir, req.Name)
Expand Down
1 change: 1 addition & 0 deletions agent/router/ro_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func (s *ContainerRouter) InitRouter(Router *gin.RouterGroup) {
baRouter.POST("/compose", baseApi.CreateCompose)
baRouter.POST("/compose/test", baseApi.TestCompose)
baRouter.POST("/compose/operate", baseApi.OperatorCompose)
baRouter.POST("/compose/clean/log", baseApi.CleanComposeLog)
baRouter.POST("/compose/update", baseApi.ComposeUpdate)

baRouter.GET("/template", baseApi.ListComposeTemplate)
Expand Down
10 changes: 9 additions & 1 deletion frontend/src/api/modules/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,17 @@ export const commitContainer = (params: Container.ContainerCommit) => {
export const loadContainerInfo = (name: string) => {
return http.post<Container.ContainerHelper>(`/containers/info`, { name: name });
};
export const cleanComposeLog = (composeName: string, composePath: string, operateNode?: string) => {
const params = operateNode ? `?operateNode=${operateNode}` : '';
return http.post(
`/containers/compose/clean/log${params}`,
{ name: composeName, path: composePath },
TimeoutEnum.T_60S,
);
};
export const cleanContainerLog = (containerName: string, operateNode?: string) => {
const params = operateNode ? `?operateNode=${operateNode}` : '';
return http.post(`/containers/clean/log${params}`, { name: containerName });
return http.post(`/containers/clean/log${params}`, { name: containerName }, TimeoutEnum.T_60S);
};
export const containerItemStats = (containerID: string) => {
return http.post<Container.ContainerItemStats>(`/containers/item/stats`, { name: containerID }, TimeoutEnum.T_60S);
Expand Down
19 changes: 18 additions & 1 deletion frontend/src/components/log/container/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
</template>

<script lang="ts" setup>
import { cleanContainerLog, DownloadFile } from '@/api/modules/container';
import { cleanComposeLog, cleanContainerLog, DownloadFile } from '@/api/modules/container';
import i18n from '@/lang';
import { dateFormatForName } from '@/utils/util';
import { computed, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue';
Expand All @@ -48,6 +48,8 @@ import hightlight from '@/components/log/custom-hightlight/index.vue';
import { GlobalStore } from '@/store';
const globalStore = GlobalStore();

const em = defineEmits(['update:loading']);

const props = defineProps({
container: {
type: String,
Expand Down Expand Up @@ -93,6 +95,7 @@ const logSearch = reactive({
mode: 'all',
tail: props.defaultFollow ? 0 : 100,
compose: '',
resource: '',
});
const logHeight = 20;
const logCount = computed(() => logs.value.length);
Expand Down Expand Up @@ -215,6 +218,19 @@ const onClean = async () => {
if (props.node && props.node !== '') {
currentNode = props.node;
}
if (logSearch.compose !== '') {
em('update:loading', true);
await cleanComposeLog(logSearch.resource, logSearch.compose, currentNode)
.then(() => {
em('update:loading', false);
searchLogs();
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
})
.finally(() => {
em('update:loading', false);
});
return;
}
await cleanContainerLog(logSearch.container, currentNode);
searchLogs();
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
Expand All @@ -240,6 +256,7 @@ const resizeObserver = ref<ResizeObserver | null>(null);
onMounted(() => {
logSearch.container = props.container;
logSearch.compose = props.compose;
logSearch.resource = props.resource;

logVisible.value = true;
logSearch.tail = 100;
Expand Down
60 changes: 44 additions & 16 deletions frontend/src/views/container/compose/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,7 @@
>
{{ $t('commons.operate.restart') }}
</el-button>
<el-button
:disabled="row.createdBy !== '1Panel'"
plain
round
size="small"
@click="onDelete(row)"
>
<el-button plain round size="small" @click="onDelete(row)">
{{ $t('commons.operate.delete') }}
</el-button>
</div>
Expand Down Expand Up @@ -174,8 +168,7 @@
<el-descriptions-item :label="$t('container.memTotal')">
{{ computeSizeForDocker(row.memoryLimit) }}
</el-descriptions-item>

<el-descriptions-item>
<el-descriptions-item v-if="row.hasLoadSize">
<template #label>
{{ $t('container.sizeRw') }}
<el-tooltip :content="$t('container.sizeRwHelper')">
Expand All @@ -184,7 +177,10 @@
</template>
{{ computeSize2(row.sizeRw) }}
</el-descriptions-item>
<el-descriptions-item :label="$t('container.sizeRootFs')">
<el-descriptions-item
:label="$t('container.sizeRootFs')"
v-if="row.hasLoadSize"
>
<template #label>
{{ $t('container.sizeRootFs') }}
<el-tooltip :content="$t('container.sizeRootFsHelper')">
Expand All @@ -194,6 +190,17 @@
{{ computeSize2(row.sizeRootFs) }}
</el-descriptions-item>
</el-descriptions>

<el-button
class="mt-2"
v-if="!row.hasLoadSize"
size="small"
link
type="primary"
@click="loadSize(row)"
>
{{ $t('container.loadSize') }}
</el-button>
</template>
</el-popover>
</div>
Expand Down Expand Up @@ -252,8 +259,10 @@

<div v-show="showType === 'log'">
<ContainerLog
v-model:loading="detailLoading"
:key="currentCompose.path"
:compose="currentCompose.path"
:resource="currentCompose.name"
:highlightDiff="450"
:defaultFollow="true"
/>
Expand Down Expand Up @@ -282,7 +291,14 @@ import TerminalDialog from '@/views/container/container/terminal/index.vue';
import ContainerLogDialog from '@/components/log/container-drawer/index.vue';
import CreateDialog from '@/views/container/compose/create/index.vue';
import DeleteDialog from '@/views/container/compose/delete/index.vue';
import { composeOperator, composeUpdate, containerListStats, inspect, searchCompose } from '@/api/modules/container';
import {
composeOperator,
composeUpdate,
containerItemStats,
containerListStats,
inspect,
searchCompose,
} from '@/api/modules/container';
import DockerStatus from '@/views/container/docker-status/index.vue';
import i18n from '@/lang';
import { Container } from '@/api/interface/container';
Expand Down Expand Up @@ -381,11 +397,15 @@ const loadDetail = async (row: Container.ComposeInfo, withRefresh: boolean) => {
detailLoading.value = true;
currentCompose.value = row;
composeContainers.value = row.containers || [];
await inspect({ id: currentCompose.value.name, type: 'compose' }).then((res) => {
composeContent.value = res.data;
detailLoading.value = false;
});
loadContainerStats();
await inspect({ id: currentCompose.value.name, type: 'compose' })
.then((res) => {
composeContent.value = res.data;
detailLoading.value = false;
})
.finally(() => {
loadContainerStats();
detailLoading.value = false;
});
};

const loadContainerStats = async () => {
Expand Down Expand Up @@ -440,6 +460,14 @@ const handleComposeOperate = async (operation: 'up' | 'stop' | 'restart', row: a
});
};

const loadSize = async (row: any) => {
containerItemStats(row.containerID).then((res) => {
row.sizeRw = res.data.sizeRw || 0;
row.sizeRootFs = res.data.sizeRootFs || 0;
row.hasLoadSize = true;
});
};

const onSubmitEdit = async () => {
const param = {
name: currentCompose.value.name,
Expand Down
Loading