mirror of https://github.com/1Panel-dev/1Panel
feat: 本地应用同步增加日志 (#1203)
parent
c743775a1e
commit
0fa11213bb
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||||
"github.com/1Panel-dev/1Panel/backend/global"
|
"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/common"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/docker"
|
"github.com/1Panel-dev/1Panel/backend/utils/docker"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||||
|
@ -383,44 +384,11 @@ func (a AppService) SyncAppListFromLocal() {
|
||||||
if dirEntry.IsDir() {
|
if dirEntry.IsDir() {
|
||||||
appDir := path.Join(localAppDir, dirEntry.Name())
|
appDir := path.Join(localAppDir, dirEntry.Name())
|
||||||
appDirEntries, err := os.ReadDir(appDir)
|
appDirEntries, err := os.ReadDir(appDir)
|
||||||
if err != nil || len(appDirEntries) == 0 {
|
app, err := handleLocalApp(localAppDir)
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
global.LOG.Errorf(i18n.GetMsgWithMap("LocalAppErr", map[string]interface{}{"name": app.Name, "err": err.Error()}))
|
||||||
continue
|
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
|
var appDetails []model.AppDetail
|
||||||
for _, appDirEntry := range appDirEntries {
|
for _, appDirEntry := range appDirEntries {
|
||||||
if appDirEntry.IsDir() {
|
if appDirEntry.IsDir() {
|
||||||
|
@ -429,37 +397,19 @@ func (a AppService) SyncAppListFromLocal() {
|
||||||
Status: constant.AppNormal,
|
Status: constant.AppNormal,
|
||||||
}
|
}
|
||||||
versionDir := path.Join(appDir, appDirEntry.Name())
|
versionDir := path.Join(appDir, appDirEntry.Name())
|
||||||
dockerComposePath := path.Join(versionDir, "docker-compose.yml")
|
if err = handleLocalAppDetail(versionDir, &appDetail); err != nil {
|
||||||
if !fileOp.Stat(dockerComposePath) {
|
global.LOG.Errorf(i18n.GetMsgWithMap("LocalAppVersionErr", map[string]interface{}{"name": app.Name, "version": appDetail.Version, "err": err.Error()}))
|
||||||
continue
|
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)
|
appDetails = append(appDetails, appDetail)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app.Details = appDetails
|
if len(appDetails) > 0 {
|
||||||
localApps = append(localApps, app)
|
app.Details = appDetails
|
||||||
|
localApps = append(localApps, *app)
|
||||||
|
} else {
|
||||||
|
global.LOG.Errorf(i18n.GetMsgWithMap("LocalAppVersionNull", map[string]interface{}{"name": app.Name}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,12 @@ package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
"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/app/dto/request"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/i18n"
|
||||||
"github.com/compose-spec/compose-go/types"
|
"github.com/compose-spec/compose-go/types"
|
||||||
"github.com/subosito/gotenv"
|
"github.com/subosito/gotenv"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
@ -628,6 +630,83 @@ func getApps(oldApps []model.App, items []dto.AppDefine) map[string]model.App {
|
||||||
return apps
|
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 {
|
func handleErr(install model.AppInstall, err error, out string) error {
|
||||||
reErr := err
|
reErr := err
|
||||||
install.Message = err.Error()
|
install.Message = err.Error()
|
||||||
|
|
|
@ -31,6 +31,12 @@ Err1PanelNetworkFailed: 'Default container network creation failed! {{ .detail }
|
||||||
ErrFileParse: 'Application docker-compose file parsing failed!'
|
ErrFileParse: 'Application docker-compose file parsing failed!'
|
||||||
ErrInstallDirNotFound: 'installation directory does not exist'
|
ErrInstallDirNotFound: 'installation directory does not exist'
|
||||||
AppStoreIsUpToDate: 'The app store is already up to date!'
|
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
|
#file
|
||||||
ErrFileCanNotRead: "File can not read"
|
ErrFileCanNotRead: "File can not read"
|
||||||
|
|
|
@ -31,6 +31,12 @@ Err1PanelNetworkFailed: '默认容器网络创建失败!{{ .detail }}'
|
||||||
ErrFileParse: '应用 docker-compose 文件解析失败!'
|
ErrFileParse: '应用 docker-compose 文件解析失败!'
|
||||||
ErrInstallDirNotFound: '安装目录不存在'
|
ErrInstallDirNotFound: '安装目录不存在'
|
||||||
AppStoreIsUpToDate: '应用商店已经是最新版本'
|
AppStoreIsUpToDate: '应用商店已经是最新版本'
|
||||||
|
LocalAppVersionNull: '{{.name}} 应用未同步到版本!无法添加到应用列表'
|
||||||
|
LocalAppVersionErr: '{{.name}} 同步版本 {{.version}} 失败!{{.err}}'
|
||||||
|
ErrFileNotFound: '{{.name}} 文件不存在'
|
||||||
|
ErrFileParseApp: '{{.name}} 文件解析失败 {{.err}}'
|
||||||
|
ErrAppDirNull: '版本文件夹不存在'
|
||||||
|
LocalAppErr: "应用 {{.name}} 同步失败!{{.err}}"
|
||||||
|
|
||||||
#file
|
#file
|
||||||
ErrFileCanNotRead: "此文件不支持预览"
|
ErrFileCanNotRead: "此文件不支持预览"
|
||||||
|
|
Loading…
Reference in New Issue