feat: 优化应用状态同步 (#3866)

This commit is contained in:
zhengkunwang 2024-02-09 09:50:11 +08:00 committed by GitHub
parent 3fd7aa17a8
commit e6a43d22c8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 75 additions and 90 deletions

View file

@ -12,8 +12,6 @@ import (
"strconv"
"strings"
"github.com/1Panel-dev/1Panel/backend/i18n"
"github.com/1Panel-dev/1Panel/backend/utils/files"
"gopkg.in/yaml.v3"
@ -152,7 +150,7 @@ func (a *AppInstallService) CheckExist(req request.AppInstalledInfo) (*response.
if reflect.DeepEqual(appInstall, model.AppInstall{}) {
return res, nil
}
if err = syncByID(appInstall.ID); err != nil {
if err = syncAppInstallStatus(&appInstall); err != nil {
return nil, err
}
@ -242,26 +240,26 @@ func (a *AppInstallService) Operate(req request.AppInstalledOperate) error {
if err != nil {
return handleErr(install, err, out)
}
return syncByID(install.ID)
return syncAppInstallStatus(&install)
case constant.Stop:
out, err := compose.Stop(dockerComposePath)
if err != nil {
return handleErr(install, err, out)
}
return syncByID(install.ID)
return syncAppInstallStatus(&install)
case constant.Restart:
out, err := compose.Restart(dockerComposePath)
if err != nil {
return handleErr(install, err, out)
}
return syncByID(install.ID)
return syncAppInstallStatus(&install)
case constant.Delete:
if err := deleteAppInstall(install, req.DeleteBackup, req.ForceDelete, req.DeleteDB); err != nil && !req.ForceDelete {
return err
}
return nil
case constant.Sync:
return syncByID(install.ID)
return syncAppInstallStatus(&install)
case constant.Upgrade:
return upgradeInstall(install.ID, req.DetailId, req.Backup, req.PullImage)
case constant.Reload:
@ -422,7 +420,7 @@ func (a *AppInstallService) SyncAll(systemInit bool) error {
continue
}
if !systemInit {
if err := syncByID(i.ID); err != nil {
if err = syncAppInstallStatus(&i); err != nil {
global.LOG.Errorf("sync install app[%s] error,mgs: %s", i.Name, err.Error())
}
}
@ -690,15 +688,11 @@ func (a *AppInstallService) GetParams(id uint) (*response.AppConfig, error) {
return &res, nil
}
func syncByID(installID uint) error {
appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(installID))
if err != nil {
return err
}
func syncAppInstallStatus(appInstall *model.AppInstall) error {
if appInstall.Status == constant.Installing {
return nil
}
containerNames, err := getContainerNames(appInstall)
containerNames, err := getContainerNames(*appInstall)
if err != nil {
return err
}
@ -710,72 +704,61 @@ func syncByID(installID uint) error {
if err != nil {
return err
}
var (
errorContainers []string
notFoundContainers []string
runningContainers []string
exitedContainers []string
runningCount int
exitedCount int
pausedCount int
exitedContainerNames []string
total = len(containerNames)
count = len(containers)
)
for _, n := range containers {
switch n.State {
foundNames := make(map[string]bool)
for _, con := range containers {
foundNames[con.Names[0]] = true
switch con.State {
case "exited":
exitedContainers = append(exitedContainers, n.Names[0])
exitedContainerNames = append(exitedContainerNames, strings.TrimPrefix(con.Names[0], "/"))
exitedCount++
case "running":
runningContainers = append(runningContainers, n.Names[0])
default:
errorContainers = append(errorContainers, n.Names[0])
runningCount++
case "paused":
pausedCount++
}
}
var notFoundNames []string
for _, name := range containerNames {
exist := false
for _, container := range containers {
if common.ExistWithStrArray(name, container.Names) {
exist = true
break
}
}
if !exist {
notFoundContainers = append(notFoundContainers, name)
if !foundNames["/"+name] {
notFoundNames = append(notFoundNames, name)
}
}
containerCount := len(containers)
errCount := len(errorContainers)
notFoundCount := len(notFoundContainers)
existedCount := len(exitedContainers)
normalCount := len(containerNames)
runningCount := len(runningContainers)
if containerCount == 0 {
switch {
case count == 0:
appInstall.Status = constant.Error
appInstall.Message = i18n.GetMsgWithMap("ErrContainerNotFound", map[string]interface{}{"name": strings.Join(containerNames, ",")})
return appInstallRepo.Save(context.Background(), &appInstall)
}
if errCount == 0 && existedCount == 0 && notFoundCount == 0 {
appInstall.Status = constant.Running
return appInstallRepo.Save(context.Background(), &appInstall)
}
if existedCount == normalCount {
appInstall.Message = buserr.WithName("ErrContainerNotFound", strings.Join(containerNames, ",")).Error()
case exitedCount == total:
appInstall.Status = constant.Stopped
return appInstallRepo.Save(context.Background(), &appInstall)
}
if errCount == normalCount {
appInstall.Status = constant.Error
}
if runningCount < normalCount {
case runningCount == total:
appInstall.Status = constant.Running
case pausedCount == total:
appInstall.Status = constant.Paused
default:
var msg string
if exitedCount > 0 {
msg = buserr.WithName("ErrContainerMsg", strings.Join(exitedContainerNames, ",")).Error()
}
if len(notFoundNames) > 0 {
msg += buserr.WithName("ErrContainerNotFound", strings.Join(notFoundNames, ",")).Error()
}
appInstall.Message = msg
appInstall.Status = constant.UnHealthy
}
_ = appInstallRepo.Save(context.Background(), appInstall)
var errMsg string
if errCount > 0 {
errMsg += i18n.GetMsgWithMap("ErrContainerMsg", map[string]interface{}{"name": strings.Join(errorContainers, ",")})
}
if notFoundCount > 0 {
errMsg += i18n.GetMsgWithMap("ErrContainerNotFound", map[string]interface{}{"name": strings.Join(notFoundContainers, ",")})
}
appInstall.Message = errMsg
return appInstallRepo.Save(context.Background(), &appInstall)
return nil
}
func updateInstallInfoInDB(appKey, appName, param string, isRestart bool, value interface{}) error {

View file

@ -1052,6 +1052,10 @@ func handleInstalled(appInstallList []model.AppInstall, updated bool) ([]respons
if updated && (installed.App.Type == "php" || installed.Status == constant.Installing || (installed.App.Key == constant.AppMysql && installed.Version == "5.6.51")) {
continue
}
if err := syncAppInstallStatus(&installed); err != nil {
global.LOG.Error("sync app install status error : ", err)
}
installDTO := response.AppInstalledDTO{
AppInstall: installed,
Path: installed.GetPath(),

View file

@ -820,30 +820,27 @@ func (w WebsiteService) PreInstallCheck(req request.WebsiteInstallCheckReq) ([]r
} else {
checkIds = append(req.InstallIds, appInstall.ID)
}
for _, id := range checkIds {
if err := syncByID(id); err != nil {
return nil, err
}
}
if len(checkIds) > 0 {
installList, _ := appInstallRepo.ListBy(commonRepo.WithIdsIn(checkIds))
for _, install := range installList {
if err = syncAppInstallStatus(&install); err != nil {
return nil, err
}
res = append(res, response.WebsitePreInstallCheck{
Name: install.Name,
Status: install.Status,
Version: install.Version,
AppName: install.App.Name,
})
if install.Status != constant.StatusRunning {
if install.Status != constant.Running {
showErr = true
}
}
}
if showErr {
return res, nil
} else {
return nil, nil
}
return nil, nil
}
func (w WebsiteService) GetWafConfig(req request.WebsiteWafReq) (response.WebsiteWafConfig, error) {

View file

@ -12,7 +12,7 @@ const (
Rebuilding = "Rebuilding"
Syncing = "Syncing"
SyncSuccess = "SyncSuccess"
SyncErr = "SyncErr"
Paused = "Paused"
ContainerPrefix = "1Panel-"

View file

@ -57,7 +57,6 @@ func (c Client) ListAllContainers() ([]types.Container, error) {
func (c Client) ListContainersByName(names []string) ([]types.Container, error) {
var (
options container.ListOptions
res []types.Container
)
options.All = true
if len(names) > 0 {
@ -71,12 +70,7 @@ func (c Client) ListContainersByName(names []string) ([]types.Container, error)
if err != nil {
return nil, err
}
for _, container := range containers {
if container.Names[0] == "/"+names[0] {
res = append(res, container)
}
}
return res, nil
return containers, nil
}
func (c Client) CreateNetwork(name string) error {

View file

@ -222,25 +222,32 @@
</el-button>
</div>
<div class="d-description">
<el-tag class="middle-center">
<el-button class="tagMargin" plain size="small">
{{ $t('app.version') }}{{ installed.version }}
</el-tag>
<el-tag
class="middle-center"
</el-button>
<el-button
v-if="installed.httpPort > 0"
@click="goDashboard(installed.httpPort, 'http')"
class="tagMargin"
icon="Position"
plain
size="small"
>
<el-icon class="middle-center"><Position /></el-icon>
{{ $t('app.busPort') }}{{ installed.httpPort }}
</el-tag>
<el-tag
class="middle-center"
</el-button>
<el-button
v-if="installed.httpsPort > 0"
@click="goDashboard(installed.httpsPort, 'https')"
class="tagMargin"
icon="Position"
plain
size="small"
>
<el-icon class="middle-center"><Position /></el-icon>
{{ $t('app.busPort') }}{{ installed.httpsPort }}
</el-tag>
</el-button>
<div class="description">
<span>
{{ $t('app.alreadyRun') }} {{ getAge(installed.createdAt) }}