1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-19 16:29:17 +08:00

feat: OpenResty 安装支持指定网站目录 (#6277)

This commit is contained in:
zhengkunwang 2024-08-28 17:48:16 +08:00 committed by GitHub
parent 6f1e5074ed
commit bc8a2511d1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 124 additions and 17 deletions

View File

@ -31,6 +31,19 @@ func (i *AppInstall) GetPath() string {
return path.Join(i.GetAppPath(), i.Name)
}
//func (i *AppInstall) GetSiteDir() string {
// var data map[string]interface{}
// err := json.Unmarshal([]byte(i.Env), &data)
// if err != nil {
// return path.Join(i.GetAppPath(), i.Name, "www")
// }
// websiteDir, ok := data["WEBSITE_DIR"].(string)
// if !ok || websiteDir == "" {
// return path.Join(i.GetAppPath(), i.Name, "www")
// }
// return websiteDir
//}
func (i *AppInstall) GetComposePath() string {
return path.Join(i.GetAppPath(), i.Name, "docker-compose.yml")
}

View File

@ -7,6 +7,7 @@ import (
"fmt"
"net/http"
"os"
"path"
"path/filepath"
"reflect"
"strconv"
@ -337,6 +338,16 @@ func (a AppService) Install(req request.AppInstallCreate) (appInstall *model.App
return
}
}
if app.Key == "openresty" && app.Resource == "remote" && common.CompareVersion(appDetail.Version, "1.21.4.3-3-3") {
if dir, ok := req.Params["WEBSITE_DIR"]; ok {
siteDir := dir.(string)
if siteDir == "" || !strings.HasPrefix(siteDir, "/") {
siteDir = path.Join(constant.DataDir, dir.(string))
}
req.Params["WEBSITE_DIR"] = siteDir
_ = settingRepo.Create("WEBSITE_DIR", siteDir)
}
}
for key := range req.Params {
if !strings.Contains(key, "PANEL_APP_PORT") {
continue

View File

@ -5,6 +5,8 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
"github.com/1Panel-dev/1Panel/agent/utils/nginx"
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
"log"
"math"
"net/http"
@ -346,12 +348,11 @@ func deleteAppInstall(deleteReq request.AppInstallDelete) error {
}
if deleteReq.DeleteImage {
delImageStr := i18n.GetMsgByKey("TaskDelete") + i18n.GetMsgByKey("Image")
projectName := strings.ToLower(install.Name)
content, err := op.GetContent(install.GetEnvPath())
if err != nil {
return err
}
images, err := composeV2.GetDockerComposeImages(projectName, content, []byte(install.DockerCompose))
images, err := composeV2.GetDockerComposeImagesV2(content, []byte(install.DockerCompose))
if err != nil {
return err
}
@ -448,7 +449,7 @@ func deleteAppInstall(deleteReq request.AppInstallDelete) error {
}
uninstallTask.AddSubTask(task.GetTaskName(install.Name, task.TaskUninstall, task.TaskScopeApp), uninstall, nil)
go func() {
if err := uninstallTask.Execute(); err != nil {
if err := uninstallTask.Execute(); err != nil && !deleteReq.ForceDelete {
install.Status = constant.Error
_ = appInstallRepo.Save(context.Background(), &install)
}
@ -615,8 +616,7 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
return err
}
if req.PullImage {
projectName := strings.ToLower(install.Name)
images, err := composeV2.GetDockerComposeImages(projectName, content, []byte(detail.DockerCompose))
images, err := composeV2.GetDockerComposeImagesV2(content, []byte(detail.DockerCompose))
if err != nil {
return err
}
@ -674,6 +674,51 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
}
envParams := make(map[string]string, len(envs))
handleMap(envs, envParams)
if install.App.Key == "openresty" && install.App.Resource == "remote" && !common.CompareVersion(install.Version, "1.25.3.2-0-1") {
t.Log(i18n.GetMsgByKey("MoveSiteDir"))
siteDir := path.Join(constant.DataDir, "www")
envParams["WEBSITE_DIR"] = siteDir
oldSiteDir := path.Join(install.GetPath(), "www")
t.Log(i18n.GetWithName("MoveSiteToDir", siteDir))
if err := fileOp.CopyDir(oldSiteDir, constant.DataDir); err != nil {
t.Log(i18n.GetMsgByKey("ErrMoveSiteDir"))
return err
}
newConfDir := path.Join(constant.DataDir, "www", "conf.d")
_ = fileOp.CreateDir(newConfDir, 0644)
oldConfDir := path.Join(install.GetPath(), "conf/conf.d")
items, err := os.ReadDir(oldConfDir)
if err != nil {
return err
}
for _, item := range items {
itemPath := path.Join(oldConfDir, item.Name())
if item.IsDir() {
_ = fileOp.Mv(itemPath, newConfDir)
}
if item.Name() != "default.conf" && item.Name() != "00.default.conf" {
_ = fileOp.Mv(itemPath, newConfDir)
}
}
nginxConfPath := path.Join(install.GetPath(), "conf", "nginx.conf")
parse, err := parser.NewParser(nginxConfPath)
if err != nil {
return err
}
config, err := parse.Parse()
if err != nil {
return err
}
config.FilePath = nginxConfPath
httpDirective := config.FindHttp()
httpDirective.UpdateDirective("include", []string{"/usr/local/openresty/nginx/conf/default/*.conf"})
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
return buserr.WithErr(constant.ErrUpdateBuWebsite, err)
}
t.Log(i18n.GetMsgByKey("MoveSiteDirSuccess"))
}
if err = env.Write(envParams, install.GetEnvPath()); err != nil {
return err
}
@ -719,7 +764,7 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
existInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(req.InstallID))
if existInstall.ID > 0 && existInstall.Status != constant.Running {
existInstall.Status = constant.UpgradeErr
existInstall.Message = upErr.Error()
existInstall.Message = err.Error()
_ = appInstallRepo.Save(context.Background(), &existInstall)
}
}

View File

@ -66,6 +66,10 @@ AppStoreIsLastVersion: "The app store is up to date"
AppStoreSyncSuccess: "App store synchronized successfully"
SyncAppDetail: "Synchronize app configuration"
AppVersionNotMatch: "{{ .name }} app requires an update to 1Panel, skipping synchronization"
MoveSiteDir: "The current upgrade requires migrating the OpenResty website directory"
MoveSiteToDir: "Migrate the website directory to {{ .name }}"
ErrMoveSiteDir: "Failed to migrate the website directory"
MoveSiteDirSuccess: "Successfully migrated the website directory"
#file

View File

@ -67,6 +67,10 @@ AppStoreIsLastVersion: "應用商店已經是最新版本"
AppStoreSyncSuccess: "應用商店同步成功"
SyncAppDetail: "同步應用配置"
AppVersionNotMatch: "{{ .name }} 應用需要更新 1Panel跳過同步"
MoveSiteDir: "當前升級需要遷移 OpenResty 網站目錄"
MoveSiteToDir: "遷移網站目錄到 {{ .name }}"
ErrMoveSiteDir: "遷移網站目錄失敗"
MoveSiteDirSuccess: "遷移網站目錄成功"
#file

View File

@ -65,7 +65,11 @@ UpgradeAppSuccess: "应用 {{ .name }} 升级成功"
AppStoreIsLastVersion: "应用商店已经是最新版本"
AppStoreSyncSuccess: "应用商店同步成功"
SyncAppDetail: "同步应用配置"
AppVersionNotMatch: "{{ .name }} 应用需要更新 1Panel跳过同步"
AppVersionNotMatch: "{{ .name }} 应用需要更高的 1Panel 版本,跳过同步"
MoveSiteDir: "当前升级需要迁移 OpenResty 网站目录"
MoveSiteToDir: "迁移网站目录到 {{ .name }}"
ErrMoveSiteDir: "迁移网站目录失败"
MoveSiteDirSuccess: "迁移网站目录成功"
#file
ErrFileCanNotRead: "此文件不支持预览"

View File

@ -16,7 +16,7 @@ import (
)
var AddTable = &gormigrate.Migration{
ID: "20240722-add-table",
ID: "20240826-add-table",
Migrate: func(tx *gorm.DB) error {
return tx.AutoMigrate(
&model.AppDetail{},

View File

@ -2,10 +2,12 @@ package docker
import (
"context"
"fmt"
"github.com/compose-spec/compose-go/v2/loader"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/compose/v2/pkg/api"
"github.com/joho/godotenv"
"gopkg.in/yaml.v3"
"path"
"regexp"
"strings"
@ -55,6 +57,34 @@ type Service struct {
Image string `yaml:"image"`
}
func replaceEnvVariables(input string, envVars map[string]string) string {
for key, value := range envVars {
placeholder := fmt.Sprintf("${%s}", key)
input = strings.ReplaceAll(input, placeholder, value)
}
return input
}
func GetDockerComposeImagesV2(env, yml []byte) ([]string, error) {
var (
compose ComposeProject
err error
images []string
)
err = yaml.Unmarshal(yml, &compose)
if err != nil {
return nil, err
}
envMap, err := godotenv.UnmarshalBytes(env)
if err != nil {
return nil, err
}
for _, service := range compose.Services {
image := replaceEnvVariables(service.Image, envMap)
images = append(images, image)
}
return images, nil
}
func GetDockerComposeImages(projectName string, env, yml []byte) ([]string, error) {
var (
configFiles []types.ConfigFile

View File

@ -25,7 +25,7 @@
{{ $t('commons.button.clean') }}
</el-button>
</div>
<LogPro v-model="logInfo" :heightDiff="400"></LogPro>
<LogPro v-model="logInfo" :heightDiff="400" />
</div>
</template>
@ -80,7 +80,7 @@ const searchLogs = async () => {
const protocol = href.split('//')[0] === 'http:' ? 'ws' : 'wss';
const host = href.split('//')[1].split('/')[0];
terminalSocket.value = new WebSocket(
`${protocol}://${host}/api/v1/containers/search/log?container=${logSearch.containerID}&since=${logSearch.mode}&tail=${logSearch.tail}&follow=${logSearch.isWatch}`,
`${protocol}://${host}/api/v2/containers/search/log?container=${logSearch.containerID}&since=${logSearch.mode}&tail=${logSearch.tail}&follow=${logSearch.isWatch}`,
);
terminalSocket.value.onmessage = (event) => {
logInfo.value += event.data;

View File

@ -65,7 +65,7 @@ const deleteReq = ref({
deleteBackup: false,
forceDelete: false,
deleteDB: true,
deleteImage: true,
deleteImage: false,
taskID: '',
});
const open = ref(false);
@ -91,7 +91,7 @@ const acceptParams = async (app: App.AppInstallDto) => {
deleteBackup: false,
forceDelete: false,
deleteDB: true,
deleteImage: true,
deleteImage: false,
taskID: uuidv4(),
};
deleteInfo.value = '';

View File

@ -204,7 +204,6 @@ const operate = async () => {
operateReq.taskID = taskID;
await InstalledOp(operateReq)
.then(() => {
MsgSuccess(i18n.global.t('app.upgradeStart'));
bus.emit('upgrade', true);
handleClose();
openTaskLog(taskID);

View File

@ -102,9 +102,6 @@
<el-button type="primary" @click="addReplaces">
{{ $t('website.addReplace') }}
</el-button>
<div>
<span class="input-help">{{ $t('website.replacementHelper') }}</span>
</div>
</el-form-item>
</el-form>
</el-col>

View File

@ -16,7 +16,7 @@
</template>
<template #main>
<Status v-if="activeName === '1'" :status="status" />
<Source v-if="activeName === '2'"></Source>
<Source v-if="activeName === '2'" />
<NginxPer v-if="activeName === '3'" />
<ContainerLog v-if="activeName === '4'" ref="dialogContainerLogRef" />
</template>