Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a9045ba44 | ||
|
|
bc7ee19962 | ||
|
|
2484cd4ae6 | ||
|
|
57b8a96c6d | ||
|
|
6c8ab7cb94 | ||
|
|
b2c2bd247b | ||
|
|
29d9e6db81 | ||
|
|
24fcb48c75 | ||
|
|
4911198fe7 | ||
|
|
c2af796992 | ||
|
|
51c8572e53 | ||
|
|
c15cc6d75c | ||
|
|
c0a99a4ba3 | ||
|
|
62e26bed5a | ||
|
|
9e68a2915c | ||
|
|
5b809fda1f | ||
|
|
88b782940a | ||
|
|
85c596644d | ||
|
|
ffa2d884bd | ||
|
|
813ed18610 | ||
|
|
564b11eae7 | ||
|
|
d2af0307b9 | ||
|
|
4fa6b03238 | ||
|
|
4bda78aa8c | ||
|
|
6002cc96d9 | ||
|
|
56c09f5be7 | ||
|
|
e1fb8e4c74 | ||
|
|
14f055ce7c | ||
|
|
7b7f2b0a00 | ||
|
|
75662586fa | ||
|
|
c024331fa0 | ||
|
|
b01ea79c5c | ||
|
|
d59f80b3ec | ||
|
|
b87e48c1f9 | ||
|
|
0e7a7f168f | ||
|
|
2bbc09d3af | ||
|
|
97b50fab28 | ||
|
|
83c867cb65 | ||
|
|
3c4b7ca57b | ||
|
|
a2f98d2f25 | ||
|
|
71677a8638 | ||
|
|
95a2187f95 | ||
|
|
86bec813bf | ||
|
|
0d7bd6f04e | ||
|
|
d7117209b2 | ||
|
|
7a340ac68b | ||
|
|
353b1b4ad1 | ||
|
|
fdac8beb40 | ||
|
|
f098723a41 | ||
|
|
6ded627903 | ||
|
|
ed2d5ee5cc | ||
|
|
c677368482 | ||
|
|
51ccd614a7 | ||
|
|
9be7f61b8c | ||
|
|
14ad97c937 | ||
|
|
94609d8ef4 | ||
|
|
e34e38bcb2 | ||
|
|
b10d9fe842 | ||
|
|
992e725378 | ||
|
|
346de7ca7a |
29
LICENSE
Normal file
29
LICENSE
Normal file
@@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2020, LiuXiangChao
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,76 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
function build() {
|
||||
ROOT=$(dirname $0)
|
||||
ROOT=$(dirname "$0")
|
||||
NAME="edge-api"
|
||||
DIST=$ROOT/"../dist/${NAME}"
|
||||
OS=${1}
|
||||
ARCH=${2}
|
||||
TAG=${3}
|
||||
NODE_ARCHITECTS=("amd64" "386" "arm64" "mips64" "mips64le")
|
||||
NODE_ARCHITECTS=("amd64" "arm64")
|
||||
|
||||
if [ -z $OS ]; then
|
||||
if [ -z "$OS" ]; then
|
||||
echo "usage: build.sh OS ARCH"
|
||||
exit
|
||||
fi
|
||||
if [ -z $ARCH ]; then
|
||||
if [ -z "$ARCH" ]; then
|
||||
echo "usage: build.sh OS ARCH"
|
||||
exit
|
||||
fi
|
||||
if [ -z $TAG ]; then
|
||||
if [ -z "$TAG" ]; then
|
||||
TAG="community"
|
||||
fi
|
||||
|
||||
VERSION=$(lookup-version $ROOT/../internal/const/const.go)
|
||||
VERSION=$(lookup-version "$ROOT"/../internal/const/const.go)
|
||||
ZIP="${NAME}-${OS}-${ARCH}-${TAG}-v${VERSION}.zip"
|
||||
|
||||
# build edge-node
|
||||
NodeVersion=$(lookup-version $ROOT"/../../EdgeNode/internal/const/const.go")
|
||||
NodeVersion=$(lookup-version "$ROOT""/../../EdgeNode/internal/const/const.go")
|
||||
echo "building edge-node v${NodeVersion} ..."
|
||||
EDGE_NODE_BUILD_SCRIPT=$ROOT"/../../EdgeNode/build/build.sh"
|
||||
if [ ! -f $EDGE_NODE_BUILD_SCRIPT ]; then
|
||||
if [ ! -f "$EDGE_NODE_BUILD_SCRIPT" ]; then
|
||||
echo "unable to find edge-node build script 'EdgeNode/build/build.sh'"
|
||||
exit
|
||||
fi
|
||||
cd $ROOT"/../../EdgeNode/build"
|
||||
cd "$ROOT""/../../EdgeNode/build" || exit
|
||||
echo "=============================="
|
||||
for arch in "${NODE_ARCHITECTS[@]}"; do
|
||||
if [ ! -f $ROOT"/../../EdgeNode/dist/edge-node-linux-${arch}-${TAG}-v${NodeVersion}.zip" ]; then
|
||||
./build.sh linux $arch $TAG
|
||||
if [ ! -f "$ROOT""/../../EdgeNode/dist/edge-node-linux-${arch}-${TAG}-v${NodeVersion}.zip" ]; then
|
||||
./build.sh linux "$arch" $TAG
|
||||
else
|
||||
echo "use built node linux/$arch/v${NodeVersion}"
|
||||
fi
|
||||
done
|
||||
echo "=============================="
|
||||
cd -
|
||||
cd - || exit
|
||||
|
||||
rm -f $ROOT/deploy/*.zip
|
||||
rm -f "$ROOT"/deploy/*.zip
|
||||
for arch in "${NODE_ARCHITECTS[@]}"; do
|
||||
cp $ROOT"/../../EdgeNode/dist/edge-node-linux-${arch}-${TAG}-v${NodeVersion}.zip" $ROOT/deploy/edge-node-linux-${arch}-v${NodeVersion}.zip
|
||||
cp "$ROOT""/../../EdgeNode/dist/edge-node-linux-${arch}-${TAG}-v${NodeVersion}.zip" "$ROOT"/deploy/edge-node-linux-"${arch}"-v"${NodeVersion}".zip
|
||||
done
|
||||
|
||||
# build edge-dns
|
||||
if [ "$TAG" = "plus" ]; then
|
||||
DNS_ROOT=$ROOT"/../../EdgeDNS"
|
||||
if [ -d $DNS_ROOT ]; then
|
||||
DNSNodeVersion=$(lookup-version $ROOT"/../../EdgeDNS/internal/const/const.go")
|
||||
if [ -d "$DNS_ROOT" ]; then
|
||||
DNSNodeVersion=$(lookup-version "$ROOT""/../../EdgeDNS/internal/const/const.go")
|
||||
echo "building edge-dns ${DNSNodeVersion} ..."
|
||||
EDGE_DNS_NODE_BUILD_SCRIPT=$ROOT"/../../EdgeDNS/build/build.sh"
|
||||
if [ ! -f $EDGE_DNS_NODE_BUILD_SCRIPT ]; then
|
||||
if [ ! -f "$EDGE_DNS_NODE_BUILD_SCRIPT" ]; then
|
||||
echo "unable to find edge-dns build script 'EdgeDNS/build/build.sh'"
|
||||
exit
|
||||
fi
|
||||
cd $ROOT"/../../EdgeDNS/build"
|
||||
cd "$ROOT""/../../EdgeDNS/build" || exit
|
||||
echo "=============================="
|
||||
architects=("amd64")
|
||||
architects=("amd64" "arm64")
|
||||
for arch in "${architects[@]}"; do
|
||||
./build.sh linux $arch $TAG
|
||||
./build.sh linux "$arch" $TAG
|
||||
done
|
||||
echo "=============================="
|
||||
cd -
|
||||
cd - || exit
|
||||
|
||||
for arch in "${architects[@]}"; do
|
||||
cp $ROOT"/../../EdgeDNS/dist/edge-dns-linux-${arch}-v${DNSNodeVersion}.zip" $ROOT/deploy/edge-dns-linux-${arch}-v${DNSNodeVersion}.zip
|
||||
cp "$ROOT""/../../EdgeDNS/dist/edge-dns-linux-${arch}-v${DNSNodeVersion}.zip" "$ROOT"/deploy/edge-dns-linux-"${arch}"-v"${DNSNodeVersion}".zip
|
||||
done
|
||||
fi
|
||||
fi
|
||||
@@ -78,48 +78,48 @@ function build() {
|
||||
# build sql
|
||||
if [ $TAG = "plus" ]; then
|
||||
echo "building sql ..."
|
||||
${ROOT}/sql.sh
|
||||
"${ROOT}"/sql.sh
|
||||
fi
|
||||
|
||||
# copy files
|
||||
echo "copying ..."
|
||||
if [ ! -d $DIST ]; then
|
||||
mkdir $DIST
|
||||
mkdir $DIST/bin
|
||||
mkdir $DIST/configs
|
||||
mkdir $DIST/logs
|
||||
if [ ! -d "$DIST" ]; then
|
||||
mkdir "$DIST"
|
||||
mkdir "$DIST"/bin
|
||||
mkdir "$DIST"/configs
|
||||
mkdir "$DIST"/logs
|
||||
fi
|
||||
cp $ROOT/configs/api.template.yaml $DIST/configs/
|
||||
cp $ROOT/configs/db.template.yaml $DIST/configs/
|
||||
cp -R $ROOT/deploy $DIST/
|
||||
rm -f $dist/deploy/.gitignore
|
||||
cp -R $ROOT/installers $DIST/
|
||||
cp -R $ROOT/resources $DIST/
|
||||
rm -f $DIST/resources/ipdata/ip2region/global_region.csv
|
||||
rm -f $DIST/resources/ipdata/ip2region/ip.merge.txt
|
||||
cp "$ROOT"/configs/api.template.yaml "$DIST"/configs/
|
||||
cp "$ROOT"/configs/db.template.yaml "$DIST"/configs/
|
||||
cp -R "$ROOT"/deploy "$DIST/"
|
||||
rm -f "$DIST"/deploy/.gitignore
|
||||
cp -R "$ROOT"/installers "$DIST"/
|
||||
cp -R "$ROOT"/resources "$DIST"/
|
||||
rm -f "$DIST"/resources/ipdata/ip2region/global_region.csv
|
||||
rm -f "$DIST"/resources/ipdata/ip2region/ip.merge.txt
|
||||
|
||||
# building edge installer
|
||||
echo "building node installer ..."
|
||||
architects=("amd64" "386" "arm64")
|
||||
architects=("amd64" "arm64")
|
||||
for arch in "${architects[@]}"; do
|
||||
# TODO support arm, mips ...
|
||||
env GOOS=linux GOARCH=${arch} go build -tags $TAG --ldflags="-s -w" -o $ROOT/installers/edge-installer-helper-linux-${arch} $ROOT/../cmd/installer-helper/main.go
|
||||
env GOOS=linux GOARCH="${arch}" go build -trimpath -tags $TAG --ldflags="-s -w" -o "$ROOT"/installers/edge-installer-helper-linux-"${arch}" "$ROOT"/../cmd/installer-helper/main.go
|
||||
done
|
||||
|
||||
# building edge dns installer
|
||||
echo "building dns node installer ..."
|
||||
architects=("amd64" "386" "arm64")
|
||||
architects=("amd64" "arm64")
|
||||
for arch in "${architects[@]}"; do
|
||||
# TODO support arm, mips ...
|
||||
env GOOS=linux GOARCH=${arch} go build -tags $TAG --ldflags="-s -w" -o $ROOT/installers/edge-installer-dns-helper-linux-${arch} $ROOT/../cmd/installer-dns-helper/main.go
|
||||
env GOOS=linux GOARCH="${arch}" go build -trimpath -tags $TAG --ldflags="-s -w" -o "$ROOT"/installers/edge-installer-dns-helper-linux-"${arch}" "$ROOT"/../cmd/installer-dns-helper/main.go
|
||||
done
|
||||
|
||||
# building api node
|
||||
env GOOS=$OS GOARCH=$ARCH go build -tags $TAG --ldflags="-s -w" -o $DIST/bin/edge-api $ROOT/../cmd/edge-api/main.go
|
||||
env GOOS="$OS" GOARCH="$ARCH" go build -trimpath -tags $TAG --ldflags="-s -w" -o "$DIST"/bin/edge-api "$ROOT"/../cmd/edge-api/main.go
|
||||
|
||||
# delete hidden files
|
||||
find $DIST -name ".DS_Store" -delete
|
||||
find $DIST -name ".gitignore" -delete
|
||||
find "$DIST" -name ".DS_Store" -delete
|
||||
find "$DIST" -name ".gitignore" -delete
|
||||
|
||||
echo "zip files"
|
||||
cd "${DIST}/../" || exit
|
||||
@@ -135,15 +135,15 @@ function build() {
|
||||
|
||||
function lookup-version() {
|
||||
FILE=$1
|
||||
VERSION_DATA=$(cat $FILE)
|
||||
VERSION_DATA=$(cat "$FILE")
|
||||
re="Version[ ]+=[ ]+\"([0-9.]+)\""
|
||||
if [[ $VERSION_DATA =~ $re ]]; then
|
||||
VERSION=${BASH_REMATCH[1]}
|
||||
echo $VERSION
|
||||
echo "$VERSION"
|
||||
else
|
||||
echo "could not match version"
|
||||
exit
|
||||
fi
|
||||
}
|
||||
|
||||
build $1 $2 $3
|
||||
build "$1" "$2" "$3"
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/apps"
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
@@ -13,6 +14,7 @@ import (
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"github.com/iwind/gosock/pkg/gosock"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
@@ -21,12 +23,12 @@ func main() {
|
||||
if !Tea.IsTesting() {
|
||||
Tea.Env = "prod"
|
||||
}
|
||||
app := apps.NewAppCmd()
|
||||
var app = apps.NewAppCmd()
|
||||
app.Version(teaconst.Version)
|
||||
app.Product(teaconst.ProductName)
|
||||
app.Usage(teaconst.ProcessName + " [start|stop|restart|setup|upgrade|service|daemon]")
|
||||
app.Usage(teaconst.ProcessName + " [start|stop|restart|setup|upgrade|service|daemon|issues]")
|
||||
app.On("setup", func() {
|
||||
setupCmd := setup.NewSetupFromCmd()
|
||||
var setupCmd = setup.NewSetupFromCmd()
|
||||
err := setupCmd.Run()
|
||||
result := maps.Map{}
|
||||
if err != nil {
|
||||
@@ -122,6 +124,43 @@ func main() {
|
||||
fmt.Println("prepared statements count: " + types.String(count))
|
||||
}
|
||||
})
|
||||
app.On("issues", func() {
|
||||
var flagSet = flag.NewFlagSet("issues", flag.ExitOnError)
|
||||
var formatJSON = false
|
||||
flagSet.BoolVar(&formatJSON, "json", false, "")
|
||||
_ = flagSet.Parse(os.Args[2:])
|
||||
|
||||
data, err := ioutil.ReadFile(Tea.LogFile("issues.log"))
|
||||
if err != nil {
|
||||
if formatJSON {
|
||||
fmt.Print("[]")
|
||||
} else {
|
||||
fmt.Println("no issues yet")
|
||||
}
|
||||
} else {
|
||||
var issueMaps = []maps.Map{}
|
||||
err = json.Unmarshal(data, &issueMaps)
|
||||
if err != nil {
|
||||
if formatJSON {
|
||||
fmt.Print("[]")
|
||||
} else {
|
||||
fmt.Println("no issues yet")
|
||||
}
|
||||
} else {
|
||||
if formatJSON {
|
||||
fmt.Print(string(data))
|
||||
} else {
|
||||
if len(issueMaps) == 0 {
|
||||
fmt.Println("no issues yet")
|
||||
} else {
|
||||
for i, issue := range issueMaps {
|
||||
fmt.Println("issue " + types.String(i+1) + ": " + issue.GetString("message"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
app.Run(func() {
|
||||
nodes.NewAPINode().Start()
|
||||
|
||||
3
dist/.gitignore
vendored
3
dist/.gitignore
vendored
@@ -1 +1,2 @@
|
||||
*.zip
|
||||
*.zip
|
||||
edge-api
|
||||
27
go.mod
27
go.mod
@@ -1,6 +1,6 @@
|
||||
module github.com/TeaOSLab/EdgeAPI
|
||||
|
||||
go 1.16
|
||||
go 1.18
|
||||
|
||||
replace github.com/TeaOSLab/EdgeCommon => ../EdgeCommon
|
||||
|
||||
@@ -12,9 +12,8 @@ require (
|
||||
github.com/go-acme/lego/v4 v4.5.2
|
||||
github.com/go-sql-driver/mysql v1.5.0
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/iwind/TeaGo v0.0.0-20220408064305-92be81dc2f7c
|
||||
github.com/iwind/TeaGo v0.0.0-20220408111647-f36b9bba3570
|
||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/mozillazg/go-pinyin v0.18.0
|
||||
github.com/pkg/sftp v1.12.0
|
||||
github.com/shirou/gopsutil/v3 v3.22.2
|
||||
@@ -24,3 +23,25 @@ require (
|
||||
google.golang.org/protobuf v1.27.1
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/cenkalti/backoff/v4 v4.1.1 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/miekg/dns v1.1.43 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.9 // indirect
|
||||
github.com/tklauser/numcpus v0.3.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
)
|
||||
|
||||
8
go.sum
8
go.sum
@@ -66,7 +66,6 @@ github.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7F
|
||||
github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ=
|
||||
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
@@ -238,10 +237,8 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
|
||||
github.com/infobloxopen/infoblox-go-client v1.1.1/go.mod h1:BXiw7S2b9qJoM8MS40vfgCNB2NLHGusk1DtO16BD9zI=
|
||||
github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
|
||||
github.com/iwind/TeaGo v0.0.0-20220322141208-22f88d04004d h1:e8fkTKras/RXQWECApM9fKlFWujjYjEClpshkmZmtYg=
|
||||
github.com/iwind/TeaGo v0.0.0-20220322141208-22f88d04004d/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
|
||||
github.com/iwind/TeaGo v0.0.0-20220408064305-92be81dc2f7c h1:ugjYZ74FJGWlfDKKraNgMyDTeS4vbXHe89JGUVQIJMo=
|
||||
github.com/iwind/TeaGo v0.0.0-20220408064305-92be81dc2f7c/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
|
||||
github.com/iwind/TeaGo v0.0.0-20220408111647-f36b9bba3570 h1:zqz2FiMMkSHXWO1EsTRJDPTwX9xQ4uuyD5GAE4JGlhM=
|
||||
github.com/iwind/TeaGo v0.0.0-20220408111647-f36b9bba3570/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
|
||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3 h1:aBSonas7vFcgTj9u96/bWGILGv1ZbUSTLiOzcI1ZT6c=
|
||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
|
||||
github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
|
||||
@@ -559,7 +556,6 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
|
||||
@@ -44,7 +44,7 @@ func (this *BaseStorage) Marshal(accessLog *pb.HTTPAccessLog) ([]byte, error) {
|
||||
|
||||
// FormatVariables 格式化字符串中的变量
|
||||
func (this *BaseStorage) FormatVariables(s string) string {
|
||||
now := time.Now()
|
||||
var now = time.Now()
|
||||
return configutils.ParseVariables(s, func(varName string) (value string) {
|
||||
switch varName {
|
||||
case "year":
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package accesslogs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
@@ -95,7 +97,10 @@ func (this *SyslogStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
|
||||
args = append(args, "-S", "10240")
|
||||
|
||||
cmd := exec.Command(this.exe, args...)
|
||||
var cmd = exec.Command(this.exe, args...)
|
||||
var stderrBuffer = &bytes.Buffer{}
|
||||
cmd.Stderr = stderrBuffer
|
||||
|
||||
w, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -111,7 +116,7 @@ func (this *SyslogStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
}
|
||||
data, err := this.Marshal(accessLog)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
remotelogs.Error("ACCESS_LOG_POLICY_SYSLOG", "marshal accesslog failed: "+err.Error())
|
||||
continue
|
||||
}
|
||||
_, err = w.Write(data)
|
||||
@@ -121,14 +126,15 @@ func (this *SyslogStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
|
||||
_, err = w.Write([]byte("\n"))
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
remotelogs.Error("ACCESS_LOG_POLICY_SYSLOG", "write accesslog failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
_ = w.Close()
|
||||
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.New("send syslog failed: " + err.Error() + ", stderr: " + stderrBuffer.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package teaconst
|
||||
|
||||
const (
|
||||
Version = "0.4.7"
|
||||
Version = "0.4.9"
|
||||
|
||||
ProductName = "Edge API"
|
||||
ProcessName = "edge-api"
|
||||
@@ -18,13 +18,13 @@ const (
|
||||
|
||||
// 其他节点版本号,用来检测是否有需要升级的节点
|
||||
|
||||
NodeVersion = "0.4.7"
|
||||
UserNodeVersion = "0.3.3"
|
||||
NodeVersion = "0.4.9"
|
||||
UserNodeVersion = "0.3.5"
|
||||
AuthorityNodeVersion = "0.0.2"
|
||||
MonitorNodeVersion = "0.0.3"
|
||||
DNSNodeVersion = "0.2.2"
|
||||
ReportNodeVersion = "0.1.0"
|
||||
MonitorNodeVersion = "0.0.4"
|
||||
DNSNodeVersion = "0.2.4"
|
||||
ReportNodeVersion = "0.1.1"
|
||||
|
||||
// SQLVersion SQL版本号
|
||||
SQLVersion = "8"
|
||||
SQLVersion = "2"
|
||||
)
|
||||
|
||||
@@ -58,15 +58,22 @@ func (this *APINodeDAO) EnableAPINode(tx *dbs.Tx, id int64) error {
|
||||
}
|
||||
|
||||
// DisableAPINode 禁用条目
|
||||
func (this *APINodeDAO) DisableAPINode(tx *dbs.Tx, id int64) error {
|
||||
func (this *APINodeDAO) DisableAPINode(tx *dbs.Tx, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Pk(nodeId).
|
||||
Set("state", APINodeStateDisabled).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, id)
|
||||
|
||||
err = this.NotifyUpdate(tx, nodeId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除运行日志
|
||||
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleAPI, nodeId)
|
||||
}
|
||||
|
||||
// FindEnabledAPINode 查找启用中的条目
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package authority
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
@@ -188,13 +189,19 @@ func (this *AuthorityNodeDAO) GenUniqueId(tx *dbs.Tx) (string, error) {
|
||||
}
|
||||
|
||||
// UpdateNodeStatus 更改节点状态
|
||||
func (this *AuthorityNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, statusJSON []byte) error {
|
||||
if statusJSON == nil {
|
||||
func (this *AuthorityNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, nodeStatus *nodeconfigs.NodeStatus) error {
|
||||
if nodeStatus == nil {
|
||||
return nil
|
||||
}
|
||||
_, err := this.Query(tx).
|
||||
|
||||
nodeStatusJSON, err := json.Marshal(nodeStatus)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Pk(nodeId).
|
||||
Set("status", string(statusJSON)).
|
||||
Set("status", nodeStatusJSON).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/base64"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/encrypt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -49,12 +50,17 @@ func (this *DBNodeDAO) EnableDBNode(tx *dbs.Tx, id int64) error {
|
||||
}
|
||||
|
||||
// DisableDBNode 禁用条目
|
||||
func (this *DBNodeDAO) DisableDBNode(tx *dbs.Tx, id int64) error {
|
||||
func (this *DBNodeDAO) DisableDBNode(tx *dbs.Tx, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Pk(nodeId).
|
||||
Set("state", DBNodeStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除运行日志
|
||||
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleDatabase, nodeId)
|
||||
}
|
||||
|
||||
// FindEnabledDBNode 查找启用中的条目
|
||||
|
||||
@@ -107,7 +107,7 @@ func (this *DNSProviderDAO) UpdateDNSProvider(tx *dbs.Tx, dnsProviderId int64, n
|
||||
}
|
||||
|
||||
// CountAllEnabledDNSProviders 计算服务商数量
|
||||
func (this *DNSProviderDAO) CountAllEnabledDNSProviders(tx *dbs.Tx, adminId int64, userId int64, keyword string, domain string) (int64, error) {
|
||||
func (this *DNSProviderDAO) CountAllEnabledDNSProviders(tx *dbs.Tx, adminId int64, userId int64, keyword string, domain string, providerType string) (int64, error) {
|
||||
var query = dbutils.NewQuery(tx, this, adminId, userId)
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
@@ -119,12 +119,16 @@ func (this *DNSProviderDAO) CountAllEnabledDNSProviders(tx *dbs.Tx, adminId int6
|
||||
query.Param("domain", domain)
|
||||
}
|
||||
|
||||
if len(providerType) > 0 {
|
||||
query.Attr("type", providerType)
|
||||
}
|
||||
|
||||
return query.State(DNSProviderStateEnabled).
|
||||
Count()
|
||||
}
|
||||
|
||||
// ListEnabledDNSProviders 列出单页服务商
|
||||
func (this *DNSProviderDAO) ListEnabledDNSProviders(tx *dbs.Tx, adminId int64, userId int64, keyword string, domain string, offset int64, size int64) (result []*DNSProvider, err error) {
|
||||
func (this *DNSProviderDAO) ListEnabledDNSProviders(tx *dbs.Tx, adminId int64, userId int64, keyword string, domain string, providerType string, offset int64, size int64) (result []*DNSProvider, err error) {
|
||||
var query = dbutils.NewQuery(tx, this, adminId, userId)
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
@@ -134,6 +138,9 @@ func (this *DNSProviderDAO) ListEnabledDNSProviders(tx *dbs.Tx, adminId int64, u
|
||||
query.Where("id IN (SELECT providerId FROM " + SharedDNSDomainDAO.Table + " WHERE state=1 AND name=:domain)")
|
||||
query.Param("domain", domain)
|
||||
}
|
||||
if len(providerType) > 0 {
|
||||
query.Attr("type", providerType)
|
||||
}
|
||||
_, err = query.
|
||||
State(DNSProviderStateEnabled).
|
||||
Offset(offset).
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -33,7 +34,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 启用条目
|
||||
// EnableFile 启用条目
|
||||
func (this *FileDAO) EnableFile(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -42,7 +43,7 @@ func (this *FileDAO) EnableFile(tx *dbs.Tx, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 禁用条目
|
||||
// DisableFile 禁用条目
|
||||
func (this *FileDAO) DisableFile(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -51,7 +52,7 @@ func (this *FileDAO) DisableFile(tx *dbs.Tx, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 查找启用中的条目
|
||||
// FindEnabledFile 查找启用中的条目
|
||||
func (this *FileDAO) FindEnabledFile(tx *dbs.Tx, id int64) (*File, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -63,9 +64,9 @@ func (this *FileDAO) FindEnabledFile(tx *dbs.Tx, id int64) (*File, error) {
|
||||
return result.(*File), err
|
||||
}
|
||||
|
||||
// 创建文件
|
||||
// CreateFile 创建文件
|
||||
func (this *FileDAO) CreateFile(tx *dbs.Tx, adminId int64, userId int64, businessType, description string, filename string, size int64, isPublic bool) (int64, error) {
|
||||
op := NewFileOperator()
|
||||
var op = NewFileOperator()
|
||||
op.AdminId = adminId
|
||||
op.UserId = userId
|
||||
op.Type = businessType
|
||||
@@ -74,6 +75,7 @@ func (this *FileDAO) CreateFile(tx *dbs.Tx, adminId int64, userId int64, busines
|
||||
op.Size = size
|
||||
op.Filename = filename
|
||||
op.IsPublic = isPublic
|
||||
op.Code = utils.Sha1RandomString()
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -82,7 +84,7 @@ func (this *FileDAO) CreateFile(tx *dbs.Tx, adminId int64, userId int64, busines
|
||||
return types.Int64(op.Id), nil
|
||||
}
|
||||
|
||||
// 将文件置为已完成
|
||||
// UpdateFileIsFinished 将文件置为已完成
|
||||
func (this *FileDAO) UpdateFileIsFinished(tx *dbs.Tx, fileId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(fileId).
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package models
|
||||
|
||||
// 文件管理
|
||||
// File 文件管理
|
||||
type File struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
Code string `field:"code"` // 代号
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
Description string `field:"description"` // 文件描述
|
||||
Filename string `field:"filename"` // 文件名
|
||||
@@ -19,6 +20,7 @@ type File struct {
|
||||
type FileOperator struct {
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
Code interface{} // 代号
|
||||
UserId interface{} // 用户ID
|
||||
Description interface{} // 文件描述
|
||||
Filename interface{} // 文件名
|
||||
|
||||
@@ -395,9 +395,14 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx,
|
||||
|
||||
var locker = sync.Mutex{}
|
||||
|
||||
// 这里正则表达式中的括号不能轻易变更,因为后面有引用
|
||||
// TODO 支持多个查询条件的组合,比如 status:200 proto:HTTP/1.1
|
||||
var statusPrefixReg = regexp.MustCompile(`status:\s*(\d{3})\b`)
|
||||
var statusRangeReg = regexp.MustCompile(`status:\s*(\d{3})-(\d{3})\b`)
|
||||
var urlReg = regexp.MustCompile(`^(http|https)://`)
|
||||
var requestPathReg = regexp.MustCompile(`requestPath:(\S+)`)
|
||||
var protoReg = regexp.MustCompile(`proto:(\S+)`)
|
||||
var schemeReg = regexp.MustCompile(`scheme:(\S+)`)
|
||||
|
||||
var count = len(tableQueries)
|
||||
var wg = &sync.WaitGroup{}
|
||||
@@ -509,13 +514,25 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx,
|
||||
isSpecialKeyword = true
|
||||
var matches = statusRangeReg.FindStringSubmatch(keyword)
|
||||
query.Between("status", types.Int(matches[1]), types.Int(matches[2]))
|
||||
|
||||
// TODO 处理剩余的关键词
|
||||
} else if statusPrefixReg.MatchString(keyword) { // status:200
|
||||
isSpecialKeyword = true
|
||||
var matches = statusPrefixReg.FindStringSubmatch(keyword)
|
||||
query.Attr("status", matches[1])
|
||||
// TODO 处理剩余的关键词
|
||||
} else if requestPathReg.MatchString(keyword) {
|
||||
isSpecialKeyword = true
|
||||
var matches = requestPathReg.FindStringSubmatch(keyword)
|
||||
query.Where("JSON_EXTRACT(content, '$.requestPath')=:keyword").
|
||||
Param("keyword", matches[1])
|
||||
} else if protoReg.MatchString(keyword) {
|
||||
isSpecialKeyword = true
|
||||
var matches = protoReg.FindStringSubmatch(keyword)
|
||||
query.Where("JSON_EXTRACT(content, '$.proto')=:keyword").
|
||||
Param("keyword", strings.ToUpper(matches[1]))
|
||||
} else if schemeReg.MatchString(keyword) {
|
||||
isSpecialKeyword = true
|
||||
var matches = schemeReg.FindStringSubmatch(keyword)
|
||||
query.Where("JSON_EXTRACT(content, '$.scheme')=:keyword").
|
||||
Param("keyword", strings.ToLower(matches[1]))
|
||||
} else if urlReg.MatchString(keyword) { // https://xxx/yyy
|
||||
u, err := url.Parse(keyword)
|
||||
if err == nil {
|
||||
|
||||
254
internal/db/models/http_cache_task_dao.go
Normal file
254
internal/db/models/http_cache_task_dao.go
Normal file
@@ -0,0 +1,254 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
HTTPCacheTaskStateEnabled = 1 // 已启用
|
||||
HTTPCacheTaskStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type HTTPCacheTaskType = string
|
||||
|
||||
const (
|
||||
HTTPCacheTaskTypePurge HTTPCacheTaskType = "purge"
|
||||
HTTPCacheTaskTypeFetch HTTPCacheTaskType = "fetch"
|
||||
)
|
||||
|
||||
type HTTPCacheTaskDAO dbs.DAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
// 清理数据任务
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedHTTPCacheTaskDAO.Clean(nil, 30) // 只保留N天
|
||||
if err != nil {
|
||||
remotelogs.Error("HTTPCacheTaskDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func NewHTTPCacheTaskDAO() *HTTPCacheTaskDAO {
|
||||
return dbs.NewDAO(&HTTPCacheTaskDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeHTTPCacheTasks",
|
||||
Model: new(HTTPCacheTask),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*HTTPCacheTaskDAO)
|
||||
}
|
||||
|
||||
var SharedHTTPCacheTaskDAO *HTTPCacheTaskDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedHTTPCacheTaskDAO = NewHTTPCacheTaskDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableHTTPCacheTask 启用条目
|
||||
func (this *HTTPCacheTaskDAO) EnableHTTPCacheTask(tx *dbs.Tx, taskId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(taskId).
|
||||
Set("state", HTTPCacheTaskStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableHTTPCacheTask 禁用条目
|
||||
func (this *HTTPCacheTaskDAO) DisableHTTPCacheTask(tx *dbs.Tx, taskId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(taskId).
|
||||
Set("state", HTTPCacheTaskStateDisabled).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyChange(tx, taskId)
|
||||
}
|
||||
|
||||
// FindEnabledHTTPCacheTask 查找启用中的条目
|
||||
func (this *HTTPCacheTaskDAO) FindEnabledHTTPCacheTask(tx *dbs.Tx, taskId int64) (*HTTPCacheTask, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(taskId).
|
||||
Attr("state", HTTPCacheTaskStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*HTTPCacheTask), err
|
||||
}
|
||||
|
||||
// CreateTask 创建任务
|
||||
func (this *HTTPCacheTaskDAO) CreateTask(tx *dbs.Tx, userId int64, taskType HTTPCacheTaskType, keyType string, description string) (int64, error) {
|
||||
var op = NewHTTPCacheTaskOperator()
|
||||
op.UserId = userId
|
||||
op.Type = taskType
|
||||
op.KeyType = keyType
|
||||
op.IsOk = false
|
||||
op.IsDone = false
|
||||
op.IsReady = false
|
||||
op.Description = description
|
||||
op.Day = timeutil.Format("Ymd")
|
||||
op.State = HTTPCacheTaskStateEnabled
|
||||
taskId, err := this.SaveInt64(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = this.NotifyChange(tx, taskId)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return taskId, nil
|
||||
}
|
||||
|
||||
// ResetTask 重置服务状态
|
||||
func (this *HTTPCacheTaskDAO) ResetTask(tx *dbs.Tx, taskId int64) error {
|
||||
if taskId <= 0 {
|
||||
return errors.New("invalid 'taskId'")
|
||||
}
|
||||
|
||||
var op = NewHTTPCacheTaskOperator()
|
||||
op.Id = taskId
|
||||
op.IsOk = false
|
||||
op.IsDone = false
|
||||
op.DoneAt = 0
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// UpdateTaskReady 设置任务为已准备
|
||||
func (this *HTTPCacheTaskDAO) UpdateTaskReady(tx *dbs.Tx, taskId int64) error {
|
||||
return this.Query(tx).
|
||||
Pk(taskId).
|
||||
Set("isReady", true).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// CountTasks 查询所有任务数量
|
||||
func (this *HTTPCacheTaskDAO) CountTasks(tx *dbs.Tx, userId int64) (int64, error) {
|
||||
var query = this.Query(tx).
|
||||
State(HTTPCacheTaskStateEnabled).
|
||||
Attr("isReady", true)
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
}
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// CountDoingTasks 查询正在执行的任务数量
|
||||
func (this *HTTPCacheTaskDAO) CountDoingTasks(tx *dbs.Tx, userId int64) (int64, error) {
|
||||
var query = this.Query(tx).
|
||||
State(HTTPCacheTaskStateEnabled).
|
||||
Attr("isReady", true).
|
||||
Attr("isDone", false)
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
}
|
||||
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// ListTasks 列出单页任务
|
||||
func (this *HTTPCacheTaskDAO) ListTasks(tx *dbs.Tx, userId int64, offset int64, size int64) (result []*HTTPCacheTask, err error) {
|
||||
var query = this.Query(tx).
|
||||
State(HTTPCacheTaskStateEnabled).
|
||||
Attr("isReady", true)
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
}
|
||||
_, err = query.
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
DescPk().
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// ListDoingTasks 列出需要执行的任务
|
||||
func (this *HTTPCacheTaskDAO) ListDoingTasks(tx *dbs.Tx, size int64) (result []*HTTPCacheTask, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(HTTPCacheTaskStateEnabled).
|
||||
Attr("isDone", false).
|
||||
Attr("isReady", true).
|
||||
Limit(size).
|
||||
AscPk(). // 按照先创建先执行的原则
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateTaskStatus 标记任务已完成
|
||||
func (this *HTTPCacheTaskDAO) UpdateTaskStatus(tx *dbs.Tx, taskId int64, isDone bool, isOk bool) error {
|
||||
if taskId <= 0 {
|
||||
return errors.New("invalid taskId '" + types.String(taskId) + "'")
|
||||
}
|
||||
var op = NewHTTPCacheTaskOperator()
|
||||
op.Id = taskId
|
||||
op.IsDone = isDone
|
||||
op.IsOk = isOk
|
||||
|
||||
if isDone {
|
||||
op.DoneAt = time.Now().Unix()
|
||||
}
|
||||
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// CheckUserTask 检查用户任务
|
||||
func (this *HTTPCacheTaskDAO) CheckUserTask(tx *dbs.Tx, userId int64, taskId int64) error {
|
||||
b, err := this.Query(tx).
|
||||
Pk(taskId).
|
||||
Attr("userId", userId).
|
||||
State(HTTPCacheTaskStateEnabled).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !b {
|
||||
return ErrNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Clean 清理以往的任务
|
||||
func (this *HTTPCacheTaskDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
if days <= 0 {
|
||||
days = 30
|
||||
}
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days))
|
||||
|
||||
// 删除Key
|
||||
err := SharedHTTPCacheTaskKeyDAO.Clean(tx, days)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除任务
|
||||
_, err = this.Query(tx).
|
||||
Lte("day", day).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
// NotifyChange 发送通知
|
||||
func (this *HTTPCacheTaskDAO) NotifyChange(tx *dbs.Tx, taskId int64) error {
|
||||
// TODO
|
||||
return nil
|
||||
}
|
||||
19
internal/db/models/http_cache_task_dao_test.go
Normal file
19
internal/db/models/http_cache_task_dao_test.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package models_test
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHTTPCacheTaskDAO_Clean(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
err := models.SharedHTTPCacheTaskDAO.Clean(nil, 30)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
218
internal/db/models/http_cache_task_key_dao.go
Normal file
218
internal/db/models/http_cache_task_key_dao.go
Normal file
@@ -0,0 +1,218 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
type HTTPCacheTaskKeyDAO dbs.DAO
|
||||
|
||||
func NewHTTPCacheTaskKeyDAO() *HTTPCacheTaskKeyDAO {
|
||||
return dbs.NewDAO(&HTTPCacheTaskKeyDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeHTTPCacheTaskKeys",
|
||||
Model: new(HTTPCacheTaskKey),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*HTTPCacheTaskKeyDAO)
|
||||
}
|
||||
|
||||
var SharedHTTPCacheTaskKeyDAO *HTTPCacheTaskKeyDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedHTTPCacheTaskKeyDAO = NewHTTPCacheTaskKeyDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// CreateKey 创建Key
|
||||
// 参数:
|
||||
// - clusterId 集群ID
|
||||
// - nodeMapJSON 集群下节点映射,格式类似于 `{ "节点1":true, ... }`
|
||||
func (this *HTTPCacheTaskKeyDAO) CreateKey(tx *dbs.Tx, taskId int64, key string, taskType HTTPCacheTaskType, keyType string, clusterId int64) (int64, error) {
|
||||
var op = NewHTTPCacheTaskKeyOperator()
|
||||
op.TaskId = taskId
|
||||
op.Key = key
|
||||
op.Type = taskType
|
||||
op.KeyType = keyType
|
||||
op.ClusterId = clusterId
|
||||
|
||||
op.Nodes = "{}"
|
||||
op.Errors = "{}"
|
||||
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// UpdateKeyStatus 修改Key状态
|
||||
func (this *HTTPCacheTaskKeyDAO) UpdateKeyStatus(tx *dbs.Tx, keyId int64, nodeId int64, errString string, nodesJSON []byte) error {
|
||||
if keyId <= 0 {
|
||||
return errors.New("invalid 'keyId'")
|
||||
}
|
||||
|
||||
if len(nodesJSON) == 0 {
|
||||
nodesJSON = []byte("{}")
|
||||
}
|
||||
|
||||
taskId, err := this.Query(tx).
|
||||
Pk(keyId).
|
||||
Result("taskId").
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var jsonPath = "$.\"" + types.String(nodeId) + "\""
|
||||
|
||||
var query = this.Query(tx).
|
||||
Pk(keyId).
|
||||
Set("nodes", dbs.SQL("JSON_SET(nodes, :jsonPath1, true)")).
|
||||
Param("jsonPath1", jsonPath)
|
||||
|
||||
if len(errString) > 0 {
|
||||
query.Set("errors", dbs.SQL("JSON_SET(errors, :jsonPath2, :jsonValue2)")).
|
||||
Param("jsonPath2", jsonPath).
|
||||
Param("jsonValue2", errString)
|
||||
} else {
|
||||
query.Set("errors", dbs.SQL("JSON_REMOVE(errors, :jsonPath2)")).
|
||||
Param("jsonPath2", jsonPath)
|
||||
}
|
||||
|
||||
err = query.
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 检查是否已完成
|
||||
isDone, err := this.Query(tx).
|
||||
Pk(keyId).
|
||||
Where("JSON_CONTAINS(nodes, :nodesJSON)").
|
||||
Param("nodesJSON", nodesJSON).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if isDone {
|
||||
err = this.Query(tx).
|
||||
Pk(keyId).
|
||||
Set("isDone", isDone).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 检查任务是否已经完成
|
||||
taskIsNotDone, err := this.Query(tx).
|
||||
Attr("taskId", taskId).
|
||||
Attr("isDone", false).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var taskIsDone = !taskIsNotDone
|
||||
var hasErrors = true
|
||||
if taskIsDone {
|
||||
// 已经完成,是否有错误
|
||||
hasErrors, err = this.Query(tx).
|
||||
Attr("taskId", taskId).
|
||||
Where("JSON_LENGTH(errors)>0").
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = SharedHTTPCacheTaskDAO.UpdateTaskStatus(tx, taskId, taskIsDone, !hasErrors)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindAllTaskKeys 查询某个任务下的所有Key
|
||||
func (this *HTTPCacheTaskKeyDAO) FindAllTaskKeys(tx *dbs.Tx, taskId int64) (result []*HTTPCacheTaskKey, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Attr("taskId", taskId).
|
||||
AscPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindDoingTaskKeys 查询要执行的任务
|
||||
func (this *HTTPCacheTaskKeyDAO) FindDoingTaskKeys(tx *dbs.Tx, nodeId int64, size int64) (result []*HTTPCacheTaskKey, err error) {
|
||||
// 集群ID
|
||||
clusterIds, err := SharedNodeDAO.FindEnabledAndOnNodeClusterIds(tx, nodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(clusterIds) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Attr("clusterId", clusterIds).
|
||||
Attr("isDone", false).
|
||||
Where("NOT JSON_CONTAINS_PATH(nodes, 'one', :jsonPath1)").
|
||||
Param("jsonPath1", "$.\""+types.String(nodeId)+"\"").
|
||||
Where("taskId IN (SELECT id FROM " + SharedHTTPCacheTaskDAO.Table + " WHERE state=1 AND isReady=1 AND isDone=0)").
|
||||
Limit(size).
|
||||
AscPk().
|
||||
Reuse(false).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ResetCacheKeysWithTaskId 重置任务下的Key状态
|
||||
func (this *HTTPCacheTaskKeyDAO) ResetCacheKeysWithTaskId(tx *dbs.Tx, taskId int64) error {
|
||||
return this.Query(tx).
|
||||
Attr("taskId", taskId).
|
||||
Set("isDone", false).
|
||||
Set("nodes", "{}").
|
||||
Set("errors", "{}").
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// CountUserTasksInDay 读取某个用户当前数量
|
||||
// day YYYYMMDD
|
||||
func (this *HTTPCacheTaskKeyDAO) CountUserTasksInDay(tx *dbs.Tx, userId int64, day string, taskType HTTPCacheTaskType) (int64, error) {
|
||||
if userId <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// 这里需要包含已删除的
|
||||
return this.Query(tx).
|
||||
Where("taskId IN (SELECT id FROM "+SharedHTTPCacheTaskDAO.Table+" WHERE userId=:userId AND day=:day AND type=:type)").
|
||||
Param("userId", userId).
|
||||
Param("day", day).
|
||||
Param("type", taskType).
|
||||
Count()
|
||||
}
|
||||
|
||||
// Clean 清理以往的任务
|
||||
func (this *HTTPCacheTaskKeyDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
if days <= 0 {
|
||||
days = 30
|
||||
}
|
||||
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days))
|
||||
_, err := this.Query(tx).
|
||||
Where("taskId IN (SELECT id FROM "+SharedHTTPCacheTaskDAO.Table+" WHERE day<=:day)").
|
||||
Param("day", day).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
54
internal/db/models/http_cache_task_key_dao_test.go
Normal file
54
internal/db/models/http_cache_task_key_dao_test.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package models_test
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHTTPCacheTaskKeyDAO_CreateKey(t *testing.T) {
|
||||
var dao = models.NewHTTPCacheTaskKeyDAO()
|
||||
var tx *dbs.Tx
|
||||
_, err := dao.CreateKey(tx, 1, "a", "purge", "key", 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestHTTPCacheTaskKeyDAO_UpdateKeyStatus(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var dao = models.NewHTTPCacheTaskKeyDAO()
|
||||
var tx *dbs.Tx
|
||||
var errString = "" // "this is error"
|
||||
err := dao.UpdateKeyStatus(tx, 3, 1, errString, []byte(`{"1":true}`))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestHTTPCacheTaskKeyDAO_CountUserTasksInDay(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var dao = models.NewHTTPCacheTaskKeyDAO()
|
||||
var tx *dbs.Tx
|
||||
{
|
||||
count, err := dao.CountUserTasksInDay(tx, 1, timeutil.Format("Ymd"), models.HTTPCacheTaskTypePurge)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("count:", count)
|
||||
}
|
||||
{
|
||||
count, err := dao.CountUserTasksInDay(tx, 1, timeutil.Format("Ymd"), models.HTTPCacheTaskTypeFetch)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("count:", count)
|
||||
}
|
||||
}
|
||||
32
internal/db/models/http_cache_task_key_model.go
Normal file
32
internal/db/models/http_cache_task_key_model.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPCacheTaskKey 缓存任务Key
|
||||
type HTTPCacheTaskKey struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
TaskId uint64 `field:"taskId"` // 任务ID
|
||||
Key string `field:"key"` // Key
|
||||
KeyType string `field:"keyType"` // Key类型:key|prefix
|
||||
Type string `field:"type"` // 操作类型
|
||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||
Nodes dbs.JSON `field:"nodes"` // 节点
|
||||
Errors dbs.JSON `field:"errors"` // 错误信息
|
||||
IsDone bool `field:"isDone"` // 是否已完成
|
||||
}
|
||||
|
||||
type HTTPCacheTaskKeyOperator struct {
|
||||
Id interface{} // ID
|
||||
TaskId interface{} // 任务ID
|
||||
Key interface{} // Key
|
||||
KeyType interface{} // Key类型:key|prefix
|
||||
Type interface{} // 操作类型
|
||||
ClusterId interface{} // 集群ID
|
||||
Nodes interface{} // 节点
|
||||
Errors interface{} // 错误信息
|
||||
IsDone interface{} // 是否已完成
|
||||
}
|
||||
|
||||
func NewHTTPCacheTaskKeyOperator() *HTTPCacheTaskKeyOperator {
|
||||
return &HTTPCacheTaskKeyOperator{}
|
||||
}
|
||||
20
internal/db/models/http_cache_task_key_model_ext.go
Normal file
20
internal/db/models/http_cache_task_key_model_ext.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package models
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
// DecodeNodes 解析已完成节点信息
|
||||
func (this *HTTPCacheTaskKey) DecodeNodes() map[string]bool {
|
||||
var result = map[string]bool{}
|
||||
var nodesJSON = this.Nodes
|
||||
if IsNull(nodesJSON) {
|
||||
return result
|
||||
}
|
||||
|
||||
err := json.Unmarshal(nodesJSON, &result)
|
||||
if err != nil {
|
||||
// ignore error
|
||||
return result
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
36
internal/db/models/http_cache_task_model.go
Normal file
36
internal/db/models/http_cache_task_model.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package models
|
||||
|
||||
// HTTPCacheTask 缓存相关任务
|
||||
type HTTPCacheTask struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
Type string `field:"type"` // 任务类型:purge|fetch
|
||||
KeyType string `field:"keyType"` // Key类型
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
DoneAt uint64 `field:"doneAt"` // 完成时间
|
||||
Day string `field:"day"` // 创建日期YYYYMMDD
|
||||
IsDone bool `field:"isDone"` // 是否已完成
|
||||
IsOk bool `field:"isOk"` // 是否完全成功
|
||||
IsReady uint8 `field:"isReady"` // 是否已准备好
|
||||
Description string `field:"description"` // 描述
|
||||
}
|
||||
|
||||
type HTTPCacheTaskOperator struct {
|
||||
Id interface{} // ID
|
||||
UserId interface{} // 用户ID
|
||||
Type interface{} // 任务类型:purge|fetch
|
||||
KeyType interface{} // Key类型
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
DoneAt interface{} // 完成时间
|
||||
Day interface{} // 创建日期YYYYMMDD
|
||||
IsDone interface{} // 是否已完成
|
||||
IsOk interface{} // 是否完全成功
|
||||
IsReady interface{} // 是否已准备好
|
||||
Description interface{} // 描述
|
||||
}
|
||||
|
||||
func NewHTTPCacheTaskOperator() *HTTPCacheTaskOperator {
|
||||
return &HTTPCacheTaskOperator{}
|
||||
}
|
||||
1
internal/db/models/http_cache_task_model_ext.go
Normal file
1
internal/db/models/http_cache_task_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package models
|
||||
@@ -117,7 +117,7 @@ func (this *HTTPFirewallPolicyDAO) FindAllEnabledFirewallPolicies(tx *dbs.Tx) (r
|
||||
|
||||
// CreateFirewallPolicy 创建策略
|
||||
func (this *HTTPFirewallPolicyDAO) CreateFirewallPolicy(tx *dbs.Tx, userId int64, serverGroupId int64, serverId int64, isOn bool, name string, description string, inboundJSON []byte, outboundJSON []byte) (int64, error) {
|
||||
op := NewHTTPFirewallPolicyOperator()
|
||||
var op = NewHTTPFirewallPolicyOperator()
|
||||
op.UserId = userId
|
||||
op.GroupId = serverGroupId
|
||||
op.ServerId = serverId
|
||||
@@ -131,14 +131,31 @@ func (this *HTTPFirewallPolicyDAO) CreateFirewallPolicy(tx *dbs.Tx, userId int64
|
||||
if len(outboundJSON) > 0 {
|
||||
op.Outbound = outboundJSON
|
||||
}
|
||||
op.UseLocalFirewall = true
|
||||
|
||||
{
|
||||
synFloodJSON, err := json.Marshal(firewallconfigs.DefaultSYNFloodConfig())
|
||||
if userId <= 0 && serverGroupId <=0 && serverId <= 0 {
|
||||
// synFlood
|
||||
var synFloodConfig = firewallconfigs.DefaultSYNFloodConfig()
|
||||
synFloodJSON, err := json.Marshal(synFloodConfig)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.SynFlood = synFloodJSON
|
||||
|
||||
// block options
|
||||
var blockOptions = firewallconfigs.DefaultHTTPFirewallBlockAction()
|
||||
blockOptionsJSON, err := json.Marshal(blockOptions)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.BlockOptions = blockOptionsJSON
|
||||
|
||||
// captcha options
|
||||
var captchaOptions = firewallconfigs.DefaultHTTPFirewallCaptchaAction()
|
||||
captchaOptionsJSON, err := json.Marshal(captchaOptions)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.CaptchaOptions = captchaOptionsJSON
|
||||
}
|
||||
|
||||
err := this.Save(tx, op)
|
||||
@@ -160,8 +177,8 @@ func (this *HTTPFirewallPolicyDAO) CreateDefaultFirewallPolicy(tx *dbs.Tx, name
|
||||
groupCodes = append(groupCodes, group.Code)
|
||||
}
|
||||
|
||||
inboundConfig := &firewallconfigs.HTTPFirewallInboundConfig{IsOn: true}
|
||||
outboundConfig := &firewallconfigs.HTTPFirewallOutboundConfig{IsOn: true}
|
||||
var inboundConfig = &firewallconfigs.HTTPFirewallInboundConfig{IsOn: true}
|
||||
var outboundConfig = &firewallconfigs.HTTPFirewallOutboundConfig{IsOn: true}
|
||||
if templatePolicy.Inbound != nil {
|
||||
for _, group := range templatePolicy.Inbound.Groups {
|
||||
isOn := lists.ContainsString(groupCodes, group.Code)
|
||||
@@ -207,6 +224,7 @@ func (this *HTTPFirewallPolicyDAO) CreateDefaultFirewallPolicy(tx *dbs.Tx, name
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return policyId, nil
|
||||
}
|
||||
|
||||
@@ -268,6 +286,7 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx,
|
||||
inboundJSON []byte,
|
||||
outboundJSON []byte,
|
||||
blockOptionsJSON []byte,
|
||||
captchaOptionsJSON []byte,
|
||||
mode firewallconfigs.FirewallMode,
|
||||
useLocalFirewall bool,
|
||||
synFloodConfig *firewallconfigs.SYNFloodConfig,
|
||||
@@ -275,7 +294,7 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx,
|
||||
if policyId <= 0 {
|
||||
return errors.New("invalid policyId")
|
||||
}
|
||||
op := NewHTTPFirewallPolicyOperator()
|
||||
var op = NewHTTPFirewallPolicyOperator()
|
||||
op.Id = policyId
|
||||
op.IsOn = isOn
|
||||
op.Name = name
|
||||
@@ -291,9 +310,12 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx,
|
||||
} else {
|
||||
op.Outbound = "null"
|
||||
}
|
||||
if len(blockOptionsJSON) > 0 {
|
||||
if IsNotNull(blockOptionsJSON) {
|
||||
op.BlockOptions = blockOptionsJSON
|
||||
}
|
||||
if IsNotNull(captchaOptionsJSON) {
|
||||
op.CaptchaOptions = captchaOptionsJSON
|
||||
}
|
||||
|
||||
if synFloodConfig != nil {
|
||||
synFloodConfigJSON, err := json.Marshal(synFloodConfig)
|
||||
@@ -456,7 +478,7 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
|
||||
|
||||
// Block动作配置
|
||||
if IsNotNull(policy.BlockOptions) {
|
||||
blockAction := &firewallconfigs.HTTPFirewallBlockAction{}
|
||||
var blockAction = &firewallconfigs.HTTPFirewallBlockAction{}
|
||||
err = json.Unmarshal(policy.BlockOptions, blockAction)
|
||||
if err != nil {
|
||||
return config, err
|
||||
@@ -464,6 +486,16 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
|
||||
config.BlockOptions = blockAction
|
||||
}
|
||||
|
||||
// Captcha动作配置
|
||||
if IsNotNull(policy.CaptchaOptions) {
|
||||
var captchaAction = &firewallconfigs.HTTPFirewallCaptchaAction{}
|
||||
err = json.Unmarshal(policy.CaptchaOptions, captchaAction)
|
||||
if err != nil {
|
||||
return config, err
|
||||
}
|
||||
config.CaptchaOptions = captchaAction
|
||||
}
|
||||
|
||||
// syn flood
|
||||
if IsNotNull(policy.SynFlood) {
|
||||
var synFloodConfig = &firewallconfigs.SYNFloodConfig{}
|
||||
@@ -526,6 +558,7 @@ func (this *HTTPFirewallPolicyDAO) CheckUserFirewallPolicy(tx *dbs.Tx, userId in
|
||||
}
|
||||
|
||||
// FindEnabledFirewallPolicyIdsWithIPListId 查找包含某个IPList的所有策略
|
||||
// TODO 改成通过 serverId 查询
|
||||
func (this *HTTPFirewallPolicyDAO) FindEnabledFirewallPolicyIdsWithIPListId(tx *dbs.Tx, ipListId int64) ([]int64, error) {
|
||||
ones, err := this.Query(tx).
|
||||
ResultPk().
|
||||
@@ -544,6 +577,7 @@ func (this *HTTPFirewallPolicyDAO) FindEnabledFirewallPolicyIdsWithIPListId(tx *
|
||||
}
|
||||
|
||||
// FindEnabledFirewallPolicyWithIPListId 查找使用某个IPList的策略
|
||||
// TODO 改成通过 serverId 查询
|
||||
func (this *HTTPFirewallPolicyDAO) FindEnabledFirewallPolicyWithIPListId(tx *dbs.Tx, ipListId int64) (*HTTPFirewallPolicy, error) {
|
||||
one, err := this.Query(tx).
|
||||
State(HTTPFirewallPolicyStateEnabled).
|
||||
|
||||
@@ -18,6 +18,7 @@ type HTTPFirewallPolicy struct {
|
||||
Inbound dbs.JSON `field:"inbound"` // 入站规则
|
||||
Outbound dbs.JSON `field:"outbound"` // 出站规则
|
||||
BlockOptions dbs.JSON `field:"blockOptions"` // BLOCK选项
|
||||
CaptchaOptions dbs.JSON `field:"captchaOptions"` // 验证码选项
|
||||
Mode string `field:"mode"` // 模式
|
||||
UseLocalFirewall uint8 `field:"useLocalFirewall"` // 是否自动使用本地防火墙
|
||||
SynFlood dbs.JSON `field:"synFlood"` // SynFlood防御设置
|
||||
@@ -39,6 +40,7 @@ type HTTPFirewallPolicyOperator struct {
|
||||
Inbound interface{} // 入站规则
|
||||
Outbound interface{} // 出站规则
|
||||
BlockOptions interface{} // BLOCK选项
|
||||
CaptchaOptions interface{} // 验证码选项
|
||||
Mode interface{} // 模式
|
||||
UseLocalFirewall interface{} // 是否自动使用本地防火墙
|
||||
SynFlood interface{} // SynFlood防御设置
|
||||
|
||||
@@ -3,6 +3,7 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
@@ -446,6 +447,16 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
||||
}
|
||||
}
|
||||
|
||||
// UAM
|
||||
if teaconst.IsPlus && IsNotNull(web.Uam) {
|
||||
var uamConfig = &serverconfigs.UAMConfig{}
|
||||
err = json.Unmarshal(web.Uam, uamConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.UAM = uamConfig
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, config)
|
||||
}
|
||||
@@ -1168,6 +1179,35 @@ func (this *HTTPWebDAO) FindWebRequestScripts(tx *dbs.Tx, webId int64) (*serverc
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// UpdateWebUAM 开启UAM
|
||||
func (this *HTTPWebDAO) UpdateWebUAM(tx *dbs.Tx, webId int64, uamConfig *serverconfigs.UAMConfig) error {
|
||||
if uamConfig == nil {
|
||||
return nil
|
||||
}
|
||||
configJSON, err := json.Marshal(uamConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = this.Query(tx).
|
||||
Pk(webId).
|
||||
Set("uam", configJSON).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, webId)
|
||||
}
|
||||
|
||||
// FindWebUAM 查找服务的UAM配置
|
||||
func (this *HTTPWebDAO) FindWebUAM(tx *dbs.Tx, webId int64) ([]byte, error) {
|
||||
return this.Query(tx).
|
||||
Pk(webId).
|
||||
Result("uam").
|
||||
FindJSONCol()
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *HTTPWebDAO) NotifyUpdate(tx *dbs.Tx, webId int64) error {
|
||||
// server
|
||||
|
||||
@@ -37,6 +37,7 @@ type HTTPWeb struct {
|
||||
MergeSlashes uint8 `field:"mergeSlashes"` // 是否合并路径中的斜杠
|
||||
RequestLimit dbs.JSON `field:"requestLimit"` // 请求限制
|
||||
RequestScripts dbs.JSON `field:"requestScripts"` // 请求脚本
|
||||
Uam dbs.JSON `field:"uam"` // UAM设置
|
||||
}
|
||||
|
||||
type HTTPWebOperator struct {
|
||||
@@ -73,6 +74,7 @@ type HTTPWebOperator struct {
|
||||
MergeSlashes interface{} // 是否合并路径中的斜杠
|
||||
RequestLimit interface{} // 请求限制
|
||||
RequestScripts interface{} // 请求脚本
|
||||
Uam interface{} // UAM设置
|
||||
}
|
||||
|
||||
func NewHTTPWebOperator() *HTTPWebOperator {
|
||||
|
||||
@@ -93,6 +93,71 @@ func (this *IPItemDAO) DisableIPItem(tx *dbs.Tx, id int64) error {
|
||||
return this.NotifyUpdate(tx, id)
|
||||
}
|
||||
|
||||
// DisableIPItemsWithIP 禁用某个IP相关条目
|
||||
func (this *IPItemDAO) DisableIPItemsWithIP(tx *dbs.Tx, ipFrom string, ipTo string, userId int64, listId int64) error {
|
||||
if len(ipFrom) == 0 {
|
||||
return errors.New("invalid 'ipFrom'")
|
||||
}
|
||||
|
||||
var query = this.Query(tx).
|
||||
Result("id", "listId").
|
||||
Attr("ipFrom", ipFrom).
|
||||
Attr("ipTo", ipTo).
|
||||
State(IPItemStateEnabled)
|
||||
|
||||
if listId > 0 {
|
||||
if userId > 0 {
|
||||
err := SharedIPListDAO.CheckUserIPList(tx, userId, listId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
query.Attr("listId", listId)
|
||||
}
|
||||
|
||||
ones, err := query.FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var itemIds = []int64{}
|
||||
for _, one := range ones {
|
||||
var item = one.(*IPItem)
|
||||
var itemId = int64(item.Id)
|
||||
var itemListId = int64(item.ListId)
|
||||
if itemListId != listId && userId > 0 {
|
||||
err = SharedIPListDAO.CheckUserIPList(tx, userId, itemListId)
|
||||
if err != nil {
|
||||
// ignore error
|
||||
continue
|
||||
}
|
||||
}
|
||||
itemIds = append(itemIds, itemId)
|
||||
}
|
||||
|
||||
for _, itemId := range itemIds {
|
||||
version, err := SharedIPListDAO.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Pk(itemId).
|
||||
Set("state", IPItemStateDisabled).
|
||||
Set("version", version).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(itemIds) > 0 {
|
||||
return this.NotifyUpdate(tx, itemIds[len(itemIds)-1])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DisableIPItemsWithListId 禁用某个IP名单内的所有IP
|
||||
func (this *IPItemDAO) DisableIPItemsWithListId(tx *dbs.Tx, listId int64) error {
|
||||
for {
|
||||
@@ -142,14 +207,35 @@ func (this *IPItemDAO) FindEnabledIPItem(tx *dbs.Tx, id int64) (*IPItem, error)
|
||||
|
||||
// DeleteOldItem 根据IP删除以前的旧记录
|
||||
func (this *IPItemDAO) DeleteOldItem(tx *dbs.Tx, listId int64, ipFrom string, ipTo string) error {
|
||||
_, err := this.Query(tx).
|
||||
ones, err := this.Query(tx).
|
||||
ResultPk().
|
||||
UseIndex("ipFrom").
|
||||
Attr("listId", listId).
|
||||
Attr("ipFrom", ipFrom).
|
||||
Attr("ipTo", ipTo).
|
||||
Delete()
|
||||
// 这里不通知更新
|
||||
return err
|
||||
Set("state", IPItemStateEnabled).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, one := range ones {
|
||||
var itemId = int64(one.(*IPItem).Id)
|
||||
version, err := SharedIPListDAO.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = this.Query(tx).
|
||||
Pk(itemId).
|
||||
Set("version", version).
|
||||
Set("state", IPItemStateDisabled).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateIPItem 创建IP
|
||||
@@ -202,6 +288,8 @@ func (this *IPItemDAO) CreateIPItem(tx *dbs.Tx,
|
||||
}
|
||||
|
||||
op.State = IPItemStateEnabled
|
||||
op.UpdatedAt = time.Now().Unix()
|
||||
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -453,7 +541,7 @@ func (this *IPItemDAO) UpdateItemsRead(tx *dbs.Tx) error {
|
||||
func (this *IPItemDAO) CleanExpiredIPItems(tx *dbs.Tx) error {
|
||||
// 删除 N 天之前过期的数据
|
||||
_, err := this.Query(tx).
|
||||
Where("expiredAt<=:timestamp").
|
||||
Where("(createdAt<=:timestamp AND updatedAt<=:timestamp)").
|
||||
State(IPItemStateDisabled).
|
||||
Param("timestamp", time.Now().Unix()-7*86400). // N 天之前过期的
|
||||
Limit(10000). // 限制条数,防止数量过多导致超时
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package models
|
||||
package models_test
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -14,7 +15,7 @@ func TestIPItemDAO_NotifyClustersUpdate(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
err := SharedIPItemDAO.NotifyUpdate(tx, 28)
|
||||
err := models.SharedIPItemDAO.NotifyUpdate(tx, 28)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -25,7 +26,7 @@ func TestIPItemDAO_DisableIPItemsWithListId(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
err := SharedIPItemDAO.DisableIPItemsWithListId(tx, 67)
|
||||
err := models.SharedIPItemDAO.DisableIPItemsWithListId(tx, 67)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -36,7 +37,7 @@ func TestIPItemDAO_ListIPItemsAfterVersion(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
_, err := SharedIPItemDAO.ListIPItemsAfterVersion(tx, 0, 100)
|
||||
_, err := models.SharedIPItemDAO.ListIPItemsAfterVersion(tx, 0, 100)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -47,10 +48,10 @@ func TestIPItemDAO_CreateManyIPs(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
var dao = NewIPItemDAO()
|
||||
var dao = models.NewIPItemDAO()
|
||||
var n = 10
|
||||
for i := 0; i < n; i++ {
|
||||
itemId, err := dao.CreateIPItem(tx, firewallconfigs.GlobalListId, "192."+types.String(rands.Int(0, 255))+"."+types.String(rands.Int(0, 255))+"."+types.String(rands.Int(0, 255)), "", time.Now().Unix()+86400, "test", IPItemTypeIPv4, "warning", 0, 0, 0, 0, 0, 0, 0)
|
||||
itemId, err := dao.CreateIPItem(tx, firewallconfigs.GlobalListId, "192."+types.String(rands.Int(0, 255))+"."+types.String(rands.Int(0, 255))+"."+types.String(rands.Int(0, 255)), "", time.Now().Unix()+86400, "test", models.IPItemTypeIPv4, "warning", 0, 0, 0, 0, 0, 0, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -62,3 +63,14 @@ func TestIPItemDAO_CreateManyIPs(t *testing.T) {
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestIPItemDAO_DisableIPItemsWithIP(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
err := models.SharedIPItemDAO.DisableIPItemsWithIP(tx, "192.168.1.100", "", 0, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
@@ -138,10 +138,11 @@ func (this *IPListDAO) FindIPListCacheable(tx *dbs.Tx, listId int64) (*IPList, e
|
||||
}
|
||||
|
||||
// CreateIPList 创建名单
|
||||
func (this *IPListDAO) CreateIPList(tx *dbs.Tx, userId int64, listType ipconfigs.IPListType, name string, code string, timeoutJSON []byte, description string, isPublic bool, isGlobal bool) (int64, error) {
|
||||
op := NewIPListOperator()
|
||||
func (this *IPListDAO) CreateIPList(tx *dbs.Tx, userId int64, serverId int64, listType ipconfigs.IPListType, name string, code string, timeoutJSON []byte, description string, isPublic bool, isGlobal bool) (int64, error) {
|
||||
var op = NewIPListOperator()
|
||||
op.IsOn = true
|
||||
op.UserId = userId
|
||||
op.ServerId = serverId
|
||||
op.State = IPListStateEnabled
|
||||
op.Type = listType
|
||||
op.Name = name
|
||||
@@ -189,26 +190,25 @@ func (this *IPListDAO) CheckUserIPList(tx *dbs.Tx, userId int64, listId int64) e
|
||||
return ErrNotFound
|
||||
}
|
||||
|
||||
ok, err := this.Query(tx).
|
||||
// 获取名单信息
|
||||
listOne, err := this.Query(tx).
|
||||
Pk(listId).
|
||||
Attr("userId", userId).
|
||||
Exist()
|
||||
Result("userId", "serverId").
|
||||
Find()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ok {
|
||||
if listOne == nil {
|
||||
return ErrNotFound
|
||||
}
|
||||
var list = listOne.(*IPList)
|
||||
if int64(list.UserId) == userId {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 检查是否被用户的服务所使用
|
||||
policyIds, err := SharedHTTPFirewallPolicyDAO.FindEnabledFirewallPolicyIdsWithIPListId(tx, listId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, policyId := range policyIds {
|
||||
if SharedHTTPFirewallPolicyDAO.CheckUserFirewallPolicy(tx, userId, policyId) == nil {
|
||||
return nil
|
||||
}
|
||||
var serverId = int64(list.ServerId)
|
||||
if serverId > 0 {
|
||||
return SharedServerDAO.CheckUserServer(tx, userId, serverId)
|
||||
}
|
||||
|
||||
return ErrNotFound
|
||||
|
||||
@@ -20,6 +20,39 @@ func TestIPListDAO_IncreaseVersion(t *testing.T) {
|
||||
t.Log("version:", version)
|
||||
}
|
||||
|
||||
func TestIPListDAO_CheckUserIPList(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
|
||||
{
|
||||
err := NewIPListDAO().CheckUserIPList(tx, 1, 100)
|
||||
if err == ErrNotFound {
|
||||
t.Log("not found")
|
||||
} else {
|
||||
t.Log(err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
err := NewIPListDAO().CheckUserIPList(tx, 1, 85)
|
||||
if err == ErrNotFound {
|
||||
t.Log("not found")
|
||||
} else {
|
||||
t.Log(err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
err := NewIPListDAO().CheckUserIPList(tx, 1, 17)
|
||||
if err == ErrNotFound {
|
||||
t.Log("not found")
|
||||
} else {
|
||||
t.Log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIPListDAO_IncreaseVersion(b *testing.B) {
|
||||
runtime.GOMAXPROCS(1)
|
||||
|
||||
@@ -32,3 +65,4 @@ func BenchmarkIPListDAO_IncreaseVersion(b *testing.B) {
|
||||
_, _ = dao.IncreaseVersion(tx)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ type IPList struct {
|
||||
Type string `field:"type"` // 类型
|
||||
AdminId uint32 `field:"adminId"` // 用户ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
ServerId uint64 `field:"serverId"` // 服务ID
|
||||
Name string `field:"name"` // 列表名
|
||||
Code string `field:"code"` // 代号
|
||||
State uint8 `field:"state"` // 状态
|
||||
@@ -26,6 +27,7 @@ type IPListOperator struct {
|
||||
Type interface{} // 类型
|
||||
AdminId interface{} // 用户ID
|
||||
UserId interface{} // 用户ID
|
||||
ServerId interface{} // 服务ID
|
||||
Name interface{} // 列表名
|
||||
Code interface{} // 代号
|
||||
State interface{} // 状态
|
||||
|
||||
@@ -90,9 +90,7 @@ func (this *MetricStatDAO) CreateStat(tx *dbs.Tx, hash string, clusterId int64,
|
||||
"value": value,
|
||||
})
|
||||
if err != nil {
|
||||
// 忽略 Error 1213: Deadlock found 错误
|
||||
mysqlErr, ok := err.(*mysql.MySQLError)
|
||||
if ok && mysqlErr.Number == 1213 {
|
||||
if this.canIgnore(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
@@ -135,6 +133,9 @@ func (this *MetricStatDAO) DeleteNodeItemStats(tx *dbs.Tx, nodeId int64, serverI
|
||||
Attr("itemId", itemId).
|
||||
Attr("time", time).
|
||||
Delete()
|
||||
if this.canIgnore(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -690,7 +691,6 @@ func (this *MetricStatDAO) Clean(tx *dbs.Tx) error {
|
||||
Table(table).
|
||||
Attr("itemId", item.Id).
|
||||
Lte("createdDay", expiresDay).
|
||||
UseIndex("createdDay").
|
||||
Limit(10_000). // 一次性不要删除太多,防止阻塞其他操作
|
||||
Delete()
|
||||
return err
|
||||
@@ -751,3 +751,18 @@ func (this *MetricStatDAO) mergeStats(stats []*MetricStat) (result []*MetricStat
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// 检查错误是否可以忽略
|
||||
func (this *MetricStatDAO) canIgnore(err error) bool {
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
// 忽略 Error 1213: Deadlock found 错误
|
||||
mysqlErr, ok := err.(*mysql.MySQLError)
|
||||
if ok && mysqlErr.Number == 1213 {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/go-sql-driver/mysql"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -55,7 +56,7 @@ func init() {
|
||||
|
||||
// UpdateSum 更新统计数据
|
||||
func (this *MetricSumStatDAO) UpdateSum(tx *dbs.Tx, clusterId int64, nodeId int64, serverId int64, time string, itemId int64, version int32, count int64, total float32) error {
|
||||
return this.Query(tx).
|
||||
err := this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
InsertOrUpdateQuickly(maps.Map{
|
||||
"clusterId": clusterId,
|
||||
@@ -71,6 +72,10 @@ func (this *MetricSumStatDAO) UpdateSum(tx *dbs.Tx, clusterId int64, nodeId int6
|
||||
"count": count,
|
||||
"total": total,
|
||||
})
|
||||
if this.canIgnore(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// FindNodeServerSum 查找某个服务在某个节点上的统计数据
|
||||
@@ -232,7 +237,6 @@ func (this *MetricSumStatDAO) Clean(tx *dbs.Tx) error {
|
||||
Attr("itemId", item.Id).
|
||||
Where("(createdDay IS NULL OR createdDay<:day)").
|
||||
Param("day", expiresDay).
|
||||
UseIndex("createdDay").
|
||||
Limit(10_000). // 一次性不要删除太多,防止阻塞其他操作
|
||||
Delete()
|
||||
return err
|
||||
@@ -277,3 +281,18 @@ func (this *MetricSumStatDAO) runBatch(f func(table string, locker *sync.Mutex)
|
||||
wg.Wait()
|
||||
return resultErr
|
||||
}
|
||||
|
||||
// 检查错误是否可以忽略
|
||||
func (this *MetricSumStatDAO) canIgnore(err error) bool {
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
// 忽略 Error 1213: Deadlock found 错误
|
||||
mysqlErr, ok := err.(*mysql.MySQLError)
|
||||
if ok && mysqlErr.Number == 1213 {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -47,12 +47,17 @@ func (this *MonitorNodeDAO) EnableMonitorNode(tx *dbs.Tx, id int64) error {
|
||||
}
|
||||
|
||||
// DisableMonitorNode 禁用条目
|
||||
func (this *MonitorNodeDAO) DisableMonitorNode(tx *dbs.Tx, id int64) error {
|
||||
func (this *MonitorNodeDAO) DisableMonitorNode(tx *dbs.Tx, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Pk(nodeId).
|
||||
Set("state", MonitorNodeStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除运行日志
|
||||
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleMonitor, nodeId)
|
||||
}
|
||||
|
||||
// FindEnabledMonitorNode 查找启用中的条目
|
||||
|
||||
@@ -214,7 +214,7 @@ func (this *NSRouteDAO) FindAllEnabledRoutes(tx *dbs.Tx, clusterId int64, domain
|
||||
State(NSRouteStateEnabled).
|
||||
Slice(&result).
|
||||
Desc("order").
|
||||
DescPk()
|
||||
AscPk()
|
||||
if clusterId > 0 {
|
||||
query.Attr("clusterId", clusterId)
|
||||
} else {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -141,10 +142,11 @@ func (this *NodeClusterDAO) CreateCluster(tx *dbs.Tx, adminId int64, name string
|
||||
// DNS设置
|
||||
op.DnsDomainId = dnsDomainId
|
||||
op.DnsName = dnsName
|
||||
dnsConfig := &dnsconfigs.ClusterDNSConfig{
|
||||
var dnsConfig = &dnsconfigs.ClusterDNSConfig{
|
||||
NodesAutoSync: true,
|
||||
ServersAutoSync: true,
|
||||
CNameRecords: []string{},
|
||||
CNameAsDomain: true,
|
||||
TTL: 0,
|
||||
}
|
||||
dnsJSON, err := json.Marshal(dnsConfig)
|
||||
@@ -180,7 +182,7 @@ func (this *NodeClusterDAO) CreateCluster(tx *dbs.Tx, adminId int64, name string
|
||||
}
|
||||
|
||||
// UpdateCluster 修改集群
|
||||
func (this *NodeClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name string, grantId int64, installDir string, timezone string, nodeMaxThreads int32, nodeTCPMaxConnections int32, autoOpenPorts bool) error {
|
||||
func (this *NodeClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name string, grantId int64, installDir string, timezone string, nodeMaxThreads int32, autoOpenPorts bool) error {
|
||||
if clusterId <= 0 {
|
||||
return errors.New("invalid clusterId")
|
||||
}
|
||||
@@ -195,11 +197,6 @@ func (this *NodeClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name stri
|
||||
nodeMaxThreads = 0
|
||||
}
|
||||
op.NodeMaxThreads = nodeMaxThreads
|
||||
|
||||
if nodeTCPMaxConnections < 0 {
|
||||
nodeTCPMaxConnections = 0
|
||||
}
|
||||
op.NodeTCPMaxConnections = nodeTCPMaxConnections
|
||||
op.AutoOpenPorts = autoOpenPorts
|
||||
|
||||
err := this.Save(tx, op)
|
||||
@@ -467,7 +464,7 @@ func (this *NodeClusterDAO) ExistClusterDNSName(tx *dbs.Tx, dnsName string, excl
|
||||
}
|
||||
|
||||
// UpdateClusterDNS 修改集群DNS相关信息
|
||||
func (this *NodeClusterDAO) UpdateClusterDNS(tx *dbs.Tx, clusterId int64, dnsName string, dnsDomainId int64, nodesAutoSync bool, serversAutoSync bool, cnameRecords []string, ttl int32) error {
|
||||
func (this *NodeClusterDAO) UpdateClusterDNS(tx *dbs.Tx, clusterId int64, dnsName string, dnsDomainId int64, nodesAutoSync bool, serversAutoSync bool, cnameRecords []string, ttl int32, cnameAsDomain bool) error {
|
||||
if clusterId <= 0 {
|
||||
return errors.New("invalid clusterId")
|
||||
}
|
||||
@@ -507,6 +504,7 @@ func (this *NodeClusterDAO) UpdateClusterDNS(tx *dbs.Tx, clusterId int64, dnsNam
|
||||
ServersAutoSync: serversAutoSync,
|
||||
CNameRecords: cnameRecords,
|
||||
TTL: ttl,
|
||||
CNameAsDomain: cnameAsDomain,
|
||||
}
|
||||
dnsJSON, err := json.Marshal(dnsConfig)
|
||||
if err != nil {
|
||||
@@ -922,7 +920,7 @@ func (this *NodeClusterDAO) FindClusterBasicInfo(tx *dbs.Tx, clusterId int64, ca
|
||||
cluster, err := this.Query(tx).
|
||||
Pk(clusterId).
|
||||
State(NodeClusterStateEnabled).
|
||||
Result("timeZone", "nodeMaxThreads", "nodeTCPMaxConnections", "cachePolicyId", "httpFirewallPolicyId", "autoOpenPorts", "webp", "isOn").
|
||||
Result("id", "timeZone", "nodeMaxThreads", "cachePolicyId", "httpFirewallPolicyId", "autoOpenPorts", "webp", "uam", "isOn", "ddosProtection").
|
||||
Find()
|
||||
if err != nil || cluster == nil {
|
||||
return nil, err
|
||||
@@ -992,6 +990,104 @@ func (this *NodeClusterDAO) FindClusterWebPPolicy(tx *dbs.Tx, clusterId int64, c
|
||||
return policy, nil
|
||||
}
|
||||
|
||||
// UpdateClusterUAMPolicy 修改UAM设置
|
||||
func (this *NodeClusterDAO) UpdateClusterUAMPolicy(tx *dbs.Tx, clusterId int64, uamPolicy *nodeconfigs.UAMPolicy) error {
|
||||
if uamPolicy == nil {
|
||||
err := this.Query(tx).
|
||||
Pk(clusterId).
|
||||
Set("uam", dbs.SQL("null")).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, clusterId)
|
||||
}
|
||||
|
||||
uamPolicyJSON, err := json.Marshal(uamPolicy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = this.Query(tx).
|
||||
Pk(clusterId).
|
||||
Set("uam", uamPolicyJSON).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, clusterId)
|
||||
}
|
||||
|
||||
// FindClusterUAMPolicy 查询设置
|
||||
func (this *NodeClusterDAO) FindClusterUAMPolicy(tx *dbs.Tx, clusterId int64, cacheMap *utils.CacheMap) (*nodeconfigs.UAMPolicy, error) {
|
||||
var cacheKey = this.Table + ":FindClusterUAMPolicy:" + types.String(clusterId)
|
||||
if cacheMap != nil {
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return cache.(*nodeconfigs.UAMPolicy), nil
|
||||
}
|
||||
}
|
||||
|
||||
uamJSON, err := this.Query(tx).
|
||||
Pk(clusterId).
|
||||
Result("uam").
|
||||
FindJSONCol()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if IsNull(uamJSON) {
|
||||
return nodeconfigs.DefaultUAMPolicy, nil
|
||||
}
|
||||
|
||||
var policy = &nodeconfigs.UAMPolicy{}
|
||||
err = json.Unmarshal(uamJSON, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return policy, nil
|
||||
}
|
||||
|
||||
// FindClusterDDoSProtection 获取集群的DDoS设置
|
||||
func (this *NodeClusterDAO) FindClusterDDoSProtection(tx *dbs.Tx, clusterId int64) (*ddosconfigs.ProtectionConfig, error) {
|
||||
one, err := this.Query(tx).
|
||||
Result("ddosProtection").
|
||||
Pk(clusterId).
|
||||
Find()
|
||||
if one == nil || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return one.(*NodeCluster).DecodeDDoSProtection(), nil
|
||||
}
|
||||
|
||||
// UpdateClusterDDoSProtection 设置集群的DDOS设置
|
||||
func (this *NodeClusterDAO) UpdateClusterDDoSProtection(tx *dbs.Tx, clusterId int64, ddosProtection *ddosconfigs.ProtectionConfig) error {
|
||||
if clusterId <= 0 {
|
||||
return ErrNotFound
|
||||
}
|
||||
|
||||
var op = NewNodeClusterOperator()
|
||||
op.Id = clusterId
|
||||
|
||||
if ddosProtection == nil {
|
||||
op.DdosProtection = "{}"
|
||||
} else {
|
||||
ddosProtectionJSON, err := json.Marshal(ddosProtection)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.DdosProtection = ddosProtectionJSON
|
||||
}
|
||||
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeDDosProtectionChanged)
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *NodeClusterDAO) NotifyUpdate(tx *dbs.Tx, clusterId int64) error {
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeConfigChanged)
|
||||
|
||||
@@ -4,69 +4,71 @@ import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// NodeCluster 节点集群
|
||||
type NodeCluster struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
UseAllAPINodes uint8 `field:"useAllAPINodes"` // 是否使用所有API节点
|
||||
ApiNodes dbs.JSON `field:"apiNodes"` // 使用的API节点
|
||||
InstallDir string `field:"installDir"` // 安装目录
|
||||
Order uint32 `field:"order"` // 排序
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
GrantId uint32 `field:"grantId"` // 默认认证方式
|
||||
State uint8 `field:"state"` // 状态
|
||||
AutoRegister uint8 `field:"autoRegister"` // 是否开启自动注册
|
||||
UniqueId string `field:"uniqueId"` // 唯一ID
|
||||
Secret string `field:"secret"` // 密钥
|
||||
HealthCheck dbs.JSON `field:"healthCheck"` // 健康检查
|
||||
DnsName string `field:"dnsName"` // DNS名称
|
||||
DnsDomainId uint32 `field:"dnsDomainId"` // 域名ID
|
||||
Dns dbs.JSON `field:"dns"` // DNS配置
|
||||
Toa dbs.JSON `field:"toa"` // TOA配置
|
||||
CachePolicyId uint32 `field:"cachePolicyId"` // 缓存策略ID
|
||||
HttpFirewallPolicyId uint32 `field:"httpFirewallPolicyId"` // WAF策略ID
|
||||
AccessLog dbs.JSON `field:"accessLog"` // 访问日志设置
|
||||
SystemServices dbs.JSON `field:"systemServices"` // 系统服务设置
|
||||
TimeZone string `field:"timeZone"` // 时区
|
||||
NodeMaxThreads uint32 `field:"nodeMaxThreads"` // 节点最大线程数
|
||||
NodeTCPMaxConnections uint32 `field:"nodeTCPMaxConnections"` // TCP最大连接数
|
||||
AutoOpenPorts uint8 `field:"autoOpenPorts"` // 是否自动尝试开放端口
|
||||
IsPinned bool `field:"isPinned"` // 是否置顶
|
||||
Webp dbs.JSON `field:"webp"` // WebP设置
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
UseAllAPINodes uint8 `field:"useAllAPINodes"` // 是否使用所有API节点
|
||||
ApiNodes dbs.JSON `field:"apiNodes"` // 使用的API节点
|
||||
InstallDir string `field:"installDir"` // 安装目录
|
||||
Order uint32 `field:"order"` // 排序
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
GrantId uint32 `field:"grantId"` // 默认认证方式
|
||||
State uint8 `field:"state"` // 状态
|
||||
AutoRegister uint8 `field:"autoRegister"` // 是否开启自动注册
|
||||
UniqueId string `field:"uniqueId"` // 唯一ID
|
||||
Secret string `field:"secret"` // 密钥
|
||||
HealthCheck dbs.JSON `field:"healthCheck"` // 健康检查
|
||||
DnsName string `field:"dnsName"` // DNS名称
|
||||
DnsDomainId uint32 `field:"dnsDomainId"` // 域名ID
|
||||
Dns dbs.JSON `field:"dns"` // DNS配置
|
||||
Toa dbs.JSON `field:"toa"` // TOA配置
|
||||
CachePolicyId uint32 `field:"cachePolicyId"` // 缓存策略ID
|
||||
HttpFirewallPolicyId uint32 `field:"httpFirewallPolicyId"` // WAF策略ID
|
||||
AccessLog dbs.JSON `field:"accessLog"` // 访问日志设置
|
||||
SystemServices dbs.JSON `field:"systemServices"` // 系统服务设置
|
||||
TimeZone string `field:"timeZone"` // 时区
|
||||
NodeMaxThreads uint32 `field:"nodeMaxThreads"` // 节点最大线程数
|
||||
DdosProtection dbs.JSON `field:"ddosProtection"` // DDOS端口
|
||||
AutoOpenPorts uint8 `field:"autoOpenPorts"` // 是否自动尝试开放端口
|
||||
IsPinned bool `field:"isPinned"` // 是否置顶
|
||||
Webp dbs.JSON `field:"webp"` // WebP设置
|
||||
Uam dbs.JSON `field:"uam"` // UAM设置
|
||||
}
|
||||
|
||||
type NodeClusterOperator struct {
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
UseAllAPINodes interface{} // 是否使用所有API节点
|
||||
ApiNodes interface{} // 使用的API节点
|
||||
InstallDir interface{} // 安装目录
|
||||
Order interface{} // 排序
|
||||
CreatedAt interface{} // 创建时间
|
||||
GrantId interface{} // 默认认证方式
|
||||
State interface{} // 状态
|
||||
AutoRegister interface{} // 是否开启自动注册
|
||||
UniqueId interface{} // 唯一ID
|
||||
Secret interface{} // 密钥
|
||||
HealthCheck interface{} // 健康检查
|
||||
DnsName interface{} // DNS名称
|
||||
DnsDomainId interface{} // 域名ID
|
||||
Dns interface{} // DNS配置
|
||||
Toa interface{} // TOA配置
|
||||
CachePolicyId interface{} // 缓存策略ID
|
||||
HttpFirewallPolicyId interface{} // WAF策略ID
|
||||
AccessLog interface{} // 访问日志设置
|
||||
SystemServices interface{} // 系统服务设置
|
||||
TimeZone interface{} // 时区
|
||||
NodeMaxThreads interface{} // 节点最大线程数
|
||||
NodeTCPMaxConnections interface{} // TCP最大连接数
|
||||
AutoOpenPorts interface{} // 是否自动尝试开放端口
|
||||
IsPinned interface{} // 是否置顶
|
||||
Webp interface{} // WebP设置
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
UseAllAPINodes interface{} // 是否使用所有API节点
|
||||
ApiNodes interface{} // 使用的API节点
|
||||
InstallDir interface{} // 安装目录
|
||||
Order interface{} // 排序
|
||||
CreatedAt interface{} // 创建时间
|
||||
GrantId interface{} // 默认认证方式
|
||||
State interface{} // 状态
|
||||
AutoRegister interface{} // 是否开启自动注册
|
||||
UniqueId interface{} // 唯一ID
|
||||
Secret interface{} // 密钥
|
||||
HealthCheck interface{} // 健康检查
|
||||
DnsName interface{} // DNS名称
|
||||
DnsDomainId interface{} // 域名ID
|
||||
Dns interface{} // DNS配置
|
||||
Toa interface{} // TOA配置
|
||||
CachePolicyId interface{} // 缓存策略ID
|
||||
HttpFirewallPolicyId interface{} // WAF策略ID
|
||||
AccessLog interface{} // 访问日志设置
|
||||
SystemServices interface{} // 系统服务设置
|
||||
TimeZone interface{} // 时区
|
||||
NodeMaxThreads interface{} // 节点最大线程数
|
||||
DdosProtection interface{} // DDOS端口
|
||||
AutoOpenPorts interface{} // 是否自动尝试开放端口
|
||||
IsPinned interface{} // 是否置顶
|
||||
Webp interface{} // WebP设置
|
||||
Uam interface{} // UAM设置
|
||||
}
|
||||
|
||||
func NewNodeClusterOperator() *NodeClusterOperator {
|
||||
|
||||
@@ -3,6 +3,7 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
|
||||
)
|
||||
|
||||
// DecodeDNSConfig 解析DNS配置
|
||||
@@ -12,12 +13,38 @@ func (this *NodeCluster) DecodeDNSConfig() (*dnsconfigs.ClusterDNSConfig, error)
|
||||
return &dnsconfigs.ClusterDNSConfig{
|
||||
NodesAutoSync: false,
|
||||
ServersAutoSync: false,
|
||||
CNameAsDomain: true,
|
||||
}, nil
|
||||
}
|
||||
dnsConfig := &dnsconfigs.ClusterDNSConfig{}
|
||||
var dnsConfig = &dnsconfigs.ClusterDNSConfig{
|
||||
CNameAsDomain: true,
|
||||
}
|
||||
err := json.Unmarshal(this.Dns, &dnsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dnsConfig, nil
|
||||
}
|
||||
|
||||
// DecodeDDoSProtection 解析DDOS Protection设置
|
||||
func (this *NodeCluster) DecodeDDoSProtection() *ddosconfigs.ProtectionConfig {
|
||||
if IsNull(this.DdosProtection) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var result = &ddosconfigs.ProtectionConfig{}
|
||||
err := json.Unmarshal(this.DdosProtection, &result)
|
||||
if err != nil {
|
||||
// ignore err
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// HasDDoSProtection 检查是否有DDOS设置
|
||||
func (this *NodeCluster) HasDDoSProtection() bool {
|
||||
var config = this.DecodeDDoSProtection()
|
||||
if config != nil {
|
||||
return config.IsOn()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@@ -99,7 +100,8 @@ func (this *NodeDAO) DisableNode(tx *dbs.Tx, nodeId int64) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
// 删除运行日志
|
||||
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleNode, nodeId)
|
||||
}
|
||||
|
||||
// FindEnabledNode 查找启用中的条目
|
||||
@@ -360,6 +362,8 @@ func (this *NodeDAO) ListEnabledNodesMatch(tx *dbs.Tx,
|
||||
// 分组
|
||||
if groupId > 0 {
|
||||
query.Attr("groupId", groupId)
|
||||
} else if groupId < 0 {
|
||||
query.Attr("groupId", 0)
|
||||
}
|
||||
|
||||
// 区域
|
||||
@@ -567,12 +571,12 @@ func (this *NodeDAO) FindEnabledNodeClusterIds(tx *dbs.Tx, nodeId int64) (result
|
||||
result = append(result, clusterId)
|
||||
}
|
||||
|
||||
for _, clusterId := range one.(*Node).DecodeSecondaryClusterIds() {
|
||||
if lists.ContainsInt64(result, clusterId) {
|
||||
for _, secondaryClusterId := range one.(*Node).DecodeSecondaryClusterIds() {
|
||||
if lists.ContainsInt64(result, secondaryClusterId) {
|
||||
continue
|
||||
}
|
||||
|
||||
result = append(result, clusterId)
|
||||
result = append(result, secondaryClusterId)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -661,16 +665,51 @@ func (this *NodeDAO) FindAllNodeIdsMatch(tx *dbs.Tx, clusterId int64, includeSec
|
||||
}
|
||||
|
||||
// FindAllEnabledNodesWithClusterId 获取一个集群的所有节点
|
||||
func (this *NodeDAO) FindAllEnabledNodesWithClusterId(tx *dbs.Tx, clusterId int64) (result []*Node, err error) {
|
||||
_, err = this.Query(tx).
|
||||
func (this *NodeDAO) FindAllEnabledNodesWithClusterId(tx *dbs.Tx, clusterId int64, includeSecondary bool) (result []*Node, err error) {
|
||||
var query = this.Query(tx)
|
||||
|
||||
if includeSecondary {
|
||||
query.Where("(clusterId=:primaryClusterId OR JSON_CONTAINS(secondaryClusterIds, :primaryClusterIdString))").
|
||||
Param("primaryClusterId", clusterId).
|
||||
Param("primaryClusterIdString", types.String(clusterId))
|
||||
} else {
|
||||
query.Attr("clusterId", clusterId)
|
||||
}
|
||||
|
||||
_, err = query.
|
||||
State(NodeStateEnabled).
|
||||
Attr("clusterId", clusterId).
|
||||
DescPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// FindEnabledAndOnNodeIdsWithClusterId 查找某个集群下的所有启用的节点IDs
|
||||
func (this *NodeDAO) FindEnabledAndOnNodeIdsWithClusterId(tx *dbs.Tx, clusterId int64, includeSecondary bool) ([]int64, error) {
|
||||
var query = this.Query(tx)
|
||||
if includeSecondary {
|
||||
query.Where("(clusterId=:primaryClusterId OR JSON_CONTAINS(secondaryClusterIds, :primaryClusterIdString))").
|
||||
Param("primaryClusterId", clusterId).
|
||||
Param("primaryClusterIdString", types.String(clusterId))
|
||||
} else {
|
||||
query.Attr("clusterId", clusterId)
|
||||
}
|
||||
ones, err := query.
|
||||
Attr("isOn", true).
|
||||
State(NodeStateEnabled).
|
||||
ResultPk().
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var result = []int64{}
|
||||
for _, one := range ones {
|
||||
result = append(result, int64(one.(*Node).Id))
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// FindAllEnabledNodeIdsWithClusterId 获取一个集群的所有节点Ids
|
||||
func (this *NodeDAO) FindAllEnabledNodeIdsWithClusterId(tx *dbs.Tx, clusterId int64) (result []int64, err error) {
|
||||
ones, err := this.Query(tx).
|
||||
@@ -757,6 +796,8 @@ func (this *NodeDAO) CountAllEnabledNodesMatch(tx *dbs.Tx,
|
||||
// 分组
|
||||
if groupId > 0 {
|
||||
query.Attr("groupId", groupId)
|
||||
} else if groupId < 0 {
|
||||
query.Attr("groupId", 0)
|
||||
}
|
||||
|
||||
// 区域
|
||||
@@ -773,11 +814,20 @@ func (this *NodeDAO) CountAllEnabledNodesMatch(tx *dbs.Tx,
|
||||
}
|
||||
|
||||
// UpdateNodeStatus 更改节点状态
|
||||
func (this *NodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, statusJSON []byte) error {
|
||||
_, err := this.Query(tx).
|
||||
func (this *NodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, nodeStatus *nodeconfigs.NodeStatus) error {
|
||||
if nodeStatus == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
nodeStatusJSON, err := json.Marshal(nodeStatus)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Pk(nodeId).
|
||||
Set("isActive", true).
|
||||
Set("status", string(statusJSON)).
|
||||
Set("status", nodeStatusJSON).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
@@ -969,6 +1019,8 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
|
||||
clusterIds = append(clusterIds, node.DecodeSecondaryClusterIds()...)
|
||||
var clusterIndex = 0
|
||||
config.WebPImagePolicies = map[int64]*nodeconfigs.WebPImagePolicy{}
|
||||
config.UAMPolicies = map[int64]*nodeconfigs.UAMPolicy{}
|
||||
var allowIPMaps = map[string]bool{}
|
||||
for _, clusterId := range clusterIds {
|
||||
nodeCluster, err := SharedNodeClusterDAO.FindClusterBasicInfo(tx, clusterId, cacheMap)
|
||||
if err != nil {
|
||||
@@ -978,6 +1030,21 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
|
||||
continue
|
||||
}
|
||||
|
||||
// 节点IP地址
|
||||
nodeIPAddresses, err := SharedNodeIPAddressDAO.FindAllAccessibleIPAddressesWithClusterId(tx, nodeconfigs.NodeRoleNode, clusterId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, address := range nodeIPAddresses {
|
||||
var ip = address.Ip
|
||||
_, ok := allowIPMaps[ip]
|
||||
if !ok {
|
||||
allowIPMaps[ip] = true
|
||||
config.AllowedIPs = append(config.AllowedIPs, ip)
|
||||
}
|
||||
}
|
||||
|
||||
// 防火墙
|
||||
var httpFirewallPolicyId = int64(nodeCluster.HttpFirewallPolicyId)
|
||||
if httpFirewallPolicyId > 0 {
|
||||
firewallPolicy, err := SharedHTTPFirewallPolicyDAO.ComposeFirewallPolicy(tx, httpFirewallPolicyId, cacheMap)
|
||||
@@ -1012,7 +1079,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
|
||||
// 最大线程数、TCP连接数
|
||||
if clusterIndex == 0 {
|
||||
config.MaxThreads = int(nodeCluster.NodeMaxThreads)
|
||||
config.TCPMaxConnections = int(nodeCluster.NodeTCPMaxConnections)
|
||||
config.DDoSProtection = nodeCluster.DecodeDDoSProtection()
|
||||
config.AutoOpenPorts = nodeCluster.AutoOpenPorts == 1
|
||||
}
|
||||
|
||||
@@ -1026,6 +1093,16 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
|
||||
config.WebPImagePolicies[clusterId] = webpPolicy
|
||||
}
|
||||
|
||||
// UAM
|
||||
if IsNotNull(nodeCluster.Uam) {
|
||||
var uamPolicy = &nodeconfigs.UAMPolicy{}
|
||||
err = json.Unmarshal(nodeCluster.Uam, uamPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.UAMPolicies[clusterId] = uamPolicy
|
||||
}
|
||||
|
||||
clusterIndex++
|
||||
}
|
||||
|
||||
@@ -1070,6 +1147,16 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
|
||||
config.SystemServices = services
|
||||
}
|
||||
|
||||
// DNS Resolver
|
||||
if IsNotNull(node.DnsResolver) {
|
||||
var dnsResolverConfig = nodeconfigs.DefaultDNSResolverConfig()
|
||||
err = json.Unmarshal(node.DnsResolver, dnsResolverConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.DNSResolver = dnsResolverConfig
|
||||
}
|
||||
|
||||
// 防火墙动作
|
||||
actions, err := SharedNodeClusterFirewallActionDAO.FindAllEnabledFirewallActions(tx, primaryClusterId, cacheMap)
|
||||
if err != nil {
|
||||
@@ -1134,6 +1221,16 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
|
||||
}
|
||||
config.OCSPVersion = ocspVersion
|
||||
|
||||
// DDOS Protection
|
||||
var ddosProtection = node.DecodeDDoSProtection()
|
||||
if ddosProtection != nil {
|
||||
if config.DDoSProtection == nil {
|
||||
config.DDoSProtection = ddosProtection
|
||||
} else {
|
||||
config.DDoSProtection.Merge(ddosProtection)
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化扩展配置
|
||||
err = this.composeExtConfig(tx, config, clusterIds, cacheMap)
|
||||
if err != nil {
|
||||
@@ -1400,6 +1497,49 @@ func (this *NodeDAO) UpdateNodeDNS(tx *dbs.Tx, nodeId int64, routes map[int64][]
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindNodeDNSResolver 查找域名DNS Resolver
|
||||
func (this *NodeDAO) FindNodeDNSResolver(tx *dbs.Tx, nodeId int64) (*nodeconfigs.DNSResolverConfig, error) {
|
||||
configJSON, err := this.Query(tx).
|
||||
Pk(nodeId).
|
||||
Result("dnsResolver").
|
||||
FindJSONCol()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if IsNull(configJSON) {
|
||||
return nodeconfigs.DefaultDNSResolverConfig(), nil
|
||||
}
|
||||
|
||||
var config = nodeconfigs.DefaultDNSResolverConfig()
|
||||
err = json.Unmarshal(configJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// UpdateNodeDNSResolver 修改域名DNS Resolver
|
||||
func (this *NodeDAO) UpdateNodeDNSResolver(tx *dbs.Tx, nodeId int64, dnsResolverConfig *nodeconfigs.DNSResolverConfig) error {
|
||||
if nodeId <= 0 {
|
||||
return ErrNotFound
|
||||
}
|
||||
|
||||
configJSON, err := json.Marshal(dnsResolverConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var op = NewNodeOperator()
|
||||
op.Id = nodeId
|
||||
op.DnsResolver = configJSON
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, nodeId)
|
||||
}
|
||||
|
||||
// UpdateNodeSystem 设置系统信息
|
||||
func (this *NodeDAO) UpdateNodeSystem(tx *dbs.Tx, nodeId int64, maxCPU int32) error {
|
||||
if nodeId <= 0 {
|
||||
@@ -1737,6 +1877,53 @@ func (this *NodeDAO) FindParentNodeConfigs(tx *dbs.Tx, nodeId int64, groupId int
|
||||
return
|
||||
}
|
||||
|
||||
// FindNodeDDoSProtection 获取节点的DDOS设置
|
||||
func (this *NodeDAO) FindNodeDDoSProtection(tx *dbs.Tx, nodeId int64) (*ddosconfigs.ProtectionConfig, error) {
|
||||
one, err := this.Query(tx).
|
||||
Result("ddosProtection").
|
||||
Pk(nodeId).
|
||||
Find()
|
||||
if one == nil || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return one.(*Node).DecodeDDoSProtection(), nil
|
||||
}
|
||||
|
||||
// UpdateNodeDDoSProtection 设置集群的DDOS设置
|
||||
func (this *NodeDAO) UpdateNodeDDoSProtection(tx *dbs.Tx, nodeId int64, ddosProtection *ddosconfigs.ProtectionConfig) error {
|
||||
if nodeId <= 0 {
|
||||
return ErrNotFound
|
||||
}
|
||||
|
||||
var op = NewNodeOperator()
|
||||
op.Id = nodeId
|
||||
|
||||
if ddosProtection == nil {
|
||||
op.DdosProtection = "{}"
|
||||
} else {
|
||||
ddosProtectionJSON, err := json.Marshal(ddosProtection)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.DdosProtection = ddosProtectionJSON
|
||||
}
|
||||
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
clusterId, err := this.FindNodeClusterId(tx, nodeId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if clusterId > 0 {
|
||||
return SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, 0, NodeTaskTypeDDosProtectionChanged, 0)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知节点相关更新
|
||||
func (this *NodeDAO) NotifyUpdate(tx *dbs.Tx, nodeId int64) error {
|
||||
// 这里只需要通知单个集群即可,因为节点是公用的,更新一个就相当于更新了所有
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
|
||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@@ -375,7 +376,15 @@ func (this *NodeIPAddressDAO) ListEnabledIPAddresses(tx *dbs.Tx, role string, no
|
||||
}
|
||||
|
||||
// FindAllAccessibleIPAddressesWithClusterId 列出所有的正在启用的IP地址
|
||||
func (this *NodeIPAddressDAO) FindAllAccessibleIPAddressesWithClusterId(tx *dbs.Tx, role string, clusterId int64) (result []*NodeIPAddress, err error) {
|
||||
func (this *NodeIPAddressDAO) FindAllAccessibleIPAddressesWithClusterId(tx *dbs.Tx, role string, clusterId int64, cacheMap *utils.CacheMap) (result []*NodeIPAddress, err error) {
|
||||
var cacheKey = this.Table + ":FindAllAccessibleIPAddressesWithClusterId:" + role + ":" + types.String(clusterId)
|
||||
if cacheMap != nil {
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return cache.([]*NodeIPAddress), nil
|
||||
}
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
State(NodeIPAddressStateEnabled).
|
||||
Attr("role", role).
|
||||
@@ -385,6 +394,14 @@ func (this *NodeIPAddressDAO) FindAllAccessibleIPAddressesWithClusterId(tx *dbs.
|
||||
Param("clusterId", clusterId).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, result)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -360,3 +360,12 @@ func (this *NodeLogDAO) UpdateAllNodeLogsRead(tx *dbs.Tx) error {
|
||||
Set("isRead", true).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// DeleteNodeLogs 删除某个节点上的日志
|
||||
func (this *NodeLogDAO) DeleteNodeLogs(tx *dbs.Tx, role nodeconfigs.NodeRole, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Attr("nodeId", nodeId).
|
||||
Attr("role", role).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -31,10 +31,13 @@ type Node struct {
|
||||
State uint8 `field:"state"` // 状态
|
||||
ConnectedAPINodes dbs.JSON `field:"connectedAPINodes"` // 当前连接的API节点
|
||||
MaxCPU uint32 `field:"maxCPU"` // 可以使用的最多CPU
|
||||
MaxThreads uint32 `field:"maxThreads"` // 最大线程数
|
||||
DdosProtection dbs.JSON `field:"ddosProtection"` // DDOS配置
|
||||
DnsRoutes dbs.JSON `field:"dnsRoutes"` // DNS线路设置
|
||||
MaxCacheDiskCapacity dbs.JSON `field:"maxCacheDiskCapacity"` // 硬盘缓存容量
|
||||
MaxCacheMemoryCapacity dbs.JSON `field:"maxCacheMemoryCapacity"` // 内存缓存容量
|
||||
CacheDiskDir string `field:"cacheDiskDir"` // 缓存目录
|
||||
DnsResolver dbs.JSON `field:"dnsResolver"` // DNS解析器
|
||||
}
|
||||
|
||||
type NodeOperator struct {
|
||||
@@ -65,10 +68,13 @@ type NodeOperator struct {
|
||||
State interface{} // 状态
|
||||
ConnectedAPINodes interface{} // 当前连接的API节点
|
||||
MaxCPU interface{} // 可以使用的最多CPU
|
||||
MaxThreads interface{} // 最大线程数
|
||||
DdosProtection interface{} // DDOS配置
|
||||
DnsRoutes interface{} // DNS线路设置
|
||||
MaxCacheDiskCapacity interface{} // 硬盘缓存容量
|
||||
MaxCacheMemoryCapacity interface{} // 内存缓存容量
|
||||
CacheDiskDir interface{} // 缓存目录
|
||||
DnsResolver interface{} // DNS解析器
|
||||
}
|
||||
|
||||
func NewNodeOperator() *NodeOperator {
|
||||
|
||||
@@ -3,6 +3,8 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
@@ -97,6 +99,7 @@ func (this *Node) DecodeSecondaryClusterIds() []int64 {
|
||||
return result
|
||||
}
|
||||
|
||||
// AllClusterIds 获取所属集群IDs
|
||||
func (this *Node) AllClusterIds() []int64 {
|
||||
var result = []int64{}
|
||||
|
||||
@@ -108,3 +111,60 @@ func (this *Node) AllClusterIds() []int64 {
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// DecodeDDoSProtection 解析DDoS Protection设置
|
||||
func (this *Node) DecodeDDoSProtection() *ddosconfigs.ProtectionConfig {
|
||||
if IsNull(this.DdosProtection) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var result = &ddosconfigs.ProtectionConfig{}
|
||||
err := json.Unmarshal(this.DdosProtection, &result)
|
||||
if err != nil {
|
||||
// ignore err
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// HasDDoSProtection 检查是否有DDOS设置
|
||||
func (this *Node) HasDDoSProtection() bool {
|
||||
var config = this.DecodeDDoSProtection()
|
||||
if config != nil {
|
||||
return !config.IsPriorEmpty()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (this *Node) DecodeMaxCacheDiskCapacity() *shared.SizeCapacity {
|
||||
if this.MaxCacheDiskCapacity.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ignore error
|
||||
capacity, _ := shared.DecodeSizeCapacityJSON(this.MaxCacheDiskCapacity)
|
||||
return capacity
|
||||
}
|
||||
|
||||
func (this *Node) DecodeMaxCacheMemoryCapacity() *shared.SizeCapacity {
|
||||
if this.MaxCacheMemoryCapacity.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ignore error
|
||||
capacity, _ := shared.DecodeSizeCapacityJSON(this.MaxCacheMemoryCapacity)
|
||||
return capacity
|
||||
}
|
||||
|
||||
// DecodeDNSResolver 解析DNS解析主机配置
|
||||
func (this *Node) DecodeDNSResolver() *nodeconfigs.DNSResolverConfig {
|
||||
if this.DnsResolver.IsNull() {
|
||||
return nil
|
||||
}
|
||||
|
||||
var resolverConfig = nodeconfigs.DefaultDNSResolverConfig()
|
||||
err := json.Unmarshal(this.DnsResolver, resolverConfig)
|
||||
if err != nil {
|
||||
// ignore error
|
||||
}
|
||||
return resolverConfig
|
||||
}
|
||||
|
||||
@@ -14,11 +14,12 @@ import (
|
||||
type NodeTaskType = string
|
||||
|
||||
const (
|
||||
NodeTaskTypeConfigChanged NodeTaskType = "configChanged"
|
||||
NodeTaskTypeIPItemChanged NodeTaskType = "ipItemChanged"
|
||||
NodeTaskTypeNodeVersionChanged NodeTaskType = "nodeVersionChanged"
|
||||
NodeTaskTypeScriptsChanged NodeTaskType = "scriptsChanged"
|
||||
NodeTaskTypeNodeLevelChanged NodeTaskType = "nodeLevelChanged"
|
||||
NodeTaskTypeConfigChanged NodeTaskType = "configChanged" // 节点整体配置变化
|
||||
NodeTaskTypeDDosProtectionChanged NodeTaskType = "ddosProtectionChanged" // 节点DDoS配置变更
|
||||
NodeTaskTypeIPItemChanged NodeTaskType = "ipItemChanged"
|
||||
NodeTaskTypeNodeVersionChanged NodeTaskType = "nodeVersionChanged"
|
||||
NodeTaskTypeScriptsChanged NodeTaskType = "scriptsChanged"
|
||||
NodeTaskTypeNodeLevelChanged NodeTaskType = "nodeLevelChanged"
|
||||
|
||||
// NS相关
|
||||
|
||||
|
||||
@@ -52,16 +52,23 @@ func (this *NSNodeDAO) EnableNSNode(tx *dbs.Tx, id int64) error {
|
||||
}
|
||||
|
||||
// DisableNSNode 禁用条目
|
||||
func (this *NSNodeDAO) DisableNSNode(tx *dbs.Tx, id int64) error {
|
||||
func (this *NSNodeDAO) DisableNSNode(tx *dbs.Tx, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Pk(nodeId).
|
||||
Set("state", NSNodeStateDisabled).
|
||||
Update()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, id)
|
||||
|
||||
err = this.NotifyUpdate(tx, nodeId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除运行日志
|
||||
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleDNS, nodeId)
|
||||
}
|
||||
|
||||
// FindEnabledNSNode 查找启用中的条目
|
||||
@@ -339,13 +346,19 @@ func (this *NSNodeDAO) UpdateNodeIsInstalled(tx *dbs.Tx, nodeId int64, isInstall
|
||||
}
|
||||
|
||||
// UpdateNodeStatus 更改节点状态
|
||||
func (this NSNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, statusJSON []byte) error {
|
||||
if statusJSON == nil {
|
||||
func (this NSNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, nodeStatus *nodeconfigs.NodeStatus) error {
|
||||
if nodeStatus == nil {
|
||||
return nil
|
||||
}
|
||||
_, err := this.Query(tx).
|
||||
|
||||
nodeStatusJSON, err := json.Marshal(nodeStatus)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Pk(nodeId).
|
||||
Set("status", string(statusJSON)).
|
||||
Set("status", nodeStatusJSON).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -101,7 +101,8 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx,
|
||||
maxIdleConns int32,
|
||||
certRef *sslconfigs.SSLCertRef,
|
||||
domains []string,
|
||||
host string) (originId int64, err error) {
|
||||
host string,
|
||||
followPort bool) (originId int64, err error) {
|
||||
var op = NewOriginOperator()
|
||||
op.AdminId = adminId
|
||||
op.UserId = userId
|
||||
@@ -167,6 +168,7 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx,
|
||||
}
|
||||
|
||||
op.Host = host
|
||||
op.FollowPort = followPort
|
||||
|
||||
op.State = OriginStateEnabled
|
||||
err = this.Save(tx, op)
|
||||
@@ -191,7 +193,8 @@ func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx,
|
||||
maxIdleConns int32,
|
||||
certRef *sslconfigs.SSLCertRef,
|
||||
domains []string,
|
||||
host string) error {
|
||||
host string,
|
||||
followPort bool) error {
|
||||
if originId <= 0 {
|
||||
return errors.New("invalid originId")
|
||||
}
|
||||
@@ -262,6 +265,7 @@ func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx,
|
||||
}
|
||||
|
||||
op.Host = host
|
||||
op.FollowPort = followPort
|
||||
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
@@ -304,10 +308,11 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
||||
RequestURI: origin.HttpRequestURI,
|
||||
RequestHost: origin.Host,
|
||||
Domains: origin.DecodeDomains(),
|
||||
FollowPort: origin.FollowPort,
|
||||
}
|
||||
|
||||
if IsNotNull(origin.Addr) {
|
||||
addr := &serverconfigs.NetworkAddressConfig{}
|
||||
var addr = &serverconfigs.NetworkAddressConfig{}
|
||||
err = json.Unmarshal(origin.Addr, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -316,7 +321,7 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
||||
}
|
||||
|
||||
if IsNotNull(origin.ConnTimeout) {
|
||||
connTimeout := &shared.TimeDuration{}
|
||||
var connTimeout = &shared.TimeDuration{}
|
||||
err = json.Unmarshal(origin.ConnTimeout, &connTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -325,7 +330,7 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
||||
}
|
||||
|
||||
if IsNotNull(origin.ReadTimeout) {
|
||||
readTimeout := &shared.TimeDuration{}
|
||||
var readTimeout = &shared.TimeDuration{}
|
||||
err = json.Unmarshal(origin.ReadTimeout, &readTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -334,7 +339,7 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
||||
}
|
||||
|
||||
if IsNotNull(origin.IdleTimeout) {
|
||||
idleTimeout := &shared.TimeDuration{}
|
||||
var idleTimeout = &shared.TimeDuration{}
|
||||
err = json.Unmarshal(origin.IdleTimeout, &idleTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -363,7 +368,7 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
||||
}
|
||||
|
||||
if IsNotNull(origin.HttpResponseHeader) {
|
||||
ref := &shared.HTTPHeaderPolicyRef{}
|
||||
var ref = &shared.HTTPHeaderPolicyRef{}
|
||||
err = json.Unmarshal(origin.HttpResponseHeader, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -382,7 +387,7 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
||||
}
|
||||
|
||||
if IsNotNull(origin.HealthCheck) {
|
||||
healthCheck := &serverconfigs.HealthCheckConfig{}
|
||||
var healthCheck = &serverconfigs.HealthCheckConfig{}
|
||||
err = json.Unmarshal(origin.HealthCheck, healthCheck)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -391,7 +396,7 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
||||
}
|
||||
|
||||
if IsNotNull(origin.Cert) {
|
||||
ref := &sslconfigs.SSLCertRef{}
|
||||
var ref = &sslconfigs.SSLCertRef{}
|
||||
err = json.Unmarshal(origin.Cert, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -417,6 +422,19 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// CheckUserOrigin 检查源站权限
|
||||
func (this *OriginDAO) CheckUserOrigin(tx *dbs.Tx, userId int64, originId int64) error {
|
||||
reverseProxyId, err := SharedReverseProxyDAO.FindReverseProxyContainsOriginId(tx, originId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if reverseProxyId == 0 {
|
||||
// 这里我们不允许源站没有被使用
|
||||
return ErrNotFound
|
||||
}
|
||||
return SharedReverseProxyDAO.CheckUserReverseProxy(tx, userId, reverseProxyId)
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *OriginDAO) NotifyUpdate(tx *dbs.Tx, originId int64) error {
|
||||
reverseProxyId, err := SharedReverseProxyDAO.FindReverseProxyContainsOriginId(tx, originId)
|
||||
|
||||
@@ -29,6 +29,7 @@ type Origin struct {
|
||||
Ftp dbs.JSON `field:"ftp"` // FTP相关设置
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Domains dbs.JSON `field:"domains"` // 所属域名
|
||||
FollowPort bool `field:"followPort"` // 端口跟随
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
@@ -58,6 +59,7 @@ type OriginOperator struct {
|
||||
Ftp interface{} // FTP相关设置
|
||||
CreatedAt interface{} // 创建时间
|
||||
Domains interface{} // 所属域名
|
||||
FollowPort interface{} // 端口跟随
|
||||
State interface{} // 状态
|
||||
}
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ func (this *PlanDAO) ListEnabledPlans(tx *dbs.Tx, offset int64, size int64) (res
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
Desc("order").
|
||||
DescPk().
|
||||
AscPk().
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -50,12 +50,17 @@ func (this *ReportNodeDAO) EnableReportNode(tx *dbs.Tx, id int64) error {
|
||||
}
|
||||
|
||||
// DisableReportNode 禁用条目
|
||||
func (this *ReportNodeDAO) DisableReportNode(tx *dbs.Tx, id int64) error {
|
||||
func (this *ReportNodeDAO) DisableReportNode(tx *dbs.Tx, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Pk(nodeId).
|
||||
Set("state", ReportNodeStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除运行日志
|
||||
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleReport, nodeId)
|
||||
}
|
||||
|
||||
// FindEnabledReportNode 查找启用中的条目
|
||||
@@ -264,13 +269,19 @@ func (this *ReportNodeDAO) FindEnabledNodeIdWithUniqueId(tx *dbs.Tx, uniqueId st
|
||||
}
|
||||
|
||||
// UpdateNodeStatus 更改节点状态
|
||||
func (this ReportNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, statusJSON []byte) error {
|
||||
if statusJSON == nil {
|
||||
func (this ReportNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, nodeStatus *reporterconfigs.Status) error {
|
||||
if nodeStatus == nil {
|
||||
return nil
|
||||
}
|
||||
_, err := this.Query(tx).
|
||||
|
||||
nodeStatusJSON, err := json.Marshal(nodeStatus)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Pk(nodeId).
|
||||
Set("status", string(statusJSON)).
|
||||
Set("status", nodeStatusJSON).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -99,17 +99,18 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(tx *dbs.Tx, reverseProxyI
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
config := &serverconfigs.ReverseProxyConfig{}
|
||||
var config = &serverconfigs.ReverseProxyConfig{}
|
||||
config.Id = int64(reverseProxy.Id)
|
||||
config.IsOn = reverseProxy.IsOn
|
||||
config.RequestHostType = types.Int8(reverseProxy.RequestHostType)
|
||||
config.RequestHost = reverseProxy.RequestHost
|
||||
config.RequestHostExcludingPort = reverseProxy.RequestHostExcludingPort
|
||||
config.RequestURI = reverseProxy.RequestURI
|
||||
config.StripPrefix = reverseProxy.StripPrefix
|
||||
config.AutoFlush = reverseProxy.AutoFlush == 1
|
||||
config.FollowRedirects = reverseProxy.FollowRedirects == 1
|
||||
|
||||
schedulingConfig := &serverconfigs.SchedulingConfig{}
|
||||
var schedulingConfig = &serverconfigs.SchedulingConfig{}
|
||||
if IsNotNull(reverseProxy.Scheduling) {
|
||||
err = json.Unmarshal(reverseProxy.Scheduling, schedulingConfig)
|
||||
if err != nil {
|
||||
@@ -118,7 +119,7 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(tx *dbs.Tx, reverseProxyI
|
||||
config.Scheduling = schedulingConfig
|
||||
}
|
||||
if IsNotNull(reverseProxy.PrimaryOrigins) {
|
||||
originRefs := []*serverconfigs.OriginRef{}
|
||||
var originRefs = []*serverconfigs.OriginRef{}
|
||||
err = json.Unmarshal(reverseProxy.PrimaryOrigins, &originRefs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -135,13 +136,13 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(tx *dbs.Tx, reverseProxyI
|
||||
}
|
||||
|
||||
if IsNotNull(reverseProxy.BackupOrigins) {
|
||||
originRefs := []*serverconfigs.OriginRef{}
|
||||
var originRefs = []*serverconfigs.OriginRef{}
|
||||
err = json.Unmarshal(reverseProxy.BackupOrigins, &originRefs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, originConfig := range originRefs {
|
||||
originConfig, err := SharedOriginDAO.ComposeOriginConfig(tx, originConfig.OriginId, cacheMap)
|
||||
for _, ref := range originRefs {
|
||||
originConfig, err := SharedOriginDAO.ComposeOriginConfig(tx, ref.OriginId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -153,7 +154,7 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(tx *dbs.Tx, reverseProxyI
|
||||
|
||||
// add headers
|
||||
if IsNotNull(reverseProxy.AddHeaders) {
|
||||
addHeaders := []string{}
|
||||
var addHeaders = []string{}
|
||||
err = json.Unmarshal(reverseProxy.AddHeaders, &addHeaders)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -166,7 +167,7 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(tx *dbs.Tx, reverseProxyI
|
||||
config.MaxIdleConns = int(reverseProxy.MaxIdleConns)
|
||||
|
||||
if IsNotNull(reverseProxy.ConnTimeout) {
|
||||
connTimeout := &shared.TimeDuration{}
|
||||
var connTimeout = &shared.TimeDuration{}
|
||||
err = json.Unmarshal(reverseProxy.ConnTimeout, &connTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -175,7 +176,7 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(tx *dbs.Tx, reverseProxyI
|
||||
}
|
||||
|
||||
if IsNotNull(reverseProxy.ReadTimeout) {
|
||||
readTimeout := &shared.TimeDuration{}
|
||||
var readTimeout = &shared.TimeDuration{}
|
||||
err = json.Unmarshal(reverseProxy.ReadTimeout, &readTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -184,7 +185,7 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(tx *dbs.Tx, reverseProxyI
|
||||
}
|
||||
|
||||
if IsNotNull(reverseProxy.IdleTimeout) {
|
||||
idleTimeout := &shared.TimeDuration{}
|
||||
var idleTimeout = &shared.TimeDuration{}
|
||||
err = json.Unmarshal(reverseProxy.IdleTimeout, &idleTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -304,6 +305,7 @@ func (this *ReverseProxyDAO) UpdateReverseProxy(tx *dbs.Tx,
|
||||
reverseProxyId int64,
|
||||
requestHostType int8,
|
||||
requestHost string,
|
||||
requestHostExcludingPort bool,
|
||||
requestURI string,
|
||||
stripPrefix string,
|
||||
autoFlush bool,
|
||||
@@ -328,6 +330,7 @@ func (this *ReverseProxyDAO) UpdateReverseProxy(tx *dbs.Tx,
|
||||
op.RequestHostType = requestHostType
|
||||
|
||||
op.RequestHost = requestHost
|
||||
op.RequestHostExcludingPort = requestHostExcludingPort
|
||||
op.RequestURI = requestURI
|
||||
op.StripPrefix = stripPrefix
|
||||
op.AutoFlush = autoFlush
|
||||
|
||||
@@ -4,55 +4,57 @@ import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// ReverseProxy 反向代理配置
|
||||
type ReverseProxy struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Scheduling dbs.JSON `field:"scheduling"` // 调度算法
|
||||
PrimaryOrigins dbs.JSON `field:"primaryOrigins"` // 主要源站
|
||||
BackupOrigins dbs.JSON `field:"backupOrigins"` // 备用源站
|
||||
StripPrefix string `field:"stripPrefix"` // 去除URL前缀
|
||||
RequestHostType uint8 `field:"requestHostType"` // 请求Host类型
|
||||
RequestHost string `field:"requestHost"` // 请求Host
|
||||
RequestURI string `field:"requestURI"` // 请求URI
|
||||
AutoFlush uint8 `field:"autoFlush"` // 是否自动刷新缓冲区
|
||||
AddHeaders dbs.JSON `field:"addHeaders"` // 自动添加的Header列表
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
ConnTimeout dbs.JSON `field:"connTimeout"` // 连接超时时间
|
||||
ReadTimeout dbs.JSON `field:"readTimeout"` // 读取超时时间
|
||||
IdleTimeout dbs.JSON `field:"idleTimeout"` // 空闲超时时间
|
||||
MaxConns uint32 `field:"maxConns"` // 最大并发连接数
|
||||
MaxIdleConns uint32 `field:"maxIdleConns"` // 最大空闲连接数
|
||||
ProxyProtocol dbs.JSON `field:"proxyProtocol"` // Proxy Protocol配置
|
||||
FollowRedirects uint8 `field:"followRedirects"` // 回源跟随
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Scheduling dbs.JSON `field:"scheduling"` // 调度算法
|
||||
PrimaryOrigins dbs.JSON `field:"primaryOrigins"` // 主要源站
|
||||
BackupOrigins dbs.JSON `field:"backupOrigins"` // 备用源站
|
||||
StripPrefix string `field:"stripPrefix"` // 去除URL前缀
|
||||
RequestHostType uint8 `field:"requestHostType"` // 请求Host类型
|
||||
RequestHost string `field:"requestHost"` // 请求Host
|
||||
RequestHostExcludingPort bool `field:"requestHostExcludingPort"` // 移除请求Host中的域名
|
||||
RequestURI string `field:"requestURI"` // 请求URI
|
||||
AutoFlush uint8 `field:"autoFlush"` // 是否自动刷新缓冲区
|
||||
AddHeaders dbs.JSON `field:"addHeaders"` // 自动添加的Header列表
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
ConnTimeout dbs.JSON `field:"connTimeout"` // 连接超时时间
|
||||
ReadTimeout dbs.JSON `field:"readTimeout"` // 读取超时时间
|
||||
IdleTimeout dbs.JSON `field:"idleTimeout"` // 空闲超时时间
|
||||
MaxConns uint32 `field:"maxConns"` // 最大并发连接数
|
||||
MaxIdleConns uint32 `field:"maxIdleConns"` // 最大空闲连接数
|
||||
ProxyProtocol dbs.JSON `field:"proxyProtocol"` // Proxy Protocol配置
|
||||
FollowRedirects uint8 `field:"followRedirects"` // 回源跟随
|
||||
}
|
||||
|
||||
type ReverseProxyOperator struct {
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
TemplateId interface{} // 模版ID
|
||||
IsOn interface{} // 是否启用
|
||||
Scheduling interface{} // 调度算法
|
||||
PrimaryOrigins interface{} // 主要源站
|
||||
BackupOrigins interface{} // 备用源站
|
||||
StripPrefix interface{} // 去除URL前缀
|
||||
RequestHostType interface{} // 请求Host类型
|
||||
RequestHost interface{} // 请求Host
|
||||
RequestURI interface{} // 请求URI
|
||||
AutoFlush interface{} // 是否自动刷新缓冲区
|
||||
AddHeaders interface{} // 自动添加的Header列表
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
ConnTimeout interface{} // 连接超时时间
|
||||
ReadTimeout interface{} // 读取超时时间
|
||||
IdleTimeout interface{} // 空闲超时时间
|
||||
MaxConns interface{} // 最大并发连接数
|
||||
MaxIdleConns interface{} // 最大空闲连接数
|
||||
ProxyProtocol interface{} // Proxy Protocol配置
|
||||
FollowRedirects interface{} // 回源跟随
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
TemplateId interface{} // 模版ID
|
||||
IsOn interface{} // 是否启用
|
||||
Scheduling interface{} // 调度算法
|
||||
PrimaryOrigins interface{} // 主要源站
|
||||
BackupOrigins interface{} // 备用源站
|
||||
StripPrefix interface{} // 去除URL前缀
|
||||
RequestHostType interface{} // 请求Host类型
|
||||
RequestHost interface{} // 请求Host
|
||||
RequestHostExcludingPort interface{} // 移除请求Host中的域名
|
||||
RequestURI interface{} // 请求URI
|
||||
AutoFlush interface{} // 是否自动刷新缓冲区
|
||||
AddHeaders interface{} // 自动添加的Header列表
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
ConnTimeout interface{} // 连接超时时间
|
||||
ReadTimeout interface{} // 读取超时时间
|
||||
IdleTimeout interface{} // 空闲超时时间
|
||||
MaxConns interface{} // 最大并发连接数
|
||||
MaxIdleConns interface{} // 最大空闲连接数
|
||||
ProxyProtocol interface{} // Proxy Protocol配置
|
||||
FollowRedirects interface{} // 回源跟随
|
||||
}
|
||||
|
||||
func NewReverseProxyOperator() *ReverseProxyOperator {
|
||||
|
||||
215
internal/db/models/server_bandwidth_stat_dao.go
Normal file
215
internal/db/models/server_bandwidth_stat_dao.go
Normal file
@@ -0,0 +1,215 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"math"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ServerBandwidthStatDAO dbs.DAO
|
||||
|
||||
const (
|
||||
ServerBandwidthStatTablePartials = 20 // 分表数量
|
||||
)
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
// 清理数据任务
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedServerBandwidthStatDAO.Clean(nil)
|
||||
if err != nil {
|
||||
remotelogs.Error("SharedServerBandwidthStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func NewServerBandwidthStatDAO() *ServerBandwidthStatDAO {
|
||||
return dbs.NewDAO(&ServerBandwidthStatDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeServerBandwidthStats",
|
||||
Model: new(ServerBandwidthStat),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*ServerBandwidthStatDAO)
|
||||
}
|
||||
|
||||
var SharedServerBandwidthStatDAO *ServerBandwidthStatDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedServerBandwidthStatDAO = NewServerBandwidthStatDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateServerBandwidth 写入数据
|
||||
func (this *ServerBandwidthStatDAO) UpdateServerBandwidth(tx *dbs.Tx, userId int64, serverId int64, day string, timeAt string, bytes int64) error {
|
||||
if serverId <= 0 {
|
||||
return errors.New("invalid server id '" + types.String(serverId) + "'")
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
Param("bytes", bytes).
|
||||
InsertOrUpdateQuickly(maps.Map{
|
||||
"userId": userId,
|
||||
"serverId": serverId,
|
||||
"day": day,
|
||||
"timeAt": timeAt,
|
||||
"bytes": bytes,
|
||||
}, maps.Map{
|
||||
"bytes": dbs.SQL("bytes+:bytes"),
|
||||
})
|
||||
}
|
||||
|
||||
// FindMinutelyPeekBandwidthBytes 获取某分钟的带宽峰值
|
||||
// day YYYYMMDD
|
||||
// minute HHII
|
||||
func (this *ServerBandwidthStatDAO) FindMinutelyPeekBandwidthBytes(tx *dbs.Tx, serverId int64, day string, minute string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
Result("bytes").
|
||||
Attr("serverId", serverId).
|
||||
Attr("day", day).
|
||||
Attr("timeAt", minute).
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// FindDailyPeekBandwidthBytes 获取某天的带宽峰值
|
||||
// day YYYYMMDD
|
||||
func (this *ServerBandwidthStatDAO) FindDailyPeekBandwidthBytes(tx *dbs.Tx, serverId int64, day string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
Attr("day", day).
|
||||
Result("MAX(bytes)").
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// FindMonthlyPeekBandwidthBytes 获取某月的带宽峰值
|
||||
// month YYYYMM
|
||||
func (this *ServerBandwidthStatDAO) FindMonthlyPeekBandwidthBytes(tx *dbs.Tx, serverId int64, month string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
Between("day", month+"01", month+"31").
|
||||
Result("MAX(bytes)").
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// FindServerStats 查找某个时间段的带宽统计
|
||||
// 参数:
|
||||
// - day YYYYMMDD
|
||||
// - timeAt HHII
|
||||
func (this *ServerBandwidthStatDAO) FindServerStats(tx *dbs.Tx, serverId int64, day string, timeFrom string, timeTo string) (result []*ServerBandwidthStat, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
Attr("serverId", serverId).
|
||||
Attr("day", day).
|
||||
Between("timeAt", timeFrom, timeTo).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindMonthlyPercentile 获取某月内百分位
|
||||
func (this *ServerBandwidthStatDAO) FindMonthlyPercentile(tx *dbs.Tx, serverId int64, month string, percentile int) (result int64, err error) {
|
||||
if percentile <= 0 {
|
||||
percentile = 95
|
||||
}
|
||||
|
||||
// 如果是100%以上,则快速返回
|
||||
if percentile >= 100 {
|
||||
result, err = this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
Result("bytes").
|
||||
Attr("serverId", serverId).
|
||||
Between("day", month+"01", month+"31").
|
||||
Desc("bytes").
|
||||
Limit(1).
|
||||
FindInt64Col(0)
|
||||
return
|
||||
}
|
||||
|
||||
// 总数量
|
||||
total, err := this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
Attr("serverId", serverId).
|
||||
Between("day", month+"01", month+"31").
|
||||
Count()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if total == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
var offset int64
|
||||
|
||||
if total > 1 {
|
||||
offset = int64(math.Ceil(float64(total) * float64(100-percentile) / 100))
|
||||
}
|
||||
|
||||
// 查询 nth 位置
|
||||
result, err = this.Query(tx).
|
||||
Table(this.partialTable(serverId)).
|
||||
Result("bytes").
|
||||
Attr("serverId", serverId).
|
||||
Between("day", month+"01", month+"31").
|
||||
Desc("bytes").
|
||||
Offset(offset).
|
||||
Limit(1).
|
||||
FindInt64Col(0)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Clean 清理过期数据
|
||||
func (this *ServerBandwidthStatDAO) Clean(tx *dbs.Tx) error {
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -62)) // 保留大约2个月的数据
|
||||
return this.runBatch(func(table string, locker *sync.Mutex) error {
|
||||
_, err := this.Query(tx).
|
||||
Table(table).
|
||||
Lt("day", day).
|
||||
Delete()
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// 批量执行
|
||||
func (this *ServerBandwidthStatDAO) runBatch(f func(table string, locker *sync.Mutex) error) error {
|
||||
var locker = &sync.Mutex{}
|
||||
var wg = sync.WaitGroup{}
|
||||
wg.Add(ServerBandwidthStatTablePartials)
|
||||
var resultErr error
|
||||
for i := 0; i < ServerBandwidthStatTablePartials; i++ {
|
||||
var table = this.partialTable(int64(i))
|
||||
go func(table string) {
|
||||
defer wg.Done()
|
||||
|
||||
err := f(table, locker)
|
||||
if err != nil {
|
||||
resultErr = err
|
||||
}
|
||||
}(table)
|
||||
}
|
||||
wg.Wait()
|
||||
return resultErr
|
||||
}
|
||||
|
||||
// 获取分区表
|
||||
func (this *ServerBandwidthStatDAO) partialTable(serverId int64) string {
|
||||
return this.Table + "_" + types.String(serverId%int64(ServerBandwidthStatTablePartials))
|
||||
}
|
||||
55
internal/db/models/server_bandwidth_stat_dao_test.go
Normal file
55
internal/db/models/server_bandwidth_stat_dao_test.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package models_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestServerBandwidthStatDAO_UpdateServerBandwidth(t *testing.T) {
|
||||
var dao = models.NewServerBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
err := dao.UpdateServerBandwidth(tx, 1, 1, timeutil.Format("Ymd"), timeutil.Format("Hi"), 1024)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestSeverBandwidthStatDAO_InsertManyStats(t *testing.T) {
|
||||
var dao = models.NewServerBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
var count = 1 // 测试时将此值设为一个比较大的数字
|
||||
for i := 0; i < count; i++ {
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -rands.Int(0, 200)))
|
||||
var minute = fmt.Sprintf("%02d%02d", rands.Int(0, 23), rands.Int(0, 59))
|
||||
err := dao.UpdateServerBandwidth(tx, 1, 1, day, minute, 1024)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestServerBandwidthStatDAO_FindMonthlyPercentile(t *testing.T) {
|
||||
var dao = models.NewServerBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
t.Log(dao.FindMonthlyPercentile(tx, 23, timeutil.Format("Ym"), 95))
|
||||
}
|
||||
|
||||
func TestServerBandwidthStatDAO_Clean(t *testing.T) {
|
||||
var dao = models.NewServerBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
var before = time.Now()
|
||||
err := dao.Clean(tx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok", time.Since(before).Seconds()*1000, "ms")
|
||||
}
|
||||
24
internal/db/models/server_bandwidth_stat_model.go
Normal file
24
internal/db/models/server_bandwidth_stat_model.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package models
|
||||
|
||||
// ServerBandwidthStat 服务峰值带宽统计
|
||||
type ServerBandwidthStat struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
ServerId uint64 `field:"serverId"` // 服务ID
|
||||
Day string `field:"day"` // 日期YYYYMMDD
|
||||
TimeAt string `field:"timeAt"` // 时间点HHMM
|
||||
Bytes uint64 `field:"bytes"` // 带宽字节
|
||||
}
|
||||
|
||||
type ServerBandwidthStatOperator struct {
|
||||
Id interface{} // ID
|
||||
UserId interface{} // 用户ID
|
||||
ServerId interface{} // 服务ID
|
||||
Day interface{} // 日期YYYYMMDD
|
||||
TimeAt interface{} // 时间点HHMM
|
||||
Bytes interface{} // 带宽字节
|
||||
}
|
||||
|
||||
func NewServerBandwidthStatOperator() *ServerBandwidthStatOperator {
|
||||
return &ServerBandwidthStatOperator{}
|
||||
}
|
||||
1
internal/db/models/server_bandwidth_stat_model_ext.go
Normal file
1
internal/db/models/server_bandwidth_stat_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package models
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"math"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -405,45 +404,6 @@ func (this *ServerDailyStatDAO) SumMonthlyBytes(tx *dbs.Tx, serverId int64, mont
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// FindMonthlyPercentile 获取某月内百分位
|
||||
func (this *ServerDailyStatDAO) FindMonthlyPercentile(tx *dbs.Tx, serverId int64, month string, percentile int) (result int64, err error) {
|
||||
if percentile <= 0 {
|
||||
percentile = 95
|
||||
}
|
||||
if percentile > 100 {
|
||||
percentile = 100
|
||||
}
|
||||
|
||||
total, err := this.Query(tx).
|
||||
Attr("serverId", serverId).
|
||||
Between("day", month+"01", month+"31").
|
||||
Count()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if total == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
var offset int64
|
||||
|
||||
if total > 1 {
|
||||
offset = int64(math.Ceil(float64(total) * float64(100-percentile) / 100))
|
||||
}
|
||||
result, err = this.Query(tx).
|
||||
Result("bytes").
|
||||
Attr("serverId", serverId).
|
||||
Between("day", month+"01", month+"31").
|
||||
Desc("bytes").
|
||||
Offset(offset).
|
||||
Limit(1).
|
||||
FindInt64Col(0)
|
||||
|
||||
// 因为是5分钟统计,所以需要除以300
|
||||
result = result / 300
|
||||
return
|
||||
}
|
||||
|
||||
// FindDailyStats 按天统计
|
||||
func (this *ServerDailyStatDAO) FindDailyStats(tx *dbs.Tx, serverId int64, dayFrom string, dayTo string) (result []*ServerDailyStat, err error) {
|
||||
ones, err := this.Query(tx).
|
||||
|
||||
@@ -83,13 +83,3 @@ func TestServerDailyStatDAO_FindDistinctPlanServerIdsBetweenDay(t *testing.T) {
|
||||
}
|
||||
t.Log(serverIds)
|
||||
}
|
||||
|
||||
func TestServerDailyStatDAO_FindMonthlyPercentile(t *testing.T) {
|
||||
var tx *dbs.Tx
|
||||
var dao = NewServerDailyStatDAO()
|
||||
result, err := dao.FindMonthlyPercentile(tx, 23, timeutil.Format("Ym"), 95)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("result:", result)
|
||||
}
|
||||
|
||||
@@ -156,8 +156,8 @@ func (this *ServerDAO) CreateServer(tx *dbs.Tx,
|
||||
webId int64,
|
||||
reverseProxyJSON []byte,
|
||||
clusterId int64,
|
||||
includeNodesJSON string,
|
||||
excludeNodesJSON string,
|
||||
includeNodesJSON []byte,
|
||||
excludeNodesJSON []byte,
|
||||
groupIds []int64,
|
||||
userPlanId int64) (serverId int64, err error) {
|
||||
var op = NewServerOperator()
|
||||
@@ -206,15 +206,15 @@ func (this *ServerDAO) CreateServer(tx *dbs.Tx,
|
||||
op.Udp = udpJSON
|
||||
}
|
||||
op.WebId = webId
|
||||
if len(reverseProxyJSON) > 0 {
|
||||
if IsNotNull(reverseProxyJSON) {
|
||||
op.ReverseProxy = reverseProxyJSON
|
||||
}
|
||||
|
||||
op.ClusterId = clusterId
|
||||
if len(includeNodesJSON) > 0 {
|
||||
if IsNotNull(includeNodesJSON) {
|
||||
op.IncludeNodes = includeNodesJSON
|
||||
}
|
||||
if len(excludeNodesJSON) > 0 {
|
||||
if IsNotNull(excludeNodesJSON) {
|
||||
op.ExcludeNodes = excludeNodesJSON
|
||||
}
|
||||
|
||||
@@ -338,12 +338,31 @@ func (this *ServerDAO) UpdateServerBasic(tx *dbs.Tx, serverId int64, name string
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateServerGroupIds 修改服务所在分组
|
||||
func (this *ServerDAO) UpdateServerGroupIds(tx *dbs.Tx, serverId int64, groupIds []int64) error {
|
||||
if groupIds == nil {
|
||||
groupIds = []int64{}
|
||||
}
|
||||
groupIdsJSON, err := json.Marshal(groupIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = this.Query(tx).
|
||||
Pk(serverId).
|
||||
Set("groupIds", groupIdsJSON).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, serverId)
|
||||
}
|
||||
|
||||
// UpdateUserServerBasic 设置用户相关的基本信息
|
||||
func (this *ServerDAO) UpdateUserServerBasic(tx *dbs.Tx, serverId int64, name string) error {
|
||||
if serverId <= 0 {
|
||||
return errors.New("serverId should not be smaller than 0")
|
||||
}
|
||||
op := NewServerOperator()
|
||||
var op = NewServerOperator()
|
||||
op.Id = serverId
|
||||
op.Name = name
|
||||
|
||||
@@ -752,8 +771,9 @@ func (this *ServerDAO) CountAllEnabledServersMatch(tx *dbs.Tx, groupId int64, ke
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
if regexp.MustCompile(`^\d+$`).MatchString(keyword) {
|
||||
query.Where("(name LIKE :keyword OR serverNames LIKE :keyword OR JSON_CONTAINS(http, :portRange, '$.listen') OR JSON_CONTAINS(https, :portRange, '$.listen') OR JSON_CONTAINS(tcp, :portRange, '$.listen') OR JSON_CONTAINS(tls, :portRange, '$.listen'))").
|
||||
query.Where("(id=:serverId OR name LIKE :keyword OR serverNames LIKE :keyword OR JSON_CONTAINS(http, :portRange, '$.listen') OR JSON_CONTAINS(https, :portRange, '$.listen') OR JSON_CONTAINS(tcp, :portRange, '$.listen') OR JSON_CONTAINS(tls, :portRange, '$.listen'))").
|
||||
Param("portRange", maps.Map{"portRange": keyword}.AsJSON()).
|
||||
Param("serverId", keyword).
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
} else {
|
||||
query.Where("(name LIKE :keyword OR serverNames LIKE :keyword)").
|
||||
@@ -806,8 +826,9 @@ func (this *ServerDAO) ListEnabledServersMatch(tx *dbs.Tx, offset int64, size in
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
if regexp.MustCompile(`^\d+$`).MatchString(keyword) {
|
||||
query.Where("(name LIKE :keyword OR serverNames LIKE :keyword OR JSON_CONTAINS(http, :portRange, '$.listen') OR JSON_CONTAINS(https, :portRange, '$.listen') OR JSON_CONTAINS(tcp, :portRange, '$.listen') OR JSON_CONTAINS(tls, :portRange, '$.listen'))").
|
||||
query.Where("(id=:serverId OR name LIKE :keyword OR serverNames LIKE :keyword OR JSON_CONTAINS(http, :portRange, '$.listen') OR JSON_CONTAINS(https, :portRange, '$.listen') OR JSON_CONTAINS(tcp, :portRange, '$.listen') OR JSON_CONTAINS(tls, :portRange, '$.listen'))").
|
||||
Param("portRange", string(maps.Map{"portRange": keyword}.AsJSON())).
|
||||
Param("serverId", keyword).
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
} else {
|
||||
query.Where("(name LIKE :keyword OR serverNames LIKE :keyword)").
|
||||
@@ -1020,9 +1041,10 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
return cache.(*serverconfigs.ServerConfig), nil
|
||||
}
|
||||
|
||||
config := &serverconfigs.ServerConfig{}
|
||||
var config = &serverconfigs.ServerConfig{}
|
||||
config.Id = int64(server.Id)
|
||||
config.ClusterId = int64(server.ClusterId)
|
||||
config.UserId = int64(server.UserId)
|
||||
config.Type = server.Type
|
||||
config.IsOn = server.IsOn
|
||||
config.Name = server.Name
|
||||
@@ -1044,7 +1066,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
|
||||
// ServerNames
|
||||
if IsNotNull(server.ServerNames) {
|
||||
serverNames := []*serverconfigs.ServerNameConfig{}
|
||||
var serverNames = []*serverconfigs.ServerNameConfig{}
|
||||
err := json.Unmarshal(server.ServerNames, &serverNames)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1060,20 +1082,29 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
return nil, err
|
||||
}
|
||||
if clusterDNS != nil && clusterDNS.DnsDomainId > 0 {
|
||||
clusterDNSConfig, err := clusterDNS.DecodeDNSConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
domain, err := dns.SharedDNSDomainDAO.FindEnabledDNSDomain(tx, int64(clusterDNS.DnsDomainId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if domain != nil {
|
||||
cname := server.DnsName + "." + domain.Name
|
||||
config.AliasServerNames = append(config.AliasServerNames, cname)
|
||||
var cname = server.DnsName + "." + domain.Name
|
||||
config.CNameDomain = cname
|
||||
if clusterDNSConfig.CNameAsDomain {
|
||||
config.CNameAsDomain = true
|
||||
config.AliasServerNames = append(config.AliasServerNames, cname)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP
|
||||
if IsNotNull(server.Http) {
|
||||
httpConfig := &serverconfigs.HTTPProtocolConfig{}
|
||||
var httpConfig = &serverconfigs.HTTPProtocolConfig{}
|
||||
err := json.Unmarshal(server.Http, httpConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1083,7 +1114,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
|
||||
// HTTPS
|
||||
if IsNotNull(server.Https) {
|
||||
httpsConfig := &serverconfigs.HTTPSProtocolConfig{}
|
||||
var httpsConfig = &serverconfigs.HTTPSProtocolConfig{}
|
||||
err := json.Unmarshal(server.Https, httpsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1105,7 +1136,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
|
||||
// TCP
|
||||
if IsNotNull(server.Tcp) {
|
||||
tcpConfig := &serverconfigs.TCPProtocolConfig{}
|
||||
var tcpConfig = &serverconfigs.TCPProtocolConfig{}
|
||||
err := json.Unmarshal(server.Tcp, tcpConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1115,7 +1146,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
|
||||
// TLS
|
||||
if IsNotNull(server.Tls) {
|
||||
tlsConfig := &serverconfigs.TLSProtocolConfig{}
|
||||
var tlsConfig = &serverconfigs.TLSProtocolConfig{}
|
||||
err := json.Unmarshal(server.Tls, tlsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1137,7 +1168,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
|
||||
// Unix
|
||||
if IsNotNull(server.Unix) {
|
||||
unixConfig := &serverconfigs.UnixProtocolConfig{}
|
||||
var unixConfig = &serverconfigs.UnixProtocolConfig{}
|
||||
err := json.Unmarshal(server.Unix, unixConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1147,7 +1178,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
|
||||
// UDP
|
||||
if IsNotNull(server.Udp) {
|
||||
udpConfig := &serverconfigs.UDPProtocolConfig{}
|
||||
var udpConfig = &serverconfigs.UDPProtocolConfig{}
|
||||
err := json.Unmarshal(server.Udp, udpConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1168,7 +1199,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
|
||||
// ReverseProxy
|
||||
if IsNotNull(server.ReverseProxy) {
|
||||
reverseProxyRef := &serverconfigs.ReverseProxyRef{}
|
||||
var reverseProxyRef = &serverconfigs.ReverseProxyRef{}
|
||||
err := json.Unmarshal(server.ReverseProxy, reverseProxyRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1185,7 +1216,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap
|
||||
}
|
||||
|
||||
// WAF策略
|
||||
clusterId := int64(server.ClusterId)
|
||||
var clusterId = int64(server.ClusterId)
|
||||
httpFirewallPolicyId, err := SharedNodeClusterDAO.FindClusterHTTPFirewallPolicyId(tx, clusterId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1476,6 +1507,7 @@ func (this *ServerDAO) FindAllServersDNSWithClusterId(tx *dbs.Tx, clusterId int6
|
||||
}
|
||||
|
||||
// FindAllEnabledServersWithDomain 根据域名查找服务
|
||||
// TODO 需要改成使用plainServerNames
|
||||
func (this *ServerDAO) FindAllEnabledServersWithDomain(tx *dbs.Tx, domain string) (result []*Server, err error) {
|
||||
if len(domain) == 0 {
|
||||
return
|
||||
@@ -1523,6 +1555,49 @@ func (this *ServerDAO) FindAllEnabledServersWithDomain(tx *dbs.Tx, domain string
|
||||
return
|
||||
}
|
||||
|
||||
// FindEnabledServerWithDomain 根据域名查找服务集群ID
|
||||
func (this *ServerDAO) FindEnabledServerWithDomain(tx *dbs.Tx, domain string) (server *Server, err error) {
|
||||
if len(domain) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
one, err := this.Query(tx).
|
||||
State(ServerStateEnabled).
|
||||
Where("JSON_CONTAINS(plainServerNames, :domain)").
|
||||
Param("domain", strconv.Quote(domain)).
|
||||
Result("id", "userId", "clusterId").
|
||||
AscPk().
|
||||
Find()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if one != nil {
|
||||
return one.(*Server), nil
|
||||
}
|
||||
|
||||
// 尝试泛解析
|
||||
var dotIndex = strings.Index(domain, ".")
|
||||
if dotIndex > 0 {
|
||||
var wildcardDomain = "*." + domain[dotIndex+1:]
|
||||
one, err = this.Query(tx).
|
||||
State(ServerStateEnabled).
|
||||
Where("JSON_CONTAINS(plainServerNames, :domain)").
|
||||
Param("domain", strconv.Quote(wildcardDomain)).
|
||||
Result("id", "userId", "clusterId").
|
||||
AscPk().
|
||||
Find()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if one != nil {
|
||||
return one.(*Server), nil
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GenerateServerDNSName 重新生成子域名
|
||||
func (this *ServerDAO) GenerateServerDNSName(tx *dbs.Tx, serverId int64) (string, error) {
|
||||
if serverId <= 0 {
|
||||
@@ -1650,6 +1725,7 @@ func (this *ServerDAO) CheckUserServer(tx *dbs.Tx, userId int64, serverId int64)
|
||||
func (this *ServerDAO) UpdateUserServersClusterId(tx *dbs.Tx, userId int64, oldClusterId, newClusterId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Attr("userId", userId).
|
||||
Attr("userPlanId", 0).
|
||||
Set("clusterId", newClusterId).
|
||||
Update()
|
||||
if err != nil {
|
||||
|
||||
@@ -3,6 +3,7 @@ package models_test
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
@@ -10,10 +11,36 @@ import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestServerDAO_CreateManyServers(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var dao = models.NewServerDAO()
|
||||
var tx *dbs.Tx
|
||||
var count = 10000
|
||||
for i := 0; i < count; i++ {
|
||||
var serverNames = []*serverconfigs.ServerNameConfig{
|
||||
{
|
||||
Name: "s" + types.String(i) + ".teaos.cn",
|
||||
},
|
||||
}
|
||||
serverNamesJSON, err := json.Marshal(serverNames)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
serverId, err := dao.CreateServer(tx, 0, 0, serverconfigs.ServerTypeHTTPProxy, "TEST"+types.String(i), "", serverNamesJSON, false, nil, nil, nil, nil, nil, nil, nil, 0, nil, 1, nil, nil, nil, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_ = serverId
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerDAO_ComposeServerConfig(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
var tx *dbs.Tx
|
||||
@@ -195,6 +222,25 @@ func TestServerDAO_FindAllEnabledServersWithDomain(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerDAO_FindEnabledServerWithDomain(t *testing.T) {
|
||||
var dao = models.NewServerDAO()
|
||||
var tx *dbs.Tx
|
||||
|
||||
for _, domain := range []string{"a", "a.com", "teaos.cn", "www.teaos.cn", "cdn.teaos.cn", "google.com"} {
|
||||
var before = time.Now()
|
||||
server, err := dao.FindEnabledServerWithDomain(tx, domain)
|
||||
var costMs = time.Since(before).Seconds() * 1000
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if server == nil {
|
||||
t.Log(domain, "NULL", fmt.Sprintf("%.2fms", costMs))
|
||||
} else {
|
||||
t.Log(domain, string(maps.Map{"id": server.Id, "clusterId": server.ClusterId, "userId": server.UserId}.AsJSON()), fmt.Sprintf("%.2fms", costMs))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerDAO_UpdateServerTrafficLimitStatus(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
|
||||
@@ -410,6 +410,17 @@ func (this *ServerGroupDAO) CheckUserGroup(tx *dbs.Tx, userId int64, groupId int
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExistsGroup 检查分组ID是否存在
|
||||
func (this *ServerGroupDAO) ExistsGroup(tx *dbs.Tx, groupId int64) (bool, error) {
|
||||
if groupId <= 0 {
|
||||
return false, nil
|
||||
}
|
||||
return this.Query(tx).
|
||||
Pk(groupId).
|
||||
State(ServerGroupStateEnabled).
|
||||
Exist()
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *ServerGroupDAO) NotifyUpdate(tx *dbs.Tx, groupId int64) error {
|
||||
serverIds, err := SharedServerDAO.FindAllEnabledServerIdsWithGroupId(tx, groupId)
|
||||
|
||||
143
internal/db/models/user_bandwidth_stat_dao.go
Normal file
143
internal/db/models/user_bandwidth_stat_dao.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type UserBandwidthStatDAO dbs.DAO
|
||||
|
||||
const (
|
||||
UserBandwidthStatTablePartials = 20
|
||||
)
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
// 清理数据任务
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedUserBandwidthStatDAO.Clean(nil)
|
||||
if err != nil {
|
||||
remotelogs.Error("SharedUserBandwidthStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func NewUserBandwidthStatDAO() *UserBandwidthStatDAO {
|
||||
return dbs.NewDAO(&UserBandwidthStatDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeUserBandwidthStats",
|
||||
Model: new(UserBandwidthStat),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*UserBandwidthStatDAO)
|
||||
}
|
||||
|
||||
var SharedUserBandwidthStatDAO *UserBandwidthStatDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedUserBandwidthStatDAO = NewUserBandwidthStatDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateUserBandwidth 写入数据
|
||||
func (this *UserBandwidthStatDAO) UpdateUserBandwidth(tx *dbs.Tx, userId int64, day string, timeAt string, bytes int64) error {
|
||||
if userId <= 0 {
|
||||
// 如果用户ID不大于0,则说明服务不属于任何用户,此时不需要处理
|
||||
return nil
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
Table(this.partialTable(userId)).
|
||||
Param("bytes", bytes).
|
||||
InsertOrUpdateQuickly(maps.Map{
|
||||
"userId": userId,
|
||||
"day": day,
|
||||
"timeAt": timeAt,
|
||||
"bytes": bytes,
|
||||
}, maps.Map{
|
||||
"bytes": dbs.SQL("bytes+:bytes"),
|
||||
})
|
||||
}
|
||||
|
||||
// FindUserPeekBandwidthInMonth 读取某月带宽峰值
|
||||
// month YYYYMM
|
||||
func (this *UserBandwidthStatDAO) FindUserPeekBandwidthInMonth(tx *dbs.Tx, userId int64, month string) (*UserBandwidthStat, error) {
|
||||
one, err := this.Query(tx).
|
||||
Table(this.partialTable(userId)).
|
||||
Attr("userId", userId).
|
||||
Between("day", month+"01", month+"31").
|
||||
Desc("bytes").
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
}
|
||||
return one.(*UserBandwidthStat), nil
|
||||
}
|
||||
|
||||
// FindUserPeekBandwidthInDay 读取某日带宽峰值
|
||||
// day YYYYMMDD
|
||||
func (this *UserBandwidthStatDAO) FindUserPeekBandwidthInDay(tx *dbs.Tx, userId int64, day string) (*UserBandwidthStat, error) {
|
||||
one, err := this.Query(tx).
|
||||
Table(this.partialTable(userId)).
|
||||
Attr("userId", userId).
|
||||
Attr("day", day).
|
||||
Desc("bytes").
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
}
|
||||
return one.(*UserBandwidthStat), nil
|
||||
}
|
||||
|
||||
// Clean 清理过期数据
|
||||
func (this *UserBandwidthStatDAO) Clean(tx *dbs.Tx) error {
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -62)) // 保留大约2个月的数据
|
||||
return this.runBatch(func(table string, locker *sync.Mutex) error {
|
||||
_, err := this.Query(tx).
|
||||
Table(table).
|
||||
Lt("day", day).
|
||||
Delete()
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// 批量执行
|
||||
func (this *UserBandwidthStatDAO) runBatch(f func(table string, locker *sync.Mutex) error) error {
|
||||
var locker = &sync.Mutex{}
|
||||
var wg = sync.WaitGroup{}
|
||||
wg.Add(UserBandwidthStatTablePartials)
|
||||
var resultErr error
|
||||
for i := 0; i < UserBandwidthStatTablePartials; i++ {
|
||||
var table = this.partialTable(int64(i))
|
||||
go func(table string) {
|
||||
defer wg.Done()
|
||||
|
||||
err := f(table, locker)
|
||||
if err != nil {
|
||||
resultErr = err
|
||||
}
|
||||
}(table)
|
||||
}
|
||||
wg.Wait()
|
||||
return resultErr
|
||||
}
|
||||
|
||||
// 获取分区表
|
||||
func (this *UserBandwidthStatDAO) partialTable(userId int64) string {
|
||||
return this.Table + "_" + types.String(userId%int64(UserBandwidthStatTablePartials))
|
||||
}
|
||||
30
internal/db/models/user_bandwidth_stat_dao_test.go
Normal file
30
internal/db/models/user_bandwidth_stat_dao_test.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package models_test
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUserBandwidthStatDAO_UpdateServerBandwidth(t *testing.T) {
|
||||
var dao = models.NewUserBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
err := dao.UpdateUserBandwidth(tx, 1, timeutil.Format("Ymd"), timeutil.Format("Hi"), 1024)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestUserBandwidthStatDAO_Clean(t *testing.T) {
|
||||
var dao = models.NewUserBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
err := dao.Clean(tx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
22
internal/db/models/user_bandwidth_stat_model.go
Normal file
22
internal/db/models/user_bandwidth_stat_model.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package models
|
||||
|
||||
// UserBandwidthStat 用户月带宽峰值
|
||||
type UserBandwidthStat struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
Day string `field:"day"` // 日期YYYYMMDD
|
||||
TimeAt string `field:"timeAt"` // 时间点HHII
|
||||
Bytes uint64 `field:"bytes"` // 带宽
|
||||
}
|
||||
|
||||
type UserBandwidthStatOperator struct {
|
||||
Id interface{} // ID
|
||||
UserId interface{} // 用户ID
|
||||
Day interface{} // 日期YYYYMMDD
|
||||
TimeAt interface{} // 时间点HHII
|
||||
Bytes interface{} // 带宽
|
||||
}
|
||||
|
||||
func NewUserBandwidthStatOperator() *UserBandwidthStatOperator {
|
||||
return &UserBandwidthStatOperator{}
|
||||
}
|
||||
1
internal/db/models/user_bandwidth_stat_model_ext.go
Normal file
1
internal/db/models/user_bandwidth_stat_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package models
|
||||
@@ -236,7 +236,7 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error {
|
||||
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -257,7 +257,7 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error {
|
||||
percentile = 100
|
||||
}
|
||||
}
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -306,7 +306,7 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error {
|
||||
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -343,7 +343,7 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error {
|
||||
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -361,7 +361,7 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error {
|
||||
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -382,7 +382,7 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error {
|
||||
percentile = 100
|
||||
}
|
||||
}
|
||||
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ func (this *UserDAO) UpdateUser(tx *dbs.Tx, userId int64, username string, passw
|
||||
if userId <= 0 {
|
||||
return errors.New("invalid userId")
|
||||
}
|
||||
op := NewUserOperator()
|
||||
var op = NewUserOperator()
|
||||
op.Id = userId
|
||||
op.Username = username
|
||||
if len(password) > 0 {
|
||||
|
||||
184
internal/db/models/user_identity_dao.go
Normal file
184
internal/db/models/user_identity_dao.go
Normal file
@@ -0,0 +1,184 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
UserIdentityStateEnabled = 1 // 已启用
|
||||
UserIdentityStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type UserIdentityDAO dbs.DAO
|
||||
|
||||
func NewUserIdentityDAO() *UserIdentityDAO {
|
||||
return dbs.NewDAO(&UserIdentityDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeUserIdentities",
|
||||
Model: new(UserIdentity),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*UserIdentityDAO)
|
||||
}
|
||||
|
||||
var SharedUserIdentityDAO *UserIdentityDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedUserIdentityDAO = NewUserIdentityDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableUserIdentity 启用条目
|
||||
func (this *UserIdentityDAO) EnableUserIdentity(tx *dbs.Tx, id uint64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", UserIdentityStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableUserIdentity 禁用条目
|
||||
func (this *UserIdentityDAO) DisableUserIdentity(tx *dbs.Tx, id uint64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", UserIdentityStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// FindEnabledUserIdentity 查找启用中的条目
|
||||
func (this *UserIdentityDAO) FindEnabledUserIdentity(tx *dbs.Tx, id int64) (*UserIdentity, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", UserIdentityStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*UserIdentity), err
|
||||
}
|
||||
|
||||
// CreateUserIdentity 创建
|
||||
func (this *UserIdentityDAO) CreateUserIdentity(tx *dbs.Tx, userId int64, idType userconfigs.UserIdentityType, realName string, number string, fileIds []int64) (int64, error) {
|
||||
var op = NewUserIdentityOperator()
|
||||
op.UserId = userId
|
||||
op.Type = idType
|
||||
op.RealName = realName
|
||||
op.Number = number
|
||||
|
||||
if fileIds == nil {
|
||||
fileIds = []int64{}
|
||||
}
|
||||
fileIdsJSON, err := json.Marshal(fileIds)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.FileIds = fileIdsJSON
|
||||
|
||||
op.Status = userconfigs.UserIdentityStatusNone
|
||||
op.State = UserIdentityStateEnabled
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// UpdateUserIdentity 修改
|
||||
func (this *UserIdentityDAO) UpdateUserIdentity(tx *dbs.Tx, identityId int64, idType userconfigs.UserIdentityType, realName string, number string, fileIds []int64) error {
|
||||
if identityId <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var op = NewUserIdentityOperator()
|
||||
op.Id = identityId
|
||||
op.Type = idType
|
||||
op.Number = number
|
||||
|
||||
if fileIds == nil {
|
||||
fileIds = []int64{}
|
||||
}
|
||||
fileIdsJSON, err := json.Marshal(fileIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.FileIds = fileIdsJSON
|
||||
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// SubmitUserIdentity 提交审核
|
||||
func (this *UserIdentityDAO) SubmitUserIdentity(tx *dbs.Tx, identityId int64) error {
|
||||
return this.Query(tx).
|
||||
Pk(identityId).
|
||||
Set("status", userconfigs.UserIdentityStatusSubmitted).
|
||||
Set("submittedAt", time.Now().Unix()).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// CancelUserIdentity 取消提交审核
|
||||
func (this *UserIdentityDAO) CancelUserIdentity(tx *dbs.Tx, identityId int64) error {
|
||||
return this.Query(tx).
|
||||
Pk(identityId).
|
||||
Set("status", userconfigs.UserIdentityStatusNone).
|
||||
Set("updatedAt", time.Now().Unix()).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// RejectUserIdentity 拒绝
|
||||
func (this *UserIdentityDAO) RejectUserIdentity(tx *dbs.Tx, identityId int64) error {
|
||||
return this.Query(tx).
|
||||
Pk(identityId).
|
||||
Set("status", userconfigs.UserIdentityStatusRejected).
|
||||
Set("rejectedAt", time.Now().Unix()).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// VerifyUserIdentity 通过
|
||||
func (this *UserIdentityDAO) VerifyUserIdentity(tx *dbs.Tx, identityId int64) error {
|
||||
return this.Query(tx).
|
||||
Pk(identityId).
|
||||
Set("status", userconfigs.UserIdentityStatusVerified).
|
||||
Set("verifiedAt", time.Now().Unix()).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// CheckUserIdentity 检查用户认证
|
||||
func (this *UserIdentityDAO) CheckUserIdentity(tx *dbs.Tx, userId int64, identityId int64) error {
|
||||
b, err := this.Query(tx).
|
||||
Pk(identityId).
|
||||
Attr("userId", userId).
|
||||
State(UserIdentityStateEnabled).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !b {
|
||||
return ErrNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindUserIdentityStatus 查找认证信息当前状态
|
||||
func (this *UserIdentityDAO) FindUserIdentityStatus(tx *dbs.Tx, identityId int64) (userconfigs.UserIdentityStatus, error) {
|
||||
return this.Query(tx).
|
||||
Pk(identityId).
|
||||
Result("status").
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// FindEnabledUserIdentityWithType 查找某个类型的认证信息
|
||||
func (this *UserIdentityDAO) FindEnabledUserIdentityWithType(tx *dbs.Tx, userId int64, idType userconfigs.UserIdentityType) (*UserIdentity, error) {
|
||||
one, err := this.Query(tx).
|
||||
Attr("userId", userId).
|
||||
Attr("type", idType).
|
||||
State(UserIdentityStateEnabled).
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
}
|
||||
return one.(*UserIdentity), nil
|
||||
}
|
||||
6
internal/db/models/user_identity_dao_test.go
Normal file
6
internal/db/models/user_identity_dao_test.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package models_test
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
40
internal/db/models/user_identity_model.go
Normal file
40
internal/db/models/user_identity_model.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// UserIdentity 用户实名认证信息
|
||||
type UserIdentity struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
Type string `field:"type"` // 类型
|
||||
RealName string `field:"realName"` // 真实姓名
|
||||
Number string `field:"number"` // 编号
|
||||
FileIds dbs.JSON `field:"fileIds"` // 文件ID
|
||||
Status string `field:"status"` // 状态:none,submitted,verified,rejected
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
|
||||
SubmittedAt uint64 `field:"submittedAt"` // 提交时间
|
||||
RejectedAt uint64 `field:"rejectedAt"` // 拒绝时间
|
||||
VerifiedAt uint64 `field:"verifiedAt"` // 认证时间
|
||||
}
|
||||
|
||||
type UserIdentityOperator struct {
|
||||
Id interface{} // ID
|
||||
UserId interface{} // 用户ID
|
||||
Type interface{} // 类型
|
||||
RealName interface{} // 真实姓名
|
||||
Number interface{} // 编号
|
||||
FileIds interface{} // 文件ID
|
||||
Status interface{} // 状态:none,submitted,verified,rejected
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
UpdatedAt interface{} // 修改时间
|
||||
SubmittedAt interface{} // 提交时间
|
||||
RejectedAt interface{} // 拒绝时间
|
||||
VerifiedAt interface{} // 认证时间
|
||||
}
|
||||
|
||||
func NewUserIdentityOperator() *UserIdentityOperator {
|
||||
return &UserIdentityOperator{}
|
||||
}
|
||||
16
internal/db/models/user_identity_model_ext.go
Normal file
16
internal/db/models/user_identity_model_ext.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package models
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
func (this *UserIdentity) DecodeFileIds() []int64 {
|
||||
if len(this.FileIds) == 0 {
|
||||
return []int64{}
|
||||
}
|
||||
|
||||
var result = []int64{}
|
||||
err := json.Unmarshal(this.FileIds, &result)
|
||||
if err != nil {
|
||||
// ignore error
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -51,12 +51,17 @@ func (this *UserNodeDAO) EnableUserNode(tx *dbs.Tx, id uint32) error {
|
||||
}
|
||||
|
||||
// DisableUserNode 禁用条目
|
||||
func (this *UserNodeDAO) DisableUserNode(tx *dbs.Tx, id int64) error {
|
||||
func (this *UserNodeDAO) DisableUserNode(tx *dbs.Tx, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Pk(nodeId).
|
||||
Set("state", UserNodeStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除运行日志
|
||||
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleUser, nodeId)
|
||||
}
|
||||
|
||||
// FindEnabledUserNode 查找启用中的条目
|
||||
@@ -254,13 +259,19 @@ func (this *UserNodeDAO) GenUniqueId(tx *dbs.Tx) (string, error) {
|
||||
}
|
||||
|
||||
// UpdateNodeStatus 更改节点状态
|
||||
func (this *UserNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, statusJSON []byte) error {
|
||||
if len(statusJSON) == 0 {
|
||||
func (this *UserNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, nodeStatus *nodeconfigs.NodeStatus) error {
|
||||
if nodeStatus == nil {
|
||||
return nil
|
||||
}
|
||||
_, err := this.Query(tx).
|
||||
|
||||
nodeStatusJSON, err := json.Marshal(nodeStatus)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Pk(nodeId).
|
||||
Set("status", string(statusJSON)).
|
||||
Set("status", nodeStatusJSON).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -17,18 +17,26 @@ type AliDNSProvider struct {
|
||||
|
||||
accessKeyId string
|
||||
accessKeySecret string
|
||||
regionId string
|
||||
}
|
||||
|
||||
// Auth 认证
|
||||
func (this *AliDNSProvider) Auth(params maps.Map) error {
|
||||
this.accessKeyId = params.GetString("accessKeyId")
|
||||
this.accessKeySecret = params.GetString("accessKeySecret")
|
||||
this.regionId = params.GetString("regionId")
|
||||
|
||||
if len(this.accessKeyId) == 0 {
|
||||
return errors.New("'accessKeyId' should not be empty")
|
||||
}
|
||||
if len(this.accessKeySecret) == 0 {
|
||||
return errors.New("'accessKeySecret' should not be empty")
|
||||
}
|
||||
|
||||
if len(this.regionId) == 0 {
|
||||
this.regionId = "cn-hangzhou"
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -196,7 +204,7 @@ func (this *AliDNSProvider) DefaultRoute() string {
|
||||
func (this *AliDNSProvider) doAPI(req requests.AcsRequest, resp responses.AcsResponse) error {
|
||||
req.SetScheme("https")
|
||||
|
||||
client, err := alidns.NewClientWithAccessKey("cn-hangzhou", this.accessKeyId, this.accessKeySecret)
|
||||
client, err := alidns.NewClientWithAccessKey(this.regionId, this.accessKeyId, this.accessKeySecret)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ func TestAliDNSProvider_AddRecord(t *testing.T) {
|
||||
Name: "test",
|
||||
Type: dnstypes.RecordTypeA,
|
||||
Value: "192.168.1.100",
|
||||
Route: "unicom",
|
||||
Route: "aliyun_r_cn-beijing",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -103,7 +103,7 @@ func testAliDNSProvider() (ProviderInterface, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
one, err := db.FindOne("SELECT * FROM edgeDNSProviders WHERE type='alidns' ORDER BY id DESC")
|
||||
one, err := db.FindOne("SELECT * FROM edgeDNSProviders WHERE type='alidns' AND state=1 ORDER BY id DESC")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ const (
|
||||
ProviderTypeDNSPod ProviderType = "dnspod" // DNSPod
|
||||
ProviderTypeAliDNS ProviderType = "alidns" // 阿里云DNS
|
||||
ProviderTypeHuaweiDNS ProviderType = "huaweiDNS" // 华为DNS
|
||||
ProviderTypeDNSCom ProviderType = "dnscom" // dns.com
|
||||
ProviderTypeCloudFlare ProviderType = "cloudFlare" // CloudFlare DNS
|
||||
ProviderTypeLocalEdgeDNS ProviderType = "localEdgeDNS" // 和当前系统集成的EdgeDNS
|
||||
ProviderTypeUserEdgeDNS ProviderType = "userEdgeDNS" // 通过API连接的EdgeDNS
|
||||
@@ -36,11 +35,6 @@ func FindAllProviderTypes() []maps.Map {
|
||||
"code": ProviderTypeHuaweiDNS,
|
||||
"description": "华为云解析DNS。",
|
||||
},
|
||||
/**{
|
||||
"name": "帝恩思DNS.COM",
|
||||
"code": ProviderTypeDNSCom,
|
||||
"description": "DNS.com提供的DNS服务。",
|
||||
},**/
|
||||
{
|
||||
"name": "CloudFlare DNS",
|
||||
"code": ProviderTypeCloudFlare,
|
||||
|
||||
90
internal/installers/upgrade_limiter.go
Normal file
90
internal/installers/upgrade_limiter.go
Normal file
@@ -0,0 +1,90 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package installers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/sizes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
UpgradeLimiterDuration = 10 // node key expire time, by seconds
|
||||
UpgradeLimiterConcurrent = 10 // 10 nodes
|
||||
UpgradeLimiterMaxBytesPerSecond = 5 * sizes.M // max bytes per second
|
||||
)
|
||||
|
||||
var SharedUpgradeLimiter = NewUpgradeLimiter()
|
||||
|
||||
// UpgradeLimiter 升级流量管理器
|
||||
type UpgradeLimiter struct {
|
||||
nodeMap map[string]int64 // key => timestamp
|
||||
|
||||
rateTimestamp int64
|
||||
rateBytes int64
|
||||
|
||||
locker sync.Mutex
|
||||
}
|
||||
|
||||
func NewUpgradeLimiter() *UpgradeLimiter {
|
||||
return &UpgradeLimiter{
|
||||
nodeMap: map[string]int64{},
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateNodeBytes 添加正在下载的节点流量
|
||||
func (this *UpgradeLimiter) UpdateNodeBytes(nodeType nodeconfigs.NodeRole, nodeId int64, bytes int64) {
|
||||
this.locker.Lock()
|
||||
defer this.locker.Unlock()
|
||||
|
||||
// 先清理
|
||||
var nowTime = time.Now().Unix()
|
||||
this.gc(nowTime)
|
||||
|
||||
// 添加
|
||||
var key = nodeType + "_" + types.String(nodeId)
|
||||
this.nodeMap[key] = nowTime
|
||||
|
||||
// 流量
|
||||
if this.rateTimestamp == nowTime {
|
||||
this.rateBytes += bytes
|
||||
} else {
|
||||
this.rateTimestamp = nowTime
|
||||
this.rateBytes = bytes
|
||||
}
|
||||
}
|
||||
|
||||
// CanUpgrade 检查是否有新的升级
|
||||
func (this *UpgradeLimiter) CanUpgrade() bool {
|
||||
this.locker.Lock()
|
||||
defer this.locker.Unlock()
|
||||
|
||||
var nowTime = time.Now().Unix()
|
||||
this.gc(nowTime)
|
||||
|
||||
// 限制并发节点数
|
||||
if len(this.nodeMap) >= UpgradeLimiterConcurrent {
|
||||
return false
|
||||
}
|
||||
|
||||
if this.rateTimestamp != nowTime {
|
||||
return true
|
||||
}
|
||||
|
||||
// 限制下载速度
|
||||
if this.rateBytes >= UpgradeLimiterMaxBytesPerSecond {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (this *UpgradeLimiter) gc(nowTime int64) {
|
||||
for nodeKey, timestamp := range this.nodeMap {
|
||||
if timestamp < nowTime-UpgradeLimiterDuration {
|
||||
delete(this.nodeMap, nodeKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
27
internal/installers/upgrade_limiter_test.go
Normal file
27
internal/installers/upgrade_limiter_test.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package installers_test
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/installers"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/sizes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestNewUpgradeLimiter(t *testing.T) {
|
||||
var limiter = installers.NewUpgradeLimiter()
|
||||
limiter.UpdateNodeBytes(nodeconfigs.NodeRoleNode, 1, 1)
|
||||
limiter.UpdateNodeBytes(nodeconfigs.NodeRoleNode, 2, 5*sizes.M)
|
||||
t.Log("limiter:", limiter)
|
||||
t.Log("canUpgrade:", limiter.CanUpgrade())
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
t.Log("canUpgrade:", limiter.CanUpgrade())
|
||||
t.Log("limiter:", limiter)
|
||||
limiter.UpdateNodeBytes(nodeconfigs.NodeRoleNode, 2, 4*sizes.M)
|
||||
t.Log("canUpgrade:", limiter.CanUpgrade())
|
||||
|
||||
t.Log("limiter:", limiter)
|
||||
}
|
||||
@@ -3,8 +3,8 @@ package nodes
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/accesslogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/configs"
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/rpc"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/setup"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
@@ -35,6 +36,7 @@ import (
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -51,12 +53,18 @@ type APINode struct {
|
||||
sock *gosock.Sock
|
||||
|
||||
isStarting bool
|
||||
|
||||
issues []*StartIssue
|
||||
issuesFile string
|
||||
}
|
||||
|
||||
func NewAPINode() *APINode {
|
||||
return &APINode{
|
||||
serviceInstanceMap: map[string]interface{}{},
|
||||
sock: gosock.NewTmpSock(teaconst.ProcessName),
|
||||
|
||||
issues: []*StartIssue{},
|
||||
issuesFile: Tea.LogFile("issues.log"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,18 +73,27 @@ func (this *APINode) Start() {
|
||||
|
||||
logs.Println("[API_NODE]start api node, pid: " + strconv.Itoa(os.Getpid()))
|
||||
|
||||
// 检查数据库连接
|
||||
err := this.checkDB()
|
||||
if err != nil {
|
||||
logs.Println("[API_NODE]" + err.Error())
|
||||
return
|
||||
}
|
||||
// 保存启动过程中的问题,以便于查看
|
||||
defer func() {
|
||||
this.saveIssues()
|
||||
}()
|
||||
|
||||
// 本地Sock
|
||||
logs.Println("[API_NODE]listening sock ...")
|
||||
err = this.listenSock()
|
||||
err := this.listenSock()
|
||||
if err != nil {
|
||||
logs.Println("[API_NODE]" + err.Error())
|
||||
var errString = "start local sock failed: " + err.Error()
|
||||
logs.Println("[API_NODE]" + errString)
|
||||
this.addStartIssue("sock", errString, "")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查数据库连接
|
||||
err = this.checkDB()
|
||||
if err != nil {
|
||||
var errString = "check database connection failed: " + err.Error()
|
||||
logs.Println("[API_NODE]" + errString)
|
||||
this.addStartIssue("db", errString, this.dbIssueSuggestion(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -84,7 +101,9 @@ func (this *APINode) Start() {
|
||||
logs.Println("[API_NODE]auto upgrading ...")
|
||||
err = this.autoUpgrade()
|
||||
if err != nil {
|
||||
logs.Println("[API_NODE]auto upgrade failed: " + err.Error())
|
||||
var errString = "auto upgrade failed: " + err.Error()
|
||||
logs.Println("[API_NODE]" + errString)
|
||||
this.addStartIssue("db", errString, this.dbIssueSuggestion(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -105,7 +124,9 @@ func (this *APINode) Start() {
|
||||
logs.Println("[API_NODE]reading api config ...")
|
||||
config, err := configs.SharedAPIConfig()
|
||||
if err != nil {
|
||||
logs.Println("[API_NODE]start failed: " + err.Error())
|
||||
var errString = "read api config failed: " + err.Error()
|
||||
logs.Println("[API_NODE]" + errString)
|
||||
this.addStartIssue("config", errString, "")
|
||||
return
|
||||
}
|
||||
sharedAPIConfig = config
|
||||
@@ -113,15 +134,23 @@ func (this *APINode) Start() {
|
||||
// 校验
|
||||
apiNode, err := models.SharedAPINodeDAO.FindEnabledAPINodeWithUniqueIdAndSecret(nil, config.NodeId, config.Secret)
|
||||
if err != nil {
|
||||
logs.Println("[API_NODE]start failed: read api node from database failed: " + err.Error())
|
||||
var errString = "start failed: read api node from database failed: " + err.Error()
|
||||
logs.Println("[API_NODE]" + errString)
|
||||
this.addStartIssue("db", errString, "")
|
||||
return
|
||||
}
|
||||
if apiNode == nil {
|
||||
logs.Println("[API_NODE]can not start node, wrong 'nodeId' or 'secret'")
|
||||
var errString = "can not start node, wrong 'nodeId' or 'secret'"
|
||||
logs.Println("[API_NODE]" + errString)
|
||||
this.addStartIssue("config", errString, "请在api.yaml配置文件中填写正确的`nodeId`和`secret`,如果数据库或者管理节点或API节点是从别的服务器迁移过来的,请将老的系统配置拷贝到当前节点配置下")
|
||||
return
|
||||
}
|
||||
config.SetNumberId(int64(apiNode.Id))
|
||||
|
||||
// 清除上一次启动错误
|
||||
// 这个错误文件可能不存在,不需要处理错误
|
||||
_ = os.Remove(this.issuesFile)
|
||||
|
||||
// 设置rlimit
|
||||
_ = utils.SetRLimit(1024 * 1024)
|
||||
|
||||
@@ -138,10 +167,12 @@ func (this *APINode) Start() {
|
||||
// 监听RPC服务
|
||||
remotelogs.Println("API_NODE", "starting RPC server ...")
|
||||
|
||||
isListening := this.listenPorts(apiNode)
|
||||
var isListening = this.listenPorts(apiNode)
|
||||
|
||||
if !isListening {
|
||||
remotelogs.Error("API_NODE", "the api node require at least one listening address")
|
||||
var errString = "the api node require at least one listening address"
|
||||
remotelogs.Error("API_NODE", errString)
|
||||
this.addStartIssue("config", errString, "请给当前API节点设置一个监听端口")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -154,9 +185,8 @@ func (this *APINode) Start() {
|
||||
|
||||
// Daemon 实现守护进程
|
||||
func (this *APINode) Daemon() {
|
||||
path := os.TempDir() + "/edge-api.sock"
|
||||
isDebug := lists.ContainsString(os.Args, "debug")
|
||||
isDebug = true
|
||||
var path = os.TempDir() + "/" + teaconst.ProcessName + ".sock"
|
||||
var isDebug = lists.ContainsString(os.Args, "debug")
|
||||
for {
|
||||
conn, err := net.DialTimeout("unix", path, 1*time.Second)
|
||||
if err != nil {
|
||||
@@ -199,14 +229,14 @@ func (this *APINode) Daemon() {
|
||||
|
||||
// InstallSystemService 安装系统服务
|
||||
func (this *APINode) InstallSystemService() error {
|
||||
shortName := teaconst.SystemdServiceName
|
||||
var shortName = teaconst.SystemdServiceName
|
||||
|
||||
exe, err := os.Executable()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
manager := utils.NewServiceManager(shortName, teaconst.ProductName)
|
||||
var manager = utils.NewServiceManager(shortName, teaconst.ProductName)
|
||||
err = manager.Install(exe, []string{})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -242,21 +272,33 @@ func (this *APINode) checkDB() error {
|
||||
return err
|
||||
}
|
||||
|
||||
maxTries := 600
|
||||
for i := 0; i <= maxTries; i++ {
|
||||
_, err := db.Exec("SELECT 1")
|
||||
if err != nil {
|
||||
if i == maxTries-1 {
|
||||
return err
|
||||
} else {
|
||||
if i%10 == 0 { // 这让提示不会太多
|
||||
logs.Println("[API_NODE]reconnecting to database (" + fmt.Sprintf("%.1f", float32(i*100)/float32(maxTries+1)) + "%) ...")
|
||||
// 第一次测试连接
|
||||
_, err = db.Exec("SELECT 1")
|
||||
if err != nil {
|
||||
var errString = "check database connection failed: " + err.Error()
|
||||
logs.Println("[API_NODE]" + errString)
|
||||
this.addStartIssue("db", errString, this.dbIssueSuggestion(errString))
|
||||
|
||||
// 多次尝试
|
||||
var maxTries = 600
|
||||
if Tea.IsTesting() {
|
||||
maxTries = 600
|
||||
}
|
||||
for i := 0; i <= maxTries; i++ {
|
||||
_, err := db.Exec("SELECT 1")
|
||||
if err != nil {
|
||||
if i == maxTries-1 {
|
||||
return err
|
||||
} else {
|
||||
if i%10 == 0 { // 这让提示不会太多
|
||||
logs.Println("[API_NODE]check database connection failed: " + err.Error() + ", reconnecting to database ...")
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
} else {
|
||||
logs.Println("[API_NODE]database connected")
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
logs.Println("[API_NODE]database connected")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,7 +312,7 @@ func (this *APINode) autoUpgrade() error {
|
||||
}
|
||||
|
||||
// 执行SQL
|
||||
config := &dbs.Config{}
|
||||
var config = &dbs.Config{}
|
||||
configData, err := ioutil.ReadFile(Tea.ConfigFile("db.yaml"))
|
||||
if err != nil {
|
||||
return errors.New("read database config file failed: " + err.Error())
|
||||
@@ -681,3 +723,62 @@ func (this *APINode) unaryInterceptor(ctx context.Context, req interface{}, info
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
// 添加启动相关的Issue
|
||||
func (this *APINode) addStartIssue(code string, message string, suggestion string) {
|
||||
this.issues = append(this.issues, NewStartIssue(code, message, suggestion))
|
||||
this.saveIssues()
|
||||
}
|
||||
|
||||
// 增加数据库建议
|
||||
func (this *APINode) dbIssueSuggestion(errString string) string {
|
||||
// 数据库配置
|
||||
db, err := dbs.Default()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
config, err := db.Config()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
var dsn = config.Dsn
|
||||
dsnConfig, err := mysql.ParseDSN(dsn)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
var addr = dsnConfig.Addr
|
||||
|
||||
// 配置文件位置
|
||||
var dbConfigPath = Tea.ConfigFile("db.yaml")
|
||||
|
||||
// 连接被拒绝
|
||||
if strings.Contains(errString, "connection refused") {
|
||||
// 本机
|
||||
if strings.HasPrefix(addr, "127.0.0.1:") || strings.HasPrefix(addr, "localhost:") {
|
||||
return "试图连接到数据库被拒绝,请检查:1)本地数据库服务是否已经启动;2)数据库IP和端口(" + addr + ")是否正确;(当前数据库配置为:" + dsn + ",配置文件位置:" + dbConfigPath + ")。"
|
||||
} else {
|
||||
return "试图连接到数据库被拒绝,请检查:1)数据库服务是否已经启动;2)数据库IP和端口(" + addr + ")是否正确;3)防火墙设置;(当前数据库配置为:" + dsn + ",配置文件位置:" + dbConfigPath + ")。"
|
||||
}
|
||||
}
|
||||
|
||||
// 权限错误
|
||||
if strings.Contains(errString, "Error 1045") || strings.Contains(errString, "Error 1044") {
|
||||
return "使用的用户和密码没有权限连接到指定数据库,请检查:1)数据库配置文件中的用户名(" + dsnConfig.User + ")和密码(" + dsnConfig.Passwd + ")是否正确;2)使用的用户是否已经在数据库中设置了正确的权限;(当前数据库配置为:" + dsn + ",配置文件位置:" + dbConfigPath + ")。"
|
||||
}
|
||||
|
||||
// 数据库名称错误
|
||||
if strings.Contains(errString, "Error 1049") {
|
||||
return "数据库名称配置错误,请检查:数据库配置文件中数据库名称(" + dsnConfig.DBName + ")是否正确;(当前数据库配置为:" + dsn + ",配置文件位置:" + dbConfigPath + ")。"
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// 保存issues
|
||||
func (this *APINode) saveIssues() {
|
||||
issuesJSON, err := json.Marshal(this.issues)
|
||||
if err == nil {
|
||||
_ = ioutil.WriteFile(this.issuesFile, issuesJSON, 0666)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,567 +14,590 @@ import (
|
||||
// 注册服务
|
||||
func (this *APINode) registerServices(server *grpc.Server) {
|
||||
{
|
||||
instance := this.serviceInstance(&services.APITokenService{}).(*services.APITokenService)
|
||||
var instance = this.serviceInstance(&services.APITokenService{}).(*services.APITokenService)
|
||||
pb.RegisterAPITokenServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.AdminService{}).(*services.AdminService)
|
||||
var instance = this.serviceInstance(&services.AdminService{}).(*services.AdminService)
|
||||
pb.RegisterAdminServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeGrantService{}).(*services.NodeGrantService)
|
||||
var instance = this.serviceInstance(&services.NodeGrantService{}).(*services.NodeGrantService)
|
||||
pb.RegisterNodeGrantServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerService{}).(*services.ServerService)
|
||||
var instance = this.serviceInstance(&services.ServerService{}).(*services.ServerService)
|
||||
pb.RegisterServerServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeService{}).(*services.NodeService)
|
||||
var instance = this.serviceInstance(&services.NodeService{}).(*services.NodeService)
|
||||
pb.RegisterNodeServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeClusterService{}).(*services.NodeClusterService)
|
||||
var instance = this.serviceInstance(&services.NodeClusterService{}).(*services.NodeClusterService)
|
||||
pb.RegisterNodeClusterServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeIPAddressService{}).(*services.NodeIPAddressService)
|
||||
var instance = this.serviceInstance(&services.NodeIPAddressService{}).(*services.NodeIPAddressService)
|
||||
pb.RegisterNodeIPAddressServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeIPAddressLogService{}).(*services.NodeIPAddressLogService)
|
||||
var instance = this.serviceInstance(&services.NodeIPAddressLogService{}).(*services.NodeIPAddressLogService)
|
||||
pb.RegisterNodeIPAddressLogServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeIPAddressThresholdService{}).(*services.NodeIPAddressThresholdService)
|
||||
var instance = this.serviceInstance(&services.NodeIPAddressThresholdService{}).(*services.NodeIPAddressThresholdService)
|
||||
pb.RegisterNodeIPAddressThresholdServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.APINodeService{}).(*services.APINodeService)
|
||||
var instance = this.serviceInstance(&services.APINodeService{}).(*services.APINodeService)
|
||||
pb.RegisterAPINodeServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.APIMethodStatService{}).(*services.APIMethodStatService)
|
||||
var instance = this.serviceInstance(&services.APIMethodStatService{}).(*services.APIMethodStatService)
|
||||
pb.RegisterAPIMethodStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.OriginService{}).(*services.OriginService)
|
||||
var instance = this.serviceInstance(&services.OriginService{}).(*services.OriginService)
|
||||
pb.RegisterOriginServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPWebService{}).(*services.HTTPWebService)
|
||||
var instance = this.serviceInstance(&services.HTTPWebService{}).(*services.HTTPWebService)
|
||||
pb.RegisterHTTPWebServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ReverseProxyService{}).(*services.ReverseProxyService)
|
||||
var instance = this.serviceInstance(&services.ReverseProxyService{}).(*services.ReverseProxyService)
|
||||
pb.RegisterReverseProxyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPGzipService{}).(*services.HTTPGzipService)
|
||||
var instance = this.serviceInstance(&services.HTTPGzipService{}).(*services.HTTPGzipService)
|
||||
pb.RegisterHTTPGzipServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPHeaderPolicyService{}).(*services.HTTPHeaderPolicyService)
|
||||
var instance = this.serviceInstance(&services.HTTPHeaderPolicyService{}).(*services.HTTPHeaderPolicyService)
|
||||
pb.RegisterHTTPHeaderPolicyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPHeaderService{}).(*services.HTTPHeaderService)
|
||||
var instance = this.serviceInstance(&services.HTTPHeaderService{}).(*services.HTTPHeaderService)
|
||||
pb.RegisterHTTPHeaderServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPPageService{}).(*services.HTTPPageService)
|
||||
var instance = this.serviceInstance(&services.HTTPPageService{}).(*services.HTTPPageService)
|
||||
pb.RegisterHTTPPageServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPAccessLogPolicyService{}).(*services.HTTPAccessLogPolicyService)
|
||||
var instance = this.serviceInstance(&services.HTTPAccessLogPolicyService{}).(*services.HTTPAccessLogPolicyService)
|
||||
pb.RegisterHTTPAccessLogPolicyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPCachePolicyService{}).(*services.HTTPCachePolicyService)
|
||||
var instance = this.serviceInstance(&services.HTTPCachePolicyService{}).(*services.HTTPCachePolicyService)
|
||||
pb.RegisterHTTPCachePolicyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPFirewallPolicyService{}).(*services.HTTPFirewallPolicyService)
|
||||
var instance = this.serviceInstance(&services.HTTPFirewallPolicyService{}).(*services.HTTPFirewallPolicyService)
|
||||
pb.RegisterHTTPFirewallPolicyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.FirewallService{}).(*services.FirewallService)
|
||||
var instance = this.serviceInstance(&services.FirewallService{}).(*services.FirewallService)
|
||||
pb.RegisterFirewallServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPLocationService{}).(*services.HTTPLocationService)
|
||||
var instance = this.serviceInstance(&services.HTTPLocationService{}).(*services.HTTPLocationService)
|
||||
pb.RegisterHTTPLocationServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPWebsocketService{}).(*services.HTTPWebsocketService)
|
||||
var instance = this.serviceInstance(&services.HTTPWebsocketService{}).(*services.HTTPWebsocketService)
|
||||
pb.RegisterHTTPWebsocketServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPRewriteRuleService{}).(*services.HTTPRewriteRuleService)
|
||||
var instance = this.serviceInstance(&services.HTTPRewriteRuleService{}).(*services.HTTPRewriteRuleService)
|
||||
pb.RegisterHTTPRewriteRuleServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.SSLCertService{}).(*services.SSLCertService)
|
||||
var instance = this.serviceInstance(&services.SSLCertService{}).(*services.SSLCertService)
|
||||
pb.RegisterSSLCertServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.SSLPolicyService{}).(*services.SSLPolicyService)
|
||||
var instance = this.serviceInstance(&services.SSLPolicyService{}).(*services.SSLPolicyService)
|
||||
pb.RegisterSSLPolicyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.SysSettingService{}).(*services.SysSettingService)
|
||||
var instance = this.serviceInstance(&services.SysSettingService{}).(*services.SysSettingService)
|
||||
pb.RegisterSysSettingServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPFirewallRuleGroupService{}).(*services.HTTPFirewallRuleGroupService)
|
||||
var instance = this.serviceInstance(&services.HTTPFirewallRuleGroupService{}).(*services.HTTPFirewallRuleGroupService)
|
||||
pb.RegisterHTTPFirewallRuleGroupServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPFirewallRuleSetService{}).(*services.HTTPFirewallRuleSetService)
|
||||
var instance = this.serviceInstance(&services.HTTPFirewallRuleSetService{}).(*services.HTTPFirewallRuleSetService)
|
||||
pb.RegisterHTTPFirewallRuleSetServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.DBNodeService{}).(*services.DBNodeService)
|
||||
var instance = this.serviceInstance(&services.DBNodeService{}).(*services.DBNodeService)
|
||||
pb.RegisterDBNodeServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeLogService{}).(*services.NodeLogService)
|
||||
var instance = this.serviceInstance(&services.NodeLogService{}).(*services.NodeLogService)
|
||||
pb.RegisterNodeLogServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeLoginService{}).(*services.NodeLoginService)
|
||||
var instance = this.serviceInstance(&services.NodeLoginService{}).(*services.NodeLoginService)
|
||||
pb.RegisterNodeLoginServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPAccessLogService{}).(*services.HTTPAccessLogService)
|
||||
var instance = this.serviceInstance(&services.HTTPAccessLogService{}).(*services.HTTPAccessLogService)
|
||||
pb.RegisterHTTPAccessLogServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MessageService{}).(*services.MessageService)
|
||||
var instance = this.serviceInstance(&services.MessageService{}).(*services.MessageService)
|
||||
pb.RegisterMessageServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MessageRecipientService{}).(*services.MessageRecipientService)
|
||||
var instance = this.serviceInstance(&services.MessageRecipientService{}).(*services.MessageRecipientService)
|
||||
pb.RegisterMessageRecipientServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MessageReceiverService{}).(*services.MessageReceiverService)
|
||||
var instance = this.serviceInstance(&services.MessageReceiverService{}).(*services.MessageReceiverService)
|
||||
pb.RegisterMessageReceiverServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MessageMediaService{}).(*services.MessageMediaService)
|
||||
var instance = this.serviceInstance(&services.MessageMediaService{}).(*services.MessageMediaService)
|
||||
pb.RegisterMessageMediaServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MessageRecipientGroupService{}).(*services.MessageRecipientGroupService)
|
||||
var instance = this.serviceInstance(&services.MessageRecipientGroupService{}).(*services.MessageRecipientGroupService)
|
||||
pb.RegisterMessageRecipientGroupServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MessageMediaInstanceService{}).(*services.MessageMediaInstanceService)
|
||||
var instance = this.serviceInstance(&services.MessageMediaInstanceService{}).(*services.MessageMediaInstanceService)
|
||||
pb.RegisterMessageMediaInstanceServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MessageTaskService{}).(*services.MessageTaskService)
|
||||
var instance = this.serviceInstance(&services.MessageTaskService{}).(*services.MessageTaskService)
|
||||
pb.RegisterMessageTaskServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MessageTaskLogService{}).(*services.MessageTaskLogService)
|
||||
var instance = this.serviceInstance(&services.MessageTaskLogService{}).(*services.MessageTaskLogService)
|
||||
pb.RegisterMessageTaskLogServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeGroupService{}).(*services.NodeGroupService)
|
||||
var instance = this.serviceInstance(&services.NodeGroupService{}).(*services.NodeGroupService)
|
||||
pb.RegisterNodeGroupServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeRegionService{}).(*services.NodeRegionService)
|
||||
var instance = this.serviceInstance(&services.NodeRegionService{}).(*services.NodeRegionService)
|
||||
pb.RegisterNodeRegionServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodePriceItemService{}).(*services.NodePriceItemService)
|
||||
var instance = this.serviceInstance(&services.NodePriceItemService{}).(*services.NodePriceItemService)
|
||||
pb.RegisterNodePriceItemServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerGroupService{}).(*services.ServerGroupService)
|
||||
var instance = this.serviceInstance(&services.ServerGroupService{}).(*services.ServerGroupService)
|
||||
pb.RegisterServerGroupServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.IPLibraryService{}).(*services.IPLibraryService)
|
||||
var instance = this.serviceInstance(&services.IPLibraryService{}).(*services.IPLibraryService)
|
||||
pb.RegisterIPLibraryServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.FileChunkService{}).(*services.FileChunkService)
|
||||
var instance = this.serviceInstance(&services.FileChunkService{}).(*services.FileChunkService)
|
||||
pb.RegisterFileChunkServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.FileService{}).(*services.FileService)
|
||||
var instance = this.serviceInstance(&services.FileService{}).(*services.FileService)
|
||||
pb.RegisterFileServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.RegionCountryService{}).(*services.RegionCountryService)
|
||||
var instance = this.serviceInstance(&services.RegionCountryService{}).(*services.RegionCountryService)
|
||||
pb.RegisterRegionCountryServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.RegionProvinceService{}).(*services.RegionProvinceService)
|
||||
var instance = this.serviceInstance(&services.RegionProvinceService{}).(*services.RegionProvinceService)
|
||||
pb.RegisterRegionProvinceServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.RegionCityService{}).(*services.RegionCityService)
|
||||
var instance = this.serviceInstance(&services.RegionCityService{}).(*services.RegionCityService)
|
||||
pb.RegisterRegionCityServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.RegionProviderService{}).(*services.RegionProviderService)
|
||||
var instance = this.serviceInstance(&services.RegionProviderService{}).(*services.RegionProviderService)
|
||||
pb.RegisterRegionProviderServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.IPListService{}).(*services.IPListService)
|
||||
var instance = this.serviceInstance(&services.IPListService{}).(*services.IPListService)
|
||||
pb.RegisterIPListServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.IPItemService{}).(*services.IPItemService)
|
||||
var instance = this.serviceInstance(&services.IPItemService{}).(*services.IPItemService)
|
||||
pb.RegisterIPItemServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.LogService{}).(*services.LogService)
|
||||
var instance = this.serviceInstance(&services.LogService{}).(*services.LogService)
|
||||
pb.RegisterLogServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.DNSProviderService{}).(*services.DNSProviderService)
|
||||
var instance = this.serviceInstance(&services.DNSProviderService{}).(*services.DNSProviderService)
|
||||
pb.RegisterDNSProviderServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.DNSDomainService{}).(*services.DNSDomainService)
|
||||
var instance = this.serviceInstance(&services.DNSDomainService{}).(*services.DNSDomainService)
|
||||
pb.RegisterDNSDomainServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.DNSService{}).(*services.DNSService)
|
||||
var instance = this.serviceInstance(&services.DNSService{}).(*services.DNSService)
|
||||
pb.RegisterDNSServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ACMEUserService{}).(*services.ACMEUserService)
|
||||
var instance = this.serviceInstance(&services.ACMEUserService{}).(*services.ACMEUserService)
|
||||
pb.RegisterACMEUserServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ACMETaskService{}).(*services.ACMETaskService)
|
||||
var instance = this.serviceInstance(&services.ACMETaskService{}).(*services.ACMETaskService)
|
||||
pb.RegisterACMETaskServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ACMEAuthenticationService{}).(*services.ACMEAuthenticationService)
|
||||
var instance = this.serviceInstance(&services.ACMEAuthenticationService{}).(*services.ACMEAuthenticationService)
|
||||
pb.RegisterACMEAuthenticationServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ACMEProviderService{}).(*services.ACMEProviderService)
|
||||
var instance = this.serviceInstance(&services.ACMEProviderService{}).(*services.ACMEProviderService)
|
||||
pb.RegisterACMEProviderServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ACMEProviderAccountService{}).(*services.ACMEProviderAccountService)
|
||||
var instance = this.serviceInstance(&services.ACMEProviderAccountService{}).(*services.ACMEProviderAccountService)
|
||||
pb.RegisterACMEProviderAccountServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.UserService{}).(*services.UserService)
|
||||
var instance = this.serviceInstance(&services.UserService{}).(*services.UserService)
|
||||
pb.RegisterUserServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerDailyStatService{}).(*services.ServerDailyStatService)
|
||||
var instance = this.serviceInstance(&services.UserIdentityService{}).(*services.UserIdentityService)
|
||||
pb.RegisterUserIdentityServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
var instance = this.serviceInstance(&services.ServerDailyStatService{}).(*services.ServerDailyStatService)
|
||||
pb.RegisterServerDailyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.UserBillService{}).(*services.UserBillService)
|
||||
var instance = this.serviceInstance(&services.UserBillService{}).(*services.UserBillService)
|
||||
pb.RegisterUserBillServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerBillService{}).(*services.ServerBillService)
|
||||
var instance = this.serviceInstance(&services.ServerBillService{}).(*services.ServerBillService)
|
||||
pb.RegisterServerBillServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.UserNodeService{}).(*services.UserNodeService)
|
||||
var instance = this.serviceInstance(&services.UserNodeService{}).(*services.UserNodeService)
|
||||
pb.RegisterUserNodeServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.LoginService{}).(*services.LoginService)
|
||||
var instance = this.serviceInstance(&services.LoginService{}).(*services.LoginService)
|
||||
pb.RegisterLoginServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.UserAccessKeyService{}).(*services.UserAccessKeyService)
|
||||
var instance = this.serviceInstance(&services.UserAccessKeyService{}).(*services.UserAccessKeyService)
|
||||
pb.RegisterUserAccessKeyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.SysLockerService{}).(*services.SysLockerService)
|
||||
var instance = this.serviceInstance(&services.SysLockerService{}).(*services.SysLockerService)
|
||||
pb.RegisterSysLockerServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeTaskService{}).(*services.NodeTaskService)
|
||||
var instance = this.serviceInstance(&services.NodeTaskService{}).(*services.NodeTaskService)
|
||||
pb.RegisterNodeTaskServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeValueService{}).(*services.NodeValueService)
|
||||
var instance = this.serviceInstance(&services.NodeValueService{}).(*services.NodeValueService)
|
||||
pb.RegisterNodeValueServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.DBService{}).(*services.DBService)
|
||||
var instance = this.serviceInstance(&services.DBService{}).(*services.DBService)
|
||||
pb.RegisterDBServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerRegionCityMonthlyStatService{}).(*services.ServerRegionCityMonthlyStatService)
|
||||
var instance = this.serviceInstance(&services.ServerRegionCityMonthlyStatService{}).(*services.ServerRegionCityMonthlyStatService)
|
||||
pb.RegisterServerRegionCityMonthlyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerRegionCountryMonthlyStatService{}).(*services.ServerRegionCountryMonthlyStatService)
|
||||
var instance = this.serviceInstance(&services.ServerRegionCountryMonthlyStatService{}).(*services.ServerRegionCountryMonthlyStatService)
|
||||
pb.RegisterServerRegionCountryMonthlyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerRegionProvinceMonthlyStatService{}).(*services.ServerRegionProvinceMonthlyStatService)
|
||||
var instance = this.serviceInstance(&services.ServerRegionProvinceMonthlyStatService{}).(*services.ServerRegionProvinceMonthlyStatService)
|
||||
pb.RegisterServerRegionProvinceMonthlyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerRegionProviderMonthlyStatService{}).(*services.ServerRegionProviderMonthlyStatService)
|
||||
var instance = this.serviceInstance(&services.ServerRegionProviderMonthlyStatService{}).(*services.ServerRegionProviderMonthlyStatService)
|
||||
pb.RegisterServerRegionProviderMonthlyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerClientSystemMonthlyStatService{}).(*services.ServerClientSystemMonthlyStatService)
|
||||
var instance = this.serviceInstance(&services.ServerClientSystemMonthlyStatService{}).(*services.ServerClientSystemMonthlyStatService)
|
||||
pb.RegisterServerClientSystemMonthlyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerClientBrowserMonthlyStatService{}).(*services.ServerClientBrowserMonthlyStatService)
|
||||
var instance = this.serviceInstance(&services.ServerClientBrowserMonthlyStatService{}).(*services.ServerClientBrowserMonthlyStatService)
|
||||
pb.RegisterServerClientBrowserMonthlyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerHTTPFirewallDailyStatService{}).(*services.ServerHTTPFirewallDailyStatService)
|
||||
var instance = this.serviceInstance(&services.ServerHTTPFirewallDailyStatService{}).(*services.ServerHTTPFirewallDailyStatService)
|
||||
pb.RegisterServerHTTPFirewallDailyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.DNSTaskService{}).(*services.DNSTaskService)
|
||||
var instance = this.serviceInstance(&services.DNSTaskService{}).(*services.DNSTaskService)
|
||||
pb.RegisterDNSTaskServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeClusterFirewallActionService{}).(*services.NodeClusterFirewallActionService)
|
||||
var instance = this.serviceInstance(&services.NodeClusterFirewallActionService{}).(*services.NodeClusterFirewallActionService)
|
||||
pb.RegisterNodeClusterFirewallActionServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MonitorNodeService{}).(*services.MonitorNodeService)
|
||||
var instance = this.serviceInstance(&services.MonitorNodeService{}).(*services.MonitorNodeService)
|
||||
pb.RegisterMonitorNodeServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.AuthorityNodeService{}).(*services.AuthorityNodeService)
|
||||
var instance = this.serviceInstance(&services.AuthorityNodeService{}).(*services.AuthorityNodeService)
|
||||
pb.RegisterAuthorityNodeServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.LatestItemService{}).(*services.LatestItemService)
|
||||
var instance = this.serviceInstance(&services.LatestItemService{}).(*services.LatestItemService)
|
||||
pb.RegisterLatestItemServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeThresholdService{}).(*services.NodeThresholdService)
|
||||
var instance = this.serviceInstance(&services.NodeThresholdService{}).(*services.NodeThresholdService)
|
||||
pb.RegisterNodeThresholdServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPFastcgiService{}).(*services.HTTPFastcgiService)
|
||||
var instance = this.serviceInstance(&services.HTTPFastcgiService{}).(*services.HTTPFastcgiService)
|
||||
pb.RegisterHTTPFastcgiServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSClusterService{}).(*nameservers.NSClusterService)
|
||||
var instance = this.serviceInstance(&nameservers.NSClusterService{}).(*nameservers.NSClusterService)
|
||||
pb.RegisterNSClusterServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSNodeService{}).(*nameservers.NSNodeService)
|
||||
var instance = this.serviceInstance(&nameservers.NSNodeService{}).(*nameservers.NSNodeService)
|
||||
pb.RegisterNSNodeServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSDomainService{}).(*nameservers.NSDomainService)
|
||||
var instance = this.serviceInstance(&nameservers.NSDomainService{}).(*nameservers.NSDomainService)
|
||||
pb.RegisterNSDomainServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSRecordService{}).(*nameservers.NSRecordService)
|
||||
var instance = this.serviceInstance(&nameservers.NSRecordService{}).(*nameservers.NSRecordService)
|
||||
pb.RegisterNSRecordServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSRouteService{}).(*nameservers.NSRouteService)
|
||||
var instance = this.serviceInstance(&nameservers.NSRouteService{}).(*nameservers.NSRouteService)
|
||||
pb.RegisterNSRouteServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSKeyService{}).(*nameservers.NSKeyService)
|
||||
var instance = this.serviceInstance(&nameservers.NSKeyService{}).(*nameservers.NSKeyService)
|
||||
pb.RegisterNSKeyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSAccessLogService{}).(*nameservers.NSAccessLogService)
|
||||
var instance = this.serviceInstance(&nameservers.NSAccessLogService{}).(*nameservers.NSAccessLogService)
|
||||
pb.RegisterNSAccessLogServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSRecordHourlyStatService{}).(*nameservers.NSRecordHourlyStatService)
|
||||
var instance = this.serviceInstance(&nameservers.NSRecordHourlyStatService{}).(*nameservers.NSRecordHourlyStatService)
|
||||
pb.RegisterNSRecordHourlyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSQuestionOptionService{}).(*nameservers.NSQuestionOptionService)
|
||||
var instance = this.serviceInstance(&nameservers.NSQuestionOptionService{}).(*nameservers.NSQuestionOptionService)
|
||||
pb.RegisterNSQuestionOptionServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSService{}).(*nameservers.NSService)
|
||||
var instance = this.serviceInstance(&nameservers.NSService{}).(*nameservers.NSService)
|
||||
pb.RegisterNSServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.HTTPAuthPolicyService{}).(*services.HTTPAuthPolicyService)
|
||||
var instance = this.serviceInstance(&services.HTTPAuthPolicyService{}).(*services.HTTPAuthPolicyService)
|
||||
pb.RegisterHTTPAuthPolicyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MetricItemService{}).(*services.MetricItemService)
|
||||
var instance = this.serviceInstance(&services.MetricItemService{}).(*services.MetricItemService)
|
||||
pb.RegisterMetricItemServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.NodeClusterMetricItemService{}).(*services.NodeClusterMetricItemService)
|
||||
var instance = this.serviceInstance(&services.NodeClusterMetricItemService{}).(*services.NodeClusterMetricItemService)
|
||||
pb.RegisterNodeClusterMetricItemServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MetricStatService{}).(*services.MetricStatService)
|
||||
var instance = this.serviceInstance(&services.MetricStatService{}).(*services.MetricStatService)
|
||||
pb.RegisterMetricStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.MetricChartService{}).(*services.MetricChartService)
|
||||
var instance = this.serviceInstance(&services.MetricChartService{}).(*services.MetricChartService)
|
||||
pb.RegisterMetricChartServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerStatBoardService{}).(*services.ServerStatBoardService)
|
||||
var instance = this.serviceInstance(&services.ServerStatBoardService{}).(*services.ServerStatBoardService)
|
||||
pb.RegisterServerStatBoardServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerStatBoardChartService{}).(*services.ServerStatBoardChartService)
|
||||
var instance = this.serviceInstance(&services.ServerStatBoardChartService{}).(*services.ServerStatBoardChartService)
|
||||
pb.RegisterServerStatBoardChartServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
instance := this.serviceInstance(&services.PlanService{}).(*services.PlanService)
|
||||
var instance = this.serviceInstance(&services.PlanService{}).(*services.PlanService)
|
||||
pb.RegisterPlanServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
instance := this.serviceInstance(&services.UserPlanService{}).(*services.UserPlanService)
|
||||
var instance = this.serviceInstance(&services.UserPlanService{}).(*services.UserPlanService)
|
||||
pb.RegisterUserPlanServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
instance := this.serviceInstance(&services.ServerDomainHourlyStatService{}).(*services.ServerDomainHourlyStatService)
|
||||
var instance = this.serviceInstance(&services.ServerDomainHourlyStatService{}).(*services.ServerDomainHourlyStatService)
|
||||
pb.RegisterServerDomainHourlyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
instance := this.serviceInstance(&services.TrafficDailyStatService{}).(*services.TrafficDailyStatService)
|
||||
var instance = this.serviceInstance(&services.TrafficDailyStatService{}).(*services.TrafficDailyStatService)
|
||||
pb.RegisterTrafficDailyStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
var instance = this.serviceInstance(&services.HTTPCacheTaskKeyService{}).(*services.HTTPCacheTaskKeyService)
|
||||
pb.RegisterHTTPCacheTaskKeyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
var instance = this.serviceInstance(&services.HTTPCacheTaskService{}).(*services.HTTPCacheTaskService)
|
||||
pb.RegisterHTTPCacheTaskServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
{
|
||||
var instance = this.serviceInstance(&services.ServerBandwidthStatService{}).(*services.ServerBandwidthStatService)
|
||||
pb.RegisterServerBandwidthStatServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
APINodeServicesRegister(this, server)
|
||||
|
||||
// TODO check service names
|
||||
for serviceName := range server.GetServiceInfo() {
|
||||
index := strings.LastIndex(serviceName, ".")
|
||||
var index = strings.LastIndex(serviceName, ".")
|
||||
if index >= 0 {
|
||||
serviceName = serviceName[index+1:]
|
||||
}
|
||||
@@ -590,7 +613,7 @@ func (this *APINode) rest(instance interface{}) {
|
||||
defer this.serviceInstanceLocker.Unlock()
|
||||
|
||||
var name = reflect.TypeOf(instance).String()
|
||||
index := strings.LastIndex(name, ".")
|
||||
var index = strings.LastIndex(name, ".")
|
||||
if index >= 0 {
|
||||
name = name[index+1:]
|
||||
}
|
||||
@@ -606,7 +629,7 @@ func (this *APINode) serviceInstance(instance interface{}) interface{} {
|
||||
this.serviceInstanceLocker.Lock()
|
||||
defer this.serviceInstanceLocker.Unlock()
|
||||
|
||||
typeName := reflect.TypeOf(instance).String()
|
||||
var typeName = reflect.TypeOf(instance).String()
|
||||
result, ok := this.serviceInstanceMap[typeName]
|
||||
if ok {
|
||||
return result
|
||||
|
||||
17
internal/nodes/start_issue.go
Normal file
17
internal/nodes/start_issue.go
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package nodes
|
||||
|
||||
type StartIssue struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Suggestion string `json:"suggestion"`
|
||||
}
|
||||
|
||||
func NewStartIssue(code string, message string, suggestion string) *StartIssue {
|
||||
return &StartIssue{
|
||||
Code: code,
|
||||
Message: message,
|
||||
Suggestion: suggestion,
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
stringutil "github.com/iwind/TeaGo/utils/string"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
// NSNodeService 域名服务器节点服务
|
||||
@@ -398,9 +399,18 @@ func (this *NSNodeService) UpdateNSNodeStatus(ctx context.Context, req *pb.Updat
|
||||
return nil, errors.New("'nodeId' should be greater than 0")
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
err = models.SharedNSNodeDAO.UpdateNodeStatus(tx, nodeId, req.StatusJSON)
|
||||
// 修改时间戳
|
||||
var nodeStatus = &nodeconfigs.NodeStatus{}
|
||||
err = json.Unmarshal(req.StatusJSON, nodeStatus)
|
||||
if err != nil {
|
||||
return nil, errors.New("decode node status json failed: " + err.Error())
|
||||
}
|
||||
nodeStatus.UpdatedAt = time.Now().Unix()
|
||||
|
||||
// 保存
|
||||
err = models.SharedNSNodeDAO.UpdateNodeStatus(tx, nodeId, nodeStatus)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -452,12 +462,12 @@ func (this *NSNodeService) CheckNSNodeLatestVersion(ctx context.Context, req *pb
|
||||
|
||||
// DownloadNSNodeInstallationFile 下载最新DNS节点安装文件
|
||||
func (this *NSNodeService) DownloadNSNodeInstallationFile(ctx context.Context, req *pb.DownloadNSNodeInstallationFileRequest) (*pb.DownloadNSNodeInstallationFileResponse, error) {
|
||||
_, err := this.ValidateNSNode(ctx)
|
||||
nodeId, err := this.ValidateNSNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file := installers.SharedDeployManager.FindNSNodeFile(req.Os, req.Arch)
|
||||
var file = installers.SharedDeployManager.FindNSNodeFile(req.Os, req.Arch)
|
||||
if file == nil {
|
||||
return &pb.DownloadNSNodeInstallationFileResponse{}, nil
|
||||
}
|
||||
@@ -472,6 +482,9 @@ func (this *NSNodeService) DownloadNSNodeInstallationFile(ctx context.Context, r
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 增加下载速度监控
|
||||
installers.SharedUpgradeLimiter.UpdateNodeBytes(nodeconfigs.NodeRoleDNS, nodeId, int64(len(data)))
|
||||
|
||||
return &pb.DownloadNSNodeInstallationFileResponse{
|
||||
Sum: sum,
|
||||
Offset: offset,
|
||||
|
||||
@@ -2,11 +2,14 @@ package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/authority"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"time"
|
||||
)
|
||||
|
||||
type AuthorityNodeService struct {
|
||||
@@ -223,9 +226,18 @@ func (this *AuthorityNodeService) UpdateAuthorityNodeStatus(ctx context.Context,
|
||||
return nil, errors.New("'nodeId' should be greater than 0")
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
err = authority.SharedAuthorityNodeDAO.UpdateNodeStatus(tx, nodeId, req.StatusJSON)
|
||||
// 修改时间戳
|
||||
var nodeStatus = &nodeconfigs.NodeStatus{}
|
||||
err = json.Unmarshal(req.StatusJSON, nodeStatus)
|
||||
if err != nil {
|
||||
return nil, errors.New("decode node status json failed: " + err.Error())
|
||||
}
|
||||
nodeStatus.UpdatedAt = time.Now().Unix()
|
||||
|
||||
// 保存
|
||||
err = authority.SharedAuthorityNodeDAO.UpdateNodeStatus(tx, nodeId, nodeStatus)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ func (this *DNSProviderService) CountAllEnabledDNSProviders(ctx context.Context,
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
count, err := dns.SharedDNSProviderDAO.CountAllEnabledDNSProviders(tx, req.AdminId, req.UserId, req.Keyword, req.Domain)
|
||||
count, err := dns.SharedDNSProviderDAO.CountAllEnabledDNSProviders(tx, req.AdminId, req.UserId, req.Keyword, req.Domain, req.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -76,9 +76,9 @@ func (this *DNSProviderService) ListEnabledDNSProviders(ctx context.Context, req
|
||||
|
||||
// TODO 校验权限
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
providers, err := dns.SharedDNSProviderDAO.ListEnabledDNSProviders(tx, req.AdminId, req.UserId, req.Keyword, req.Domain, req.Offset, req.Size)
|
||||
providers, err := dns.SharedDNSProviderDAO.ListEnabledDNSProviders(tx, req.AdminId, req.UserId, req.Keyword, req.Domain, req.Type, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
383
internal/rpc/services/service_http_cache_task.go
Normal file
383
internal/rpc/services/service_http_cache_task.go
Normal file
@@ -0,0 +1,383 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
// HTTPCacheTaskService 缓存任务管理
|
||||
type HTTPCacheTaskService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// CreateHTTPCacheTask 创建任务
|
||||
func (this *HTTPCacheTaskService) CreateHTTPCacheTask(ctx context.Context, req *pb.CreateHTTPCacheTaskRequest) (*pb.CreateHTTPCacheTaskResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 检查操作类型
|
||||
if req.Type != models.HTTPCacheTaskTypePurge && req.Type != models.HTTPCacheTaskTypeFetch {
|
||||
return nil, errors.New("invalid type '" + req.Type + "'")
|
||||
}
|
||||
|
||||
// 检查Key数量
|
||||
var clusterId int64
|
||||
if userId > 0 {
|
||||
// 限制单次
|
||||
var maxKeysPerTask = userconfigs.MaxCacheKeysPerTask
|
||||
var maxKeysPerDay = userconfigs.MaxCacheKeysPerDay
|
||||
|
||||
serverConfig, err := models.SharedSysSettingDAO.ReadUserServerConfig(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if serverConfig != nil {
|
||||
switch req.Type {
|
||||
case models.HTTPCacheTaskTypePurge:
|
||||
if serverConfig.HTTPCacheTaskPurgeConfig != nil {
|
||||
if serverConfig.HTTPCacheTaskPurgeConfig.MaxKeysPerTask > 0 {
|
||||
maxKeysPerTask = serverConfig.HTTPCacheTaskPurgeConfig.MaxKeysPerTask
|
||||
}
|
||||
if serverConfig.HTTPCacheTaskPurgeConfig.MaxKeysPerDay > 0 {
|
||||
maxKeysPerDay = serverConfig.HTTPCacheTaskPurgeConfig.MaxKeysPerDay
|
||||
}
|
||||
}
|
||||
case models.HTTPCacheTaskTypeFetch:
|
||||
if serverConfig.HTTPCacheTaskFetchConfig != nil {
|
||||
if serverConfig.HTTPCacheTaskFetchConfig.MaxKeysPerTask > 0 {
|
||||
maxKeysPerTask = serverConfig.HTTPCacheTaskFetchConfig.MaxKeysPerTask
|
||||
}
|
||||
if serverConfig.HTTPCacheTaskFetchConfig.MaxKeysPerDay > 0 {
|
||||
maxKeysPerDay = serverConfig.HTTPCacheTaskFetchConfig.MaxKeysPerDay
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if maxKeysPerTask > 0 && len(req.Keys) > types.Int(maxKeysPerTask) {
|
||||
return nil, errors.New("too many keys in task (current:" + types.String(len(req.Keys)) + ", max:" + types.String(maxKeysPerTask) + ")")
|
||||
}
|
||||
|
||||
if maxKeysPerDay > 0 {
|
||||
countInDay, err := models.SharedHTTPCacheTaskKeyDAO.CountUserTasksInDay(tx, userId, timeutil.Format("Ymd"), req.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if types.Int(countInDay)+len(req.Keys) > types.Int(maxKeysPerDay) {
|
||||
return nil, errors.New("too many keys in today (current:" + types.String(types.Int(countInDay)+len(req.Keys)) + ", max:" + types.String(maxKeysPerDay) + ")")
|
||||
}
|
||||
}
|
||||
|
||||
clusterId, err = models.SharedUserDAO.FindUserClusterId(tx, userId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 创建任务
|
||||
taskId, err := models.SharedHTTPCacheTaskDAO.CreateTask(tx, userId, req.Type, req.KeyType, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var countKeys = 0
|
||||
var domainMap = map[string]*models.Server{} // domain name => *Server
|
||||
for _, key := range req.Keys {
|
||||
if len(key) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// 获取域名
|
||||
var domain = utils.ParseDomainFromKey(key)
|
||||
if len(domain) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// 查询所在集群
|
||||
server, ok := domainMap[domain]
|
||||
if !ok {
|
||||
server, err = models.SharedServerDAO.FindEnabledServerWithDomain(tx, domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if server == nil {
|
||||
continue
|
||||
}
|
||||
domainMap[domain] = server
|
||||
}
|
||||
|
||||
// 检查用户
|
||||
if userId > 0 {
|
||||
if int64(server.UserId) != userId {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
var serverClusterId = int64(server.ClusterId)
|
||||
if serverClusterId == 0 {
|
||||
if clusterId > 0 {
|
||||
serverClusterId = clusterId
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
_, err = models.SharedHTTPCacheTaskKeyDAO.CreateKey(tx, taskId, key, req.Type, req.KeyType, serverClusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
countKeys++
|
||||
}
|
||||
|
||||
if countKeys == 0 {
|
||||
// 如果没有有效的Key,则直接完成
|
||||
err = models.SharedHTTPCacheTaskDAO.UpdateTaskStatus(tx, taskId, true, true)
|
||||
} else {
|
||||
err = models.SharedHTTPCacheTaskDAO.UpdateTaskReady(tx, taskId)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.CreateHTTPCacheTaskResponse{
|
||||
HttpCacheTaskId: taskId,
|
||||
CountKeys: int64(countKeys),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CountHTTPCacheTasks 计算任务数量
|
||||
func (this *HTTPCacheTaskService) CountHTTPCacheTasks(ctx context.Context, req *pb.CountHTTPCacheTasksRequest) (*pb.RPCCountResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
count, err := models.SharedHTTPCacheTaskDAO.CountTasks(tx, userId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// CountDoingHTTPCacheTasks 计算正在执行的任务数量
|
||||
func (this *HTTPCacheTaskService) CountDoingHTTPCacheTasks(ctx context.Context, req *pb.CountDoingHTTPCacheTasksRequest) (*pb.RPCCountResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
count, err := models.SharedHTTPCacheTaskDAO.CountDoingTasks(tx, userId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// ListHTTPCacheTasks 列出单页任务
|
||||
func (this *HTTPCacheTaskService) ListHTTPCacheTasks(ctx context.Context, req *pb.ListHTTPCacheTasksRequest) (*pb.ListHTTPCacheTasksResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
tasks, err := models.SharedHTTPCacheTaskDAO.ListTasks(tx, userId, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var pbTasks = []*pb.HTTPCacheTask{}
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
for _, task := range tasks {
|
||||
var taskId = int64(task.Id)
|
||||
|
||||
// 查询所属用户
|
||||
var pbUser = &pb.User{}
|
||||
if task.UserId > 0 {
|
||||
var taskUserId = int64(task.UserId)
|
||||
if taskUserId > 0 {
|
||||
taskUser, err := models.SharedUserDAO.FindEnabledUser(tx, taskUserId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if taskUser == nil {
|
||||
// 找不到用户就删除
|
||||
err = models.SharedHTTPCacheTaskDAO.DisableHTTPCacheTask(tx, taskUserId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
pbUser = &pb.User{
|
||||
Id: int64(taskUser.Id),
|
||||
Username: taskUser.Username,
|
||||
Fullname: taskUser.Fullname,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pbTasks = append(pbTasks, &pb.HTTPCacheTask{
|
||||
Id: taskId,
|
||||
UserId: int64(task.UserId),
|
||||
Type: task.Type,
|
||||
KeyType: task.KeyType,
|
||||
CreatedAt: int64(task.CreatedAt),
|
||||
DoneAt: int64(task.DoneAt),
|
||||
IsDone: task.IsDone,
|
||||
IsOk: task.IsOk,
|
||||
Description: task.Description,
|
||||
User: pbUser,
|
||||
HttpCacheTaskKeys: nil,
|
||||
})
|
||||
}
|
||||
return &pb.ListHTTPCacheTasksResponse{
|
||||
HttpCacheTasks: pbTasks,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// FindEnabledHTTPCacheTask 查找单个任务
|
||||
func (this *HTTPCacheTaskService) FindEnabledHTTPCacheTask(ctx context.Context, req *pb.FindEnabledHTTPCacheTaskRequest) (*pb.FindEnabledHTTPCacheTaskResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
if userId > 0 {
|
||||
err = models.SharedHTTPCacheTaskDAO.CheckUserTask(tx, userId, req.HttpCacheTaskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
task, err := models.SharedHTTPCacheTaskDAO.FindEnabledHTTPCacheTask(tx, req.HttpCacheTaskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if task == nil {
|
||||
return &pb.FindEnabledHTTPCacheTaskResponse{HttpCacheTask: nil}, nil
|
||||
}
|
||||
|
||||
// 查询所属用户
|
||||
var pbUser = &pb.User{}
|
||||
if task.UserId > 0 {
|
||||
var taskUserId = int64(task.UserId)
|
||||
if taskUserId > 0 {
|
||||
taskUser, err := models.SharedUserDAO.FindEnabledUser(tx, taskUserId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if taskUser == nil {
|
||||
// 找不到用户就删除
|
||||
err = models.SharedHTTPCacheTaskDAO.DisableHTTPCacheTask(tx, taskUserId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
pbUser = &pb.User{
|
||||
Id: int64(taskUser.Id),
|
||||
Username: taskUser.Username,
|
||||
Fullname: taskUser.Fullname,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Keys
|
||||
keys, err := models.SharedHTTPCacheTaskKeyDAO.FindAllTaskKeys(tx, req.HttpCacheTaskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbKeys = []*pb.HTTPCacheTaskKey{}
|
||||
for _, key := range keys {
|
||||
|
||||
pbKeys = append(pbKeys, &pb.HTTPCacheTaskKey{
|
||||
Id: int64(key.Id),
|
||||
TaskId: int64(key.TaskId),
|
||||
Key: key.Key,
|
||||
KeyType: key.KeyType,
|
||||
IsDone: key.IsDone,
|
||||
IsDoing: !key.IsDone && len(key.DecodeNodes()) > 0,
|
||||
ErrorsJSON: key.Errors,
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.FindEnabledHTTPCacheTaskResponse{
|
||||
HttpCacheTask: &pb.HTTPCacheTask{
|
||||
Id: int64(task.Id),
|
||||
UserId: int64(task.UserId),
|
||||
Type: task.Type,
|
||||
KeyType: task.KeyType,
|
||||
CreatedAt: int64(task.CreatedAt),
|
||||
DoneAt: int64(task.DoneAt),
|
||||
IsDone: task.IsDone,
|
||||
IsOk: task.IsOk,
|
||||
User: pbUser,
|
||||
HttpCacheTaskKeys: pbKeys,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DeleteHTTPCacheTask 删除任务
|
||||
func (this *HTTPCacheTaskService) DeleteHTTPCacheTask(ctx context.Context, req *pb.DeleteHTTPCacheTaskRequest) (*pb.RPCSuccess, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
if userId > 0 {
|
||||
err = models.SharedHTTPCacheTaskDAO.CheckUserTask(tx, userId, req.HttpCacheTaskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedHTTPCacheTaskDAO.DisableHTTPCacheTask(tx, req.HttpCacheTaskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// ResetHTTPCacheTask 重置任务状态
|
||||
// 只允许管理员重置,用于调试
|
||||
func (this *HTTPCacheTaskService) ResetHTTPCacheTask(ctx context.Context, req *pb.ResetHTTPCacheTaskRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 重置任务
|
||||
err = models.SharedHTTPCacheTaskDAO.ResetTask(tx, req.HttpCacheTaskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 重置任务下的Key
|
||||
err = models.SharedHTTPCacheTaskKeyDAO.ResetCacheKeysWithTaskId(tx, req.HttpCacheTaskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
173
internal/rpc/services/service_http_cache_task_key.go
Normal file
173
internal/rpc/services/service_http_cache_task_key.go
Normal file
@@ -0,0 +1,173 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
// HTTPCacheTaskKeyService 缓存任务Key管理
|
||||
type HTTPCacheTaskKeyService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// ValidateHTTPCacheTaskKeys 校验缓存Key
|
||||
func (this *HTTPCacheTaskKeyService) ValidateHTTPCacheTaskKeys(ctx context.Context, req *pb.ValidateHTTPCacheTaskKeysRequest) (*pb.ValidateHTTPCacheTaskKeysResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx *dbs.Tx
|
||||
|
||||
// 检查Key数量
|
||||
var clusterId int64
|
||||
if userId > 0 {
|
||||
clusterId, err = models.SharedUserDAO.FindUserClusterId(tx, userId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var pbFailResults = []*pb.ValidateHTTPCacheTaskKeysResponse_FailKey{}
|
||||
var domainMap = map[string]*models.Server{} // domain name => *Server
|
||||
for _, key := range req.Keys {
|
||||
if len(key) == 0 {
|
||||
pbFailResults = append(pbFailResults, &pb.ValidateHTTPCacheTaskKeysResponse_FailKey{
|
||||
Key: key,
|
||||
ReasonCode: "requireKey",
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
// 获取域名
|
||||
var domain = utils.ParseDomainFromKey(key)
|
||||
if len(domain) == 0 {
|
||||
pbFailResults = append(pbFailResults, &pb.ValidateHTTPCacheTaskKeysResponse_FailKey{
|
||||
Key: key,
|
||||
ReasonCode: "requireDomain",
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
// 查询所在集群
|
||||
server, ok := domainMap[domain]
|
||||
if !ok {
|
||||
server, err = models.SharedServerDAO.FindEnabledServerWithDomain(tx, domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if server == nil {
|
||||
pbFailResults = append(pbFailResults, &pb.ValidateHTTPCacheTaskKeysResponse_FailKey{
|
||||
Key: key,
|
||||
ReasonCode: "requireServer",
|
||||
})
|
||||
continue
|
||||
}
|
||||
domainMap[domain] = server
|
||||
}
|
||||
|
||||
// 检查用户
|
||||
if userId > 0 {
|
||||
if int64(server.UserId) != userId {
|
||||
pbFailResults = append(pbFailResults, &pb.ValidateHTTPCacheTaskKeysResponse_FailKey{
|
||||
Key: key,
|
||||
ReasonCode: "requireUser",
|
||||
})
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
var serverClusterId = int64(server.ClusterId)
|
||||
if serverClusterId == 0 {
|
||||
if clusterId > 0 {
|
||||
serverClusterId = clusterId
|
||||
} else {
|
||||
pbFailResults = append(pbFailResults, &pb.ValidateHTTPCacheTaskKeysResponse_FailKey{
|
||||
Key: key,
|
||||
ReasonCode: "requireClusterId",
|
||||
})
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.ValidateHTTPCacheTaskKeysResponse{FailKeys: pbFailResults}, nil
|
||||
}
|
||||
|
||||
// FindDoingHTTPCacheTaskKeys 查找需要执行的Key
|
||||
func (this *HTTPCacheTaskKeyService) FindDoingHTTPCacheTaskKeys(ctx context.Context, req *pb.FindDoingHTTPCacheTaskKeysRequest) (*pb.FindDoingHTTPCacheTaskKeysResponse, error) {
|
||||
nodeId, err := this.ValidateNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.Size <= 0 {
|
||||
req.Size = 100
|
||||
}
|
||||
|
||||
var tx *dbs.Tx
|
||||
keys, err := models.SharedHTTPCacheTaskKeyDAO.FindDoingTaskKeys(tx, nodeId, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var pbKeys = []*pb.HTTPCacheTaskKey{}
|
||||
for _, key := range keys {
|
||||
pbKeys = append(pbKeys, &pb.HTTPCacheTaskKey{
|
||||
Id: int64(key.Id),
|
||||
TaskId: int64(key.TaskId),
|
||||
Key: key.Key,
|
||||
Type: key.Type,
|
||||
KeyType: key.KeyType,
|
||||
NodeClusterId: int64(key.ClusterId),
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.FindDoingHTTPCacheTaskKeysResponse{HttpCacheTaskKeys: pbKeys}, nil
|
||||
}
|
||||
|
||||
// UpdateHTTPCacheTaskKeysStatus 更新一组Key状态
|
||||
func (this *HTTPCacheTaskKeyService) UpdateHTTPCacheTaskKeysStatus(ctx context.Context, req *pb.UpdateHTTPCacheTaskKeysStatusRequest) (*pb.RPCSuccess, error) {
|
||||
nodeId, err := this.ValidateNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx *dbs.Tx
|
||||
|
||||
var nodesJSONMap = map[int64][]byte{} // clusterId => nodesJSON
|
||||
|
||||
for _, result := range req.KeyResults {
|
||||
// 集群Id
|
||||
var clusterId = result.NodeClusterId
|
||||
nodesJSON, ok := nodesJSONMap[clusterId]
|
||||
if !ok {
|
||||
nodeIdsInCluster, err := models.SharedNodeDAO.FindEnabledAndOnNodeIdsWithClusterId(tx, clusterId, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var nodeMap = map[int64]bool{}
|
||||
for _, nodeIdInCluster := range nodeIdsInCluster {
|
||||
nodeMap[nodeIdInCluster] = true
|
||||
}
|
||||
nodesJSON, err = json.Marshal(nodeMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nodesJSONMap[clusterId] = nodesJSON
|
||||
}
|
||||
|
||||
err = models.SharedHTTPCacheTaskKeyDAO.UpdateKeyStatus(tx, result.Id, nodeId, result.Error, nodesJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
23
internal/rpc/services/service_http_cache_task_test.go
Normal file
23
internal/rpc/services/service_http_cache_task_test.go
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHTTPCacheTaskService_CountHTTPCacheTasks(t *testing.T) {
|
||||
var a = assert.NewAssertion(t)
|
||||
|
||||
var service = &HTTPCacheTaskService{}
|
||||
a.IsTrue(service.parseDomain("aaa") == "aaa")
|
||||
a.IsTrue(service.parseDomain("AAA") == "aaa")
|
||||
a.IsTrue(service.parseDomain("a.b-c.com") == "a.b-c.com")
|
||||
a.IsTrue(service.parseDomain("a.b-c.com/hello/world") == "a.b-c.com")
|
||||
a.IsTrue(service.parseDomain("https://a.b-c.com") == "a.b-c.com")
|
||||
a.IsTrue(service.parseDomain("http://a.b-c.com/hello/world") == "a.b-c.com")
|
||||
a.IsTrue(service.parseDomain("http://a.B-c.com/hello/world") == "a.b-c.com")
|
||||
a.IsTrue(service.parseDomain("http:/aaaa.com") == "http")
|
||||
a.IsTrue(service.parseDomain("北京") == "")
|
||||
}
|
||||
@@ -173,7 +173,7 @@ func (this *HTTPFirewallPolicyService) UpdateHTTPFirewallPolicy(ctx context.Cont
|
||||
return nil, err
|
||||
}
|
||||
|
||||
templatePolicy := firewallconfigs.HTTPFirewallTemplate()
|
||||
var templatePolicy = firewallconfigs.HTTPFirewallTemplate()
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
@@ -186,18 +186,18 @@ func (this *HTTPFirewallPolicyService) UpdateHTTPFirewallPolicy(ctx context.Cont
|
||||
return nil, errors.New("can not found firewall policy")
|
||||
}
|
||||
|
||||
inboundConfig := firewallPolicy.Inbound
|
||||
var inboundConfig = firewallPolicy.Inbound
|
||||
if inboundConfig == nil {
|
||||
inboundConfig = &firewallconfigs.HTTPFirewallInboundConfig{IsOn: true}
|
||||
}
|
||||
|
||||
outboundConfig := firewallPolicy.Outbound
|
||||
var outboundConfig = firewallPolicy.Outbound
|
||||
if outboundConfig == nil {
|
||||
outboundConfig = &firewallconfigs.HTTPFirewallOutboundConfig{IsOn: true}
|
||||
}
|
||||
|
||||
// 更新老的
|
||||
oldCodes := []string{}
|
||||
var oldCodes = []string{}
|
||||
if firewallPolicy.Inbound != nil {
|
||||
for _, g := range firewallPolicy.Inbound.Groups {
|
||||
if len(g.Code) > 0 {
|
||||
@@ -301,7 +301,7 @@ func (this *HTTPFirewallPolicyService) UpdateHTTPFirewallPolicy(ctx context.Cont
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedHTTPFirewallPolicyDAO.UpdateFirewallPolicy(tx, req.HttpFirewallPolicyId, req.IsOn, req.Name, req.Description, inboundConfigJSON, outboundConfigJSON, req.BlockOptionsJSON, req.Mode, req.UseLocalFirewall, synFloodConfig, logConfig)
|
||||
err = models.SharedHTTPFirewallPolicyDAO.UpdateFirewallPolicy(tx, req.HttpFirewallPolicyId, req.IsOn, req.Name, req.Description, inboundConfigJSON, outboundConfigJSON, req.BlockOptionsJSON, req.CaptchaOptionsJSON, req.Mode, req.UseLocalFirewall, synFloodConfig, logConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
20
internal/rpc/services/service_http_web_community.go
Normal file
20
internal/rpc/services/service_http_web_community.go
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
// UpdateHTTPWebUAM 修改UAM设置
|
||||
func (this *HTTPWebService) UpdateHTTPWebUAM(ctx context.Context, req *pb.UpdateHTTPWebUAMRequest) (*pb.RPCSuccess, error) {
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindHTTPWebUAM 查找UAM设置
|
||||
func (this *HTTPWebService) FindHTTPWebUAM(ctx context.Context, req *pb.FindHTTPWebUAMRequest) (*pb.FindHTTPWebUAMResponse, error) {
|
||||
return &pb.FindHTTPWebUAMResponse{UamJSON: nil}, nil
|
||||
}
|
||||
@@ -114,23 +114,42 @@ func (this *IPItemService) DeleteIPItem(ctx context.Context, req *pb.DeleteIPIte
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
if userId > 0 {
|
||||
listId, err := models.SharedIPItemDAO.FindItemListId(tx, req.IpItemId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// 如果是使用IPItemId删除
|
||||
if req.IpItemId > 0 {
|
||||
if userId > 0 {
|
||||
listId, err := models.SharedIPItemDAO.FindItemListId(tx, req.IpItemId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = models.SharedIPListDAO.CheckUserIPList(tx, userId, listId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedIPListDAO.CheckUserIPList(tx, userId, listId)
|
||||
err = models.SharedIPItemDAO.DisableIPItem(tx, req.IpItemId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedIPItemDAO.DisableIPItem(tx, req.IpItemId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// 如果是使用ipFrom+ipTo删除
|
||||
if len(req.IpFrom) > 0 {
|
||||
// 检查IP列表
|
||||
if req.IpListId > 0 && userId > 0 {
|
||||
err = models.SharedIPListDAO.CheckUserIPList(tx, userId, req.IpListId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedIPItemDAO.DisableIPItemsWithIP(tx, req.IpFrom, req.IpTo, userId, req.IpListId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
|
||||
@@ -21,9 +21,20 @@ func (this *IPListService) CreateIPList(ctx context.Context, req *pb.CreateIPLis
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
listId, err := models.SharedIPListDAO.CreateIPList(tx, userId, req.Type, req.Name, req.Code, req.TimeoutJSON, req.Description, req.IsPublic, req.IsGlobal)
|
||||
// 检查用户相关信息
|
||||
if userId > 0 {
|
||||
// 检查服务ID
|
||||
if req.ServerId > 0 {
|
||||
err = models.SharedServerDAO.CheckUserServer(tx, userId, req.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
listId, err := models.SharedIPListDAO.CreateIPList(tx, userId, req.ServerId, req.Type, req.Name, req.Code, req.TimeoutJSON, req.Description, req.IsPublic, req.IsGlobal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -50,12 +61,18 @@ func (this *IPListService) UpdateIPList(ctx context.Context, req *pb.UpdateIPLis
|
||||
// FindEnabledIPList 查找IP列表
|
||||
func (this *IPListService) FindEnabledIPList(ctx context.Context, req *pb.FindEnabledIPListRequest) (*pb.FindEnabledIPListResponse, error) {
|
||||
// 校验请求
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
if userId > 0 {
|
||||
err = models.SharedIPListDAO.CheckUserIPList(tx, userId, req.IpListId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
list, err := models.SharedIPListDAO.FindEnabledIPList(tx, req.IpListId, nil)
|
||||
if err != nil {
|
||||
|
||||
@@ -5,10 +5,81 @@ package services
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 队列相关数据
|
||||
var metricStatsMap = map[string]*pb.UploadMetricStatsRequest{} // key (clusterId@nodeId@serverId@itemId) => UploadMetricStatsRequest
|
||||
var metricStatKeysQueue = make(chan string, 100_000)
|
||||
var metricStatsLocker = &sync.Mutex{}
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
goman.New(func() {
|
||||
// 将队列导入数据库
|
||||
var countKeys = 0
|
||||
for key := range metricStatKeysQueue {
|
||||
err := func(key string) error {
|
||||
var tx *dbs.Tx
|
||||
|
||||
metricStatsLocker.Lock()
|
||||
req, ok := metricStatsMap[key]
|
||||
if !ok {
|
||||
metricStatsLocker.Unlock()
|
||||
return nil
|
||||
}
|
||||
delete(metricStatsMap, key)
|
||||
metricStatsLocker.Unlock()
|
||||
|
||||
var pieces = strings.Split(key, "@")
|
||||
var clusterId = types.Int64(pieces[0])
|
||||
var nodeId = types.Int64(pieces[1])
|
||||
var serverId = types.Int64(pieces[2])
|
||||
var itemId = types.Int64(pieces[3])
|
||||
|
||||
// 删除旧的数据
|
||||
err := models.SharedMetricStatDAO.DeleteNodeItemStats(tx, nodeId, serverId, itemId, req.Time)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, stat := range req.MetricStats {
|
||||
err := models.SharedMetricStatDAO.CreateStat(tx, stat.Hash, clusterId, nodeId, req.ServerId, req.ItemId, stat.Keys, float64(stat.Value), req.Time, req.Version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 保存总和
|
||||
err = models.SharedMetricSumStatDAO.UpdateSum(tx, clusterId, nodeId, req.ServerId, req.Time, req.ItemId, req.Version, req.Count, req.Total)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}(key)
|
||||
if err != nil {
|
||||
remotelogs.Error("METRIC_STAT", "upload metric stats failed: "+err.Error())
|
||||
}
|
||||
|
||||
// 人为限速
|
||||
countKeys++
|
||||
if countKeys >= 100 {
|
||||
countKeys = 0
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// MetricStatService 指标统计数据相关服务
|
||||
type MetricStatService struct {
|
||||
BaseService
|
||||
@@ -27,24 +98,18 @@ func (this *MetricStatService) UploadMetricStats(ctx context.Context, req *pb.Up
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 删除旧的数据
|
||||
err = models.SharedMetricStatDAO.DeleteNodeItemStats(tx, nodeId, req.ServerId, req.ItemId, req.Time)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var key = types.String(clusterId) + "@" + types.String(nodeId) + "@" + types.String(req.ServerId) + "@" + types.String(req.ItemId)
|
||||
metricStatsLocker.Lock()
|
||||
metricStatsMap[key] = req
|
||||
|
||||
select {
|
||||
case metricStatKeysQueue <- key:
|
||||
default:
|
||||
// 如果满了就删除
|
||||
delete(metricStatsMap, key)
|
||||
}
|
||||
|
||||
for _, stat := range req.MetricStats {
|
||||
err := models.SharedMetricStatDAO.CreateStat(tx, stat.Hash, clusterId, nodeId, req.ServerId, req.ItemId, stat.Keys, float64(stat.Value), req.Time, req.Version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 保存总和
|
||||
err = models.SharedMetricSumStatDAO.UpdateSum(tx, clusterId, nodeId, req.ServerId, req.Time, req.ItemId, req.Version, req.Count, req.Total)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
metricStatsLocker.Unlock()
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
@@ -10,17 +10,18 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/installers"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/andybalholm/brotli"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
stringutil "github.com/iwind/TeaGo/utils/string"
|
||||
"io"
|
||||
@@ -399,7 +400,7 @@ func (this *NodeService) FindAllEnabledNodesWithNodeClusterId(ctx context.Contex
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
nodes, err := models.SharedNodeDAO.FindAllEnabledNodesWithClusterId(tx, req.NodeClusterId)
|
||||
nodes, err := models.SharedNodeDAO.FindAllEnabledNodesWithClusterId(tx, req.NodeClusterId, req.IncludeSecondary)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -767,13 +768,14 @@ func (this *NodeService) FindCurrentNodeConfig(ctx context.Context, req *pb.Find
|
||||
NodeJSON: data,
|
||||
DataSize: int64(len(data)),
|
||||
IsCompressed: isCompressed,
|
||||
Timestamp: time.Now().Unix(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateNodeStatus 更新节点状态
|
||||
func (this *NodeService) UpdateNodeStatus(ctx context.Context, req *pb.UpdateNodeStatusRequest) (*pb.RPCSuccess, error) {
|
||||
// 校验节点
|
||||
_, _, nodeId, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeNode)
|
||||
nodeId, err := this.ValidateNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -786,9 +788,18 @@ func (this *NodeService) UpdateNodeStatus(ctx context.Context, req *pb.UpdateNod
|
||||
return nil, errors.New("'nodeId' should be greater than 0")
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
err = models.SharedNodeDAO.UpdateNodeStatus(tx, nodeId, req.StatusJSON)
|
||||
// 修改时间戳
|
||||
var nodeStatus = &nodeconfigs.NodeStatus{}
|
||||
err = json.Unmarshal(req.StatusJSON, nodeStatus)
|
||||
if err != nil {
|
||||
return nil, errors.New("decode node status json failed: " + err.Error())
|
||||
}
|
||||
nodeStatus.UpdatedAt = time.Now().Unix()
|
||||
|
||||
// 保存
|
||||
err = models.SharedNodeDAO.UpdateNodeStatus(tx, nodeId, nodeStatus)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -823,7 +834,7 @@ func (this *NodeService) InstallNode(ctx context.Context, req *pb.InstallNodeReq
|
||||
goman.New(func() {
|
||||
err = installers.SharedNodeQueue().InstallNodeProcess(req.NodeId, false)
|
||||
if err != nil {
|
||||
logs.Println("[RPC]install node:" + err.Error())
|
||||
remotelogs.Error("NODE_SERVICE", "install node failed:"+err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
@@ -863,7 +874,7 @@ func (this *NodeService) UpgradeNode(ctx context.Context, req *pb.UpgradeNodeReq
|
||||
goman.New(func() {
|
||||
err = installers.SharedNodeQueue().InstallNodeProcess(req.NodeId, true)
|
||||
if err != nil {
|
||||
logs.Println("[RPC]install node:" + err.Error())
|
||||
remotelogs.Error("NODE_SERVICE", "install node:"+err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1591,12 +1602,12 @@ func (this *NodeService) UpdateNodeUp(ctx context.Context, req *pb.UpdateNodeUpR
|
||||
|
||||
// DownloadNodeInstallationFile 下载最新边缘节点安装文件
|
||||
func (this *NodeService) DownloadNodeInstallationFile(ctx context.Context, req *pb.DownloadNodeInstallationFileRequest) (*pb.DownloadNodeInstallationFileResponse, error) {
|
||||
_, err := this.ValidateNode(ctx)
|
||||
nodeId, err := this.ValidateNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file := installers.SharedDeployManager.FindNodeFile(req.Os, req.Arch)
|
||||
var file = installers.SharedDeployManager.FindNodeFile(req.Os, req.Arch)
|
||||
if file == nil {
|
||||
return &pb.DownloadNodeInstallationFileResponse{}, nil
|
||||
}
|
||||
@@ -1611,6 +1622,9 @@ func (this *NodeService) DownloadNodeInstallationFile(ctx context.Context, req *
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 增加下载速度监控
|
||||
installers.SharedUpgradeLimiter.UpdateNodeBytes(nodeconfigs.NodeRoleNode, nodeId, int64(len(data)))
|
||||
|
||||
return &pb.DownloadNodeInstallationFileResponse{
|
||||
Sum: sum,
|
||||
Offset: offset,
|
||||
@@ -1746,3 +1760,204 @@ func (this *NodeService) FindNodeLevelInfo(ctx context.Context, req *pb.FindNode
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// FindNodeDNSResolver 读取节点DNS Resolver
|
||||
func (this *NodeService) FindNodeDNSResolver(ctx context.Context, req *pb.FindNodeDNSResolverRequest) (*pb.FindNodeDNSResolverResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
config, err := models.SharedNodeDAO.FindNodeDNSResolver(tx, req.NodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.FindNodeDNSResolverResponse{
|
||||
DnsResolverJSON: configJSON,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateNodeDNSResolver 修改DNS Resolver
|
||||
func (this *NodeService) UpdateNodeDNSResolver(ctx context.Context, req *pb.UpdateNodeDNSResolverRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
var config = nodeconfigs.DefaultDNSResolverConfig()
|
||||
err = json.Unmarshal(req.DnsResolverJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = models.SharedNodeDAO.UpdateNodeDNSResolver(tx, req.NodeId, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindNodeDDoSProtection 获取集群的DDoS设置
|
||||
func (this *NodeService) FindNodeDDoSProtection(ctx context.Context, req *pb.FindNodeDDoSProtectionRequest) (*pb.FindNodeDDoSProtectionResponse, error) {
|
||||
var nodeId = req.NodeId
|
||||
var isFromNode = false
|
||||
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
// 检查是否来自节点
|
||||
currentNodeId, err2 := this.ValidateNode(ctx)
|
||||
if err2 != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if nodeId > 0 && currentNodeId != nodeId {
|
||||
return nil, errors.New("invalid 'nodeId'")
|
||||
}
|
||||
|
||||
nodeId = currentNodeId
|
||||
isFromNode = true
|
||||
}
|
||||
|
||||
var tx *dbs.Tx
|
||||
ddosProtection, err := models.SharedNodeDAO.FindNodeDDoSProtection(tx, nodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ddosProtection == nil {
|
||||
ddosProtection = ddosconfigs.DefaultProtectionConfig()
|
||||
}
|
||||
|
||||
// 组合父级节点配置
|
||||
// 只有从节点读取配置时才需要组合
|
||||
if isFromNode {
|
||||
clusterId, err := models.SharedNodeDAO.FindNodeClusterId(tx, nodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if clusterId > 0 {
|
||||
clusterDDoSProtection, err := models.SharedNodeClusterDAO.FindClusterDDoSProtection(tx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if clusterDDoSProtection == nil {
|
||||
clusterDDoSProtection = ddosconfigs.DefaultProtectionConfig()
|
||||
}
|
||||
|
||||
clusterDDoSProtection.Merge(ddosProtection)
|
||||
ddosProtection = clusterDDoSProtection
|
||||
}
|
||||
}
|
||||
|
||||
ddosProtectionJSON, err := json.Marshal(ddosProtection)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result = &pb.FindNodeDDoSProtectionResponse{
|
||||
DdosProtectionJSON: ddosProtectionJSON,
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// UpdateNodeDDoSProtection 修改集群的DDOS设置
|
||||
func (this *NodeService) UpdateNodeDDoSProtection(ctx context.Context, req *pb.UpdateNodeDDoSProtectionRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ddosProtection = &ddosconfigs.ProtectionConfig{}
|
||||
err = json.Unmarshal(req.DdosProtectionJSON, ddosProtection)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx *dbs.Tx
|
||||
err = models.SharedNodeDAO.UpdateNodeDDoSProtection(tx, req.NodeId, ddosProtection)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindEnabledNodeConfigInfo 取得节点的配置概要信息
|
||||
func (this *NodeService) FindEnabledNodeConfigInfo(ctx context.Context, req *pb.FindEnabledNodeConfigInfoRequest) (*pb.FindEnabledNodeConfigInfoResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
var result = &pb.FindEnabledNodeConfigInfoResponse{}
|
||||
node, err := models.SharedNodeDAO.FindEnabledNode(tx, req.NodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if node == nil {
|
||||
// 总是返回非空
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// dns
|
||||
if len(node.DNSRouteCodes()) > 0 {
|
||||
result.HasDNSInfo = true
|
||||
}
|
||||
|
||||
// cache
|
||||
if len(node.CacheDiskDir) > 0 {
|
||||
result.HasCacheInfo = true
|
||||
} else {
|
||||
var diskCapacity = node.DecodeMaxCacheDiskCapacity()
|
||||
var memoryCapacity = node.DecodeMaxCacheMemoryCapacity()
|
||||
if (diskCapacity != nil && diskCapacity.IsNotEmpty()) || (memoryCapacity != nil && memoryCapacity.IsNotEmpty()) {
|
||||
result.HasCacheInfo = true
|
||||
}
|
||||
}
|
||||
|
||||
// thresholds
|
||||
countThresholds, err := models.SharedNodeThresholdDAO.CountAllEnabledThresholds(tx, nodeconfigs.NodeRoleNode, 0, req.NodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.HasThresholds = countThresholds > 0
|
||||
|
||||
// ssh
|
||||
nodeLogin, err := models.SharedNodeLoginDAO.FindEnabledNodeLoginWithNodeId(tx, nodeconfigs.NodeRoleNode, req.NodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if nodeLogin != nil {
|
||||
sshParams, err := nodeLogin.DecodeSSHParams()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if sshParams != nil {
|
||||
result.HasSSH = len(sshParams.Host) > 0 || sshParams.Port > 0
|
||||
}
|
||||
}
|
||||
|
||||
// systemSettings
|
||||
if node.MaxCPU > 0 {
|
||||
result.HasSystemSettings = true
|
||||
} else {
|
||||
// dns resolver
|
||||
var dnsResolverConfig = node.DecodeDNSResolver()
|
||||
if dnsResolverConfig != nil {
|
||||
result.HasSystemSettings = dnsResolverConfig.Type != nodeconfigs.DNSResolverTypeDefault
|
||||
}
|
||||
}
|
||||
|
||||
// ddos protection
|
||||
result.HasDDoSProtection = node.HasDDoSProtection()
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
@@ -83,7 +84,7 @@ func (this *NodeClusterService) UpdateNodeCluster(ctx context.Context, req *pb.U
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
err = models.SharedNodeClusterDAO.UpdateCluster(tx, req.NodeClusterId, req.Name, req.NodeGrantId, req.InstallDir, req.TimeZone, req.NodeMaxThreads, req.NodeTCPMaxConnections, req.AutoOpenPorts)
|
||||
err = models.SharedNodeClusterDAO.UpdateCluster(tx, req.NodeClusterId, req.Name, req.NodeGrantId, req.InstallDir, req.TimeZone, req.NodeMaxThreads, req.AutoOpenPorts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -148,22 +149,21 @@ func (this *NodeClusterService) FindEnabledNodeCluster(ctx context.Context, req
|
||||
}
|
||||
|
||||
return &pb.FindEnabledNodeClusterResponse{NodeCluster: &pb.NodeCluster{
|
||||
Id: int64(cluster.Id),
|
||||
Name: cluster.Name,
|
||||
CreatedAt: int64(cluster.CreatedAt),
|
||||
InstallDir: cluster.InstallDir,
|
||||
NodeGrantId: int64(cluster.GrantId),
|
||||
UniqueId: cluster.UniqueId,
|
||||
Secret: cluster.Secret,
|
||||
HttpCachePolicyId: int64(cluster.CachePolicyId),
|
||||
HttpFirewallPolicyId: int64(cluster.HttpFirewallPolicyId),
|
||||
DnsName: cluster.DnsName,
|
||||
DnsDomainId: int64(cluster.DnsDomainId),
|
||||
IsOn: cluster.IsOn,
|
||||
TimeZone: cluster.TimeZone,
|
||||
NodeMaxThreads: int32(cluster.NodeMaxThreads),
|
||||
NodeTCPMaxConnections: int32(cluster.NodeTCPMaxConnections),
|
||||
AutoOpenPorts: cluster.AutoOpenPorts == 1,
|
||||
Id: int64(cluster.Id),
|
||||
Name: cluster.Name,
|
||||
CreatedAt: int64(cluster.CreatedAt),
|
||||
InstallDir: cluster.InstallDir,
|
||||
NodeGrantId: int64(cluster.GrantId),
|
||||
UniqueId: cluster.UniqueId,
|
||||
Secret: cluster.Secret,
|
||||
HttpCachePolicyId: int64(cluster.CachePolicyId),
|
||||
HttpFirewallPolicyId: int64(cluster.HttpFirewallPolicyId),
|
||||
DnsName: cluster.DnsName,
|
||||
DnsDomainId: int64(cluster.DnsDomainId),
|
||||
IsOn: cluster.IsOn,
|
||||
TimeZone: cluster.TimeZone,
|
||||
NodeMaxThreads: int32(cluster.NodeMaxThreads),
|
||||
AutoOpenPorts: cluster.AutoOpenPorts == 1,
|
||||
}}, nil
|
||||
}
|
||||
|
||||
@@ -429,7 +429,7 @@ func (this *NodeClusterService) FindEnabledNodeClusterDNS(ctx context.Context, r
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
dnsInfo, err := models.SharedNodeClusterDAO.FindClusterDNSInfo(tx, req.NodeClusterId, nil)
|
||||
if err != nil {
|
||||
@@ -457,6 +457,7 @@ func (this *NodeClusterService) FindEnabledNodeClusterDNS(ctx context.Context, r
|
||||
ServersAutoSync: dnsConfig.ServersAutoSync,
|
||||
CnameRecords: dnsConfig.CNameRecords,
|
||||
Ttl: dnsConfig.TTL,
|
||||
CnameAsDomain: dnsConfig.CNameAsDomain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -471,7 +472,7 @@ func (this *NodeClusterService) FindEnabledNodeClusterDNS(ctx context.Context, r
|
||||
Provider: nil,
|
||||
}, nil
|
||||
}
|
||||
pbDomain := &pb.DNSDomain{
|
||||
var pbDomain = &pb.DNSDomain{
|
||||
Id: int64(domain.Id),
|
||||
Name: domain.Name,
|
||||
IsOn: domain.IsOn,
|
||||
@@ -515,6 +516,7 @@ func (this *NodeClusterService) FindEnabledNodeClusterDNS(ctx context.Context, r
|
||||
ServersAutoSync: dnsConfig.ServersAutoSync,
|
||||
CnameRecords: dnsConfig.CNameRecords,
|
||||
Ttl: dnsConfig.TTL,
|
||||
CnameAsDomain: dnsConfig.CNameAsDomain,
|
||||
DefaultRoute: defaultRoute,
|
||||
}, nil
|
||||
}
|
||||
@@ -527,7 +529,7 @@ func (this *NodeClusterService) CountAllEnabledNodeClustersWithDNSProviderId(ctx
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
count, err := models.SharedNodeClusterDAO.CountAllEnabledClustersWithDNSProviderId(tx, req.DnsProviderId)
|
||||
if err != nil {
|
||||
@@ -544,7 +546,7 @@ func (this *NodeClusterService) CountAllEnabledNodeClustersWithDNSDomainId(ctx c
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
count, err := models.SharedNodeClusterDAO.CountAllEnabledClustersWithDNSDomainId(tx, req.DnsDomainId)
|
||||
if err != nil {
|
||||
@@ -561,7 +563,7 @@ func (this *NodeClusterService) FindAllEnabledNodeClustersWithDNSDomainId(ctx co
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
clusters, err := models.SharedNodeClusterDAO.FindAllEnabledClustersWithDNSDomainId(tx, req.DnsDomainId)
|
||||
if err != nil {
|
||||
@@ -589,7 +591,7 @@ func (this *NodeClusterService) CheckNodeClusterDNSName(ctx context.Context, req
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
exists, err := models.SharedNodeClusterDAO.ExistClusterDNSName(tx, req.DnsName, req.NodeClusterId)
|
||||
if err != nil {
|
||||
@@ -606,9 +608,9 @@ func (this *NodeClusterService) UpdateNodeClusterDNS(ctx context.Context, req *p
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
err = models.SharedNodeClusterDAO.UpdateClusterDNS(tx, req.NodeClusterId, req.DnsName, req.DnsDomainId, req.NodesAutoSync, req.ServersAutoSync, req.CnameRecords, req.Ttl)
|
||||
err = models.SharedNodeClusterDAO.UpdateClusterDNS(tx, req.NodeClusterId, req.DnsName, req.DnsDomainId, req.NodesAutoSync, req.ServersAutoSync, req.CnameRecords, req.Ttl, req.CnameAsDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1040,6 +1042,18 @@ func (this *NodeClusterService) FindEnabledNodeClusterConfigInfo(ctx context.Con
|
||||
result.WebpIsOn = nodeconfigs.DefaultWebPImagePolicy.IsOn
|
||||
}
|
||||
|
||||
// UAM
|
||||
if models.IsNotNull(cluster.Uam) {
|
||||
var uamPolicy = &nodeconfigs.UAMPolicy{}
|
||||
err = json.Unmarshal(cluster.Uam, uamPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.UamIsOn = uamPolicy.IsOn
|
||||
} else {
|
||||
result.UamIsOn = nodeconfigs.DefaultUAMPolicy.IsOn
|
||||
}
|
||||
|
||||
// system service
|
||||
if models.IsNotNull(cluster.SystemServices) {
|
||||
var servicesMap = map[string]maps.Map{}
|
||||
@@ -1054,6 +1068,9 @@ func (this *NodeClusterService) FindEnabledNodeClusterConfigInfo(ctx context.Con
|
||||
}
|
||||
}
|
||||
|
||||
// ddos
|
||||
result.HasDDoSProtection = cluster.HasDDoSProtection()
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -1101,16 +1118,116 @@ func (this *NodeClusterService) UpdateNodeClusterWebPPolicy(ctx context.Context,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
var webpPolicy = &nodeconfigs.WebPImagePolicy{}
|
||||
err = json.Unmarshal(req.WebpPolicyJSON, webpPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = webpPolicy.Init()
|
||||
if err != nil {
|
||||
return nil, errors.New("validate webp policy failed: " + err.Error())
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedNodeClusterDAO.UpdateClusterWebPPolicy(tx, req.NodeClusterId, webpPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindEnabledNodeClusterUAMPolicy 读取集群UAM策略
|
||||
func (this *NodeClusterService) FindEnabledNodeClusterUAMPolicy(ctx context.Context, req *pb.FindEnabledNodeClusterUAMPolicyRequest) (*pb.FindEnabledNodeClusterUAMPolicyResponse, error) {
|
||||
_, _, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
uamPolicy, err := models.SharedNodeClusterDAO.FindClusterUAMPolicy(tx, req.NodeClusterId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uamPolicyJSON, err := json.Marshal(uamPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.FindEnabledNodeClusterUAMPolicyResponse{
|
||||
UamPolicyJSON: uamPolicyJSON,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateNodeClusterUAMPolicy 设置集群的UAM策略
|
||||
func (this *NodeClusterService) UpdateNodeClusterUAMPolicy(ctx context.Context, req *pb.UpdateNodeClusterUAMPolicyRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var uamPolicy = &nodeconfigs.UAMPolicy{}
|
||||
err = json.Unmarshal(req.UamPolicyJSON, uamPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = uamPolicy.Init()
|
||||
if err != nil {
|
||||
return nil, errors.New("validate uam policy failed: " + err.Error())
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedNodeClusterDAO.UpdateClusterUAMPolicy(tx, req.NodeClusterId, uamPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindNodeClusterDDoSProtection 获取集群的DDOS设置
|
||||
func (this *NodeClusterService) FindNodeClusterDDoSProtection(ctx context.Context, req *pb.FindNodeClusterDDoSProtectionRequest) (*pb.FindNodeClusterDDoSProtectionResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx *dbs.Tx
|
||||
ddosProtection, err := models.SharedNodeClusterDAO.FindClusterDDoSProtection(tx, req.NodeClusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ddosProtection == nil {
|
||||
ddosProtection = ddosconfigs.DefaultProtectionConfig()
|
||||
}
|
||||
ddosProtectionJSON, err := json.Marshal(ddosProtection)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result = &pb.FindNodeClusterDDoSProtectionResponse{
|
||||
DdosProtectionJSON: ddosProtectionJSON,
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// UpdateNodeClusterDDoSProtection 修改集群的DDOS设置
|
||||
func (this *NodeClusterService) UpdateNodeClusterDDoSProtection(ctx context.Context, req *pb.UpdateNodeClusterDDoSProtectionRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ddosProtection = &ddosconfigs.ProtectionConfig{}
|
||||
err = json.Unmarshal(req.DdosProtectionJSON, ddosProtection)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx *dbs.Tx
|
||||
err = models.SharedNodeClusterDAO.UpdateClusterDDoSProtection(tx, req.NodeClusterId, ddosProtection)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ func (this *NodeTaskService) FindNodeTasks(ctx context.Context, req *pb.FindNode
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pbTasks := []*pb.NodeTask{}
|
||||
var pbTasks = []*pb.NodeTask{}
|
||||
for _, task := range tasks {
|
||||
pbTasks = append(pbTasks, &pb.NodeTask{
|
||||
Id: int64(task.Id),
|
||||
@@ -44,13 +44,13 @@ func (this *NodeTaskService) FindNodeTasks(ctx context.Context, req *pb.FindNode
|
||||
}
|
||||
|
||||
// 边缘节点版本更新任务
|
||||
if nodeType == rpcutils.UserTypeNode {
|
||||
if nodeType == rpcutils.UserTypeNode && installers.SharedUpgradeLimiter.CanUpgrade() {
|
||||
status, err := models.SharedNodeDAO.FindNodeStatus(tx, nodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if status != nil && len(status.OS) > 0 && len(status.Arch) > 0 && len(status.BuildVersion) > 0 {
|
||||
deployFile := installers.SharedDeployManager.FindNodeFile(status.OS, status.Arch)
|
||||
var deployFile = installers.SharedDeployManager.FindNodeFile(status.OS, status.Arch)
|
||||
if deployFile != nil {
|
||||
if stringutil.VersionCompare(deployFile.Version, status.BuildVersion) > 0 {
|
||||
pbTasks = append(pbTasks, &pb.NodeTask{
|
||||
|
||||
@@ -72,7 +72,7 @@ func (this *OriginService) CreateOrigin(ctx context.Context, req *pb.CreateOrigi
|
||||
}
|
||||
}
|
||||
|
||||
originId, err := models.SharedOriginDAO.CreateOrigin(tx, adminId, userId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains, req.Host)
|
||||
originId, err := models.SharedOriginDAO.CreateOrigin(tx, adminId, userId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains, req.Host, req.FollowPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -87,20 +87,23 @@ func (this *OriginService) UpdateOrigin(ctx context.Context, req *pb.UpdateOrigi
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
if userId > 0 {
|
||||
// TODO 校验权限
|
||||
err = models.SharedOriginDAO.CheckUserOrigin(tx, userId, req.OriginId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if req.Addr == nil {
|
||||
return nil, errors.New("'addr' can not be nil")
|
||||
}
|
||||
addrMap := maps.Map{
|
||||
var addrMap = maps.Map{
|
||||
"protocol": req.Addr.Protocol,
|
||||
"portRange": req.Addr.PortRange,
|
||||
"host": req.Addr.Host,
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
// 校验参数
|
||||
var connTimeout = &shared.TimeDuration{}
|
||||
if len(req.ConnTimeoutJSON) > 0 {
|
||||
@@ -139,7 +142,7 @@ func (this *OriginService) UpdateOrigin(ctx context.Context, req *pb.UpdateOrigi
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedOriginDAO.UpdateOrigin(tx, req.OriginId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains, req.Host)
|
||||
err = models.SharedOriginDAO.UpdateOrigin(tx, req.OriginId, req.Name, string(addrMap.AsJSON()), req.Description, req.Weight, req.IsOn, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, certRef, req.Domains, req.Host, req.FollowPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -154,11 +157,14 @@ func (this *OriginService) FindEnabledOrigin(ctx context.Context, req *pb.FindEn
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if userId > 0 {
|
||||
// TODO 校验权限
|
||||
}
|
||||
var tx = this.NullTx()
|
||||
|
||||
tx := this.NullTx()
|
||||
if userId > 0 {
|
||||
err = models.SharedOriginDAO.CheckUserOrigin(tx, userId, req.OriginId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
origin, err := models.SharedOriginDAO.FindEnabledOrigin(tx, req.OriginId)
|
||||
if err != nil {
|
||||
@@ -196,11 +202,14 @@ func (this *OriginService) FindEnabledOriginConfig(ctx context.Context, req *pb.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if userId > 0 {
|
||||
// TODO 校验权限
|
||||
}
|
||||
var tx = this.NullTx()
|
||||
|
||||
tx := this.NullTx()
|
||||
if userId > 0 {
|
||||
err = models.SharedOriginDAO.CheckUserOrigin(tx, userId, req.OriginId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
config, err := models.SharedOriginDAO.ComposeOriginConfig(tx, req.OriginId, nil)
|
||||
if err != nil {
|
||||
|
||||
@@ -27,12 +27,39 @@ func (this *RegionCityService) FindAllEnabledRegionCities(ctx context.Context, r
|
||||
}
|
||||
|
||||
var pbCities = []*pb.RegionCity{}
|
||||
|
||||
var provincesMap = map[int64]*regions.RegionProvince{} // provinceId => RegionProvince
|
||||
|
||||
for _, city := range cities {
|
||||
var provinceId = int64(city.ProvinceId)
|
||||
|
||||
var pbProvince = &pb.RegionProvince{Id: provinceId}
|
||||
if req.IncludeRegionProvince {
|
||||
province, ok := provincesMap[provinceId]
|
||||
if !ok {
|
||||
province, err = regions.SharedRegionProvinceDAO.FindEnabledRegionProvince(tx, provinceId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if province == nil {
|
||||
continue
|
||||
}
|
||||
provincesMap[provinceId] = province
|
||||
}
|
||||
|
||||
pbProvince = &pb.RegionProvince{
|
||||
Id: int64(province.Id),
|
||||
Name: province.Name,
|
||||
Codes: province.DecodeCodes(),
|
||||
}
|
||||
}
|
||||
|
||||
pbCities = append(pbCities, &pb.RegionCity{
|
||||
Id: int64(city.Id),
|
||||
Name: city.Name,
|
||||
Codes: city.DecodeCodes(),
|
||||
RegionProvinceId: int64(city.ProvinceId),
|
||||
RegionProvince: pbProvince,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ func (this *ReverseProxyService) FindEnabledReverseProxyConfig(ctx context.Conte
|
||||
}
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
config, err := models.SharedReverseProxyDAO.ComposeReverseProxyConfig(tx, req.ReverseProxyId, nil)
|
||||
if err != nil {
|
||||
@@ -189,7 +189,7 @@ func (this *ReverseProxyService) UpdateReverseProxy(ctx context.Context, req *pb
|
||||
}
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 校验参数
|
||||
var connTimeout = &shared.TimeDuration{}
|
||||
@@ -216,7 +216,7 @@ func (this *ReverseProxyService) UpdateReverseProxy(ctx context.Context, req *pb
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedReverseProxyDAO.UpdateReverseProxy(tx, req.ReverseProxyId, types.Int8(req.RequestHostType), req.RequestHost, req.RequestURI, req.StripPrefix, req.AutoFlush, req.AddHeaders, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, req.ProxyProtocolJSON, req.FollowRedirects)
|
||||
err = models.SharedReverseProxyDAO.UpdateReverseProxy(tx, req.ReverseProxyId, types.Int8(req.RequestHostType), req.RequestHost, req.RequestHostExcludingPort, req.RequestURI, req.StripPrefix, req.AutoFlush, req.AddHeaders, connTimeout, readTimeout, idleTimeout, req.MaxConns, req.MaxIdleConns, req.ProxyProtocolJSON, req.FollowRedirects)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/regions"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
@@ -154,7 +153,7 @@ func (this *ServerService) CreateServer(ctx context.Context, req *pb.CreateServe
|
||||
}
|
||||
}
|
||||
|
||||
serverId, err := models.SharedServerDAO.CreateServer(tx, req.AdminId, req.UserId, req.Type, req.Name, req.Description, serverNamesJSON, isAuditing, auditingServerNamesJSON, req.HttpJSON, req.HttpsJSON, req.TcpJSON, req.TlsJSON, req.UnixJSON, req.UdpJSON, req.WebId, req.ReverseProxyJSON, req.NodeClusterId, string(req.IncludeNodesJSON), string(req.ExcludeNodesJSON), req.ServerGroupIds, req.UserPlanId)
|
||||
serverId, err := models.SharedServerDAO.CreateServer(tx, req.AdminId, req.UserId, req.Type, req.Name, req.Description, serverNamesJSON, isAuditing, auditingServerNamesJSON, req.HttpJSON, req.HttpsJSON, req.TcpJSON, req.TlsJSON, req.UnixJSON, req.UdpJSON, req.WebId, req.ReverseProxyJSON, req.NodeClusterId, req.IncludeNodesJSON, req.ExcludeNodesJSON, req.ServerGroupIds, req.UserPlanId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -193,6 +192,56 @@ func (this *ServerService) UpdateServerBasic(ctx context.Context, req *pb.Update
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// UpdateServerGroupIds 修改服务所在分组
|
||||
func (this *ServerService) UpdateServerGroupIds(ctx context.Context, req *pb.UpdateServerGroupIdsRequest) (*pb.RPCSuccess, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
if userId > 0 {
|
||||
err = models.SharedServerDAO.CheckUserServer(tx, userId, req.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 检查分组IDs
|
||||
for _, groupId := range req.ServerGroupIds {
|
||||
if userId > 0 {
|
||||
err = models.SharedServerGroupDAO.CheckUserGroup(tx, userId, groupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
b, err := models.SharedServerGroupDAO.ExistsGroup(tx, groupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !b {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 增加默认分组
|
||||
if userId > 0 {
|
||||
config, err := models.SharedSysSettingDAO.ReadUserServerConfig(tx)
|
||||
if err == nil && config.GroupId > 0 && !lists.ContainsInt64(req.ServerGroupIds, config.GroupId) {
|
||||
req.ServerGroupIds = append(req.ServerGroupIds, config.GroupId)
|
||||
}
|
||||
}
|
||||
|
||||
// 修改
|
||||
err = models.SharedServerDAO.UpdateServerGroupIds(tx, req.ServerId, req.ServerGroupIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// UpdateServerIsOn 修改服务是否启用
|
||||
func (this *ServerService) UpdateServerIsOn(ctx context.Context, req *pb.UpdateServerIsOnRequest) (*pb.RPCSuccess, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
@@ -200,7 +249,7 @@ func (this *ServerService) UpdateServerIsOn(ctx context.Context, req *pb.UpdateS
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
|
||||
if userId > 0 {
|
||||
err = models.SharedServerDAO.CheckUserServer(tx, userId, req.ServerId)
|
||||
@@ -833,8 +882,9 @@ func (this *ServerService) FindEnabledServer(ctx context.Context, req *pb.FindEn
|
||||
continue
|
||||
}
|
||||
pbGroups = append(pbGroups, &pb.ServerGroup{
|
||||
Id: int64(group.Id),
|
||||
Name: group.Name,
|
||||
Id: int64(group.Id),
|
||||
Name: group.Name,
|
||||
UserId: int64(group.UserId),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1710,79 +1760,88 @@ func (this *ServerService) PurgeServerCache(ctx context.Context, req *pb.PurgeSe
|
||||
}
|
||||
}
|
||||
|
||||
if len(req.Domains) == 0 {
|
||||
return nil, errors.New("'domains' field is required")
|
||||
}
|
||||
|
||||
if len(req.Keys) == 0 && len(req.Prefixes) == 0 {
|
||||
return &pb.PurgeServerCacheResponse{IsOk: true}, nil
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
var purgeResponse = &pb.PurgeServerCacheResponse{}
|
||||
|
||||
for _, domain := range req.Domains {
|
||||
servers, err := models.SharedServerDAO.FindAllEnabledServersWithDomain(tx, domain)
|
||||
var tx = this.NullTx()
|
||||
|
||||
var taskType = "purge"
|
||||
|
||||
var tasks = []*pb.CreateHTTPCacheTaskRequest{}
|
||||
if len(req.Keys) > 0 {
|
||||
tasks = append(tasks, &pb.CreateHTTPCacheTaskRequest{
|
||||
Type: taskType,
|
||||
KeyType: "key",
|
||||
Keys: req.Keys,
|
||||
})
|
||||
}
|
||||
if len(req.Prefixes) > 0 {
|
||||
tasks = append(tasks, &pb.CreateHTTPCacheTaskRequest{
|
||||
Type: taskType,
|
||||
KeyType: "prefix",
|
||||
Keys: req.Prefixes,
|
||||
})
|
||||
}
|
||||
|
||||
var domainMap = map[string]*models.Server{} // domain name => *Server
|
||||
|
||||
for _, pbTask := range tasks {
|
||||
// 创建任务
|
||||
taskId, err := models.SharedHTTPCacheTaskDAO.CreateTask(tx, 0, pbTask.Type, pbTask.KeyType, "调用PURGE API")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, server := range servers {
|
||||
clusterId := int64(server.ClusterId)
|
||||
if clusterId > 0 {
|
||||
nodeIds, err := models.SharedNodeDAO.FindAllEnabledNodeIdsWithClusterId(tx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var countKeys = 0
|
||||
|
||||
cachePolicyId, err := models.SharedNodeClusterDAO.FindClusterHTTPCachePolicyId(tx, clusterId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cachePolicyId == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
cachePolicy, err := models.SharedHTTPCachePolicyDAO.ComposeCachePolicy(tx, cachePolicyId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cachePolicy == nil {
|
||||
continue
|
||||
}
|
||||
cachePolicyJSON, err := json.Marshal(cachePolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, nodeId := range nodeIds {
|
||||
msg := &messageconfigs.PurgeCacheMessage{
|
||||
CachePolicyJSON: cachePolicyJSON,
|
||||
}
|
||||
if len(req.Prefixes) > 0 {
|
||||
msg.Type = messageconfigs.PurgeCacheMessageTypeDir
|
||||
msg.Keys = req.Prefixes
|
||||
} else {
|
||||
msg.Type = messageconfigs.PurgeCacheMessageTypeFile
|
||||
msg.Keys = req.Keys
|
||||
}
|
||||
msgJSON, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := SendCommandToNode(nodeId, NextCommandRequestId(), messageconfigs.MessageCodePurgeCache, msgJSON, 10, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !resp.IsOk {
|
||||
purgeResponse.IsOk = false
|
||||
purgeResponse.Message = resp.Message
|
||||
return purgeResponse, nil
|
||||
}
|
||||
}
|
||||
for _, key := range req.Keys {
|
||||
if len(key) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// 获取域名
|
||||
var domain = utils.ParseDomainFromKey(key)
|
||||
if len(domain) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// 查询所在集群
|
||||
server, ok := domainMap[domain]
|
||||
if !ok {
|
||||
server, err = models.SharedServerDAO.FindEnabledServerWithDomain(tx, domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if server == nil {
|
||||
continue
|
||||
}
|
||||
domainMap[domain] = server
|
||||
}
|
||||
|
||||
var serverClusterId = int64(server.ClusterId)
|
||||
if serverClusterId == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = models.SharedHTTPCacheTaskKeyDAO.CreateKey(tx, taskId, key, pbTask.Type, pbTask.KeyType, serverClusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
countKeys++
|
||||
}
|
||||
|
||||
if countKeys == 0 {
|
||||
// 如果没有有效的Key,则直接完成
|
||||
err = models.SharedHTTPCacheTaskDAO.UpdateTaskStatus(tx, taskId, true, true)
|
||||
} else {
|
||||
err = models.SharedHTTPCacheTaskDAO.UpdateTaskReady(tx, taskId)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1955,9 +2014,11 @@ func (this *ServerService) FindServerUserPlan(ctx context.Context, req *pb.FindS
|
||||
DayTo: userPlan.DayTo,
|
||||
User: nil,
|
||||
Plan: &pb.Plan{
|
||||
Id: int64(plan.Id),
|
||||
Name: plan.Name,
|
||||
PriceType: plan.PriceType,
|
||||
Id: int64(plan.Id),
|
||||
Name: plan.Name,
|
||||
PriceType: plan.PriceType,
|
||||
TrafficPriceJSON: plan.TrafficPrice,
|
||||
TrafficLimitJSON: plan.TrafficLimit,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user