fix: 删除容器后 compose 记录保存以便后续处理 (#6447)
Some checks failed
Build Test / build-linux-binary (push) Failing after -8m28s
Build / SonarCloud (push) Failing after -8m53s
sync2gitee / repo-sync (push) Failing after -8m58s

Refs https://github.com/1Panel-dev/1Panel/issues/5099
This commit is contained in:
John Bro 2024-09-12 18:06:22 +08:00 committed by GitHub
parent 1dfbca3d5b
commit 535d4bbe1b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 71 additions and 11 deletions

View file

@ -116,7 +116,7 @@ type PortHelper struct {
type ContainerOperation struct { type ContainerOperation struct {
Names []string `json:"names" validate:"required"` Names []string `json:"names" validate:"required"`
Operation string `json:"operation" validate:"required,oneof=start stop restart kill pause unpause remove"` Operation string `json:"operation" validate:"required,oneof=up start stop restart kill pause unpause remove"`
} }
type ContainerRename struct { type ContainerRename struct {
@ -217,7 +217,7 @@ type ComposeCreate struct {
type ComposeOperation struct { type ComposeOperation struct {
Name string `json:"name" validate:"required"` Name string `json:"name" validate:"required"`
Path string `json:"path" validate:"required"` Path string `json:"path" validate:"required"`
Operation string `json:"operation" validate:"required,oneof=start stop down"` Operation string `json:"operation" validate:"required,oneof=up start stop down"`
WithFile bool `json:"withFile"` WithFile bool `json:"withFile"`
} }
type ComposeUpdate struct { type ComposeUpdate struct {

View file

@ -12,4 +12,5 @@ type Compose struct {
BaseModel BaseModel
Name string `gorm:"type:varchar(256)" json:"name"` Name string `gorm:"type:varchar(256)" json:"name"`
Path string `gorm:"type:varchar(256)" json:"path"`
} }

View file

@ -19,6 +19,7 @@ type IComposeTemplateRepo interface {
CreateRecord(compose *model.Compose) error CreateRecord(compose *model.Compose) error
DeleteRecord(opts ...DBOption) error DeleteRecord(opts ...DBOption) error
ListRecord() ([]model.Compose, error) ListRecord() ([]model.Compose, error)
UpdateRecord(name string, vars map[string]interface{}) error
} }
func NewIComposeTemplateRepo() IComposeTemplateRepo { func NewIComposeTemplateRepo() IComposeTemplateRepo {
@ -102,3 +103,7 @@ func (u *ComposeTemplateRepo) DeleteRecord(opts ...DBOption) error {
} }
return db.Delete(&model.Compose{}).Error return db.Delete(&model.Compose{}).Error
} }
func (u *ComposeTemplateRepo) UpdateRecord(name string, vars map[string]interface{}) error {
return global.DB.Model(&model.Compose{}).Where("name = ?", name).Updates(vars).Error
}

View file

@ -898,6 +898,10 @@ func (u *ContainerService) LoadContainerLogs(req dto.OperationWithNameAndType) s
break break
} }
} }
if len(containers) == 0 {
composeItem, _ := composeRepo.GetRecord(commonRepo.WithByName(req.Name))
filePath = composeItem.Path
}
} }
if _, err := os.Stat(filePath); err != nil { if _, err := os.Stat(filePath); err != nil {
return "" return ""

View file

@ -52,6 +52,20 @@ func (u *ContainerService) PageCompose(req dto.SearchWithPage) (int64, interface
} }
composeCreatedByLocal, _ := composeRepo.ListRecord() composeCreatedByLocal, _ := composeRepo.ListRecord()
composeLocalMap := make(map[string]dto.ComposeInfo)
for _, localItem := range composeCreatedByLocal {
composeItemLocal := dto.ComposeInfo{
ContainerNumber: 0,
CreatedAt: localItem.CreatedAt.Format(constant.DateTimeLayout),
ConfigFile: localItem.Path,
Workdir: strings.TrimSuffix(localItem.Path, "/docker-compose.yml"),
}
composeItemLocal.CreatedBy = "1Panel"
composeItemLocal.Path = localItem.Path
composeLocalMap[localItem.Name] = composeItemLocal
}
composeMap := make(map[string]dto.ComposeInfo) composeMap := make(map[string]dto.ComposeInfo)
for _, container := range list { for _, container := range list {
if name, ok := container.Labels[composeProjectLabel]; ok { if name, ok := container.Labels[composeProjectLabel]; ok {
@ -95,12 +109,24 @@ func (u *ContainerService) PageCompose(req dto.SearchWithPage) (int64, interface
} }
} }
} }
for _, item := range composeCreatedByLocal {
if err := composeRepo.DeleteRecord(commonRepo.WithByID(item.ID)); err != nil { mergedMap := make(map[string]dto.ComposeInfo)
global.LOG.Error(err) for key, localItem := range composeLocalMap {
mergedMap[key] = localItem
}
for key, item := range composeMap {
if existingItem, exists := mergedMap[key]; exists {
if item.ContainerNumber > 0 {
if existingItem.ContainerNumber <= 0 {
mergedMap[key] = item
}
}
} else {
mergedMap[key] = item
} }
} }
for key, value := range composeMap {
for key, value := range mergedMap {
value.Name = key value.Name = key
records = append(records, value) records = append(records, value)
} }
@ -186,7 +212,7 @@ func (u *ContainerService) CreateCompose(req dto.ComposeCreate) (string, error)
return return
} }
global.LOG.Infof("docker-compose up %s successful!", req.Name) global.LOG.Infof("docker-compose up %s successful!", req.Name)
_ = composeRepo.CreateRecord(&model.Compose{Name: req.Name}) _ = composeRepo.CreateRecord(&model.Compose{Name: req.Name, Path: req.Path})
_, _ = file.WriteString("docker-compose up successful!") _, _ = file.WriteString("docker-compose up successful!")
}() }()
@ -200,14 +226,27 @@ func (u *ContainerService) ComposeOperation(req dto.ComposeOperation) error {
if _, err := os.Stat(req.Path); err != nil { if _, err := os.Stat(req.Path); err != nil {
return fmt.Errorf("load file with path %s failed, %v", req.Path, err) return fmt.Errorf("load file with path %s failed, %v", req.Path, err)
} }
if stdout, err := compose.Operate(req.Path, req.Operation); err != nil { if req.Operation == "up" {
return errors.New(string(stdout)) if stdout, err := compose.Up(req.Path); err != nil {
return errors.New(string(stdout))
}
} else {
if stdout, err := compose.Operate(req.Path, req.Operation); err != nil {
return errors.New(string(stdout))
}
} }
global.LOG.Infof("docker-compose %s %s successful", req.Operation, req.Name) global.LOG.Infof("docker-compose %s %s successful", req.Operation, req.Name)
if req.Operation == "down" { if req.Operation == "down" {
_ = composeRepo.DeleteRecord(commonRepo.WithByName(req.Name))
if req.WithFile { if req.WithFile {
_ = composeRepo.DeleteRecord(commonRepo.WithByName(req.Name))
_ = os.RemoveAll(path.Dir(req.Path)) _ = os.RemoveAll(path.Dir(req.Path))
} else {
composeItem, _ := composeRepo.GetRecord(commonRepo.WithByName(req.Name))
if composeItem.Path == "" {
upMap := make(map[string]interface{})
upMap["path"] = req.Path
_ = composeRepo.UpdateRecord(req.Name, upMap)
}
} }
} }

View file

@ -94,6 +94,7 @@ func Init() {
migrations.AddClam, migrations.AddClam,
migrations.AddClamStatus, migrations.AddClamStatus,
migrations.AddAlertMenu, migrations.AddAlertMenu,
migrations.AddComposeColumn,
}) })
if err := m.Migrate(); err != nil { if err := m.Migrate(); err != nil {
global.LOG.Error(err) global.LOG.Error(err)

View file

@ -314,3 +314,13 @@ var AddAlertMenu = &gormigrate.Migration{
return tx.Model(&model.Setting{}).Where("key", "XpackHideMenu").Updates(map[string]interface{}{"value": string(data)}).Error return tx.Model(&model.Setting{}).Where("key", "XpackHideMenu").Updates(map[string]interface{}{"value": string(data)}).Error
}, },
} }
var AddComposeColumn = &gormigrate.Migration{
ID: "20240906-add-compose-command",
Migrate: func(tx *gorm.DB) error {
if err := tx.AutoMigrate(&model.Compose{}); err != nil {
return err
}
return nil
},
}

View file

@ -7,7 +7,7 @@
<el-tag effect="dark" type="success">{{ composeName }}</el-tag> <el-tag effect="dark" type="success">{{ composeName }}</el-tag>
</div> </div>
<div v-if="createdBy === '1Panel'" style="margin-left: 50px"> <div v-if="createdBy === '1Panel'" style="margin-left: 50px">
<el-button link type="primary" @click="onComposeOperate('start')"> <el-button link type="primary" @click="onComposeOperate('up')">
{{ $t('container.start') }} {{ $t('container.start') }}
</el-button> </el-button>
<el-divider direction="vertical" /> <el-divider direction="vertical" />