From 88961e4ab7c916d06efb544953842afbf4c1ad16 Mon Sep 17 00:00:00 2001 From: zhengkunwang <31820853+zhengkunwang223@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:20:15 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E9=9D=99=E6=80=81?= =?UTF-8?q?=E7=BD=91=E7=AB=99=E5=92=8C=20PHP=20=E8=BF=90=E8=A1=8C=E7=8E=AF?= =?UTF-8?q?=E5=A2=83=E7=BD=91=E7=AB=99=E4=BA=92=E7=9B=B8=E5=88=87=E6=8D=A2?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=20(#6452)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs https://github.com/1Panel-dev/1Panel/issues/2532 --- agent/app/dto/request/website.go | 5 +- agent/app/dto/response/website.go | 1 + agent/app/service/website.go | 149 ++++++------------ agent/router/ro_website.go | 2 + frontend/src/api/interface/website.ts | 1 - frontend/src/lang/modules/en.ts | 4 +- frontend/src/lang/modules/tw.ts | 3 +- frontend/src/lang/modules/zh.ts | 3 +- .../website/website/config/basic/index.vue | 18 ++- .../website/config/basic/other/index.vue | 1 - .../website/config/basic/php/index.vue | 91 +++++++++++ .../views/website/website/config/index.vue | 15 +- .../website/website/config/resource/index.vue | 2 - 13 files changed, 171 insertions(+), 124 deletions(-) create mode 100644 frontend/src/views/website/website/config/basic/php/index.vue diff --git a/agent/app/dto/request/website.go b/agent/app/dto/request/website.go index 2ed599cd3..2ca39e31b 100644 --- a/agent/app/dto/request/website.go +++ b/agent/app/dto/request/website.go @@ -182,9 +182,8 @@ type WebsiteDefaultUpdate struct { } type WebsitePHPVersionReq struct { - WebsiteID uint `json:"websiteID" validate:"required"` - RuntimeID uint `json:"runtimeID" validate:"required"` - RetainConfig bool `json:"retainConfig" ` + WebsiteID uint `json:"websiteID" validate:"required"` + RuntimeID uint `json:"runtimeID"` } type WebsiteUpdateDir struct { diff --git a/agent/app/dto/response/website.go b/agent/app/dto/response/website.go index e2cf2d87c..89a6a33d5 100644 --- a/agent/app/dto/response/website.go +++ b/agent/app/dto/response/website.go @@ -13,6 +13,7 @@ type WebsiteDTO struct { SitePath string `json:"sitePath"` AppName string `json:"appName"` RuntimeName string `json:"runtimeName"` + RuntimeType string `json:"runtimeType"` SiteDir string `json:"siteDir"` } diff --git a/agent/app/service/website.go b/agent/app/service/website.go index a443259e3..c905021e8 100644 --- a/agent/app/service/website.go +++ b/agent/app/service/website.go @@ -27,9 +27,6 @@ import ( "github.com/1Panel-dev/1Panel/agent/i18n" "github.com/spf13/afero" - "github.com/1Panel-dev/1Panel/agent/utils/compose" - "github.com/1Panel-dev/1Panel/agent/utils/env" - "github.com/1Panel-dev/1Panel/agent/app/api/v2/helper" "github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/dto/request" @@ -532,13 +529,18 @@ func (w WebsiteService) GetWebsite(id uint) (response.WebsiteDTO, error) { return res, err } res.Website = website - - sitePath := GetSitePath(website, SiteDir) - res.ErrorLogPath = GetSitePath(website, SiteErrorLog) res.AccessLogPath = GetSitePath(website, SiteAccessLog) - res.SitePath = sitePath + res.SitePath = GetSitePath(website, SiteDir) res.SiteDir = website.SiteDir + if website.Type == constant.Runtime { + runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID)) + if err != nil { + return res, err + } + res.RuntimeType = runtime.Type + res.RuntimeName = runtime.Name + } return res, nil } @@ -1319,108 +1321,61 @@ func (w WebsiteService) ChangePHPVersion(req request.WebsitePHPVersionReq) error if err != nil { return err } - runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(req.RuntimeID)) + if website.Type == constant.Runtime { + oldRuntime, err := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID)) + if err != nil { + return err + } + if oldRuntime.Resource == constant.ResourceLocal { + return buserr.New("ErrPHPResource") + } + } + configPath := GetSitePath(website, SiteConf) + nginxContent, err := files.NewFileOp().GetContent(configPath) if err != nil { return err } - oldRuntime, err := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID)) + config, err := parser.NewStringParser(string(nginxContent)).Parse() if err != nil { return err } - if runtime.Resource == constant.ResourceLocal || oldRuntime.Resource == constant.ResourceLocal { - return buserr.New("ErrPHPResource") + servers := config.FindServers() + if len(servers) == 0 { + return errors.New("nginx config is not valid") } - appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) + server := servers[0] + + if req.RuntimeID > 0 { + runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(req.RuntimeID)) + if err != nil { + return err + } + if runtime.Resource == constant.ResourceLocal { + return buserr.New("ErrPHPResource") + } + website.RuntimeID = req.RuntimeID + phpProxy := fmt.Sprintf("127.0.0.1:%d", runtime.Port) + website.Proxy = phpProxy + server.UpdatePHPProxy([]string{website.Proxy}, "") + website.Type = constant.Runtime + } else { + website.RuntimeID = 0 + website.Type = constant.Static + website.Proxy = "" + server.RemoveDirective("location", []string{"~", "[^/]\\.php(/|$)"}) + } + + config.FilePath = configPath + if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { + return err + } + nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) if err != nil { return err } - appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(runtime.AppDetailID)) - if err != nil { + if err = nginxCheckAndReload(string(nginxContent), configPath, nginxInstall.ContainerName); err != nil { return err } - - envs := make(map[string]interface{}) - if err = json.Unmarshal([]byte(appInstall.Env), &envs); err != nil { - return err - } - if out, err := compose.Down(appInstall.GetComposePath()); err != nil { - if out != "" { - return errors.New(out) - } - return err - } - - var ( - busErr error - fileOp = files.NewFileOp() - envPath = appInstall.GetEnvPath() - composePath = appInstall.GetComposePath() - confDir = path.Join(appInstall.GetPath(), "conf") - backupConfDir = path.Join(appInstall.GetPath(), "conf_bak") - fpmConfDir = path.Join(confDir, "php-fpm.conf") - phpDir = path.Join(constant.RuntimeDir, runtime.Type, runtime.Name, "php") - oldFmContent, _ = fileOp.GetContent(fpmConfDir) - newComposeByte []byte - ) - envParams := make(map[string]string, len(envs)) - handleMap(envs, envParams) - envParams["IMAGE_NAME"] = runtime.Image - defer func() { - if busErr != nil { - envParams["IMAGE_NAME"] = oldRuntime.Image - _ = env.Write(envParams, envPath) - _ = fileOp.WriteFile(composePath, strings.NewReader(appInstall.DockerCompose), 0775) - if fileOp.Stat(backupConfDir) { - _ = fileOp.DeleteDir(confDir) - _ = fileOp.Rename(backupConfDir, confDir) - } - } - }() - - if busErr = env.Write(envParams, envPath); busErr != nil { - return busErr - } - - newComposeByte, busErr = changeServiceName(appDetail.DockerCompose, appInstall.ServiceName) - if busErr != nil { - return err - } - - if busErr = fileOp.WriteFile(composePath, bytes.NewReader(newComposeByte), 0775); busErr != nil { - return busErr - } - if !req.RetainConfig { - if busErr = fileOp.Rename(confDir, backupConfDir); busErr != nil { - return busErr - } - _ = fileOp.CreateDir(confDir, 0755) - if busErr = fileOp.CopyFile(path.Join(phpDir, "php-fpm.conf"), confDir); busErr != nil { - return busErr - } - if busErr = fileOp.CopyFile(path.Join(phpDir, "php.ini"), confDir); busErr != nil { - _ = fileOp.WriteFile(fpmConfDir, bytes.NewReader(oldFmContent), 0775) - return busErr - } - } - - if out, err := compose.Up(appInstall.GetComposePath()); err != nil { - if out != "" { - busErr = errors.New(out) - return busErr - } - busErr = err - return busErr - } - - _ = fileOp.DeleteDir(backupConfDir) - - appInstall.AppDetailId = runtime.AppDetailID - appInstall.AppId = appDetail.AppId - appInstall.Version = appDetail.Version - appInstall.DockerCompose = string(newComposeByte) - - _ = appInstallRepo.Save(context.Background(), &appInstall) - website.RuntimeID = req.RuntimeID return websiteRepo.Save(context.Background(), &website) } diff --git a/agent/router/ro_website.go b/agent/router/ro_website.go index a70a028d1..c4f423e5d 100644 --- a/agent/router/ro_website.go +++ b/agent/router/ro_website.go @@ -70,5 +70,7 @@ func (a *WebsiteRouter) InitRouter(Router *gin.RouterGroup) { websiteRouter.POST("/lbs/del", baseApi.DeleteLoadBalance) websiteRouter.POST("/lbs/update", baseApi.UpdateLoadBalance) websiteRouter.POST("/lbs/file", baseApi.UpdateLoadBalanceFile) + + websiteRouter.POST("/php/version", baseApi.ChangePHPVersion) } } diff --git a/frontend/src/api/interface/website.ts b/frontend/src/api/interface/website.ts index 487ab397e..e4fe24154 100644 --- a/frontend/src/api/interface/website.ts +++ b/frontend/src/api/interface/website.ts @@ -472,7 +472,6 @@ export namespace Website { export interface PHPVersionChange { websiteID: number; runtimeID: number; - retainConfig: boolean; } export interface DirConfig { diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 8466a32ae..58f827019 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -2129,8 +2129,7 @@ const message = { notKeep: 'Do not keep', redirectRoot: 'Redirect to the homepage', redirectHelper: '301 permanent redirection, 302 temporary redirection', - changePHPVersionWarn: - 'Switching the PHP version will delete the original PHP container (the website code that has been mounted will not be lost), continue? ', + changePHPVersionWarn: 'This operation cannot be rolled back, do you want to continue?', changeVersion: 'Switch version', retainConfig: 'Whether to keep php-fpm.conf and php.ini files', runDirHelper2: 'Please ensure that the secondary running directory is under the index directory', @@ -2187,6 +2186,7 @@ const message = { strategy: 'Strategy', strategyDown: 'Down', strategyBackup: 'Backup', + staticChangePHPHelper: 'Currently a static website, you can switch to a PHP website', }, php: { short_open_tag: 'Short tag support', diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts index c28ed2c1a..b27c7292c 100644 --- a/frontend/src/lang/modules/tw.ts +++ b/frontend/src/lang/modules/tw.ts @@ -1983,7 +1983,7 @@ const message = { notKeep: '不保留', redirectRoot: '重定向到首頁', redirectHelper: '301永久重定向,302臨時重定向', - changePHPVersionWarn: '切換 PHP 版本會刪除原有的 PHP 容器(不會丟失已經掛載的網站代碼),是否繼續? ', + changePHPVersionWarn: '此動作不可回滾,是否繼續', changeVersion: '切換版本', retainConfig: '是否保留 php-fpm.conf 和 php.ini 文件', runDirHelper2: '請確保二級運行目錄位於 index 目錄下', @@ -2034,6 +2034,7 @@ const message = { strategy: '策略', strategyDown: '停用', strategyBackup: '備用', + staticChangePHPHelper: '目前為靜態網站,可切換為 PHP 網站', }, php: { short_open_tag: '短標簽支持', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index c393a3aa9..7e43e4fa2 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -1984,7 +1984,7 @@ const message = { notKeep: '不保留', redirectRoot: '重定向到首页', redirectHelper: '301永久重定向,302临时重定向', - changePHPVersionWarn: '切换 PHP 版本会删除原有的 PHP 容器(不会丢失已经挂载的网站代码),是否继续?', + changePHPVersionWarn: '此操作不可回滚,是否继续', changeVersion: '切换版本', retainConfig: '是否保留 php-fpm.conf 和 php.ini 文件', runDirHelper2: '请确保二级运行目录位于 index 目录下', @@ -2035,6 +2035,7 @@ const message = { strategy: '策略', strategyDown: '停用', strategyBackup: '备用', + staticChangePHPHelper: '当前为静态网站,可以切换为 PHP 网站', }, php: { short_open_tag: '短标签支持', diff --git a/frontend/src/views/website/website/config/basic/index.vue b/frontend/src/views/website/website/config/basic/index.vue index aaffeb36b..9b25ae4d2 100644 --- a/frontend/src/views/website/website/config/basic/index.vue +++ b/frontend/src/views/website/website/config/basic/index.vue @@ -1,7 +1,7 @@ @@ -54,15 +60,15 @@ import AuthBasic from './auth-basic/index.vue'; import AntiLeech from './anti-Leech/index.vue'; import Redirect from './redirect/index.vue'; import LoadBalance from './load-balance/index.vue'; +import PHP from './php/index.vue'; const props = defineProps({ - id: { - type: Number, - default: -1, + website: { + type: Object, }, }); const id = computed(() => { - return props.id; + return props.website.id; }); const tabIndex = ref('0'); diff --git a/frontend/src/views/website/website/config/basic/other/index.vue b/frontend/src/views/website/website/config/basic/other/index.vue index 74121df1f..d459f2003 100644 --- a/frontend/src/views/website/website/config/basic/other/index.vue +++ b/frontend/src/views/website/website/config/basic/other/index.vue @@ -24,7 +24,6 @@ - {{ $t('commons.button.save') }} diff --git a/frontend/src/views/website/website/config/basic/php/index.vue b/frontend/src/views/website/website/config/basic/php/index.vue new file mode 100644 index 000000000..f16a22751 --- /dev/null +++ b/frontend/src/views/website/website/config/basic/php/index.vue @@ -0,0 +1,91 @@ + + + diff --git a/frontend/src/views/website/website/config/index.vue b/frontend/src/views/website/website/config/index.vue index 7ac447a31..97423f2a6 100644 --- a/frontend/src/views/website/website/config/index.vue +++ b/frontend/src/views/website/website/config/index.vue @@ -27,16 +27,12 @@ {{ $t('website.source') }} - - PHP - @@ -48,7 +44,6 @@ import { onMounted, ref, watch } from 'vue'; import Basic from './basic/index.vue'; import Resource from './resource/index.vue'; import Log from './log/index.vue'; -import PHP from './php/index.vue'; import router from '@/routers'; import WebsiteStatus from '@/views/website/website/status/index.vue'; import { GetWebsite } from '@/api/modules/website'; @@ -65,10 +60,10 @@ const props = defineProps({ }, }); -let id = ref(0); -let index = ref('basic'); -let website = ref({}); -let loading = ref(false); +const id = ref(0); +const index = ref('basic'); +const website = ref({}); +const loading = ref(false); const configPHP = ref(false); watch(index, (curr, old) => { diff --git a/frontend/src/views/website/website/config/resource/index.vue b/frontend/src/views/website/website/config/resource/index.vue index 54b80bd9b..c5c2de29e 100644 --- a/frontend/src/views/website/website/config/resource/index.vue +++ b/frontend/src/views/website/website/config/resource/index.vue @@ -3,7 +3,6 @@ - @@ -13,7 +12,6 @@ import { GetWebsite } from '@/api/modules/website'; import { computed, onMounted, ref } from 'vue'; import Nginx from './nginx/index.vue'; - const props = defineProps({ id: { type: Number,