mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 08:19:15 +08:00
feat: 容器创建编辑增加 cpu 、内存最大限制 (#1383)
This commit is contained in:
parent
aa37e3885c
commit
c82e20efd7
@ -205,6 +205,20 @@ func (b *BaseApi) ContainerInfo(c *gin.Context) {
|
|||||||
helper.SuccessWithData(c, data)
|
helper.SuccessWithData(c, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary Load container limis
|
||||||
|
// @Description 获取容器限制
|
||||||
|
// @Success 200 {object} dto.ResourceLimit
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Router /containers/limit [get]
|
||||||
|
func (b *BaseApi) LoadResouceLimit(c *gin.Context) {
|
||||||
|
data, err := containerService.LoadResouceLimit()
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.SuccessWithData(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
// @Tags Container
|
// @Tags Container
|
||||||
// @Summary Create container
|
// @Summary Create container
|
||||||
// @Description 创建容器
|
// @Description 创建容器
|
||||||
|
@ -30,6 +30,11 @@ type ContainerInfo struct {
|
|||||||
IsFromCompose bool `json:"isFromCompose"`
|
IsFromCompose bool `json:"isFromCompose"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ResourceLimit struct {
|
||||||
|
CPU int `json:"cpu"`
|
||||||
|
Memory int `json:"memory"`
|
||||||
|
}
|
||||||
|
|
||||||
type ContainerOperate struct {
|
type ContainerOperate struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Image string `json:"image"`
|
Image string `json:"image"`
|
||||||
|
@ -27,6 +27,8 @@ import (
|
|||||||
"github.com/docker/go-connections/nat"
|
"github.com/docker/go-connections/nat"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
"github.com/shirou/gopsutil/v3/cpu"
|
||||||
|
"github.com/shirou/gopsutil/v3/mem"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ContainerService struct{}
|
type ContainerService struct{}
|
||||||
@ -42,6 +44,7 @@ type IContainerService interface {
|
|||||||
ContainerCreate(req dto.ContainerOperate) error
|
ContainerCreate(req dto.ContainerOperate) error
|
||||||
ContainerUpdate(req dto.ContainerOperate) error
|
ContainerUpdate(req dto.ContainerOperate) error
|
||||||
ContainerInfo(req dto.OperationWithName) (*dto.ContainerOperate, error)
|
ContainerInfo(req dto.OperationWithName) (*dto.ContainerOperate, error)
|
||||||
|
LoadResouceLimit() (*dto.ResourceLimit, error)
|
||||||
ContainerLogClean(req dto.OperationWithName) error
|
ContainerLogClean(req dto.OperationWithName) error
|
||||||
ContainerOperation(req dto.ContainerOperation) error
|
ContainerOperation(req dto.ContainerOperation) error
|
||||||
ContainerLogs(wsConn *websocket.Conn, container, since, tail string, follow bool) error
|
ContainerLogs(wsConn *websocket.Conn, container, since, tail string, follow bool) error
|
||||||
@ -215,6 +218,23 @@ func (u *ContainerService) Prune(req dto.ContainerPrune) (dto.ContainerPruneRepo
|
|||||||
return report, nil
|
return report, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *ContainerService) LoadResouceLimit() (*dto.ResourceLimit, error) {
|
||||||
|
cpuCounts, err := cpu.Counts(false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("load cpu limit failed, err: %v", err)
|
||||||
|
}
|
||||||
|
memoryInfo, err := mem.VirtualMemory()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("load memory limit failed, err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
data := dto.ResourceLimit{
|
||||||
|
CPU: cpuCounts,
|
||||||
|
Memory: int(memoryInfo.Total),
|
||||||
|
}
|
||||||
|
return &data, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (u *ContainerService) ContainerCreate(req dto.ContainerOperate) error {
|
func (u *ContainerService) ContainerCreate(req dto.ContainerOperate) error {
|
||||||
client, err := docker.NewDockerClient()
|
client, err := docker.NewDockerClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -23,6 +23,7 @@ func (s *ContainerRouter) InitContainerRouter(Router *gin.RouterGroup) {
|
|||||||
baRouter.POST("/info", baseApi.ContainerInfo)
|
baRouter.POST("/info", baseApi.ContainerInfo)
|
||||||
baRouter.POST("/search", baseApi.SearchContainer)
|
baRouter.POST("/search", baseApi.SearchContainer)
|
||||||
baRouter.GET("/search/log", baseApi.ContainerLogs)
|
baRouter.GET("/search/log", baseApi.ContainerLogs)
|
||||||
|
baRouter.GET("/limit", baseApi.LoadResouceLimit)
|
||||||
baRouter.POST("/clean/log", baseApi.CleanContainerLog)
|
baRouter.POST("/clean/log", baseApi.CleanContainerLog)
|
||||||
baRouter.POST("/inspect", baseApi.Inspect)
|
baRouter.POST("/inspect", baseApi.Inspect)
|
||||||
baRouter.POST("/operate", baseApi.ContainerOperation)
|
baRouter.POST("/operate", baseApi.ContainerOperation)
|
||||||
|
@ -1853,6 +1853,25 @@ var doc = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/containers/limit": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "获取容器限制",
|
||||||
|
"summary": "Load container limis",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/dto.ResourceLimit"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/containers/network": {
|
"/containers/network": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
@ -12408,6 +12427,17 @@ var doc = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dto.ResourceLimit": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"cpu": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"memory": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"dto.SSHConf": {
|
"dto.SSHConf": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -1839,6 +1839,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/containers/limit": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "获取容器限制",
|
||||||
|
"summary": "Load container limis",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/dto.ResourceLimit"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/containers/network": {
|
"/containers/network": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
@ -12394,6 +12413,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dto.ResourceLimit": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"cpu": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"memory": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"dto.SSHConf": {
|
"dto.SSHConf": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -1422,6 +1422,13 @@ definitions:
|
|||||||
used_memory_rss:
|
used_memory_rss:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
dto.ResourceLimit:
|
||||||
|
properties:
|
||||||
|
cpu:
|
||||||
|
type: integer
|
||||||
|
memory:
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
dto.SSHConf:
|
dto.SSHConf:
|
||||||
properties:
|
properties:
|
||||||
file:
|
file:
|
||||||
@ -4529,6 +4536,17 @@ paths:
|
|||||||
summary: Container inspect
|
summary: Container inspect
|
||||||
tags:
|
tags:
|
||||||
- Container
|
- Container
|
||||||
|
/containers/limit:
|
||||||
|
get:
|
||||||
|
description: 获取容器限制
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/dto.ResourceLimit'
|
||||||
|
security:
|
||||||
|
- ApiKeyAuth: []
|
||||||
|
summary: Load container limis
|
||||||
/containers/network:
|
/containers/network:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
|
@ -10,18 +10,20 @@ export namespace Container {
|
|||||||
name: string;
|
name: string;
|
||||||
filters: string;
|
filters: string;
|
||||||
}
|
}
|
||||||
|
export interface ResourceLimit {
|
||||||
|
cpu: number;
|
||||||
|
memory: number;
|
||||||
|
}
|
||||||
export interface ContainerHelper {
|
export interface ContainerHelper {
|
||||||
name: string;
|
name: string;
|
||||||
image: string;
|
image: string;
|
||||||
cmdStr: string;
|
cmdStr: string;
|
||||||
memoryUnit: string;
|
|
||||||
memoryItem: number;
|
memoryItem: number;
|
||||||
cmd: Array<string>;
|
cmd: Array<string>;
|
||||||
publishAllPorts: boolean;
|
publishAllPorts: boolean;
|
||||||
exposedPorts: Array<Port>;
|
exposedPorts: Array<Port>;
|
||||||
nanoCPUs: number;
|
nanoCPUs: number;
|
||||||
cpuShares: number;
|
cpuShares: number;
|
||||||
cpuUnit: string;
|
|
||||||
memory: number;
|
memory: number;
|
||||||
volumes: Array<Volume>;
|
volumes: Array<Volume>;
|
||||||
autoRemove: boolean;
|
autoRemove: boolean;
|
||||||
|
@ -5,6 +5,9 @@ import { Container } from '../interface/container';
|
|||||||
export const searchContainer = (params: Container.ContainerSearch) => {
|
export const searchContainer = (params: Container.ContainerSearch) => {
|
||||||
return http.post<ResPage<Container.ContainerInfo>>(`/containers/search`, params, 400000);
|
return http.post<ResPage<Container.ContainerInfo>>(`/containers/search`, params, 400000);
|
||||||
};
|
};
|
||||||
|
export const loadResourceLimit = () => {
|
||||||
|
return http.get<Container.ResourceLimit>(`/containers/limit`);
|
||||||
|
};
|
||||||
export const createContainer = (params: Container.ContainerHelper) => {
|
export const createContainer = (params: Container.ContainerHelper) => {
|
||||||
return http.post(`/containers`, params, 3000000);
|
return http.post(`/containers`, params, 3000000);
|
||||||
};
|
};
|
||||||
@ -17,10 +20,10 @@ export const loadContainerInfo = (name: string) => {
|
|||||||
export const cleanContainerLog = (containerName: string) => {
|
export const cleanContainerLog = (containerName: string) => {
|
||||||
return http.post(`/containers/clean/log`, { name: containerName });
|
return http.post(`/containers/clean/log`, { name: containerName });
|
||||||
};
|
};
|
||||||
export const ContainerStats = (id: string) => {
|
export const containerStats = (id: string) => {
|
||||||
return http.get<Container.ContainerStats>(`/containers/stats/${id}`);
|
return http.get<Container.ContainerStats>(`/containers/stats/${id}`);
|
||||||
};
|
};
|
||||||
export const ContainerOperator = (params: Container.ContainerOperate) => {
|
export const containerOperator = (params: Container.ContainerOperate) => {
|
||||||
return http.post(`/containers/operate`, params);
|
return http.post(`/containers/operate`, params);
|
||||||
};
|
};
|
||||||
export const containerPrune = (params: Container.ContainerPrune) => {
|
export const containerPrune = (params: Container.ContainerPrune) => {
|
||||||
|
@ -507,7 +507,7 @@ const message = {
|
|||||||
autoRemove: 'Auto remove',
|
autoRemove: 'Auto remove',
|
||||||
cpuQuota: 'NacosCPU',
|
cpuQuota: 'NacosCPU',
|
||||||
memoryLimit: 'Memory',
|
memoryLimit: 'Memory',
|
||||||
limitHelper: 'If the limit is 0, the limit is turned off',
|
limitHelper: 'If you limit it to 0, then the limitation is turned off, and the maximum available is {0}.',
|
||||||
mount: 'Mount',
|
mount: 'Mount',
|
||||||
serverPath: 'Server path',
|
serverPath: 'Server path',
|
||||||
containerDir: 'Container path',
|
containerDir: 'Container path',
|
||||||
|
@ -512,7 +512,7 @@ const message = {
|
|||||||
autoRemove: '容器退出后自动删除容器',
|
autoRemove: '容器退出后自动删除容器',
|
||||||
cpuQuota: 'CPU 限制',
|
cpuQuota: 'CPU 限制',
|
||||||
memoryLimit: '内存限制',
|
memoryLimit: '内存限制',
|
||||||
limitHelper: '限制为 0 则关闭限制',
|
limitHelper: '限制为 0 则关闭限制,最大可用为 {0}',
|
||||||
mount: '挂载卷',
|
mount: '挂载卷',
|
||||||
serverPath: '服务器目录',
|
serverPath: '服务器目录',
|
||||||
containerDir: '容器目录',
|
containerDir: '容器目录',
|
||||||
|
@ -104,7 +104,6 @@
|
|||||||
<CodemirrorDialog ref="mydetail" />
|
<CodemirrorDialog ref="mydetail" />
|
||||||
|
|
||||||
<ContainerLogDialog ref="dialogContainerLogRef" />
|
<ContainerLogDialog ref="dialogContainerLogRef" />
|
||||||
<CreateDialog @search="search" ref="dialogCreateRef" />
|
|
||||||
<MonitorDialog ref="dialogMonitorRef" />
|
<MonitorDialog ref="dialogMonitorRef" />
|
||||||
<TerminalDialog ref="dialogTerminalRef" />
|
<TerminalDialog ref="dialogTerminalRef" />
|
||||||
</template>
|
</template>
|
||||||
@ -115,14 +114,13 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { reactive, ref } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
import Tooltip from '@/components/tooltip/index.vue';
|
import Tooltip from '@/components/tooltip/index.vue';
|
||||||
import CreateDialog from '@/views/container/container/create/index.vue';
|
|
||||||
import MonitorDialog from '@/views/container/container/monitor/index.vue';
|
import MonitorDialog from '@/views/container/container/monitor/index.vue';
|
||||||
import ContainerLogDialog from '@/views/container/container/log/index.vue';
|
import ContainerLogDialog from '@/views/container/container/log/index.vue';
|
||||||
import TerminalDialog from '@/views/container/container/terminal/index.vue';
|
import TerminalDialog from '@/views/container/container/terminal/index.vue';
|
||||||
import CodemirrorDialog from '@/components/codemirror-dialog/index.vue';
|
import CodemirrorDialog from '@/components/codemirror-dialog/index.vue';
|
||||||
import Status from '@/components/status/index.vue';
|
import Status from '@/components/status/index.vue';
|
||||||
import { dateFormat } from '@/utils/util';
|
import { dateFormat } from '@/utils/util';
|
||||||
import { composeOperator, ContainerOperator, inspect, searchContainer } from '@/api/modules/container';
|
import { composeOperator, containerOperator, inspect, searchContainer } from '@/api/modules/container';
|
||||||
import { ElMessageBox } from 'element-plus';
|
import { ElMessageBox } from 'element-plus';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { Container } from '@/api/interface/container';
|
import { Container } from '@/api/interface/container';
|
||||||
@ -240,7 +238,7 @@ const onOperate = async (operation: string) => {
|
|||||||
operation: operation,
|
operation: operation,
|
||||||
newName: '',
|
newName: '',
|
||||||
};
|
};
|
||||||
ps.push(ContainerOperator(param));
|
ps.push(containerOperator(param));
|
||||||
}
|
}
|
||||||
Promise.all(ps)
|
Promise.all(ps)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -141,7 +141,7 @@ import CodemirrorDialog from '@/components/codemirror-dialog/index.vue';
|
|||||||
import Status from '@/components/status/index.vue';
|
import Status from '@/components/status/index.vue';
|
||||||
import { reactive, onMounted, ref } from 'vue';
|
import { reactive, onMounted, ref } from 'vue';
|
||||||
import {
|
import {
|
||||||
ContainerOperator,
|
containerOperator,
|
||||||
containerPrune,
|
containerPrune,
|
||||||
inspect,
|
inspect,
|
||||||
loadContainerInfo,
|
loadContainerInfo,
|
||||||
@ -352,7 +352,7 @@ const onOperate = async (operation: string) => {
|
|||||||
operation: operation,
|
operation: operation,
|
||||||
newName: '',
|
newName: '',
|
||||||
};
|
};
|
||||||
ps.push(ContainerOperator(param));
|
ps.push(containerOperator(param));
|
||||||
}
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
Promise.all(ps)
|
Promise.all(ps)
|
||||||
|
@ -62,7 +62,7 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onBeforeUnmount, ref } from 'vue';
|
import { onBeforeUnmount, ref } from 'vue';
|
||||||
import { ContainerStats } from '@/api/modules/container';
|
import { containerStats } from '@/api/modules/container';
|
||||||
import { dateFormatForSecond } from '@/utils/util';
|
import { dateFormatForSecond } from '@/utils/util';
|
||||||
import VCharts from '@/components/v-charts/index.vue';
|
import VCharts from '@/components/v-charts/index.vue';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
@ -125,7 +125,7 @@ const changeTimer = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
const res = await ContainerStats(dialogData.value.containerID);
|
const res = await containerStats(dialogData.value.containerID);
|
||||||
cpuDatas.value.push(res.data.cpuPercent.toFixed(2));
|
cpuDatas.value.push(res.data.cpuPercent.toFixed(2));
|
||||||
if (cpuDatas.value.length > 20) {
|
if (cpuDatas.value.length > 20) {
|
||||||
cpuDatas.value.splice(0, 1);
|
cpuDatas.value.splice(0, 1);
|
||||||
|
@ -94,31 +94,29 @@
|
|||||||
<el-input style="width: 40%" v-model.number="dialogData.rowData!.cpuShares" />
|
<el-input style="width: 40%" v-model.number="dialogData.rowData!.cpuShares" />
|
||||||
<span class="input-help">{{ $t('container.cpuShareHelper') }}</span>
|
<span class="input-help">{{ $t('container.cpuShareHelper') }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('container.cpuQuota')" prop="nanoCPUs">
|
<el-form-item
|
||||||
<el-input type="number" style="width: 40%" v-model.number="dialogData.rowData!.nanoCPUs">
|
:label="$t('container.cpuQuota')"
|
||||||
<template #append>
|
prop="nanoCPUs"
|
||||||
<el-select v-model="dialogData.rowData!.cpuUnit" disabled style="width: 85px">
|
:rules="checkNumberRange(0, limits.cpu)"
|
||||||
<el-option label="Core" value="Core" />
|
|
||||||
</el-select>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
<span class="input-help">{{ $t('container.limitHelper') }}</span>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item :label="$t('container.memoryLimit')" prop="memoryItem">
|
|
||||||
<el-input style="width: 40%" v-model.number="dialogData.rowData!.memoryItem">
|
|
||||||
<template #append>
|
|
||||||
<el-select
|
|
||||||
v-model="dialogData.rowData!.memoryUnit"
|
|
||||||
placeholder="Select"
|
|
||||||
style="width: 85px"
|
|
||||||
>
|
>
|
||||||
<el-option label="KB" value="KB" />
|
<el-input style="width: 40%" v-model.number="dialogData.rowData!.nanoCPUs">
|
||||||
<el-option label="MB" value="MB" />
|
<template #append>
|
||||||
<el-option label="GB" value="GB" />
|
<div style="width: 35px">{{ $t('home.coreUnit') }}</div>
|
||||||
</el-select>
|
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
<span class="input-help">{{ $t('container.limitHelper') }}</span>
|
<span class="input-help">
|
||||||
|
{{ $t('container.limitHelper', [limits.cpu]) }}{{ $t('home.coreUnit') }}
|
||||||
|
</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
:label="$t('container.memoryLimit')"
|
||||||
|
prop="memoryItem"
|
||||||
|
:rules="checkNumberRange(0, limits.memory)"
|
||||||
|
>
|
||||||
|
<el-input style="width: 40%" v-model.number="dialogData.rowData!.memoryItem">
|
||||||
|
<template #append><div style="width: 35px">MB</div></template>
|
||||||
|
</el-input>
|
||||||
|
<span class="input-help">{{ $t('container.limitHelper', [limits.memory]) }}MB</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('container.mount')">
|
<el-form-item :label="$t('container.mount')">
|
||||||
<el-card style="width: 100%">
|
<el-card style="width: 100%">
|
||||||
@ -224,10 +222,10 @@ import { Rules, checkNumberRange } from '@/global/form-rules';
|
|||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { ElForm } from 'element-plus';
|
import { ElForm } from 'element-plus';
|
||||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||||
import { listImage, listVolume, createContainer, updateContainer } from '@/api/modules/container';
|
import { listImage, listVolume, createContainer, updateContainer, loadResourceLimit } from '@/api/modules/container';
|
||||||
import { Container } from '@/api/interface/container';
|
import { Container } from '@/api/interface/container';
|
||||||
import { MsgError, MsgSuccess } from '@/utils/message';
|
import { MsgError, MsgSuccess } from '@/utils/message';
|
||||||
import { checkIp, checkPort, computeSize } from '@/utils/util';
|
import { checkIp, checkPort } from '@/utils/util';
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
interface DialogProps {
|
interface DialogProps {
|
||||||
@ -246,10 +244,7 @@ const acceptParams = (params: DialogProps): void => {
|
|||||||
dialogData.value = params;
|
dialogData.value = params;
|
||||||
title.value = i18n.global.t('commons.button.' + dialogData.value.title);
|
title.value = i18n.global.t('commons.button.' + dialogData.value.title);
|
||||||
if (params.title === 'edit') {
|
if (params.title === 'edit') {
|
||||||
dialogData.value.rowData.cpuUnit = 'Core';
|
dialogData.value.rowData.memoryItem = Number((dialogData.value.rowData.memory / 1024 / 1024).toFixed(2));
|
||||||
let itemMem = computeSize(Number(dialogData.value.rowData.memory));
|
|
||||||
dialogData.value.rowData.memoryItem = itemMem.indexOf(' ') !== -1 ? Number(itemMem.split(' ')[0]) : 0;
|
|
||||||
dialogData.value.rowData.memoryUnit = itemMem.indexOf(' ') !== -1 ? itemMem.split(' ')[1] : 'MB';
|
|
||||||
let itemCmd = '';
|
let itemCmd = '';
|
||||||
for (const item of dialogData.value.rowData.cmd) {
|
for (const item of dialogData.value.rowData.cmd) {
|
||||||
itemCmd += `'${item}' `;
|
itemCmd += `'${item}' `;
|
||||||
@ -261,6 +256,7 @@ const acceptParams = (params: DialogProps): void => {
|
|||||||
item.host = item.hostPort;
|
item.host = item.hostPort;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
loadLimit();
|
||||||
loadImageOptions();
|
loadImageOptions();
|
||||||
loadVolumeOptions();
|
loadVolumeOptions();
|
||||||
drawerVisiable.value = true;
|
drawerVisiable.value = true;
|
||||||
@ -269,6 +265,10 @@ const emit = defineEmits<{ (e: 'search'): void }>();
|
|||||||
|
|
||||||
const images = ref();
|
const images = ref();
|
||||||
const volumes = ref();
|
const volumes = ref();
|
||||||
|
const limits = ref<Container.ResourceLimit>({
|
||||||
|
cpu: null as number,
|
||||||
|
memory: null as number,
|
||||||
|
});
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
drawerVisiable.value = false;
|
drawerVisiable.value = false;
|
||||||
@ -311,6 +311,12 @@ const handleVolumesDelete = (index: number) => {
|
|||||||
dialogData.value.rowData!.volumes.splice(index, 1);
|
dialogData.value.rowData!.volumes.splice(index, 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const loadLimit = async () => {
|
||||||
|
const res = await loadResourceLimit();
|
||||||
|
limits.value = res.data;
|
||||||
|
limits.value.memory = Number((limits.value.memory / 1024 / 1024).toFixed(2));
|
||||||
|
};
|
||||||
|
|
||||||
const loadImageOptions = async () => {
|
const loadImageOptions = async () => {
|
||||||
const res = await listImage();
|
const res = await listImage();
|
||||||
images.value = res.data;
|
images.value = res.data;
|
||||||
@ -351,17 +357,8 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
|
|||||||
if (!checkPortValid()) {
|
if (!checkPortValid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (dialogData.value.rowData!.memoryUnit) {
|
|
||||||
case 'KB':
|
|
||||||
dialogData.value.rowData!.memory = dialogData.value.rowData!.memoryItem * 1024;
|
|
||||||
break;
|
|
||||||
case 'MB':
|
|
||||||
dialogData.value.rowData!.memory = dialogData.value.rowData!.memoryItem * 1024 * 1024;
|
dialogData.value.rowData!.memory = dialogData.value.rowData!.memoryItem * 1024 * 1024;
|
||||||
break;
|
|
||||||
case 'GB':
|
|
||||||
dialogData.value.rowData!.memory = dialogData.value.rowData!.memoryItem * 1024 * 1024 * 1024;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
if (dialogData.value.title === 'create') {
|
if (dialogData.value.title === 'create') {
|
||||||
await createContainer(dialogData.value.rowData!)
|
await createContainer(dialogData.value.rowData!)
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ContainerOperator } from '@/api/modules/container';
|
import { containerOperator } from '@/api/modules/container';
|
||||||
import { Rules } from '@/global/form-rules';
|
import { Rules } from '@/global/form-rules';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
@ -54,7 +54,7 @@ const onSubmitName = async (formEl: FormInstance | undefined) => {
|
|||||||
formEl.validate(async (valid) => {
|
formEl.validate(async (valid) => {
|
||||||
if (!valid) return;
|
if (!valid) return;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
await ContainerOperator(renameForm)
|
await containerOperator(renameForm)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
emit('search');
|
emit('search');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user