Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee61feb581 | ||
|
|
7f04f1ed62 | ||
|
|
82646c3576 | ||
|
|
b3f62240c4 | ||
|
|
86a5992e8a | ||
|
|
82a731ed06 | ||
|
|
e650529efb | ||
|
|
1de57e124f | ||
|
|
9e72dcc390 | ||
|
|
80019e2071 | ||
|
|
ab7cdcd1b1 | ||
|
|
7afe1e0a30 | ||
|
|
a39eb80214 | ||
|
|
10e2a08cd2 | ||
|
|
6da4949c98 | ||
|
|
4d092f329b | ||
|
|
69c1d35406 | ||
|
|
a256a7328e | ||
|
|
75c8658366 | ||
|
|
c3e68915a3 | ||
|
|
d97f4da7fa | ||
|
|
06e81dbe37 | ||
|
|
4a46aaa880 | ||
|
|
e766372a81 | ||
|
|
c5ee9f095a | ||
|
|
9734ed1cf8 | ||
|
|
548d122c64 | ||
|
|
c5205ef7a9 | ||
|
|
f71a27960b | ||
|
|
d747e656dc | ||
|
|
867215e2af | ||
|
|
3614b9f3b7 | ||
|
|
cbfa4c85c1 | ||
|
|
b9bef5042a | ||
|
|
46e523d005 | ||
|
|
fa2930dfc5 | ||
|
|
086ab15e8a | ||
|
|
c2e3e784a2 | ||
|
|
9dd01bd36e | ||
|
|
02d08b0762 | ||
|
|
cbd312e67d | ||
|
|
5084d9f87e | ||
|
|
3c3408624d | ||
|
|
6e8403390b | ||
|
|
ef9e5d4bbc | ||
|
|
c0b49948d7 | ||
|
|
48b066fb83 | ||
|
|
7d551d59db | ||
|
|
5a057857dc | ||
|
|
0a9cea722c | ||
|
|
f7eb7b1ec6 | ||
|
|
0eb57a734e | ||
|
|
82ff9a2b06 | ||
|
|
051a48bc73 | ||
|
|
6b9d5cf7a0 | ||
|
|
2e7d64d97b | ||
|
|
dd6050ee0b | ||
|
|
c954910728 | ||
|
|
0fe2bc4a54 | ||
|
|
9f39cd615f | ||
|
|
07bf21dbb4 | ||
|
|
43e8c65473 | ||
|
|
8a926eabbe |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
*_plus.go
|
*_plus.go
|
||||||
|
*-plus.sh
|
||||||
@@ -8,6 +8,9 @@
|
|||||||
* `简单` - 架构简单清晰,安装简单,使用简单,运维简单
|
* `简单` - 架构简单清晰,安装简单,使用简单,运维简单
|
||||||
* `高扩展性` - 可以自由扩展新的节点,支持亿级数据
|
* `高扩展性` - 可以自由扩展新的节点,支持亿级数据
|
||||||
|
|
||||||
|
## 在线演示
|
||||||
|
* [http://demo.goedge.cn](http://demo.goedge.cn)
|
||||||
|
|
||||||
## 文档
|
## 文档
|
||||||
* [新手指南](https://edge.teaos.cn/docs/QuickStart/Index.md)
|
* [新手指南](https://edge.teaos.cn/docs/QuickStart/Index.md)
|
||||||
* [完整文档](https://edge.teaos.cn/docs)
|
* [完整文档](https://edge.teaos.cn/docs)
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
ROOT=$(dirname $0)
|
||||||
|
|
||||||
|
# build all nodes
|
||||||
|
if [ -f $ROOT"/../../EdgeNode/build/build-all-plus.sh" ]; then
|
||||||
|
echo "=============================="
|
||||||
|
echo "build all edge-node"
|
||||||
|
echo "=============================="
|
||||||
|
cd $ROOT"/../../EdgeNode/build"
|
||||||
|
./build-all-plus.sh
|
||||||
|
cd -
|
||||||
|
fi
|
||||||
|
|
||||||
./build.sh linux amd64
|
./build.sh linux amd64
|
||||||
./build.sh linux 386
|
./build.sh linux 386
|
||||||
./build.sh linux arm64
|
./build.sh linux arm64
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ function build() {
|
|||||||
DIST=$ROOT/"../dist/${NAME}"
|
DIST=$ROOT/"../dist/${NAME}"
|
||||||
OS=${1}
|
OS=${1}
|
||||||
ARCH=${2}
|
ARCH=${2}
|
||||||
|
TAG=${3}
|
||||||
|
|
||||||
if [ -z $OS ]; then
|
if [ -z $OS ]; then
|
||||||
echo "usage: build.sh OS ARCH"
|
echo "usage: build.sh OS ARCH"
|
||||||
@@ -15,11 +16,14 @@ function build() {
|
|||||||
echo "usage: build.sh OS ARCH"
|
echo "usage: build.sh OS ARCH"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
if [ -z $TAG ]; then
|
||||||
|
TAG="community"
|
||||||
|
fi
|
||||||
|
|
||||||
VERSION=$(lookup-version $ROOT/../internal/const/const.go)
|
VERSION=$(lookup-version $ROOT/../internal/const/const.go)
|
||||||
ZIP="${NAME}-${OS}-${ARCH}-v${VERSION}.zip"
|
ZIP="${NAME}-${OS}-${ARCH}-${TAG}-v${VERSION}.zip"
|
||||||
|
|
||||||
# check edge-api
|
# 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} ..."
|
echo "building edge-api v${APINodeVersion} ..."
|
||||||
EDGE_API_BUILD_SCRIPT=$ROOT"/../../EdgeAPI/build/build.sh"
|
EDGE_API_BUILD_SCRIPT=$ROOT"/../../EdgeAPI/build/build.sh"
|
||||||
@@ -30,7 +34,7 @@ function build() {
|
|||||||
|
|
||||||
cd $ROOT"/../../EdgeAPI/build"
|
cd $ROOT"/../../EdgeAPI/build"
|
||||||
echo "=============================="
|
echo "=============================="
|
||||||
./build.sh $OS $ARCH
|
./build.sh $OS $ARCH $TAG
|
||||||
echo "=============================="
|
echo "=============================="
|
||||||
cd -
|
cd -
|
||||||
|
|
||||||
@@ -47,7 +51,7 @@ function build() {
|
|||||||
rm -f $DIST/web/tmp/*
|
rm -f $DIST/web/tmp/*
|
||||||
cp $ROOT/configs/server.template.yaml $DIST/configs/
|
cp $ROOT/configs/server.template.yaml $DIST/configs/
|
||||||
|
|
||||||
EDGE_API_ZIP_FILE=$ROOT"/../../EdgeAPI/dist/edge-api-${OS}-${ARCH}-v${APINodeVersion}.zip"
|
EDGE_API_ZIP_FILE=$ROOT"/../../EdgeAPI/dist/edge-api-${OS}-${ARCH}-${TAG}-v${APINodeVersion}.zip"
|
||||||
cp $EDGE_API_ZIP_FILE $DIST/
|
cp $EDGE_API_ZIP_FILE $DIST/
|
||||||
cd $DIST/
|
cd $DIST/
|
||||||
unzip -q $(basename $EDGE_API_ZIP_FILE)
|
unzip -q $(basename $EDGE_API_ZIP_FILE)
|
||||||
@@ -56,7 +60,7 @@ function build() {
|
|||||||
|
|
||||||
# build
|
# build
|
||||||
echo "building "${NAME}" ..."
|
echo "building "${NAME}" ..."
|
||||||
env GOOS=$OS GOARCH=$GOARCH go build -ldflags="-s -w" -o $DIST/bin/${NAME} $ROOT/../cmd/edge-admin/main.go
|
env GOOS=$OS GOARCH=$GOARCH go build -tags $TAG -ldflags="-s -w" -o $DIST/bin/${NAME} $ROOT/../cmd/edge-admin/main.go
|
||||||
|
|
||||||
# delete hidden files
|
# delete hidden files
|
||||||
find $DIST -name ".DS_Store" -delete
|
find $DIST -name ".DS_Store" -delete
|
||||||
@@ -88,4 +92,4 @@ function lookup-version() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
build $1 $2
|
build $1 $2 $3
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ func main() {
|
|||||||
app := apps.NewAppCmd().
|
app := apps.NewAppCmd().
|
||||||
Version(teaconst.Version).
|
Version(teaconst.Version).
|
||||||
Product(teaconst.ProductName).
|
Product(teaconst.ProductName).
|
||||||
Usage(teaconst.ProcessName+" [-v|start|stop|restart|service|daemon|reset|recover]").
|
Usage(teaconst.ProcessName+" [-v|start|stop|restart|service|daemon|reset|recover|demo]").
|
||||||
Option("-h", "show this help").
|
Option("-h", "show this help").
|
||||||
Option("-v", "show version").
|
Option("-v", "show version").
|
||||||
Option("start", "start the service").
|
Option("start", "start the service").
|
||||||
@@ -57,6 +57,19 @@ func main() {
|
|||||||
}
|
}
|
||||||
fmt.Println("enter recovery mode successfully")
|
fmt.Println("enter recovery mode successfully")
|
||||||
})
|
})
|
||||||
|
app.On("demo", func() {
|
||||||
|
sock := gosock.NewTmpSock(teaconst.ProcessName)
|
||||||
|
if !sock.IsListening() {
|
||||||
|
fmt.Println("[ERROR]the service not started yet, you should start the service first")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err := sock.Send(&gosock.Command{Code: "demo"})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("[ERROR]change demo mode failed: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println("change demo mode successfully")
|
||||||
|
})
|
||||||
app.Run(func() {
|
app.Run(func() {
|
||||||
adminNode := nodes.NewAdminNode()
|
adminNode := nodes.NewAdminNode()
|
||||||
adminNode.Run()
|
adminNode.Run()
|
||||||
|
|||||||
5
go.mod
5
go.mod
@@ -1,6 +1,6 @@
|
|||||||
module github.com/TeaOSLab/EdgeAdmin
|
module github.com/TeaOSLab/EdgeAdmin
|
||||||
|
|
||||||
go 1.15
|
go 1.16
|
||||||
|
|
||||||
replace github.com/TeaOSLab/EdgeCommon => ../EdgeCommon
|
replace github.com/TeaOSLab/EdgeCommon => ../EdgeCommon
|
||||||
|
|
||||||
@@ -9,10 +9,9 @@ require (
|
|||||||
github.com/cespare/xxhash v1.1.0
|
github.com/cespare/xxhash v1.1.0
|
||||||
github.com/go-sql-driver/mysql v1.5.0
|
github.com/go-sql-driver/mysql v1.5.0
|
||||||
github.com/go-yaml/yaml v2.1.0+incompatible
|
github.com/go-yaml/yaml v2.1.0+incompatible
|
||||||
github.com/golang/protobuf v1.5.2
|
|
||||||
github.com/google/go-cmp v0.5.6 // indirect
|
github.com/google/go-cmp v0.5.6 // indirect
|
||||||
github.com/iwind/TeaGo v0.0.0-20210720011303-fc255c995afa
|
github.com/iwind/TeaGo v0.0.0-20210720011303-fc255c995afa
|
||||||
github.com/iwind/gosock v0.0.0-20210720054405-4030f271aa3f
|
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3
|
||||||
github.com/miekg/dns v1.1.35
|
github.com/miekg/dns v1.1.35
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||||
github.com/tealeg/xlsx/v3 v3.2.3
|
github.com/tealeg/xlsx/v3 v3.2.3
|
||||||
|
|||||||
17
go.sum
17
go.sum
@@ -64,13 +64,10 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
|
|||||||
github.com/iwind/TeaGo v0.0.0-20210628135026-38575a4ab060/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
github.com/iwind/TeaGo v0.0.0-20210628135026-38575a4ab060/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||||
github.com/iwind/TeaGo v0.0.0-20210720011303-fc255c995afa h1:woN88uEmRRUNFD7pRZEtX9heDcjFn0ClMxjF5ButKow=
|
github.com/iwind/TeaGo v0.0.0-20210720011303-fc255c995afa h1:woN88uEmRRUNFD7pRZEtX9heDcjFn0ClMxjF5ButKow=
|
||||||
github.com/iwind/TeaGo v0.0.0-20210720011303-fc255c995afa/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
github.com/iwind/TeaGo v0.0.0-20210720011303-fc255c995afa/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||||
github.com/iwind/gosock v0.0.0-20210706152215-08fe64b7a8a3 h1:BVHIjJU5RUX0grmvDtr3ZZ2z0hX+ideJRpg4NtBXZfs=
|
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3 h1:aBSonas7vFcgTj9u96/bWGILGv1ZbUSTLiOzcI1ZT6c=
|
||||||
github.com/iwind/gosock v0.0.0-20210706152215-08fe64b7a8a3/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
|
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
|
||||||
github.com/iwind/gosock v0.0.0-20210720054405-4030f271aa3f h1:+mKLTd5tCCLXK+iY5Xjz58hau6qFv9chGqcZ4FWUiIs=
|
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||||
github.com/iwind/gosock v0.0.0-20210720054405-4030f271aa3f/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
|
|
||||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
|
|
||||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
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.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
@@ -78,12 +75,10 @@ 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/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 h1:oTfOaDH+mZkdcgdIjH6yBajRGtIwcwcaR+rt23ZSrJs=
|
||||||
github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
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/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||||
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 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
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/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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
@@ -146,6 +141,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
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-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
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-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
|
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
|
||||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
@@ -169,6 +165,7 @@ 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-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-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-20201119102817-f84b799fce68/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-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ func (this *AppCmd) Run(main func()) {
|
|||||||
|
|
||||||
// 版本号
|
// 版本号
|
||||||
func (this *AppCmd) runVersion() {
|
func (this *AppCmd) runVersion() {
|
||||||
fmt.Println(this.product+" v"+this.version, "(build: "+runtime.Version(), runtime.GOOS, runtime.GOARCH+")")
|
fmt.Println(this.product+" v"+this.version, "(build: "+runtime.Version(), runtime.GOOS, runtime.GOARCH, teaconst.Tag+")")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 帮助
|
// 帮助
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ func AllModuleMaps() []maps.Map {
|
|||||||
}
|
}
|
||||||
if teaconst.IsPlus {
|
if teaconst.IsPlus {
|
||||||
m = append(m, maps.Map{
|
m = append(m, maps.Map{
|
||||||
"name": "域名服务",
|
"name": "自建DNS",
|
||||||
"code": AdminModuleCodeNS,
|
"code": AdminModuleCodeNS,
|
||||||
"url": "/ns",
|
"url": "/ns",
|
||||||
})
|
})
|
||||||
|
|||||||
8
internal/const/build.go
Normal file
8
internal/const/build.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
// +build community
|
||||||
|
|
||||||
|
package teaconst
|
||||||
|
|
||||||
|
const BuildCommunity = true
|
||||||
|
const BuildPlus = false
|
||||||
|
const Tag = "community"
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package teaconst
|
package teaconst
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version = "0.2.5"
|
Version = "0.2.9"
|
||||||
|
|
||||||
ProductName = "Edge Admin"
|
ProductName = "Edge Admin"
|
||||||
ProcessName = "edge-admin"
|
ProcessName = "edge-admin"
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
// +build demo
|
|
||||||
|
|
||||||
package teaconst
|
|
||||||
|
|
||||||
const (
|
|
||||||
IsDemo = true
|
|
||||||
)
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
// +build !demo
|
|
||||||
|
|
||||||
package teaconst
|
|
||||||
|
|
||||||
const (
|
|
||||||
IsDemo = false
|
|
||||||
)
|
|
||||||
@@ -5,3 +5,8 @@ package teaconst
|
|||||||
var (
|
var (
|
||||||
IsRecoverMode = false
|
IsRecoverMode = false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
IsDemoMode = false
|
||||||
|
ErrorDemoOperation = "DEMO模式下无法进行创建、修改、删除等操作"
|
||||||
|
)
|
||||||
|
|||||||
@@ -323,6 +323,9 @@ func (this *AdminNode) listenSock() error {
|
|||||||
case "recover":
|
case "recover":
|
||||||
teaconst.IsRecoverMode = true
|
teaconst.IsRecoverMode = true
|
||||||
_ = cmd.ReplyOk()
|
_ = cmd.ReplyOk()
|
||||||
|
case "demo":
|
||||||
|
teaconst.IsDemoMode = !teaconst.IsDemoMode
|
||||||
|
_ = cmd.ReplyOk()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,10 @@ func (this *RPCClient) NodeGrantRPC() pb.NodeGrantServiceClient {
|
|||||||
return pb.NewNodeGrantServiceClient(this.pickConn())
|
return pb.NewNodeGrantServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) NodeLoginRPC() pb.NodeLoginServiceClient {
|
||||||
|
return pb.NewNodeLoginServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
func (this *RPCClient) NodeClusterRPC() pb.NodeClusterServiceClient {
|
func (this *RPCClient) NodeClusterRPC() pb.NodeClusterServiceClient {
|
||||||
return pb.NewNodeClusterServiceClient(this.pickConn())
|
return pb.NewNodeClusterServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
@@ -388,6 +392,10 @@ func (this *RPCClient) NSRecordRPC() pb.NSRecordServiceClient {
|
|||||||
return pb.NewNSRecordServiceClient(this.pickConn())
|
return pb.NewNSRecordServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) NSKeyRPC() pb.NSKeyServiceClient {
|
||||||
|
return pb.NewNSKeyServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
func (this *RPCClient) NSRouteRPC() pb.NSRouteServiceClient {
|
func (this *RPCClient) NSRouteRPC() pb.NSRouteServiceClient {
|
||||||
return pb.NewNSRouteServiceClient(this.pickConn())
|
return pb.NewNSRouteServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
@@ -400,6 +408,10 @@ func (this *RPCClient) NSRPC() pb.NSServiceClient {
|
|||||||
return pb.NewNSServiceClient(this.pickConn())
|
return pb.NewNSServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) NSQuestionOptionRPC() pb.NSQuestionOptionServiceClient {
|
||||||
|
return pb.NewNSQuestionOptionServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
func (this *RPCClient) MetricItemRPC() pb.MetricItemServiceClient {
|
func (this *RPCClient) MetricItemRPC() pb.MetricItemServiceClient {
|
||||||
return pb.NewMetricItemServiceClient(this.pickConn())
|
return pb.NewMetricItemServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
|
||||||
|
|
||||||
package tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/events"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/setup"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/Tea"
|
|
||||||
"github.com/iwind/TeaGo/logs"
|
|
||||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
events.On(events.EventStart, func() {
|
|
||||||
task := NewAuthorityTask()
|
|
||||||
go task.Start()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type AuthorityTask struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewAuthorityTask() *AuthorityTask {
|
|
||||||
return &AuthorityTask{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *AuthorityTask) Start() {
|
|
||||||
// 从缓存中读取
|
|
||||||
config := configs.ReadPlusConfig()
|
|
||||||
if config != nil {
|
|
||||||
teaconst.IsPlus = config.IsPlus
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开始计时器
|
|
||||||
ticker := time.NewTicker(10 * time.Minute)
|
|
||||||
if Tea.IsTesting() {
|
|
||||||
// 快速测试
|
|
||||||
ticker = time.NewTicker(1 * time.Minute)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化的时候先获取一次
|
|
||||||
timeout := time.NewTimer(3 * time.Second)
|
|
||||||
<-timeout.C
|
|
||||||
err := this.Loop()
|
|
||||||
if err != nil {
|
|
||||||
logs.Println("[TASK][AuthorityTask]" + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// 定时获取
|
|
||||||
for range ticker.C {
|
|
||||||
err := this.Loop()
|
|
||||||
if err != nil {
|
|
||||||
logs.Println("[TASK][AuthorityTask]" + err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *AuthorityTask) Loop() error {
|
|
||||||
// 如果还没有安装直接返回
|
|
||||||
if !setup.IsConfigured() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
rpcClient, err := rpc.SharedRPC()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
resp, err := rpcClient.AuthorityKeyRPC().ReadAuthorityKey(rpcClient.Context(0), &pb.ReadAuthorityKeyRequest{})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var oldState = teaconst.IsPlus
|
|
||||||
if resp.AuthorityKey != nil && len(resp.AuthorityKey.Value) > 0 && resp.AuthorityKey.DayTo >= timeutil.Format("Y-m-d") {
|
|
||||||
teaconst.IsPlus = true
|
|
||||||
} else {
|
|
||||||
teaconst.IsPlus = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if oldState != teaconst.IsPlus {
|
|
||||||
_ = configs.WritePlusConfig(&configs.PlusConfig{IsPlus: teaconst.IsPlus})
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -39,6 +39,10 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
Offset: page.Offset,
|
Offset: page.Offset,
|
||||||
Size: page.Size,
|
Size: page.Size,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
recipientMaps := []maps.Map{}
|
recipientMaps := []maps.Map{}
|
||||||
for _, recipient := range recipientsResp.MessageRecipients {
|
for _, recipient := range recipientsResp.MessageRecipients {
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
Offset: page.Offset,
|
Offset: page.Offset,
|
||||||
Size: page.Size,
|
Size: page.Size,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
instanceMaps := []maps.Map{}
|
instanceMaps := []maps.Map{}
|
||||||
for _, instance := range instancesResp.MessageMediaInstances {
|
for _, instance := range instancesResp.MessageMediaInstances {
|
||||||
|
|||||||
@@ -4,14 +4,16 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"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/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 创建节点
|
// CreateNodeAction 创建节点
|
||||||
type CreateNodeAction struct {
|
type CreateNodeAction struct {
|
||||||
actionutils.ParentAction
|
actionutils.ParentAction
|
||||||
}
|
}
|
||||||
@@ -57,14 +59,32 @@ func (this *CreateNodeAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
for _, route := range routesResp.Routes {
|
for _, route := range routesResp.Routes {
|
||||||
dnsRouteMaps = append(dnsRouteMaps, maps.Map{
|
dnsRouteMaps = append(dnsRouteMaps, maps.Map{
|
||||||
"name": route.Name,
|
"domainId": domainId,
|
||||||
"code": route.Code,
|
"domainName": clusterDNSResp.Domain.Name,
|
||||||
|
"name": route.Name,
|
||||||
|
"code": route.Code,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.Data["dnsRoutes"] = dnsRouteMaps
|
this.Data["dnsRoutes"] = dnsRouteMaps
|
||||||
|
|
||||||
|
// API节点列表
|
||||||
|
apiNodesResp, err := this.RPC().APINodeRPC().FindAllEnabledAPINodes(this.AdminContext(), &pb.FindAllEnabledAPINodesRequest{})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
apiNodes := apiNodesResp.Nodes
|
||||||
|
apiEndpoints := []string{}
|
||||||
|
for _, apiNode := range apiNodes {
|
||||||
|
if !apiNode.IsOn {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
apiEndpoints = append(apiEndpoints, apiNode.AccessAddrs...)
|
||||||
|
}
|
||||||
|
this.Data["apiEndpoints"] = "\"" + strings.Join(apiEndpoints, "\", \"") + "\""
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,5 +192,57 @@ func (this *CreateNodeAction) RunPost(params struct {
|
|||||||
// 创建日志
|
// 创建日志
|
||||||
defer this.CreateLog(oplogs.LevelInfo, "创建节点 %d", nodeId)
|
defer this.CreateLog(oplogs.LevelInfo, "创建节点 %d", nodeId)
|
||||||
|
|
||||||
|
// 响应数据
|
||||||
|
this.Data["nodeId"] = nodeId
|
||||||
|
nodeResp, err := this.RPC().NodeRPC().FindEnabledNode(this.AdminContext(), &pb.FindEnabledNodeRequest{NodeId: nodeId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if nodeResp.Node != nil {
|
||||||
|
var addresses = []string{}
|
||||||
|
for _, addrMap := range ipAddresses {
|
||||||
|
addresses = append(addresses, addrMap.GetString("ip"))
|
||||||
|
}
|
||||||
|
|
||||||
|
var grantMap maps.Map = nil
|
||||||
|
grantId := params.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 && grantResp.NodeGrant.Id > 0 {
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["node"] = maps.Map{
|
||||||
|
"id": nodeResp.Node.Id,
|
||||||
|
"name": nodeResp.Node.Name,
|
||||||
|
"uniqueId": nodeResp.Node.UniqueId,
|
||||||
|
"secret": nodeResp.Node.Secret,
|
||||||
|
"addresses": addresses,
|
||||||
|
"login": maps.Map{
|
||||||
|
"id": 0,
|
||||||
|
"name": "SSH",
|
||||||
|
"type": "ssh",
|
||||||
|
"params": maps.Map{
|
||||||
|
"grantId": params.GrantId,
|
||||||
|
"host": params.SshHost,
|
||||||
|
"port": params.SshPort,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"grant": grantMap,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
// 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 CreateNodeInstallAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreateNodeInstallAction) RunPost(params struct {
|
||||||
|
NodeId int64
|
||||||
|
SshHost string
|
||||||
|
SshPort int
|
||||||
|
GrantId int64
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("安装节点 %d", params.NodeId)
|
||||||
|
|
||||||
|
params.Must.
|
||||||
|
Field("sshHost2", params.SshHost).
|
||||||
|
Require("请填写SSH主机地址").
|
||||||
|
Field("sshPort2", params.SshPort).
|
||||||
|
Gt(0, "请填写SSH主机端口").
|
||||||
|
Lt(65535, "SSH主机端口需要小于65535").
|
||||||
|
Field("grantId", params.GrantId).
|
||||||
|
Gt(0, "请选择SSH登录认证")
|
||||||
|
|
||||||
|
// 查询login
|
||||||
|
nodeResp, err := this.RPC().NodeRPC().FindEnabledNode(this.AdminContext(), &pb.FindEnabledNodeRequest{NodeId: params.NodeId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var node = nodeResp.Node
|
||||||
|
if node == nil {
|
||||||
|
this.Fail("找不到要修改的节点")
|
||||||
|
}
|
||||||
|
var loginId int64
|
||||||
|
if node.NodeLogin != nil {
|
||||||
|
loginId = node.NodeLogin.Id
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改节点信息
|
||||||
|
_, err = this.RPC().NodeRPC().UpdateNodeLogin(this.AdminContext(), &pb.UpdateNodeLoginRequest{
|
||||||
|
NodeId: params.NodeId,
|
||||||
|
NodeLogin: &pb.NodeLogin{
|
||||||
|
Id: loginId,
|
||||||
|
Name: "SSH",
|
||||||
|
Type: "ssh",
|
||||||
|
Params: maps.Map{
|
||||||
|
"grantId": params.GrantId,
|
||||||
|
"host": params.SshHost,
|
||||||
|
"port": params.SshPort,
|
||||||
|
}.AsJSON(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开始安装
|
||||||
|
_, err = this.RPC().NodeRPC().InstallNode(this.AdminContext(), &pb.InstallNodeRequest{NodeId: params.NodeId})
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("安装失败:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -27,9 +27,11 @@ func init() {
|
|||||||
Post("/upgradeStatus", new(UpgradeStatusAction)).
|
Post("/upgradeStatus", new(UpgradeStatusAction)).
|
||||||
GetPost("/delete", new(DeleteAction)).
|
GetPost("/delete", new(DeleteAction)).
|
||||||
GetPost("/createNode", new(CreateNodeAction)).
|
GetPost("/createNode", new(CreateNodeAction)).
|
||||||
|
Post("/createNodeInstall", new(CreateNodeInstallAction)).
|
||||||
GetPost("/createBatch", new(CreateBatchAction)).
|
GetPost("/createBatch", new(CreateBatchAction)).
|
||||||
GetPost("/updateNodeSSH", new(UpdateNodeSSHAction)).
|
GetPost("/updateNodeSSH", new(UpdateNodeSSHAction)).
|
||||||
GetPost("/installManual", new(InstallManualAction)).
|
GetPost("/installManual", new(InstallManualAction)).
|
||||||
|
Post("/suggestLoginPorts", new(SuggestLoginPortsAction)).
|
||||||
|
|
||||||
// 节点相关
|
// 节点相关
|
||||||
Prefix("/clusters/cluster/node").
|
Prefix("/clusters/cluster/node").
|
||||||
@@ -58,7 +60,6 @@ func init() {
|
|||||||
// 看板相关
|
// 看板相关
|
||||||
Prefix("/clusters/cluster/boards").
|
Prefix("/clusters/cluster/boards").
|
||||||
Get("", new(boards.IndexAction)).
|
Get("", new(boards.IndexAction)).
|
||||||
|
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ func (this *InstallManualAction) RunGet(params struct {
|
|||||||
nodeMaps := []maps.Map{}
|
nodeMaps := []maps.Map{}
|
||||||
for _, node := range nodesResp.Nodes {
|
for _, node := range nodesResp.Nodes {
|
||||||
loginParams := maps.Map{}
|
loginParams := maps.Map{}
|
||||||
if node.Login != nil && len(node.Login.Params) > 0 {
|
if node.NodeLogin != nil && len(node.NodeLogin.Params) > 0 {
|
||||||
err := json.Unmarshal(node.Login.Params, &loginParams)
|
err := json.Unmarshal(node.NodeLogin.Params, &loginParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
@@ -56,7 +56,7 @@ func (this *InstallManualAction) RunGet(params struct {
|
|||||||
"isOn": node.IsOn,
|
"isOn": node.IsOn,
|
||||||
"name": node.Name,
|
"name": node.Name,
|
||||||
"addresses": node.IpAddresses,
|
"addresses": node.IpAddresses,
|
||||||
"login": node.Login,
|
"login": node.NodeLogin,
|
||||||
"loginParams": loginParams,
|
"loginParams": loginParams,
|
||||||
"installStatus": installStatus,
|
"installStatus": installStatus,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ func (this *InstallRemoteAction) RunGet(params struct {
|
|||||||
nodeMaps := []maps.Map{}
|
nodeMaps := []maps.Map{}
|
||||||
for _, node := range nodesResp.Nodes {
|
for _, node := range nodesResp.Nodes {
|
||||||
loginParams := maps.Map{}
|
loginParams := maps.Map{}
|
||||||
if node.Login != nil && len(node.Login.Params) > 0 {
|
if node.NodeLogin != nil && len(node.NodeLogin.Params) > 0 {
|
||||||
err := json.Unmarshal(node.Login.Params, &loginParams)
|
err := json.Unmarshal(node.NodeLogin.Params, &loginParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
@@ -58,7 +58,7 @@ func (this *InstallRemoteAction) RunGet(params struct {
|
|||||||
"isOn": node.IsOn,
|
"isOn": node.IsOn,
|
||||||
"name": node.Name,
|
"name": node.Name,
|
||||||
"addresses": node.IpAddresses,
|
"addresses": node.IpAddresses,
|
||||||
"login": node.Login,
|
"login": node.NodeLogin,
|
||||||
"loginParams": loginParams,
|
"loginParams": loginParams,
|
||||||
"installStatus": installStatus,
|
"installStatus": installStatus,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package node
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"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/clusters/grants/grantutils"
|
||||||
@@ -37,6 +38,7 @@ func (this *DetailAction) RunGet(params struct {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 主集群
|
||||||
var clusterMap maps.Map = nil
|
var clusterMap maps.Map = nil
|
||||||
if node.NodeCluster != nil {
|
if node.NodeCluster != nil {
|
||||||
clusterId := node.NodeCluster.Id
|
clusterId := node.NodeCluster.Id
|
||||||
@@ -55,6 +57,16 @@ func (this *DetailAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 从集群
|
||||||
|
var secondaryClustersMaps = []maps.Map{}
|
||||||
|
for _, cluster := range node.SecondaryNodeClusters {
|
||||||
|
secondaryClustersMaps = append(secondaryClustersMaps, maps.Map{
|
||||||
|
"id": cluster.Id,
|
||||||
|
"name": cluster.Name,
|
||||||
|
"isOn": cluster.IsOn,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// IP地址
|
// IP地址
|
||||||
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{
|
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{
|
||||||
NodeId: params.NodeId,
|
NodeId: params.NodeId,
|
||||||
@@ -64,6 +76,7 @@ func (this *DetailAction) RunGet(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var ipAddresses = ipAddressesResp.Addresses
|
||||||
ipAddressMaps := []maps.Map{}
|
ipAddressMaps := []maps.Map{}
|
||||||
for _, addr := range ipAddressesResp.Addresses {
|
for _, addr := range ipAddressesResp.Addresses {
|
||||||
ipAddressMaps = append(ipAddressMaps, maps.Map{
|
ipAddressMaps = append(ipAddressMaps, maps.Map{
|
||||||
@@ -75,40 +88,63 @@ func (this *DetailAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DNS相关
|
// DNS相关
|
||||||
dnsInfoResp, err := this.RPC().NodeRPC().FindEnabledNodeDNS(this.AdminContext(), &pb.FindEnabledNodeDNSRequest{NodeId: params.NodeId})
|
var clusters = []*pb.NodeCluster{node.NodeCluster}
|
||||||
if err != nil {
|
clusters = append(clusters, node.SecondaryNodeClusters...)
|
||||||
this.ErrorPage(err)
|
var recordMaps = []maps.Map{}
|
||||||
return
|
var routeMaps = []maps.Map{}
|
||||||
}
|
for _, cluster := range clusters {
|
||||||
dnsRouteMaps := []maps.Map{}
|
dnsInfoResp, err := this.RPC().NodeRPC().FindEnabledNodeDNS(this.AdminContext(), &pb.FindEnabledNodeDNSRequest{
|
||||||
recordName := ""
|
NodeId: params.NodeId,
|
||||||
recordValue := ""
|
NodeClusterId: cluster.Id,
|
||||||
if dnsInfoResp.Node != nil {
|
})
|
||||||
recordName = dnsInfoResp.Node.NodeClusterDNSName + "." + dnsInfoResp.Node.DnsDomainName
|
if err != nil {
|
||||||
recordValue = dnsInfoResp.Node.IpAddr
|
this.ErrorPage(err)
|
||||||
for _, dnsInfo := range dnsInfoResp.Node.Routes {
|
return
|
||||||
dnsRouteMaps = append(dnsRouteMaps, maps.Map{
|
}
|
||||||
"name": dnsInfo.Name,
|
var dnsInfo = dnsInfoResp.Node
|
||||||
"code": dnsInfo.Code,
|
if len(dnsInfo.DnsDomainName) == 0 || len(dnsInfo.NodeClusterDNSName) == 0 {
|
||||||
})
|
continue
|
||||||
|
}
|
||||||
|
var domainName = dnsInfo.DnsDomainName
|
||||||
|
|
||||||
|
// 默认线路
|
||||||
|
if len(dnsInfo.Routes) == 0 {
|
||||||
|
dnsInfo.Routes = append(dnsInfo.Routes, &pb.DNSRoute{})
|
||||||
|
} else {
|
||||||
|
for _, route := range dnsInfo.Routes {
|
||||||
|
routeMaps = append(routeMaps, maps.Map{
|
||||||
|
"domainName": domainName,
|
||||||
|
"code": route.Code,
|
||||||
|
"name": route.Name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, addr := range ipAddresses {
|
||||||
|
if !addr.CanAccess {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, route := range dnsInfo.Routes {
|
||||||
|
var recordType = "A"
|
||||||
|
if utils.IsIPv6(addr.Ip) {
|
||||||
|
recordType = "AAAA"
|
||||||
|
}
|
||||||
|
recordMaps = append(recordMaps, maps.Map{
|
||||||
|
"name": dnsInfo.NodeClusterDNSName + "." + domainName,
|
||||||
|
"type": recordType,
|
||||||
|
"route": route.Name,
|
||||||
|
"value": addr.Ip,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(dnsRouteMaps) == 0 {
|
|
||||||
dnsRouteMaps = append(dnsRouteMaps, maps.Map{
|
|
||||||
"name": "",
|
|
||||||
"code": "",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.Data["dnsRoutes"] = dnsRouteMaps
|
|
||||||
this.Data["dnsRecordName"] = recordName
|
|
||||||
this.Data["dnsRecordValue"] = recordValue
|
|
||||||
|
|
||||||
// 登录信息
|
// 登录信息
|
||||||
var loginMap maps.Map = nil
|
var loginMap maps.Map = nil
|
||||||
if node.Login != nil {
|
if node.NodeLogin != nil {
|
||||||
loginParams := maps.Map{}
|
loginParams := maps.Map{}
|
||||||
if len(node.Login.Params) > 0 {
|
if len(node.NodeLogin.Params) > 0 {
|
||||||
err = json.Unmarshal(node.Login.Params, &loginParams)
|
err = json.Unmarshal(node.NodeLogin.Params, &loginParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
@@ -129,14 +165,15 @@ func (this *DetailAction) RunGet(params struct {
|
|||||||
"name": grantResp.NodeGrant.Name,
|
"name": grantResp.NodeGrant.Name,
|
||||||
"method": grantResp.NodeGrant.Method,
|
"method": grantResp.NodeGrant.Method,
|
||||||
"methodName": grantutils.FindGrantMethodName(grantResp.NodeGrant.Method),
|
"methodName": grantutils.FindGrantMethodName(grantResp.NodeGrant.Method),
|
||||||
|
"username": grantResp.NodeGrant.Username,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loginMap = maps.Map{
|
loginMap = maps.Map{
|
||||||
"id": node.Login.Id,
|
"id": node.NodeLogin.Id,
|
||||||
"name": node.Login.Name,
|
"name": node.NodeLogin.Name,
|
||||||
"type": node.Login.Type,
|
"type": node.NodeLogin.Type,
|
||||||
"params": loginParams,
|
"params": loginParams,
|
||||||
"grant": grantMap,
|
"grant": grantMap,
|
||||||
}
|
}
|
||||||
@@ -217,17 +254,20 @@ func (this *DetailAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.Data["node"] = maps.Map{
|
this.Data["node"] = maps.Map{
|
||||||
"id": node.Id,
|
"id": node.Id,
|
||||||
"name": node.Name,
|
"name": node.Name,
|
||||||
"ipAddresses": ipAddressMaps,
|
"ipAddresses": ipAddressMaps,
|
||||||
"cluster": clusterMap,
|
"cluster": clusterMap,
|
||||||
"login": loginMap,
|
"secondaryClusters": secondaryClustersMaps,
|
||||||
"installDir": node.InstallDir,
|
"login": loginMap,
|
||||||
"isInstalled": node.IsInstalled,
|
"installDir": node.InstallDir,
|
||||||
"uniqueId": node.UniqueId,
|
"isInstalled": node.IsInstalled,
|
||||||
"secret": node.Secret,
|
"uniqueId": node.UniqueId,
|
||||||
"maxCPU": node.MaxCPU,
|
"secret": node.Secret,
|
||||||
"isOn": node.IsOn,
|
"maxCPU": node.MaxCPU,
|
||||||
|
"isOn": node.IsOn,
|
||||||
|
"records": recordMaps,
|
||||||
|
"routes": routeMaps,
|
||||||
|
|
||||||
"status": maps.Map{
|
"status": maps.Map{
|
||||||
"isActive": status.IsActive,
|
"isActive": status.IsActive,
|
||||||
|
|||||||
@@ -29,6 +29,6 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
if teaconst.IsPlus {
|
if teaconst.IsPlus {
|
||||||
this.RedirectURL("/clusters/cluster/node/boards?clusterId=" + fmt.Sprintf("%d", this.Data["clusterId"]) + "&nodeId=" + strconv.FormatInt(params.NodeId, 10))
|
this.RedirectURL("/clusters/cluster/node/boards?clusterId=" + fmt.Sprintf("%d", this.Data["clusterId"]) + "&nodeId=" + strconv.FormatInt(params.NodeId, 10))
|
||||||
} else {
|
} else {
|
||||||
this.RedirectURL("/clusters/cluster/node/detail?clusterId=" + fmt.Sprintf("%d", this.Data["clusterId"]) + strconv.FormatInt(params.NodeId, 10))
|
this.RedirectURL("/clusters/cluster/node/detail?clusterId=" + fmt.Sprintf("%d", this.Data["clusterId"]) + "&nodeId=" + strconv.FormatInt(params.NodeId, 10))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 安装节点
|
// InstallAction 安装节点
|
||||||
type InstallAction struct {
|
type InstallAction struct {
|
||||||
actionutils.ParentAction
|
actionutils.ParentAction
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@ func (this *InstallAction) RunGet(params struct {
|
|||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开始安装
|
// RunPost 开始安装
|
||||||
func (this *InstallAction) RunPost(params struct {
|
func (this *InstallAction) RunPost(params struct {
|
||||||
NodeId int64
|
NodeId int64
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,10 @@ func (this *LogsAction) RunGet(params struct {
|
|||||||
Offset: page.Offset,
|
Offset: page.Offset,
|
||||||
Size: page.Size,
|
Size: page.Size,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
logs := []maps.Map{}
|
logs := []maps.Map{}
|
||||||
for _, log := range logsResp.NodeLogs {
|
for _, log := range logsResp.NodeLogs {
|
||||||
|
|||||||
@@ -66,50 +66,70 @@ func (this *UpdateAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DNS相关
|
// DNS相关
|
||||||
dnsInfoResp, err := this.RPC().NodeRPC().FindEnabledNodeDNS(this.AdminContext(), &pb.FindEnabledNodeDNSRequest{NodeId: params.NodeId})
|
var clusters = []*pb.NodeCluster{node.NodeCluster}
|
||||||
if err != nil {
|
clusters = append(clusters, node.SecondaryNodeClusters...)
|
||||||
this.ErrorPage(err)
|
var allDNSRouteMaps = map[int64][]maps.Map{} // domain id => routes
|
||||||
return
|
var routeMaps = map[int64][]maps.Map{} // domain id => routes
|
||||||
}
|
for _, cluster := range clusters {
|
||||||
nodeDNS := dnsInfoResp.Node
|
dnsInfoResp, err := this.RPC().NodeRPC().FindEnabledNodeDNS(this.AdminContext(), &pb.FindEnabledNodeDNSRequest{
|
||||||
dnsRouteMaps := []maps.Map{}
|
NodeId: params.NodeId,
|
||||||
if nodeDNS != nil {
|
NodeClusterId: cluster.Id,
|
||||||
for _, dnsInfo := range nodeDNS.Routes {
|
})
|
||||||
dnsRouteMaps = append(dnsRouteMaps, maps.Map{
|
if err != nil {
|
||||||
"name": dnsInfo.Name,
|
this.ErrorPage(err)
|
||||||
"code": dnsInfo.Code,
|
return
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
var dnsInfo = dnsInfoResp.Node
|
||||||
this.Data["dnsRoutes"] = dnsRouteMaps
|
if dnsInfo.DnsDomainId <= 0 || len(dnsInfo.DnsDomainName) == 0 {
|
||||||
this.Data["allDNSRoutes"] = []maps.Map{}
|
continue
|
||||||
if nodeDNS != nil {
|
}
|
||||||
this.Data["dnsDomainId"] = nodeDNS.DnsDomainId
|
var domainId = dnsInfo.DnsDomainId
|
||||||
} else {
|
var domainName = dnsInfo.DnsDomainName
|
||||||
this.Data["dnsDomainId"] = 0
|
if len(dnsInfo.Routes) > 0 {
|
||||||
}
|
for _, route := range dnsInfo.Routes {
|
||||||
if nodeDNS != nil && nodeDNS.DnsDomainId > 0 {
|
routeMaps[domainId] = append(routeMaps[domainId], maps.Map{
|
||||||
routesMaps := []maps.Map{}
|
"domainId": domainId,
|
||||||
|
"domainName": domainName,
|
||||||
|
"code": route.Code,
|
||||||
|
"name": route.Name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 所有线路选项
|
||||||
routesResp, err := this.RPC().DNSDomainRPC().FindAllDNSDomainRoutes(this.AdminContext(), &pb.FindAllDNSDomainRoutesRequest{DnsDomainId: dnsInfoResp.Node.DnsDomainId})
|
routesResp, err := this.RPC().DNSDomainRPC().FindAllDNSDomainRoutes(this.AdminContext(), &pb.FindAllDNSDomainRoutesRequest{DnsDomainId: dnsInfoResp.Node.DnsDomainId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, route := range routesResp.Routes {
|
for _, route := range routesResp.Routes {
|
||||||
routesMaps = append(routesMaps, maps.Map{
|
allDNSRouteMaps[domainId] = append(allDNSRouteMaps[domainId], maps.Map{
|
||||||
"name": route.Name,
|
"domainId": domainId,
|
||||||
"code": route.Code,
|
"domainName": domainName,
|
||||||
|
"name": route.Name,
|
||||||
|
"code": route.Code,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.Data["allDNSRoutes"] = routesMaps
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var domainRoutes = []maps.Map{}
|
||||||
|
for _, m := range routeMaps {
|
||||||
|
domainRoutes = append(domainRoutes, m...)
|
||||||
|
}
|
||||||
|
this.Data["dnsRoutes"] = domainRoutes
|
||||||
|
|
||||||
|
var allDomainRoutes = []maps.Map{}
|
||||||
|
for _, m := range allDNSRouteMaps {
|
||||||
|
allDomainRoutes = append(allDomainRoutes, m...)
|
||||||
|
}
|
||||||
|
this.Data["allDNSRoutes"] = allDomainRoutes
|
||||||
|
|
||||||
// 登录信息
|
// 登录信息
|
||||||
var loginMap maps.Map = nil
|
var loginMap maps.Map = nil
|
||||||
if node.Login != nil {
|
if node.NodeLogin != nil {
|
||||||
loginParams := maps.Map{}
|
loginParams := maps.Map{}
|
||||||
if len(node.Login.Params) > 0 {
|
if len(node.NodeLogin.Params) > 0 {
|
||||||
err = json.Unmarshal(node.Login.Params, &loginParams)
|
err = json.Unmarshal(node.NodeLogin.Params, &loginParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
@@ -130,14 +150,15 @@ func (this *UpdateAction) RunGet(params struct {
|
|||||||
"name": grantResp.NodeGrant.Name,
|
"name": grantResp.NodeGrant.Name,
|
||||||
"method": grantResp.NodeGrant.Method,
|
"method": grantResp.NodeGrant.Method,
|
||||||
"methodName": grantutils.FindGrantMethodName(grantResp.NodeGrant.Method),
|
"methodName": grantutils.FindGrantMethodName(grantResp.NodeGrant.Method),
|
||||||
|
"username": grantResp.NodeGrant.Username,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loginMap = maps.Map{
|
loginMap = maps.Map{
|
||||||
"id": node.Login.Id,
|
"id": node.NodeLogin.Id,
|
||||||
"name": node.Login.Name,
|
"name": node.NodeLogin.Name,
|
||||||
"type": node.Login.Type,
|
"type": node.NodeLogin.Type,
|
||||||
"params": loginParams,
|
"params": loginParams,
|
||||||
"grant": grantMap,
|
"grant": grantMap,
|
||||||
}
|
}
|
||||||
@@ -188,7 +209,7 @@ func (this *UpdateAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Data["node"] = maps.Map{
|
var m = maps.Map{
|
||||||
"id": node.Id,
|
"id": node.Id,
|
||||||
"name": node.Name,
|
"name": node.Name,
|
||||||
"ipAddresses": ipAddressMaps,
|
"ipAddresses": ipAddressMaps,
|
||||||
@@ -202,23 +223,29 @@ func (this *UpdateAction) RunGet(params struct {
|
|||||||
"maxCacheMemoryCapacity": maxCacheMemoryCapacity,
|
"maxCacheMemoryCapacity": maxCacheMemoryCapacity,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 所有集群
|
if node.NodeCluster != nil {
|
||||||
resp, err := this.RPC().NodeClusterRPC().FindAllEnabledNodeClusters(this.AdminContext(), &pb.FindAllEnabledNodeClustersRequest{})
|
m["primaryCluster"] = maps.Map{
|
||||||
if err != nil {
|
"id": node.NodeCluster.Id,
|
||||||
this.ErrorPage(err)
|
"name": node.NodeCluster.Name,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m["primaryCluster"] = nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
if len(node.SecondaryNodeClusters) > 0 {
|
||||||
return
|
var secondaryClusterMaps = []maps.Map{}
|
||||||
|
for _, cluster := range node.SecondaryNodeClusters {
|
||||||
|
secondaryClusterMaps = append(secondaryClusterMaps, maps.Map{
|
||||||
|
"id": cluster.Id,
|
||||||
|
"name": cluster.Name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
m["secondaryClusters"] = secondaryClusterMaps
|
||||||
|
} else {
|
||||||
|
m["secondaryClusters"] = []interface{}{}
|
||||||
}
|
}
|
||||||
clusterMaps := []maps.Map{}
|
|
||||||
for _, cluster := range resp.NodeClusters {
|
this.Data["node"] = m
|
||||||
clusterMaps = append(clusterMaps, maps.Map{
|
|
||||||
"id": cluster.Id,
|
|
||||||
"name": cluster.Name,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.Data["clusters"] = clusterMaps
|
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
@@ -230,7 +257,8 @@ func (this *UpdateAction) RunPost(params struct {
|
|||||||
RegionId int64
|
RegionId int64
|
||||||
Name string
|
Name string
|
||||||
IPAddressesJSON []byte `alias:"ipAddressesJSON"`
|
IPAddressesJSON []byte `alias:"ipAddressesJSON"`
|
||||||
ClusterId int64
|
PrimaryClusterId int64
|
||||||
|
SecondaryClusterIds []byte
|
||||||
GrantId int64
|
GrantId int64
|
||||||
SshHost string
|
SshHost string
|
||||||
SshPort int
|
SshPort int
|
||||||
@@ -256,8 +284,17 @@ func (this *UpdateAction) RunPost(params struct {
|
|||||||
Require("请输入节点名称")
|
Require("请输入节点名称")
|
||||||
|
|
||||||
// TODO 检查cluster
|
// TODO 检查cluster
|
||||||
if params.ClusterId <= 0 {
|
if params.PrimaryClusterId <= 0 {
|
||||||
this.Fail("请选择所在集群")
|
this.Fail("请选择节点所在主集群")
|
||||||
|
}
|
||||||
|
|
||||||
|
var secondaryClusterIds = []int64{}
|
||||||
|
if len(params.SecondaryClusterIds) > 0 {
|
||||||
|
err := json.Unmarshal(params.SecondaryClusterIds, &secondaryClusterIds)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IP地址
|
// IP地址
|
||||||
@@ -325,18 +362,19 @@ func (this *UpdateAction) RunPost(params struct {
|
|||||||
|
|
||||||
// 保存
|
// 保存
|
||||||
_, err := this.RPC().NodeRPC().UpdateNode(this.AdminContext(), &pb.UpdateNodeRequest{
|
_, err := this.RPC().NodeRPC().UpdateNode(this.AdminContext(), &pb.UpdateNodeRequest{
|
||||||
NodeId: params.NodeId,
|
NodeId: params.NodeId,
|
||||||
NodeGroupId: params.GroupId,
|
NodeGroupId: params.GroupId,
|
||||||
NodeRegionId: params.RegionId,
|
NodeRegionId: params.RegionId,
|
||||||
Name: params.Name,
|
Name: params.Name,
|
||||||
NodeClusterId: params.ClusterId,
|
NodeClusterId: params.PrimaryClusterId,
|
||||||
NodeLogin: loginInfo,
|
SecondaryNodeClusterIds: secondaryClusterIds,
|
||||||
MaxCPU: params.MaxCPU,
|
NodeLogin: loginInfo,
|
||||||
IsOn: params.IsOn,
|
MaxCPU: params.MaxCPU,
|
||||||
DnsDomainId: params.DnsDomainId,
|
IsOn: params.IsOn,
|
||||||
DnsRoutes: dnsRouteCodes,
|
DnsDomainId: params.DnsDomainId,
|
||||||
MaxCacheDiskCapacity: pbMaxCacheDiskCapacity,
|
DnsRoutes: dnsRouteCodes,
|
||||||
MaxCacheMemoryCapacity: pbMaxCacheMemoryCapacity,
|
MaxCacheDiskCapacity: pbMaxCacheDiskCapacity,
|
||||||
|
MaxCacheMemoryCapacity: pbMaxCacheMemoryCapacity,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -156,6 +156,16 @@ func (this *NodesAction) RunGet(params struct {
|
|||||||
dnsRouteNames = append(dnsRouteNames, route.Name)
|
dnsRouteNames = append(dnsRouteNames, route.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 从集群
|
||||||
|
var secondaryClusterMaps []maps.Map
|
||||||
|
for _, secondaryCluster := range node.SecondaryNodeClusters {
|
||||||
|
secondaryClusterMaps = append(secondaryClusterMaps, maps.Map{
|
||||||
|
"id": secondaryCluster.Id,
|
||||||
|
"name": secondaryCluster.Name,
|
||||||
|
"isOn": secondaryCluster.IsOn,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
nodeMaps = append(nodeMaps, maps.Map{
|
nodeMaps = append(nodeMaps, maps.Map{
|
||||||
"id": node.Id,
|
"id": node.Id,
|
||||||
"name": node.Name,
|
"name": node.Name,
|
||||||
@@ -183,11 +193,12 @@ func (this *NodesAction) RunGet(params struct {
|
|||||||
"id": node.NodeCluster.Id,
|
"id": node.NodeCluster.Id,
|
||||||
"name": node.NodeCluster.Name,
|
"name": node.NodeCluster.Name,
|
||||||
},
|
},
|
||||||
"isSynced": isSynced,
|
"secondaryClusters": secondaryClusterMaps,
|
||||||
"ipAddresses": ipAddresses,
|
"isSynced": isSynced,
|
||||||
"group": groupMap,
|
"ipAddresses": ipAddresses,
|
||||||
"region": regionMap,
|
"group": groupMap,
|
||||||
"dnsRouteNames": dnsRouteNames,
|
"region": regionMap,
|
||||||
|
"dnsRouteNames": dnsRouteNames,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.Data["nodes"] = nodeMaps
|
this.Data["nodes"] = nodeMaps
|
||||||
|
|||||||
@@ -63,6 +63,14 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
// 创建日志
|
// 创建日志
|
||||||
defer this.CreateLog(oplogs.LevelInfo, "修改集群 %d DNS设置", params.ClusterId)
|
defer this.CreateLog(oplogs.LevelInfo, "修改集群 %d DNS设置", params.ClusterId)
|
||||||
|
|
||||||
|
if params.DnsDomainId <= 0 {
|
||||||
|
this.Fail("请选择集群的主域名")
|
||||||
|
}
|
||||||
|
|
||||||
|
params.Must.
|
||||||
|
Field("dnsName", params.DnsName).
|
||||||
|
Require("请输入DNS子域名")
|
||||||
|
|
||||||
// 检查DNS名称
|
// 检查DNS名称
|
||||||
if len(params.DnsName) > 0 {
|
if len(params.DnsName) > 0 {
|
||||||
if !domainutils.ValidateDomainFormat(params.DnsName) {
|
if !domainutils.ValidateDomainFormat(params.DnsName) {
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SuggestLoginPortsAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *SuggestLoginPortsAction) RunPost(params struct {
|
||||||
|
Host string
|
||||||
|
}) {
|
||||||
|
portsResp, err := this.RPC().NodeLoginRPC().FindNodeLoginSuggestPorts(this.AdminContext(), &pb.FindNodeLoginSuggestPortsRequest{Host: params.Host})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(portsResp.Ports) == 0 {
|
||||||
|
this.Data["ports"] = []int32{}
|
||||||
|
} else {
|
||||||
|
this.Data["ports"] = portsResp.Ports
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(portsResp.AvailablePorts) == 0 {
|
||||||
|
this.Data["availablePorts"] = []int32{}
|
||||||
|
} else {
|
||||||
|
this.Data["availablePorts"] = portsResp.AvailablePorts
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -36,6 +36,11 @@ func (this *UpdateNodeSSHAction) RunGet(params struct {
|
|||||||
"id": node.Id,
|
"id": node.Id,
|
||||||
"name": node.Name,
|
"name": node.Name,
|
||||||
}
|
}
|
||||||
|
if nodeResp.Node.NodeCluster != nil {
|
||||||
|
this.Data["clusterId"] = nodeResp.Node.NodeCluster.Id
|
||||||
|
} else {
|
||||||
|
this.Data["clusterId"] = 0
|
||||||
|
}
|
||||||
|
|
||||||
// SSH
|
// SSH
|
||||||
loginParams := maps.Map{
|
loginParams := maps.Map{
|
||||||
@@ -44,10 +49,10 @@ func (this *UpdateNodeSSHAction) RunGet(params struct {
|
|||||||
"grantId": 0,
|
"grantId": 0,
|
||||||
}
|
}
|
||||||
this.Data["loginId"] = 0
|
this.Data["loginId"] = 0
|
||||||
if node.Login != nil {
|
if node.NodeLogin != nil {
|
||||||
this.Data["loginId"] = node.Login.Id
|
this.Data["loginId"] = node.NodeLogin.Id
|
||||||
if len(node.Login.Params) > 0 {
|
if len(node.NodeLogin.Params) > 0 {
|
||||||
err = json.Unmarshal(node.Login.Params, &loginParams)
|
err = json.Unmarshal(node.NodeLogin.Params, &loginParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ func (this *UpgradeRemoteAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
for _, node := range resp.Nodes {
|
for _, node := range resp.Nodes {
|
||||||
loginParams := maps.Map{}
|
loginParams := maps.Map{}
|
||||||
if node.Node.Login != nil && len(node.Node.Login.Params) > 0 {
|
if node.Node.NodeLogin != nil && len(node.Node.NodeLogin.Params) > 0 {
|
||||||
err := json.Unmarshal(node.Node.Login.Params, &loginParams)
|
err := json.Unmarshal(node.Node.NodeLogin.Params, &loginParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
@@ -46,7 +46,7 @@ func (this *UpgradeRemoteAction) RunGet(params struct {
|
|||||||
"arch": node.Arch,
|
"arch": node.Arch,
|
||||||
"oldVersion": node.OldVersion,
|
"oldVersion": node.OldVersion,
|
||||||
"newVersion": node.NewVersion,
|
"newVersion": node.NewVersion,
|
||||||
"login": node.Node.Login,
|
"login": node.Node.NodeLogin,
|
||||||
"loginParams": loginParams,
|
"loginParams": loginParams,
|
||||||
"addresses": node.Node.IpAddresses,
|
"addresses": node.Node.IpAddresses,
|
||||||
"installStatus": node.Node.InstallStatus,
|
"installStatus": node.Node.InstallStatus,
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ func (this *CreatePopupAction) RunPost(params struct {
|
|||||||
this.FailField("username", "请输入SSH登录用户名")
|
this.FailField("username", "请输入SSH登录用户名")
|
||||||
}
|
}
|
||||||
case "privateKey":
|
case "privateKey":
|
||||||
|
if len(params.Username) == 0 {
|
||||||
|
this.FailField("username", "请输入SSH登录用户名")
|
||||||
|
}
|
||||||
if len(params.PrivateKey) == 0 {
|
if len(params.PrivateKey) == 0 {
|
||||||
this.FailField("privateKey", "请输入RSA私钥")
|
this.FailField("privateKey", "请输入RSA私钥")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,10 @@ func (this *SelectPopupAction) Init() {
|
|||||||
this.Nav("", "", "")
|
this.Nav("", "", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *SelectPopupAction) RunGet(params struct{}) {
|
func (this *SelectPopupAction) RunGet(params struct {
|
||||||
|
NodeClusterId int64
|
||||||
|
NsClusterId int64
|
||||||
|
}) {
|
||||||
// 所有的认证
|
// 所有的认证
|
||||||
grantsResp, err := this.RPC().NodeGrantRPC().FindAllEnabledNodeGrants(this.AdminContext(), &pb.FindAllEnabledNodeGrantsRequest{})
|
grantsResp, err := this.RPC().NodeGrantRPC().FindAllEnabledNodeGrants(this.AdminContext(), &pb.FindAllEnabledNodeGrantsRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -37,6 +40,28 @@ func (this *SelectPopupAction) RunGet(params struct{}) {
|
|||||||
}
|
}
|
||||||
this.Data["grants"] = grantMaps
|
this.Data["grants"] = grantMaps
|
||||||
|
|
||||||
|
// 推荐的认证
|
||||||
|
suggestGrantsResp, err := this.RPC().NodeGrantRPC().FindSuggestNodeGrants(this.AdminContext(), &pb.FindSuggestNodeGrantsRequest{
|
||||||
|
NodeClusterId: params.NodeClusterId,
|
||||||
|
NsClusterId: params.NsClusterId,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var suggestGrantMaps = []maps.Map{}
|
||||||
|
for _, grant := range suggestGrantsResp.NodeGrants {
|
||||||
|
suggestGrantMaps = append(suggestGrantMaps, maps.Map{
|
||||||
|
"id": grant.Id,
|
||||||
|
"name": grant.Name,
|
||||||
|
"method": grant.Method,
|
||||||
|
"methodName": grantutils.FindGrantMethodName(grant.Method),
|
||||||
|
"username": grant.Username,
|
||||||
|
"description": grant.Description,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["suggestGrants"] = suggestGrantMaps
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,9 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
|||||||
this.FailField("username", "请输入SSH登录用户名")
|
this.FailField("username", "请输入SSH登录用户名")
|
||||||
}
|
}
|
||||||
case "privateKey":
|
case "privateKey":
|
||||||
|
if len(params.Username) == 0 {
|
||||||
|
this.FailField("username", "请输入SSH登录用户名")
|
||||||
|
}
|
||||||
if len(params.PrivateKey) == 0 {
|
if len(params.PrivateKey) == 0 {
|
||||||
this.FailField("privateKey", "请输入RSA私钥")
|
this.FailField("privateKey", "请输入RSA私钥")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,6 +235,16 @@ func (this *IndexAction) searchNodes(keyword string) {
|
|||||||
dnsRouteNames = append(dnsRouteNames, route.Name)
|
dnsRouteNames = append(dnsRouteNames, route.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 从集群
|
||||||
|
var secondaryClusterMaps []maps.Map
|
||||||
|
for _, secondaryCluster := range node.SecondaryNodeClusters {
|
||||||
|
secondaryClusterMaps = append(secondaryClusterMaps, maps.Map{
|
||||||
|
"id": secondaryCluster.Id,
|
||||||
|
"name": secondaryCluster.Name,
|
||||||
|
"isOn": secondaryCluster.IsOn,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
nodeMaps = append(nodeMaps, maps.Map{
|
nodeMaps = append(nodeMaps, maps.Map{
|
||||||
"id": node.Id,
|
"id": node.Id,
|
||||||
"name": node.Name,
|
"name": node.Name,
|
||||||
@@ -260,11 +270,12 @@ func (this *IndexAction) searchNodes(keyword string) {
|
|||||||
"id": node.NodeCluster.Id,
|
"id": node.NodeCluster.Id,
|
||||||
"name": node.NodeCluster.Name,
|
"name": node.NodeCluster.Name,
|
||||||
},
|
},
|
||||||
"isSynced": isSynced,
|
"secondaryClusters": secondaryClusterMaps,
|
||||||
"ipAddresses": ipAddresses,
|
"isSynced": isSynced,
|
||||||
"group": groupMap,
|
"ipAddresses": ipAddresses,
|
||||||
"region": regionMap,
|
"group": groupMap,
|
||||||
"dnsRouteNames": dnsRouteNames,
|
"region": regionMap,
|
||||||
|
"dnsRouteNames": dnsRouteNames,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.Data["nodes"] = nodeMaps
|
this.Data["nodes"] = nodeMaps
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ func init() {
|
|||||||
EndHelpers().
|
EndHelpers().
|
||||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeCommon)).
|
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeCommon)).
|
||||||
Post("/options", new(OptionsAction)).
|
Post("/options", new(OptionsAction)).
|
||||||
|
GetPost("/selectPopup", new(SelectPopupAction)).
|
||||||
|
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -51,6 +51,10 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
Offset: page.Offset,
|
Offset: page.Offset,
|
||||||
Size: page.Size,
|
Size: page.Size,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
logs := []maps.Map{}
|
logs := []maps.Map{}
|
||||||
for _, log := range logsResp.NodeLogs {
|
for _, log := range logsResp.NodeLogs {
|
||||||
|
|||||||
64
internal/web/actions/default/clusters/selectPopup.go
Normal file
64
internal/web/actions/default/clusters/selectPopup.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package clusters
|
||||||
|
|
||||||
|
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 SelectPopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *SelectPopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *SelectPopupAction) RunGet(params struct {
|
||||||
|
SelectedClusterIds string
|
||||||
|
}) {
|
||||||
|
var selectedIds = utils.SplitNumbers(params.SelectedClusterIds)
|
||||||
|
|
||||||
|
countResp, err := this.RPC().NodeClusterRPC().CountAllEnabledNodeClusters(this.AdminContext(), &pb.CountAllEnabledNodeClustersRequest{})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var count = countResp.Count
|
||||||
|
var page = this.NewPage(count)
|
||||||
|
this.Data["page"] = page.AsHTML()
|
||||||
|
|
||||||
|
clustersResp, err := this.RPC().NodeClusterRPC().ListEnabledNodeClusters(this.AdminContext(), &pb.ListEnabledNodeClustersRequest{
|
||||||
|
Offset: page.Offset,
|
||||||
|
Size: page.Size,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var clusterMaps = []maps.Map{}
|
||||||
|
for _, cluster := range clustersResp.NodeClusters {
|
||||||
|
// 节点数
|
||||||
|
countNodesResp, err := this.RPC().NodeRPC().CountAllEnabledNodesMatch(this.AdminContext(), &pb.CountAllEnabledNodesMatchRequest{NodeClusterId: cluster.Id})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var countNodes = countNodesResp.Count
|
||||||
|
|
||||||
|
clusterMaps = append(clusterMaps, maps.Map{
|
||||||
|
"id": cluster.Id,
|
||||||
|
"name": cluster.Name,
|
||||||
|
"isOn": cluster.IsOn,
|
||||||
|
"countNodes": countNodes,
|
||||||
|
"isSelected": lists.ContainsInt64(selectedIds, cluster.Id),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["clusters"] = clusterMaps
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
@@ -43,16 +43,21 @@ func (this *ClustersPopupAction) RunGet(params struct {
|
|||||||
for _, cluster := range clustersResp.NodeClusters {
|
for _, cluster := range clustersResp.NodeClusters {
|
||||||
isOk := false
|
isOk := false
|
||||||
if len(cluster.Name) > 0 {
|
if len(cluster.Name) > 0 {
|
||||||
checkResp, err := this.RPC().DNSDomainRPC().ExistDNSDomainRecord(this.AdminContext(), &pb.ExistDNSDomainRecordRequest{
|
for _, recordType := range []string{"A", "AAAA"} {
|
||||||
DnsDomainId: params.DomainId,
|
checkResp, err := this.RPC().DNSDomainRPC().ExistDNSDomainRecord(this.AdminContext(), &pb.ExistDNSDomainRecordRequest{
|
||||||
Name: cluster.DnsName,
|
DnsDomainId: params.DomainId,
|
||||||
Type: "A",
|
Name: cluster.DnsName,
|
||||||
})
|
Type: recordType,
|
||||||
if err != nil {
|
})
|
||||||
this.ErrorPage(err)
|
if err != nil {
|
||||||
return
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if checkResp.IsOk {
|
||||||
|
isOk = true
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
isOk = checkResp.IsOk
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clusterMaps = append(clusterMaps, maps.Map{
|
clusterMaps = append(clusterMaps, maps.Map{
|
||||||
|
|||||||
@@ -33,12 +33,17 @@ func ValidateDomainFormat(domain string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ConvertRoutesToMaps 转换线路列表
|
// ConvertRoutesToMaps 转换线路列表
|
||||||
func ConvertRoutesToMaps(routes []*pb.DNSRoute) []maps.Map {
|
func ConvertRoutesToMaps(info *pb.NodeDNSInfo) []maps.Map {
|
||||||
|
if info == nil {
|
||||||
|
return []maps.Map{}
|
||||||
|
}
|
||||||
result := []maps.Map{}
|
result := []maps.Map{}
|
||||||
for _, route := range routes {
|
for _, route := range info.Routes {
|
||||||
result = append(result, maps.Map{
|
result = append(result, maps.Map{
|
||||||
"name": route.Name,
|
"name": route.Name,
|
||||||
"code": route.Code,
|
"code": route.Code,
|
||||||
|
"domainId": info.DnsDomainId,
|
||||||
|
"domainName": info.DnsDomainName,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package domains
|
package domains
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
@@ -55,10 +56,14 @@ func (this *NodesPopupAction) RunGet(params struct {
|
|||||||
// 检查是否有域名解析记录
|
// 检查是否有域名解析记录
|
||||||
isOk := false
|
isOk := false
|
||||||
if len(route.Name) > 0 && len(node.IpAddr) > 0 && len(cluster.DnsName) > 0 {
|
if len(route.Name) > 0 && len(node.IpAddr) > 0 && len(cluster.DnsName) > 0 {
|
||||||
|
var recordType = "A"
|
||||||
|
if utils.IsIPv6(node.IpAddr) {
|
||||||
|
recordType = "AAAA"
|
||||||
|
}
|
||||||
checkResp, err := this.RPC().DNSDomainRPC().ExistDNSDomainRecord(this.AdminContext(), &pb.ExistDNSDomainRecordRequest{
|
checkResp, err := this.RPC().DNSDomainRPC().ExistDNSDomainRecord(this.AdminContext(), &pb.ExistDNSDomainRecordRequest{
|
||||||
DnsDomainId: params.DomainId,
|
DnsDomainId: params.DomainId,
|
||||||
Name: cluster.DnsName,
|
Name: cluster.DnsName,
|
||||||
Type: "A",
|
Type: recordType,
|
||||||
Route: route.Code,
|
Route: route.Code,
|
||||||
Value: node.IpAddr,
|
Value: node.IpAddr,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -20,11 +20,15 @@ func (this *UpdateNodePopupAction) Init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *UpdateNodePopupAction) RunGet(params struct {
|
func (this *UpdateNodePopupAction) RunGet(params struct {
|
||||||
NodeId int64
|
ClusterId int64
|
||||||
|
NodeId int64
|
||||||
}) {
|
}) {
|
||||||
this.Data["nodeId"] = params.NodeId
|
this.Data["nodeId"] = params.NodeId
|
||||||
|
|
||||||
dnsInfoResp, err := this.RPC().NodeRPC().FindEnabledNodeDNS(this.AdminContext(), &pb.FindEnabledNodeDNSRequest{NodeId: params.NodeId})
|
dnsInfoResp, err := this.RPC().NodeRPC().FindEnabledNodeDNS(this.AdminContext(), &pb.FindEnabledNodeDNSRequest{
|
||||||
|
NodeId: params.NodeId,
|
||||||
|
NodeClusterId: params.ClusterId,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
@@ -35,7 +39,7 @@ func (this *UpdateNodePopupAction) RunGet(params struct {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.Data["ipAddr"] = dnsInfo.IpAddr
|
this.Data["ipAddr"] = dnsInfo.IpAddr
|
||||||
this.Data["routes"] = domainutils.ConvertRoutesToMaps(dnsInfo.Routes)
|
this.Data["routes"] = domainutils.ConvertRoutesToMaps(dnsInfo)
|
||||||
this.Data["domainId"] = dnsInfo.DnsDomainId
|
this.Data["domainId"] = dnsInfo.DnsDomainId
|
||||||
this.Data["domainName"] = dnsInfo.DnsDomainName
|
this.Data["domainName"] = dnsInfo.DnsDomainName
|
||||||
|
|
||||||
@@ -50,13 +54,17 @@ func (this *UpdateNodePopupAction) RunGet(params struct {
|
|||||||
if len(routesResp.Routes) > 0 {
|
if len(routesResp.Routes) > 0 {
|
||||||
for _, route := range routesResp.Routes {
|
for _, route := range routesResp.Routes {
|
||||||
allRouteMaps = append(allRouteMaps, maps.Map{
|
allRouteMaps = append(allRouteMaps, maps.Map{
|
||||||
"name": route.Name,
|
"name": route.Name,
|
||||||
"code": route.Code,
|
"code": route.Code,
|
||||||
|
"domainName": dnsInfo.DnsDomainName,
|
||||||
|
"domainId": dnsInfo.DnsDomainId,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 筛选
|
// 筛选
|
||||||
this.Data["routes"] = domainutils.ConvertRoutesToMaps(domainutils.FilterRoutes(dnsInfo.Routes, routesResp.Routes))
|
var routes = domainutils.FilterRoutes(dnsInfo.Routes, routesResp.Routes)
|
||||||
|
dnsInfo.Routes = routes
|
||||||
|
this.Data["routes"] = domainutils.ConvertRoutesToMaps(dnsInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.Data["allRoutes"] = allRouteMaps
|
this.Data["allRoutes"] = allRouteMaps
|
||||||
|
|||||||
@@ -67,6 +67,10 @@ func (this *CreatePopupAction) RunPost(params struct {
|
|||||||
ParamAccessKeyId string
|
ParamAccessKeyId string
|
||||||
ParamAccessKeySecret string
|
ParamAccessKeySecret string
|
||||||
|
|
||||||
|
// HuaweiDNS
|
||||||
|
ParamHuaweiAccessKeyId string
|
||||||
|
ParamHuaweiAccessKeySecret string
|
||||||
|
|
||||||
// DNS.COM
|
// DNS.COM
|
||||||
ParamApiKey string
|
ParamApiKey string
|
||||||
ParamApiSecret string
|
ParamApiSecret string
|
||||||
@@ -111,6 +115,15 @@ func (this *CreatePopupAction) RunPost(params struct {
|
|||||||
|
|
||||||
apiParams["accessKeyId"] = params.ParamAccessKeyId
|
apiParams["accessKeyId"] = params.ParamAccessKeyId
|
||||||
apiParams["accessKeySecret"] = params.ParamAccessKeySecret
|
apiParams["accessKeySecret"] = params.ParamAccessKeySecret
|
||||||
|
case "huaweiDNS":
|
||||||
|
params.Must.
|
||||||
|
Field("paramHuaweiAccessKeyId", params.ParamHuaweiAccessKeyId).
|
||||||
|
Require("请输入AccessKeyId").
|
||||||
|
Field("paramHuaweiAccessKeySecret", params.ParamHuaweiAccessKeySecret).
|
||||||
|
Require("请输入AccessKeySecret")
|
||||||
|
|
||||||
|
apiParams["accessKeyId"] = params.ParamHuaweiAccessKeyId
|
||||||
|
apiParams["accessKeySecret"] = params.ParamHuaweiAccessKeySecret
|
||||||
case "dnscom":
|
case "dnscom":
|
||||||
params.Must.
|
params.Must.
|
||||||
Field("paramApiKey", params.ParamApiKey).
|
Field("paramApiKey", params.ParamApiKey).
|
||||||
|
|||||||
@@ -96,6 +96,10 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
|||||||
ParamAccessKeyId string
|
ParamAccessKeyId string
|
||||||
ParamAccessKeySecret string
|
ParamAccessKeySecret string
|
||||||
|
|
||||||
|
// HuaweiDNS
|
||||||
|
ParamHuaweiAccessKeyId string
|
||||||
|
ParamHuaweiAccessKeySecret string
|
||||||
|
|
||||||
// DNS.COM
|
// DNS.COM
|
||||||
ParamApiKey string
|
ParamApiKey string
|
||||||
ParamApiSecret string
|
ParamApiSecret string
|
||||||
@@ -142,6 +146,15 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
|||||||
|
|
||||||
apiParams["accessKeyId"] = params.ParamAccessKeyId
|
apiParams["accessKeyId"] = params.ParamAccessKeyId
|
||||||
apiParams["accessKeySecret"] = params.ParamAccessKeySecret
|
apiParams["accessKeySecret"] = params.ParamAccessKeySecret
|
||||||
|
case "huaweiDNS":
|
||||||
|
params.Must.
|
||||||
|
Field("paramHuaweiAccessKeyId", params.ParamHuaweiAccessKeyId).
|
||||||
|
Require("请输入AccessKeyId").
|
||||||
|
Field("paramHuaweiAccessKeySecret", params.ParamHuaweiAccessKeySecret).
|
||||||
|
Require("请输入AccessKeySecret")
|
||||||
|
|
||||||
|
apiParams["accessKeyId"] = params.ParamHuaweiAccessKeyId
|
||||||
|
apiParams["accessKeySecret"] = params.ParamHuaweiAccessKeySecret
|
||||||
case "dnscom":
|
case "dnscom":
|
||||||
params.Must.
|
params.Must.
|
||||||
Field("paramApiKey", params.ParamApiKey).
|
Field("paramApiKey", params.ParamApiKey).
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
|
|
||||||
Auth *helpers.UserShouldAuth
|
Auth *helpers.UserShouldAuth
|
||||||
}) {
|
}) {
|
||||||
|
// DEMO模式
|
||||||
|
this.Data["isDemo"] = teaconst.IsDemoMode
|
||||||
|
|
||||||
// 检查系统是否已经配置过
|
// 检查系统是否已经配置过
|
||||||
if !setup.IsConfigured() {
|
if !setup.IsConfigured() {
|
||||||
this.RedirectURL("/setup")
|
this.RedirectURL("/setup")
|
||||||
@@ -53,19 +56,26 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
this.Data["token"] = stringutil.Md5(TokenSalt+timestamp) + timestamp
|
this.Data["token"] = stringutil.Md5(TokenSalt+timestamp) + timestamp
|
||||||
this.Data["from"] = params.From
|
this.Data["from"] = params.From
|
||||||
|
|
||||||
config, err := configloaders.LoadAdminUIConfig()
|
uiConfig, err := configloaders.LoadAdminUIConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.Data["systemName"] = config.AdminSystemName
|
this.Data["systemName"] = uiConfig.AdminSystemName
|
||||||
this.Data["showVersion"] = config.ShowVersion
|
this.Data["showVersion"] = uiConfig.ShowVersion
|
||||||
if len(config.Version) > 0 {
|
if len(uiConfig.Version) > 0 {
|
||||||
this.Data["version"] = config.Version
|
this.Data["version"] = uiConfig.Version
|
||||||
} else {
|
} else {
|
||||||
this.Data["version"] = teaconst.Version
|
this.Data["version"] = teaconst.Version
|
||||||
}
|
}
|
||||||
this.Data["faviconFileId"] = config.FaviconFileId
|
this.Data["faviconFileId"] = uiConfig.FaviconFileId
|
||||||
|
|
||||||
|
securityConfig, err := configloaders.LoadSecurityConfig()
|
||||||
|
if err != nil {
|
||||||
|
this.Data["rememberLogin"] = false
|
||||||
|
} else {
|
||||||
|
this.Data["rememberLogin"] = securityConfig.AllowRememberLogin
|
||||||
|
}
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ func (this *IndexAction) RunGet(params struct{}) {
|
|||||||
|
|
||||||
messages = append(messages, maps.Map{
|
messages = append(messages, maps.Map{
|
||||||
"id": message.Id,
|
"id": message.Id,
|
||||||
|
"role": message.Role,
|
||||||
"isRead": message.IsRead,
|
"isRead": message.IsRead,
|
||||||
"body": message.Body,
|
"body": message.Body,
|
||||||
"level": message.Level,
|
"level": message.Level,
|
||||||
|
|||||||
@@ -10,12 +10,16 @@ type DeleteAction struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *DeleteAction) RunPost(params struct {
|
func (this *DeleteAction) RunPost(params struct {
|
||||||
NodeId int64
|
ClusterId int64
|
||||||
|
NodeId int64
|
||||||
}) {
|
}) {
|
||||||
// 创建日志
|
// 创建日志
|
||||||
defer this.CreateLogInfo("删除节点", params.NodeId)
|
defer this.CreateLogInfo("从集群 %d 中删除节点 %d", params.ClusterId, params.NodeId)
|
||||||
|
|
||||||
_, err := this.RPC().NodeRPC().DeleteNode(this.AdminContext(), &pb.DeleteNodeRequest{NodeId: params.NodeId})
|
_, err := this.RPC().NodeRPC().DeleteNodeFromNodeCluster(this.AdminContext(), &pb.DeleteNodeFromNodeClusterRequest{
|
||||||
|
NodeId: params.NodeId,
|
||||||
|
NodeClusterId: params.ClusterId,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
"error": node.InstallStatus.Error,
|
"error": node.InstallStatus.Error,
|
||||||
},
|
},
|
||||||
"status": maps.Map{
|
"status": maps.Map{
|
||||||
"isActive": status.IsActive,
|
"isActive": node.IsActive,
|
||||||
"updatedAt": status.UpdatedAt,
|
"updatedAt": status.UpdatedAt,
|
||||||
"hostname": status.Hostname,
|
"hostname": status.Hostname,
|
||||||
"cpuUsage": status.CPUUsage,
|
"cpuUsage": status.CPUUsage,
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ func init() {
|
|||||||
GetPost("/createNode", new(CreateNodeAction)).
|
GetPost("/createNode", new(CreateNodeAction)).
|
||||||
Post("/deleteNode", new(DeleteNodeAction)).
|
Post("/deleteNode", new(DeleteNodeAction)).
|
||||||
Get("/upgradeRemote", new(UpgradeRemoteAction)).
|
Get("/upgradeRemote", new(UpgradeRemoteAction)).
|
||||||
|
GetPost("/updateNodeSSH", new(UpdateNodeSSHAction)).
|
||||||
|
|
||||||
// 节点相关
|
// 节点相关
|
||||||
Prefix("/ns/clusters/cluster/node").
|
Prefix("/ns/clusters/cluster/node").
|
||||||
@@ -30,7 +31,8 @@ func init() {
|
|||||||
GetPost("/install", new(node.InstallAction)).
|
GetPost("/install", new(node.InstallAction)).
|
||||||
Post("/status", new(node.StatusAction)).
|
Post("/status", new(node.StatusAction)).
|
||||||
Post("/updateInstallStatus", new(node.UpdateInstallStatusAction)).
|
Post("/updateInstallStatus", new(node.UpdateInstallStatusAction)).
|
||||||
|
Post("/start", new(node.StartAction)).
|
||||||
|
Post("/stop", new(node.StopAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"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/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
@@ -102,6 +103,46 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
this.Data["newVersion"] = ""
|
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{
|
this.Data["node"] = maps.Map{
|
||||||
"id": node.Id,
|
"id": node.Id,
|
||||||
"name": node.Name,
|
"name": node.Name,
|
||||||
@@ -114,7 +155,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
"isOn": node.IsOn,
|
"isOn": node.IsOn,
|
||||||
|
|
||||||
"status": maps.Map{
|
"status": maps.Map{
|
||||||
"isActive": status.IsActive,
|
"isActive": node.IsActive && status.IsActive,
|
||||||
"updatedAt": status.UpdatedAt,
|
"updatedAt": status.UpdatedAt,
|
||||||
"hostname": status.Hostname,
|
"hostname": status.Hostname,
|
||||||
"cpuUsage": status.CPUUsage,
|
"cpuUsage": status.CPUUsage,
|
||||||
@@ -131,6 +172,8 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
"cacheTotalDiskSize": numberutils.FormatBytes(status.CacheTotalDiskSize),
|
"cacheTotalDiskSize": numberutils.FormatBytes(status.CacheTotalDiskSize),
|
||||||
"cacheTotalMemorySize": numberutils.FormatBytes(status.CacheTotalMemorySize),
|
"cacheTotalMemorySize": numberutils.FormatBytes(status.CacheTotalMemorySize),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"login": loginMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"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/EdgeAdmin/internal/web/actions/default/nodes/ipAddresses/ipaddressutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
@@ -63,12 +64,53 @@ func (this *UpdateAction) RunGet(params struct {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 登录信息
|
||||||
|
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{
|
this.Data["node"] = maps.Map{
|
||||||
"id": node.Id,
|
"id": node.Id,
|
||||||
"name": node.Name,
|
"name": node.Name,
|
||||||
"ipAddresses": ipAddressMaps,
|
"ipAddresses": ipAddressMaps,
|
||||||
"cluster": clusterMap,
|
"cluster": clusterMap,
|
||||||
"isOn": node.IsOn,
|
"isOn": node.IsOn,
|
||||||
|
"login": loginMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 所有集群
|
// 所有集群
|
||||||
@@ -93,7 +135,11 @@ func (this *UpdateAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *UpdateAction) RunPost(params struct {
|
func (this *UpdateAction) RunPost(params struct {
|
||||||
LoginId int64
|
LoginId int64
|
||||||
|
GrantId int64
|
||||||
|
SshHost string
|
||||||
|
SshPort int
|
||||||
|
|
||||||
NodeId int64
|
NodeId int64
|
||||||
Name string
|
Name string
|
||||||
IPAddressesJSON []byte `alias:"ipAddressesJSON"`
|
IPAddressesJSON []byte `alias:"ipAddressesJSON"`
|
||||||
@@ -139,12 +185,25 @@ func (this *UpdateAction) RunPost(params struct {
|
|||||||
this.Fail("请至少输入一个IP地址")
|
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{
|
_, err = this.RPC().NSNodeRPC().UpdateNSNode(this.AdminContext(), &pb.UpdateNSNodeRequest{
|
||||||
NsNodeId: params.NodeId,
|
NsNodeId: params.NodeId,
|
||||||
Name: params.Name,
|
Name: params.Name,
|
||||||
NsClusterId: params.ClusterId,
|
NsClusterId: params.ClusterId,
|
||||||
IsOn: params.IsOn,
|
IsOn: params.IsOn,
|
||||||
|
NodeLogin: loginInfo,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
accessLogRef := &dnsconfigs.AccessLogRef{}
|
accessLogRef := &dnsconfigs.NSAccessLogRef{}
|
||||||
if len(accessLogResp.AccessLogJSON) > 0 {
|
if len(accessLogResp.AccessLogJSON) > 0 {
|
||||||
err = json.Unmarshal(accessLogResp.AccessLogJSON, accessLogRef)
|
err = json.Unmarshal(accessLogResp.AccessLogJSON, accessLogRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -50,7 +50,7 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
}) {
|
}) {
|
||||||
defer this.CreateLogInfo("修改域名服务集群 %d 访问日志配置", params.ClusterId)
|
defer this.CreateLogInfo("修改域名服务集群 %d 访问日志配置", params.ClusterId)
|
||||||
|
|
||||||
ref := &dnsconfigs.AccessLogRef{}
|
ref := &dnsconfigs.NSAccessLogRef{}
|
||||||
err := json.Unmarshal(params.AccessLogJSON, ref)
|
err := json.Unmarshal(params.AccessLogJSON, ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.Fail("数据格式错误:" + err.Error())
|
this.Fail("数据格式错误:" + err.Error())
|
||||||
|
|||||||
@@ -0,0 +1,129 @@
|
|||||||
|
package cluster
|
||||||
|
|
||||||
|
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/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpdateNodeSSHAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdateNodeSSHAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdateNodeSSHAction) RunGet(params struct {
|
||||||
|
NodeId int64
|
||||||
|
}) {
|
||||||
|
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: params.NodeId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if nodeResp.NsNode == nil {
|
||||||
|
this.NotFound("node", params.NodeId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
node := nodeResp.NsNode
|
||||||
|
this.Data["node"] = maps.Map{
|
||||||
|
"id": node.Id,
|
||||||
|
"name": node.Name,
|
||||||
|
}
|
||||||
|
|
||||||
|
if nodeResp.NsNode.NsCluster != nil {
|
||||||
|
this.Data["clusterId"] = nodeResp.NsNode.NsCluster.Id
|
||||||
|
} else {
|
||||||
|
this.Data["clusterId"] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// SSH
|
||||||
|
loginParams := maps.Map{
|
||||||
|
"host": "",
|
||||||
|
"port": "",
|
||||||
|
"grantId": 0,
|
||||||
|
}
|
||||||
|
this.Data["loginId"] = 0
|
||||||
|
if node.NodeLogin != nil {
|
||||||
|
this.Data["loginId"] = node.NodeLogin.Id
|
||||||
|
if len(node.NodeLogin.Params) > 0 {
|
||||||
|
err = json.Unmarshal(node.NodeLogin.Params, &loginParams)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Data["params"] = loginParams
|
||||||
|
|
||||||
|
// 认证信息
|
||||||
|
grantId := loginParams.GetInt64("grantId")
|
||||||
|
grantResp, err := this.RPC().NodeGrantRPC().FindEnabledNodeGrant(this.AdminContext(), &pb.FindEnabledNodeGrantRequest{NodeGrantId: grantId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
}
|
||||||
|
var grantMap maps.Map = nil
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Data["grant"] = grantMap
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdateNodeSSHAction) RunPost(params struct {
|
||||||
|
NodeId int64
|
||||||
|
LoginId int64
|
||||||
|
SshHost string
|
||||||
|
SshPort int
|
||||||
|
GrantId int64
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
params.Must.
|
||||||
|
Field("sshHost", params.SshHost).
|
||||||
|
Require("请输入SSH主机地址").
|
||||||
|
Field("sshPort", params.SshPort).
|
||||||
|
Gt(0, "SSH主机端口需要大于0").
|
||||||
|
Lt(65535, "SSH主机端口需要小于65535")
|
||||||
|
|
||||||
|
if params.GrantId <= 0 {
|
||||||
|
this.Fail("需要选择或填写至少一个认证信息")
|
||||||
|
}
|
||||||
|
|
||||||
|
login := &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().UpdateNSNodeLogin(this.AdminContext(), &pb.UpdateNSNodeLoginRequest{
|
||||||
|
NsNodeId: params.NodeId,
|
||||||
|
NodeLogin: login,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建日志
|
||||||
|
defer this.CreateLog(oplogs.LevelInfo, "修改节点 %d 配置", params.NodeId)
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@ func (this *CreateAction) Init() {
|
|||||||
|
|
||||||
func (this *CreateAction) RunGet(params struct{}) {
|
func (this *CreateAction) RunGet(params struct{}) {
|
||||||
// 默认的访问日志设置
|
// 默认的访问日志设置
|
||||||
this.Data["accessLogRef"] = &dnsconfigs.AccessLogRef{
|
this.Data["accessLogRef"] = &dnsconfigs.NSAccessLogRef{
|
||||||
IsOn: true,
|
IsOn: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ func (this *CreateAction) RunPost(params struct {
|
|||||||
Require("请输入集群名称")
|
Require("请输入集群名称")
|
||||||
|
|
||||||
// 校验访问日志设置
|
// 校验访问日志设置
|
||||||
ref := &dnsconfigs.AccessLogRef{}
|
ref := &dnsconfigs.NSAccessLogRef{}
|
||||||
err := json.Unmarshal(params.AccessLogJSON, ref)
|
err := json.Unmarshal(params.AccessLogJSON, ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.Fail("数据格式错误:" + err.Error())
|
this.Fail("数据格式错误:" + err.Error())
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package domains
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"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/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
)
|
)
|
||||||
@@ -19,6 +20,14 @@ func (this *DomainAction) Init() {
|
|||||||
func (this *DomainAction) RunGet(params struct {
|
func (this *DomainAction) RunGet(params struct {
|
||||||
DomainId int64
|
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})
|
domainResp, err := this.RPC().NSDomainRPC().FindEnabledNSDomain(this.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: params.DomainId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -50,11 +59,13 @@ func (this *DomainAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.Data["domain"] = maps.Map{
|
this.Data["domain"] = maps.Map{
|
||||||
"id": domain.Id,
|
"id": domain.Id,
|
||||||
"name": domain.Name,
|
"name": domain.Name,
|
||||||
"isOn": domain.IsOn,
|
"isOn": domain.IsOn,
|
||||||
"cluster": clusterMap,
|
"cluster": clusterMap,
|
||||||
"user": userMap,
|
"user": userMap,
|
||||||
|
"countRecords": countRecords,
|
||||||
|
"countKeys": countKeys,
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
|
|||||||
55
internal/web/actions/default/ns/domains/domainutils/utils.go
Normal file
55
internal/web/actions/default/ns/domains/domainutils/utils.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
// 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
|
||||||
|
}
|
||||||
96
internal/web/actions/default/ns/domains/index.go
Normal file
96
internal/web/actions/default/ns/domains/index.go
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
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.FirstMenu("domain")
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
86
internal/web/actions/default/ns/domains/keys/createPopup.go
Normal file
86
internal/web/actions/default/ns/domains/keys/createPopup.go
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
// 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()
|
||||||
|
}
|
||||||
26
internal/web/actions/default/ns/domains/keys/delete.go
Normal file
26
internal/web/actions/default/ns/domains/keys/delete.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// 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()
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// 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()
|
||||||
|
}
|
||||||
68
internal/web/actions/default/ns/domains/keys/index.go
Normal file
68
internal/web/actions/default/ns/domains/keys/index.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
// 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()
|
||||||
|
}
|
||||||
100
internal/web/actions/default/ns/domains/keys/updatePopup.go
Normal file
100
internal/web/actions/default/ns/domains/keys/updatePopup.go
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
// 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()
|
||||||
|
}
|
||||||
@@ -54,7 +54,7 @@ func (this *CreatePopupAction) RunPost(params struct {
|
|||||||
Value string
|
Value string
|
||||||
Ttl int32
|
Ttl int32
|
||||||
Description string
|
Description string
|
||||||
RouteIds []int64
|
RouteCodes []string
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
@@ -76,13 +76,13 @@ func (this *CreatePopupAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createResp, err := this.RPC().NSRecordRPC().CreateNSRecord(this.AdminContext(), &pb.CreateNSRecordRequest{
|
createResp, err := this.RPC().NSRecordRPC().CreateNSRecord(this.AdminContext(), &pb.CreateNSRecordRequest{
|
||||||
NsDomainId: params.DomainId,
|
NsDomainId: params.DomainId,
|
||||||
Description: params.Description,
|
Description: params.Description,
|
||||||
Name: params.Name,
|
Name: params.Name,
|
||||||
Type: params.Type,
|
Type: params.Type,
|
||||||
Value: params.Value,
|
Value: params.Value,
|
||||||
Ttl: params.Ttl,
|
Ttl: params.Ttl,
|
||||||
NsRouteIds: params.RouteIds,
|
NsRouteCodes: params.RouteCodes,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package records
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"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/dnsconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
@@ -21,34 +22,25 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
DomainId int64
|
DomainId int64
|
||||||
Type string
|
Type string
|
||||||
Keyword string
|
Keyword string
|
||||||
RouteId int64
|
RouteCode string
|
||||||
}) {
|
}) {
|
||||||
this.Data["type"] = params.Type
|
// 初始化域名信息
|
||||||
this.Data["keyword"] = params.Keyword
|
err := domainutils.InitDomain(this.Parent(), params.DomainId)
|
||||||
this.Data["routeId"] = params.RouteId
|
|
||||||
|
|
||||||
// 域名信息
|
|
||||||
domainResp, err := this.RPC().NSDomainRPC().FindEnabledNSDomain(this.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: params.DomainId})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
domain := domainResp.NsDomain
|
|
||||||
if domain == nil {
|
this.Data["type"] = params.Type
|
||||||
this.NotFound("nsDomain", params.DomainId)
|
this.Data["keyword"] = params.Keyword
|
||||||
return
|
this.Data["routeCode"] = params.RouteCode
|
||||||
}
|
|
||||||
this.Data["domain"] = maps.Map{
|
|
||||||
"id": domain.Id,
|
|
||||||
"name": domain.Name,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 记录
|
// 记录
|
||||||
countResp, err := this.RPC().NSRecordRPC().CountAllEnabledNSRecords(this.AdminContext(), &pb.CountAllEnabledNSRecordsRequest{
|
countResp, err := this.RPC().NSRecordRPC().CountAllEnabledNSRecords(this.AdminContext(), &pb.CountAllEnabledNSRecordsRequest{
|
||||||
NsDomainId: params.DomainId,
|
NsDomainId: params.DomainId,
|
||||||
Type: params.Type,
|
Type: params.Type,
|
||||||
NsRouteId: params.RouteId,
|
NsRouteCode: params.RouteCode,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
@@ -59,12 +51,12 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
this.Data["page"] = page.AsHTML()
|
this.Data["page"] = page.AsHTML()
|
||||||
|
|
||||||
recordsResp, err := this.RPC().NSRecordRPC().ListEnabledNSRecords(this.AdminContext(), &pb.ListEnabledNSRecordsRequest{
|
recordsResp, err := this.RPC().NSRecordRPC().ListEnabledNSRecords(this.AdminContext(), &pb.ListEnabledNSRecordsRequest{
|
||||||
NsDomainId: params.DomainId,
|
NsDomainId: params.DomainId,
|
||||||
Type: params.Type,
|
Type: params.Type,
|
||||||
NsRouteId: params.RouteId,
|
NsRouteCode: params.RouteCode,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
Offset: page.Offset,
|
Offset: page.Offset,
|
||||||
Size: page.Size,
|
Size: page.Size,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -33,11 +33,6 @@ func (this *UpdatePopupAction) RunGet(params struct {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
routeIds := []int64{}
|
|
||||||
for _, route := range record.NsRoutes {
|
|
||||||
routeIds = append(routeIds, route.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Data["record"] = maps.Map{
|
this.Data["record"] = maps.Map{
|
||||||
"id": record.Id,
|
"id": record.Id,
|
||||||
"name": record.Name,
|
"name": record.Name,
|
||||||
@@ -47,7 +42,7 @@ func (this *UpdatePopupAction) RunGet(params struct {
|
|||||||
"weight": record.Weight,
|
"weight": record.Weight,
|
||||||
"description": record.Description,
|
"description": record.Description,
|
||||||
"isOn": record.IsOn,
|
"isOn": record.IsOn,
|
||||||
"routeIds": routeIds,
|
"routes": record.NsRoutes,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 域名信息
|
// 域名信息
|
||||||
@@ -83,7 +78,7 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
|||||||
Ttl int32
|
Ttl int32
|
||||||
Description string
|
Description string
|
||||||
IsOn bool
|
IsOn bool
|
||||||
RouteIds []int64
|
RouteCodes []string
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
@@ -102,14 +97,14 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, err := this.RPC().NSRecordRPC().UpdateNSRecord(this.AdminContext(), &pb.UpdateNSRecordRequest{
|
_, err := this.RPC().NSRecordRPC().UpdateNSRecord(this.AdminContext(), &pb.UpdateNSRecordRequest{
|
||||||
NsRecordId: params.RecordId,
|
NsRecordId: params.RecordId,
|
||||||
Description: params.Description,
|
Description: params.Description,
|
||||||
Name: params.Name,
|
Name: params.Name,
|
||||||
Type: params.Type,
|
Type: params.Type,
|
||||||
Value: params.Value,
|
Value: params.Value,
|
||||||
Ttl: params.Ttl,
|
Ttl: params.Ttl,
|
||||||
IsOn: params.IsOn,
|
IsOn: params.IsOn,
|
||||||
NsRouteIds: params.RouteIds,
|
NsRouteCodes: params.RouteCodes,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
80
internal/web/actions/default/ns/domains/tsig.go
Normal file
80
internal/web/actions/default/ns/domains/tsig.go
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
// 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()
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ package domains
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"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/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
@@ -20,6 +21,15 @@ func (this *UpdateAction) Init() {
|
|||||||
func (this *UpdateAction) RunGet(params struct {
|
func (this *UpdateAction) RunGet(params struct {
|
||||||
DomainId int64
|
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})
|
domainResp, err := this.RPC().NSDomainRPC().FindEnabledNSDomain(this.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: params.DomainId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -44,11 +54,13 @@ func (this *UpdateAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.Data["domain"] = maps.Map{
|
this.Data["domain"] = maps.Map{
|
||||||
"id": domain.Id,
|
"id": domain.Id,
|
||||||
"name": domain.Name,
|
"name": domain.Name,
|
||||||
"isOn": domain.IsOn,
|
"isOn": domain.IsOn,
|
||||||
"clusterId": clusterId,
|
"clusterId": clusterId,
|
||||||
"userId": userId,
|
"userId": userId,
|
||||||
|
"countRecords": countRecords,
|
||||||
|
"countKeys": countKeys,
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
package ns
|
package ns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IndexAction struct {
|
type IndexAction struct {
|
||||||
@@ -12,85 +15,113 @@ type IndexAction struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *IndexAction) Init() {
|
func (this *IndexAction) Init() {
|
||||||
this.FirstMenu("index")
|
this.Nav("", "", "dns")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *IndexAction) RunGet(params struct {
|
func (this *IndexAction) RunGet(params struct{}) {
|
||||||
ClusterId int64
|
resp, err := this.RPC().NSRPC().ComposeNSBoard(this.AdminContext(), &pb.ComposeNSBoardRequest{})
|
||||||
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 {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.Data["countClusters"] = countClustersResp.Count
|
this.Data["board"] = maps.Map{
|
||||||
|
"countDomains": resp.CountNSDomains,
|
||||||
// 分页
|
"countRecords": resp.CountNSRecords,
|
||||||
countResp, err := this.RPC().NSDomainRPC().CountAllEnabledNSDomains(this.AdminContext(), &pb.CountAllEnabledNSDomainsRequest{
|
"countClusters": resp.CountNSClusters,
|
||||||
UserId: params.UserId,
|
"countNodes": resp.CountNSNodes,
|
||||||
NsClusterId: params.ClusterId,
|
"countOfflineNodes": resp.CountOfflineNSNodes,
|
||||||
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,
|
var statMaps = []maps.Map{}
|
||||||
NsClusterId: params.ClusterId,
|
for _, stat := range resp.HourlyTrafficStats {
|
||||||
Keyword: params.Keyword,
|
statMaps = append(statMaps, maps.Map{
|
||||||
Offset: page.Offset,
|
"day": stat.Hour[4:6] + "月" + stat.Hour[6:8] + "日",
|
||||||
Size: page.Size,
|
"hour": stat.Hour[8:],
|
||||||
})
|
"countRequests": stat.CountRequests,
|
||||||
if err != nil {
|
"bytes": stat.Bytes,
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
this.Data["hourlyStats"] = statMaps
|
||||||
// 用户信息
|
}
|
||||||
var userMap maps.Map
|
|
||||||
if domain.User != nil {
|
{
|
||||||
userMap = maps.Map{
|
var statMaps = []maps.Map{}
|
||||||
"id": domain.User.Id,
|
for _, stat := range resp.DailyTrafficStats {
|
||||||
"username": domain.User.Username,
|
statMaps = append(statMaps, maps.Map{
|
||||||
"fullname": domain.User.Fullname,
|
"day": stat.Day[4:6] + "月" + stat.Day[6:] + "日",
|
||||||
}
|
"countRequests": stat.CountRequests,
|
||||||
}
|
"bytes": stat.Bytes,
|
||||||
|
})
|
||||||
domainMaps = append(domainMaps, maps.Map{
|
}
|
||||||
"id": domain.Id,
|
this.Data["dailyStats"] = statMaps
|
||||||
"name": domain.Name,
|
}
|
||||||
"isOn": domain.IsOn,
|
|
||||||
"cluster": clusterMap,
|
// 域名排行
|
||||||
"user": userMap,
|
{
|
||||||
})
|
var statMaps = []maps.Map{}
|
||||||
|
for _, stat := range resp.TopNSDomainStats {
|
||||||
|
statMaps = append(statMaps, maps.Map{
|
||||||
|
"domainId": stat.NsDomainId,
|
||||||
|
"domainName": stat.NsDomainName,
|
||||||
|
"countRequests": stat.CountRequests,
|
||||||
|
"bytes": stat.Bytes,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["topDomainStats"] = statMaps
|
||||||
|
}
|
||||||
|
|
||||||
|
// 节点排行
|
||||||
|
{
|
||||||
|
var statMaps = []maps.Map{}
|
||||||
|
for _, stat := range resp.TopNSNodeStats {
|
||||||
|
statMaps = append(statMaps, maps.Map{
|
||||||
|
"clusterId": stat.NsClusterId,
|
||||||
|
"nodeId": stat.NsNodeId,
|
||||||
|
"nodeName": stat.NsNodeName,
|
||||||
|
"countRequests": stat.CountRequests,
|
||||||
|
"bytes": stat.Bytes,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["topNodeStats"] = statMaps
|
||||||
|
}
|
||||||
|
|
||||||
|
// CPU
|
||||||
|
{
|
||||||
|
var statMaps = []maps.Map{}
|
||||||
|
for _, stat := range resp.CpuNodeValues {
|
||||||
|
statMaps = append(statMaps, maps.Map{
|
||||||
|
"time": timeutil.FormatTime("H:i", stat.CreatedAt),
|
||||||
|
"value": types.Float32(string(stat.ValueJSON)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["cpuValues"] = statMaps
|
||||||
|
}
|
||||||
|
|
||||||
|
// Memory
|
||||||
|
{
|
||||||
|
var statMaps = []maps.Map{}
|
||||||
|
for _, stat := range resp.MemoryNodeValues {
|
||||||
|
statMaps = append(statMaps, maps.Map{
|
||||||
|
"time": timeutil.FormatTime("H:i", stat.CreatedAt),
|
||||||
|
"value": types.Float32(string(stat.ValueJSON)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["memoryValues"] = statMaps
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load
|
||||||
|
{
|
||||||
|
var statMaps = []maps.Map{}
|
||||||
|
for _, stat := range resp.LoadNodeValues {
|
||||||
|
statMaps = append(statMaps, maps.Map{
|
||||||
|
"time": timeutil.FormatTime("H:i", stat.CreatedAt),
|
||||||
|
"value": types.Float32(string(stat.ValueJSON)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["loadValues"] = statMaps
|
||||||
}
|
}
|
||||||
this.Data["domains"] = domainMaps
|
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package ns
|
|||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/keys"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/records"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/records"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/settings"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||||
"github.com/iwind/TeaGo"
|
"github.com/iwind/TeaGo"
|
||||||
)
|
)
|
||||||
@@ -18,10 +20,22 @@ func init() {
|
|||||||
|
|
||||||
// 域名相关
|
// 域名相关
|
||||||
Prefix("/ns/domains").
|
Prefix("/ns/domains").
|
||||||
|
Data("teaSubMenu", "domain").
|
||||||
|
Get("", new(domains.IndexAction)).
|
||||||
GetPost("/create", new(domains.CreateAction)).
|
GetPost("/create", new(domains.CreateAction)).
|
||||||
Post("/delete", new(domains.DeleteAction)).
|
Post("/delete", new(domains.DeleteAction)).
|
||||||
Get("/domain", new(domains.DomainAction)).
|
Get("/domain", new(domains.DomainAction)).
|
||||||
GetPost("/update", new(domains.UpdateAction)).
|
GetPost("/update", new(domains.UpdateAction)).
|
||||||
|
GetPost("/tsig", new(domains.TsigAction)).
|
||||||
|
|
||||||
|
// 域名密钥
|
||||||
|
Prefix("/ns/domains/keys").
|
||||||
|
Data("teaSubMenu", "domain").
|
||||||
|
Get("", new(keys.IndexAction)).
|
||||||
|
GetPost("/createPopup", new(keys.CreatePopupAction)).
|
||||||
|
GetPost("/updatePopup", new(keys.UpdatePopupAction)).
|
||||||
|
Post("/delete", new(keys.DeleteAction)).
|
||||||
|
Post("/generateSecret", new(keys.GenerateSecretAction)).
|
||||||
|
|
||||||
// 记录相关
|
// 记录相关
|
||||||
Prefix("/ns/domains/records").
|
Prefix("/ns/domains/records").
|
||||||
@@ -30,6 +44,9 @@ func init() {
|
|||||||
GetPost("/updatePopup", new(records.UpdatePopupAction)).
|
GetPost("/updatePopup", new(records.UpdatePopupAction)).
|
||||||
Post("/delete", new(records.DeleteAction)).
|
Post("/delete", new(records.DeleteAction)).
|
||||||
|
|
||||||
|
// 设置
|
||||||
|
Prefix("/ns/settings").
|
||||||
|
Get("", new(settings.IndexAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ package clusters
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"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/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OptionsAction struct {
|
type OptionsAction struct {
|
||||||
@@ -17,6 +19,18 @@ func (this *OptionsAction) RunPost(params struct {
|
|||||||
DomainId int64
|
DomainId int64
|
||||||
UserId 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{
|
routesResp, err := this.RPC().NSRouteRPC().FindAllEnabledNSRoutes(this.AdminContext(), &pb.FindAllEnabledNSRoutesRequest{
|
||||||
NsClusterId: params.ClusterId,
|
NsClusterId: params.ClusterId,
|
||||||
NsDomainId: params.DomainId,
|
NsDomainId: params.DomainId,
|
||||||
@@ -27,13 +41,45 @@ func (this *OptionsAction) RunPost(params struct {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
routeMaps := []maps.Map{}
|
|
||||||
for _, route := range routesResp.NsRoutes {
|
for _, route := range routesResp.NsRoutes {
|
||||||
|
if len(route.Code) == 0 {
|
||||||
|
route.Code = "id:" + types.String(route.Id)
|
||||||
|
}
|
||||||
|
|
||||||
routeMaps = append(routeMaps, maps.Map{
|
routeMaps = append(routeMaps, maps.Map{
|
||||||
"id": route.Id,
|
|
||||||
"name": route.Name,
|
"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.Data["routes"] = routeMaps
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
|
|||||||
77
internal/web/actions/default/ns/settings/accesslogs/index.go
Normal file
77
internal/web/actions/default/ns/settings/accesslogs/index.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
// 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()
|
||||||
|
}
|
||||||
23
internal/web/actions/default/ns/settings/accesslogs/init.go
Normal file
23
internal/web/actions/default/ns/settings/accesslogs/init.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package accesslogs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/settings/settingutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||||
|
"github.com/iwind/TeaGo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||||
|
server.
|
||||||
|
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||||
|
Helper(new(settingutils.Helper)).
|
||||||
|
Data("teaMenu", "ns").
|
||||||
|
Data("teaSubMenu", "setting").
|
||||||
|
Prefix("/ns/settings/accesslogs").
|
||||||
|
GetPost("", new(IndexAction)).
|
||||||
|
EndAll()
|
||||||
|
})
|
||||||
|
}
|
||||||
17
internal/web/actions/default/ns/settings/index.go
Normal file
17
internal/web/actions/default/ns/settings/index.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// 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")
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// 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",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
156
internal/web/actions/default/ns/test/index.go
Normal file
156
internal/web/actions/default/ns/test/index.go
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
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"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
"net"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IndexAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunGet(params struct{}) {
|
||||||
|
// 集群列表
|
||||||
|
clustersResp, err := this.RPC().NSClusterRPC().FindAllEnabledNSClusters(this.AdminContext(), &pb.FindAllEnabledNSClustersRequest{})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var clusterMaps = []maps.Map{}
|
||||||
|
for _, cluster := range clustersResp.NsClusters {
|
||||||
|
if !cluster.IsOn {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
countNodesResp, err := this.RPC().NSNodeRPC().CountAllEnabledNSNodesMatch(this.AdminContext(), &pb.CountAllEnabledNSNodesMatchRequest{
|
||||||
|
NsClusterId: cluster.Id,
|
||||||
|
InstallState: 0,
|
||||||
|
ActiveState: 0,
|
||||||
|
Keyword: "",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var countNodes = countNodesResp.Count
|
||||||
|
if countNodes <= 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
clusterMaps = append(clusterMaps, maps.Map{
|
||||||
|
"id": cluster.Id,
|
||||||
|
"name": cluster.Name,
|
||||||
|
"countNodes": countNodes,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["clusters"] = clusterMaps
|
||||||
|
|
||||||
|
// 记录类型
|
||||||
|
this.Data["recordTypes"] = dnsconfigs.FindAllRecordTypeDefinitions()
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunPost(params struct {
|
||||||
|
NodeId int64
|
||||||
|
Domain string
|
||||||
|
Type string
|
||||||
|
Ip string
|
||||||
|
ClientIP string
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: params.NodeId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var node = nodeResp.NsNode
|
||||||
|
if node == nil {
|
||||||
|
this.Fail("找不到要测试的节点")
|
||||||
|
}
|
||||||
|
|
||||||
|
var isOk = false
|
||||||
|
var errMsg string
|
||||||
|
var isNetError = false
|
||||||
|
var result string
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
this.Data["isOk"] = isOk
|
||||||
|
this.Data["err"] = errMsg
|
||||||
|
this.Data["isNetErr"] = isNetError
|
||||||
|
this.Data["result"] = result
|
||||||
|
this.Success()
|
||||||
|
}()
|
||||||
|
|
||||||
|
if !domainutils.ValidateDomainFormat(params.Domain) {
|
||||||
|
errMsg = "域名格式错误"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
recordType, ok := dns.StringToType[params.Type]
|
||||||
|
if !ok {
|
||||||
|
errMsg = "不支持此记录类型"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(params.ClientIP) > 0 && net.ParseIP(params.ClientIP) == nil {
|
||||||
|
errMsg = "客户端IP格式不正确"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var optionId int64
|
||||||
|
if len(params.ClientIP) > 0 {
|
||||||
|
optionResp, err := this.RPC().NSQuestionOptionRPC().CreateNSQuestionOption(this.AdminContext(), &pb.CreateNSQuestionOptionRequest{
|
||||||
|
Name: "setRemoteAddr",
|
||||||
|
ValuesJSON: maps.Map{"ip": params.ClientIP}.AsJSON(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
optionId = optionResp.NsQuestionOptionId
|
||||||
|
defer func() {
|
||||||
|
_, err = this.RPC().NSQuestionOptionRPC().DeleteNSQuestionOption(this.AdminContext(), &pb.DeleteNSQuestionOptionRequest{NsQuestionOptionId: optionId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
c := new(dns.Client)
|
||||||
|
m := new(dns.Msg)
|
||||||
|
var domain = params.Domain + "."
|
||||||
|
if optionId > 0 {
|
||||||
|
domain = "$" + types.String(optionId) + "-" + domain
|
||||||
|
}
|
||||||
|
m.SetQuestion(domain, recordType)
|
||||||
|
r, _, err := c.Exchange(m, params.Ip+":53")
|
||||||
|
if err != nil {
|
||||||
|
errMsg = "解析过程中出错:" + err.Error()
|
||||||
|
|
||||||
|
// 是否为网络错误
|
||||||
|
if regexp.MustCompile(`timeout|connect`).MatchString(err.Error()) {
|
||||||
|
isNetError = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
result = r.String()
|
||||||
|
result = regexp.MustCompile(`\$\d+-`).ReplaceAllString(result, "")
|
||||||
|
isOk = true
|
||||||
|
}
|
||||||
20
internal/web/actions/default/ns/test/init.go
Normal file
20
internal/web/actions/default/ns/test/init.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
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.AdminModuleCodeNS)).
|
||||||
|
Data("teaMenu", "ns").
|
||||||
|
Data("teaSubMenu", "test").
|
||||||
|
Prefix("/ns/test").
|
||||||
|
GetPost("", new(IndexAction)).
|
||||||
|
Post("/nodeOptions", new(NodeOptionsAction)).
|
||||||
|
EndAll()
|
||||||
|
})
|
||||||
|
}
|
||||||
59
internal/web/actions/default/ns/test/nodeOptions.go
Normal file
59
internal/web/actions/default/ns/test/nodeOptions.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
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 NodeOptionsAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *NodeOptionsAction) RunPost(params struct {
|
||||||
|
ClusterId int64
|
||||||
|
}) {
|
||||||
|
nodesResp, err := this.RPC().NSNodeRPC().FindAllEnabledNSNodesWithNSClusterId(this.AdminContext(), &pb.FindAllEnabledNSNodesWithNSClusterIdRequest{NsClusterId: params.ClusterId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var nodeMaps = []maps.Map{}
|
||||||
|
for _, node := range nodesResp.NsNodes {
|
||||||
|
if !node.IsOn {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
addressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{
|
||||||
|
NodeId: node.Id,
|
||||||
|
Role: nodeconfigs.NodeRoleDNS,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var addresses = addressesResp.Addresses
|
||||||
|
if len(addresses) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var addrs = []string{}
|
||||||
|
for _, addr := range addresses {
|
||||||
|
if addr.CanAccess {
|
||||||
|
addrs = append(addrs, addr.Ip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeMaps = append(nodeMaps, maps.Map{
|
||||||
|
"id": node.Id,
|
||||||
|
"name": node.Name,
|
||||||
|
"addrs": addrs,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["nodes"] = nodeMaps
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
179
internal/web/actions/default/servers/accesslogs/createPopup.go
Normal file
179
internal/web/actions/default/servers/accesslogs/createPopup.go
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package ipbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"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/actions"
|
||||||
|
"github.com/iwind/TeaGo/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreatePopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreatePopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreatePopupAction) RunGet(params struct{}) {
|
||||||
|
this.Data["types"] = serverconfigs.FindAllAccessLogStorageTypes()
|
||||||
|
this.Data["syslogPriorities"] = serverconfigs.AccessLogSyslogStoragePriorities
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreatePopupAction) RunPost(params struct {
|
||||||
|
Name string
|
||||||
|
Type string
|
||||||
|
|
||||||
|
// file
|
||||||
|
FilePath string
|
||||||
|
FileAutoCreate bool
|
||||||
|
|
||||||
|
// es
|
||||||
|
EsEndpoint string
|
||||||
|
EsIndex string
|
||||||
|
EsMappingType string
|
||||||
|
EsUsername string
|
||||||
|
EsPassword string
|
||||||
|
|
||||||
|
// mysql
|
||||||
|
MysqlHost string
|
||||||
|
MysqlPort int
|
||||||
|
MysqlUsername string
|
||||||
|
MysqlPassword string
|
||||||
|
MysqlDatabase string
|
||||||
|
MysqlTable string
|
||||||
|
MysqlLogField string
|
||||||
|
|
||||||
|
// tcp
|
||||||
|
TcpNetwork string
|
||||||
|
TcpAddr string
|
||||||
|
|
||||||
|
// syslog
|
||||||
|
SyslogProtocol string
|
||||||
|
SyslogServerAddr string
|
||||||
|
SyslogServerPort int
|
||||||
|
SyslogSocket string
|
||||||
|
SyslogTag string
|
||||||
|
SyslogPriority int
|
||||||
|
|
||||||
|
// command
|
||||||
|
CommandCommand string
|
||||||
|
CommandArgs string
|
||||||
|
CommandDir string
|
||||||
|
|
||||||
|
IsPublic bool
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
CSRF *actionutils.CSRF
|
||||||
|
}) {
|
||||||
|
var policyId int64 = 0
|
||||||
|
defer func() {
|
||||||
|
this.CreateLogInfo("创建访问日志策略 %d", policyId)
|
||||||
|
}()
|
||||||
|
|
||||||
|
params.Must.
|
||||||
|
Field("name", params.Name).
|
||||||
|
Require("请输入日志策略的名称").
|
||||||
|
Field("type", params.Type).
|
||||||
|
Require("请选择存储类型")
|
||||||
|
|
||||||
|
var options interface{} = nil
|
||||||
|
switch params.Type {
|
||||||
|
case serverconfigs.AccessLogStorageTypeFile:
|
||||||
|
params.Must.
|
||||||
|
Field("filePath", params.FilePath).
|
||||||
|
Require("请输入日志文件路径")
|
||||||
|
|
||||||
|
storage := new(serverconfigs.AccessLogFileStorageConfig)
|
||||||
|
storage.Path = params.FilePath
|
||||||
|
storage.AutoCreate = params.FileAutoCreate
|
||||||
|
options = storage
|
||||||
|
case serverconfigs.AccessLogStorageTypeES:
|
||||||
|
params.Must.
|
||||||
|
Field("esEndpoint", params.EsEndpoint).
|
||||||
|
Require("请输入Endpoint").
|
||||||
|
Field("esIndex", params.EsIndex).
|
||||||
|
Require("请输入Index名称").
|
||||||
|
Field("esMappingType", params.EsMappingType).
|
||||||
|
Require("请输入Mapping名称")
|
||||||
|
|
||||||
|
storage := new(serverconfigs.AccessLogESStorageConfig)
|
||||||
|
storage.Endpoint = params.EsEndpoint
|
||||||
|
storage.Index = params.EsIndex
|
||||||
|
storage.MappingType = params.EsMappingType
|
||||||
|
storage.Username = params.EsUsername
|
||||||
|
storage.Password = params.EsPassword
|
||||||
|
options = storage
|
||||||
|
case serverconfigs.AccessLogStorageTypeTCP:
|
||||||
|
params.Must.
|
||||||
|
Field("tcpNetwork", params.TcpNetwork).
|
||||||
|
Require("请选择网络协议").
|
||||||
|
Field("tcpAddr", params.TcpAddr).
|
||||||
|
Require("请输入网络地址")
|
||||||
|
|
||||||
|
storage := new(serverconfigs.AccessLogTCPStorageConfig)
|
||||||
|
storage.Network = params.TcpNetwork
|
||||||
|
storage.Addr = params.TcpAddr
|
||||||
|
options = storage
|
||||||
|
case serverconfigs.AccessLogStorageTypeSyslog:
|
||||||
|
switch params.SyslogProtocol {
|
||||||
|
case serverconfigs.AccessLogSyslogStorageProtocolTCP, serverconfigs.AccessLogSyslogStorageProtocolUDP:
|
||||||
|
params.Must.
|
||||||
|
Field("syslogServerAddr", params.SyslogServerAddr).
|
||||||
|
Require("请输入网络地址")
|
||||||
|
case serverconfigs.AccessLogSyslogStorageProtocolSocket:
|
||||||
|
params.Must.
|
||||||
|
Field("syslogSocket", params.SyslogSocket).
|
||||||
|
Require("请输入Socket路径")
|
||||||
|
}
|
||||||
|
|
||||||
|
storage := new(serverconfigs.AccessLogSyslogStorageConfig)
|
||||||
|
storage.Protocol = params.SyslogProtocol
|
||||||
|
storage.ServerAddr = params.SyslogServerAddr
|
||||||
|
storage.ServerPort = params.SyslogServerPort
|
||||||
|
storage.Socket = params.SyslogSocket
|
||||||
|
storage.Tag = params.SyslogTag
|
||||||
|
storage.Priority = params.SyslogPriority
|
||||||
|
options = storage
|
||||||
|
case serverconfigs.AccessLogStorageTypeCommand:
|
||||||
|
params.Must.
|
||||||
|
Field("commandCommand", params.CommandCommand).
|
||||||
|
Require("请输入可执行命令")
|
||||||
|
|
||||||
|
storage := new(serverconfigs.AccessLogCommandStorageConfig)
|
||||||
|
storage.Command = params.CommandCommand
|
||||||
|
storage.Args = cmd.ParseArgs(params.CommandArgs)
|
||||||
|
storage.Dir = params.CommandDir
|
||||||
|
options = storage
|
||||||
|
}
|
||||||
|
|
||||||
|
if options == nil {
|
||||||
|
this.Fail("找不到选择的存储类型")
|
||||||
|
}
|
||||||
|
|
||||||
|
optionsJSON, err := json.Marshal(options)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
createResp, err := this.RPC().HTTPAccessLogPolicyRPC().CreateHTTPAccessLogPolicy(this.AdminContext(), &pb.CreateHTTPAccessLogPolicyRequest{
|
||||||
|
Name: params.Name,
|
||||||
|
Type: params.Type,
|
||||||
|
OptionsJSON: optionsJSON,
|
||||||
|
CondsJSON: nil, // TODO
|
||||||
|
IsPublic: params.IsPublic,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
policyId = createResp.HttpAccessLogPolicyId
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
26
internal/web/actions/default/servers/accesslogs/delete.go
Normal file
26
internal/web/actions/default/servers/accesslogs/delete.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package ipbox
|
||||||
|
|
||||||
|
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 {
|
||||||
|
PolicyId int64
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("删除访问日志策略 %d", params.PolicyId)
|
||||||
|
|
||||||
|
_, err := this.RPC().HTTPAccessLogPolicyRPC().DeleteHTTPAccessLogPolicy(this.AdminContext(), &pb.DeleteHTTPAccessLogPolicyRequest{HttpAccessLogPolicyId: params.PolicyId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
57
internal/web/actions/default/servers/accesslogs/index.go
Normal file
57
internal/web/actions/default/servers/accesslogs/index.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package ipbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"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/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IndexAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) Init() {
|
||||||
|
this.Nav("", "", "index")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunGet(params struct{}) {
|
||||||
|
countResp, err := this.RPC().HTTPAccessLogPolicyRPC().CountAllEnabledHTTPAccessLogPolicies(this.AdminContext(), &pb.CountAllEnabledHTTPAccessLogPoliciesRequest{})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
page := this.NewPage(countResp.Count)
|
||||||
|
this.Data["page"] = page.AsHTML()
|
||||||
|
|
||||||
|
policiesResp, err := this.RPC().HTTPAccessLogPolicyRPC().ListEnabledHTTPAccessLogPolicies(this.AdminContext(), &pb.ListEnabledHTTPAccessLogPoliciesRequest{
|
||||||
|
Offset: page.Offset,
|
||||||
|
Size: page.Size,
|
||||||
|
})
|
||||||
|
var policyMaps = []maps.Map{}
|
||||||
|
for _, policy := range policiesResp.HttpAccessLogPolicies {
|
||||||
|
var optionsMap = maps.Map{}
|
||||||
|
if len(policy.OptionsJSON) > 0 {
|
||||||
|
err = json.Unmarshal(policy.OptionsJSON, &optionsMap)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
policyMaps = append(policyMaps, maps.Map{
|
||||||
|
"id": policy.Id,
|
||||||
|
"name": policy.Name,
|
||||||
|
"type": policy.Type,
|
||||||
|
"typeName": serverconfigs.FindAccessLogStorageTypeName(policy.Type),
|
||||||
|
"isOn": policy.IsOn,
|
||||||
|
"isPublic": policy.IsPublic,
|
||||||
|
"options": optionsMap,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["policies"] = policyMaps
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
26
internal/web/actions/default/servers/accesslogs/init.go
Normal file
26
internal/web/actions/default/servers/accesslogs/init.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package ipbox
|
||||||
|
|
||||||
|
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)).
|
||||||
|
Prefix("/servers/accesslogs").
|
||||||
|
Data("teaMenu", "servers").
|
||||||
|
Data("teaSubMenu", "accesslog").
|
||||||
|
Get("", new(IndexAction)).
|
||||||
|
GetPost("/createPopup", new(CreatePopupAction)).
|
||||||
|
Get("/policy", new(PolicyAction)).
|
||||||
|
GetPost("/test", new(TestAction)).
|
||||||
|
GetPost("/update", new(UpdateAction)).
|
||||||
|
Post("/delete", new(DeleteAction)).
|
||||||
|
EndAll()
|
||||||
|
})
|
||||||
|
}
|
||||||
36
internal/web/actions/default/servers/accesslogs/policy.go
Normal file
36
internal/web/actions/default/servers/accesslogs/policy.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package ipbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/accesslogs/policyutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PolicyAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *PolicyAction) Init() {
|
||||||
|
this.Nav("", "", "policy")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *PolicyAction) RunGet(params struct {
|
||||||
|
PolicyId int64
|
||||||
|
}) {
|
||||||
|
err := policyutils.InitPolicy(this.Parent(), params.PolicyId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var policyMap = this.Data.GetMap("policy")
|
||||||
|
if policyMap.GetString("type") == serverconfigs.AccessLogStorageTypeSyslog {
|
||||||
|
this.Data["syslogPriorityName"] = serverconfigs.FindAccessLogSyslogStoragePriorityName(policyMap.GetMap("options").GetInt("priority"))
|
||||||
|
} else {
|
||||||
|
this.Data["syslogPriorityName"] = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package policyutils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
|
"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/maps"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// InitPolicy 初始化访问日志策略
|
||||||
|
func InitPolicy(parent *actionutils.ParentAction, policyId int64) error {
|
||||||
|
rpcClient, err := rpc.SharedRPC()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
policyResp, err := rpcClient.HTTPAccessLogPolicyRPC().FindEnabledHTTPAccessLogPolicy(parent.AdminContext(), &pb.FindEnabledHTTPAccessLogPolicyRequest{HttpAccessLogPolicyId: policyId})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var policy = policyResp.HttpAccessLogPolicy
|
||||||
|
if policy == nil {
|
||||||
|
return errors.New("can not find policy '" + types.String(policyId) + "'")
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = maps.Map{}
|
||||||
|
if len(policy.OptionsJSON) > 0 {
|
||||||
|
err = json.Unmarshal(policy.OptionsJSON, &options)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.Data["policy"] = maps.Map{
|
||||||
|
"id": policy.Id,
|
||||||
|
"name": policy.Name,
|
||||||
|
"type": policy.Type,
|
||||||
|
"typeName": serverconfigs.FindAccessLogStorageTypeName(policy.Type),
|
||||||
|
"isOn": policy.IsOn,
|
||||||
|
"isPublic": policy.IsPublic,
|
||||||
|
"options": options,
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
57
internal/web/actions/default/servers/accesslogs/test.go
Normal file
57
internal/web/actions/default/servers/accesslogs/test.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package ipbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/accesslogs/policyutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TestAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *TestAction) Init() {
|
||||||
|
this.Nav("", "", "test")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *TestAction) RunGet(params struct {
|
||||||
|
PolicyId int64
|
||||||
|
}) {
|
||||||
|
err := policyutils.InitPolicy(this.Parent(), params.PolicyId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *TestAction) RunPost(params struct {
|
||||||
|
PolicyId int64
|
||||||
|
BodyJSON []byte
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("测试向访问日志策略 %d 写入数据", params.PolicyId)
|
||||||
|
|
||||||
|
var accessLog = &pb.HTTPAccessLog{}
|
||||||
|
err := json.Unmarshal(params.BodyJSON, accessLog)
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("发送内容不是有效的JSON:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = this.RPC().HTTPAccessLogPolicyRPC().WriteHTTPAccessLogPolicy(this.AdminContext(), &pb.WriteHTTPAccessLogPolicyRequest{
|
||||||
|
HttpAccessLogPolicyId: params.PolicyId,
|
||||||
|
HttpAccessLog: accessLog,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("发送失败:" + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
195
internal/web/actions/default/servers/accesslogs/update.go
Normal file
195
internal/web/actions/default/servers/accesslogs/update.go
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package ipbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/accesslogs/policyutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpdateAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdateAction) Init() {
|
||||||
|
this.Nav("", "", "update")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdateAction) RunGet(params struct {
|
||||||
|
PolicyId int64
|
||||||
|
}) {
|
||||||
|
err := policyutils.InitPolicy(this.Parent(), params.PolicyId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["types"] = serverconfigs.FindAllAccessLogStorageTypes()
|
||||||
|
this.Data["syslogPriorities"] = serverconfigs.AccessLogSyslogStoragePriorities
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdateAction) RunPost(params struct {
|
||||||
|
PolicyId int64
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// file
|
||||||
|
FilePath string
|
||||||
|
FileAutoCreate bool
|
||||||
|
|
||||||
|
// es
|
||||||
|
EsEndpoint string
|
||||||
|
EsIndex string
|
||||||
|
EsMappingType string
|
||||||
|
EsUsername string
|
||||||
|
EsPassword string
|
||||||
|
|
||||||
|
// mysql
|
||||||
|
MysqlHost string
|
||||||
|
MysqlPort int
|
||||||
|
MysqlUsername string
|
||||||
|
MysqlPassword string
|
||||||
|
MysqlDatabase string
|
||||||
|
MysqlTable string
|
||||||
|
MysqlLogField string
|
||||||
|
|
||||||
|
// tcp
|
||||||
|
TcpNetwork string
|
||||||
|
TcpAddr string
|
||||||
|
|
||||||
|
// syslog
|
||||||
|
SyslogProtocol string
|
||||||
|
SyslogServerAddr string
|
||||||
|
SyslogServerPort int
|
||||||
|
SyslogSocket string
|
||||||
|
SyslogTag string
|
||||||
|
SyslogPriority int
|
||||||
|
|
||||||
|
// command
|
||||||
|
CommandCommand string
|
||||||
|
CommandArgs string
|
||||||
|
CommandDir string
|
||||||
|
|
||||||
|
IsOn bool
|
||||||
|
IsPublic bool
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
CSRF *actionutils.CSRF
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("修改访问日志策略 %d", params.PolicyId)
|
||||||
|
|
||||||
|
policyResp, err := this.RPC().HTTPAccessLogPolicyRPC().FindEnabledHTTPAccessLogPolicy(this.AdminContext(), &pb.FindEnabledHTTPAccessLogPolicyRequest{HttpAccessLogPolicyId: params.PolicyId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var policy = policyResp.HttpAccessLogPolicy
|
||||||
|
if policy == nil {
|
||||||
|
this.Fail("找不到要修改的策略")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
params.Must.
|
||||||
|
Field("name", params.Name).
|
||||||
|
Require("请输入日志策略的名称")
|
||||||
|
|
||||||
|
var options interface{} = nil
|
||||||
|
switch policy.Type {
|
||||||
|
case serverconfigs.AccessLogStorageTypeFile:
|
||||||
|
params.Must.
|
||||||
|
Field("filePath", params.FilePath).
|
||||||
|
Require("请输入日志文件路径")
|
||||||
|
|
||||||
|
storage := new(serverconfigs.AccessLogFileStorageConfig)
|
||||||
|
storage.Path = params.FilePath
|
||||||
|
storage.AutoCreate = params.FileAutoCreate
|
||||||
|
options = storage
|
||||||
|
case serverconfigs.AccessLogStorageTypeES:
|
||||||
|
params.Must.
|
||||||
|
Field("esEndpoint", params.EsEndpoint).
|
||||||
|
Require("请输入Endpoint").
|
||||||
|
Field("esIndex", params.EsIndex).
|
||||||
|
Require("请输入Index名称").
|
||||||
|
Field("esMappingType", params.EsMappingType).
|
||||||
|
Require("请输入Mapping名称")
|
||||||
|
|
||||||
|
storage := new(serverconfigs.AccessLogESStorageConfig)
|
||||||
|
storage.Endpoint = params.EsEndpoint
|
||||||
|
storage.Index = params.EsIndex
|
||||||
|
storage.MappingType = params.EsMappingType
|
||||||
|
storage.Username = params.EsUsername
|
||||||
|
storage.Password = params.EsPassword
|
||||||
|
options = storage
|
||||||
|
case serverconfigs.AccessLogStorageTypeTCP:
|
||||||
|
params.Must.
|
||||||
|
Field("tcpNetwork", params.TcpNetwork).
|
||||||
|
Require("请选择网络协议").
|
||||||
|
Field("tcpAddr", params.TcpAddr).
|
||||||
|
Require("请输入网络地址")
|
||||||
|
|
||||||
|
storage := new(serverconfigs.AccessLogTCPStorageConfig)
|
||||||
|
storage.Network = params.TcpNetwork
|
||||||
|
storage.Addr = params.TcpAddr
|
||||||
|
options = storage
|
||||||
|
case serverconfigs.AccessLogStorageTypeSyslog:
|
||||||
|
switch params.SyslogProtocol {
|
||||||
|
case serverconfigs.AccessLogSyslogStorageProtocolTCP, serverconfigs.AccessLogSyslogStorageProtocolUDP:
|
||||||
|
params.Must.
|
||||||
|
Field("syslogServerAddr", params.SyslogServerAddr).
|
||||||
|
Require("请输入网络地址")
|
||||||
|
case serverconfigs.AccessLogSyslogStorageProtocolSocket:
|
||||||
|
params.Must.
|
||||||
|
Field("syslogSocket", params.SyslogSocket).
|
||||||
|
Require("请输入Socket路径")
|
||||||
|
}
|
||||||
|
|
||||||
|
storage := new(serverconfigs.AccessLogSyslogStorageConfig)
|
||||||
|
storage.Protocol = params.SyslogProtocol
|
||||||
|
storage.ServerAddr = params.SyslogServerAddr
|
||||||
|
storage.ServerPort = params.SyslogServerPort
|
||||||
|
storage.Socket = params.SyslogSocket
|
||||||
|
storage.Tag = params.SyslogTag
|
||||||
|
storage.Priority = params.SyslogPriority
|
||||||
|
options = storage
|
||||||
|
case serverconfigs.AccessLogStorageTypeCommand:
|
||||||
|
params.Must.
|
||||||
|
Field("commandCommand", params.CommandCommand).
|
||||||
|
Require("请输入可执行命令")
|
||||||
|
|
||||||
|
storage := new(serverconfigs.AccessLogCommandStorageConfig)
|
||||||
|
storage.Command = params.CommandCommand
|
||||||
|
storage.Args = cmd.ParseArgs(params.CommandArgs)
|
||||||
|
storage.Dir = params.CommandDir
|
||||||
|
options = storage
|
||||||
|
}
|
||||||
|
|
||||||
|
if options == nil {
|
||||||
|
this.Fail("找不到选择的存储类型")
|
||||||
|
}
|
||||||
|
|
||||||
|
optionsJSON, err := json.Marshal(options)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = this.RPC().HTTPAccessLogPolicyRPC().UpdateHTTPAccessLogPolicy(this.AdminContext(), &pb.UpdateHTTPAccessLogPolicyRequest{
|
||||||
|
HttpAccessLogPolicyId: params.PolicyId,
|
||||||
|
Name: params.Name,
|
||||||
|
OptionsJSON: optionsJSON,
|
||||||
|
CondsJSON: nil, // TODO
|
||||||
|
IsOn: params.IsOn,
|
||||||
|
IsPublic: params.IsPublic,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -132,7 +132,7 @@ func (this *CreateAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
case serverconfigs.ServerTypeTCPProxy:
|
case serverconfigs.ServerTypeTCPProxy:
|
||||||
// 在DEMO模式下不能创建
|
// 在DEMO模式下不能创建
|
||||||
if teaconst.IsDemo {
|
if teaconst.IsDemoMode {
|
||||||
this.Fail("DEMO模式下不能创建TCP反向代理")
|
this.Fail("DEMO模式下不能创建TCP反向代理")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ func (this *CreateAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
case serverconfigs.ServerTypeUDPProxy:
|
case serverconfigs.ServerTypeUDPProxy:
|
||||||
// 在DEMO模式下不能创建
|
// 在DEMO模式下不能创建
|
||||||
if teaconst.IsDemo {
|
if teaconst.IsDemoMode {
|
||||||
this.Fail("DEMO模式下不能创建UDP反向代理")
|
this.Fail("DEMO模式下不能创建UDP反向代理")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -274,7 +274,9 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
server := serverResp.Server
|
|
||||||
|
// 服务
|
||||||
|
var server = serverResp.Server
|
||||||
if server == nil {
|
if server == nil {
|
||||||
// 设置为已修复
|
// 设置为已修复
|
||||||
_, err = this.RPC().NodeLogRPC().FixNodeLog(this.AdminContext(), &pb.FixNodeLogRequest{NodeLogId: errorLog.Id})
|
_, err = this.RPC().NodeLogRPC().FixNodeLog(this.AdminContext(), &pb.FixNodeLogRequest{NodeLogId: errorLog.Id})
|
||||||
@@ -286,6 +288,24 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 节点
|
||||||
|
nodeResp, err := this.RPC().NodeRPC().FindEnabledNode(this.AdminContext(), &pb.FindEnabledNodeRequest{NodeId: errorLog.NodeId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var node = nodeResp.Node
|
||||||
|
if node == nil || node.NodeCluster == nil {
|
||||||
|
// 设置为已修复
|
||||||
|
_, err = this.RPC().NodeLogRPC().FixNodeLog(this.AdminContext(), &pb.FixNodeLogRequest{NodeLogId: errorLog.Id})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
errorLogMaps = append(errorLogMaps, maps.Map{
|
errorLogMaps = append(errorLogMaps, maps.Map{
|
||||||
"id": errorLog.Id,
|
"id": errorLog.Id,
|
||||||
"description": errorLog.Description,
|
"description": errorLog.Description,
|
||||||
@@ -293,6 +313,9 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
"serverId": errorLog.ServerId,
|
"serverId": errorLog.ServerId,
|
||||||
"level": errorLog.Level,
|
"level": errorLog.Level,
|
||||||
"serverName": server.Name,
|
"serverName": server.Name,
|
||||||
|
"nodeId": node.Id,
|
||||||
|
"nodeName": node.Name,
|
||||||
|
"clusterId": node.NodeCluster.Id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.Data["errorLogs"] = errorLogMaps
|
this.Data["errorLogs"] = errorLogMaps
|
||||||
|
|||||||
40
internal/web/actions/default/servers/ipbox/addIP.go
Normal file
40
internal/web/actions/default/servers/ipbox/addIP.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package ipbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AddIPAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *AddIPAction) RunPost(params struct {
|
||||||
|
ListId int64
|
||||||
|
Ip string
|
||||||
|
}) {
|
||||||
|
var ipType = "ipv4"
|
||||||
|
if strings.Contains(params.Ip, ":") {
|
||||||
|
ipType = "ipv6"
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := this.RPC().IPItemRPC().CreateIPItem(this.AdminContext(), &pb.CreateIPItemRequest{
|
||||||
|
IpListId: params.ListId,
|
||||||
|
IpFrom: params.Ip,
|
||||||
|
IpTo: "",
|
||||||
|
ExpiredAt: time.Now().Unix() + 86400, // TODO 可以自定义时间
|
||||||
|
Reason: "从IPBox中加入名单",
|
||||||
|
Type: ipType,
|
||||||
|
EventLevel: "critical",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ package ipbox
|
|||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -22,10 +23,62 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
}) {
|
}) {
|
||||||
this.Data["ip"] = params.Ip
|
this.Data["ip"] = params.Ip
|
||||||
|
|
||||||
|
// IP信息
|
||||||
|
regionResp, err := this.RPC().IPLibraryRPC().LookupIPRegion(this.AdminContext(), &pb.LookupIPRegionRequest{Ip: params.Ip})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if regionResp.IpRegion != nil {
|
||||||
|
this.Data["regions"] = regionResp.IpRegion.Summary
|
||||||
|
} else {
|
||||||
|
this.Data["regions"] = ""
|
||||||
|
}
|
||||||
|
this.Data["isp"] = regionResp.IpRegion.Isp
|
||||||
|
|
||||||
|
// IP列表
|
||||||
|
ipListResp, err := this.RPC().IPListRPC().FindEnabledIPListContainsIP(this.AdminContext(), &pb.FindEnabledIPListContainsIPRequest{Ip: params.Ip})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var ipListMaps = []maps.Map{}
|
||||||
|
for _, ipList := range ipListResp.IpLists {
|
||||||
|
ipListMaps = append(ipListMaps, maps.Map{
|
||||||
|
"id": ipList.Id,
|
||||||
|
"name": ipList.Name,
|
||||||
|
"type": ipList.Type,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["ipLists"] = ipListMaps
|
||||||
|
|
||||||
|
// 所有公用的IP列表
|
||||||
|
publicBlackIPListResp, err := this.RPC().IPListRPC().ListEnabledIPLists(this.AdminContext(), &pb.ListEnabledIPListsRequest{
|
||||||
|
Type: "black",
|
||||||
|
IsPublic: true,
|
||||||
|
Keyword: "",
|
||||||
|
Offset: 0,
|
||||||
|
Size: 10, // TODO 将来考虑到支持更多的黑名单
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var publicBlackIPListMaps = []maps.Map{}
|
||||||
|
for _, ipList := range publicBlackIPListResp.IpLists {
|
||||||
|
publicBlackIPListMaps = append(publicBlackIPListMaps, maps.Map{
|
||||||
|
"id": ipList.Id,
|
||||||
|
"name": ipList.Name,
|
||||||
|
"type": ipList.Type,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["publicBlackIPLists"] = publicBlackIPListMaps
|
||||||
|
|
||||||
|
// 访问日志
|
||||||
accessLogsResp, err := this.RPC().HTTPAccessLogRPC().ListHTTPAccessLogs(this.AdminContext(), &pb.ListHTTPAccessLogsRequest{
|
accessLogsResp, err := this.RPC().HTTPAccessLogRPC().ListHTTPAccessLogs(this.AdminContext(), &pb.ListHTTPAccessLogsRequest{
|
||||||
Day: timeutil.Format("Ymd"),
|
Day: timeutil.Format("Ymd"),
|
||||||
Keyword: "ip:" + params.Ip,
|
Ip: params.Ip,
|
||||||
Size: 10,
|
Size: 20,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
@@ -35,9 +88,9 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
if len(accessLogs) == 0 {
|
if len(accessLogs) == 0 {
|
||||||
// 查询昨天
|
// 查询昨天
|
||||||
accessLogsResp, err = this.RPC().HTTPAccessLogRPC().ListHTTPAccessLogs(this.AdminContext(), &pb.ListHTTPAccessLogsRequest{
|
accessLogsResp, err = this.RPC().HTTPAccessLogRPC().ListHTTPAccessLogs(this.AdminContext(), &pb.ListHTTPAccessLogsRequest{
|
||||||
Day: timeutil.Format("Ymd", time.Now().AddDate(0, 0, -1)),
|
Day: timeutil.Format("Ymd", time.Now().AddDate(0, 0, -1)),
|
||||||
Keyword: "ip:" + params.Ip,
|
Ip: params.Ip,
|
||||||
Size: 10,
|
Size: 20,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ func init() {
|
|||||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
|
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
|
||||||
Prefix("/servers/ipbox").
|
Prefix("/servers/ipbox").
|
||||||
Get("", new(IndexAction)).
|
Get("", new(IndexAction)).
|
||||||
|
Post("/addIP", new(AddIPAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -3,10 +3,15 @@
|
|||||||
package iplists
|
package iplists
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/csv"
|
||||||
|
"encoding/json"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
"github.com/tealeg/xlsx/v3"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -20,10 +25,55 @@ func (this *ExportDataAction) Init() {
|
|||||||
|
|
||||||
func (this *ExportDataAction) RunGet(params struct {
|
func (this *ExportDataAction) RunGet(params struct {
|
||||||
ListId int64
|
ListId int64
|
||||||
|
Format string
|
||||||
}) {
|
}) {
|
||||||
defer this.CreateLogInfo("导出IP名单 %d", params.ListId)
|
defer this.CreateLogInfo("导出IP名单 %d", params.ListId)
|
||||||
|
|
||||||
resp := &pb.ListIPItemsWithListIdResponse{}
|
var err error
|
||||||
|
var ext = ""
|
||||||
|
var jsonMaps = []maps.Map{}
|
||||||
|
var xlsxFile *xlsx.File
|
||||||
|
var xlsxSheet *xlsx.Sheet
|
||||||
|
var csvWriter *csv.Writer
|
||||||
|
var csvBuffer *bytes.Buffer
|
||||||
|
|
||||||
|
var data []byte
|
||||||
|
|
||||||
|
switch params.Format {
|
||||||
|
case "xlsx":
|
||||||
|
ext = ".xlsx"
|
||||||
|
xlsxFile = xlsx.NewFile()
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
xlsxSheet, err = xlsxFile.AddSheet("IP名单")
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
row := xlsxSheet.AddRow()
|
||||||
|
row.SetHeight(26)
|
||||||
|
row.AddCell().SetValue("开始IP")
|
||||||
|
row.AddCell().SetValue("结束IP")
|
||||||
|
row.AddCell().SetValue("过期时间戳")
|
||||||
|
row.AddCell().SetValue("类型")
|
||||||
|
row.AddCell().SetValue("级别")
|
||||||
|
row.AddCell().SetValue("备注")
|
||||||
|
case "csv":
|
||||||
|
ext = ".csv"
|
||||||
|
csvBuffer = &bytes.Buffer{}
|
||||||
|
csvWriter = csv.NewWriter(csvBuffer)
|
||||||
|
case "txt":
|
||||||
|
ext = ".txt"
|
||||||
|
case "json":
|
||||||
|
ext = ".json"
|
||||||
|
default:
|
||||||
|
this.WriteString("请选择正确的导出格式")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var offset int64 = 0
|
var offset int64 = 0
|
||||||
var size int64 = 1000
|
var size int64 = 1000
|
||||||
for {
|
for {
|
||||||
@@ -40,18 +90,60 @@ func (this *ExportDataAction) RunGet(params struct {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
for _, item := range itemsResp.IpItems {
|
for _, item := range itemsResp.IpItems {
|
||||||
resp.IpItems = append(resp.IpItems, item)
|
switch params.Format {
|
||||||
|
case "xlsx":
|
||||||
|
row := xlsxSheet.AddRow()
|
||||||
|
row.SetHeight(26)
|
||||||
|
row.AddCell().SetValue(item.IpFrom)
|
||||||
|
row.AddCell().SetValue(item.IpTo)
|
||||||
|
row.AddCell().SetValue(types.String(item.ExpiredAt))
|
||||||
|
row.AddCell().SetValue(item.Type)
|
||||||
|
row.AddCell().SetValue(item.EventLevel)
|
||||||
|
row.AddCell().SetValue(item.Reason)
|
||||||
|
case "csv":
|
||||||
|
err = csvWriter.Write([]string{item.IpFrom, item.IpTo, types.String(item.ExpiredAt), item.Type, item.EventLevel, item.Reason})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "txt":
|
||||||
|
data = append(data, item.IpFrom+","+item.IpTo+","+types.String(item.ExpiredAt)+","+item.Type+","+item.EventLevel+","+item.Reason...)
|
||||||
|
data = append(data, '\n')
|
||||||
|
case "json":
|
||||||
|
jsonMaps = append(jsonMaps, maps.Map{
|
||||||
|
"ipFrom": item.IpFrom,
|
||||||
|
"ipTo": item.IpTo,
|
||||||
|
"expiredAt": item.ExpiredAt,
|
||||||
|
"type": item.Type,
|
||||||
|
"eventLevel": item.EventLevel,
|
||||||
|
"reason": item.Reason,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
offset += size
|
offset += size
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := proto.Marshal(resp)
|
switch params.Format {
|
||||||
if err != nil {
|
case "xlsx":
|
||||||
this.ErrorPage(err)
|
var buf = &bytes.Buffer{}
|
||||||
return
|
err = xlsxFile.Write(buf)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data = buf.Bytes()
|
||||||
|
case "csv":
|
||||||
|
csvWriter.Flush()
|
||||||
|
data = csvBuffer.Bytes()
|
||||||
|
case "json":
|
||||||
|
data, err = json.Marshal(jsonMaps)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.AddHeader("Content-Disposition", "attachment; filename=\"ip-list-"+numberutils.FormatInt64(params.ListId)+".data\";")
|
this.AddHeader("Content-Disposition", "attachment; filename=\"ip-list-"+numberutils.FormatInt64(params.ListId)+ext+"\";")
|
||||||
this.AddHeader("Content-Length", strconv.Itoa(len(data)))
|
this.AddHeader("Content-Length", strconv.Itoa(len(data)))
|
||||||
this.Write(data)
|
this.Write(data)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,19 @@
|
|||||||
package iplists
|
package iplists
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/csv"
|
||||||
|
"encoding/json"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/lists"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
"github.com/tealeg/xlsx/v3"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ImportAction struct {
|
type ImportAction struct {
|
||||||
@@ -51,20 +60,92 @@ func (this *ImportAction) RunPost(params struct {
|
|||||||
this.Fail("请选择要导入的IP文件")
|
this.Fail("请选择要导入的IP文件")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查文件扩展名
|
||||||
|
if !regexp.MustCompile(`(?i)\.(xlsx|csv|json|txt)$`).MatchString(params.File.Filename) {
|
||||||
|
this.Fail("不支持当前格式的文件导入")
|
||||||
|
}
|
||||||
|
|
||||||
|
var ext = strings.ToLower(params.File.Ext)
|
||||||
|
|
||||||
data, err := params.File.Read()
|
data, err := params.File.Read()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resp := &pb.ListIPItemsWithListIdResponse{}
|
|
||||||
err = proto.Unmarshal(data, resp)
|
var countIgnore = 0
|
||||||
if err != nil {
|
var items = []*pb.IPItem{}
|
||||||
this.Fail("导入失败,文件格式错误:" + err.Error())
|
switch ext {
|
||||||
|
case ".xlsx":
|
||||||
|
file, err := xlsx.OpenBinary(data)
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("Excel读取错误:" + err.Error())
|
||||||
|
}
|
||||||
|
if len(file.Sheets) > 0 {
|
||||||
|
var sheet = file.Sheets[0]
|
||||||
|
err = sheet.ForEachRow(func(r *xlsx.Row) error {
|
||||||
|
var values = []string{}
|
||||||
|
err = r.ForEachCell(func(c *xlsx.Cell) error {
|
||||||
|
values = append(values, c.Value)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(values) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if values[0] == "开始IP" || values[0] == "IP" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
item := this.createItemFromValues(values, &countIgnore)
|
||||||
|
if item != nil {
|
||||||
|
items = append(items, item)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("Excel读取错误:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case ".csv":
|
||||||
|
reader := csv.NewReader(bytes.NewBuffer(data))
|
||||||
|
for {
|
||||||
|
values, err := reader.Read()
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
this.Fail("CSV读取错误:" + err.Error())
|
||||||
|
}
|
||||||
|
item := this.createItemFromValues(values, &countIgnore)
|
||||||
|
if item != nil {
|
||||||
|
items = append(items, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case ".json":
|
||||||
|
err = json.Unmarshal(data, &items)
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("导入失败:" + err.Error())
|
||||||
|
}
|
||||||
|
case ".txt":
|
||||||
|
lines := bytes.Split(data, []byte{'\n'})
|
||||||
|
for _, line := range lines {
|
||||||
|
if len(line) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
item := this.createItemFromValues(strings.SplitN(string(line), ",", 6), &countIgnore)
|
||||||
|
if item != nil {
|
||||||
|
items = append(items, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var count = 0
|
var count = 0
|
||||||
var countIgnore = 0
|
|
||||||
for _, item := range resp.IpItems {
|
lists.Reverse(items)
|
||||||
|
|
||||||
|
for _, item := range items {
|
||||||
_, err = this.RPC().IPItemRPC().CreateIPItem(this.AdminContext(), &pb.CreateIPItemRequest{
|
_, err = this.RPC().IPItemRPC().CreateIPItem(this.AdminContext(), &pb.CreateIPItemRequest{
|
||||||
IpListId: params.ListId,
|
IpListId: params.ListId,
|
||||||
IpFrom: item.IpFrom,
|
IpFrom: item.IpFrom,
|
||||||
@@ -85,3 +166,48 @@ func (this *ImportAction) RunPost(params struct {
|
|||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *ImportAction) createItemFromValues(values []string, countIgnore *int) *pb.IPItem {
|
||||||
|
// ipFrom, ipTo, expiredAt, type, eventType, reason
|
||||||
|
|
||||||
|
var item = &pb.IPItem{}
|
||||||
|
switch len(values) {
|
||||||
|
case 1:
|
||||||
|
item.IpFrom = values[0]
|
||||||
|
case 2:
|
||||||
|
item.IpFrom = values[0]
|
||||||
|
item.IpTo = values[1]
|
||||||
|
case 3:
|
||||||
|
item.IpFrom = values[0]
|
||||||
|
item.IpTo = values[1]
|
||||||
|
item.ExpiredAt = types.Int64(values[2])
|
||||||
|
case 4:
|
||||||
|
item.IpFrom = values[0]
|
||||||
|
item.IpTo = values[1]
|
||||||
|
item.ExpiredAt = types.Int64(values[2])
|
||||||
|
item.Type = values[3]
|
||||||
|
case 5:
|
||||||
|
item.IpFrom = values[0]
|
||||||
|
item.IpTo = values[1]
|
||||||
|
item.ExpiredAt = types.Int64(values[2])
|
||||||
|
item.Type = values[3]
|
||||||
|
item.EventLevel = values[4]
|
||||||
|
case 6:
|
||||||
|
item.IpFrom = values[0]
|
||||||
|
item.IpTo = values[1]
|
||||||
|
item.ExpiredAt = types.Int64(values[2])
|
||||||
|
item.Type = values[3]
|
||||||
|
item.EventLevel = values[4]
|
||||||
|
item.Reason = values[5]
|
||||||
|
}
|
||||||
|
|
||||||
|
if net.ParseIP(item.IpFrom) == nil {
|
||||||
|
*countIgnore++
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(item.IpTo) > 0 && net.ParseIP(item.IpTo) == nil {
|
||||||
|
*countIgnore++
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|||||||
127
internal/web/actions/default/servers/logs/index.go
Normal file
127
internal/web/actions/default/servers/logs/index.go
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package logs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/lists"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IndexAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunGet(params struct {
|
||||||
|
Day string
|
||||||
|
Keyword string
|
||||||
|
Ip string
|
||||||
|
Domain string
|
||||||
|
HasError int
|
||||||
|
|
||||||
|
RequestId string
|
||||||
|
ServerId int64
|
||||||
|
}) {
|
||||||
|
if len(params.Day) == 0 {
|
||||||
|
params.Day = timeutil.Format("Y-m-d")
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["serverId"] = 0
|
||||||
|
this.Data["path"] = this.Request.URL.Path
|
||||||
|
this.Data["day"] = params.Day
|
||||||
|
this.Data["keyword"] = params.Keyword
|
||||||
|
this.Data["ip"] = params.Ip
|
||||||
|
this.Data["domain"] = params.Domain
|
||||||
|
this.Data["accessLogs"] = []interface{}{}
|
||||||
|
this.Data["hasError"] = params.HasError
|
||||||
|
|
||||||
|
day := params.Day
|
||||||
|
ipList := []string{}
|
||||||
|
|
||||||
|
if len(day) > 0 && regexp.MustCompile(`\d{4}-\d{2}-\d{2}`).MatchString(day) {
|
||||||
|
day = strings.ReplaceAll(day, "-", "")
|
||||||
|
size := int64(10)
|
||||||
|
|
||||||
|
this.Data["hasError"] = params.HasError
|
||||||
|
|
||||||
|
resp, err := this.RPC().HTTPAccessLogRPC().ListHTTPAccessLogs(this.AdminContext(), &pb.ListHTTPAccessLogsRequest{
|
||||||
|
RequestId: params.RequestId,
|
||||||
|
ServerId: params.ServerId,
|
||||||
|
HasError: params.HasError > 0,
|
||||||
|
Day: day,
|
||||||
|
Keyword: params.Keyword,
|
||||||
|
Ip: params.Ip,
|
||||||
|
Domain: params.Domain,
|
||||||
|
Size: size,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(resp.HttpAccessLogs) == 0 {
|
||||||
|
this.Data["accessLogs"] = []interface{}{}
|
||||||
|
} else {
|
||||||
|
this.Data["accessLogs"] = resp.HttpAccessLogs
|
||||||
|
for _, accessLog := range resp.HttpAccessLogs {
|
||||||
|
if len(accessLog.RemoteAddr) > 0 {
|
||||||
|
if !lists.ContainsString(ipList, accessLog.RemoteAddr) {
|
||||||
|
ipList = append(ipList, accessLog.RemoteAddr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Data["hasMore"] = resp.HasMore
|
||||||
|
this.Data["nextRequestId"] = resp.RequestId
|
||||||
|
|
||||||
|
// 上一个requestId
|
||||||
|
this.Data["hasPrev"] = false
|
||||||
|
this.Data["lastRequestId"] = ""
|
||||||
|
if len(params.RequestId) > 0 {
|
||||||
|
this.Data["hasPrev"] = true
|
||||||
|
prevResp, err := this.RPC().HTTPAccessLogRPC().ListHTTPAccessLogs(this.AdminContext(), &pb.ListHTTPAccessLogsRequest{
|
||||||
|
RequestId: params.RequestId,
|
||||||
|
ServerId: params.ServerId,
|
||||||
|
HasError: params.HasError > 0,
|
||||||
|
Day: day,
|
||||||
|
Keyword: params.Keyword,
|
||||||
|
Ip: params.Ip,
|
||||||
|
Domain: params.Domain,
|
||||||
|
Size: size,
|
||||||
|
Reverse: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if int64(len(prevResp.HttpAccessLogs)) == size {
|
||||||
|
this.Data["lastRequestId"] = prevResp.RequestId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据IP查询区域
|
||||||
|
regionMap := map[string]string{} // ip => region
|
||||||
|
if len(ipList) > 0 {
|
||||||
|
resp, err := this.RPC().IPLibraryRPC().LookupIPRegions(this.AdminContext(), &pb.LookupIPRegionsRequest{IpList: ipList})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if resp.IpRegionMap != nil {
|
||||||
|
for ip, region := range resp.IpRegionMap {
|
||||||
|
regionMap[ip] = region.Summary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Data["regions"] = regionMap
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
21
internal/web/actions/default/servers/logs/init.go
Normal file
21
internal/web/actions/default/servers/logs/init.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package logs
|
||||||
|
|
||||||
|
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", "log").
|
||||||
|
Prefix("/servers/logs").
|
||||||
|
Get("", new(IndexAction)).
|
||||||
|
EndAll()
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -25,14 +25,19 @@ func InitChart(parent *actionutils.ParentAction, chartId int64) (*pb.MetricChart
|
|||||||
if chart == nil {
|
if chart == nil {
|
||||||
return nil, errors.New("metric chart not found")
|
return nil, errors.New("metric chart not found")
|
||||||
}
|
}
|
||||||
|
if len(chart.IgnoredKeys) == 0 {
|
||||||
|
chart.IgnoredKeys = []string{}
|
||||||
|
}
|
||||||
parent.Data["chart"] = maps.Map{
|
parent.Data["chart"] = maps.Map{
|
||||||
"id": chart.Id,
|
"id": chart.Id,
|
||||||
"name": chart.Name,
|
"name": chart.Name,
|
||||||
"isOn": chart.IsOn,
|
"isOn": chart.IsOn,
|
||||||
"widthDiv": chart.WidthDiv,
|
"widthDiv": chart.WidthDiv,
|
||||||
"maxItems": chart.MaxItems,
|
"maxItems": chart.MaxItems,
|
||||||
"type": chart.Type,
|
"type": chart.Type,
|
||||||
"typeName": serverconfigs.FindMetricChartTypeName(chart.Type),
|
"typeName": serverconfigs.FindMetricChartTypeName(chart.Type),
|
||||||
|
"ignoreEmptyKeys": chart.IgnoreEmptyKeys,
|
||||||
|
"ignoredKeys": chart.IgnoredKeys,
|
||||||
}
|
}
|
||||||
return chart, nil
|
return chart, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user