mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 14:08:06 +08:00
feat: 增加应用从OSS更新功能
This commit is contained in:
parent
226a81ecf3
commit
5f5a48041b
4
apps/apps.json
Normal file
4
apps/apps.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"version": "0.0.1",
|
||||
"package": ""
|
||||
}
|
@ -3,8 +3,7 @@ system:
|
||||
db_type: sqlite
|
||||
level: debug
|
||||
data_dir: /opt/1Panel/data
|
||||
resource_dir: /opt/1Panel/data/resource
|
||||
app_dir: /opt/1Panel/data/apps
|
||||
app_oss: "https://1panel.oss-cn-hangzhou.aliyuncs.com/apps.json"
|
||||
|
||||
mysql:
|
||||
path: localhost
|
||||
|
@ -24,49 +24,6 @@ type AppDetailDTO struct {
|
||||
Params interface{} `json:"params"`
|
||||
}
|
||||
|
||||
type AppList struct {
|
||||
Version string `json:"version"`
|
||||
Tags []Tag `json:"tags"`
|
||||
Items []AppDefine `json:"items"`
|
||||
}
|
||||
|
||||
type AppDefine struct {
|
||||
Key string `json:"key"`
|
||||
Name string `json:"name"`
|
||||
Tags []string `json:"tags"`
|
||||
Versions []string `json:"versions"`
|
||||
Icon string `json:"icon"`
|
||||
Author string `json:"author"`
|
||||
Source string `json:"source"`
|
||||
ShortDesc string `json:"short_desc"`
|
||||
Type string `json:"type"`
|
||||
Required []string `json:"Required"`
|
||||
CrossVersionUpdate bool `json:"crossVersionUpdate"`
|
||||
}
|
||||
|
||||
func (define AppDefine) GetRequired() string {
|
||||
by, _ := json.Marshal(define.Required)
|
||||
return string(by)
|
||||
}
|
||||
|
||||
type Tag struct {
|
||||
Key string `json:"key"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type AppForm struct {
|
||||
FormFields []AppFormFields `json:"form_fields"`
|
||||
}
|
||||
|
||||
type AppFormFields struct {
|
||||
Type string `json:"type"`
|
||||
LabelZh string `json:"label_zh"`
|
||||
LabelEn string `json:"label_en"`
|
||||
Required string `json:"required"`
|
||||
Default string `json:"default"`
|
||||
EnvKey string `json:"env_variable"`
|
||||
}
|
||||
|
||||
type AppRequest struct {
|
||||
PageInfo
|
||||
Name string `json:"name"`
|
||||
@ -143,7 +100,55 @@ type ContainerExec struct {
|
||||
Auth AuthParam `json:"auth"`
|
||||
}
|
||||
|
||||
type AppOssConfig struct {
|
||||
Version string `json:"version"`
|
||||
Package string `json:"package"`
|
||||
}
|
||||
|
||||
type AppVersion struct {
|
||||
Version string `json:"version"`
|
||||
DetailId uint `json:"detailId"`
|
||||
}
|
||||
|
||||
type AppList struct {
|
||||
Version string `json:"version"`
|
||||
Tags []Tag `json:"tags"`
|
||||
Items []AppDefine `json:"items"`
|
||||
}
|
||||
|
||||
type AppDefine struct {
|
||||
Key string `json:"key"`
|
||||
Name string `json:"name"`
|
||||
Tags []string `json:"tags"`
|
||||
Versions []string `json:"versions"`
|
||||
Icon string `json:"icon"`
|
||||
Author string `json:"author"`
|
||||
Source string `json:"source"`
|
||||
ShortDesc string `json:"short_desc"`
|
||||
Type string `json:"type"`
|
||||
Required []string `json:"Required"`
|
||||
CrossVersionUpdate bool `json:"crossVersionUpdate"`
|
||||
}
|
||||
|
||||
func (define AppDefine) GetRequired() string {
|
||||
by, _ := json.Marshal(define.Required)
|
||||
return string(by)
|
||||
}
|
||||
|
||||
type Tag struct {
|
||||
Key string `json:"key"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type AppForm struct {
|
||||
FormFields []AppFormFields `json:"form_fields"`
|
||||
}
|
||||
|
||||
type AppFormFields struct {
|
||||
Type string `json:"type"`
|
||||
LabelZh string `json:"label_zh"`
|
||||
LabelEn string `json:"label_en"`
|
||||
Required string `json:"required"`
|
||||
Default string `json:"default"`
|
||||
EnvKey string `json:"env_variable"`
|
||||
}
|
||||
|
@ -84,5 +84,5 @@ func (a AppInstallRepo) BatchUpdateBy(maps map[string]interface{}, opts ...DBOpt
|
||||
if len(opts) == 0 {
|
||||
db = db.Where("1=1")
|
||||
}
|
||||
return db.Updates(&maps).Error
|
||||
return db.Debug().Updates(&maps).Error
|
||||
}
|
||||
|
@ -444,7 +444,10 @@ func (a AppService) SyncInstalled(installId uint) error {
|
||||
}
|
||||
|
||||
func (a AppService) SyncAppList() error {
|
||||
//TODO 从 oss 拉取最新列表
|
||||
if err := getAppFromOss(); err != nil {
|
||||
global.LOG.Errorf("get app from oss error: %s", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
appDir := constant.AppResourceDir
|
||||
iconDir := path.Join(appDir, "icons")
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/app/model"
|
||||
"github.com/1Panel-dev/1Panel/constant"
|
||||
"github.com/1Panel-dev/1Panel/global"
|
||||
"github.com/1Panel-dev/1Panel/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/utils/compose"
|
||||
@ -14,7 +15,9 @@ import (
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/yaml.v3"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
@ -229,13 +232,9 @@ func restoreInstall(install model.AppInstall, backup model.AppInstallBackup) err
|
||||
if !fileOp.Stat(backupFile) {
|
||||
return errors.New(fmt.Sprintf("%s file is not exist", backup.Name))
|
||||
}
|
||||
backDir := installDir + "_back"
|
||||
if fileOp.Stat(backDir) {
|
||||
if err := fileOp.DeleteDir(backDir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := fileOp.Rename(installDir, backDir); err != nil {
|
||||
|
||||
backupDir, err := fileOp.Backup(installDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fileOp.Decompress(backupFile, installKeyDir, files.TarGz); err != nil {
|
||||
@ -280,7 +279,7 @@ func restoreInstall(install model.AppInstall, backup model.AppInstallBackup) err
|
||||
}
|
||||
|
||||
install.Param = backup.Param
|
||||
_ = fileOp.DeleteDir(backDir)
|
||||
_ = fileOp.DeleteDir(backupDir)
|
||||
if out, err := compose.Up(install.GetComposePath()); err != nil {
|
||||
return handleErr(install, err, out)
|
||||
}
|
||||
@ -456,3 +455,50 @@ func handleErr(install model.AppInstall, err error, out string) error {
|
||||
_ = appInstallRepo.Save(&install)
|
||||
return reErr
|
||||
}
|
||||
|
||||
func getAppFromOss() error {
|
||||
res, err := http.Get(global.CONF.System.AppOss)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
appByte, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var ossConfig dto.AppOssConfig
|
||||
if err := json.Unmarshal(appByte, &ossConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
appDir := constant.AppResourceDir
|
||||
oldListFile := path.Join(appDir, "list.json")
|
||||
content, err := os.ReadFile(oldListFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
list := &dto.AppList{}
|
||||
if err := json.Unmarshal(content, list); err != nil {
|
||||
return err
|
||||
}
|
||||
if list.Version == ossConfig.Version {
|
||||
return nil
|
||||
}
|
||||
|
||||
fileOp := files.NewFileOp()
|
||||
if _, err := fileOp.Backup(appDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
packageName := path.Base(ossConfig.Package)
|
||||
packagePath := path.Join(constant.ResourceDir, packageName)
|
||||
if err := fileOp.DownloadFile(ossConfig.Package, packagePath); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fileOp.Decompress(packagePath, constant.ResourceDir, files.Zip); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_ = fileOp.DeleteFile(packagePath)
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func (f FileService) ChangeName(re dto.FileRename) error {
|
||||
func (f FileService) Wget(w dto.FileWget) (string, error) {
|
||||
fo := files.NewFileOp()
|
||||
key := "file-wget-" + uuid.NewV4().String()
|
||||
return key, fo.DownloadFile(w.Url, filepath.Join(w.Path, w.Name), key)
|
||||
return key, fo.DownloadFileWithProcess(w.Url, filepath.Join(w.Path, w.Name), key)
|
||||
}
|
||||
|
||||
func (f FileService) MvFile(m dto.FileMove) error {
|
||||
|
@ -137,7 +137,7 @@ func (w *WriteCounter) SaveProcess() {
|
||||
|
||||
}
|
||||
|
||||
func (f FileOp) DownloadFile(url, dst, key string) error {
|
||||
func (f FileOp) DownloadFileWithProcess(url, dst, key string) error {
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("get download file [%s] error, err %s", dst, err.Error())
|
||||
@ -167,6 +167,26 @@ func (f FileOp) DownloadFile(url, dst, key string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f FileOp) DownloadFile(url, dst string) error {
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("get download file [%s] error, err %s", dst, err.Error())
|
||||
}
|
||||
|
||||
out, err := os.Create(dst)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("create download file [%s] error, err %s", dst, err.Error())
|
||||
}
|
||||
|
||||
if _, err = io.Copy(out, resp.Body); err != nil {
|
||||
global.LOG.Errorf("save download file [%s] error, err %s", dst, err.Error())
|
||||
}
|
||||
out.Close()
|
||||
resp.Body.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f FileOp) Cut(oldPaths []string, dst string) error {
|
||||
for _, p := range oldPaths {
|
||||
base := filepath.Base(p)
|
||||
@ -396,3 +416,19 @@ func (f FileOp) Decompress(srcFile string, dst string, cType CompressType) error
|
||||
}
|
||||
return format.Extract(context.Background(), input, nil, handler)
|
||||
}
|
||||
|
||||
func (f FileOp) Backup(srcFile string) (string, error) {
|
||||
backupPath := srcFile + "_bak"
|
||||
info, _ := f.Fs.Stat(backupPath)
|
||||
if info != nil {
|
||||
if info.IsDir() {
|
||||
f.DeleteDir(backupPath)
|
||||
} else {
|
||||
f.DeleteFile(backupPath)
|
||||
}
|
||||
}
|
||||
if err := f.Rename(srcFile, backupPath); err != nil {
|
||||
return backupPath, err
|
||||
}
|
||||
return backupPath, nil
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user