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:
parent
6f1e5074ed
commit
bc8a2511d1
@ -31,6 +31,19 @@ func (i *AppInstall) GetPath() string {
|
|||||||
return path.Join(i.GetAppPath(), i.Name)
|
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 {
|
func (i *AppInstall) GetComposePath() string {
|
||||||
return path.Join(i.GetAppPath(), i.Name, "docker-compose.yml")
|
return path.Join(i.GetAppPath(), i.Name, "docker-compose.yml")
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -337,6 +338,16 @@ func (a AppService) Install(req request.AppInstallCreate) (appInstall *model.App
|
|||||||
return
|
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 {
|
for key := range req.Params {
|
||||||
if !strings.Contains(key, "PANEL_APP_PORT") {
|
if !strings.Contains(key, "PANEL_APP_PORT") {
|
||||||
continue
|
continue
|
||||||
|
@ -5,6 +5,8 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/1Panel-dev/1Panel/agent/utils/nginx"
|
||||||
|
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
|
||||||
"log"
|
"log"
|
||||||
"math"
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -346,12 +348,11 @@ func deleteAppInstall(deleteReq request.AppInstallDelete) error {
|
|||||||
}
|
}
|
||||||
if deleteReq.DeleteImage {
|
if deleteReq.DeleteImage {
|
||||||
delImageStr := i18n.GetMsgByKey("TaskDelete") + i18n.GetMsgByKey("Image")
|
delImageStr := i18n.GetMsgByKey("TaskDelete") + i18n.GetMsgByKey("Image")
|
||||||
projectName := strings.ToLower(install.Name)
|
|
||||||
content, err := op.GetContent(install.GetEnvPath())
|
content, err := op.GetContent(install.GetEnvPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
images, err := composeV2.GetDockerComposeImages(projectName, content, []byte(install.DockerCompose))
|
images, err := composeV2.GetDockerComposeImagesV2(content, []byte(install.DockerCompose))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -448,7 +449,7 @@ func deleteAppInstall(deleteReq request.AppInstallDelete) error {
|
|||||||
}
|
}
|
||||||
uninstallTask.AddSubTask(task.GetTaskName(install.Name, task.TaskUninstall, task.TaskScopeApp), uninstall, nil)
|
uninstallTask.AddSubTask(task.GetTaskName(install.Name, task.TaskUninstall, task.TaskScopeApp), uninstall, nil)
|
||||||
go func() {
|
go func() {
|
||||||
if err := uninstallTask.Execute(); err != nil {
|
if err := uninstallTask.Execute(); err != nil && !deleteReq.ForceDelete {
|
||||||
install.Status = constant.Error
|
install.Status = constant.Error
|
||||||
_ = appInstallRepo.Save(context.Background(), &install)
|
_ = appInstallRepo.Save(context.Background(), &install)
|
||||||
}
|
}
|
||||||
@ -615,8 +616,7 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if req.PullImage {
|
if req.PullImage {
|
||||||
projectName := strings.ToLower(install.Name)
|
images, err := composeV2.GetDockerComposeImagesV2(content, []byte(detail.DockerCompose))
|
||||||
images, err := composeV2.GetDockerComposeImages(projectName, content, []byte(detail.DockerCompose))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -674,6 +674,51 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
|
|||||||
}
|
}
|
||||||
envParams := make(map[string]string, len(envs))
|
envParams := make(map[string]string, len(envs))
|
||||||
handleMap(envs, envParams)
|
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 {
|
if err = env.Write(envParams, install.GetEnvPath()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -719,7 +764,7 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
|
|||||||
existInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(req.InstallID))
|
existInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(req.InstallID))
|
||||||
if existInstall.ID > 0 && existInstall.Status != constant.Running {
|
if existInstall.ID > 0 && existInstall.Status != constant.Running {
|
||||||
existInstall.Status = constant.UpgradeErr
|
existInstall.Status = constant.UpgradeErr
|
||||||
existInstall.Message = upErr.Error()
|
existInstall.Message = err.Error()
|
||||||
_ = appInstallRepo.Save(context.Background(), &existInstall)
|
_ = appInstallRepo.Save(context.Background(), &existInstall)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,10 @@ AppStoreIsLastVersion: "The app store is up to date"
|
|||||||
AppStoreSyncSuccess: "App store synchronized successfully"
|
AppStoreSyncSuccess: "App store synchronized successfully"
|
||||||
SyncAppDetail: "Synchronize app configuration"
|
SyncAppDetail: "Synchronize app configuration"
|
||||||
AppVersionNotMatch: "{{ .name }} app requires an update to 1Panel, skipping synchronization"
|
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
|
#file
|
||||||
|
@ -67,6 +67,10 @@ AppStoreIsLastVersion: "應用商店已經是最新版本"
|
|||||||
AppStoreSyncSuccess: "應用商店同步成功"
|
AppStoreSyncSuccess: "應用商店同步成功"
|
||||||
SyncAppDetail: "同步應用配置"
|
SyncAppDetail: "同步應用配置"
|
||||||
AppVersionNotMatch: "{{ .name }} 應用需要更新 1Panel,跳過同步"
|
AppVersionNotMatch: "{{ .name }} 應用需要更新 1Panel,跳過同步"
|
||||||
|
MoveSiteDir: "當前升級需要遷移 OpenResty 網站目錄"
|
||||||
|
MoveSiteToDir: "遷移網站目錄到 {{ .name }}"
|
||||||
|
ErrMoveSiteDir: "遷移網站目錄失敗"
|
||||||
|
MoveSiteDirSuccess: "遷移網站目錄成功"
|
||||||
|
|
||||||
|
|
||||||
#file
|
#file
|
||||||
|
@ -65,7 +65,11 @@ UpgradeAppSuccess: "应用 {{ .name }} 升级成功"
|
|||||||
AppStoreIsLastVersion: "应用商店已经是最新版本"
|
AppStoreIsLastVersion: "应用商店已经是最新版本"
|
||||||
AppStoreSyncSuccess: "应用商店同步成功"
|
AppStoreSyncSuccess: "应用商店同步成功"
|
||||||
SyncAppDetail: "同步应用配置"
|
SyncAppDetail: "同步应用配置"
|
||||||
AppVersionNotMatch: "{{ .name }} 应用需要更新 1Panel,跳过同步"
|
AppVersionNotMatch: "{{ .name }} 应用需要更高的 1Panel 版本,跳过同步"
|
||||||
|
MoveSiteDir: "当前升级需要迁移 OpenResty 网站目录"
|
||||||
|
MoveSiteToDir: "迁移网站目录到 {{ .name }}"
|
||||||
|
ErrMoveSiteDir: "迁移网站目录失败"
|
||||||
|
MoveSiteDirSuccess: "迁移网站目录成功"
|
||||||
|
|
||||||
#file
|
#file
|
||||||
ErrFileCanNotRead: "此文件不支持预览"
|
ErrFileCanNotRead: "此文件不支持预览"
|
||||||
|
@ -16,7 +16,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var AddTable = &gormigrate.Migration{
|
var AddTable = &gormigrate.Migration{
|
||||||
ID: "20240722-add-table",
|
ID: "20240826-add-table",
|
||||||
Migrate: func(tx *gorm.DB) error {
|
Migrate: func(tx *gorm.DB) error {
|
||||||
return tx.AutoMigrate(
|
return tx.AutoMigrate(
|
||||||
&model.AppDetail{},
|
&model.AppDetail{},
|
||||||
|
@ -2,10 +2,12 @@ package docker
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"github.com/compose-spec/compose-go/v2/loader"
|
"github.com/compose-spec/compose-go/v2/loader"
|
||||||
"github.com/compose-spec/compose-go/v2/types"
|
"github.com/compose-spec/compose-go/v2/types"
|
||||||
"github.com/docker/compose/v2/pkg/api"
|
"github.com/docker/compose/v2/pkg/api"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
"path"
|
"path"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
@ -55,6 +57,34 @@ type Service struct {
|
|||||||
Image string `yaml:"image"`
|
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) {
|
func GetDockerComposeImages(projectName string, env, yml []byte) ([]string, error) {
|
||||||
var (
|
var (
|
||||||
configFiles []types.ConfigFile
|
configFiles []types.ConfigFile
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
{{ $t('commons.button.clean') }}
|
{{ $t('commons.button.clean') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<LogPro v-model="logInfo" :heightDiff="400"></LogPro>
|
<LogPro v-model="logInfo" :heightDiff="400" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ const searchLogs = async () => {
|
|||||||
const protocol = href.split('//')[0] === 'http:' ? 'ws' : 'wss';
|
const protocol = href.split('//')[0] === 'http:' ? 'ws' : 'wss';
|
||||||
const host = href.split('//')[1].split('/')[0];
|
const host = href.split('//')[1].split('/')[0];
|
||||||
terminalSocket.value = new WebSocket(
|
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) => {
|
terminalSocket.value.onmessage = (event) => {
|
||||||
logInfo.value += event.data;
|
logInfo.value += event.data;
|
||||||
|
@ -65,7 +65,7 @@ const deleteReq = ref({
|
|||||||
deleteBackup: false,
|
deleteBackup: false,
|
||||||
forceDelete: false,
|
forceDelete: false,
|
||||||
deleteDB: true,
|
deleteDB: true,
|
||||||
deleteImage: true,
|
deleteImage: false,
|
||||||
taskID: '',
|
taskID: '',
|
||||||
});
|
});
|
||||||
const open = ref(false);
|
const open = ref(false);
|
||||||
@ -91,7 +91,7 @@ const acceptParams = async (app: App.AppInstallDto) => {
|
|||||||
deleteBackup: false,
|
deleteBackup: false,
|
||||||
forceDelete: false,
|
forceDelete: false,
|
||||||
deleteDB: true,
|
deleteDB: true,
|
||||||
deleteImage: true,
|
deleteImage: false,
|
||||||
taskID: uuidv4(),
|
taskID: uuidv4(),
|
||||||
};
|
};
|
||||||
deleteInfo.value = '';
|
deleteInfo.value = '';
|
||||||
|
@ -204,7 +204,6 @@ const operate = async () => {
|
|||||||
operateReq.taskID = taskID;
|
operateReq.taskID = taskID;
|
||||||
await InstalledOp(operateReq)
|
await InstalledOp(operateReq)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
MsgSuccess(i18n.global.t('app.upgradeStart'));
|
|
||||||
bus.emit('upgrade', true);
|
bus.emit('upgrade', true);
|
||||||
handleClose();
|
handleClose();
|
||||||
openTaskLog(taskID);
|
openTaskLog(taskID);
|
||||||
|
@ -102,9 +102,6 @@
|
|||||||
<el-button type="primary" @click="addReplaces">
|
<el-button type="primary" @click="addReplaces">
|
||||||
{{ $t('website.addReplace') }}
|
{{ $t('website.addReplace') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<div>
|
|
||||||
<span class="input-help">{{ $t('website.replacementHelper') }}</span>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #main>
|
<template #main>
|
||||||
<Status v-if="activeName === '1'" :status="status" />
|
<Status v-if="activeName === '1'" :status="status" />
|
||||||
<Source v-if="activeName === '2'"></Source>
|
<Source v-if="activeName === '2'" />
|
||||||
<NginxPer v-if="activeName === '3'" />
|
<NginxPer v-if="activeName === '3'" />
|
||||||
<ContainerLog v-if="activeName === '4'" ref="dialogContainerLogRef" />
|
<ContainerLog v-if="activeName === '4'" ref="dialogContainerLogRef" />
|
||||||
</template>
|
</template>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user