Skip to content

Commit

Permalink
feat: OpenResty 支持新增扩展
Browse files Browse the repository at this point in the history
  • Loading branch information
zhengkunwang223 committed Sep 20, 2024
1 parent 6a4897b commit e4c1c43
Show file tree
Hide file tree
Showing 20 changed files with 531 additions and 13 deletions.
57 changes: 57 additions & 0 deletions agent/app/api/v2/nginx.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,60 @@ func (b *BaseApi) ClearNginxProxyCache(c *gin.Context) {
}
helper.SuccessWithOutData(c)
}

// @Tags OpenResty
// @Summary Build OpenResty
// @Description 构建 OpenResty
// @Accept json
// @Param request body request.NginxBuildReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /openresty/build [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"构建 OpenResty","formatEN":"Build OpenResty"}
func (b *BaseApi) BuildNginx(c *gin.Context) {
var req request.NginxBuildReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := nginxService.Build(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithOutData(c)
}

// @Tags OpenResty
// @Summary Update OpenResty module
// @Description 更新 OpenResty 模块
// @Accept json
// @Param request body request.NginxModuleUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /openresty/module/update [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 OpenResty 模块","formatEN":"Update OpenResty module"}
func (b *BaseApi) UpdateNginxModule(c *gin.Context) {
var req request.NginxModuleUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := nginxService.UpdateModule(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithOutData(c)
}

// @Tags OpenResty
// @Summary Get OpenResty modules
// @Description 获取 OpenResty 模块
// @Success 200 {array} response.NginxModule
// @Security ApiKeyAuth
// @Router /openresty/modules [get]
func (b *BaseApi) GetNginxModules(c *gin.Context) {
modules, err := nginxService.GetModules()
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, modules)
}
13 changes: 13 additions & 0 deletions agent/app/dto/request/nginx.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,16 @@ type NginxRedirectUpdate struct {
Content string `json:"content" validate:"required"`
Name string `json:"name" validate:"required"`
}

type NginxBuildReq struct {
TaskID string `json:"taskID" validate:"required"`
}

type NginxModuleUpdate struct {
Operate string `json:"operate" validate:"required,oneof=create delete update"`
Name string `json:"name" validate:"required"`
Script string `json:"script"`
Packages string `json:"packages"`
Enable bool `json:"enable"`
Params string `json:"params"`
}
8 changes: 8 additions & 0 deletions agent/app/dto/response/nginx.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,11 @@ type NginxProxyCache struct {
CacheExpire int `json:"cacheExpire" `
CacheExpireUnit string `json:"cacheExpireUnit" `
}

type NginxModule struct {
Name string `json:"name"`
Script string `json:"script"`
Packages []string `json:"packages"`
Params string `json:"params"`
Enable bool `json:"enable"`
}
164 changes: 164 additions & 0 deletions agent/app/service/nginx.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package service

import (
"bufio"
"encoding/json"
"fmt"
"github.com/1Panel-dev/1Panel/agent/app/task"
"github.com/1Panel-dev/1Panel/agent/buserr"
cmd2 "github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/subosito/gotenv"
"io"
"net/http"
"os"
Expand Down Expand Up @@ -29,6 +35,10 @@ type INginxService interface {
GetStatus() (response.NginxStatus, error)
UpdateConfigFile(req request.NginxConfigFileUpdate) error
ClearProxyCache() error

Build(req request.NginxBuildReq) error
GetModules() ([]response.NginxModule, error)
UpdateModule(req request.NginxModuleUpdate) error
}

func NewINginxService() INginxService {
Expand Down Expand Up @@ -152,3 +162,157 @@ func (n NginxService) ClearProxyCache() error {
}
return nil
}

func (n NginxService) Build(req request.NginxBuildReq) error {
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return err
}
fileOp := files.NewFileOp()
buildPath := path.Join(nginxInstall.GetPath(), "build")
if !fileOp.Stat(buildPath) {
return buserr.New("ErrBuildDirNotFound")
}
moduleConfigPath := path.Join(buildPath, "module.json")
moduleContent, err := fileOp.GetContent(moduleConfigPath)
if err != nil {
return err
}
var (
modules []response.NginxModule
addModuleParams []string
addPackages []string
)
if len(moduleContent) > 0 {
_ = json.Unmarshal(moduleContent, &modules)
bashFile, err := os.OpenFile(path.Join(buildPath, "tmp", "pre.sh"), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0755)
if err != nil {
return err
}
defer bashFile.Close()
bashFileWriter := bufio.NewWriter(bashFile)
for _, module := range modules {
if !module.Enable {
continue
}
_, err = bashFileWriter.WriteString(module.Script + "\n")
if err != nil {
return err
}
addModuleParams = append(addModuleParams, module.Params)
addPackages = append(addPackages, module.Packages...)
}
err = bashFileWriter.Flush()
if err != nil {
return err
}
}
envs, err := gotenv.Read(nginxInstall.GetEnvPath())
if err != nil {
return err
}
envs["RESTY_CONFIG_OPTIONS_MORE"] = ""
envs["RESTY_ADD_PACKAGE_BUILDDEPS"] = ""
if len(addModuleParams) > 0 {
envs["RESTY_CONFIG_OPTIONS_MORE"] = strings.Join(addModuleParams, " ")
}
if len(addPackages) > 0 {
envs["RESTY_ADD_PACKAGE_BUILDDEPS"] = strings.Join(addPackages, " ")
}
_ = gotenv.Write(envs, nginxInstall.GetEnvPath())

buildTask, err := task.NewTaskWithOps(nginxInstall.Name, task.TaskBuild, task.TaskScopeApp, req.TaskID, nginxInstall.ID)
if err != nil {
return err
}
buildTask.AddSubTask("", func(t *task.Task) error {
if err = cmd2.ExecWithLogFile(fmt.Sprintf("docker compose -f %s build", nginxInstall.GetComposePath()), 15*time.Minute, t.Task.LogFile); err != nil {
return err
}
_, err = compose.DownAndUp(nginxInstall.GetComposePath())
return err
}, nil)

go func() {
_ = buildTask.Execute()
}()
return nil
}

func (n NginxService) GetModules() ([]response.NginxModule, error) {
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return nil, err
}
fileOp := files.NewFileOp()
var modules []response.NginxModule
moduleConfigPath := path.Join(nginxInstall.GetPath(), "build", "module.json")
if !fileOp.Stat(moduleConfigPath) {
return modules, nil
}
moduleContent, err := fileOp.GetContent(moduleConfigPath)
if err != nil {
return nil, err
}
if len(moduleContent) > 0 {
_ = json.Unmarshal(moduleContent, &modules)
}
return modules, nil
}

