diff --git a/backend/app/service/app.go b/backend/app/service/app.go index 643b0ab4a..9aff52eb7 100644 --- a/backend/app/service/app.go +++ b/backend/app/service/app.go @@ -13,6 +13,7 @@ import ( "github.com/1Panel-dev/1Panel/backend/buserr" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/global" + "github.com/1Panel-dev/1Panel/backend/i18n" "github.com/1Panel-dev/1Panel/backend/utils/common" "github.com/1Panel-dev/1Panel/backend/utils/docker" "github.com/1Panel-dev/1Panel/backend/utils/files" @@ -383,44 +384,11 @@ func (a AppService) SyncAppListFromLocal() { if dirEntry.IsDir() { appDir := path.Join(localAppDir, dirEntry.Name()) appDirEntries, err := os.ReadDir(appDir) - if err != nil || len(appDirEntries) == 0 { - continue - } - configYamlPath := path.Join(appDir, "data.yml") - if !fileOp.Stat(configYamlPath) { - continue - } - iconPath := path.Join(appDir, "logo.png") - if !fileOp.Stat(iconPath) { - continue - } - configYamlByte, err := fileOp.GetContent(configYamlPath) + app, err := handleLocalApp(localAppDir) if err != nil { + global.LOG.Errorf(i18n.GetMsgWithMap("LocalAppErr", map[string]interface{}{"name": app.Name, "err": err.Error()})) continue } - localAppDefine := dto.LocalAppAppDefine{} - if err := yaml.Unmarshal(configYamlByte, &localAppDefine); err != nil { - continue - } - app := localAppDefine.AppProperty - app.Resource = constant.AppResourceLocal - app.Status = constant.AppNormal - app.Recommend = 9999 - app.TagsKey = append(app.TagsKey, "Local") - app.Key = "local" + app.Key - readMePath := path.Join(appDir, "README.md") - if fileOp.Stat(configYamlPath) { - readMeByte, err := fileOp.GetContent(readMePath) - if err == nil { - app.ReadMe = string(readMeByte) - } - } - - iconByte, _ := fileOp.GetContent(iconPath) - if iconByte != nil { - iconStr := base64.StdEncoding.EncodeToString(iconByte) - app.Icon = iconStr - } var appDetails []model.AppDetail for _, appDirEntry := range appDirEntries { if appDirEntry.IsDir() { @@ -429,37 +397,19 @@ func (a AppService) SyncAppListFromLocal() { Status: constant.AppNormal, } versionDir := path.Join(appDir, appDirEntry.Name()) - dockerComposePath := path.Join(versionDir, "docker-compose.yml") - if !fileOp.Stat(dockerComposePath) { + if err = handleLocalAppDetail(versionDir, &appDetail); err != nil { + global.LOG.Errorf(i18n.GetMsgWithMap("LocalAppVersionErr", map[string]interface{}{"name": app.Name, "version": appDetail.Version, "err": err.Error()})) continue } - dockerComposeByte, _ := fileOp.GetContent(dockerComposePath) - if dockerComposeByte == nil { - continue - } - appDetail.DockerCompose = string(dockerComposeByte) - paramPath := path.Join(versionDir, "data.yml") - if !fileOp.Stat(paramPath) { - continue - } - paramByte, _ := fileOp.GetContent(paramPath) - if paramByte == nil { - continue - } - appParamConfig := dto.LocalAppParam{} - if err := yaml.Unmarshal(paramByte, &appParamConfig); err != nil { - continue - } - dataJson, err := json.Marshal(appParamConfig.AppParams) - if err != nil { - continue - } - appDetail.Params = string(dataJson) appDetails = append(appDetails, appDetail) } } - app.Details = appDetails - localApps = append(localApps, app) + if len(appDetails) > 0 { + app.Details = appDetails + localApps = append(localApps, *app) + } else { + global.LOG.Errorf(i18n.GetMsgWithMap("LocalAppVersionNull", map[string]interface{}{"name": app.Name})) + } } } diff --git a/backend/app/service/app_utils.go b/backend/app/service/app_utils.go index 16ec590ed..93db05a08 100644 --- a/backend/app/service/app_utils.go +++ b/backend/app/service/app_utils.go @@ -2,10 +2,12 @@ package service import ( "context" + "encoding/base64" "encoding/json" "fmt" "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" "github.com/1Panel-dev/1Panel/backend/app/dto/request" + "github.com/1Panel-dev/1Panel/backend/i18n" "github.com/compose-spec/compose-go/types" "github.com/subosito/gotenv" "gopkg.in/yaml.v3" @@ -628,6 +630,83 @@ func getApps(oldApps []model.App, items []dto.AppDefine) map[string]model.App { return apps } +func handleLocalAppDetail(versionDir string, appDetail *model.AppDetail) error { + fileOp := files.NewFileOp() + dockerComposePath := path.Join(versionDir, "docker-compose.yml") + if !fileOp.Stat(dockerComposePath) { + return errors.New(i18n.GetMsgWithMap("ErrFileNotFound", map[string]interface{}{"name": "docker-compose.yml"})) + } + dockerComposeByte, _ := fileOp.GetContent(dockerComposePath) + if dockerComposeByte == nil { + return errors.New(i18n.GetMsgWithMap("ErrFileParseApp", map[string]interface{}{"name": "docker-compose.yml"})) + } + appDetail.DockerCompose = string(dockerComposeByte) + paramPath := path.Join(versionDir, "data.yml") + if !fileOp.Stat(paramPath) { + return errors.New(i18n.GetMsgWithMap("ErrFileNotFound", map[string]interface{}{"name": "data.yml"})) + } + paramByte, _ := fileOp.GetContent(paramPath) + if paramByte == nil { + return errors.New(i18n.GetMsgWithMap("ErrFileParseApp", map[string]interface{}{"name": "data.yml"})) + } + appParamConfig := dto.LocalAppParam{} + if err := yaml.Unmarshal(paramByte, &appParamConfig); err != nil { + return errors.New(i18n.GetMsgWithMap("ErrFileParseApp", map[string]interface{}{"name": "data.yml"})) + } + dataJson, err := json.Marshal(appParamConfig.AppParams) + if err != nil { + return errors.New(i18n.GetMsgWithMap("ErrFileParseApp", map[string]interface{}{"name": "data.yml", "err": err.Error()})) + } + appDetail.Params = string(dataJson) + return nil +} + +func handleLocalApp(appDir string) (app *model.App, err error) { + fileOp := files.NewFileOp() + appDirEntries, err := os.ReadDir(appDir) + if err != nil || len(appDirEntries) == 0 { + err = errors.New("ErrAppDirNull") + return + } + configYamlPath := path.Join(appDir, "data.yml") + if !fileOp.Stat(configYamlPath) { + err = errors.New(i18n.GetMsgWithMap("ErrFileNotFound", map[string]interface{}{"name": "data.yml"})) + return + } + iconPath := path.Join(appDir, "logo.png") + if !fileOp.Stat(iconPath) { + err = errors.New(i18n.GetMsgWithMap("ErrFileNotFound", map[string]interface{}{"name": "logo.png"})) + return + } + configYamlByte, err := fileOp.GetContent(configYamlPath) + if err != nil { + err = errors.New(i18n.GetMsgWithMap("ErrFileParseApp", map[string]interface{}{"name": "data.yml", "err": err.Error()})) + return + } + localAppDefine := dto.LocalAppAppDefine{} + if err = yaml.Unmarshal(configYamlByte, &localAppDefine); err != nil { + err = errors.New(i18n.GetMsgWithMap("ErrFileParseApp", map[string]interface{}{"name": "data.yml", "err": err.Error()})) + return + } + app = &localAppDefine.AppProperty + app.Resource = constant.AppResourceLocal + app.Status = constant.AppNormal + app.Recommend = 9999 + app.TagsKey = append(app.TagsKey, "Local") + app.Key = "local" + app.Key + readMePath := path.Join(appDir, "README.md") + readMeByte, err := fileOp.GetContent(readMePath) + if err == nil { + app.ReadMe = string(readMeByte) + } + iconByte, _ := fileOp.GetContent(iconPath) + if iconByte != nil { + iconStr := base64.StdEncoding.EncodeToString(iconByte) + app.Icon = iconStr + } + return +} + func handleErr(install model.AppInstall, err error, out string) error { reErr := err install.Message = err.Error() diff --git a/backend/i18n/lang/en.yaml b/backend/i18n/lang/en.yaml index d94865a78..0635281a6 100644 --- a/backend/i18n/lang/en.yaml +++ b/backend/i18n/lang/en.yaml @@ -31,6 +31,12 @@ Err1PanelNetworkFailed: 'Default container network creation failed! {{ .detail } ErrFileParse: 'Application docker-compose file parsing failed!' ErrInstallDirNotFound: 'installation directory does not exist' AppStoreIsUpToDate: 'The app store is already up to date!' +LocalAppVersionNull: 'The {{.name}} app is not synced to version! Could not add to application list' +LocalAppVersionErr: '{{.name}} failed to sync version {{.version}}! {{.err}}' +ErrFileNotFound: '{{.name}} file does not exist' +ErrFileParseApp: 'Failed to parse {{.name}} file {{.err}}' +ErrAppDirNull: 'version folder does not exist' +LocalAppErr: "App {{.name}} sync failed! {{.err}}" #file ErrFileCanNotRead: "File can not read" diff --git a/backend/i18n/lang/zh.yaml b/backend/i18n/lang/zh.yaml index be0dfa585..7c91af7ed 100644 --- a/backend/i18n/lang/zh.yaml +++ b/backend/i18n/lang/zh.yaml @@ -31,6 +31,12 @@ Err1PanelNetworkFailed: '默认容器网络创建失败!{{ .detail }}' ErrFileParse: '应用 docker-compose 文件解析失败!' ErrInstallDirNotFound: '安装目录不存在' AppStoreIsUpToDate: '应用商店已经是最新版本' +LocalAppVersionNull: '{{.name}} 应用未同步到版本!无法添加到应用列表' +LocalAppVersionErr: '{{.name}} 同步版本 {{.version}} 失败!{{.err}}' +ErrFileNotFound: '{{.name}} 文件不存在' +ErrFileParseApp: '{{.name}} 文件解析失败 {{.err}}' +ErrAppDirNull: '版本文件夹不存在' +LocalAppErr: "应用 {{.name}} 同步失败!{{.err}}" #file ErrFileCanNotRead: "此文件不支持预览"