1Panel/backend/app/service/app_utils.go

200 lines
5.2 KiB
Go
Raw Normal View History

package service
import (
"encoding/json"
"fmt"
"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/compose"
"github.com/1Panel-dev/1Panel/utils/files"
"github.com/joho/godotenv"
2022-10-10 22:56:42 +08:00
"github.com/pkg/errors"
"path"
"strconv"
)
type DatabaseOp string
var (
Add DatabaseOp = "add"
Delete DatabaseOp = "delete"
)
func execDockerCommand(database model.Database, container model.AppContainer, op DatabaseOp) error {
var auth dto.AuthParam
var dbConfig dto.AppDatabase
dbConfig.Password = database.Password
dbConfig.DbUser = database.Username
dbConfig.DbName = database.Dbname
json.Unmarshal([]byte(container.Auth), &auth)
execConfig := dto.ContainerExec{
ContainerName: container.ContainerName,
Auth: auth,
DbParam: dbConfig,
}
_, err := cmd.Exec(getSqlStr(database.Key, op, execConfig))
if err != nil {
return err
}
return nil
}
func getSqlStr(key string, operate DatabaseOp, exec dto.ContainerExec) string {
var str string
param := exec.DbParam
switch key {
case "mysql":
if operate == Add {
str = fmt.Sprintf("docker exec -i %s mysql -uroot -p%s -e \"CREATE USER '%s'@'%%' IDENTIFIED BY '%s';\" -e \"create database %s;\" -e \"GRANT ALL ON %s.* TO '%s'@'%%';\"",
exec.ContainerName, exec.Auth.RootPassword, param.DbUser, param.Password, param.DbName, param.DbName, param.DbUser)
}
if operate == Delete {
str = fmt.Sprintf("docker exec -i %s mysql -uroot -p%s -e \"drop database %s;\" -e \"drop user %s;\" ",
exec.ContainerName, exec.Auth.RootPassword, param.DbName, param.DbUser)
}
}
return str
}
2022-10-10 22:56:42 +08:00
func checkRequiredAndLimit(app model.App) error {
if app.Limit > 0 {
installs, err := appInstallRepo.GetBy(appInstallRepo.WithAppId(app.ID))
if err != nil {
return err
}
if len(installs) >= app.Limit {
return errors.New(fmt.Sprintf("app install limit %d", app.Limit))
}
}
if app.Required != "" {
var requiredArray []string
if err := json.Unmarshal([]byte(app.Required), &requiredArray); err != nil {
return err
}
for _, key := range requiredArray {
if key == "" {
continue
}
requireApp, err := appRepo.GetFirst(appRepo.WithKey(key))
if err != nil {
return err
}
details, err := appDetailRepo.GetBy(appDetailRepo.WithAppId(requireApp.ID))
if err != nil {
return err
}
var detailIds []uint
for _, d := range details {
detailIds = append(detailIds, d.ID)
}
_, err = appInstallRepo.GetFirst(appInstallRepo.WithDetailIdsIn(detailIds))
if err != nil {
return errors.New(fmt.Sprintf("%s is required", requireApp.Key))
}
}
}
return nil
}
func copyAppData(key, version, installName string, params map[string]interface{}) (composeFilePath string, err error) {
resourceDir := path.Join(global.CONF.System.ResourceDir, "apps", key, version)
installDir := path.Join(global.CONF.System.AppDir, key)
installVersionDir := path.Join(installDir, version)
fileOp := files.NewFileOp()
if err = fileOp.Copy(resourceDir, installVersionDir); err != nil {
return
}
appDir := path.Join(installDir, installName)
if err = fileOp.Rename(installVersionDir, appDir); err != nil {
return
}
composeFilePath = path.Join(appDir, "docker-compose.yml")
envPath := path.Join(appDir, ".env")
envParams := make(map[string]string, len(params))
for k, v := range params {
switch t := v.(type) {
case string:
envParams[k] = t
case float64:
envParams[k] = strconv.FormatFloat(t, 'f', -1, 32)
default:
envParams[k] = t.(string)
}
}
if err = godotenv.Write(envParams, envPath); err != nil {
return
}
return
}
func upApp(composeFilePath string, appInstall model.AppInstall) {
out, err := compose.Up(composeFilePath)
if err != nil {
if out != "" {
appInstall.Message = out
} else {
appInstall.Message = err.Error()
}
appInstall.Status = constant.Error
_ = appInstallRepo.Save(appInstall)
} else {
appInstall.Status = constant.Running
_ = appInstallRepo.Save(appInstall)
}
}
func getAppDetails(details []model.AppDetail, versions []string) map[string]model.AppDetail {
appDetails := make(map[string]model.AppDetail, len(details))
for _, old := range details {
old.Status = constant.AppTakeDown
appDetails[old.Version] = old
}
for _, v := range versions {
detail, ok := appDetails[v]
if ok {
detail.Status = constant.AppNormal
appDetails[v] = detail
} else {
appDetails[v] = model.AppDetail{
Version: v,
Status: constant.AppNormal,
}
}
}
return appDetails
}
func getApps(oldApps []model.App, items []dto.AppDefine) map[string]model.App {
apps := make(map[string]model.App, len(oldApps))
for _, old := range oldApps {
old.Status = constant.AppTakeDown
apps[old.Key] = old
}
for _, item := range items {
app, ok := apps[item.Key]
if !ok {
app = model.App{}
}
app.Name = item.Name
app.Key = item.Key
app.ShortDesc = item.ShortDesc
app.Author = item.Author
app.Source = item.Source
app.Type = item.Type
app.CrossVersionUpdate = item.CrossVersionUpdate
app.Required = item.GetRequired()
app.Status = constant.AppNormal
apps[item.Key] = app
}
return apps
}