func (n NginxService) UpdateModule(req request.NginxModuleUpdate) error {
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return err
}
fileOp := files.NewFileOp()
var modules []response.NginxModule
moduleConfigPath := path.Join(nginxInstall.GetPath(), "build", "module.json")
if !fileOp.Stat(moduleConfigPath) {
_ = fileOp.CreateFile(moduleConfigPath)
}
moduleContent, err := fileOp.GetContent(moduleConfigPath)
if err != nil {
return err
}
if len(moduleContent) > 0 {
_ = json.Unmarshal(moduleContent, &modules)
}
switch req.Operate {
case "create":
for _, module := range modules {
if module.Name == req.Name {
return buserr.New("ErrNameIsExist")
}
}
modules = append(modules, response.NginxModule{
Name: req.Name,
Script: req.Script,
Packages: strings.Split(req.Packages, " "),
Params: req.Params,
Enable: true,
})
case "update":
for i, module := range modules {
if module.Name == req.Name {
modules[i].Script = req.Script
modules[i].Packages = strings.Split(req.Packages, " ")
modules[i].Params = req.Params
modules[i].Enable = req.Enable
break
}
}
case "delete":
for i, module := range modules {
if module.Name == req.Name {
modules = append(modules[:i], modules[i+1:]...)
break
}
}
}
moduleByte, err := json.Marshal(modules)
if err != nil {
return err
}
return fileOp.SaveFileWithByte(moduleConfigPath, moduleByte, 0644)
}
1 change: 1 addition & 0 deletions agent/app/task/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const (
TaskRestart = "TaskRestart"
TaskBackup = "TaskBackup"
TaskSync = "TaskSync"
TaskBuild = "TaskBuild"
)

