feat: 优化应用安装和删除逻辑 (#6112)

This commit is contained in:
zhengkunwang 2024-08-13 15:28:39 +08:00 committed by GitHub
parent c7c5f75d17
commit d100edb75b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 91 additions and 52 deletions

View file

@ -136,7 +136,7 @@ func (a *AppInstallRepo) Create(ctx context.Context, install *model.AppInstall)
} }
func (a *AppInstallRepo) Save(ctx context.Context, install *model.AppInstall) error { func (a *AppInstallRepo) Save(ctx context.Context, install *model.AppInstall) error {
return getTx(ctx).Save(&install).Error return getTx(ctx).Debug().Omit("App").Save(&install).Error
} }
func (a *AppInstallRepo) DeleteBy(opts ...DBOption) error { func (a *AppInstallRepo) DeleteBy(opts ...DBOption) error {

View file

@ -446,7 +446,7 @@ func (a *AppInstallService) SyncAll(systemInit bool) error {
return err return err
} }
for _, i := range allList { for _, i := range allList {
if i.Status == constant.Installing || i.Status == constant.Upgrading || i.Status == constant.Rebuilding { if i.Status == constant.Installing || i.Status == constant.Upgrading || i.Status == constant.Rebuilding || i.Status == constant.Uninstalling {
if systemInit { if systemInit {
i.Status = constant.Error i.Status = constant.Error
i.Message = "1Panel restart causes the task to terminate" i.Message = "1Panel restart causes the task to terminate"
@ -755,7 +755,7 @@ func (a *AppInstallService) GetParams(id uint) (*response.AppConfig, error) {
} }
func syncAppInstallStatus(appInstall *model.AppInstall, force bool) error { func syncAppInstallStatus(appInstall *model.AppInstall, force bool) error {
if appInstall.Status == constant.Installing || appInstall.Status == constant.Rebuilding || appInstall.Status == constant.Upgrading { if appInstall.Status == constant.Installing || appInstall.Status == constant.Rebuilding || appInstall.Status == constant.Upgrading || appInstall.Status == constant.Uninstalling {
return nil return nil
} }
cli, err := docker.NewClient() cli, err := docker.NewClient()

View file

@ -330,6 +330,8 @@ func deleteAppInstall(deleteReq request.AppInstallDelete) error {
} }
uninstall := func(t *task.Task) error { uninstall := func(t *task.Task) error {
install.Status = constant.Uninstalling
_ = appInstallRepo.Save(context.Background(), &install)
dir, _ := os.Stat(appDir) dir, _ := os.Stat(appDir)
if dir != nil { if dir != nil {
logStr := i18n.GetMsgByKey("Stop") + i18n.GetMsgByKey("App") logStr := i18n.GetMsgByKey("Stop") + i18n.GetMsgByKey("App")
@ -346,7 +348,15 @@ func deleteAppInstall(deleteReq request.AppInstallDelete) error {
} }
if deleteReq.DeleteImage { if deleteReq.DeleteImage {
delImageStr := i18n.GetMsgByKey("TaskDelete") + i18n.GetMsgByKey("Image") delImageStr := i18n.GetMsgByKey("TaskDelete") + i18n.GetMsgByKey("Image")
images, _ := getImages(install) projectName := strings.ToLower(install.Name)
content, err := op.GetContent(install.GetEnvPath())
if err != nil {
return err
}
images, err := composeV2.GetDockerComposeImages(projectName, content, []byte(install.DockerCompose))
if err != nil {
return err
}
client, err := docker.NewClient() client, err := docker.NewClient()
if err != nil { if err != nil {
return err return err
@ -440,7 +450,12 @@ func deleteAppInstall(deleteReq request.AppInstallDelete) error {
return nil return nil
} }
uninstallTask.AddSubTask(task.GetTaskName(install.Name, task.TaskUninstall, task.TaskScopeApp), uninstall, nil) uninstallTask.AddSubTask(task.GetTaskName(install.Name, task.TaskUninstall, task.TaskScopeApp), uninstall, nil)
go uninstallTask.Execute() go func() {
if err := uninstallTask.Execute(); err != nil {
install.Status = constant.Error
_ = appInstallRepo.Save(context.Background(), &install)
}
}()
return nil return nil
} }
@ -746,22 +761,6 @@ func getContainerNames(install model.AppInstall) ([]string, error) {
return containerNames, nil return containerNames, nil
} }
func getImages(install model.AppInstall) ([]string, error) {
envStr, err := coverEnvJsonToStr(install.Env)
if err != nil {
return nil, err
}
project, err := composeV2.GetComposeProject(install.Name, install.GetPath(), []byte(install.DockerCompose), []byte(envStr), true)
if err != nil {
return nil, err
}
var images []string
for _, service := range project.AllServices() {
images = append(images, service.Image)
}
return images, nil
}
func coverEnvJsonToStr(envJson string) (string, error) { func coverEnvJsonToStr(envJson string) (string, error) {
envMap := make(map[string]interface{}) envMap := make(map[string]interface{})
_ = json.Unmarshal([]byte(envJson), &envMap) _ = json.Unmarshal([]byte(envJson), &envMap)
@ -1254,10 +1253,11 @@ func handleErr(install model.AppInstall, err error, out string) error {
func doNotNeedSync(installed model.AppInstall) bool { func doNotNeedSync(installed model.AppInstall) bool {
return installed.Status == constant.Installing || installed.Status == constant.Rebuilding || installed.Status == constant.Upgrading || return installed.Status == constant.Installing || installed.Status == constant.Rebuilding || installed.Status == constant.Upgrading ||
installed.Status == constant.Syncing installed.Status == constant.Syncing || installed.Status == constant.Uninstalling
} }
func synAppInstall(containers map[string]types.Container, appInstall *model.AppInstall, force bool) { func synAppInstall(containers map[string]types.Container, appInstall *model.AppInstall, force bool) {
oldStatus := appInstall.Status
containerNames := strings.Split(appInstall.ContainerName, ",") containerNames := strings.Split(appInstall.ContainerName, ",")
if len(containers) == 0 { if len(containers) == 0 {
if appInstall.Status == constant.UpErr && !force { if appInstall.Status == constant.UpErr && !force {
@ -1294,6 +1294,9 @@ func synAppInstall(containers map[string]types.Container, appInstall *model.AppI
appInstall.Status = constant.Stopped appInstall.Status = constant.Stopped
case runningCount == total: case runningCount == total:
appInstall.Status = constant.Running appInstall.Status = constant.Running
if oldStatus == constant.Running {
return
}
case pausedCount == total: case pausedCount == total:
appInstall.Status = constant.Paused appInstall.Status = constant.Paused
case len(notFoundNames) == total: case len(notFoundNames) == total:

View file

@ -1,20 +1,21 @@
package constant package constant
const ( const (
Running = "Running" Running = "Running"
UnHealthy = "UnHealthy" UnHealthy = "UnHealthy"
Error = "Error" Error = "Error"
Stopped = "Stopped" Stopped = "Stopped"
Installing = "Installing" Installing = "Installing"
DownloadErr = "DownloadErr" DownloadErr = "DownloadErr"
Upgrading = "Upgrading" Upgrading = "Upgrading"
UpgradeErr = "UpgradeErr" UpgradeErr = "UpgradeErr"
Rebuilding = "Rebuilding" Rebuilding = "Rebuilding"
Syncing = "Syncing" Syncing = "Syncing"
SyncSuccess = "SyncSuccess" SyncSuccess = "SyncSuccess"
Paused = "Paused" Paused = "Paused"
UpErr = "UpErr" UpErr = "UpErr"
InstallErr = "InstallErr" InstallErr = "InstallErr"
Uninstalling = "Uninstalling"
ContainerPrefix = "1Panel-" ContainerPrefix = "1Panel-"

View file

@ -59,6 +59,7 @@ func GetDockerComposeImages(projectName string, env, yml []byte) ([]string, erro
var ( var (
configFiles []types.ConfigFile configFiles []types.ConfigFile
images []string images []string
imagesMap = make(map[string]struct{})
) )
configFiles = append(configFiles, types.ConfigFile{ configFiles = append(configFiles, types.ConfigFile{
Filename: "docker-compose.yml", Filename: "docker-compose.yml",
@ -81,7 +82,10 @@ func GetDockerComposeImages(projectName string, env, yml []byte) ([]string, erro
return nil, err return nil, err
} }
for _, service := range project.AllServices() { for _, service := range project.AllServices() {
images = append(images, service.Image) imagesMap[service.Image] = struct{}{}
}
for image := range imagesMap {
images = append(images, image)
} }
return images, nil return images, nil
} }

View file

@ -72,16 +72,21 @@ func countLines(path string) (int, error) {
return 0, err return 0, err
} }
defer file.Close() defer file.Close()
reader := bufio.NewReader(file)
scanner := bufio.NewScanner(file) count := 0
lineCount := 0 for {
for scanner.Scan() { _, err := reader.ReadString('\n')
lineCount++ if err != nil {
if err == io.EOF {
if count > 0 {
count++
}
return count, nil
}
return count, err
}
count++
} }
if err := scanner.Err(); err != nil {
return 0, err
}
return lineCount, nil
} }
func ReadFileByLine(filename string, page, pageSize int, latest bool) (lines []string, isEndOfFile bool, total int, err error) { func ReadFileByLine(filename string, page, pageSize int, latest bool) (lines []string, isEndOfFile bool, total int, err error) {

View file

@ -51,6 +51,7 @@ const loadingStatus = [
'starting', 'starting',
'removing', 'removing',
'applying', 'applying',
'uninstalling',
]; ];
const loadingIcon = (status: string): boolean => { const loadingIcon = (status: string): boolean => {

View file

@ -280,6 +280,7 @@ const message = {
applyerror: 'Failure', applyerror: 'Failure',
syncerr: 'Error', syncerr: 'Error',
uperr: 'Error', uperr: 'Error',
uninstalling: 'Uninstalling',
}, },
units: { units: {
second: 'Second', second: 'Second',

View file

@ -275,6 +275,7 @@ const message = {
applyerror: '失敗', applyerror: '失敗',
syncerr: '失敗', syncerr: '失敗',
uperr: '失败', uperr: '失败',
uninstalling: '卸載中',
}, },
units: { units: {
second: '秒', second: '秒',

View file

@ -275,6 +275,7 @@ const message = {
applyerror: '失败', applyerror: '失败',
syncerr: '失败', syncerr: '失败',
uperr: '失败', uperr: '失败',
uninstalling: '卸载中',
}, },
units: { units: {
second: '秒', second: '秒',

View file

@ -520,7 +520,12 @@ const buttons = [
openOperate(row, 'sync'); openOperate(row, 'sync');
}, },
disabled: (row: any) => { disabled: (row: any) => {
return row.status === 'DownloadErr' || row.status === 'Upgrading' || row.status === 'Rebuilding'; return (
row.status === 'DownloadErr' ||
row.status === 'Upgrading' ||
row.status === 'Rebuilding' ||
row.status === 'Uninstalling'
);
}, },
}, },
{ {
@ -529,7 +534,12 @@ const buttons = [
openOperate(row, 'rebuild'); openOperate(row, 'rebuild');
}, },
disabled: (row: any) => { disabled: (row: any) => {
return row.status === 'DownloadErr' || row.status === 'Upgrading' || row.status === 'Rebuilding'; return (
row.status === 'DownloadErr' ||
row.status === 'Upgrading' ||
row.status === 'Rebuilding' ||
row.status === 'Uninstalling'
);
}, },
}, },
{ {
@ -538,7 +548,12 @@ const buttons = [
openOperate(row, 'restart'); openOperate(row, 'restart');
}, },
disabled: (row: any) => { disabled: (row: any) => {
return row.status === 'DownloadErr' || row.status === 'Upgrading' || row.status === 'Rebuilding'; return (
row.status === 'DownloadErr' ||
row.status === 'Upgrading' ||
row.status === 'Rebuilding' ||
row.status === 'Uninstalling'
);
}, },
}, },
{ {
@ -552,7 +567,8 @@ const buttons = [
row.status === 'Error' || row.status === 'Error' ||
row.status === 'DownloadErr' || row.status === 'DownloadErr' ||
row.status === 'Upgrading' || row.status === 'Upgrading' ||
row.status === 'Rebuilding' row.status === 'Rebuilding' ||
row.status === 'Uninstalling'
); );
}, },
}, },
@ -566,7 +582,8 @@ const buttons = [
row.status !== 'Running' || row.status !== 'Running' ||
row.status === 'DownloadErr' || row.status === 'DownloadErr' ||
row.status === 'Upgrading' || row.status === 'Upgrading' ||
row.status === 'Rebuilding' row.status === 'Rebuilding' ||
row.status === 'Uninstalling'
); );
}, },
}, },
@ -582,7 +599,12 @@ const buttons = [
openParam(row); openParam(row);
}, },
disabled: (row: any) => { disabled: (row: any) => {
return row.status === 'DownloadErr' || row.status === 'Upgrading' || row.status === 'Rebuilding'; return (
row.status === 'DownloadErr' ||
row.status === 'Upgrading' ||
row.status === 'Rebuilding' ||
row.status === 'Uninstalling'
);
}, },
}, },
]; ];