Skip to content

Commit 5674673

Browse files
authored
feat: Support display and operations for multi-YAML compose startup (#11421)
Refs #11405
1 parent 74f29e3 commit 5674673

File tree

18 files changed

+107
-60
lines changed

18 files changed

+107
-60
lines changed

agent/app/dto/container.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ type PageContainer struct {
1515
}
1616

1717
type InspectReq struct {
18-
ID string `json:"id" validate:"required"`
19-
Type string `json:"type" validate:"required"`
18+
ID string `json:"id" validate:"required"`
19+
Type string `json:"type" validate:"required"`
20+
Detail string `json:"detail"`
2021
}
2122

2223
type ContainerInfo struct {
@@ -284,17 +285,19 @@ type ComposeOperation struct {
284285
Path string `json:"path"`
285286
Operation string `json:"operation" validate:"required,oneof=up start restart stop down delete"`
286287
WithFile bool `json:"withFile"`
287-
Force bool `josn:"force"`
288+
Force bool `json:"force"`
288289
}
289290
type ComposeUpdate struct {
290-
Name string `json:"name" validate:"required"`
291-
Path string `json:"path" validate:"required"`
292-
Content string `json:"content" validate:"required"`
293-
Env string `json:"env"`
291+
Name string `json:"name" validate:"required"`
292+
Path string `json:"path" validate:"required"`
293+
DetailPath string `json:"detailPath"`
294+
Content string `json:"content" validate:"required"`
295+
Env string `json:"env"`
294296
}
295297
type ComposeLogClean struct {
296-
Name string `json:"name" validate:"required"`
297-
Path string `json:"path" validate:"required"`
298+
Name string `json:"name" validate:"required"`
299+
Path string `json:"path" validate:"required"`
300+
DetailPath string `json:"detailPath"`
298301
}
299302

300303
type ContainerLog struct {

agent/app/service/container.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,8 @@ import (
1919
"syscall"
2020
"time"
2121

22-
"github.com/1Panel-dev/1Panel/agent/app/repo"
23-
"github.com/gin-gonic/gin"
24-
25-
"github.com/pkg/errors"
26-
2722
"github.com/1Panel-dev/1Panel/agent/app/dto"
23+
"github.com/1Panel-dev/1Panel/agent/app/repo"
2824
"github.com/1Panel-dev/1Panel/agent/app/task"
2925
"github.com/1Panel-dev/1Panel/agent/buserr"
3026
"github.com/1Panel-dev/1Panel/agent/constant"
@@ -45,7 +41,9 @@ import (
4541
"github.com/docker/docker/api/types/volume"
4642
"github.com/docker/docker/client"
4743
"github.com/docker/go-connections/nat"
44+
"github.com/gin-gonic/gin"
4845
v1 "github.com/opencontainers/image-spec/specs-go/v1"
46+
"github.com/pkg/errors"
4947
"github.com/shirou/gopsutil/v4/cpu"
5048
"github.com/shirou/gopsutil/v4/mem"
5149
)
@@ -362,6 +360,9 @@ func (u *ContainerService) Inspect(req dto.InspectReq) (string, error) {
362360
}
363361
for _, container := range containers {
364362
config := container.Labels[composeConfigLabel]
363+
if len(req.Detail) != 0 && strings.Contains(config, req.Detail) {
364+
config = req.Detail
365+
}
365366
workdir := container.Labels[composeWorkdirLabel]
366367
if len(config) != 0 && len(workdir) != 0 && strings.Contains(config, workdir) {
367368
filePath = config
@@ -970,13 +971,20 @@ func collectLogs(done <-chan struct{}, params dto.StreamLog, messageChan chan<-
970971
var dockerCmd *exec.Cmd
971972
if params.Type == "compose" {
972973
dockerComposCmd := common.GetDockerComposeCommand()
974+
var yamlFiles []string
975+
for _, item := range strings.Split(params.Compose, ",") {
976+
if len(item) != 0 {
977+
yamlFiles = append(yamlFiles, "-f", item)
978+
}
979+
}
973980
if dockerComposCmd == "docker-compose" {
974-
newCmdArgs := append([]string{"-f", params.Compose}, cmdArgs...)
981+
newCmdArgs := append(yamlFiles, cmdArgs...)
975982
dockerCmd = exec.Command(dockerComposCmd, newCmdArgs...)
976983
} else {
977-
newCmdArgs := append([]string{"compose", "-f", params.Compose}, cmdArgs...)
984+
newCmdArgs := append(append([]string{"compose"}, yamlFiles...), cmdArgs...)
978985
dockerCmd = exec.Command("docker", newCmdArgs...)
979986
}
987+
global.LOG.Debug("Docker command:", dockerCmd.Args)
980988
} else {
981989
dockerCmd = exec.Command("docker", cmdArgs...)
982990
}

agent/app/service/container_compose.go

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package service
22

33
import (
44
"bufio"
5+
"context"
56
"errors"
67
"fmt"
78
"os"
@@ -24,7 +25,6 @@ import (
2425
"github.com/1Panel-dev/1Panel/agent/utils/docker"
2526
"github.com/docker/docker/api/types/container"
2627
"github.com/docker/docker/api/types/filters"
27-
"golang.org/x/net/context"
2828
)
2929

3030
const composeProjectLabel = "com.docker.compose.project"
@@ -233,14 +233,15 @@ func (u *ContainerService) ComposeOperation(req dto.ComposeOperation) error {
233233
return err
234234
}
235235
if req.WithFile {
236-
_ = os.RemoveAll(path.Dir(req.Path))
236+
for _, item := range strings.Split(req.Path, ",") {
237+
if len(item) != 0 {
238+
_ = os.RemoveAll(path.Dir(item))
239+
}
240+
}
237241
}
238242
_ = composeRepo.DeleteRecord(repo.WithByName(req.Name))
239243
return nil
240244
}
241-
if _, err := os.Stat(req.Path); err != nil {
242-
return fmt.Errorf("load file with path %s failed, %v", req.Path, err)
243-
}
244245
if req.Operation == "up" {
245246
if stdout, err := compose.Up(req.Path); err != nil {
246247
return fmt.Errorf("docker-compose up failed, std: %s, err: %v", stdout, err)
@@ -257,11 +258,11 @@ func (u *ContainerService) ComposeUpdate(req dto.ComposeUpdate) error {
257258
if cmd.CheckIllegal(req.Name, req.Path) {
258259
return buserr.New("ErrCmdIllegal")
259260
}
260-
oldFile, err := os.ReadFile(req.Path)
261+
oldFile, err := os.ReadFile(req.DetailPath)
261262
if err != nil {
262-
return fmt.Errorf("load file with path %s failed, %v", req.Path, err)
263+
return fmt.Errorf("load file with path %s failed, %v", req.DetailPath, err)
263264
}
264-
file, err := os.OpenFile(req.Path, os.O_WRONLY|os.O_TRUNC, 0640)
265+
file, err := os.OpenFile(req.DetailPath, os.O_WRONLY|os.O_TRUNC, 0640)
265266
if err != nil {
266267
return err
267268
}
@@ -270,8 +271,8 @@ func (u *ContainerService) ComposeUpdate(req dto.ComposeUpdate) error {
270271
_, _ = write.WriteString(req.Content)
271272
write.Flush()
272273

273-
global.LOG.Infof("docker-compose.yml %s has been replaced, now start to docker-compose restart", req.Path)
274-
if err := newComposeEnv(req.Path, req.Env); err != nil {
274+
global.LOG.Infof("docker-compose.yml %s has been replaced, now start to docker-compose restart", req.DetailPath)
275+
if err := newComposeEnv(req.DetailPath, req.Env); err != nil {
275276
return err
276277
}
277278

@@ -361,11 +362,8 @@ func (u *ContainerService) loadPath(req *dto.ComposeCreate) error {
361362
}
362363

363364
func removeContainerForCompose(composeName, composePath string) error {
364-
if _, err := os.Stat(composePath); err == nil {
365-
if stdout, err := compose.Operate(composePath, "down"); err != nil {
366-
return errors.New(stdout)
367-
}
368-
return nil
365+
if stdout, err := compose.Operate(composePath, "down"); err != nil {
366+
return errors.New(stdout)
369367
}
370368
var options container.ListOptions
371369
options.All = true
@@ -405,7 +403,11 @@ func recreateCompose(content, path string) error {
405403

406404
func loadEnv(list []dto.ComposeInfo) []dto.ComposeInfo {
407405
for i := 0; i < len(list); i++ {
408-
envFilePath := path.Join(path.Dir(list[i].Path), ".env")
406+
tmpPath := list[i].Path
407+
if strings.Contains(list[i].Path, ",") {
408+
tmpPath = strings.Split(list[i].Path, ",")[0]
409+
}
410+
envFilePath := path.Join(path.Dir(tmpPath), ".env")
409411
file, err := os.ReadFile(envFilePath)
410412
if err != nil {
411413
continue

agent/utils/compose/compose.go

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ func Up(filePath string) (string, error) {
3333
if err := checkCmd(); err != nil {
3434
return "", err
3535
}
36-
stdout, err := cmd.RunDefaultWithStdoutBashCfAndTimeOut(global.CONF.DockerConfig.Command+" -f %s up -d", 20*time.Minute, filePath)
37-
return stdout, err
36+
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Minute)).RunWithStdoutBashCf("%s %s up -d", global.CONF.DockerConfig.Command, loadFiles(filePath))
3837
}
3938

4039
func UpWithTask(filePath string, task *task.Task) error {
@@ -81,54 +80,56 @@ func UpWithTask(filePath string, task *task.Task) error {
8180
}
8281
}
8382

84-
dockerCommand := global.CONF.DockerConfig.Command
85-
if dockerCommand == "docker-compose" {
86-
return cmd.NewCommandMgr(cmd.WithTask(*task)).Run("docker-compose", "-f", filePath, "up", "-d")
87-
} else {
88-
return cmd.NewCommandMgr(cmd.WithTask(*task)).Run("docker", "compose", "-f", filePath, "up", "-d")
89-
}
83+
return cmd.NewCommandMgr(cmd.WithTask(*task)).Run("%s %s up -d", global.CONF.DockerConfig.Command, loadFiles(filePath))
9084
}
9185

9286
func Down(filePath string) (string, error) {
9387
if err := checkCmd(); err != nil {
9488
return "", err
9589
}
96-
stdout, err := cmd.RunDefaultWithStdoutBashCfAndTimeOut(global.CONF.DockerConfig.Command+" -f %s down --remove-orphans", 20*time.Minute, filePath)
97-
return stdout, err
90+
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Minute)).RunWithStdoutBashCf("%s %s down --remove-orphans", global.CONF.DockerConfig.Command, loadFiles(filePath))
9891
}
9992

10093
func Stop(filePath string) (string, error) {
10194
if err := checkCmd(); err != nil {
10295
return "", err
10396
}
104-
stdout, err := cmd.RunDefaultWithStdoutBashCf(global.CONF.DockerConfig.Command+" -f %s stop", filePath)
105-
return stdout, err
97+
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Minute)).RunWithStdoutBashCf("%s %s stop", global.CONF.DockerConfig.Command, loadFiles(filePath))
10698
}
10799

108100
func Restart(filePath string) (string, error) {
109101
if err := checkCmd(); err != nil {
110102
return "", err
111103
}
112-
stdout, err := cmd.RunDefaultWithStdoutBashCf(global.CONF.DockerConfig.Command+" -f %s restart", filePath)
113-
return stdout, err
104+
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Minute)).RunWithStdoutBashCf("%s %s restart", global.CONF.DockerConfig.Command, loadFiles(filePath))
114105
}
115106

116107
func Operate(filePath, operation string) (string, error) {
117108
if err := checkCmd(); err != nil {
118109
return "", err
119110
}
120-
stdout, err := cmd.RunDefaultWithStdoutBashCf(global.CONF.DockerConfig.Command+" -f %s %s", filePath, operation)
121-
return stdout, err
111+
return cmd.NewCommandMgr(cmd.WithTimeout(20*time.Minute)).RunWithStdoutBashCf("%s %s %s", global.CONF.DockerConfig.Command, loadFiles(filePath), operation)
122112
}
123113

124114
func DownAndUp(filePath string) (string, error) {
125115
if err := checkCmd(); err != nil {
126116
return "", err
127117
}
128-
stdout, err := cmd.RunDefaultWithStdoutBashCf(global.CONF.DockerConfig.Command+" -f %s down", filePath)
118+
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Minute))
119+
stdout, err := cmdMgr.RunWithStdoutBashCf("%s %s down", global.CONF.DockerConfig.Command, loadFiles(filePath))
129120
if err != nil {
130121
return stdout, err
131122
}
132-
stdout, err = cmd.RunDefaultWithStdoutBashCf(global.CONF.DockerConfig.Command+" -f %s up -d", filePath)
123+
stdout, err = cmdMgr.RunWithStdoutBashCf("%s %s up -d", global.CONF.DockerConfig.Command, loadFiles(filePath))
133124
return stdout, err
134125
}
126+
127+
func loadFiles(filePath string) string {
128+
var fileItem []string
129+
for _, item := range strings.Split(filePath, ",") {
130+
if len(item) != 0 {
131+
fileItem = append(fileItem, fmt.Sprintf("-f %s", item))
132+
}
133+
}
134+
return strings.Join(fileItem, " ")
135+
}

frontend/src/api/interface/container.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ export namespace Container {
173173
export interface ContainerInspect {
174174
id: string;
175175
type: string;
176+
detail: string;
176177
}
177178
export interface ContainerPrune {
178179
pruneType: string;

frontend/src/api/modules/container.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ export const upCompose = (params: Container.ComposeCreate) => {
190190
export const testCompose = (params: Container.ComposeCreate) => {
191191
return http.post<boolean>(`/containers/compose/test`, params);
192192
};
193-
export const composeOperator = (params: Container.ComposeOperation) => {
193+
export const composeOperate = (params: Container.ComposeOperation) => {
194194
return http.post(`/containers/compose/operate`, params);
195195
};
196196
export const composeUpdate = (params: Container.ComposeUpdate) => {

frontend/src/lang/modules/en.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,7 @@ const message = {
10171017
'If multiple private repositories exist, newlines must be displayed, for example:\n172.16.10.111:8081 \n172.16.10.112:8081',
10181018

10191019
compose: 'Compose | Composes',
1020+
composeFile: 'Compose File',
10201021
fromChangeHelper: 'Switching the source will clean the current edited content. Do you want to continue?',
10211022
composePathHelper: 'Configuration file save path: {0}',
10221023
composeHelper:

frontend/src/lang/modules/es-es.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,7 +1021,9 @@ const message = {
10211021
'Si hay varios mirrors, deben estar en líneas separadas. Ejemplo:\nhttp://xxxxxx.m.daocloud.io\nhttps://xxxxxx.mirror.aliyuncs.com',
10221022
registrieHelper:
10231023
'Si existen varios repositorios privados, deben estar en líneas separadas. Ejemplo:\n172.16.10.111:8081\n172.16.10.112:8081',
1024+
10241025
compose: 'Compose | Composes',
1026+
composeFile: 'Archivo de Orquestación',
10251027
fromChangeHelper: 'Cambiar la fuente limpiará el contenido actualmente editado. ¿Desea continuar?',
10261028
composePathHelper: 'Ruta de guardado del archivo de configuración: {0}',
10271029
composeHelper:

frontend/src/lang/modules/ja.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,7 @@ const message = {
995995
registrieHelper: '複数のプライベートリポジトリが存在する場合、たとえばnewlinesを表示する必要があります。',
996996

997997
compose: '構成|作曲',
998+
composeFile: 'オーケストレーションファイル',
998999
fromChangeHelper: 'ソースを切り替えると、現在の編集されたコンテンツがきれいになります。続けたいですか?',
9991000
composePathHelper: '構成ファイル保存パス:{0}',
10001001
composeHelper:

frontend/src/lang/modules/ko.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,7 @@ const message = {
983983
'개인 레지스트리가 여러 개 있을 경우 각 줄에 하나씩 표시해야 합니다. 예시:\n172.16.10.111:8081 \n172.16.10.112:8081',
984984

985985
compose: '컴포즈 | 컴포즈들',
986+
composeFile: '컴포즈 파일',
986987
fromChangeHelper: '소스를 변경하면 현재 편집한 내용이 삭제됩니다. 계속 하시겠습니까?',
987988
composePathHelper: '구성 파일 저장 경로: {0}',
988989
composeHelper: '1Panel 에디터나 템플릿을 통해 생성된 컴포지션은 {0}/docker/compose 디렉토리에 저장됩니다.',

0 commit comments

Comments
 (0)