From c82e20efd78c2adb50a65044453775ca1b967813 Mon Sep 17 00:00:00 2001 From: ssongliu <73214554+ssongliu@users.noreply.github.com> Date: Thu, 15 Jun 2023 20:44:13 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=B9=E5=99=A8=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=A2=9E=E5=8A=A0=20cpu=20=E3=80=81=E5=86=85?= =?UTF-8?q?=E5=AD=98=E6=9C=80=E5=A4=A7=E9=99=90=E5=88=B6=20(#1383)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/v1/container.go | 14 ++++ backend/app/dto/container.go | 5 ++ backend/app/service/container.go | 20 ++++++ backend/router/ro_container.go | 1 + cmd/server/docs/docs.go | 30 ++++++++ cmd/server/docs/swagger.json | 30 ++++++++ cmd/server/docs/swagger.yaml | 18 +++++ frontend/src/api/interface/container.ts | 6 +- frontend/src/api/modules/container.ts | 7 +- frontend/src/lang/modules/en.ts | 2 +- frontend/src/lang/modules/zh.ts | 2 +- .../views/container/compose/detail/index.vue | 6 +- .../src/views/container/container/index.vue | 4 +- .../container/container/monitor/index.vue | 4 +- .../container/container/operate/index.vue | 69 +++++++++---------- .../container/container/rename/index.vue | 4 +- 16 files changed, 170 insertions(+), 52 deletions(-) diff --git a/backend/app/api/v1/container.go b/backend/app/api/v1/container.go index 90773bef1..b9482a504 100644 --- a/backend/app/api/v1/container.go +++ b/backend/app/api/v1/container.go @@ -205,6 +205,20 @@ func (b *BaseApi) ContainerInfo(c *gin.Context) { 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 // @Summary Create container // @Description 创建容器 diff --git a/backend/app/dto/container.go b/backend/app/dto/container.go index caee347d2..0d017474d 100644 --- a/backend/app/dto/container.go +++ b/backend/app/dto/container.go @@ -30,6 +30,11 @@ type ContainerInfo struct { IsFromCompose bool `json:"isFromCompose"` } +type ResourceLimit struct { + CPU int `json:"cpu"` + Memory int `json:"memory"` +} + type ContainerOperate struct { Name string `json:"name"` Image string `json:"image"` diff --git a/backend/app/service/container.go b/backend/app/service/container.go index 51b0e1d51..c4aa0a87f 100644 --- a/backend/app/service/container.go +++ b/backend/app/service/container.go @@ -27,6 +27,8 @@ import ( "github.com/docker/go-connections/nat" "github.com/gorilla/websocket" v1 "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/shirou/gopsutil/v3/cpu" + "github.com/shirou/gopsutil/v3/mem" ) type ContainerService struct{} @@ -42,6 +44,7 @@ type IContainerService interface { ContainerCreate(req dto.ContainerOperate) error ContainerUpdate(req dto.ContainerOperate) error ContainerInfo(req dto.OperationWithName) (*dto.ContainerOperate, error) + LoadResouceLimit() (*dto.ResourceLimit, error) ContainerLogClean(req dto.OperationWithName) error ContainerOperation(req dto.ContainerOperation) 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 } +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 { client, err := docker.NewDockerClient() if err != nil { diff --git a/backend/router/ro_container.go b/backend/router/ro_container.go index 594e17947..23cc6dc95 100644 --- a/backend/router/ro_container.go +++ b/backend/router/ro_container.go @@ -23,6 +23,7 @@ func (s *ContainerRouter) InitContainerRouter(Router *gin.RouterGroup) { baRouter.POST("/info", baseApi.ContainerInfo) baRouter.POST("/search", baseApi.SearchContainer) baRouter.GET("/search/log", baseApi.ContainerLogs) + baRouter.GET("/limit", baseApi.LoadResouceLimit) baRouter.POST("/clean/log", baseApi.CleanContainerLog) baRouter.POST("/inspect", baseApi.Inspect) baRouter.POST("/operate", baseApi.ContainerOperation) diff --git a/cmd/server/docs/docs.go b/cmd/server/docs/docs.go index 5da806e28..c31a7a2c1 100644 --- a/cmd/server/docs/docs.go +++ b/cmd/server/docs/docs.go @@ -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": { "post": { "security": [ @@ -12408,6 +12427,17 @@ var doc = `{ } } }, + "dto.ResourceLimit": { + "type": "object", + "properties": { + "cpu": { + "type": "integer" + }, + "memory": { + "type": "integer" + } + } + }, "dto.SSHConf": { "type": "object", "properties": { diff --git a/cmd/server/docs/swagger.json b/cmd/server/docs/swagger.json index ae97ed90e..34804055d 100644 --- a/cmd/server/docs/swagger.json +++ b/cmd/server/docs/swagger.json @@ -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": { "post": { "security": [ @@ -12394,6 +12413,17 @@ } } }, + "dto.ResourceLimit": { + "type": "object", + "properties": { + "cpu": { + "type": "integer" + }, + "memory": { + "type": "integer" + } + } + }, "dto.SSHConf": { "type": "object", "properties": { diff --git a/cmd/server/docs/swagger.yaml b/cmd/server/docs/swagger.yaml index 8aefbc18e..18b0dd483 100644 --- a/cmd/server/docs/swagger.yaml +++ b/cmd/server/docs/swagger.yaml @@ -1422,6 +1422,13 @@ definitions: used_memory_rss: type: string type: object + dto.ResourceLimit: + properties: + cpu: + type: integer + memory: + type: integer + type: object dto.SSHConf: properties: file: @@ -4529,6 +4536,17 @@ paths: summary: Container inspect tags: - Container + /containers/limit: + get: + description: 获取容器限制 + responses: + "200": + description: OK + schema: + $ref: '#/definitions/dto.ResourceLimit' + security: + - ApiKeyAuth: [] + summary: Load container limis /containers/network: post: consumes: diff --git a/frontend/src/api/interface/container.ts b/frontend/src/api/interface/container.ts index 6f581d83c..c814ee3e7 100644 --- a/frontend/src/api/interface/container.ts +++ b/frontend/src/api/interface/container.ts @@ -10,18 +10,20 @@ export namespace Container { name: string; filters: string; } + export interface ResourceLimit { + cpu: number; + memory: number; + } export interface ContainerHelper { name: string; image: string; cmdStr: string; - memoryUnit: string; memoryItem: number; cmd: Array; publishAllPorts: boolean; exposedPorts: Array; nanoCPUs: number; cpuShares: number; - cpuUnit: string; memory: number; volumes: Array; autoRemove: boolean; diff --git a/frontend/src/api/modules/container.ts b/frontend/src/api/modules/container.ts index eea00225a..88ce65e66 100644 --- a/frontend/src/api/modules/container.ts +++ b/frontend/src/api/modules/container.ts @@ -5,6 +5,9 @@ import { Container } from '../interface/container'; export const searchContainer = (params: Container.ContainerSearch) => { return http.post>(`/containers/search`, params, 400000); }; +export const loadResourceLimit = () => { + return http.get(`/containers/limit`); +}; export const createContainer = (params: Container.ContainerHelper) => { return http.post(`/containers`, params, 3000000); }; @@ -17,10 +20,10 @@ export const loadContainerInfo = (name: string) => { export const cleanContainerLog = (containerName: string) => { return http.post(`/containers/clean/log`, { name: containerName }); }; -export const ContainerStats = (id: string) => { +export const containerStats = (id: string) => { return http.get(`/containers/stats/${id}`); }; -export const ContainerOperator = (params: Container.ContainerOperate) => { +export const containerOperator = (params: Container.ContainerOperate) => { return http.post(`/containers/operate`, params); }; export const containerPrune = (params: Container.ContainerPrune) => { diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 4048def71..28fc8af4d 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -507,7 +507,7 @@ const message = { autoRemove: 'Auto remove', cpuQuota: 'NacosCPU', 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', serverPath: 'Server path', containerDir: 'Container path', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 2de4334f4..db6aa295a 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -512,7 +512,7 @@ const message = { autoRemove: '容器退出后自动删除容器', cpuQuota: 'CPU 限制', memoryLimit: '内存限制', - limitHelper: '限制为 0 则关闭限制', + limitHelper: '限制为 0 则关闭限制,最大可用为 {0}', mount: '挂载卷', serverPath: '服务器目录', containerDir: '容器目录', diff --git a/frontend/src/views/container/compose/detail/index.vue b/frontend/src/views/container/compose/detail/index.vue index 0effa5219..118d58bec 100644 --- a/frontend/src/views/container/compose/detail/index.vue +++ b/frontend/src/views/container/compose/detail/index.vue @@ -104,7 +104,6 @@ - @@ -115,14 +114,13 @@