Compare commits

...

90 Commits

Author SHA1 Message Date
刘祥超
43c6bff964 准备发布 2022-07-17 21:19:45 +08:00
刘祥超
aef84189a4 优化代码/自动去除域名中的http://和https://等,防止误填 2022-07-17 17:12:44 +08:00
刘祥超
04f8bfc975 价格增加总价格设定 2022-07-17 10:53:03 +08:00
刘祥超
d139e93160 改进文字提示 2022-07-16 19:21:37 +08:00
刘祥超
1fcc0694ca 改进文字提示 2022-07-16 19:03:56 +08:00
刘祥超
7ba7858076 WAF策略增加记录区域封禁日志选项 2022-07-16 18:45:39 +08:00
刘祥超
b1cbc433ed WAF策略增加记录请求Body选项 2022-07-16 17:04:56 +08:00
刘祥超
8beaf97306 cc2增加忽略常见文件扩展名选项 2022-07-15 12:04:24 +08:00
刘祥超
e626364f45 日志详情中增加源站信息 2022-07-14 11:59:09 +08:00
刘祥超
ebaec51f67 修复全局封锁名单不能创建IP的Bug/创建和修改IP可以直接选择过期时间 2022-07-14 10:19:45 +08:00
刘祥超
36b90451af 集群DNS设置增加允许通过CNAME访问网站服务选项/集群DNS设置可以设置不使用主域名 2022-07-14 09:48:13 +08:00
刘祥超
e0b1c2a6a4 去除开源版本中不必要的菜单 2022-07-12 14:07:25 +08:00
刘祥超
42c6f4264e 删除不必要的文件 2022-07-12 14:05:24 +08:00
刘祥超
78641e7052 删除不必要的文件 2022-07-12 13:57:17 +08:00
刘祥超
6bf0118d20 修复开源版本无法编译的问题 2022-07-12 13:55:00 +08:00
刘祥超
0415cd3719 优化代码 2022-07-11 14:42:38 +08:00
刘祥超
a3412b2f95 域名解析支持DNS.COM(商业版) 2022-07-11 11:52:03 +08:00
刘祥超
6a4b3b026f 修复开源版本无法访问“刷新预热”菜单的Bug 2022-07-10 20:47:48 +08:00
刘祥超
f213976a5d 支持ClouDNS(商业版) 2022-07-10 19:35:13 +08:00
刘祥超
3605f71f70 安全设置中增加禁止搜索引擎、禁止爬虫、允许访问的域名等选项 2022-07-07 19:58:30 +08:00
刘祥超
dc08847a7d 在robots.txt中移除GoEdge标识 2022-07-07 14:42:47 +08:00
刘祥超
a34204e25e 可以在管理界面修改用户平台数据看板相关设置 2022-07-07 12:39:23 +08:00
刘祥超
25d73ac0a2 Go版本号改为从v1.18开始 2022-07-07 09:16:29 +08:00
刘祥超
f67c0c0e75 优化文字 2022-07-05 20:07:37 +08:00
刘祥超
08c8255d59 优化集群设置菜单 2022-07-04 10:31:25 +08:00
刘祥超
157efaa02e 增加UAM(5秒盾)集群设置 2022-07-03 22:09:27 +08:00
刘祥超
a56a29495e 反向代理设置中增加移除回源主机名端口功能 2022-06-30 12:11:17 +08:00
刘祥超
c454cd75b3 实现源站端口跟随功能 2022-06-29 21:56:44 +08:00
刘祥超
633684f576 优化编译脚本 2022-06-29 17:00:05 +08:00
刘祥超
de50b5e0a1 优化编译脚本 2022-06-29 14:50:51 +08:00
刘祥超
855f287e39 DNS自定义线路中增加CIDR、区域以及排除功能 2022-06-28 20:26:06 +08:00
刘祥超
f018dee75e 修复弹窗中没有正确设置favicon的Bug 2022-06-28 20:25:19 +08:00
刘祥超
7d3b218e24 支持ZSTD压缩 2022-06-27 22:40:12 +08:00
刘祥超
536382ce34 改进文字提示 2022-06-27 15:17:54 +08:00
刘祥超
f6f003d524 TLS源站支持填写回源主机名 2022-06-27 15:10:45 +08:00
刘祥超
8126de4048 改进文字 2022-06-25 19:31:23 +08:00
刘祥超
4c41df85a0 优化网站服务菜单 2022-06-20 15:59:55 +08:00
刘祥超
2c9f78bb9e 版本改为v0.4.9 2022-06-20 15:59:26 +08:00
刘祥超
23899e196e 完善一些文字细节 2022-06-19 20:19:58 +08:00
刘祥超
ecbc87265e 优化交互 2022-06-16 19:32:40 +08:00
刘祥超
9f8731d668 删除不必要的文件 2022-06-16 16:33:50 +08:00
刘祥超
12d545138a 删除不必要的文件 2022-06-16 16:26:44 +08:00
刘祥超
0c054581ac 删除不必要的文件 2022-06-16 16:25:37 +08:00
刘祥超
c8c2f83763 删除不必要的文件 2022-06-16 15:35:14 +08:00
刘祥超
9056d591c3 DNS线路可以批量添加IP范围 2022-06-15 20:24:52 +08:00
刘祥超
191f58074e 取消IP库上传入口,防止用户误操作 2022-06-15 19:51:54 +08:00
刘祥超
92d3af3d2b 修改源站时校验端口号 2022-06-15 19:42:03 +08:00
刘祥超
2ddc4d62a2 添加源站时校验端口号 2022-06-15 19:40:07 +08:00
刘祥超
81a2967683 删除不必要的文件 2022-06-15 16:32:11 +08:00
刘祥超
29e3c55df0 优化界面 2022-06-15 15:52:30 +08:00
刘祥超
27e3cdffb1 自动更新缓存任务执行状况/优化缓存相关文字提示 2022-06-15 15:47:43 +08:00
刘祥超
a1ad56aebb 优化缓存任务Key状态显示 2022-06-15 15:17:54 +08:00
刘祥超
2573b3b827 边缘节点时间和API节点时间相差超过3秒时才会在节点详情提示。 2022-06-15 11:51:03 +08:00
刘祥超
bcd9a8fcd2 优化界面提示 2022-06-14 20:00:00 +08:00
刘祥超
8dbc83fd27 增加管理平台所在服务器磁盘空间过小提醒 2022-06-14 19:55:38 +08:00
刘祥超
275280d24e WAF规则中国家/地区、省份、城市、ISP增加候选项检索和选择 2022-06-14 17:38:50 +08:00
刘祥超
c82fa4709d 优化代码 2022-06-12 20:59:55 +08:00
刘祥超
c8e826014b 访问日志查询增加requestPath:/hello、proto:HTTP/1.1、scheme:http等语法 2022-06-12 20:36:05 +08:00
刘祥超
75b2e93678 优化界面 2022-06-09 19:45:09 +08:00
刘祥超
b0573df9d8 优化界面 2022-06-09 12:23:02 +08:00
刘祥超
e6c14590f1 启用服务HTTP/HTTPS设置时如果没有设置端口,则自动添加80/443 2022-06-08 20:11:38 +08:00
刘祥超
248ac43f28 优化代码 2022-06-08 19:55:57 +08:00
刘祥超
9361a27dca API连接错误提示更加详细,以便于快速发现问题 2022-06-08 15:17:00 +08:00
刘祥超
700836903f 安装时如果数据库地址填写的是公网IP,则提示会影响系统运行性能 2022-06-08 11:00:03 +08:00
刘祥超
039ce26f58 在节点详情中提示边缘节点和API节点时间差 2022-06-06 20:13:04 +08:00
刘祥超
95bfb7f0b6 可以设置用户每天执行缓存任务的额度 2022-06-05 21:15:08 +08:00
刘祥超
9a181556ca 发送远程指令时包括从节点 2022-06-05 17:18:26 +08:00
刘祥超
9554b6f3ec 增加刷新、预热缓存任务管理 2022-06-05 17:12:54 +08:00
刘祥超
45089437ef 优化界面 2022-05-25 11:45:56 +08:00
刘祥超
f47a3b0586 优化界面/修改用户集群不影响套餐服务 2022-05-25 11:44:05 +08:00
刘祥超
1a19c7520a 优化界面 2022-05-23 14:54:27 +08:00
刘祥超
6266af66f7 新创建WAF时增加默认选项 2022-05-21 20:00:39 +08:00
刘祥超
d3cdc24ebf WAF策略中增加验证码相关定制设置 2022-05-20 22:07:04 +08:00
刘祥超
f37d2fc4d7 健康检查增加是否记录访问日志选项 2022-05-19 17:14:19 +08:00
刘祥超
6cd182b858 实现基础的DDoS防护 2022-05-18 21:02:47 +08:00
刘祥超
d46bf37726 调整左侧主菜单顺序 2022-05-12 11:04:37 +08:00
刘祥超
363295e0ea 增加edge-admin [dev|prod]两个命令 2022-05-11 21:39:31 +08:00
刘祥超
611d5daf27 升级部分库 2022-05-09 15:51:14 +08:00
刘祥超
0c1e42078e 集群节点列表可以使用“未分组”筛选 2022-05-08 19:32:55 +08:00
刘祥超
c9acafd3ad fix typo 2022-05-08 19:32:05 +08:00
刘祥超
75dd760148 阿里云DNS增加区域ID 2022-05-07 20:59:38 +08:00
刘祥超
28bfbbfa68 DNS服务商增加厂家筛选 2022-05-07 20:41:20 +08:00
刘祥超
36326697d7 创建网站服务时强制填写域名/优化源站未填写时交互 2022-05-07 20:26:40 +08:00
刘祥超
34b7cfec6f 域名设置增加说明文字 2022-05-07 20:01:29 +08:00
刘祥超
f65b725b27 修复缓存条件设置时界面可能不会自动刷新的问题 2022-05-05 11:25:23 +08:00
刘祥超
d7bceb8f2d 路由规则可以单独设置UAM(仅企业版可用) 2022-05-04 20:31:58 +08:00
刘祥超
549f418b69 节点增加DNS解析库类型设置 2022-05-04 16:41:28 +08:00
刘祥超
8a95f49f8f 改进文字提示 2022-04-29 08:28:07 +08:00
刘祥超
2c269a87a6 syn flood封禁时间从4位延长到8位 2022-04-27 16:09:15 +08:00
刘祥超
c17a27b7bf 版本修改为0.4.8 2022-04-25 11:11:52 +08:00
334 changed files with 7234 additions and 5059 deletions

3
build/.gitignore vendored
View File