const (
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ ErrDomainIsUsed: "Domain is already used by website {{ .name }}"
ErrDomainFormat: "{{ .name }} domain format error"
ErrDefaultAlias: "default is a reserved code name, please use another code name"
ErrParentWebsite: "You need to delete the subsite(s) {{ .name }} first"
ErrBuildDirNotFound: "Build directory does not exist"

#ssl
ErrSSLCannotDelete: "The certificate {{ .name }} is being used by the website and cannot be removed"
Expand Down Expand Up @@ -244,4 +245,5 @@ TaskSync: "Sync"
LocalApp: "Local App"
SubTask: "Subtask"
RuntimeExtension: "Runtime Extension"
TaskBuild: "Build"

3 changes: 3 additions & 0 deletions agent/i18n/lang/zh-Hant.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ ErrDomainIsUsed: "域名已被網站【{{ .name }}】使用"
ErrDomainFormat: "{{ .name }} 域名格式不正確"
ErrDefaultAlias: "default 為保留代號,請使用其他代號"
ErrParentWebsite: "需要先刪除子網站 {{ .name }}"
ErrBuildDirNotFound: "編譯目錄不存在"

#ssl
ErrSSLCannotDelete: "{{ .name }} 證書正在被網站使用,無法刪除"
Expand Down Expand Up @@ -246,4 +247,6 @@ TaskSync: "同步"
LocalApp: "本地應用"
SubTask: "子任務"
RuntimeExtension: "運行環境擴展"
TaskBuild: "構建"


4 changes: 3 additions & 1 deletion agent/i18n/lang/zh.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ ErrDomainIsUsed: "域名已被网站【{{ .name }}】使用"
ErrDomainFormat: "{{ .name }} 域名格式不正确"
ErrDefaultAlias: "default 为保留代号,请使用其他代号"
ErrParentWebsite: "需要先删除子网站 {{ .name }}"
ErrBuildDirNotFound: "构建目录不存在"

#ssl
ErrSSLCannotDelete: "{{ .name }} 证书正在被网站使用,无法删除"
Expand Down Expand Up @@ -247,4 +248,5 @@ AppStore: "应用商店"
TaskSync: "同步"
LocalApp: "本地应用"
SubTask: "子任务"
RuntimeExtension: "运行环境扩展"
RuntimeExtension: "运行环境扩展"
TaskBuild: "构建"
3 changes: 3 additions & 0 deletions agent/router/ro_nginx.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,8 @@ func (a *NginxRouter) InitRouter(Router *gin.RouterGroup) {
groupRouter.GET("/status", baseApi.GetNginxStatus)
groupRouter.POST("/file", baseApi.UpdateNginxFile)
groupRouter.POST("/clear", baseApi.ClearNginxProxyCache)
groupRouter.POST("/build", baseApi.BuildNginx)
groupRouter.POST("/modules/update", baseApi.UpdateNginxModule)
groupRouter.GET("/modules", baseApi.GetNginxModules)
}
}
21 changes: 21 additions & 0 deletions frontend/src/api/interface/nginx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,25 @@ export namespace Nginx {
content: string;
backup: boolean;
}

export interface NginxBuildReq {
taskID: string;
}

export interface NginxModule {
name: string;
script?: string;
packages?: string[];
enable: boolean;
params: string;
}

export interface NginxModuleUpdate {
operate: string;
name: string;
script?: string;
packages?: string;
enable: boolean;
params: string;
}
}
18 changes: 15 additions & 3 deletions frontend/src/api/modules/nginx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,29 @@ export const GetNginxConfigByScope = (req: Nginx.NginxScopeReq) => {
};

export const UpdateNginxConfigByScope = (req: Nginx.NginxConfigReq) => {
return http.post<any>(`/openresty/update`, req);
return http.post(`/openresty/update`, req);
};

export const GetNginxStatus = () => {
return http.get<Nginx.NginxStatus>(`/openresty/status`);
};

export const UpdateNginxConfigFile = (req: Nginx.NginxFileUpdate) => {
return http.post<any>(`/openresty/file`, req);
return http.post(`/openresty/file`, req);
};

export const ClearNginxCache = () => {
return http.post<any>(`/openresty/clear`);
return http.post(`/openresty/clear`);
};

export const BuildNginx = (req: Nginx.NginxBuildReq) => {
return http.post(`/openresty/build`, req);
};

export const GetNginxModules = () => {
return http.get<Nginx.NginxModule[]>(`/openresty/modules`);
};

export const UpdateNginxModule = (req: Nginx.NginxModuleUpdate) => {
return http.post(`/openresty/modules/update`, req);
};
Loading

0 comments on commit e4c1c43

Please sign in to comment.