feat: OpenResty 增加默认扩展 (#6556)
Some checks failed
sync2gitee / repo-sync (push) Failing after -9m27s

This commit is contained in:
zhengkunwang 2024-09-23 18:32:20 +08:00 committed by GitHub
parent 3c0dca6992
commit 4720bda29b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 235 additions and 57 deletions

View file

@ -84,3 +84,11 @@ type NginxUpstreamServer struct {
var LBAlgorithms = map[string]struct{}{"ip_hash": {}, "least_conn": {}}
var RealIPKeys = map[string]struct{}{"X-Forwarded-For": {}, "X-Real-IP": {}, "CF-Connecting-IP": {}}
type NginxModule struct {
Name string `json:"name"`
Script string `json:"script"`
Packages []string `json:"packages"`
Params string `json:"params"`
Enable bool `json:"enable"`
}

View file

@ -109,6 +109,7 @@ type NginxRedirectUpdate struct {
type NginxBuildReq struct {
TaskID string `json:"taskID" validate:"required"`
Mirror string `json:"mirror" validate:"required"`
}
type NginxModuleUpdate struct {

View file

@ -69,9 +69,14 @@ type NginxProxyCache struct {
}
type NginxModule struct {
Name string `json:"name"`
Script string `json:"script"`
Packages []string `json:"packages"`
Params string `json:"params"`
Enable bool `json:"enable"`
Name string `json:"name"`
Script string `json:"script"`
Packages string `json:"packages"`
Params string `json:"params"`
Enable bool `json:"enable"`
}
type NginxBuildConfig struct {
Mirror string `json:"mirror"`
Modules []NginxModule `json:"modules"`
}

View file

@ -37,7 +37,7 @@ type INginxService interface {
ClearProxyCache() error
Build(req request.NginxBuildReq) error
GetModules() ([]response.NginxModule, error)
GetModules() (*response.NginxBuildConfig, error)
UpdateModule(req request.NginxModuleUpdate) error
}
@ -179,7 +179,7 @@ func (n NginxService) Build(req request.NginxBuildReq) error {
return err
}
var (
modules []response.NginxModule
modules []dto.NginxModule
addModuleParams []string
addPackages []string
)
@ -211,6 +211,7 @@ func (n NginxService) Build(req request.NginxBuildReq) error {
if err != nil {
return err
}
envs["CONTAINER_PACKAGE_URL"] = req.Mirror
envs["RESTY_CONFIG_OPTIONS_MORE"] = ""
envs["RESTY_ADD_PACKAGE_BUILDDEPS"] = ""
if len(addModuleParams) > 0 {
@ -239,16 +240,16 @@ func (n NginxService) Build(req request.NginxBuildReq) error {
return nil
}
func (n NginxService) GetModules() ([]response.NginxModule, error) {
func (n NginxService) GetModules() (*response.NginxBuildConfig, error) {
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return nil, err
}
fileOp := files.NewFileOp()
var modules []response.NginxModule
var modules []dto.NginxModule
moduleConfigPath := path.Join(nginxInstall.GetPath(), "build", "module.json")
if !fileOp.Stat(moduleConfigPath) {
return modules, nil
return nil, nil
}
moduleContent, err := fileOp.GetContent(moduleConfigPath)
if err != nil {
@ -257,7 +258,25 @@ func (n NginxService) GetModules() ([]response.NginxModule, error) {
if len(moduleContent) > 0 {
_ = json.Unmarshal(moduleContent, &modules)
}
return modules, nil
var resList []response.NginxModule
for _, module := range modules {
resList = append(resList, response.NginxModule{
Name: module.Name,
Script: module.Script,
Packages: strings.Join(module.Packages, ","),
Params: module.Params,
Enable: module.Enable,
})
}
envs, err := gotenv.Read(nginxInstall.GetEnvPath())
if err != nil {
return nil, err
}
return &response.NginxBuildConfig{
Mirror: envs["CONTAINER_PACKAGE_URL"],
Modules: resList,
}, nil
}
func (n NginxService) UpdateModule(req request.NginxModuleUpdate) error {
@ -266,7 +285,9 @@ func (n NginxService) UpdateModule(req request.NginxModuleUpdate) error {
return err
}
fileOp := files.NewFileOp()
var modules []response.NginxModule
var (
modules []dto.NginxModule
)
moduleConfigPath := path.Join(nginxInstall.GetPath(), "build", "module.json")
if !fileOp.Stat(moduleConfigPath) {
_ = fileOp.CreateFile(moduleConfigPath)
@ -278,6 +299,7 @@ func (n NginxService) UpdateModule(req request.NginxModuleUpdate) error {
if len(moduleContent) > 0 {
_ = json.Unmarshal(moduleContent, &modules)
}
switch req.Operate {
case "create":
for _, module := range modules {
@ -285,10 +307,10 @@ func (n NginxService) UpdateModule(req request.NginxModuleUpdate) error {
return buserr.New("ErrNameIsExist")
}
}
modules = append(modules, response.NginxModule{
modules = append(modules, dto.NginxModule{
Name: req.Name,
Script: req.Script,
Packages: strings.Split(req.Packages, " "),
Packages: strings.Split(req.Packages, ","),
Params: req.Params,
Enable: true,
})
@ -296,7 +318,7 @@ func (n NginxService) UpdateModule(req request.NginxModuleUpdate) error {
for i, module := range modules {
if module.Name == req.Name {
modules[i].Script = req.Script
modules[i].Packages = strings.Split(req.Packages, " ")
modules[i].Packages = strings.Split(req.Packages, ",")
modules[i].Params = req.Params
modules[i].Enable = req.Enable
break

View file

@ -31,22 +31,23 @@ export namespace Nginx {
export interface NginxBuildReq {
taskID: string;
mirror: 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;
}
export interface NginxBuildConfig {
mirror: string;
modules: NginxModule[];
}
export interface NginxModuleUpdate extends NginxModule {
operate: string;
}
}

View file

@ -31,7 +31,7 @@ export const BuildNginx = (req: Nginx.NginxBuildReq) => {
};
export const GetNginxModules = () => {
return http.get<Nginx.NginxModule[]>(`/openresty/modules`);
return http.get<Nginx.NginxBuildConfig>(`/openresty/modules`);
};
export const UpdateNginxModule = (req: Nginx.NginxModuleUpdate) => {

View file

@ -2260,6 +2260,13 @@ const message = {
build: 'Build',
buildWarn:
'Building OpenResty requires reserving a certain amount of CPU and memory, which may take a long time, please be patient',
mirrorUrl: 'Software Source',
paramsHelper: 'For example: --add-module=/tmp/ngx_brotli',
packagesHelper: 'For example: git, curl (separated by commas)',
scriptHelper:
'Scripts to execute before compilation, usually for downloading module source code, installing dependencies, etc.',
buildHelper:
'Click build after adding/modifying a module. OpenResty will automatically restart upon successful build.',
},
ssl: {
create: 'Apply',

View file

@ -2104,6 +2104,11 @@ const message = {
module: '模組',
build: '建構',
buildWarn: '建構 OpenResty 需要預留一定的 CPU 和內存時間較長請耐心等待',
mirrorUrl: '軟體源',
paramsHelper: '例如--add-module=/tmp/ngx_brotli',
packagesHelper: '例如git,curl 以逗號分割',
scriptHelper: '編譯之前執行的腳本通常用於下載模組原始碼安裝依賴等',
buildHelper: '添加/修改模組後點擊構建構建成功後會自動重啟 OpenResty',
},
ssl: {
create: '申請證書',

View file

@ -2105,6 +2105,11 @@ const message = {
module: '模块',
build: '构建',
buildWarn: '构建 OpenResty 需要预留一定的 CPU 和内存时间较长请耐心等待',
mirrorUrl: '软件源',
paramsHelper: '例如--add-module=/tmp/ngx_brotli',
packagesHelper: '例如git,curl ,分割',
scriptHelper: '编译之前执行的脚本一般为下载模块源码安装依赖等',
buildHelper: '添加/修改模块之后点击构建构建成功后会自动重启 OpenResty',
},
ssl: {
create: '申请证书',

View file

@ -0,0 +1,96 @@
<template>
<DrawerPro v-model="open" :header="$t('nginx.build')" size="normal" :back="handleClose">
<el-form ref="buildForm" label-position="top" :model="build" :rules="rules">
<el-form-item :label="$t('nginx.mirrorUrl')" prop="mirror">
<el-select v-model="build.mirror">
<el-option
value="http://archive.ubuntu.com/ubuntu/"
label="http://archive.ubuntu.com/ubuntu/"
></el-option>
<el-option
value="http://mirrors.aliyun.com/ubuntu/"
label="http://mirrors.aliyun.com/ubuntu/"
></el-option>
<el-option
value="https://mirrors.tuna.tsinghua.edu.cn/ubuntu/"
label="https://mirrors.tuna.tsinghua.edu.cn/ubuntu/"
></el-option>
<el-option
value="https://mirrors.ustc.edu.cn/ubuntu/"
label="https://mirrors.ustc.edu.cn/ubuntu/"
></el-option>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="handleClose" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
<el-button type="primary" @click="submit(buildForm)" :disabled="loading">
{{ $t('commons.button.confirm') }}
</el-button>
</template>
</DrawerPro>
<TaskLog ref="taskLogRef" />
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { FormInstance } from 'element-plus';
import { GetNginxModules, BuildNginx } from '@/api/modules/nginx';
import i18n from '@/lang';
import { newUUID } from '@/utils/util';
import TaskLog from '@/components/task-log/index.vue';
import { Rules } from '@/global/form-rules';
const open = ref(false);
const loading = ref(false);
const buildForm = ref<FormInstance>();
const build = ref({
mirror: 'http://archive.ubuntu.com/ubuntu',
});
const rules = {
mirror: [Rules.requiredSelect],
};
const taskLogRef = ref();
const acceptParams = async () => {
getModules();
open.value = true;
};
const getModules = async () => {
try {
const res = await GetNginxModules();
build.value.mirror = res.data.mirror;
} catch (error) {}
};
const submit = async (form: FormInstance) => {
await form.validate();
if (form.validate()) {
ElMessageBox.confirm(i18n.global.t('nginx.buildWarn'), i18n.global.t('nginx.build'), {
confirmButtonText: i18n.global.t('commons.button.confirm'),
cancelButtonText: i18n.global.t('commons.button.cancel'),
}).then(async () => {
const taskID = newUUID();
try {
await BuildNginx({
taskID: taskID,
mirror: build.value.mirror,
});
openTaskLog(taskID);
} catch (error) {}
});
}
};
const openTaskLog = (taskID: string) => {
taskLogRef.value.openWithTaskID(taskID);
};
const handleClose = () => {
open.value = false;
};
defineExpose({
acceptParams,
});
</script>

View file

@ -4,40 +4,46 @@
<template #toolbar>
<el-button type="primary" @click="openOperate">{{ $t('commons.button.create') }}</el-button>
<el-button type="primary" plain @click="buildNginx">{{ $t('nginx.build') }}</el-button>
<el-text type="warning" class="!ml-2">{{ $t('nginx.buildHelper') }}</el-text>
</template>
<el-table-column prop="name" :label="$t('commons.table.name')" />
<el-table-column prop="params" :label="$t('nginx.params')" />
<el-table-column :label="$t('commons.table.status')" fix>
<template #default="{ row }">
<el-switch v-model="row.enable" />
<el-switch v-model="row.enable" @click="updateModule(row)" />
</template>
</el-table-column>
<fu-table-operations
:ellipsis="2"
width="100px"
width="200px"
:buttons="buttons"
:label="$t('commons.table.operate')"
fixed="right"
fix
/>
</ComplexTable>
<TaskLog ref="taskLogRef" />
<Operate ref="operateRef" @close="search" />
<OpDialog ref="deleteRef" @search="search" @cancel="search" />
<Build ref="buildRef" />
</div>
</template>
<script lang="ts" setup>
import { BuildNginx, GetNginxModules, UpdateNginxModule } from '@/api/modules/nginx';
import { newUUID } from '@/utils/util';
import TaskLog from '@/components/task-log/index.vue';
import Operate from './operate/index.vue';
import { GetNginxModules, UpdateNginxModule } from '@/api/modules/nginx';
import i18n from '@/lang';
import { Nginx } from '@/api/interface/nginx';
import { MsgSuccess } from '@/utils/message';
import Operate from './operate/index.vue';
import Build from './build/index.vue';
const taskLogRef = ref();
const data = ref([]);
const loading = ref(false);
const buttons = [
{
label: i18n.global.t('commons.button.edit'),
click: function (row: Nginx.NginxModule) {
openEdit(row);
},
},
{
label: i18n.global.t('commons.button.delete'),
click: function (row: Nginx.NginxModule) {
@ -47,39 +53,44 @@ const buttons = [
];
const operateRef = ref();
const deleteRef = ref();
const buildRef = ref();
const buildNginx = async () => {
ElMessageBox.confirm(i18n.global.t('nginx.buildWarn'), i18n.global.t('nginx.build'), {
confirmButtonText: i18n.global.t('commons.button.confirm'),
cancelButtonText: i18n.global.t('commons.button.cancel'),
}).then(async () => {
const taskID = newUUID();
try {
await BuildNginx({
taskID: taskID,
});
openTaskLog(taskID);
} catch (error) {}
});
buildRef.value.acceptParams();
};
const search = () => {
loading.value = true;
GetNginxModules()
.then((res) => {
data.value = res.data;
data.value = res.data.modules;
})
.finally(() => {
loading.value = false;
});
};
const openTaskLog = (taskID: string) => {
taskLogRef.value.openWithTaskID(taskID);
const openOperate = () => {
operateRef.value.acceptParams('create');
};
const openOperate = () => {
operateRef.value.acceptParams();
const openEdit = (row: Nginx.NginxModule) => {
operateRef.value.acceptParams('update', row);
};
const updateModule = (row: Nginx.NginxModule) => {
loading.value = true;
const data = {
...row,
operate: 'update',
};
UpdateNginxModule(data)
.then(() => {
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
})
.finally(() => {
loading.value = false;
});
};
const deleteModule = async (row: Nginx.NginxModule) => {

View file

@ -3,21 +3,26 @@
v-model="open"
:header="$t('nginx.' + mode)"
size="large"
:resource="mode === 'edit' ? module.name : ''"
:resource="mode === 'update' ? module.name : ''"
:back="handleClose"
>
<el-form ref="moduleForm" label-position="top" :model="module" :rules="rules">
<el-form-item :label="$t('commons.table.name')" prop="name">
<el-input v-model.trim="module.name" :disabled="mode === 'edit'"></el-input>
<el-input v-model.trim="module.name" :disabled="mode === 'update'"></el-input>
</el-form-item>
<el-form-item :label="$t('nginx.params')" prop="params">
<el-input v-model.trim="module.params"></el-input>
<el-input v-model.trim="module.params" :placeholder="$t('nginx.paramsHelper')"></el-input>
</el-form-item>
<el-form-item :label="$t('nginx.packages')" prop="packages">
<el-input v-model.trim="module.packages"></el-input>
<el-input v-model.trim="module.packages" :placeholder="$t('nginx.packagesHelper')"></el-input>
</el-form-item>
<el-form-item :label="$t('nginx.script')" prop="script">
<el-input v-model="module.script" type="textarea" :rows="10"></el-input>
<el-input
v-model="module.script"
type="textarea"
:rows="10"
:placeholder="$t('nginx.scriptHelper')"
></el-input>
</el-form-item>
</el-form>
<template #footer>
@ -30,6 +35,7 @@
</template>
<script lang="ts" setup>
import { Nginx } from '@/api/interface/nginx';
import { UpdateNginxModule } from '@/api/modules/nginx';
import { Rules } from '@/global/form-rules';
import i18n from '@/lang';
@ -59,7 +65,18 @@ const handleClose = () => {
em('close', false);
};
const acceptParams = async () => {
const acceptParams = async (operate: string, editModule: Nginx.NginxModule) => {
mode.value = operate;
if (operate === 'update') {
module.value = {
name: editModule.name,
script: editModule.script,
enable: editModule.enable,
params: editModule.params,
packages: editModule.packages,
operate: 'update',
};
}
open.value = true;
};
@ -73,7 +90,7 @@ const submit = async (form: FormInstance) => {
};
UpdateNginxModule(data)
.then(() => {
if (mode.value === 'edit') {
if (mode.value === 'update') {
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
} else if (mode.value === 'create') {
MsgSuccess(i18n.global.t('commons.msg.createSuccess'));