@@ -1 +1,2 @@
edge-api/
edge-api/
build-all-test.sh

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
function build() {
ROOT=$(dirname $0)
ROOT=$(dirname "$0")
JS_ROOT=$ROOT/../web/public/js
NAME="edge-admin"
DIST=$ROOT/"../dist/${NAME}"
@@ -9,15 +9,15 @@ function build() {
ARCH=${2}
TAG=${3}
if [ -z $OS ]; then
if [ -z "$OS" ]; then
echo "usage: build.sh OS ARCH"
exit
fi
if [ -z $ARCH ]; then
if [ -z "$ARCH" ]; then
echo "usage: build.sh OS ARCH"
exit
fi
if [ -z $TAG ]; then
if [ -z "$TAG" ]; then
TAG="community"
fi
@@ -25,7 +25,7 @@ function build() {
echo "checking required commands ..."
commands=("zip" "unzip" "go" "find" "sed")
for cmd in "${commands[@]}"; do
if [ `which ${cmd}` ]; then
if [ "$(which "${cmd}")" ]; then
echo "checking ${cmd}: ok"
else
echo "checking ${cmd}: not found"
@@ -33,49 +33,49 @@ function build() {
fi
done
VERSION=$(lookup-version $ROOT/../internal/const/const.go)
VERSION=$(lookup-version "$ROOT"/../internal/const/const.go)
ZIP="${NAME}-${OS}-${ARCH}-${TAG}-v${VERSION}.zip"
# build edge-api
APINodeVersion=$(lookup-version $ROOT"/../../EdgeAPI/internal/const/const.go")
APINodeVersion=$(lookup-version "$ROOT""/../../EdgeAPI/internal/const/const.go")
echo "building edge-api v${APINodeVersion} ..."
EDGE_API_BUILD_SCRIPT=$ROOT"/../../EdgeAPI/build/build.sh"
if [ ! -f $EDGE_API_BUILD_SCRIPT ]; then
if [ ! -f "$EDGE_API_BUILD_SCRIPT" ]; then
echo "unable to find edge-api build script 'EdgeAPI/build/build.sh'"
exit
fi
cd $ROOT"/../../EdgeAPI/build"
cd "$ROOT""/../../EdgeAPI/build" || exit
echo "=============================="
./build.sh $OS $ARCH $TAG
./build.sh "$OS" "$ARCH" $TAG
echo "=============================="
cd -
cd - || exit
# generate files
echo "generating files ..."
go run -tags $TAG $ROOT/../cmd/edge-admin/main.go generate
if [ `which uglifyjs` ]; then
go run -tags $TAG "$ROOT"/../cmd/edge-admin/main.go generate
if [ "$(which uglifyjs)" ]; then
echo "compress to component.js ..."
uglifyjs --compress --mangle -- ${JS_ROOT}/components.src.js > ${JS_ROOT}/components.js
uglifyjs --compress --mangle -- "${JS_ROOT}"/components.src.js > "${JS_ROOT}"/components.js
else
echo "copy to component.js ..."
cp ${JS_ROOT}/components.src.js ${JS_ROOT}/components.js
cp "${JS_ROOT}"/components.src.js "${JS_ROOT}"/components.js
fi
# create dir & copy files
echo "copying ..."
if [ ! -d $DIST ]; then
mkdir $DIST
mkdir $DIST/bin
mkdir $DIST/configs
mkdir $DIST/logs
if [ ! -d "$DIST" ]; then
mkdir "$DIST"
mkdir "$DIST"/bin
mkdir "$DIST"/configs
mkdir "$DIST"/logs
fi
cp -R $ROOT/../web $DIST/
rm -f $DIST/web/tmp/*
rm -rf $DIST/web/public/js/components
rm -f $DIST/web/public/js/components.src.js
cp $ROOT/configs/server.template.yaml $DIST/configs/
cp -R "$ROOT"/../web "$DIST"/
rm -f "$DIST"/web/tmp/*
rm -rf "$DIST"/web/public/js/components
rm -f "$DIST"/web/public/js/components.src.js
cp "$ROOT"/configs/server.template.yaml "$DIST"/configs/
# change _plus.[ext] to .[ext]
if [ "${TAG}" = "plus" ]; then
@@ -83,30 +83,30 @@ function build() {
exts=("html" "js" "css")
for ext in "${exts[@]}"; do
pattern="*_plus."${ext}
find $DIST/web/views -type f -name $pattern | \
find "$DIST"/web/views -type f -name "$pattern" | \
while read filename; do
mv ${filename} "${filename/_plus."${ext}"/."${ext}"}"
mv "${filename}" "${filename/_plus."${ext}"/."${ext}"}"
done
done
fi
EDGE_API_ZIP_FILE=$ROOT"/../../EdgeAPI/dist/edge-api-${OS}-${ARCH}-${TAG}-v${APINodeVersion}.zip"
cp $EDGE_API_ZIP_FILE $DIST/
cd $DIST/
unzip -q $(basename $EDGE_API_ZIP_FILE)
rm -f $(basename $EDGE_API_ZIP_FILE)
cd -
cp "$EDGE_API_ZIP_FILE" "$DIST"/
cd "$DIST"/ || exit
unzip -q "$(basename "$EDGE_API_ZIP_FILE")"
rm -f "$(basename "$EDGE_API_ZIP_FILE")"
cd - || exit
# build
echo "building "${NAME}" ..."
env GOOS=$OS GOARCH=$ARCH go build -tags $TAG -ldflags="-s -w" -o $DIST/bin/${NAME} $ROOT/../cmd/edge-admin/main.go
echo "building ${NAME} ..."
env GOOS="$OS" GOARCH="$ARCH" go build -trimpath -tags $TAG -ldflags="-s -w" -o "$DIST"/bin/${NAME} "$ROOT"/../cmd/edge-admin/main.go
# delete hidden files
find $DIST -name ".DS_Store" -delete
find $DIST -name ".gitignore" -delete
find $DIST -name "*.less" -delete
find $DIST -name "*.css.map" -delete
find $DIST -name "*.js.map" -delete
find "$DIST" -name ".DS_Store" -delete
find "$DIST" -name ".gitignore" -delete
find "$DIST" -name "*.less" -delete
find "$DIST" -name "*.css.map" -delete
find "$DIST" -name "*.js.map" -delete
# zip
echo "zip files ..."
@@ -123,15 +123,15 @@ function build() {
function lookup-version() {
FILE=$1
VERSION_DATA=$(cat $FILE)
VERSION_DATA=$(cat "$FILE")
re="Version[ ]+=[ ]+\"([0-9.]+)\""
if [[ $VERSION_DATA =~ $re ]]; then
VERSION=${BASH_REMATCH[1]}
echo $VERSION
echo "$VERSION"
else
echo "could not match version"
exit
fi
}
build $1 $2 $3
build "$1" "$2" "$3"

View File

@@ -18,14 +18,19 @@ func main() {
Version(teaconst.Version).
Product(teaconst.ProductName).
Usage(teaconst.ProcessName+" [-v|start|stop|restart|service|daemon|reset|recover|demo]").
Usage(teaconst.ProcessName+" [dev|prod]").
Option("-h", "show this help").
Option("-v", "show version").
Option("start", "start the service").
Option("stop", "stop the service").
Option("restart", "restart the service").
Option("service", "register service into systemd").
Option("daemon", "start the service with daemon").
Option("reset", "reset configs").
Option("recover", "enter recovery mode")
Option("recover", "enter recovery mode").
Option("demo", "switch to demo mode").
Option("dev", "switch to 'dev' mode").
Option("prod", "switch to 'prod' mode")
app.On("daemon", func() {
nodes.NewAdminNode().Daemon()
@@ -84,6 +89,32 @@ func main() {
return
}
})
app.On("dev", func() {
var env = "dev"
var sock = gosock.NewTmpSock(teaconst.ProcessName)
_, err := sock.Send(&gosock.Command{
Code: env,
Params: nil,
})
if err != nil {
fmt.Println("failed to switch to '" + env + "': " + err.Error())
} else {
fmt.Println("switch to '" + env + "' ok")
}
})
app.On("prod", func() {
var env = "prod"
var sock = gosock.NewTmpSock(teaconst.ProcessName)
_, err := sock.Send(&gosock.Command{
Code: env,
Params: nil,
})
if err != nil {
fmt.Println("failed to switch to '" + env + "': " + err.Error())
} else {
fmt.Println("switch to '" + env + "' ok")
}
})
app.Run(func() {
adminNode := nodes.NewAdminNode()
adminNode.Run()

2
dist/.gitignore vendored
View File

@@ -1,2 +1,2 @@
*.zip
shield-admin
edge-admin

34
go.mod
View File

@@ -1,6 +1,6 @@
module github.com/TeaOSLab/EdgeAdmin
go 1.16
go 1.18
replace github.com/TeaOSLab/EdgeCommon => ../EdgeCommon
@@ -8,17 +8,37 @@ require (
github.com/TeaOSLab/EdgeCommon v0.0.0-00010101000000-000000000000
github.com/cespare/xxhash v1.1.0
github.com/go-sql-driver/mysql v1.5.0
github.com/google/go-cmp v0.5.6 // indirect
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475
github.com/iwind/gosock v0.0.0-20211103081026-ee4652210ca4
github.com/json-iterator/go v1.1.12 // indirect
github.com/miekg/dns v1.1.35
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/miekg/dns v1.1.43
github.com/shirou/gopsutil/v3 v3.22.5
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/tealeg/xlsx/v3 v3.2.3
github.com/xlzd/gotp v0.0.0-20181030022105-c8557ba2c119
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad
google.golang.org/grpc v1.45.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)
require (
github.com/frankban/quicktest v1.11.3 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/btree v1.0.0 // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kr/pretty v0.2.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/rogpeppe/fastuuid v1.2.0 // indirect
github.com/shabbyrobe/xmlwriter v0.0.0-20200208144257-9fca06d00ffa // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
golang.org/x/text v0.3.7 // indirect
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)

63
go.sum
View File

@@ -11,7 +11,6 @@ github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiU
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
@@ -20,6 +19,7 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -30,12 +30,15 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/frankban/quicktest v1.5.0 h1:Tb4jWdSpdjKzTUicPnY61PZxKbDoGa7ABbrReT3gQVY=
github.com/frankban/quicktest v1.5.0/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o=
github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-redis/redis/v8 v8.0.0-beta.7/go.mod h1:FGJAWDWFht1sQ4qxyJHZZbVyvnVcKQN0E3u5/5lRz+g=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
@@ -62,18 +65,15 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/iwind/TeaGo v0.0.0-20210628135026-38575a4ab060/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
github.com/iwind/TeaGo v0.0.0-20211026123858-7de7a21cad24 h1:1cGulkD2SNJJRok5OKwyhP/Ddm+PgSWKOupn0cR36/A=
github.com/iwind/TeaGo v0.0.0-20211026123858-7de7a21cad24/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
github.com/iwind/TeaGo v0.0.0-20220304042834-d8b5103e9027 h1:4knh28YgldmEtu8QG8pgQhUaI3i//qRjOdEyj9OVqXA=
github.com/iwind/TeaGo v0.0.0-20220304042834-d8b5103e9027/go.mod h1:IyKPaIhjbjsTctPguMWJZDHuBHu+XiYcV5ZEDxQpq94=
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475 h1:EseyfFaQOjWanGiby9KMw7PjDBMg/95tLDgIw/ns0Cw=
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
github.com/iwind/gosock v0.0.0-20211103081026-ee4652210ca4 h1:VWGsCqTzObdlbf7UUE3oceIpcEKi4C/YBUszQXk118A=
@@ -81,20 +81,22 @@ github.com/iwind/gosock v0.0.0-20211103081026-ee4652210ca4/go.mod h1:H5Q7SXwbx3a
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/miekg/dns v1.1.35 h1:oTfOaDH+mZkdcgdIjH6yBajRGtIwcwcaR+rt23ZSrJs=
github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -111,11 +113,15 @@ github.com/pkg/profile v1.5.0 h1:042Buzk+NhDI+DeSAA62RwJL8VAuZUMQZUjCsRz1Mug=
github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/shabbyrobe/xmlwriter v0.0.0-20200208144257-9fca06d00ffa h1:2cO3RojjYl3hVTbEvJVqrMaFmORhL6O06qdW42toftk=
github.com/shabbyrobe/xmlwriter v0.0.0-20200208144257-9fca06d00ffa/go.mod h1:Yjr3bdWaVWyME1kha7X0jsz3k2DgXNa1Pj3XGyUAbx8=
github.com/shirou/gopsutil/v3 v3.22.5 h1:atX36I/IXgFiB81687vSiBI5zrMsxcIBkP9cQMJQoJA=
github.com/shirou/gopsutil/v3 v3.22.5/go.mod h1:so9G9VzeHt/hsd0YwqprnjHnfARAUktauykSbr+y2gA=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
@@ -124,17 +130,21 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tealeg/xlsx/v3 v3.2.3 h1:MXnVh+9Y8cUglowItTy2HL3Kv6z+q/0aNjeKuTsVqZQ=
github.com/tealeg/xlsx/v3 v3.2.3/go.mod h1:0hGmAEoZ48SS1ZAE6eqZJkJVXgOMY+8a33vjXa8S8HA=
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/xlzd/gotp v0.0.0-20181030022105-c8557ba2c119 h1:YyPWX3jLOtYKulBR6AScGIs74lLrJcgeKRwcbAuQOG4=
github.com/xlzd/gotp v0.0.0-20181030022105-c8557ba2c119/go.mod h1:/nuTSlK+okRfR/vnIPqR89fFKonnWPiZymN5ydRJkX8=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.opentelemetry.io/otel v0.7.0/go.mod h1:aZMyHG5TqDOXEgH2tyLiXSUKly1jT3yqE9PmrzIeCdo=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -158,6 +168,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
@@ -175,7 +186,7 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -183,14 +194,16 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -204,11 +217,9 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -217,8 +228,6 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98
google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20220303160752-862486edd9cc h1:fb/ViRpv3ln/LvbqZtTpoOd1YQDNH12gaGZreoSFovE=
google.golang.org/genproto v0.0.0-20220303160752-862486edd9cc/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e h1:fNKDNuUyC4WH+inqDMpfXDdfvwfYILbsX+oskGZ8hxg=
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -228,8 +237,6 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg=
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
@@ -247,8 +254,9 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -256,10 +264,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -18,7 +18,7 @@ import (
type AppCmd struct {
product string
version string
usage string
usages []string
options []*CommandHelpOption
appendStrings []string
@@ -52,7 +52,7 @@ func (this *AppCmd) Version(version string) *AppCmd {
// Usage 使用方法
func (this *AppCmd) Usage(usage string) *AppCmd {
this.usage = usage
this.usages = append(this.usages, usage)
return this
}
@@ -75,8 +75,10 @@ func (this *AppCmd) Append(appendString string) *AppCmd {
func (this *AppCmd) Print() {
fmt.Println(this.product + " v" + this.version)
usage := this.usage
fmt.Println("Usage:", "\n "+usage)
fmt.Println("Usage:")
for _, usage := range this.usages {
fmt.Println(" " + usage)
}
if len(this.options) > 0 {
fmt.Println("")

View File

@@ -84,10 +84,13 @@ func loadUserUIConfig() (*systemconfigs.UserUIConfig, error) {
func defaultUserUIConfig() *systemconfigs.UserUIConfig {
return &systemconfigs.UserUIConfig{
ProductName: "GoEdge",
UserSystemName: "GoEdge用户系统",
ShowOpenSourceInfo: true,
ShowVersion: true,
ShowFinance: true,
ProductName: "GoEdge",
UserSystemName: "GoEdge用户系统",
ShowOpenSourceInfo: true,
ShowVersion: true,
ShowFinance: true,
BandwidthUnit: systemconfigs.BandwidthUnitBit,
ShowBandwidthCharts: true,
ShowTrafficCharts: true,
}
}

View File

@@ -1,5 +1,5 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
// +build community
// +build !plus
package teaconst

View File

@@ -1,9 +1,9 @@
package teaconst
const (
Version = "0.4.7.1"
Version = "0.4.9"
APINodeVersion = "0.4.7"
APINodeVersion = "0.4.9"
ProductName = "Edge Admin"
ProcessName = "edge-admin"

View File

@@ -1,6 +1,6 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build community
// +build community
//go:build !plus
// +build !plus
package teaconst

View File

@@ -41,7 +41,7 @@ func (this *AdminNode) Run() {
SharedAdminNode = this
// 启动管理界面
secret := this.genSecret()
var secret = this.genSecret()
configs.Secret = secret
// 本地Sock
@@ -382,6 +382,12 @@ func (this *AdminNode) listenSock() error {
"path": exePath,
},
})
case "dev": // 切换到dev
Tea.Env = Tea.EnvDev
_ = cmd.ReplyOk()
case "prod": // 切换到prod
Tea.Env = Tea.EnvProd
_ = cmd.ReplyOk()
}
})

View File

@@ -219,6 +219,14 @@ func (this *RPCClient) HTTPCachePolicyRPC() pb.HTTPCachePolicyServiceClient {
return pb.NewHTTPCachePolicyServiceClient(this.pickConn())
}
func (this *RPCClient) HTTPCacheTaskRPC() pb.HTTPCacheTaskServiceClient {
return pb.NewHTTPCacheTaskServiceClient(this.pickConn())
}
func (this *RPCClient) HTTPCacheTaskKeyRPC() pb.HTTPCacheTaskKeyServiceClient {
return pb.NewHTTPCacheTaskKeyServiceClient(this.pickConn())
}
func (this *RPCClient) HTTPFirewallPolicyRPC() pb.HTTPFirewallPolicyServiceClient {
return pb.NewHTTPFirewallPolicyServiceClient(this.pickConn())
}
@@ -344,6 +352,14 @@ func (this *RPCClient) RegionProvinceRPC() pb.RegionProvinceServiceClient {
return pb.NewRegionProvinceServiceClient(this.pickConn())
}
func (this *RPCClient) RegionCityRPC() pb.RegionCityServiceClient {
return pb.NewRegionCityServiceClient(this.pickConn())
}
func (this *RPCClient) RegionProviderRPC() pb.RegionProviderServiceClient {
return pb.NewRegionProviderServiceClient(this.pickConn())
}
func (this *RPCClient) LogRPC() pb.LogServiceClient {
return pb.NewLogServiceClient(this.pickConn())
}

View File

@@ -134,3 +134,23 @@ func NextIP(prevIP net.IP) net.IP {
}
return ip
}
// IsLocalIP 判断是否为本地IP
// ip 是To4()或者To16()的结果
func IsLocalIP(ip net.IP) bool {
if ip == nil {
return false
}
if ip[0] == 127 ||
ip[0] == 10 ||
(ip[0] == 172 && ip[1]&0xf0 == 16) ||
(ip[0] == 192 && ip[1] == 168) {
return true
}
if ip.String() == "::1" {
return true
}
return false
}

View File

@@ -1,6 +1,6 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build community
// +build community
//go:build !plus
// +build !plus
package nodelogutils

View File

@@ -3,7 +3,7 @@
package sizes_test
import (
"github.com/TeaOSLab/EdgeNode/internal/utils/sizes"
"github.com/TeaOSLab/EdgeAdmin/internal/utils/sizes"
"github.com/iwind/TeaGo/assert"
"testing"
)

View File

@@ -1,6 +1,6 @@
package actionutils
// 子菜单定义
// Menu 子菜单定义
type Menu struct {
Id string `json:"id"`
Name string `json:"name"`
@@ -11,14 +11,14 @@ type Menu struct {
CountNormalItems int `json:"countNormalItems"`
}
// 获取新对象
// NewMenu 获取新对象
func NewMenu() *Menu {
return &Menu{
Items: []*MenuItem{},
}
}
// 添加菜单项
// Add 添加菜单项
func (this *Menu) Add(name string, subName string, url string, isActive bool) *MenuItem {
item := &MenuItem{
Name: name,
@@ -36,7 +36,7 @@ func (this *Menu) Add(name string, subName string, url string, isActive bool) *M
return item
}
// 添加特殊菜单项,不计数
// AddSpecial 添加特殊菜单项,不计数
func (this *Menu) AddSpecial(name string, subName string, url string, isActive bool) *MenuItem {
item := this.Add(name, subName, url, isActive)
this.CountNormalItems--

View File

@@ -5,20 +5,20 @@ import (
"github.com/iwind/TeaGo/lists"
)
// 菜单分组
// MenuGroup 菜单分组
type MenuGroup struct {
Menus []*Menu `json:"menus"`
AlwaysMenu *Menu `json:"alwaysMenu"`
}
// 获取新菜单分组对象
// NewMenuGroup 获取新菜单分组对象
func NewMenuGroup() *MenuGroup {
return &MenuGroup{
Menus: []*Menu{},
}
}
// 查找菜单,如果找不到则自动创建
// FindMenu 查找菜单,如果找不到则自动创建
func (this *MenuGroup) FindMenu(menuId string, menuName string) *Menu {
for _, m := range this.Menus {
if m.Id == menuId {
@@ -33,7 +33,7 @@ func (this *MenuGroup) FindMenu(menuId string, menuName string) *Menu {
return menu
}
// 排序
// Sort 排序
func (this *MenuGroup) Sort() {
lists.Sort(this.Menus, func(i int, j int) bool {
menu1 := this.Menus[i]
@@ -42,7 +42,7 @@ func (this *MenuGroup) Sort() {
})
}
// 设置子菜单
// SetSubMenu 设置子菜单
func SetSubMenu(action actions.ActionWrapper, menu *MenuGroup) {
action.Object().Data["teaSubMenus"] = menu
}

View File

@@ -1,6 +1,6 @@
package actionutils
// 菜单项
// MenuItem 菜单项
type MenuItem struct {
Id string `json:"id"`
Name string `json:"name"`

View File

@@ -127,7 +127,7 @@ func (this *Page) AsHTML() string {
return `<div class="page">` + strings.Join(result, "") + `</div>`
}
// 判断是否为最后一页
// IsLastPage 判断是否为最后一页
func (this *Page) IsLastPage() bool {
return this.Current == this.Max
}

View File

@@ -5,19 +5,19 @@ import (
"github.com/iwind/TeaGo/maps"
)
// Tabbar定义
// Tabbar Tabbar定义
type Tabbar struct {
items []maps.Map
}
// 获取新对象
// NewTabbar 获取新对象
func NewTabbar() *Tabbar {
return &Tabbar{
items: []maps.Map{},
}
}
// 添加菜单项
// Add 添加菜单项
func (this *Tabbar) Add(name string, subName string, url string, icon string, active bool) maps.Map {
m := maps.Map{
"name": name,
@@ -31,12 +31,12 @@ func (this *Tabbar) Add(name string, subName string, url string, icon string, ac
return m
}
// 取得所有的Items
// Items 取得所有的Items
func (this *Tabbar) Items() []maps.Map {
return this.items
}
// 设置子菜单
// SetTabbar 设置子菜单
func SetTabbar(action actions.ActionWrapper, tabbar *Tabbar) {
action.Object().Data["teaTabbar"] = tabbar.Items()
}

View File

@@ -1,11 +1,18 @@
package actionutils
import (
"encoding/json"
"errors"
"fmt"
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
rpcerrors "github.com/TeaOSLab/EdgeCommon/pkg/rpc/errors"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/logs"
"github.com/iwind/TeaGo/maps"
"io/ioutil"
"net"
"net/http"
"os"
"path/filepath"
@@ -24,24 +31,78 @@ func Fail(action actions.ActionWrapper, err error) {
// FailPage 提示页面错误信息
func FailPage(action actions.ActionWrapper, err error) {
if err != nil {
logs.Println("[" + reflect.TypeOf(action).String() + "]" + findStack(err.Error()))
if err == nil {
err = errors.New("unknown error")
}
err = rpcerrors.HumanError(err)
logs.Println("[" + reflect.TypeOf(action).String() + "]" + findStack(err.Error()))
// 当前API终端地址
var apiEndpoints = []string{}
apiConfig, apiConfigErr := configs.LoadAPIConfig()
if apiConfigErr == nil && apiConfig != nil {
apiEndpoints = append(apiEndpoints, apiConfig.RPC.Endpoints...)
}
var isRPCConnError bool
err, isRPCConnError = rpcerrors.HumanError(err, apiEndpoints, Tea.ConfigFile("api.yaml"))
action.Object().ResponseWriter.WriteHeader(http.StatusInternalServerError)
if len(action.Object().Request.Header.Get("X-Requested-With")) > 0 {
action.Object().WriteString(teaconst.ErrServer)
} else {
action.Object().WriteString(`<!DOCTYPE html>
// 本地的一些错误提示
var isLocalAPI = false
if isRPCConnError {
host, _, hostErr := net.SplitHostPort(action.Object().Request.Host)
if hostErr == nil {
for _, endpoint := range apiEndpoints {
if strings.HasPrefix(endpoint, "http://"+host) || strings.HasPrefix(endpoint, "https://"+host) || strings.HasPrefix(endpoint, host) {
isLocalAPI = true
break
}
}
}
}
var issuesHTML = ""
if isLocalAPI {
// 读取本地API节点的issues
issuesData, issuesErr := ioutil.ReadFile(Tea.Root + "/edge-api/logs/issues.log")
if issuesErr == nil {
var issueMaps = []maps.Map{}
issuesErr = json.Unmarshal(issuesData, &issueMaps)
if issuesErr == nil && len(issueMaps) > 0 {
var issueMap = issueMaps[0]
issuesHTML = "本地API节点启动错误" + issueMap.GetString("message") + ",处理建议:" + issueMap.GetString("suggestion")
}
}
}
var html = `<!DOCTYPE html>
<html>
<head></head>
<head>
<title>有系统错误需要处理</title>
<meta charset="UTF-8"/>
<style type="text/css">
hr { border-top: 1px #ccc solid; }
.red { color: red; }
</style>
</head>
<body>
<div style="background: #eee; border: 1px #ccc solid; padding: 10px; font-size: 12px; line-height: 1.8">
` + teaconst.ErrServer + `
<div>可以通过查看 <strong><em>$安装目录/logs/run.log</em></strong> 日志文件查看具体的错误提示。</div>
<hr style="border-top: 1px #ccc solid"/>
<div style="color: red">Error: ` + err.Error() + `</pre>
</div>
<div>可以通过查看 <strong><em>$安装目录/logs/run.log</em></strong> 日志文件查看具体的错误提示。</div>
<hr/>
<div class="red">Error: ` + err.Error() + `</div>`
if len(issuesHTML) > 0 {
html += ` <hr/>
<div class="red">` + issuesHTML + `</div>`
}
action.Object().WriteString(html + `
</div>
</body>
</html>`)
}

View File

@@ -5,10 +5,10 @@ import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/groups"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/settings/cache"
ddosProtection "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/settings/ddos-protection"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/settings/dns"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/settings/ssh"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/settings/system"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/settings/thresholds"
clusters "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/clusterutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
@@ -55,7 +55,8 @@ func init() {
GetPost("/settings/system", new(system.IndexAction)).
GetPost("/settings/ssh", new(ssh.IndexAction)).
GetPost("/settings/ssh/test", new(ssh.TestAction)).
GetPost("/settings/thresholds", new(thresholds.IndexAction)).
GetPost("/settings/ddos-protection", new(ddosProtection.IndexAction)).
Post("/settings/ddos-protection/status", new(ddosProtection.StatusAction)).
// 分组相关
Prefix("/clusters/cluster/groups").

View File

@@ -11,6 +11,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
"time"
)
@@ -198,6 +199,8 @@ func (this *DetailAction) RunGet(params struct {
// 运行状态
var status = &nodeconfigs.NodeStatus{}
this.Data["nodeDatetime"] = ""
this.Data["nodeTimeDiff"] = 0
if len(node.StatusJSON) > 0 {
err = json.Unmarshal(node.StatusJSON, &status)
if err != nil {
@@ -205,6 +208,19 @@ func (this *DetailAction) RunGet(params struct {
return
}
status.IsActive = status.IsActive && time.Now().Unix()-status.UpdatedAt <= 60 // N秒之内认为活跃
if status.Timestamp > 0 {
this.Data["nodeDatetime"] = timeutil.FormatTime("Y-m-d H:i:s", status.Timestamp)
if status.UpdatedAt > 0 {
var diff = status.UpdatedAt - status.Timestamp
if diff < 0 {
diff = -diff
}
this.Data["nodeTimeDiff"] = diff
}
} else if status.UpdatedAt > 0 {
this.Data["nodeDatetime"] = timeutil.FormatTime("Y-m-d H:i:s", status.UpdatedAt)
}
}
// 检查是否有新版本

View File

@@ -4,7 +4,6 @@ package nodeutils
import (
"errors"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
@@ -24,6 +23,11 @@ func InitNodeInfo(parentAction *actionutils.ParentAction, nodeId int64) (*pb.Nod
}
var node = nodeResp.Node
info, err := parentAction.RPC().NodeRPC().FindEnabledNodeConfigInfo(parentAction.AdminContext(), &pb.FindEnabledNodeConfigInfoRequest{NodeId: nodeId})
if err != nil {
return nil, err
}
var groupMap maps.Map
if node.NodeGroup != nil {
groupMap = maps.Map{
@@ -61,38 +65,38 @@ func InitNodeInfo(parentAction *actionutils.ParentAction, nodeId int64) (*pb.Nod
"name": "DNS设置",
"url": prefix + "/settings/dns?" + query,
"isActive": menuItem == "dns",
"isOn": len(node.DnsRoutes) > 0,
"isOn": info.HasDNSInfo,
},
{
"name": "缓存设置",
"url": prefix + "/settings/cache?" + query,
"isActive": menuItem == "cache",
"isOn": len(node.CacheDiskDir) > 0 ||
(node.MaxCacheDiskCapacity != nil && node.MaxCacheDiskCapacity.Count > 0) ||
(node.MaxCacheMemoryCapacity != nil && node.MaxCacheMemoryCapacity.Count > 0),
"isOn": info.HasCacheInfo,
},
{
"name": "DDoS防护",
"url": prefix + "/settings/ddos-protection?" + query,
"isActive": menuItem == "ddosProtection",
"isOn": info.HasDDoSProtection,
},
{
"name": "-",
"url": "",
},
}
if teaconst.IsPlus {
menuItems = append(menuItems, []maps.Map{
{
"name": "阈值设置",
"url": prefix + "/settings/thresholds?" + query,
"isActive": menuItem == "threshold",
},
}...)
}
menuItems = filterMenuItems(menuItems, menuItem, prefix, query, info)
menuItems = append(menuItems, []maps.Map{
{
"name": "SSH设置",
"url": prefix + "/settings/ssh?" + query,
"isActive": menuItem == "ssh",
"isOn": node.NodeLogin != nil,
"isOn": info.HasSSH,
},
{
"name": "系统设置",
"url": prefix + "/settings/system?" + query,
"isActive": menuItem == "system",
"isOn": node.MaxCPU > 0,
"isOn": info.HasSystemSettings,
},
}...)
parentAction.Data["leftMenuItems"] = menuItems

View File

@@ -0,0 +1,14 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build !plus
// +build !plus
package nodeutils
import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
func filterMenuItems(menuItems []maps.Map, menuItem string, prefix string, query string, info *pb.FindEnabledNodeConfigInfoResponse) []maps.Map {
return menuItems
}

View File

@@ -0,0 +1,133 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package ddosProtection
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/nodeutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/types"
"net"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "node", "update")
this.SecondMenu("ddosProtection")
}
func (this *IndexAction) RunGet(params struct {
ClusterId int64
NodeId int64
}) {
_, err := nodeutils.InitNodeInfo(this.Parent(), params.NodeId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["nodeId"] = params.NodeId
// 集群设置
clusterProtectionResp, err := this.RPC().NodeClusterRPC().FindNodeClusterDDoSProtection(this.AdminContext(), &pb.FindNodeClusterDDoSProtectionRequest{NodeClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return
}
var clusterDDoSProtectionIsOn = false
if len(clusterProtectionResp.DdosProtectionJSON) > 0 {
var clusterDDoSProtection = &ddosconfigs.ProtectionConfig{}
err = json.Unmarshal(clusterProtectionResp.DdosProtectionJSON, clusterDDoSProtection)
if err != nil {
this.ErrorPage(err)
return
}
clusterDDoSProtectionIsOn = clusterDDoSProtection.IsOn()
}
this.Data["clusterDDoSProtectionIsOn"] = clusterDDoSProtectionIsOn
// 节点设置
ddosProtectionResp, err := this.RPC().NodeRPC().FindNodeDDoSProtection(this.AdminContext(), &pb.FindNodeDDoSProtectionRequest{NodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
var ddosProtectionConfig = ddosconfigs.DefaultProtectionConfig()
if len(ddosProtectionResp.DdosProtectionJSON) > 0 {
err = json.Unmarshal(ddosProtectionResp.DdosProtectionJSON, ddosProtectionConfig)
if err != nil {
this.ErrorPage(err)
return
}
}
this.Data["config"] = ddosProtectionConfig
this.Data["defaultConfigs"] = nodeconfigs.DefaultConfigs
this.Show()
}
func (this *IndexAction) RunPost(params struct {
NodeId int64
DdosProtectionJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo("修改节点 %d 的DDOS防护设置", params.NodeId)
var ddosProtectionConfig = &ddosconfigs.ProtectionConfig{}
err := json.Unmarshal(params.DdosProtectionJSON, ddosProtectionConfig)
if err != nil {
this.ErrorPage(err)
return
}
err = ddosProtectionConfig.Init()
if err != nil {
this.Fail("配置校验失败:" + err.Error())
}
// 校验参数
if ddosProtectionConfig.TCP != nil {
var tcpConfig = ddosProtectionConfig.TCP
if tcpConfig.MaxConnectionsPerIP > 0 && tcpConfig.MaxConnectionsPerIP < nodeconfigs.DefaultTCPMinConnectionsPerIP {
this.FailField("tcpMaxConnectionsPerIP", "TCP: 单IP TCP最大连接数不能小于"+types.String(nodeconfigs.DefaultTCPMinConnectionsPerIP))
}
if tcpConfig.NewConnectionsRate > 0 && tcpConfig.NewConnectionsRate < nodeconfigs.DefaultTCPNewConnectionsMinRate {
this.FailField("tcpNewConnectionsRate", "TCP: 单IP连接速率不能小于"+types.String(nodeconfigs.DefaultTCPNewConnectionsMinRate))
}
// Port
for _, portConfig := range tcpConfig.Ports {
if portConfig.Port > 65535 {
this.Fail("端口号" + types.String(portConfig.Port) + "不能大于65535")
}
}
// IP
for _, ipConfig := range tcpConfig.AllowIPList {
if net.ParseIP(ipConfig.IP) == nil {
this.Fail("白名单IP '" + ipConfig.IP + "' 格式错误")
}
}
}
_, err = this.RPC().NodeRPC().UpdateNodeDDoSProtection(this.AdminContext(), &pb.UpdateNodeDDoSProtectionRequest{
NodeId: params.NodeId,
DdosProtectionJSON: params.DdosProtectionJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,27 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package ddosProtection
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils"
"github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs"
)
type StatusAction struct {
actionutils.ParentAction
}
func (this *StatusAction) RunPost(params struct {
NodeId int64
}) {
results, err := nodeutils.SendMessageToNodeIds(this.AdminContext(), []int64{params.NodeId}, messageconfigs.MessageCodeCheckLocalFirewall, &messageconfigs.CheckLocalFirewallMessage{
Name: "nftables",
}, 10)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["results"] = results
this.Success()
}

View File

@@ -32,6 +32,8 @@ func (this *IndexAction) RunGet(params struct {
return
}
this.Data["hostIsAutoFilled"] = false
// 登录信息
var loginMap maps.Map = nil
if node.NodeLogin != nil {
@@ -79,6 +81,7 @@ func (this *IndexAction) RunGet(params struct {
return
}
if len(addressesResp.NodeIPAddresses) > 0 {
this.Data["hostIsAutoFilled"] = true
loginMap = maps.Map{
"id": 0,
"name": "",
@@ -100,6 +103,7 @@ func (this *IndexAction) RunGet(params struct {
return
}
if len(addressesResp.NodeIPAddresses) > 0 {
this.Data["hostIsAutoFilled"] = true
loginParams["host"] = addressesResp.NodeIPAddresses[0].Ip
}
}

View File

@@ -3,8 +3,10 @@
package system
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/nodeutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
@@ -32,6 +34,22 @@ func (this *IndexAction) RunGet(params struct {
var nodeMap = this.Data["node"].(maps.Map)
nodeMap["maxCPU"] = node.MaxCPU
// DNS
dnsResolverResp, err := this.RPC().NodeRPC().FindNodeDNSResolver(this.AdminContext(), &pb.FindNodeDNSResolverRequest{NodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
var dnsResolverConfig = nodeconfigs.DefaultDNSResolverConfig()
if len(dnsResolverResp.DnsResolverJSON) > 0 {
err = json.Unmarshal(dnsResolverResp.DnsResolverJSON, dnsResolverConfig)
if err != nil {
this.ErrorPage(err)
return
}
}
this.Data["dnsResolverConfig"] = dnsResolverConfig
this.Show()
}
@@ -39,6 +57,8 @@ func (this *IndexAction) RunPost(params struct {
NodeId int64
MaxCPU int32
DnsResolverJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
@@ -57,5 +77,26 @@ func (this *IndexAction) RunPost(params struct {
return
}
var dnsResolverConfig = nodeconfigs.DefaultDNSResolverConfig()
err = json.Unmarshal(params.DnsResolverJSON, dnsResolverConfig)
if err != nil {
this.ErrorPage(err)
return
}
err = dnsResolverConfig.Init()
if err != nil {
this.Fail("校验DNS解析配置失败" + err.Error())
}
_, err = this.RPC().NodeRPC().UpdateNodeDNSResolver(this.AdminContext(), &pb.UpdateNodeDNSResolverRequest{
NodeId: params.NodeId,
DnsResolverJSON: params.DnsResolverJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -11,7 +11,6 @@ import (
"github.com/iwind/TeaGo/logs"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"strconv"
"time"
)
@@ -238,7 +237,10 @@ func (this *NodesAction) RunGet(params struct {
return
}
for _, group := range groupsResp.NodeGroups {
countNodesInGroupResp, err := this.RPC().NodeRPC().CountAllEnabledNodesWithNodeGroupId(this.AdminContext(), &pb.CountAllEnabledNodesWithNodeGroupIdRequest{NodeGroupId: group.Id})
countNodesInGroupResp, err := this.RPC().NodeRPC().CountAllEnabledNodesMatch(this.AdminContext(), &pb.CountAllEnabledNodesMatchRequest{
NodeClusterId: params.ClusterId,
NodeGroupId: group.Id,
})
if err != nil {
this.ErrorPage(err)
return
@@ -246,7 +248,7 @@ func (this *NodesAction) RunGet(params struct {
countNodes := countNodesInGroupResp.Count
groupName := group.Name
if countNodes > 0 {
groupName += "(" + strconv.FormatInt(countNodes, 10) + ")"
groupName += "(" + types.String(countNodes) + ")"
}
groupMaps = append(groupMaps, maps.Map{
"id": group.Id,
@@ -254,6 +256,29 @@ func (this *NodesAction) RunGet(params struct {
"countNodes": countNodes,
})
}
// 是否有未分组
if len(groupMaps) > 0 {
countNodesInGroupResp, err := this.RPC().NodeRPC().CountAllEnabledNodesMatch(this.AdminContext(), &pb.CountAllEnabledNodesMatchRequest{
NodeClusterId: params.ClusterId,
NodeGroupId: -1,
})
if err != nil {
this.ErrorPage(err)
return
}
var countUngroupNodes = countNodesInGroupResp.Count
if countUngroupNodes > 0 {
groupMaps = append([]maps.Map{
{
"id": -1,
"name": "[未分组](" + types.String(countUngroupNodes) + ")",
"countNodes": countUngroupNodes,
},
}, groupMaps...)
}
}
this.Data["groups"] = groupMaps
// 所有区域

View File

@@ -0,0 +1,106 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package ddosProtection
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/types"
"net"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "")
this.SecondMenu("ddosProtection")
}
func (this *IndexAction) RunGet(params struct {
ClusterId int64
}) {
this.Data["clusterId"] = params.ClusterId
protectionResp, err := this.RPC().NodeClusterRPC().FindNodeClusterDDoSProtection(this.AdminContext(), &pb.FindNodeClusterDDoSProtectionRequest{NodeClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return
}
var ddosProtectionConfig = ddosconfigs.DefaultProtectionConfig()
if len(protectionResp.DdosProtectionJSON) > 0 {
err = json.Unmarshal(protectionResp.DdosProtectionJSON, ddosProtectionConfig)
if err != nil {
this.ErrorPage(err)
return
}
}
this.Data["config"] = ddosProtectionConfig
this.Data["defaultConfigs"] = nodeconfigs.DefaultConfigs
this.Show()
}
func (this *IndexAction) RunPost(params struct {
ClusterId int64
DdosProtectionJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo("修改集群 %d 的DDOS防护设置", params.ClusterId)
var ddosProtectionConfig = &ddosconfigs.ProtectionConfig{}
err := json.Unmarshal(params.DdosProtectionJSON, ddosProtectionConfig)
if err != nil {
this.ErrorPage(err)
return
}
err = ddosProtectionConfig.Init()
if err != nil {
this.Fail("配置校验失败:" + err.Error())
}
// 校验参数
if ddosProtectionConfig.TCP != nil {
var tcpConfig = ddosProtectionConfig.TCP
if tcpConfig.MaxConnectionsPerIP > 0 && tcpConfig.MaxConnectionsPerIP < nodeconfigs.DefaultTCPMinConnectionsPerIP {
this.FailField("tcpMaxConnectionsPerIP", "TCP: 单IP TCP最大连接数不能小于"+types.String(nodeconfigs.DefaultTCPMinConnectionsPerIP))
}
if tcpConfig.NewConnectionsRate > 0 && tcpConfig.NewConnectionsRate < nodeconfigs.DefaultTCPNewConnectionsMinRate {
this.FailField("tcpNewConnectionsRate", "TCP: 单IP连接速率不能小于"+types.String(nodeconfigs.DefaultTCPNewConnectionsMinRate))
}
// Port
for _, portConfig := range tcpConfig.Ports {
if portConfig.Port > 65535 {
this.Fail("端口号" + types.String(portConfig.Port) + "不能大于65535")
}
}
// IP
for _, ipConfig := range tcpConfig.AllowIPList {
if net.ParseIP(ipConfig.IP) == nil {
this.Fail("白名单IP '" + ipConfig.IP + "' 格式错误")
}
}
}
_, err = this.RPC().NodeClusterRPC().UpdateNodeClusterDDoSProtection(this.AdminContext(), &pb.UpdateNodeClusterDDoSProtectionRequest{
NodeClusterId: params.ClusterId,
DdosProtectionJSON: params.DdosProtectionJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,71 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package ddosProtection
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils"
"github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
"github.com/iwind/TeaGo/maps"
)
type StatusAction struct {
actionutils.ParentAction
}
func (this *StatusAction) Init() {
this.Nav("", "setting", "")
this.SecondMenu("ddosProtection")
}
func (this *StatusAction) RunGet(params struct {
ClusterId int64
}) {
this.Data["clusterId"] = params.ClusterId
this.Show()
}
func (this *StatusAction) RunPost(params struct {
ClusterId int64
}) {
results, err := nodeutils.SendMessageToCluster(this.AdminContext(), params.ClusterId, messageconfigs.MessageCodeCheckLocalFirewall, &messageconfigs.CheckLocalFirewallMessage{
Name: "nftables",
}, 10)
if err != nil {
this.ErrorPage(err)
return
}
var resultMaps = []maps.Map{}
for _, result := range results {
var resultMap = maps.Map{
"isOk": result.IsOK,
"message": result.Message,
"nodeId": result.NodeId,
"nodeName": result.NodeName,
}
nodeResp, err := this.RPC().NodeRPC().FindNodeDDoSProtection(this.AdminContext(), &pb.FindNodeDDoSProtectionRequest{NodeId: result.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
if len(nodeResp.DdosProtectionJSON) > 0 {
var ddosProtection = ddosconfigs.DefaultProtectionConfig()
err = json.Unmarshal(nodeResp.DdosProtectionJSON, ddosProtection)
if err != nil {
this.ErrorPage(err)
return
}
resultMap["isPrior"] = !ddosProtection.IsPriorEmpty()
}
resultMaps = append(resultMaps, resultMap)
}
this.Data["results"] = resultMaps
this.Success()
}

View File

@@ -52,6 +52,7 @@ func (this *IndexAction) RunGet(params struct {
this.Data["cnameRecords"] = dnsInfoResp.CnameRecords
}
this.Data["ttl"] = dnsInfoResp.Ttl
this.Data["cnameAsDomain"] = dnsInfoResp.CnameAsDomain
this.Show()
}
@@ -65,6 +66,9 @@ func (this *IndexAction) RunPost(params struct {
ServersAutoSync bool
CnameRecords []string
Ttl int32
CnameAsDomain bool
ConfirmResetDomain bool // 是否确认重置域名
Must *actions.Must
CSRF *actionutils.CSRF
@@ -72,13 +76,15 @@ func (this *IndexAction) RunPost(params struct {
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "修改集群 %d DNS设置", params.ClusterId)
if params.DnsDomainId <= 0 {
this.Fail("请选择集群的主域名")
}
if !params.ConfirmResetDomain {
if params.DnsDomainId <= 0 {
this.Fail("请选择集群的主域名")
}
params.Must.
Field("dnsName", params.DnsName).
Require("请输入DNS子域名")
params.Must.
Field("dnsName", params.DnsName).
Require("请输入DNS子域名")
}
// 检查DNS名称
if len(params.DnsName) > 0 {
@@ -108,6 +114,7 @@ func (this *IndexAction) RunPost(params struct {
ServersAutoSync: params.ServersAutoSync,
CnameRecords: params.CnameRecords,
Ttl: params.Ttl,
CnameAsDomain: params.CnameAsDomain,
})
if err != nil {
this.ErrorPage(err)

View File

@@ -66,34 +66,31 @@ func (this *IndexAction) RunGet(params struct {
this.Data["timeZoneLocation"] = nodeconfigs.FindTimeZoneLocation(cluster.TimeZone)
this.Data["cluster"] = maps.Map{
"id": cluster.Id,
"name": cluster.Name,
"installDir": cluster.InstallDir,
"timeZone": cluster.TimeZone,
"nodeMaxThreads": cluster.NodeMaxThreads,
"nodeTCPMaxConnections": cluster.NodeTCPMaxConnections,
"autoOpenPorts": cluster.AutoOpenPorts,
"id": cluster.Id,
"name": cluster.Name,
"installDir": cluster.InstallDir,
"timeZone": cluster.TimeZone,
"nodeMaxThreads": cluster.NodeMaxThreads,
"autoOpenPorts": cluster.AutoOpenPorts,
}
// 默认值
this.Data["defaultNodeMaxThreads"] = nodeconfigs.DefaultMaxThreads
this.Data["defaultNodeMaxThreadsMin"] = nodeconfigs.DefaultMaxThreadsMin
this.Data["defaultNodeMaxThreadsMax"] = nodeconfigs.DefaultMaxThreadsMax
this.Data["defaultNodeTCPMaxConnections"] = nodeconfigs.DefaultTCPMaxConnections
this.Show()
}
// RunPost 保存设置
func (this *IndexAction) RunPost(params struct {
ClusterId int64
Name string
GrantId int64
InstallDir string
TimeZone string
NodeMaxThreads int32
NodeTCPMaxConnections int32
AutoOpenPorts bool
ClusterId int64
Name string
GrantId int64
InstallDir string
TimeZone string
NodeMaxThreads int32
AutoOpenPorts bool
Must *actions.Must
}) {
@@ -112,14 +109,13 @@ func (this *IndexAction) RunPost(params struct {
}
_, err := this.RPC().NodeClusterRPC().UpdateNodeCluster(this.AdminContext(), &pb.UpdateNodeClusterRequest{
NodeClusterId: params.ClusterId,
Name: params.Name,
NodeGrantId: params.GrantId,
InstallDir: params.InstallDir,
TimeZone: params.TimeZone,
NodeMaxThreads: params.NodeMaxThreads,
NodeTCPMaxConnections: params.NodeTCPMaxConnections,
AutoOpenPorts: params.AutoOpenPorts,
NodeClusterId: params.ClusterId,
Name: params.Name,
NodeGrantId: params.GrantId,
InstallDir: params.InstallDir,
TimeZone: params.TimeZone,
NodeMaxThreads: params.NodeMaxThreads,
AutoOpenPorts: params.AutoOpenPorts,
})
if err != nil {
this.ErrorPage(err)

View File

@@ -3,13 +3,12 @@ package settings
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/cache"
ddosProtection "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/ddos-protection"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/dns"
firewallActions "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/firewall-actions"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/health"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/message"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/metrics"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/services"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/thresholds"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/toa"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/waf"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/webp"
@@ -41,12 +40,6 @@ func init() {
GetPost("", new(dns.IndexAction)).
Post("/randomName", new(dns.RandomNameAction)).
// 消息
Prefix("/clusters/cluster/settings/message").
GetPost("", new(message.IndexAction)).
Get("/selectReceiverPopup", new(message.SelectReceiverPopupAction)).
Post("/selectedReceivers", new(message.SelectedReceiversAction)).
// TOA
Prefix("/clusters/cluster/settings/toa").
GetPost("", new(toa.IndexAction)).
@@ -63,13 +56,6 @@ func init() {
GetPost("/updatePopup", new(firewallActions.UpdatePopupAction)).
Post("/delete", new(firewallActions.DeleteAction)).
// 阈值
Prefix("/clusters/cluster/settings/thresholds").
Get("", new(thresholds.IndexAction)).
GetPost("/createPopup", new(thresholds.CreatePopupAction)).
GetPost("/updatePopup", new(thresholds.UpdatePopupAction)).
Post("/delete", new(thresholds.DeleteAction)).
// 指标
Prefix("/clusters/cluster/settings/metrics").
Get("", new(metrics.IndexAction)).
@@ -79,6 +65,13 @@ func init() {
// WebP
Prefix("/clusters/cluster/settings/webp").
GetPost("", new(webp.IndexAction)).
// DDOS Protection
Prefix("/clusters/cluster/settings/ddos-protection").
GetPost("", new(ddosProtection.IndexAction)).
GetPost("/status", new(ddosProtection.StatusAction)).
//
EndAll()
})
}

View File

@@ -1,75 +0,0 @@
package message
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "")
this.SecondMenu("message")
}
func (this *IndexAction) RunGet(params struct{}) {
this.Show()
}
func (this *IndexAction) RunPost(params struct {
ClusterId int64
ReceiversJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo("修改集群 %d 消息接收人", params.ClusterId)
receiverMaps := []maps.Map{}
if len(params.ReceiversJSON) > 0 {
err := json.Unmarshal(params.ReceiversJSON, &receiverMaps)
if err != nil {
this.ErrorPage(err)
return
}
}
pbReceiverOptions := &pb.UpdateMessageReceiversRequest_RecipientOptions{}
for _, receiverMap := range receiverMaps {
recipientId := int64(0)
groupId := int64(0)
receiverType := receiverMap.GetString("type")
switch receiverType {
case "recipient":
recipientId = receiverMap.GetInt64("id")
case "group":
groupId = receiverMap.GetInt64("id")
default:
continue
}
pbReceiverOptions.RecipientOptions = append(pbReceiverOptions.RecipientOptions, &pb.UpdateMessageReceiversRequest_RecipientOption{
MessageRecipientId: recipientId,
MessageRecipientGroupId: groupId,
})
}
_, err := this.RPC().MessageReceiverRPC().UpdateMessageReceivers(this.AdminContext(), &pb.UpdateMessageReceiversRequest{
NodeClusterId: params.ClusterId,
NodeId: 0,
ServerId: 0,
ParamsJSON: nil,
RecipientOptions: map[string]*pb.UpdateMessageReceiversRequest_RecipientOptions{
"*": pbReceiverOptions,
},
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,77 +0,0 @@
package message
import (
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
)
type SelectReceiverPopupAction struct {
actionutils.ParentAction
}
func (this *SelectReceiverPopupAction) Init() {
this.Nav("", "", "")
}
func (this *SelectReceiverPopupAction) RunGet(params struct {
RecipientIds string
GroupIds string
}) {
recipientIds := utils.SplitNumbers(params.RecipientIds)
groupIds := utils.SplitNumbers(params.GroupIds)
// 所有接收人
recipientsResp, err := this.RPC().MessageRecipientRPC().ListEnabledMessageRecipients(this.AdminContext(), &pb.ListEnabledMessageRecipientsRequest{
AdminId: 0,
MediaType: "",
MessageRecipientGroupId: 0,
Keyword: "",
Offset: 0,
Size: 1000, // TODO 支持搜索
})
if err != nil {
this.ErrorPage(err)
return
}
recipientMaps := []maps.Map{}
for _, recipient := range recipientsResp.MessageRecipients {
if !recipient.IsOn {
continue
}
if lists.ContainsInt64(recipientIds, recipient.Id) {
continue
}
recipientMaps = append(recipientMaps, maps.Map{
"id": recipient.Id,
"name": recipient.Admin.Fullname,
"instanceName": recipient.MessageMediaInstance.Name,
})
}
this.Data["recipients"] = recipientMaps
// 所有分组
groupsResp, err := this.RPC().MessageRecipientGroupRPC().FindAllEnabledMessageRecipientGroups(this.AdminContext(), &pb.FindAllEnabledMessageRecipientGroupsRequest{})
if err != nil {
this.ErrorPage(err)
return
}
groupMaps := []maps.Map{}
for _, group := range groupsResp.MessageRecipientGroups {
if !group.IsOn {
continue
}
if lists.ContainsInt64(groupIds, group.Id) {
continue
}
groupMaps = append(groupMaps, maps.Map{
"id": group.Id,
"name": group.Name,
})
}
this.Data["groups"] = groupMaps
this.Show()
}

View File

@@ -1,61 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package message
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type SelectedReceiversAction struct {
actionutils.ParentAction
}
func (this *SelectedReceiversAction) Init() {
this.Nav("", "", "")
}
func (this *SelectedReceiversAction) RunPost(params struct {
ClusterId int64
NodeId int64
ServerId int64
}) {
receiversResp, err := this.RPC().MessageReceiverRPC().FindAllEnabledMessageReceivers(this.AdminContext(), &pb.FindAllEnabledMessageReceiversRequest{
NodeClusterId: params.ClusterId,
NodeId: params.NodeId,
ServerId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
receiverMaps := []maps.Map{}
for _, receiver := range receiversResp.MessageReceivers {
id := int64(0)
name := ""
receiverType := ""
subName := ""
if receiver.MessageRecipient != nil {
id = receiver.MessageRecipient.Id
name = receiver.MessageRecipient.Admin.Fullname
subName = receiver.MessageRecipient.MessageMediaInstance.Name
receiverType = "recipient"
} else if receiver.MessageRecipientGroup != nil {
id = receiver.MessageRecipientGroup.Id
name = receiver.MessageRecipientGroup.Name
receiverType = "group"
} else {
continue
}
receiverMaps = append(receiverMaps, maps.Map{
"id": id,
"name": name,
"subName": subName,
"type": receiverType,
})
}
this.Data["receivers"] = receiverMaps
this.Success()
}

View File

@@ -1,79 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package thresholds
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
)
type CreatePopupAction struct {
actionutils.ParentAction
}
func (this *CreatePopupAction) Init() {
this.Nav("", "", "")
}
func (this *CreatePopupAction) RunGet(params struct {
ClusterId int64
NodeId int64
}) {
this.Data["clusterId"] = params.ClusterId
this.Data["nodeId"] = params.NodeId
this.Data["items"] = nodeconfigs.FindAllNodeValueItemDefinitions()
this.Data["operators"] = nodeconfigs.FindAllNodeValueOperatorDefinitions()
this.Show()
}
func (this *CreatePopupAction) RunPost(params struct {
ClusterId int64
NodeId int64
Item string
Param string
SumMethod string
Operator string
Value string
Duration int32
DurationUnit string
Message string
NotifyDuration int32
Must *actions.Must
CSRF *actionutils.CSRF
}) {
if params.ClusterId <= 0 && params.NodeId >= 0 {
this.Fail("集群或者节点至少需要填写其中一个参数")
}
valueJSON, err := json.Marshal(params.Value)
if err != nil {
this.ErrorPage(err)
return
}
resp, err := this.RPC().NodeThresholdRPC().CreateNodeThreshold(this.AdminContext(), &pb.CreateNodeThresholdRequest{
Role: "node",
NodeClusterId: params.ClusterId,
NodeId: params.NodeId,
Item: params.Item,
Param: params.Param,
Operator: params.Operator,
ValueJSON: valueJSON,
Message: params.Message,
Duration: params.Duration,
DurationUnit: params.DurationUnit,
SumMethod: params.SumMethod,
NotifyDuration: params.NotifyDuration,
})
if err != nil {
this.ErrorPage(err)
return
}
defer this.CreateLogInfo("创建节点阈值 %d", resp.NodeThresholdId)
this.Success()
}

View File

@@ -1,27 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package thresholds
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
// DeleteAction 删除阈值
type DeleteAction struct {
actionutils.ParentAction
}
func (this *DeleteAction) RunPost(params struct {
ThresholdId int64
}) {
defer this.CreateLogInfo("删除阈值 %d", params.ThresholdId)
_, err := this.RPC().NodeThresholdRPC().DeleteNodeThreshold(this.AdminContext(), &pb.DeleteNodeThresholdRequest{NodeThresholdId: params.ThresholdId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,61 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package thresholds
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "setting")
this.SecondMenu("threshold")
}
func (this *IndexAction) RunGet(params struct {
ClusterId int64
}) {
// 列出所有阈值
thresholdsResp, err := this.RPC().NodeThresholdRPC().FindAllEnabledNodeThresholds(this.AdminContext(), &pb.FindAllEnabledNodeThresholdsRequest{
Role: "node",
NodeClusterId: params.ClusterId,
NodeId: 0,
})
if err != nil {
this.ErrorPage(err)
return
}
thresholdMaps := []maps.Map{}
for _, threshold := range thresholdsResp.NodeThresholds {
var nodeMap maps.Map = nil
if threshold.Node != nil {
nodeMap = maps.Map{
"id": threshold.Node.Id,
"name": threshold.Node.Name,
}
}
thresholdMaps = append(thresholdMaps, maps.Map{
"id": threshold.Id,
"itemName": nodeconfigs.FindNodeValueItemName(threshold.Item),
"paramName": nodeconfigs.FindNodeValueItemParamName(threshold.Item, threshold.Param),
"operatorName": nodeconfigs.FindNodeValueOperatorName(threshold.Operator),
"value": nodeconfigs.UnmarshalNodeValue(threshold.ValueJSON),
"sumMethodName": nodeconfigs.FindNodeValueSumMethodName(threshold.SumMethod),
"duration": threshold.Duration,
"durationUnitName": nodeconfigs.FindNodeValueDurationUnitName(threshold.DurationUnit),
"isOn": threshold.IsOn,
"node": nodeMap,
})
}
this.Data["thresholds"] = thresholdMaps
this.Show()
}

View File

@@ -1,106 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package thresholds
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type UpdatePopupAction struct {
actionutils.ParentAction
}
func (this *UpdatePopupAction) Init() {
this.Nav("", "", "")
}
func (this *UpdatePopupAction) RunGet(params struct {
ThresholdId int64
}) {
// 通用参数
this.Data["items"] = nodeconfigs.FindAllNodeValueItemDefinitions()
this.Data["operators"] = nodeconfigs.FindAllNodeValueOperatorDefinitions()
// 阈值详情
thresholdResp, err := this.RPC().NodeThresholdRPC().FindEnabledNodeThreshold(this.AdminContext(), &pb.FindEnabledNodeThresholdRequest{NodeThresholdId: params.ThresholdId})
if err != nil {
this.ErrorPage(err)
return
}
threshold := thresholdResp.NodeThreshold
if threshold == nil {
this.NotFound("nodeThreshold", params.ThresholdId)
return
}
valueInterface := new(interface{})
err = json.Unmarshal(threshold.ValueJSON, valueInterface)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["threshold"] = maps.Map{
"id": threshold.Id,
"item": threshold.Item,
"param": threshold.Param,
"message": threshold.Message,
"notifyDuration": threshold.NotifyDuration,
"value": nodeconfigs.UnmarshalNodeValue(threshold.ValueJSON),
"operator": threshold.Operator,
"duration": threshold.Duration,
"durationUnit": threshold.DurationUnit,
"isOn": threshold.IsOn,
}
this.Show()
}
func (this *UpdatePopupAction) RunPost(params struct {
ThresholdId int64
Item string
Param string
SumMethod string
Operator string
Value string
Duration int32
DurationUnit string
Message string
NotifyDuration int32
IsOn bool
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo("修改节点阈值 %d", params.ThresholdId)
valueJSON, err := json.Marshal(params.Value)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().NodeThresholdRPC().UpdateNodeThreshold(this.AdminContext(), &pb.UpdateNodeThresholdRequest{
NodeThresholdId: params.ThresholdId,
Item: params.Item,
Param: params.Param,
Operator: params.Operator,
ValueJSON: valueJSON,
Message: params.Message,
NotifyDuration: params.NotifyDuration,
Duration: params.Duration,
DurationUnit: params.DurationUnit,
SumMethod: params.SumMethod,
IsOn: params.IsOn,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -22,7 +22,7 @@ func NewClusterHelper() *ClusterHelper {
}
func (this *ClusterHelper) BeforeAction(actionPtr actions.ActionWrapper) (goNext bool) {
action := actionPtr.Object()
var action = actionPtr.Object()
if action.Request.Method != http.MethodGet {
return true
}
@@ -57,7 +57,7 @@ func (this *ClusterHelper) BeforeAction(actionPtr actions.ActionWrapper) (goNext
return
}
tabbar := actionutils.NewTabbar()
var tabbar = actionutils.NewTabbar()
tabbar.Add("集群列表", "", "/clusters", "", false)
if teaconst.IsPlus {
tabbar.Add("集群看板", "", "/clusters/cluster/boards?clusterId="+clusterIdString, "board", selectedTabbar == "board")
@@ -118,10 +118,18 @@ func (this *ClusterHelper) createSettingMenu(cluster *pb.NodeCluster, info *pb.F
})
items = append(items, maps.Map{
"name": "健康检查",
"url": "/clusters/cluster/settings/health?clusterId=" + clusterId,
"isActive": selectedItem == "health",
"isOn": info != nil && info.HealthCheckIsOn,
"name": "WebP",
"url": "/clusters/cluster/settings/webp?clusterId=" + clusterId,
"isActive": selectedItem == "webp",
"isOn": info != nil && info.WebpIsOn,
})
items = filterMenuItems1(items, info, clusterId, selectedItem)
items = append(items, maps.Map{
"name": "-",
"url": "",
"isActive": false,
})
items = append(items, maps.Map{
@@ -130,12 +138,25 @@ func (this *ClusterHelper) createSettingMenu(cluster *pb.NodeCluster, info *pb.F
"isActive": selectedItem == "dns",
"isOn": cluster.DnsDomainId > 0 || len(cluster.DnsName) > 0,
})
items = append(items, maps.Map{
"name": "WebP",
"url": "/clusters/cluster/settings/webp?clusterId=" + clusterId,
"isActive": selectedItem == "webp",
"isOn": info != nil && info.WebpIsOn,
"name": "健康检查",
"url": "/clusters/cluster/settings/health?clusterId=" + clusterId,
"isActive": selectedItem == "health",
"isOn": info != nil && info.HealthCheckIsOn,
})
items = append(items, maps.Map{
"name": "DDoS防护",
"url": "/clusters/cluster/settings/ddos-protection?clusterId=" + clusterId,
"isActive": selectedItem == "ddosProtection",
"isOn": info != nil && info.HasDDoSProtection,
})
items = append(items, maps.Map{
"name": "-",
})
items = append(items, maps.Map{
"name": "统计指标",
"url": "/clusters/cluster/settings/metrics?clusterId=" + clusterId,
@@ -143,21 +164,7 @@ func (this *ClusterHelper) createSettingMenu(cluster *pb.NodeCluster, info *pb.F
"isOn": info != nil && info.HasMetricItems,
})
if teaconst.IsPlus {
items = append(items, maps.Map{
"name": "阈值设置",
"url": "/clusters/cluster/settings/thresholds?clusterId=" + clusterId,
"isActive": selectedItem == "threshold",
"isOn": info != nil && info.HasThresholds,
})
items = append(items, maps.Map{
"name": "消息通知",
"url": "/clusters/cluster/settings/message?clusterId=" + clusterId,
"isActive": selectedItem == "message",
"isOn": info != nil && info.HasMessageReceivers,
})
}
items = filterMenuItems2(items, info, clusterId, selectedItem)
items = append(items, maps.Map{
"name": "-",

View File

@@ -0,0 +1,18 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build !plus
// +build !plus
package clusterutils
import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
func filterMenuItems1(items []maps.Map, info *pb.FindEnabledNodeClusterConfigInfoResponse, clusterIdString string, selectedItem string) []maps.Map {
return items
}
func filterMenuItems2(items []maps.Map, info *pb.FindEnabledNodeClusterConfigInfoResponse, clusterIdString string, selectedItem string) []maps.Map {
return items
}

View File

@@ -1,32 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package groups
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type OptionsAction struct {
actionutils.ParentAction
}
func (this *OptionsAction) RunPost(params struct{}) {
resp, err := this.RPC().ReportNodeGroupRPC().FindAllEnabledReportNodeGroups(this.AdminContext(), &pb.FindAllEnabledReportNodeGroupsRequest{})
if err != nil {
this.ErrorPage(err)
return
}
var groupMaps = []maps.Map{}
for _, group := range resp.ReportNodeGroups {
groupMaps = append(groupMaps, maps.Map{
"id": group.Id,
"name": group.Name,
})
}
this.Data["groups"] = groupMaps
this.Success()
}

View File

@@ -3,14 +3,20 @@
package dashboard
import (
"fmt"
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
"github.com/TeaOSLab/EdgeAdmin/internal/utils/sizes"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"github.com/shirou/gopsutil/v3/disk"
"regexp"
"runtime"
)
type IndexAction struct {
@@ -57,6 +63,14 @@ func (this *IndexAction) RunPost(params struct{}) {
this.ErrorPage(err)
return
}
// 检查当前服务器空间
var diskUsageWarning = ""
diskPath, diskUsage, diskUsagePercent, shouldWarning := this.checkDiskPartitions(90)
if shouldWarning {
diskUsageWarning = "当前服务器磁盘空间不足,请立即扩充容量,文件路径:" + diskPath + ",已使用:" + types.String(diskUsage/1024/1024/1024) + "G已使用比例" + fmt.Sprintf("%.2f%%", diskUsagePercent) + ",仅剩余空间:" + fmt.Sprintf("%.2f%%", 100-diskUsagePercent) + "。"
}
this.Data["dashboard"] = maps.Map{
"defaultClusterId": resp.DefaultNodeClusterId,
@@ -75,6 +89,8 @@ func (this *IndexAction) RunPost(params struct{}) {
"canGoNodes": configloaders.AllowModule(this.AdminId(), configloaders.AdminModuleCodeNode),
"canGoSettings": configloaders.AllowModule(this.AdminId(), configloaders.AdminModuleCodeSetting),
"canGoUsers": configloaders.AllowModule(this.AdminId(), configloaders.AdminModuleCodeUser),
"diskUsageWarning": diskUsageWarning,
}
// 今日流量
@@ -249,3 +265,47 @@ func (this *IndexAction) RunPost(params struct{}) {
this.Success()
}
// 检查服务器磁盘空间
func (this *IndexAction) checkDiskPartitions(thresholdPercent float64) (path string, usage uint64, usagePercent float64, shouldWarning bool) {
partitions, err := disk.Partitions(false)
if err != nil {
return
}
if !lists.ContainsString([]string{"darwin", "linux", "freebsd"}, runtime.GOOS) {
return
}
var rootFS = ""
for _, p := range partitions {
if p.Mountpoint == "/" {
rootFS = p.Fstype
break
}
}
for _, p := range partitions {
if p.Mountpoint == "/boot" {
continue
}
if p.Fstype != rootFS {
continue
}
stat, _ := disk.Usage(p.Mountpoint)
if stat != nil {
if stat.Used < 2*uint64(sizes.G) {
continue
}
if stat.UsedPercent > thresholdPercent {
path = stat.Path
usage = stat.Used
usagePercent = stat.UsedPercent
shouldWarning = true
break
}
}
}
return
}

View File

@@ -70,17 +70,14 @@ func (this *CreatePopupAction) RunPost(params struct {
ParamRegion string
// AliDNS
ParamAccessKeyId string
ParamAccessKeySecret string
ParamAliDNSAccessKeyId string
ParamAliDNSAccessKeySecret string
ParamAliDNSRegionId string
// HuaweiDNS
ParamHuaweiAccessKeyId string
ParamHuaweiAccessKeySecret string
// DNS.COM
ParamApiKey string
ParamApiSecret string
// CloudFlare
ParamCloudFlareAPIKey string
ParamCloudFlareEmail string
@@ -115,13 +112,14 @@ func (this *CreatePopupAction) RunPost(params struct {
apiParams["region"] = params.ParamRegion
case "alidns":
params.Must.
Field("paramAccessKeyId", params.ParamAccessKeyId).
Field("paramAliDNSAccessKeyId", params.ParamAliDNSAccessKeyId).
Require("请输入AccessKeyId").
Field("paramAccessKeySecret", params.ParamAccessKeySecret).
Field("paramAliDNSAccessKeySecret", params.ParamAliDNSAccessKeySecret).
Require("请输入AccessKeySecret")
apiParams["accessKeyId"] = params.ParamAccessKeyId
apiParams["accessKeySecret"] = params.ParamAccessKeySecret
apiParams["accessKeyId"] = params.ParamAliDNSAccessKeyId
apiParams["accessKeySecret"] = params.ParamAliDNSAccessKeySecret
apiParams["regionId"] = params.ParamAliDNSRegionId
case "huaweiDNS":
params.Must.
Field("paramHuaweiAccessKeyId", params.ParamHuaweiAccessKeyId).
@@ -131,15 +129,6 @@ func (this *CreatePopupAction) RunPost(params struct {
apiParams["accessKeyId"] = params.ParamHuaweiAccessKeyId
apiParams["accessKeySecret"] = params.ParamHuaweiAccessKeySecret
case "dnscom":
params.Must.
Field("paramApiKey", params.ParamApiKey).
Require("请输入ApiKey").
Field("paramApiSecret", params.ParamApiSecret).
Require("请输入ApiSecret")
apiParams["apiKey"] = params.ParamApiKey
apiParams["apiSecret"] = params.ParamApiSecret
case "cloudFlare":
params.Must.
Field("paramCloudFlareAPIKey", params.ParamCloudFlareAPIKey).

View File

@@ -18,11 +18,13 @@ func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
Keyword string
Domain string
Keyword string
Domain string
ProviderType string
}) {
this.Data["keyword"] = params.Keyword
this.Data["domain"] = params.Domain
this.Data["providerType"] = params.ProviderType
// 格式化域名
var domain = params.Domain
@@ -33,6 +35,7 @@ func (this *IndexAction) RunGet(params struct {
AdminId: this.AdminId(),
Keyword: params.Keyword,
Domain: domain,
Type: params.ProviderType,
})
if err != nil {
this.ErrorPage(err)
@@ -46,6 +49,7 @@ func (this *IndexAction) RunGet(params struct {
AdminId: this.AdminId(),
Keyword: params.Keyword,
Domain: domain,
Type: params.ProviderType,
Offset: page.Offset,
Size: page.Size,
})
@@ -53,7 +57,7 @@ func (this *IndexAction) RunGet(params struct {
this.ErrorPage(err)
return
}
providerMaps := []maps.Map{}
var providerMaps = []maps.Map{}
for _, provider := range providersResp.DnsProviders {
dataUpdatedTime := ""
if provider.DataUpdatedAt > 0 {
@@ -61,7 +65,9 @@ func (this *IndexAction) RunGet(params struct {
}
// 域名
countDomainsResp, err := this.RPC().DNSDomainRPC().CountAllEnabledDNSDomainsWithDNSProviderId(this.AdminContext(), &pb.CountAllEnabledDNSDomainsWithDNSProviderIdRequest{DnsProviderId: provider.Id})
countDomainsResp, err := this.RPC().DNSDomainRPC().CountAllEnabledDNSDomainsWithDNSProviderId(this.AdminContext(), &pb.CountAllEnabledDNSDomainsWithDNSProviderIdRequest{
DnsProviderId: provider.Id,
})
if err != nil {
this.ErrorPage(err)
return
@@ -79,5 +85,30 @@ func (this *IndexAction) RunGet(params struct {
}
this.Data["providers"] = providerMaps
// 类型
typesResponse, err := this.RPC().DNSProviderRPC().FindAllDNSProviderTypes(this.AdminContext(), &pb.FindAllDNSProviderTypesRequest{})
if err != nil {
this.ErrorPage(err)
return
}
var providerTypeMaps = []maps.Map{}
for _, providerType := range typesResponse.ProviderTypes {
countProvidersWithTypeResp, err := this.RPC().DNSProviderRPC().CountAllEnabledDNSProviders(this.AdminContext(), &pb.CountAllEnabledDNSProvidersRequest{
Type: providerType.Code,
})
if err != nil {
this.ErrorPage(err)
return
}
if countProvidersWithTypeResp.Count > 0 {
providerTypeMaps = append(providerTypeMaps, maps.Map{
"name": providerType.Name,
"code": providerType.Code,
"count": countProvidersWithTypeResp.Count,
})
}
}
this.Data["providerTypes"] = providerTypeMaps
this.Show()
}

View File

@@ -97,17 +97,14 @@ func (this *UpdatePopupAction) RunPost(params struct {
ParamRegion string
// AliDNS
ParamAccessKeyId string
ParamAccessKeySecret string
ParamAliDNSAccessKeyId string
ParamAliDNSAccessKeySecret string
ParamAliDNSRegionId string
// HuaweiDNS
ParamHuaweiAccessKeyId string
ParamHuaweiAccessKeySecret string
// DNS.COM
ParamApiKey string
ParamApiSecret string
// CloudFlare
ParamCloudFlareAPIKey string
ParamCloudFlareEmail string
@@ -144,13 +141,14 @@ func (this *UpdatePopupAction) RunPost(params struct {
apiParams["region"] = params.ParamRegion
case "alidns":
params.Must.
Field("paramAccessKeyId", params.ParamAccessKeyId).
Field("paramAliDNSAccessKeyId", params.ParamAliDNSAccessKeyId).
Require("请输入AccessKeyId").
Field("paramAccessKeySecret", params.ParamAccessKeySecret).
Field("paramAliDNSAccessKeySecret", params.ParamAliDNSAccessKeySecret).
Require("请输入AccessKeySecret")
apiParams["accessKeyId"] = params.ParamAccessKeyId
apiParams["accessKeySecret"] = params.ParamAccessKeySecret
apiParams["accessKeyId"] = params.ParamAliDNSAccessKeyId
apiParams["accessKeySecret"] = params.ParamAliDNSAccessKeySecret
apiParams["regionId"] = params.ParamAliDNSRegionId
case "huaweiDNS":
params.Must.
Field("paramHuaweiAccessKeyId", params.ParamHuaweiAccessKeyId).
@@ -160,15 +158,6 @@ func (this *UpdatePopupAction) RunPost(params struct {
apiParams["accessKeyId"] = params.ParamHuaweiAccessKeyId
apiParams["accessKeySecret"] = params.ParamHuaweiAccessKeySecret
case "dnscom":
params.Must.
Field("paramApiKey", params.ParamApiKey).
Require("请输入ApiKey").
Field("paramApiSecret", params.ParamApiSecret).
Require("请输入ApiSecret")
apiParams["apiKey"] = params.ParamApiKey
apiParams["apiSecret"] = params.ParamApiSecret
case "cloudFlare":
params.Must.
Field("paramCloudFlareAPIKey", params.ParamCloudFlareAPIKey).

View File

@@ -34,7 +34,10 @@ func SendMessageToCluster(ctx context.Context, clusterId int64, code string, msg
}
// 获取所有节点
nodesResp, err := defaultRPCClient.NodeRPC().FindAllEnabledNodesWithNodeClusterId(ctx, &pb.FindAllEnabledNodesWithNodeClusterIdRequest{NodeClusterId: clusterId})
nodesResp, err := defaultRPCClient.NodeRPC().FindAllEnabledNodesWithNodeClusterId(ctx, &pb.FindAllEnabledNodesWithNodeClusterIdRequest{
NodeClusterId: clusterId,
IncludeSecondary: true,
})
if err != nil {
return results, err
}
@@ -43,10 +46,10 @@ func SendMessageToCluster(ctx context.Context, clusterId int64, code string, msg
return results, nil
}
rpcMap := map[int64]*rpc.RPCClient{} // apiNodeId => RPCClient
locker := &sync.Mutex{}
var rpcMap = map[int64]*rpc.RPCClient{} // apiNodeId => RPCClient
var locker = &sync.Mutex{}
wg := &sync.WaitGroup{}
var wg = &sync.WaitGroup{}
wg.Add(len(nodes))
for _, node := range nodes {

View File

@@ -1,182 +0,0 @@
package node
import (
"encoding/json"
"fmt"
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/grants/grantutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
"time"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "node", "node")
this.SecondMenu("nodes")
}
func (this *IndexAction) RunGet(params struct {
NodeId int64
}) {
this.Data["nodeId"] = params.NodeId
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
node := nodeResp.NsNode
if node == nil {
this.WriteString("找不到要操作的节点")
return
}
var clusterMap maps.Map = nil
if node.NsCluster != nil {
clusterId := node.NsCluster.Id
clusterResp, err := this.RPC().NSClusterRPC().FindEnabledNSCluster(this.AdminContext(), &pb.FindEnabledNSClusterRequest{NsClusterId: clusterId})
if err != nil {
this.ErrorPage(err)
return
}
cluster := clusterResp.NsCluster
if cluster != nil {
clusterMap = maps.Map{
"id": cluster.Id,
"name": cluster.Name,
"installDir": cluster.InstallDir,
}
}
}
// IP地址
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledNodeIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledNodeIPAddressesWithNodeIdRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleDNS,
})
if err != nil {
this.ErrorPage(err)
return
}
ipAddressMaps := []maps.Map{}
for _, addr := range ipAddressesResp.NodeIPAddresses {
ipAddressMaps = append(ipAddressMaps, maps.Map{
"id": addr.Id,
"name": addr.Name,
"ip": addr.Ip,
"canAccess": addr.CanAccess,
"isOn": addr.IsOn,
"isUp": addr.IsUp,
})
}
// 运行状态
status := &nodeconfigs.NodeStatus{}
if len(node.StatusJSON) > 0 {
err = json.Unmarshal(node.StatusJSON, &status)
if err != nil {
this.ErrorPage(err)
return
}
status.IsActive = status.IsActive && time.Now().Unix()-status.UpdatedAt <= 60 // N秒之内认为活跃
}
// 检查是否有新版本
if len(status.OS) > 0 {
checkVersionResp, err := this.RPC().NSNodeRPC().CheckNSNodeLatestVersion(this.AdminContext(), &pb.CheckNSNodeLatestVersionRequest{
Os: status.OS,
Arch: status.Arch,
CurrentVersion: status.BuildVersion,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["shouldUpgrade"] = checkVersionResp.HasNewVersion
this.Data["newVersion"] = checkVersionResp.NewVersion
} else {
this.Data["shouldUpgrade"] = false
this.Data["newVersion"] = ""
}
// 登录信息
var loginMap maps.Map = nil
if node.NodeLogin != nil {
loginParams := maps.Map{}
if len(node.NodeLogin.Params) > 0 {
err = json.Unmarshal(node.NodeLogin.Params, &loginParams)
if err != nil {
this.ErrorPage(err)
return
}
}
grantMap := maps.Map{}
grantId := loginParams.GetInt64("grantId")
if grantId > 0 {
grantResp, err := this.RPC().NodeGrantRPC().FindEnabledNodeGrant(this.AdminContext(), &pb.FindEnabledNodeGrantRequest{NodeGrantId: grantId})
if err != nil {
this.ErrorPage(err)
return
}
if grantResp.NodeGrant != nil {
grantMap = maps.Map{
"id": grantResp.NodeGrant.Id,
"name": grantResp.NodeGrant.Name,
"method": grantResp.NodeGrant.Method,
"methodName": grantutils.FindGrantMethodName(grantResp.NodeGrant.Method),
"username": grantResp.NodeGrant.Username,
}
}
}
loginMap = maps.Map{
"id": node.NodeLogin.Id,
"name": node.NodeLogin.Name,
"type": node.NodeLogin.Type,
"params": loginParams,
"grant": grantMap,
}
}
this.Data["node"] = maps.Map{
"id": node.Id,
"name": node.Name,
"ipAddresses": ipAddressMaps,
"cluster": clusterMap,
"installDir": node.InstallDir,
"isInstalled": node.IsInstalled,
"uniqueId": node.UniqueId,
"secret": node.Secret,
"isOn": node.IsOn,
"status": maps.Map{
"isActive": node.IsActive && status.IsActive,
"updatedAt": status.UpdatedAt,
"hostname": status.Hostname,
"cpuUsage": status.CPUUsage,
"cpuUsageText": fmt.Sprintf("%.2f%%", status.CPUUsage*100),
"memUsage": status.MemoryUsage,
"memUsageText": fmt.Sprintf("%.2f%%", status.MemoryUsage*100),
"connectionCount": status.ConnectionCount,
"buildVersion": status.BuildVersion,
"cpuPhysicalCount": status.CPUPhysicalCount,
"cpuLogicalCount": status.CPULogicalCount,
"load1m": fmt.Sprintf("%.2f", status.Load1m),
"load5m": fmt.Sprintf("%.2f", status.Load5m),
"load15m": fmt.Sprintf("%.2f", status.Load15m),
"cacheTotalDiskSize": numberutils.FormatBytes(status.CacheTotalDiskSize),
"cacheTotalMemorySize": numberutils.FormatBytes(status.CacheTotalMemorySize),
},
"login": loginMap,
}
this.Show()
}

View File

@@ -1,117 +0,0 @@
package node
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
"strings"
)
// InstallAction 安装节点
type InstallAction struct {
actionutils.ParentAction
}
func (this *InstallAction) Init() {
this.Nav("", "node", "install")
this.SecondMenu("nodes")
}
func (this *InstallAction) RunGet(params struct {
NodeId int64
}) {
this.Data["nodeId"] = params.NodeId
// 节点
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
node := nodeResp.NsNode
if node == nil {
this.WriteString("找不到要操作的节点")
return
}
// 安装信息
if node.InstallStatus != nil {
this.Data["installStatus"] = maps.Map{
"isRunning": node.InstallStatus.IsRunning,
"isFinished": node.InstallStatus.IsFinished,
"isOk": node.InstallStatus.IsOk,
"updatedAt": node.InstallStatus.UpdatedAt,
"error": node.InstallStatus.Error,
}
} else {
this.Data["installStatus"] = nil
}
// 集群
var clusterMap maps.Map = nil
if node.NsCluster != nil {
clusterId := node.NsCluster.Id
clusterResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeCluster(this.AdminContext(), &pb.FindEnabledNodeClusterRequest{NodeClusterId: clusterId})
if err != nil {
this.ErrorPage(err)
return
}
cluster := clusterResp.NodeCluster
if cluster != nil {
clusterMap = maps.Map{
"id": cluster.Id,
"name": cluster.Name,
"installDir": cluster.InstallDir,
}
}
}
// API节点列表
apiNodesResp, err := this.RPC().APINodeRPC().FindAllEnabledAPINodes(this.AdminContext(), &pb.FindAllEnabledAPINodesRequest{})
if err != nil {
this.ErrorPage(err)
return
}
apiNodes := apiNodesResp.ApiNodes
apiEndpoints := []string{}
for _, apiNode := range apiNodes {
if !apiNode.IsOn {
continue
}
apiEndpoints = append(apiEndpoints, apiNode.AccessAddrs...)
}
this.Data["apiEndpoints"] = "\"" + strings.Join(apiEndpoints, "\", \"") + "\""
this.Data["node"] = maps.Map{
"id": node.Id,
"name": node.Name,
"installDir": node.InstallDir,
"isInstalled": node.IsInstalled,
"uniqueId": node.UniqueId,
"secret": node.Secret,
"cluster": clusterMap,
}
this.Show()
}
// RunPost 开始安装
func (this *InstallAction) RunPost(params struct {
NodeId int64
Must *actions.Must
}) {
// 创建日志
defer this.CreateLogInfo("安装节点 %d", params.NodeId)
_, err := this.RPC().NSNodeRPC().InstallNSNode(this.AdminContext(), &pb.InstallNSNodeRequest{
NsNodeId: params.NodeId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,75 +0,0 @@
package node
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
)
type LogsAction struct {
actionutils.ParentAction
}
func (this *LogsAction) Init() {
this.Nav("", "node", "log")
this.SecondMenu("nodes")
}
func (this *LogsAction) RunGet(params struct {
NodeId int64
DayFrom string
DayTo string
Keyword string
Level string
}) {
this.Data["nodeId"] = params.NodeId
this.Data["dayFrom"] = params.DayFrom
this.Data["dayTo"] = params.DayTo
this.Data["keyword"] = params.Keyword
this.Data["level"] = params.Level
countResp, err := this.RPC().NodeLogRPC().CountNodeLogs(this.AdminContext(), &pb.CountNodeLogsRequest{
Role: nodeconfigs.NodeRoleDNS,
NodeId: params.NodeId,
DayFrom: params.DayFrom,
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
})
if err != nil {
this.ErrorPage(err)
return
}
count := countResp.Count
page := this.NewPage(count, 20)
logsResp, err := this.RPC().NodeLogRPC().ListNodeLogs(this.AdminContext(), &pb.ListNodeLogsRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleDNS,
DayFrom: params.DayFrom,
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
Offset: page.Offset,
Size: page.Size,
})
logs := []maps.Map{}
for _, log := range logsResp.NodeLogs {
logs = append(logs, maps.Map{
"tag": log.Tag,
"description": log.Description,
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", log.CreatedAt),
"level": log.Level,
"isToday": timeutil.FormatTime("Y-m-d", log.CreatedAt) == timeutil.Format("Y-m-d"),
"count": log.Count,
})
}
this.Data["logs"] = logs
this.Data["page"] = page.AsHTML()
this.Show()
}

View File

@@ -1,30 +0,0 @@
package node
import (
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type StartAction struct {
actionutils.ParentAction
}
func (this *StartAction) RunPost(params struct {
NodeId int64
}) {
resp, err := this.RPC().NSNodeRPC().StartNSNode(this.AdminContext(), &pb.StartNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "远程启动节点 %d", params.NodeId)
if resp.IsOk {
this.Success()
}
this.Fail("启动失败:" + resp.Error)
}

View File

@@ -1,46 +0,0 @@
package node
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
// StatusAction 节点状态
type StatusAction struct {
actionutils.ParentAction
}
func (this *StatusAction) RunPost(params struct {
NodeId int64
}) {
// 节点
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
node := nodeResp.NsNode
if node == nil {
this.WriteString("找不到要操作的节点")
return
}
// 安装信息
if node.InstallStatus != nil {
this.Data["installStatus"] = maps.Map{
"isRunning": node.InstallStatus.IsRunning,
"isFinished": node.InstallStatus.IsFinished,
"isOk": node.InstallStatus.IsOk,
"updatedAt": node.InstallStatus.UpdatedAt,
"error": node.InstallStatus.Error,
"errorCode": node.InstallStatus.ErrorCode,
}
} else {
this.Data["installStatus"] = nil
}
this.Data["isInstalled"] = node.IsInstalled
this.Success()
}

View File

@@ -1,30 +0,0 @@
package node
import (
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type StopAction struct {
actionutils.ParentAction
}
func (this *StopAction) RunPost(params struct {
NodeId int64
}) {
resp, err := this.RPC().NSNodeRPC().StopNSNode(this.AdminContext(), &pb.StopNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "远程停止节点 %d", params.NodeId)
if resp.IsOk {
this.Success()
}
this.Fail("执行失败:" + resp.Error)
}

View File

@@ -1,233 +0,0 @@
package node
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/grants/grantutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/ipAddresses/ipaddressutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type UpdateAction struct {
actionutils.ParentAction
}
func (this *UpdateAction) Init() {
this.Nav("", "node", "update")
this.SecondMenu("nodes")
}
func (this *UpdateAction) RunGet(params struct {
NodeId int64
}) {
this.Data["nodeId"] = params.NodeId
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
node := nodeResp.NsNode
if node == nil {
this.WriteString("找不到要操作的节点")
return
}
var clusterMap maps.Map = nil
if node.NsCluster != nil {
clusterMap = maps.Map{
"id": node.NsCluster.Id,
"name": node.NsCluster.Name,
}
}
// IP地址
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledNodeIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledNodeIPAddressesWithNodeIdRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleDNS,
})
if err != nil {
this.ErrorPage(err)
return
}
ipAddressMaps := []maps.Map{}
for _, addr := range ipAddressesResp.NodeIPAddresses {
ipAddressMaps = append(ipAddressMaps, maps.Map{
"id": addr.Id,
"name": addr.Name,
"ip": addr.Ip,
"canAccess": addr.CanAccess,
"isOn": addr.IsOn,
"isUp": addr.IsUp,
})
}
// 登录信息
var loginMap maps.Map = nil
if node.NodeLogin != nil {
loginParams := maps.Map{}
if len(node.NodeLogin.Params) > 0 {
err = json.Unmarshal(node.NodeLogin.Params, &loginParams)
if err != nil {
this.ErrorPage(err)
return
}
}
grantMap := maps.Map{}
grantId := loginParams.GetInt64("grantId")
if grantId > 0 {
grantResp, err := this.RPC().NodeGrantRPC().FindEnabledNodeGrant(this.AdminContext(), &pb.FindEnabledNodeGrantRequest{NodeGrantId: grantId})
if err != nil {
this.ErrorPage(err)
return
}
if grantResp.NodeGrant != nil {
grantMap = maps.Map{
"id": grantResp.NodeGrant.Id,
"name": grantResp.NodeGrant.Name,
"method": grantResp.NodeGrant.Method,
"methodName": grantutils.FindGrantMethodName(grantResp.NodeGrant.Method),
"username": grantResp.NodeGrant.Username,
}
}
}
loginMap = maps.Map{
"id": node.NodeLogin.Id,
"name": node.NodeLogin.Name,
"type": node.NodeLogin.Type,
"params": loginParams,
"grant": grantMap,
}
}
this.Data["node"] = maps.Map{
"id": node.Id,
"name": node.Name,
"ipAddresses": ipAddressMaps,
"cluster": clusterMap,
"isOn": node.IsOn,
"login": loginMap,
}
// 所有集群
resp, err := this.RPC().NSClusterRPC().FindAllEnabledNSClusters(this.AdminContext(), &pb.FindAllEnabledNSClustersRequest{})
if err != nil {
this.ErrorPage(err)
}
if err != nil {
this.ErrorPage(err)
return
}
clusterMaps := []maps.Map{}
for _, cluster := range resp.NsClusters {
clusterMaps = append(clusterMaps, maps.Map{
"id": cluster.Id,
"name": cluster.Name,
})
}
this.Data["clusters"] = clusterMaps
this.Show()
}
func (this *UpdateAction) RunPost(params struct {
LoginId int64
GrantId int64
SshHost string
SshPort int
NodeId int64
Name string
IPAddressesJSON []byte `alias:"ipAddressesJSON"`
ClusterId int64
IsOn bool
Must *actions.Must
}) {
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "修改节点 %d", params.NodeId)
if params.NodeId <= 0 {
this.Fail("要操作的节点不存在")
}
params.Must.
Field("name", params.Name).
Require("请输入节点名称")
// 检查cluster
if params.ClusterId <= 0 {
this.Fail("请选择所在集群")
}
clusterResp, err := this.RPC().NSClusterRPC().FindEnabledNSCluster(this.AdminContext(), &pb.FindEnabledNSClusterRequest{NsClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return
}
if clusterResp.NsCluster == nil {
this.Fail("选择的集群不存在")
}
// IP地址
ipAddresses := []maps.Map{}
if len(params.IPAddressesJSON) > 0 {
err := json.Unmarshal(params.IPAddressesJSON, &ipAddresses)
if err != nil {
this.ErrorPage(err)
return
}
}
if len(ipAddresses) == 0 {
this.Fail("请至少输入一个IP地址")
}
// TODO 检查登录授权
loginInfo := &pb.NodeLogin{
Id: params.LoginId,
Name: "SSH",
Type: "ssh",
Params: maps.Map{
"grantId": params.GrantId,
"host": params.SshHost,
"port": params.SshPort,
}.AsJSON(),
}
// 保存
_, err = this.RPC().NSNodeRPC().UpdateNSNode(this.AdminContext(), &pb.UpdateNSNodeRequest{
NsNodeId: params.NodeId,
Name: params.Name,
NsClusterId: params.ClusterId,
IsOn: params.IsOn,
NodeLogin: loginInfo,
})
if err != nil {
this.ErrorPage(err)
return
}
// 禁用老的IP地址
_, err = this.RPC().NodeIPAddressRPC().DisableAllNodeIPAddressesWithNodeId(this.AdminContext(), &pb.DisableAllNodeIPAddressesWithNodeIdRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleDNS,
})
if err != nil {
this.ErrorPage(err)
return
}
// 添加新的IP地址
err = ipaddressutils.UpdateNodeIPAddresses(this.Parent(), params.NodeId, nodeconfigs.NodeRoleDNS, params.IPAddressesJSON)
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,30 +0,0 @@
package node
import (
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type UpdateInstallStatusAction struct {
actionutils.ParentAction
}
func (this *UpdateInstallStatusAction) RunPost(params struct {
NodeId int64
IsInstalled bool
}) {
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "修改节点安装状态 %d", params.NodeId)
_, err := this.RPC().NSNodeRPC().UpdateNSNodeIsInstalled(this.AdminContext(), &pb.UpdateNSNodeIsInstalledRequest{
NsNodeId: params.NodeId,
IsInstalled: params.IsInstalled,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,73 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package accessLog
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "")
this.SecondMenu("accessLog")
}
func (this *IndexAction) RunGet(params struct {
ClusterId int64
}) {
accessLogResp, err := this.RPC().NSClusterRPC().FindNSClusterAccessLog(this.AdminContext(), &pb.FindNSClusterAccessLogRequest{NsClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return
}
accessLogRef := &dnsconfigs.NSAccessLogRef{}
if len(accessLogResp.AccessLogJSON) > 0 {
err = json.Unmarshal(accessLogResp.AccessLogJSON, accessLogRef)
if err != nil {
this.ErrorPage(err)
return
}
}
this.Data["accessLogRef"] = accessLogRef
this.Show()
}
func (this *IndexAction) RunPost(params struct {
ClusterId int64
AccessLogJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo("修改域名服务集群 %d 访问日志配置", params.ClusterId)
ref := &dnsconfigs.NSAccessLogRef{}
err := json.Unmarshal(params.AccessLogJSON, ref)
if err != nil {
this.Fail("数据格式错误:" + err.Error())
}
err = ref.Init()
if err != nil {
this.Fail("数据格式错误:" + err.Error())
}
_, err = this.RPC().NSClusterRPC().UpdateNSClusterAccessLog(this.AdminContext(), &pb.UpdateNSClusterAccessLogRequest{
NsClusterId: params.ClusterId,
AccessLogJSON: params.AccessLogJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,69 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package cluster
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "")
this.SecondMenu("basic")
}
func (this *IndexAction) RunGet(params struct {
ClusterId int64
}) {
clusterResp, err := this.RPC().NSClusterRPC().FindEnabledNSCluster(this.AdminContext(), &pb.FindEnabledNSClusterRequest{NsClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return
}
cluster := clusterResp.NsCluster
if cluster == nil {
this.NotFound("nsCluster", params.ClusterId)
return
}
this.Data["cluster"] = maps.Map{
"id": cluster.Id,
"name": cluster.Name,
"isOn": cluster.IsOn,
}
this.Show()
}
func (this *IndexAction) RunPost(params struct {
ClusterId int64
Name string
IsOn bool
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo("修改域名服务集群基本信息 %d", params.ClusterId)
params.Must.
Field("name", params.Name).
Require("请输入集群名称")
_, err := this.RPC().NSClusterRPC().UpdateNSCluster(this.AdminContext(), &pb.UpdateNSClusterRequest{
NsClusterId: params.ClusterId,
Name: params.Name,
IsOn: params.IsOn,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,68 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package recursion
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "")
this.SecondMenu("recursion")
}
func (this *IndexAction) RunGet(params struct {
ClusterId int64
}) {
this.Data["clusterId"] = params.ClusterId
resp, err := this.RPC().NSClusterRPC().FindNSClusterRecursionConfig(this.AdminContext(), &pb.FindNSClusterRecursionConfigRequest{NsClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return
}
var config = &dnsconfigs.RecursionConfig{}
if len(resp.RecursionJSON) > 0 {
err = json.Unmarshal(resp.RecursionJSON, config)
if err != nil {
this.ErrorPage(err)
return
}
} else {
config.UseLocalHosts = true
}
this.Data["config"] = config
this.Show()
}
func (this *IndexAction) RunPost(params struct {
ClusterId int64
RecursionJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo("修改DNS集群 %d 的递归DNS设置", params.ClusterId)
// TODO 校验域名
_, err := this.RPC().NSClusterRPC().UpdateNSClusterRecursionConfig(this.AdminContext(), &pb.UpdateNSClusterRecursionConfigRequest{
NsClusterId: params.ClusterId,
RecursionJSON: params.RecursionJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,73 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package domains
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"strings"
)
type CreateAction struct {
actionutils.ParentAction
}
func (this *CreateAction) Init() {
this.Nav("", "", "create")
}
func (this *CreateAction) RunGet(params struct{}) {
// 集群数量
countClustersResp, err := this.RPC().NSClusterRPC().CountAllEnabledNSClusters(this.AdminContext(), &pb.CountAllEnabledNSClustersRequest{})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["countClusters"] = countClustersResp.Count
this.Show()
}
func (this *CreateAction) RunPost(params struct {
Name string
ClusterId int64
UserId int64
Must *actions.Must
CSRF *actionutils.CSRF
}) {
var domainId int64
defer func() {
this.CreateLogInfo("创建域名 %d", domainId)
}()
params.Name = strings.ToLower(params.Name)
params.Must.
Field("name", params.Name).
Require("请输入域名").
Expect(func() (message string, success bool) {
success = domainutils.ValidateDomainFormat(params.Name)
if !success {
message = "请输入正确的域名"
}
return
}).
Field("clusterId", params.ClusterId).
Gt(0, "请选择所属集群")
createResp, err := this.RPC().NSDomainRPC().CreateNSDomain(this.AdminContext(), &pb.CreateNSDomainRequest{
NsClusterId: params.ClusterId,
UserId: params.UserId,
Name: params.Name,
})
if err != nil {
this.ErrorPage(err)
return
}
domainId = createResp.NsDomainId
this.Success()
}

View File

@@ -1,26 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package domains
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteAction struct {
actionutils.ParentAction
}
func (this *DeleteAction) RunPost(params struct {
DomainId int64
}) {
defer this.CreateLogInfo("删除域名 %d", params.DomainId)
_, err := this.RPC().NSDomainRPC().DeleteNSDomain(this.AdminContext(), &pb.DeleteNSDomainRequest{NsDomainId: params.DomainId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,72 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package domains
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type DomainAction struct {
actionutils.ParentAction
}
func (this *DomainAction) Init() {
this.Nav("", "", "index")
}
func (this *DomainAction) RunGet(params struct {
DomainId int64
}) {
err := domainutils.InitDomain(this.Parent(), params.DomainId)
if err != nil {
this.ErrorPage(err)
return
}
var countRecords = this.Data.GetMap("domain").GetInt64("countRecords")
var countKeys = this.Data.GetMap("domain").GetInt64("countKeys")
// 域名信息
domainResp, err := this.RPC().NSDomainRPC().FindEnabledNSDomain(this.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: params.DomainId})
if err != nil {
this.ErrorPage(err)
return
}
domain := domainResp.NsDomain
if domain == nil {
this.NotFound("nsDomain", params.DomainId)
return
}
var clusterMap maps.Map
if domain.NsCluster != nil {
clusterMap = maps.Map{
"id": domain.NsCluster.Id,
"name": domain.NsCluster.Name,
}
}
// 用户信息
var userMap maps.Map
if domain.User != nil {
userMap = maps.Map{
"id": domain.User.Id,
"username": domain.User.Username,
"fullname": domain.User.Fullname,
}
}
this.Data["domain"] = maps.Map{
"id": domain.Id,
"name": domain.Name,
"isOn": domain.IsOn,
"cluster": clusterMap,
"user": userMap,
"countRecords": countRecords,
"countKeys": countKeys,
}
this.Show()
}

View File

@@ -1,55 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package domainutils
import (
"errors"
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
)
// InitDomain 初始化域名信息
func InitDomain(parent *actionutils.ParentAction, domainId int64) error {
rpcClient, err := rpc.SharedRPC()
if err != nil {
return err
}
domainResp, err := rpcClient.NSDomainRPC().FindEnabledNSDomain(parent.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: domainId})
if err != nil {
return err
}
var domain = domainResp.NsDomain
if domain == nil {
return errors.New("InitDomain: can not find domain with id '" + types.String(domainId) + "'")
}
// 记录数量
countRecordsResp, err := rpcClient.NSRecordRPC().CountAllEnabledNSRecords(parent.AdminContext(), &pb.CountAllEnabledNSRecordsRequest{
NsDomainId: domainId,
})
if err != nil {
return err
}
var countRecords = countRecordsResp.Count
// Key数量
countKeysResp, err := rpcClient.NSKeyRPC().CountAllEnabledNSKeys(parent.AdminContext(), &pb.CountAllEnabledNSKeysRequest{
NsDomainId: domainId,
})
if err != nil {
return err
}
var countKeys = countKeysResp.Count
parent.Data["domain"] = maps.Map{
"id": domain.Id,
"name": domain.Name,
"countRecords": countRecords,
"countKeys": countKeys,
}
return nil
}

View File

@@ -1,96 +0,0 @@
package domains
import (
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "index")
}
func (this *IndexAction) RunGet(params struct {
ClusterId int64
UserId int64
Keyword string
}) {
if !teaconst.IsPlus {
this.RedirectURL("/")
return
}
this.Data["clusterId"] = params.ClusterId
this.Data["userId"] = params.UserId
this.Data["keyword"] = params.Keyword
// 集群数量
countClustersResp, err := this.RPC().NSClusterRPC().CountAllEnabledNSClusters(this.AdminContext(), &pb.CountAllEnabledNSClustersRequest{})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["countClusters"] = countClustersResp.Count
// 分页
countResp, err := this.RPC().NSDomainRPC().CountAllEnabledNSDomains(this.AdminContext(), &pb.CountAllEnabledNSDomainsRequest{
UserId: params.UserId,
NsClusterId: params.ClusterId,
Keyword: params.Keyword,
})
if err != nil {
this.ErrorPage(err)
return
}
page := this.NewPage(countResp.Count)
// 列表
domainsResp, err := this.RPC().NSDomainRPC().ListEnabledNSDomains(this.AdminContext(), &pb.ListEnabledNSDomainsRequest{
UserId: params.UserId,
NsClusterId: params.ClusterId,
Keyword: params.Keyword,
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)
return
}
domainMaps := []maps.Map{}
for _, domain := range domainsResp.NsDomains {
// 集群信息
var clusterMap maps.Map
if domain.NsCluster != nil {
clusterMap = maps.Map{
"id": domain.NsCluster.Id,
"name": domain.NsCluster.Name,
}
}
// 用户信息
var userMap maps.Map
if domain.User != nil {
userMap = maps.Map{
"id": domain.User.Id,
"username": domain.User.Username,
"fullname": domain.User.Fullname,
}
}
domainMaps = append(domainMaps, maps.Map{
"id": domain.Id,
"name": domain.Name,
"isOn": domain.IsOn,
"cluster": clusterMap,
"user": userMap,
})
}
this.Data["domains"] = domainMaps
this.Show()
}

View File

@@ -1,86 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package keys
import (
"encoding/base64"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type CreatePopupAction struct {
actionutils.ParentAction
}
func (this *CreatePopupAction) Init() {
this.Nav("", "", "")
}
func (this *CreatePopupAction) RunGet(params struct {
DomainId int64
}) {
this.Data["domainId"] = params.DomainId
// 所有算法
var algorithmMaps = []maps.Map{}
for _, algo := range dnsconfigs.FindAllKeyAlgorithmTypes() {
algorithmMaps = append(algorithmMaps, maps.Map{
"name": algo.Name,
"code": algo.Code,
})
}
this.Data["algorithms"] = algorithmMaps
this.Show()
}
func (this *CreatePopupAction) RunPost(params struct {
DomainId int64
Name string
Algo string
Secret string
SecretType string
Must *actions.Must
CSRF *actionutils.CSRF
}) {
var keyId int64 = 0
defer func() {
this.CreateLogInfo("创建DNS密钥 %d", keyId)
}()
params.Must.
Field("name", params.Name).
Require("请输入密钥名称").
Field("algo", params.Algo).
Require("请选择算法").
Field("secret", params.Secret).
Require("请输入密码")
// 校验密码
if params.SecretType == dnsconfigs.NSKeySecretTypeBase64 {
_, err := base64.StdEncoding.DecodeString(params.Secret)
if err != nil {
this.FailField("secret", "请输入BASE64格式的密码或者选择明文")
}
}
createResp, err := this.RPC().NSKeyRPC().CreateNSKey(this.AdminContext(), &pb.CreateNSKeyRequest{
NsDomainId: params.DomainId,
NsZoneId: 0,
Name: params.Name,
Algo: params.Algo,
Secret: params.Secret,
SecretType: params.SecretType,
})
if err != nil {
this.ErrorPage(err)
return
}
keyId = createResp.NsKeyId
this.Success()
}

View File

@@ -1,26 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package keys
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteAction struct {
actionutils.ParentAction
}
func (this *DeleteAction) RunPost(params struct {
KeyId int64
}) {
defer this.CreateLogInfo("删除DNS密钥 %d", params.KeyId)
_, err := this.RPC().NSKeyRPC().DeleteNSKey(this.AdminContext(), &pb.DeleteNSKeyRequest{NsKeyId: params.KeyId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,29 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package keys
import (
"encoding/base64"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/iwind/TeaGo/rands"
)
type GenerateSecretAction struct {
actionutils.ParentAction
}
func (this *GenerateSecretAction) RunPost(params struct {
SecretType string
}) {
switch params.SecretType {
case dnsconfigs.NSKeySecretTypeClear:
this.Data["secret"] = rands.HexString(128)
case dnsconfigs.NSKeySecretTypeBase64:
this.Data["secret"] = base64.StdEncoding.EncodeToString([]byte(rands.HexString(128)))
default:
this.Data["secret"] = rands.HexString(128)
}
this.Success()
}

View File

@@ -1,68 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package keys
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "key")
}
func (this *IndexAction) RunGet(params struct {
DomainId int64
}) {
// 初始化域名信息
err := domainutils.InitDomain(this.Parent(), params.DomainId)
if err != nil {
this.ErrorPage(err)
return
}
// 数量
countResp, err := this.RPC().NSKeyRPC().CountAllEnabledNSKeys(this.AdminContext(), &pb.CountAllEnabledNSKeysRequest{
NsDomainId: params.DomainId,
NsZoneId: 0,
})
if err != nil {
this.ErrorPage(err)
return
}
var page = this.NewPage(countResp.Count)
this.Data["page"] = page.AsHTML()
// 列表
keysResp, err := this.RPC().NSKeyRPC().ListEnabledNSKeys(this.AdminContext(), &pb.ListEnabledNSKeysRequest{
NsDomainId: params.DomainId,
NsZoneId: 0,
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)
return
}
var keyMaps = []maps.Map{}
for _, key := range keysResp.NsKeys {
keyMaps = append(keyMaps, maps.Map{
"id": key.Id,
"name": key.Name,
"secret": key.Secret,
"secretTypeName": dnsconfigs.FindKeySecretTypeName(key.SecretType),
"algoName": dnsconfigs.FindKeyAlgorithmTypeName(key.Algo),
"isOn": key.IsOn,
})
}
this.Data["keys"] = keyMaps
this.Show()
}

View File

@@ -1,100 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package keys
import (
"encoding/base64"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type UpdatePopupAction struct {
actionutils.ParentAction
}
func (this *UpdatePopupAction) Init() {
this.Nav("", "", "")
}
func (this *UpdatePopupAction) RunGet(params struct {
KeyId int64
}) {
keyResp, err := this.RPC().NSKeyRPC().FindEnabledNSKey(this.AdminContext(), &pb.FindEnabledNSKeyRequest{NsKeyId: params.KeyId})
if err != nil {
this.ErrorPage(err)
return
}
var key = keyResp.NsKey
if key == nil {
return
}
this.Data["key"] = maps.Map{
"id": key.Id,
"name": key.Name,
"algo": key.Algo,
"secret": key.Secret,
"secretType": key.SecretType,
"isOn": key.IsOn,
}
// 所有算法
var algorithmMaps = []maps.Map{}
for _, algo := range dnsconfigs.FindAllKeyAlgorithmTypes() {
algorithmMaps = append(algorithmMaps, maps.Map{
"name": algo.Name,
"code": algo.Code,
})
}
this.Data["algorithms"] = algorithmMaps
this.Show()
}
func (this *UpdatePopupAction) RunPost(params struct {
KeyId int64
Name string
Algo string
Secret string
SecretType string
IsOn bool
Must *actions.Must
CSRF *actionutils.CSRF
}) {
this.CreateLogInfo("修改DNS密钥 %d", params.KeyId)
params.Must.
Field("name", params.Name).
Require("请输入密钥名称").
Field("algo", params.Algo).
Require("请选择算法").
Field("secret", params.Secret).
Require("请输入密码")
// 校验密码
if params.SecretType == dnsconfigs.NSKeySecretTypeBase64 {
_, err := base64.StdEncoding.DecodeString(params.Secret)
if err != nil {
this.FailField("secret", "请输入BASE64格式的密码或者选择明文")
}
}
_, err := this.RPC().NSKeyRPC().UpdateNSKey(this.AdminContext(), &pb.UpdateNSKeyRequest{
NsKeyId: params.KeyId,
Name: params.Name,
Algo: params.Algo,
Secret: params.Secret,
SecretType: params.SecretType,
IsOn: params.IsOn,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,94 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package records
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type CreatePopupAction struct {
actionutils.ParentAction
}
func (this *CreatePopupAction) Init() {
this.Nav("", "", "")
}
func (this *CreatePopupAction) RunGet(params struct {
DomainId int64
}) {
// 域名信息
domainResp, err := this.RPC().NSDomainRPC().FindEnabledNSDomain(this.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: params.DomainId})
if err != nil {
this.ErrorPage(err)
return
}
domain := domainResp.NsDomain
if domain == nil {
this.NotFound("nsDomain", params.DomainId)
return
}
this.Data["domain"] = maps.Map{
"id": domain.Id,
"name": domain.Name,
}
// 类型
this.Data["types"] = dnsconfigs.FindAllRecordTypeDefinitions()
// TTL
this.Data["ttlValues"] = dnsconfigs.FindAllRecordTTL()
this.Show()
}
func (this *CreatePopupAction) RunPost(params struct {
DomainId int64
Name string
Type string
Value string
Ttl int32
Description string
RouteCodes []string
Must *actions.Must
CSRF *actionutils.CSRF
}) {
var recordId int64
defer func() {
this.CreateLogInfo("创建域名记录 %d", recordId)
}()
// 校验记录名
if !domainutils.ValidateRecordName(params.Name) {
this.FailField("name", "请输入正确的记录名")
}
// 校验记录值
message, ok := domainutils.ValidateRecordValue(params.Type, params.Value)
if !ok {
this.FailField("value", "记录值错误:"+message)
}
createResp, err := this.RPC().NSRecordRPC().CreateNSRecord(this.AdminContext(), &pb.CreateNSRecordRequest{
NsDomainId: params.DomainId,
Description: params.Description,
Name: params.Name,
Type: params.Type,
Value: params.Value,
Ttl: params.Ttl,
NsRouteCodes: params.RouteCodes,
})
if err != nil {
this.ErrorPage(err)
return
}
recordId = createResp.NsRecordId
this.Success()
}

View File

@@ -1,26 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package records
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteAction struct {
actionutils.ParentAction
}
func (this *DeleteAction) RunPost(params struct {
RecordId int64
}) {
defer this.CreateLogInfo("删除域名记录 %d", params.RecordId)
_, err := this.RPC().NSRecordRPC().DeleteNSRecord(this.AdminContext(), &pb.DeleteNSRecordRequest{NsRecordId: params.RecordId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,93 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package records
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "record")
}
func (this *IndexAction) RunGet(params struct {
DomainId int64
Type string
Keyword string
RouteCode string
}) {
// 初始化域名信息
err := domainutils.InitDomain(this.Parent(), params.DomainId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["type"] = params.Type
this.Data["keyword"] = params.Keyword
this.Data["routeCode"] = params.RouteCode
// 记录
countResp, err := this.RPC().NSRecordRPC().CountAllEnabledNSRecords(this.AdminContext(), &pb.CountAllEnabledNSRecordsRequest{
NsDomainId: params.DomainId,
Type: params.Type,
NsRouteCode: params.RouteCode,
Keyword: params.Keyword,
})
if err != nil {
this.ErrorPage(err)
return
}
count := countResp.Count
page := this.NewPage(count)
this.Data["page"] = page.AsHTML()
recordsResp, err := this.RPC().NSRecordRPC().ListEnabledNSRecords(this.AdminContext(), &pb.ListEnabledNSRecordsRequest{
NsDomainId: params.DomainId,
Type: params.Type,
NsRouteCode: params.RouteCode,
Keyword: params.Keyword,
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)
return
}
var recordMaps = []maps.Map{}
for _, record := range recordsResp.NsRecords {
routeMaps := []maps.Map{}
for _, route := range record.NsRoutes {
routeMaps = append(routeMaps, maps.Map{
"id": route.Id,
"name": route.Name,
})
}
recordMaps = append(recordMaps, maps.Map{
"id": record.Id,
"name": record.Name,
"type": record.Type,
"value": record.Value,
"ttl": record.Ttl,
"weight": record.Weight,
"description": record.Description,
"isOn": record.IsOn,
"routes": routeMaps,
})
}
this.Data["records"] = recordMaps
// 所有记录类型
this.Data["types"] = dnsconfigs.FindAllRecordTypeDefinitions()
this.Show()
}

View File

@@ -1,115 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package records
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type UpdatePopupAction struct {
actionutils.ParentAction
}
func (this *UpdatePopupAction) Init() {
this.Nav("", "", "")
}
func (this *UpdatePopupAction) RunGet(params struct {
RecordId int64
}) {
recordResp, err := this.RPC().NSRecordRPC().FindEnabledNSRecord(this.AdminContext(), &pb.FindEnabledNSRecordRequest{NsRecordId: params.RecordId})
if err != nil {
this.ErrorPage(err)
return
}
record := recordResp.NsRecord
if record == nil {
this.NotFound("nsRecord", params.RecordId)
return
}
this.Data["record"] = maps.Map{
"id": record.Id,
"name": record.Name,
"type": record.Type,
"value": record.Value,
"ttl": record.Ttl,
"weight": record.Weight,
"description": record.Description,
"isOn": record.IsOn,
"routes": record.NsRoutes,
}
// 域名信息
domainResp, err := this.RPC().NSDomainRPC().FindEnabledNSDomain(this.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: record.NsDomain.Id})
if err != nil {
this.ErrorPage(err)
return
}
domain := domainResp.NsDomain
if domain == nil {
this.NotFound("nsDomain", record.NsDomain.Id)
return
}
this.Data["domain"] = maps.Map{
"id": domain.Id,
"name": domain.Name,
}
// 类型
this.Data["types"] = dnsconfigs.FindAllRecordTypeDefinitions()
// TTL
this.Data["ttlValues"] = dnsconfigs.FindAllRecordTTL()
this.Show()
}
func (this *UpdatePopupAction) RunPost(params struct {
RecordId int64
Name string
Type string
Value string
Ttl int32
Description string
IsOn bool
RouteCodes []string
Must *actions.Must
CSRF *actionutils.CSRF
}) {
this.CreateLogInfo("修改域名记录 %d", params.RecordId)
// 校验记录名
if !domainutils.ValidateRecordName(params.Name) {
this.FailField("name", "请输入正确的记录名")
}
// 校验记录值
message, ok := domainutils.ValidateRecordValue(params.Type, params.Value)
if !ok {
this.FailField("value", "记录值错误:"+message)
}
_, err := this.RPC().NSRecordRPC().UpdateNSRecord(this.AdminContext(), &pb.UpdateNSRecordRequest{
NsRecordId: params.RecordId,
Description: params.Description,
Name: params.Name,
Type: params.Type,
Value: params.Value,
Ttl: params.Ttl,
IsOn: params.IsOn,
NsRouteCodes: params.RouteCodes,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,80 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package domains
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/logs"
)
type TsigAction struct {
actionutils.ParentAction
}
func (this *TsigAction) Init() {
this.Nav("", "", "tsig")
}
func (this *TsigAction) RunGet(params struct {
DomainId int64
}) {
// 初始化域名信息
err := domainutils.InitDomain(this.Parent(), params.DomainId)
if err != nil {
this.ErrorPage(err)
return
}
// TSIG信息
tsigResp, err := this.RPC().NSDomainRPC().FindEnabledNSDomainTSIG(this.AdminContext(), &pb.FindEnabledNSDomainTSIGRequest{NsDomainId: params.DomainId})
if err != nil {
this.ErrorPage(err)
return
}
var tsigJSON = tsigResp.TsigJSON
var tsigConfig = &dnsconfigs.TSIGConfig{}
if len(tsigJSON) > 0 {
err = json.Unmarshal(tsigJSON, tsigConfig)
if err != nil {
// 只是提示错误,仍然允许用户修改
logs.Error(err)
}
}
this.Data["tsig"] = tsigConfig
this.Show()
}
func (this *TsigAction) RunPost(params struct {
DomainId int64
IsOn bool
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo("修改DNS域名 %d 的TSIG配置", params.DomainId)
var tsigConfig = &dnsconfigs.TSIGConfig{
IsOn: params.IsOn,
}
tsigJSON, err := json.Marshal(tsigConfig)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().NSDomainRPC().UpdateNSDomainTSIG(this.AdminContext(), &pb.UpdateNSDomainTSIGRequest{
NsDomainId: params.DomainId,
TsigJSON: tsigJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,96 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package domains
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type UpdateAction struct {
actionutils.ParentAction
}
func (this *UpdateAction) Init() {
this.Nav("", "", "update")
}
func (this *UpdateAction) RunGet(params struct {
DomainId int64
}) {
// 初始化域名信息
err := domainutils.InitDomain(this.Parent(), params.DomainId)
if err != nil {
this.ErrorPage(err)
return
}
var countRecords = this.Data.GetMap("domain").GetInt64("countRecords")
var countKeys = this.Data.GetMap("domain").GetInt64("countKeys")
// 域名信息
domainResp, err := this.RPC().NSDomainRPC().FindEnabledNSDomain(this.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: params.DomainId})
if err != nil {
this.ErrorPage(err)
return
}
domain := domainResp.NsDomain
if domain == nil {
this.NotFound("nsDomain", params.DomainId)
return
}
var clusterId = int64(0)
if domain.NsCluster != nil {
clusterId = domain.NsCluster.Id
}
// 用户信息
var userId = int64(0)
if domain.User != nil {
userId = domain.User.Id
}
this.Data["domain"] = maps.Map{
"id": domain.Id,
"name": domain.Name,
"isOn": domain.IsOn,
"clusterId": clusterId,
"userId": userId,
"countRecords": countRecords,
"countKeys": countKeys,
}
this.Show()
}
func (this *UpdateAction) RunPost(params struct {
DomainId int64
ClusterId int64
UserId int64
IsOn bool
Must *actions.Must
CSRF *actionutils.CSRF
}) {
this.CreateLogInfo("修改域名 %d", params.DomainId)
params.Must.
Field("clusterId", params.ClusterId).
Gt(0, "请选择所属集群")
_, err := this.RPC().NSDomainRPC().UpdateNSDomain(this.AdminContext(), &pb.UpdateNSDomainRequest{
NsDomainId: params.DomainId,
NsClusterId: params.ClusterId,
UserId: params.UserId,
IsOn: params.IsOn,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,63 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
)
type CreatePopupAction struct {
actionutils.ParentAction
}
func (this *CreatePopupAction) Init() {
}
func (this *CreatePopupAction) RunGet(params struct {
ClusterId int64
DomainId int64
UserId int64
}) {
this.Data["clusterId"] = params.ClusterId
this.Data["domainId"] = params.DomainId
this.Data["userId"] = params.UserId
this.Show()
}
func (this *CreatePopupAction) RunPost(params struct {
ClusterId int64
DomainId int64
UserId int64
Name string
RangesJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
var routeId = int64(0)
defer func() {
this.CreateLogInfo("创建域名服务线路 %d", routeId)
}()
params.Must.Field("name", params.Name).
Require("请输入线路名称")
createResp, err := this.RPC().NSRouteRPC().CreateNSRoute(this.AdminContext(), &pb.CreateNSRouteRequest{
NsClusterId: params.ClusterId,
NsDomainId: params.DomainId,
UserId: params.UserId,
Name: params.Name,
RangesJSON: params.RangesJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
routeId = createResp.NsRouteId
this.Success()
}

View File

@@ -1,26 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteAction struct {
actionutils.ParentAction
}
func (this *DeleteAction) RunPost(params struct {
RouteId int64
}) {
defer this.CreateLogInfo("删除域名服务线路 %d", params.RouteId)
_, err := this.RPC().NSRouteRPC().DeleteNSRoute(this.AdminContext(), &pb.DeleteNSRouteRequest{NsRouteId: params.RouteId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,41 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "index")
}
func (this *IndexAction) RunGet(params struct{}) {
routesResp, err := this.RPC().NSRouteRPC().FindAllEnabledNSRoutes(this.AdminContext(), &pb.FindAllEnabledNSRoutesRequest{
NsClusterId: 0,
NsDomainId: 0,
UserId: 0,
})
if err != nil {
this.ErrorPage(err)
return
}
routeMaps := []maps.Map{}
for _, route := range routesResp.NsRoutes {
routeMaps = append(routeMaps, maps.Map{
"id": route.Id,
"name": route.Name,
"isOn": route.IsOn,
})
}
this.Data["routes"] = routeMaps
this.Show()
}

View File

@@ -1,86 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
)
type OptionsAction struct {
actionutils.ParentAction
}
func (this *OptionsAction) RunPost(params struct {
ClusterId int64
DomainId int64
UserId int64
}) {
var routeMaps = []maps.Map{}
// 默认线路
for _, route := range dnsconfigs.AllDefaultRoutes {
routeMaps = append(routeMaps, maps.Map{
"name": route.Name,
"code": route.Code,
"type": "default",
})
}
// 自定义
routesResp, err := this.RPC().NSRouteRPC().FindAllEnabledNSRoutes(this.AdminContext(), &pb.FindAllEnabledNSRoutesRequest{
NsClusterId: params.ClusterId,
NsDomainId: params.DomainId,
UserId: params.UserId,
})
if err != nil {
this.ErrorPage(err)
return
}
for _, route := range routesResp.NsRoutes {
if len(route.Code) == 0 {
route.Code = "id:" + types.String(route.Id)
}
routeMaps = append(routeMaps, maps.Map{
"name": route.Name,
"code": route.Code,
"type": "user",
})
}
// 运营商
for _, route := range dnsconfigs.AllDefaultISPRoutes {
routeMaps = append(routeMaps, maps.Map{
"name": route.Name,
"code": route.Code,
"type": "isp",
})
}
// 中国
for _, route := range dnsconfigs.AllDefaultChinaProvinceRoutes {
routeMaps = append(routeMaps, maps.Map{
"name": route.Name,
"code": route.Code,
"type": "china",
})
}
// 全球
for _, route := range dnsconfigs.AllDefaultWorldRegionRoutes {
routeMaps = append(routeMaps, maps.Map{
"name": route.Name,
"code": route.Code,
"type": "world",
})
}
this.Data["routes"] = routeMaps
this.Success()
}

View File

@@ -1,17 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
type RouteAction struct {
actionutils.ParentAction
}
func (this *RouteAction) Init() {
this.Nav("", "", "")
}
func (this *RouteAction) RunGet(params struct{}) {
this.Show()
}

View File

@@ -1,26 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type SortAction struct {
actionutils.ParentAction
}
func (this *SortAction) RunPost(params struct {
RouteIds []int64
}) {
defer this.CreateLogInfo("对线路进行排序")
_, err := this.RPC().NSRouteRPC().UpdateNSRouteOrders(this.AdminContext(), &pb.UpdateNSRouteOrdersRequest{NsRouteIds: params.RouteIds})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,78 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type UpdatePopupAction struct {
actionutils.ParentAction
}
func (this *UpdatePopupAction) Init() {
this.Nav("", "", "")
}
func (this *UpdatePopupAction) RunGet(params struct {
RouteId int64
}) {
routeResp, err := this.RPC().NSRouteRPC().FindEnabledNSRoute(this.AdminContext(), &pb.FindEnabledNSRouteRequest{NsRouteId: params.RouteId})
if err != nil {
this.ErrorPage(err)
return
}
route := routeResp.NsRoute
if route == nil {
this.NotFound("nsRoute", params.RouteId)
return
}
rangeMaps := []maps.Map{}
if len(route.RangesJSON) > 0 {
err = json.Unmarshal([]byte(route.RangesJSON), &rangeMaps)
if err != nil {
this.ErrorPage(err)
return
}
}
this.Data["route"] = maps.Map{
"id": route.Id,
"name": route.Name,
"isOn": route.IsOn,
"ranges": rangeMaps,
}
this.Show()
}
func (this *UpdatePopupAction) RunPost(params struct {
RouteId int64
Name string
RangesJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo("修改域名线路 %d", params.RouteId)
params.Must.Field("name", params.Name).
Require("请输入线路名称")
_, err := this.RPC().NSRouteRPC().UpdateNSRoute(this.AdminContext(), &pb.UpdateNSRouteRequest{
NsRouteId: params.RouteId,
Name: params.Name,
RangesJSON: params.RangesJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,77 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package accesslogs
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "")
this.SecondMenu("accessLog")
}
func (this *IndexAction) RunGet(params struct{}) {
resp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{
Code: systemconfigs.SettingCodeNSAccessLogSetting,
})
if err != nil {
this.ErrorPage(err)
return
}
var config = &dnsconfigs.NSAccessLogRef{}
if len(resp.ValueJSON) > 0 {
err = json.Unmarshal(resp.ValueJSON, config)
if err != nil {
this.ErrorPage(err)
return
}
} else {
config.IsOn = true
config.LogMissingDomains = true
}
this.Data["config"] = config
this.Show()
}
func (this *IndexAction) RunPost(params struct {
AccessLogJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
// 校验配置
var config = &dnsconfigs.NSAccessLogRef{}
err := json.Unmarshal(params.AccessLogJSON, config)
if err != nil {
this.Fail("配置解析失败:" + err.Error())
}
err = config.Init()
if err != nil {
this.Fail("配置校验失败:" + err.Error())
}
_, err = this.RPC().SysSettingRPC().UpdateSysSetting(this.AdminContext(), &pb.UpdateSysSettingRequest{
Code: systemconfigs.SettingCodeNSAccessLogSetting,
ValueJSON: params.AccessLogJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,17 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package settings
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "")
}
func (this *IndexAction) RunGet(params struct{}) {
this.RedirectURL("/ns/settings/accesslogs")
}

View File

@@ -1,28 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package settingutils
import (
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type Helper struct {
}
func (this *Helper) BeforeAction(actionPtr actions.ActionWrapper) (goNext bool) {
var action = actionPtr.Object()
secondMenuItem := action.Data.GetString("secondMenuItem")
action.Data["leftMenuItems"] = this.createSettingMenu(secondMenuItem)
return true
}
func (this *Helper) createSettingMenu(selectedItem string) (items []maps.Map) {
return []maps.Map{
{
"name": "访问日志",
"url": "/ns/settings/accesslogs",
"isActive": selectedItem == "accessLog",
},
}
}

View File

@@ -1,11 +1,14 @@
package servers
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/types"
"net/url"
"regexp"
"strings"
@@ -31,13 +34,17 @@ func (this *AddOriginPopupAction) RunPost(params struct {
Protocol string
Addr string
DomainsJSON []byte
Host string
FollowPort bool
Must *actions.Must
}) {
params.Must.
Field("addr", params.Addr).
Require("请输入源站地址")
addr := params.Addr
var addr = params.Addr
// 是否是完整的地址
if (params.Protocol == "http" || params.Protocol == "https") && regexp.MustCompile(`^(http|https)://`).MatchString(addr) {
@@ -48,7 +55,7 @@ func (this *AddOriginPopupAction) RunPost(params struct {
}
addr = regexp.MustCompile(`\s+`).ReplaceAllString(addr, "")
portIndex := strings.LastIndex(addr, ":")
var portIndex = strings.LastIndex(addr, ":")
if portIndex < 0 {
if params.Protocol == "http" {
addr += ":80"
@@ -59,8 +66,41 @@ func (this *AddOriginPopupAction) RunPost(params struct {
}
portIndex = strings.LastIndex(addr, ":")
}
host := addr[:portIndex]
port := addr[portIndex+1:]
var host = addr[:portIndex]
var port = addr[portIndex+1:]
// 检查端口号
if port == "0" {
this.Fail("端口号不能为0")
}
if !configutils.HasVariables(port) {
// 必须是整数
if !regexp.MustCompile(`^\d+$`).MatchString(port) {
this.Fail("端口号只能为整数")
}
var portInt = types.Int(port)
if portInt == 0 {
this.Fail("端口号不能为0")
}
if portInt > 65535 {
this.Fail("端口号不能大于65535")
}
}
// 专属域名
var domains = []string{}
if len(params.DomainsJSON) > 0 {
err := json.Unmarshal(params.DomainsJSON, &domains)
if err != nil {
this.ErrorPage(err)
return
}
// 去除可能误加的斜杠
for index, domain := range domains {
domains[index] = strings.TrimSuffix(domain, "/")
}
}
resp, err := this.RPC().OriginRPC().CreateOrigin(this.AdminContext(), &pb.CreateOriginRequest{
Name: "",
@@ -72,13 +112,16 @@ func (this *AddOriginPopupAction) RunPost(params struct {
Description: "",
Weight: 10,
IsOn: true,
Domains: domains,
Host: params.Host,
FollowPort: params.FollowPort,
})
if err != nil {
this.ErrorPage(err)
return
}
origin := &serverconfigs.OriginConfig{
var origin = &serverconfigs.OriginConfig{
Id: resp.OriginId,
IsOn: true,
Addr: &serverconfigs.NetworkAddressConfig{

View File

@@ -4,6 +4,7 @@ import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
"net/url"
"regexp"
"strings"
)
@@ -29,11 +30,25 @@ func (this *AddServerNamePopupAction) RunPost(params struct {
Must *actions.Must
}) {
if params.Mode == "single" {
var serverName = params.ServerName
// 去除空格
serverName = regexp.MustCompile(`\s+`).ReplaceAllString(serverName, "")
// 处理URL
if regexp.MustCompile(`^(?i)(http|https|ftp)://`).MatchString(serverName) {
u, err := url.Parse(serverName)
if err == nil && len(u.Host) > 0 {
serverName = u.Host
}
}
params.Must.
Field("serverName", params.ServerName).
Field("serverName", serverName).
Require("请输入域名")
this.Data["serverName"] = maps.Map{
"name": params.ServerName,
"name": serverName,
"type": "full",
}
} else if params.Mode == "multiple" {
@@ -41,14 +56,23 @@ func (this *AddServerNamePopupAction) RunPost(params struct {
this.FailField("serverNames", "请输入至少域名")
}
serverNames := []string{}
var serverNames = []string{}
for _, line := range strings.Split(params.ServerNames, "\n") {
line := strings.TrimSpace(line)
line = regexp.MustCompile(`\s+`).ReplaceAllString(line, "")
if len(line) == 0 {
var serverName = strings.TrimSpace(line)
serverName = regexp.MustCompile(`\s+`).ReplaceAllString(serverName, "")
if len(serverName) == 0 {
continue
}
serverNames = append(serverNames, line)
// 处理URL
if regexp.MustCompile(`^(?i)(http|https|ftp)://`).MatchString(serverName) {
u, err := url.Parse(serverName)
if err == nil && len(u.Host) > 0 {
serverName = u.Host
}
}
serverNames = append(serverNames, serverName)
}
this.Data["serverName"] = maps.Map{
"name": "",

View File

@@ -15,6 +15,7 @@ func init() {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(NewHelper()).
Data("teaMenu", "servers").
Data("teaSubMenu", "cert").
Prefix("/servers/certs").
Data("leftMenuItem", "cert").

View File

@@ -0,0 +1,28 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package cache
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteTaskAction struct {
actionutils.ParentAction
}
func (this *DeleteTaskAction) RunPost(params struct {
TaskId int64
}) {
defer this.CreateLogInfo("删除缓存任务 %d", params.TaskId)
_, err := this.RPC().HTTPCacheTaskRPC().DeleteHTTPCacheTask(this.AdminContext(), &pb.DeleteHTTPCacheTaskRequest{
HttpCacheTaskId: params.TaskId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,97 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package cache
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"strings"
)
type FetchAction struct {
actionutils.ParentAction
}
func (this *FetchAction) Init() {
this.Nav("", "", "fetch")
}
func (this *FetchAction) RunGet(params struct{}) {
// 初始化菜单数据
err := InitMenu(this.Parent())
if err != nil {
this.ErrorPage(err)
return
}
this.Show()
}
func (this *FetchAction) RunPost(params struct {
Keys string
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo("批量预热缓存Key")
if len(params.Keys) == 0 {
this.Fail("请输入要预热的Key列表")
}
// 检查Key
var realKeys = []string{}
for _, key := range strings.Split(params.Keys, "\n") {
key = strings.TrimSpace(key)
if len(key) == 0 {
continue
}
if lists.ContainsString(realKeys, key) {
continue
}
realKeys = append(realKeys, key)
}
if len(realKeys) == 0 {
this.Fail("请输入要预热的Key列表")
}
// 校验Key
validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys})
if err != nil {
this.ErrorPage(err)
return
}
var failKeyMaps = []maps.Map{}
if len(validateResp.FailKeys) > 0 {
for _, key := range validateResp.FailKeys {
failKeyMaps = append(failKeyMaps, maps.Map{
"key": key.Key,
"reason": cacheutils.KeyFailReason(key.ReasonCode),
})
}
}
this.Data["failKeys"] = failKeyMaps
if len(failKeyMaps) > 0 {
this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作请删除后重试")
}
// 提交任务
_, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{
Type: "fetch",
KeyType: "key",
Keys: realKeys,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,102 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package cache
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"strings"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "purge")
}
func (this *IndexAction) RunGet(params struct {
KeyType string
}) {
// 初始化菜单数据
err := InitMenu(this.Parent())
if err != nil {
this.ErrorPage(err)
return
}
this.Data["keyType"] = params.KeyType
this.Show()
}
func (this *IndexAction) RunPost(params struct {
KeyType string
Keys string
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo("批量刷新缓存Key")
if len(params.Keys) == 0 {
this.Fail("请输入要刷新的Key列表")
}
// 检查Key
var realKeys = []string{}
for _, key := range strings.Split(params.Keys, "\n") {
key = strings.TrimSpace(key)
if len(key) == 0 {
continue
}
if lists.ContainsString(realKeys, key) {
continue
}
realKeys = append(realKeys, key)
}
if len(realKeys) == 0 {
this.Fail("请输入要刷新的Key列表")
}
// 校验Key
validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys})
if err != nil {
this.ErrorPage(err)
return
}
var failKeyMaps = []maps.Map{}
if len(validateResp.FailKeys) > 0 {
for _, key := range validateResp.FailKeys {
failKeyMaps = append(failKeyMaps, maps.Map{
"key": key.Key,
"reason": cacheutils.KeyFailReason(key.ReasonCode),
})
}
}
this.Data["failKeys"] = failKeyMaps
if len(failKeyMaps) > 0 {
this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作请删除后重试")
}
// 提交任务
_, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{
Type: "purge",
KeyType: params.KeyType,
Keys: realKeys,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,24 @@
package cache
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Data("teaMenu", "servers").
Data("teaSubMenu", "cacheBatch").
Prefix("/servers/components/cache/batch").
GetPost("", new(IndexAction)).
GetPost("/fetch", new(FetchAction)).
Get("/tasks", new(TasksAction)).
GetPost("/task", new(TaskAction)).
Post("/deleteTask", new(DeleteTaskAction)).
Post("/resetTask", new(ResetTaskAction)).
EndAll()
})
}

View File

@@ -0,0 +1,26 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package cache
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type ResetTaskAction struct {
actionutils.ParentAction
}
func (this *ResetTaskAction) RunPost(params struct {
TaskId int64
}) {
this.CreateLogInfo("重置缓存任务 %d 状态", params.TaskId)
_, err := this.RPC().HTTPCacheTaskRPC().ResetHTTPCacheTask(this.AdminContext(), &pb.ResetHTTPCacheTaskRequest{HttpCacheTaskId: params.TaskId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,124 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package cache
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
"sort"
)
type TaskAction struct {
actionutils.ParentAction
}
func (this *TaskAction) Init() {
this.Nav("", "", "task")
}
func (this *TaskAction) RunGet(params struct {
TaskId int64
}) {
// 初始化菜单数据
err := InitMenu(this.Parent())
if err != nil {
this.ErrorPage(err)
return
}
if !this.readTask(params.TaskId) {
return
}
this.Show()
}
func (this *TaskAction) RunPost(params struct {
TaskId int64
}) {
if !this.readTask(params.TaskId) {
return
}
this.Success()
}
// 读取任务信息
func (this *TaskAction) readTask(taskId int64) (ok bool) {
taskResp, err := this.RPC().HTTPCacheTaskRPC().FindEnabledHTTPCacheTask(this.AdminContext(), &pb.FindEnabledHTTPCacheTaskRequest{HttpCacheTaskId: taskId})
if err != nil {
this.ErrorPage(err)
return
}
var task = taskResp.HttpCacheTask
if task == nil {
this.NotFound("HTTPCacheTask", taskId)
return
}
// 用户
var userMap = maps.Map{"id": 0, "username": "", "fullname": ""}
if task.User != nil {
userMap = maps.Map{
"id": task.User.Id,
"username": task.User.Username,
"fullname": task.User.Fullname,
}
}
// keys
var keyMaps = []maps.Map{}
for _, key := range task.HttpCacheTaskKeys {
// 错误信息
var errorMaps = []maps.Map{}
if len(key.ErrorsJSON) > 0 {
var m = map[int64]string{}
err = json.Unmarshal(key.ErrorsJSON, &m)
if err != nil {
this.ErrorPage(err)
return
}
for nodeId, errString := range m {
errorMaps = append(errorMaps, maps.Map{
"nodeId": nodeId,
"error": errString,
})
}
}
// 错误信息排序
if len(errorMaps) > 0 {
sort.Slice(errorMaps, func(i, j int) bool {
var m1 = errorMaps[i]
var m2 = errorMaps[j]
return m1.GetInt64("nodeId") < m2.GetInt64("nodeId")
})
}
keyMaps = append(keyMaps, maps.Map{
"key": key.Key,
"isDone": key.IsDone,
"isDoing": key.IsDoing,
"errors": errorMaps,
})
}
this.Data["task"] = maps.Map{
"id": task.Id,
"type": task.Type,
"keyType": task.KeyType,
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", task.CreatedAt),
"doneTime": timeutil.FormatTime("Y-m-d H:i:s", task.DoneAt),
"isDone": task.IsDone,
"isOk": task.IsOk,
"keys": keyMaps,
"user": userMap,
}
ok = true
return
}

View File

@@ -0,0 +1,73 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package cache
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
)
type TasksAction struct {
actionutils.ParentAction
}
func (this *TasksAction) Init() {
this.Nav("", "", "task")
}
func (this *TasksAction) RunGet(params struct{}) {
// 初始化菜单数据
err := InitMenu(this.Parent())
if err != nil {
this.ErrorPage(err)
return
}
// 任务数量
countResp, err := this.RPC().HTTPCacheTaskRPC().CountHTTPCacheTasks(this.AdminContext(), &pb.CountHTTPCacheTasksRequest{})
if err != nil {
this.ErrorPage(err)
return
}
var count = countResp.Count
var page = this.NewPage(count)
this.Data["page"] = page.AsHTML()
// 任务列表
var taskMaps = []maps.Map{}
tasksResp, err := this.RPC().HTTPCacheTaskRPC().ListHTTPCacheTasks(this.AdminContext(), &pb.ListHTTPCacheTasksRequest{
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)
return
}
for _, task := range tasksResp.HttpCacheTasks {
var userMap = maps.Map{"id": 0, "username": "", "fullname": ""}
if task.User != nil {
userMap = maps.Map{
"id": task.User.Id,
"username": task.User.Username,
"fullname": task.User.Fullname,
}
}
taskMaps = append(taskMaps, maps.Map{
"id": task.Id,
"type": task.Type,
"keyType": task.KeyType,
"isDone": task.IsDone,
"isOk": task.IsOk,
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", task.CreatedAt),
"description": task.Description,
"user": userMap,
})
}
this.Data["tasks"] = taskMaps
this.Show()
}

View File

@@ -0,0 +1,24 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package cache
import (
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
func InitMenu(parent *actionutils.ParentAction) error {
rpcClient, err := rpc.SharedRPC()
if err != nil {
return err
}
countTasksResp, err := rpcClient.HTTPCacheTaskRPC().CountDoingHTTPCacheTasks(parent.AdminContext(), &pb.CountDoingHTTPCacheTasksRequest{})
if err != nil {
return err
}
parent.Data["countDoingTasks"] = countTasksResp.Count
return nil
}

View File

@@ -8,7 +8,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
)
// 查找缓存策略名称并忽略错误
// FindCachePolicyNameWithoutError 查找缓存策略名称并忽略错误
func FindCachePolicyNameWithoutError(parent *actionutils.ParentAction, cachePolicyId int64) string {
policy, err := FindCachePolicy(parent, cachePolicyId)
if err != nil {
@@ -20,7 +20,7 @@ func FindCachePolicyNameWithoutError(parent *actionutils.ParentAction, cachePoli
return policy.Name
}
// 查找缓存策略配置
// FindCachePolicy 查找缓存策略配置
func FindCachePolicy(parent *actionutils.ParentAction, cachePolicyId int64) (*serverconfigs.HTTPCachePolicy, error) {
resp, err := parent.RPC().HTTPCachePolicyRPC().FindEnabledHTTPCachePolicyConfig(parent.AdminContext(), &pb.FindEnabledHTTPCachePolicyConfigRequest{HttpCachePolicyId: cachePolicyId})
if err != nil {
@@ -36,3 +36,20 @@ func FindCachePolicy(parent *actionutils.ParentAction, cachePolicyId int64) (*se
}
return config, nil
}
// KeyFailReason Key相关失败原因
func KeyFailReason(reasonCode string) string {
switch reasonCode {
case "requireKey":
return "空的Key"
case "requireDomain":
return "找不到Key对应的域名"
case "requireServer":
return "找不到Key对应的网站服务"
case "requireUser":
return "该域名不属于当前用户"
case "requireClusterId":
return "该网站没有部署到集群"
}
return "未知错误"
}

Some files were not shown because too many files have changed in this diff Show More