Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77c67ccd3f | ||
|
|
d855fdedde | ||
|
|
95c734c87a | ||
|
|
89ff1927b7 | ||
|
|
1a3aaf2846 | ||
|
|
7d25019abb | ||
|
|
4cfc7d5387 | ||
|
|
9245cf9cdb | ||
|
|
9e1e57dfd8 | ||
|
|
87f032bebd | ||
|
|
bda407fc3f | ||
|
|
3b2f6060b8 | ||
|
|
a15ad7dd04 | ||
|
|
a415ef6070 | ||
|
|
d94a822f52 | ||
|
|
9e3fb9cf66 | ||
|
|
84a9916d3e | ||
|
|
7d1ae0d242 | ||
|
|
3fbad22218 | ||
|
|
5fffc8a833 | ||
|
|
2c72d28c48 | ||
|
|
45ea803e7a | ||
|
|
edd4b59207 | ||
|
|
38ad11fda0 | ||
|
|
961d9b4dbc | ||
|
|
6436e83d9e | ||
|
|
b2d3d483e8 | ||
|
|
89ec81f6b1 | ||
|
|
5124169e28 |
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*_plus.go
|
||||
*-plus.sh
|
||||
@@ -6,6 +6,7 @@ function build() {
|
||||
DIST=$ROOT/"../dist/${NAME}"
|
||||
OS=${1}
|
||||
ARCH=${2}
|
||||
TAG=${3}
|
||||
|
||||
if [ -z $OS ]; then
|
||||
echo "usage: build.sh OS ARCH"
|
||||
@@ -15,9 +16,12 @@ function build() {
|
||||
echo "usage: build.sh OS ARCH"
|
||||
exit
|
||||
fi
|
||||
if [ -z $TAG ]; then
|
||||
TAG="community"
|
||||
fi
|
||||
|
||||
VERSION=$(lookup-version $ROOT/../internal/const/const.go)
|
||||
ZIP="${NAME}-${OS}-${ARCH}-v${VERSION}.zip"
|
||||
ZIP="${NAME}-${OS}-${ARCH}-${TAG}-v${VERSION}.zip"
|
||||
|
||||
# check edge-node
|
||||
NodeVersion=$(lookup-version $ROOT"/../../EdgeNode/internal/const/const.go")
|
||||
@@ -31,14 +35,14 @@ function build() {
|
||||
echo "=============================="
|
||||
architects=("amd64" "386" "arm64" "mips64" "mips64le")
|
||||
for arch in "${architects[@]}"; do
|
||||
./build.sh linux $arch
|
||||
./build.sh linux $arch $TAG
|
||||
done
|
||||
echo "=============================="
|
||||
cd -
|
||||
|
||||
rm -f $ROOT/deploy/*.zip
|
||||
for arch in "${architects[@]}"; do
|
||||
cp $ROOT"/../../EdgeNode/dist/edge-node-linux-${arch}-v${NodeVersion}.zip" $ROOT/deploy/
|
||||
cp $ROOT"/../../EdgeNode/dist/edge-node-linux-${arch}-${TAG}-v${NodeVersion}.zip" $ROOT/deploy/edge-node-linux-${arch}-v${NodeVersion}.zip
|
||||
done
|
||||
|
||||
# build sql
|
||||
@@ -64,14 +68,14 @@ function build() {
|
||||
|
||||
# building installer
|
||||
echo "building installer ..."
|
||||
architects=("amd64" "386")
|
||||
architects=("amd64" "386" "arm64")
|
||||
for arch in "${architects[@]}"; do
|
||||
# TODO support arm, mips ...
|
||||
env GOOS=linux GOARCH=${arch} go build --ldflags="-s -w" -o $ROOT/installers/edge-installer-helper-linux-${arch} $ROOT/../cmd/installer-helper/main.go
|
||||
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
|
||||
done
|
||||
|
||||
# building api node
|
||||
env GOOS=$OS GOARCH=$ARCH go build --ldflags="-s -w" -o $DIST/bin/edge-api $ROOT/../cmd/edge-api/main.go
|
||||
env GOOS=$OS GOARCH=$ARCH go build -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
|
||||
@@ -102,4 +106,4 @@ function lookup-version() {
|
||||
fi
|
||||
}
|
||||
|
||||
build $1 $2
|
||||
build $1 $2 $3
|
||||
|
||||
@@ -44,6 +44,7 @@ func main() {
|
||||
_, _ = os.Stdout.Write(resultJSON)
|
||||
})
|
||||
app.On("upgrade", func() {
|
||||
fmt.Println("start ...")
|
||||
executor, err := setup.NewSQLExecutorFromCmd()
|
||||
if err != nil {
|
||||
fmt.Println("ERROR: " + err.Error())
|
||||
|
||||
4
go.mod
4
go.mod
@@ -4,6 +4,8 @@ go 1.15
|
||||
|
||||
replace github.com/TeaOSLab/EdgeCommon => ../EdgeCommon
|
||||
|
||||
|
||||
|
||||
require (
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
|
||||
github.com/TeaOSLab/EdgeCommon v0.0.0-00010101000000-000000000000
|
||||
@@ -15,6 +17,7 @@ require (
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/iwind/TeaGo v0.0.0-20210628135026-38575a4ab060
|
||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3
|
||||
github.com/lionsoul2014/ip2region v2.2.0-release+incompatible
|
||||
github.com/mozillazg/go-pinyin v0.18.0
|
||||
github.com/pkg/sftp v1.12.0
|
||||
@@ -26,5 +29,4 @@ require (
|
||||
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced // indirect
|
||||
google.golang.org/grpc v1.38.0
|
||||
google.golang.org/protobuf v1.26.0
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
||||
24
go.sum
24
go.sum
@@ -134,7 +134,6 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
@@ -146,8 +145,8 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
@@ -181,11 +180,11 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
|
||||
github.com/iwind/TeaGo v0.0.0-20200923021120-f5d76441fe9e/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f h1:r2O8PONj/KiuZjJHVHn7KlCePUIjNtgAmvLfgRafQ8o=
|
||||
github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/TeaGo v0.0.0-20210628135026-38575a4ab060 h1:qdLtK4PDXxk2vMKkTWl5Fl9xqYuRCukzWAgJbLHdfOo=
|
||||
github.com/iwind/TeaGo v0.0.0-20210628135026-38575a4ab060/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
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/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
|
||||
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
|
||||
@@ -194,8 +193,6 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
@@ -292,8 +289,6 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sacloud/libsacloud v1.36.2/go.mod h1:P7YAOVmnIn3DKHqCZcUKYUXmSwGBm3yS7IBEjKVSrjg=
|
||||
github.com/shirou/gopsutil v2.20.9+incompatible h1:msXs2frUV+O/JLva9EDLpuJ84PrFsdCTCQex8PUdtkQ=
|
||||
github.com/shirou/gopsutil v2.20.9+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shirou/gopsutil v3.21.5+incompatible h1:OloQyEerMi7JUrXiNzy8wQ5XN+baemxSl12QgIzt0jc=
|
||||
github.com/shirou/gopsutil v3.21.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
@@ -403,7 +398,6 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
|
||||
@@ -418,8 +412,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -455,7 +449,6 @@ golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -468,7 +461,6 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@@ -515,8 +507,8 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs
|
||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
@@ -553,7 +545,6 @@ google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced h1:c5geK1iMU3cDKtFrCVQIcjR3W+JOZMuhIyICMCTbtus=
|
||||
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
|
||||
@@ -568,7 +559,6 @@ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.32.0 h1:zWTV+LMdc3kaiJMSTOFz2UgSBgx8RNQoTGiZu3fR9S0=
|
||||
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0=
|
||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
@@ -580,7 +570,6 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
@@ -612,9 +601,8 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
||||
66
internal/accesslogs/storage_base.go
Normal file
66
internal/accesslogs/storage_base.go
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package accesslogs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type BaseStorage struct {
|
||||
isOk bool
|
||||
version int
|
||||
}
|
||||
|
||||
func (this *BaseStorage) SetVersion(version int) {
|
||||
this.version = version
|
||||
}
|
||||
|
||||
func (this *BaseStorage) Version() int {
|
||||
return this.version
|
||||
}
|
||||
|
||||
func (this *BaseStorage) IsOk() bool {
|
||||
return this.isOk
|
||||
}
|
||||
|
||||
func (this *BaseStorage) SetOk(isOk bool) {
|
||||
this.isOk = isOk
|
||||
}
|
||||
|
||||
// Marshal 对日志进行编码
|
||||
func (this *BaseStorage) Marshal(accessLog *pb.HTTPAccessLog) ([]byte, error) {
|
||||
return json.Marshal(accessLog)
|
||||
}
|
||||
|
||||
// FormatVariables 格式化字符串中的变量
|
||||
func (this *BaseStorage) FormatVariables(s string) string {
|
||||
now := time.Now()
|
||||
return configutils.ParseVariables(s, func(varName string) (value string) {
|
||||
switch varName {
|
||||
case "year":
|
||||
return strconv.Itoa(now.Year())
|
||||
case "month":
|
||||
return fmt.Sprintf("%02d", now.Month())
|
||||
case "week":
|
||||
_, week := now.ISOWeek()
|
||||
return fmt.Sprintf("%02d", week)
|
||||
case "day":
|
||||
return fmt.Sprintf("%02d", now.Day())
|
||||
case "hour":
|
||||
return fmt.Sprintf("%02d", now.Hour())
|
||||
case "minute":
|
||||
return fmt.Sprintf("%02d", now.Minute())
|
||||
case "second":
|
||||
return fmt.Sprintf("%02d", now.Second())
|
||||
case "date":
|
||||
return fmt.Sprintf("%d%02d%02d", now.Year(), now.Month(), now.Day())
|
||||
}
|
||||
|
||||
return varName
|
||||
})
|
||||
}
|
||||
95
internal/accesslogs/storage_command.go
Normal file
95
internal/accesslogs/storage_command.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package accesslogs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"os/exec"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// CommandStorage 通过命令行存储
|
||||
type CommandStorage struct {
|
||||
BaseStorage
|
||||
|
||||
config *serverconfigs.AccessLogCommandStorageConfig
|
||||
|
||||
writeLocker sync.Mutex
|
||||
}
|
||||
|
||||
func NewCommandStorage(config *serverconfigs.AccessLogCommandStorageConfig) *CommandStorage {
|
||||
return &CommandStorage{config: config}
|
||||
}
|
||||
|
||||
func (this *CommandStorage) Config() interface{} {
|
||||
return this.config
|
||||
}
|
||||
|
||||
// Start 启动
|
||||
func (this *CommandStorage) Start() error {
|
||||
if len(this.config.Command) == 0 {
|
||||
return errors.New("'command' should not be empty")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 写入日志
|
||||
func (this *CommandStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
if len(accessLogs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
this.writeLocker.Lock()
|
||||
defer this.writeLocker.Unlock()
|
||||
|
||||
cmd := exec.Command(this.config.Command, this.config.Args...)
|
||||
if len(this.config.Dir) > 0 {
|
||||
cmd.Dir = this.config.Dir
|
||||
}
|
||||
|
||||
stdout := bytes.NewBuffer([]byte{})
|
||||
cmd.Stdout = stdout
|
||||
|
||||
w, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, accessLog := range accessLogs {
|
||||
data, err := this.Marshal(accessLog)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
continue
|
||||
}
|
||||
_, err = w.Write(data)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
}
|
||||
|
||||
_, err = w.Write([]byte("\n"))
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
}
|
||||
}
|
||||
_ = w.Close()
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
|
||||
if stdout.Len() > 0 {
|
||||
logs.Error(errors.New(string(stdout.Bytes())))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close 关闭
|
||||
func (this *CommandStorage) Close() error {
|
||||
return nil
|
||||
}
|
||||
63
internal/accesslogs/storage_command_test.go
Normal file
63
internal/accesslogs/storage_command_test.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package accesslogs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"os"
|
||||
"os/exec"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCommandStorage_Write(t *testing.T) {
|
||||
php, err := exec.LookPath("php")
|
||||
if err != nil { // not found php, so we can not test
|
||||
t.Log("php:", err)
|
||||
return
|
||||
}
|
||||
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
before := time.Now()
|
||||
|
||||
storage := NewCommandStorage(&serverconfigs.AccessLogCommandStorageConfig{
|
||||
Command: php,
|
||||
Args: []string{cwd + "/tests/command_storage.php"},
|
||||
})
|
||||
err = storage.Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = storage.Write([]*pb.HTTPAccessLog{
|
||||
{
|
||||
RequestMethod: "GET",
|
||||
RequestPath: "/hello",
|
||||
},
|
||||
{
|
||||
RequestMethod: "GET",
|
||||
RequestPath: "/world",
|
||||
},
|
||||
{
|
||||
RequestMethod: "GET",
|
||||
RequestPath: "/lu",
|
||||
},
|
||||
{
|
||||
RequestMethod: "GET",
|
||||
RequestPath: "/ping",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = storage.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Log(time.Since(before).Seconds(), "seconds")
|
||||
}
|
||||
131
internal/accesslogs/storage_es.go
Normal file
131
internal/accesslogs/storage_es.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package accesslogs
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ESStorage ElasticSearch存储策略
|
||||
type ESStorage struct {
|
||||
BaseStorage
|
||||
|
||||
config *serverconfigs.AccessLogESStorageConfig
|
||||
}
|
||||
|
||||
func NewESStorage(config *serverconfigs.AccessLogESStorageConfig) *ESStorage {
|
||||
return &ESStorage{config: config}
|
||||
}
|
||||
|
||||
func (this *ESStorage) Config() interface{} {
|
||||
return this.config
|
||||
}
|
||||
|
||||
// Start 开启
|
||||
func (this *ESStorage) Start() error {
|
||||
if len(this.config.Endpoint) == 0 {
|
||||
return errors.New("'endpoint' should not be nil")
|
||||
}
|
||||
if !regexp.MustCompile(`(?i)^(http|https)://`).MatchString(this.config.Endpoint) {
|
||||
this.config.Endpoint = "http://" + this.config.Endpoint
|
||||
}
|
||||
if len(this.config.Index) == 0 {
|
||||
return errors.New("'index' should not be nil")
|
||||
}
|
||||
if len(this.config.MappingType) == 0 {
|
||||
return errors.New("'mappingType' should not be nil")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 写入日志
|
||||
func (this *ESStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
if len(accessLogs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var requestId int64 = 1_0000_0000_0000_0000
|
||||
|
||||
bulk := &strings.Builder{}
|
||||
indexName := this.FormatVariables(this.config.Index)
|
||||
typeName := this.FormatVariables(this.config.MappingType)
|
||||
for _, accessLog := range accessLogs {
|
||||
if len(accessLog.RequestId) == 0 {
|
||||
accessLog.RequestId = strconv.FormatInt(time.Now().UnixNano(), 10) + strconv.FormatInt(atomic.AddInt64(&requestId, 1), 10) + fmt.Sprintf("%08d", 1)
|
||||
}
|
||||
|
||||
opData, err := json.Marshal(map[string]interface{}{
|
||||
"index": map[string]interface{}{
|
||||
"_index": indexName,
|
||||
"_type": typeName,
|
||||
"_id": accessLog.RequestId,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
remotelogs.Error("ACCESS_LOG_ES_STORAGE", "write failed: "+err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
data, err := this.Marshal(accessLog)
|
||||
if err != nil {
|
||||
remotelogs.Error("ACCESS_LOG_ES_STORAGE", "marshal data failed: "+err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
bulk.Write(opData)
|
||||
bulk.WriteString("\n")
|
||||
bulk.Write(data)
|
||||
bulk.WriteString("\n")
|
||||
}
|
||||
|
||||
if bulk.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, this.config.Endpoint+"/_bulk", strings.NewReader(bulk.String()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("User-Agent", strings.ReplaceAll(teaconst.ProductName, " ", "-")+"/"+teaconst.Version)
|
||||
if len(this.config.Username) > 0 || len(this.config.Password) > 0 {
|
||||
req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(this.config.Username+":"+this.config.Password)))
|
||||
}
|
||||
client := utils.SharedHttpClient(10 * time.Second)
|
||||
defer func() {
|
||||
_ = req.Body.Close()
|
||||
}()
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
_ = resp.Body.Close()
|
||||
}()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
bodyData, _ := ioutil.ReadAll(resp.Body)
|
||||
return errors.New("ElasticSearch response status code: " + fmt.Sprintf("%d", resp.StatusCode) + " content: " + string(bodyData))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close 关闭
|
||||
func (this *ESStorage) Close() error {
|
||||
return nil
|
||||
}
|
||||
53
internal/accesslogs/storage_es_test.go
Normal file
53
internal/accesslogs/storage_es_test.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package accesslogs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestESStorage_Write(t *testing.T) {
|
||||
storage := NewESStorage(&serverconfigs.AccessLogESStorageConfig{
|
||||
Endpoint: "http://127.0.0.1:9200",
|
||||
Index: "logs",
|
||||
MappingType: "accessLogs",
|
||||
Username: "hello",
|
||||
Password: "world",
|
||||
})
|
||||
err := storage.Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
{
|
||||
err = storage.Write([]*pb.HTTPAccessLog{
|
||||
{
|
||||
RequestMethod: "POST",
|
||||
RequestPath: "/1",
|
||||
TimeLocal: time.Now().Format("2/Jan/2006:15:04:05 -0700"),
|
||||
TimeISO8601: "2018-07-23T22:23:35+08:00",
|
||||
Header: map[string]*pb.Strings{
|
||||
"Content-Type": {Values: []string{"text/html"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
RequestMethod: "GET",
|
||||
RequestPath: "/2",
|
||||
TimeLocal: time.Now().Format("2/Jan/2006:15:04:05 -0700"),
|
||||
TimeISO8601: "2018-07-23T22:23:35+08:00",
|
||||
Header: map[string]*pb.Strings{
|
||||
"Content-Type": {Values: []string{"text/css"}},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
err = storage.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
127
internal/accesslogs/storage_file.go
Normal file
127
internal/accesslogs/storage_file.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package accesslogs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// FileStorage 文件存储策略
|
||||
type FileStorage struct {
|
||||
BaseStorage
|
||||
|
||||
config *serverconfigs.AccessLogFileStorageConfig
|
||||
|
||||
writeLocker sync.Mutex
|
||||
|
||||
files map[string]*os.File // path => *File
|
||||
filesLocker sync.Mutex
|
||||
}
|
||||
|
||||
func NewFileStorage(config *serverconfigs.AccessLogFileStorageConfig) *FileStorage {
|
||||
return &FileStorage{
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *FileStorage) Config() interface{} {
|
||||
return this.config
|
||||
}
|
||||
|
||||
// Start 开启
|
||||
func (this *FileStorage) Start() error {
|
||||
if len(this.config.Path) == 0 {
|
||||
return errors.New("'path' should not be empty")
|
||||
}
|
||||
|
||||
this.files = map[string]*os.File{}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write 写入日志
|
||||
func (this *FileStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
if len(accessLogs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
fp := this.fp()
|
||||
if fp == nil {
|
||||
return errors.New("file pointer should not be nil")
|
||||
}
|
||||
this.writeLocker.Lock()
|
||||
defer this.writeLocker.Unlock()
|
||||
|
||||
for _, accessLog := range accessLogs {
|
||||
data, err := this.Marshal(accessLog)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
continue
|
||||
}
|
||||
_, err = fp.Write(data)
|
||||
if err != nil {
|
||||
_ = this.Close()
|
||||
break
|
||||
}
|
||||
_, _ = fp.WriteString("\n")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close 关闭
|
||||
func (this *FileStorage) Close() error {
|
||||
this.filesLocker.Lock()
|
||||
defer this.filesLocker.Unlock()
|
||||
|
||||
var resultErr error
|
||||
for _, f := range this.files {
|
||||
err := f.Close()
|
||||
if err != nil {
|
||||
resultErr = err
|
||||
}
|
||||
}
|
||||
return resultErr
|
||||
}
|
||||
|
||||
func (this *FileStorage) fp() *os.File {
|
||||
path := this.FormatVariables(this.config.Path)
|
||||
|
||||
this.filesLocker.Lock()
|
||||
defer this.filesLocker.Unlock()
|
||||
fp, ok := this.files[path]
|
||||
if ok {
|
||||
return fp
|
||||
}
|
||||
|
||||
// 关闭其他的文件
|
||||
for _, f := range this.files {
|
||||
_ = f.Close()
|
||||
}
|
||||
|
||||
// 是否创建文件目录
|
||||
if this.config.AutoCreate {
|
||||
dir := filepath.Dir(path)
|
||||
_, err := os.Stat(dir)
|
||||
if os.IsNotExist(err) {
|
||||
err = os.MkdirAll(dir, 0777)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 打开新文件
|
||||
fp, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return nil
|
||||
}
|
||||
this.files[path] = fp
|
||||
|
||||
return fp
|
||||
}
|
||||
70
internal/accesslogs/storage_file_test.go
Normal file
70
internal/accesslogs/storage_file_test.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package accesslogs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestFileStorage_Write(t *testing.T) {
|
||||
storage := NewFileStorage(&serverconfigs.AccessLogFileStorageConfig{
|
||||
Path: Tea.Root + "/logs/access-${date}.log",
|
||||
})
|
||||
err := storage.Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
{
|
||||
err = storage.Write([]*pb.HTTPAccessLog{
|
||||
{
|
||||
RequestPath: "/hello",
|
||||
},
|
||||
{
|
||||
RequestPath: "/world",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
err = storage.Write([]*pb.HTTPAccessLog{
|
||||
{
|
||||
RequestPath: "/1",
|
||||
},
|
||||
{
|
||||
RequestPath: "/2",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
err = storage.Write([]*pb.HTTPAccessLog{
|
||||
{
|
||||
RequestMethod: "POST",
|
||||
RequestPath: "/1",
|
||||
TimeLocal: time.Now().Format("2/Jan/2006:15:04:05 -0700"),
|
||||
},
|
||||
{
|
||||
RequestMethod: "GET",
|
||||
RequestPath: "/2",
|
||||
TimeLocal: time.Now().Format("2/Jan/2006:15:04:05 -0700"),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
err = storage.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
30
internal/accesslogs/storage_interface.go
Normal file
30
internal/accesslogs/storage_interface.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package accesslogs
|
||||
|
||||
import "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
|
||||
// StorageInterface 日志存储接口
|
||||
type StorageInterface interface {
|
||||
// Version 获取版本
|
||||
Version() int
|
||||
|
||||
// SetVersion 设置版本
|
||||
SetVersion(version int)
|
||||
|
||||
IsOk() bool
|
||||
|
||||
SetOk(ok bool)
|
||||
|
||||
// Config 获取配置
|
||||
Config() interface{}
|
||||
|
||||
// Start 开启
|
||||
Start() error
|
||||
|
||||
// Write 写入日志
|
||||
Write(accessLogs []*pb.HTTPAccessLog) error
|
||||
|
||||
// Close 关闭
|
||||
Close() error
|
||||
}
|
||||
199
internal/accesslogs/storage_manager.go
Normal file
199
internal/accesslogs/storage_manager.go
Normal file
@@ -0,0 +1,199 @@
|
||||
package accesslogs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var SharedStorageManager = NewStorageManager()
|
||||
|
||||
type StorageManager struct {
|
||||
storageMap map[int64]StorageInterface // policyId => Storage
|
||||
|
||||
locker sync.Mutex
|
||||
}
|
||||
|
||||
func NewStorageManager() *StorageManager {
|
||||
return &StorageManager{
|
||||
storageMap: map[int64]StorageInterface{},
|
||||
}
|
||||
}
|
||||
|
||||
func (this *StorageManager) Start() {
|
||||
var ticker = time.NewTicker(1 * time.Minute)
|
||||
if Tea.IsTesting() {
|
||||
ticker = time.NewTicker(5 * time.Second)
|
||||
}
|
||||
|
||||
// 启动时执行一次
|
||||
var err = this.Loop()
|
||||
if err != nil {
|
||||
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "update error: "+err.Error())
|
||||
}
|
||||
|
||||
// 循环执行
|
||||
for range ticker.C {
|
||||
err := this.Loop()
|
||||
if err != nil {
|
||||
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "update error: "+err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 写入日志
|
||||
func (this *StorageManager) Write(policyId int64, accessLogs []*pb.HTTPAccessLog) error {
|
||||
this.locker.Lock()
|
||||
storage, ok := this.storageMap[policyId]
|
||||
this.locker.Unlock()
|
||||
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !storage.IsOk() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return storage.Write(accessLogs)
|
||||
}
|
||||
|
||||
// Loop 更新
|
||||
func (this *StorageManager) Loop() error {
|
||||
policies, err := models.SharedHTTPAccessLogPolicyDAO.FindAllEnabledAndOnPolicies(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var policyIds = []int64{}
|
||||
for _, policy := range policies {
|
||||
if policy.IsOn == 1 {
|
||||
policyIds = append(policyIds, int64(policy.Id))
|
||||
}
|
||||
}
|
||||
|
||||
this.locker.Lock()
|
||||
defer this.locker.Unlock()
|
||||
|
||||
// 关闭不用的
|
||||
for policyId, storage := range this.storageMap {
|
||||
if !lists.ContainsInt64(policyIds, policyId) {
|
||||
err := storage.Close()
|
||||
if err != nil {
|
||||
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "close '"+types.String(policyId)+"' failed: "+err.Error())
|
||||
}
|
||||
delete(this.storageMap, policyId)
|
||||
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "remove '"+types.String(policyId)+"'")
|
||||
}
|
||||
}
|
||||
|
||||
for _, policy := range policies {
|
||||
var policyId = int64(policy.Id)
|
||||
storage, ok := this.storageMap[policyId]
|
||||
if ok {
|
||||
// 检查配置是否有变更
|
||||
if types.Int(policy.Version) != storage.Version() {
|
||||
err = storage.Close()
|
||||
if err != nil {
|
||||
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "close policy '"+types.String(policyId)+"' failed: "+err.Error())
|
||||
|
||||
// 继续往下执行
|
||||
}
|
||||
|
||||
if len(policy.Options) > 0 {
|
||||
err = json.Unmarshal([]byte(policy.Options), storage.Config())
|
||||
if err != nil {
|
||||
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "unmarshal policy '"+types.String(policyId)+"' config failed: "+err.Error())
|
||||
storage.SetOk(false)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
storage.SetVersion(types.Int(policy.Version))
|
||||
err := storage.Start()
|
||||
if err != nil {
|
||||
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "start policy '"+types.String(policyId)+"' failed: "+err.Error())
|
||||
continue
|
||||
}
|
||||
storage.SetOk(true)
|
||||
remotelogs.Println("ACCESS_LOG_STORAGE_MANAGER", "restart policy '"+types.String(policyId)+"'")
|
||||
}
|
||||
} else {
|
||||
storage, err := this.createStorage(policy.Type, []byte(policy.Options))
|
||||
if err != nil {
|
||||
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "create policy '"+types.String(policyId)+"' failed: "+err.Error())
|
||||
continue
|
||||
}
|
||||
storage.SetVersion(types.Int(policy.Version))
|
||||
this.storageMap[policyId] = storage
|
||||
err = storage.Start()
|
||||
if err != nil {
|
||||
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "start policy '"+types.String(policyId)+"' failed: "+err.Error())
|
||||
continue
|
||||
}
|
||||
storage.SetOk(true)
|
||||
remotelogs.Println("ACCESS_LOG_STORAGE_MANAGER", "start policy '"+types.String(policyId)+"'")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *StorageManager) createStorage(storageType string, optionsJSON []byte) (StorageInterface, error) {
|
||||
switch storageType {
|
||||
case serverconfigs.AccessLogStorageTypeFile:
|
||||
var config = &serverconfigs.AccessLogFileStorageConfig{}
|
||||
if len(optionsJSON) > 0 {
|
||||
err := json.Unmarshal(optionsJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return NewFileStorage(config), nil
|
||||
case serverconfigs.AccessLogStorageTypeES:
|
||||
var config = &serverconfigs.AccessLogESStorageConfig{}
|
||||
if len(optionsJSON) > 0 {
|
||||
err := json.Unmarshal(optionsJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return NewESStorage(config), nil
|
||||
case serverconfigs.AccessLogStorageTypeTCP:
|
||||
var config = &serverconfigs.AccessLogTCPStorageConfig{}
|
||||
if len(optionsJSON) > 0 {
|
||||
err := json.Unmarshal(optionsJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return NewTCPStorage(config), nil
|
||||
case serverconfigs.AccessLogStorageTypeSyslog:
|
||||
var config = &serverconfigs.AccessLogSyslogStorageConfig{}
|
||||
if len(optionsJSON) > 0 {
|
||||
err := json.Unmarshal(optionsJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return NewSyslogStorage(config), nil
|
||||
case serverconfigs.AccessLogStorageTypeCommand:
|
||||
var config = &serverconfigs.AccessLogCommandStorageConfig{}
|
||||
if len(optionsJSON) > 0 {
|
||||
err := json.Unmarshal(optionsJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return NewCommandStorage(config), nil
|
||||
}
|
||||
|
||||
return nil, errors.New("invalid policy type '" + storageType + "'")
|
||||
}
|
||||
17
internal/accesslogs/storage_manager_test.go
Normal file
17
internal/accesslogs/storage_manager_test.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package accesslogs
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStorageManager_Loop(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var storage = NewStorageManager()
|
||||
err := storage.Loop()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(storage.storageMap)
|
||||
}
|
||||
137
internal/accesslogs/storage_syslog.go
Normal file
137
internal/accesslogs/storage_syslog.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package accesslogs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type SyslogStorageProtocol = string
|
||||
|
||||
const (
|
||||
SyslogStorageProtocolTCP SyslogStorageProtocol = "tcp"
|
||||
SyslogStorageProtocolUDP SyslogStorageProtocol = "udp"
|
||||
SyslogStorageProtocolNone SyslogStorageProtocol = "none"
|
||||
SyslogStorageProtocolSocket SyslogStorageProtocol = "socket"
|
||||
)
|
||||
|
||||
type SyslogStoragePriority = int
|
||||
|
||||
// SyslogStorage syslog存储策略
|
||||
type SyslogStorage struct {
|
||||
BaseStorage
|
||||
|
||||
config *serverconfigs.AccessLogSyslogStorageConfig
|
||||
|
||||
exe string
|
||||
}
|
||||
|
||||
func NewSyslogStorage(config *serverconfigs.AccessLogSyslogStorageConfig) *SyslogStorage {
|
||||
return &SyslogStorage{config: config}
|
||||
}
|
||||
|
||||
func (this *SyslogStorage) Config() interface{} {
|
||||
return this.config
|
||||
}
|
||||
|
||||
// Start 开启
|
||||
func (this *SyslogStorage) Start() error {
|
||||
if runtime.GOOS != "linux" {
|
||||
return errors.New("'syslog' storage only works on linux")
|
||||
}
|
||||
|
||||
exe, err := exec.LookPath("logger")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
this.exe = exe
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 写入日志
|
||||
func (this *SyslogStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
if len(accessLogs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
args := []string{}
|
||||
if len(this.config.Tag) > 0 {
|
||||
args = append(args, "-t", this.config.Tag)
|
||||
}
|
||||
|
||||
if this.config.Priority >= 0 {
|
||||
args = append(args, "-p", strconv.Itoa(this.config.Priority))
|
||||
}
|
||||
|
||||
switch this.config.Protocol {
|
||||
case SyslogStorageProtocolTCP:
|
||||
args = append(args, "-T")
|
||||
if len(this.config.ServerAddr) > 0 {
|
||||
args = append(args, "-n", this.config.ServerAddr)
|
||||
}
|
||||
if this.config.ServerPort > 0 {
|
||||
args = append(args, "-P", strconv.Itoa(this.config.ServerPort))
|
||||
}
|
||||
case SyslogStorageProtocolUDP:
|
||||
args = append(args, "-d")
|
||||
if len(this.config.ServerAddr) > 0 {
|
||||
args = append(args, "-n", this.config.ServerAddr)
|
||||
}
|
||||
if this.config.ServerPort > 0 {
|
||||
args = append(args, "-P", strconv.Itoa(this.config.ServerPort))
|
||||
}
|
||||
case SyslogStorageProtocolSocket:
|
||||
args = append(args, "-u")
|
||||
args = append(args, this.config.Socket)
|
||||
case SyslogStorageProtocolNone:
|
||||
// do nothing
|
||||
}
|
||||
|
||||
args = append(args, "-S", "10240")
|
||||
|
||||
cmd := exec.Command(this.exe, args...)
|
||||
w, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, accessLog := range accessLogs {
|
||||
data, err := this.Marshal(accessLog)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
continue
|
||||
}
|
||||
_, err = w.Write(data)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
}
|
||||
|
||||
_, err = w.Write([]byte("\n"))
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
_ = w.Close()
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close 关闭
|
||||
func (this *SyslogStorage) Close() error {
|
||||
return nil
|
||||
}
|
||||
111
internal/accesslogs/storage_tcp.go
Normal file
111
internal/accesslogs/storage_tcp.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package accesslogs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"net"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// TCPStorage TCP存储策略
|
||||
type TCPStorage struct {
|
||||
BaseStorage
|
||||
|
||||
config *serverconfigs.AccessLogTCPStorageConfig
|
||||
|
||||
writeLocker sync.Mutex
|
||||
|
||||
connLocker sync.Mutex
|
||||
conn net.Conn
|
||||
}
|
||||
|
||||
func NewTCPStorage(config *serverconfigs.AccessLogTCPStorageConfig) *TCPStorage {
|
||||
return &TCPStorage{config: config}
|
||||
}
|
||||
|
||||
func (this *TCPStorage) Config() interface{} {
|
||||
return this.config
|
||||
}
|
||||
|
||||
// Start 开启
|
||||
func (this *TCPStorage) Start() error {
|
||||
if len(this.config.Network) == 0 {
|
||||
return errors.New("'network' should not be empty")
|
||||
}
|
||||
if len(this.config.Addr) == 0 {
|
||||
return errors.New("'addr' should not be empty")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 写入日志
|
||||
func (this *TCPStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
if len(accessLogs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := this.connect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
conn := this.conn
|
||||
if conn == nil {
|
||||
return errors.New("connection should not be nil")
|
||||
}
|
||||
|
||||
this.writeLocker.Lock()
|
||||
defer this.writeLocker.Unlock()
|
||||
|
||||
for _, accessLog := range accessLogs {
|
||||
data, err := this.Marshal(accessLog)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
continue
|
||||
}
|
||||
_, err = conn.Write(data)
|
||||
if err != nil {
|
||||
_ = this.Close()
|
||||
break
|
||||
}
|
||||
_, err = conn.Write([]byte("\n"))
|
||||
if err != nil {
|
||||
_ = this.Close()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close 关闭
|
||||
func (this *TCPStorage) Close() error {
|
||||
this.connLocker.Lock()
|
||||
defer this.connLocker.Unlock()
|
||||
|
||||
if this.conn != nil {
|
||||
err := this.conn.Close()
|
||||
this.conn = nil
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *TCPStorage) connect() error {
|
||||
this.connLocker.Lock()
|
||||
defer this.connLocker.Unlock()
|
||||
|
||||
if this.conn != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
conn, err := net.Dial(this.config.Network, this.config.Addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
this.conn = conn
|
||||
|
||||
return nil
|
||||
}
|
||||
72
internal/accesslogs/storage_tcp_test.go
Normal file
72
internal/accesslogs/storage_tcp_test.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package accesslogs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestTCPStorage_Write(t *testing.T) {
|
||||
go func() {
|
||||
server, err := net.Listen("tcp", "127.0.0.1:9981")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
for {
|
||||
conn, err := server.Accept()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
buf := make([]byte, 1024)
|
||||
for {
|
||||
n, err := conn.Read(buf)
|
||||
if n > 0 {
|
||||
t.Log(string(buf[:n]))
|
||||
}
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
_ = server.Close()
|
||||
}()
|
||||
|
||||
storage := NewTCPStorage(&serverconfigs.AccessLogTCPStorageConfig{
|
||||
Network: "tcp",
|
||||
Addr: "127.0.0.1:9981",
|
||||
})
|
||||
err := storage.Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
{
|
||||
err = storage.Write([]*pb.HTTPAccessLog{
|
||||
{
|
||||
RequestMethod: "POST",
|
||||
RequestPath: "/1",
|
||||
TimeLocal: time.Now().Format("2/Jan/2006:15:04:05 -0700"),
|
||||
},
|
||||
{
|
||||
RequestMethod: "GET",
|
||||
RequestPath: "/2",
|
||||
TimeLocal: time.Now().Format("2/Jan/2006:15:04:05 -0700"),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
err = storage.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
24
internal/accesslogs/tests/command_storage.php
Normal file
24
internal/accesslogs/tests/command_storage.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
// test command storage
|
||||
|
||||
// open access log file
|
||||
$fp = fopen("/tmp/goedge-command-storage.log", "a+");
|
||||
|
||||
// read access logs from stdin
|
||||
$stdin = fopen("php://stdin", "r");
|
||||
while(true) {
|
||||
if (feof($stdin)) {
|
||||
break;
|
||||
}
|
||||
$line = fgets($stdin);
|
||||
|
||||
// write to access log file
|
||||
fwrite($fp, $line);
|
||||
}
|
||||
|
||||
// close file pointers
|
||||
fclose($fp);
|
||||
fclose($stdin);
|
||||
|
||||
?>
|
||||
@@ -2,8 +2,11 @@ package apps
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"github.com/iwind/gosock/pkg/gosock"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
@@ -11,7 +14,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// App命令帮助
|
||||
// AppCmd App命令帮助
|
||||
type AppCmd struct {
|
||||
product string
|
||||
version string
|
||||
@@ -20,10 +23,14 @@ type AppCmd struct {
|
||||
appendStrings []string
|
||||
|
||||
directives []*Directive
|
||||
|
||||
sock *gosock.Sock
|
||||
}
|
||||
|
||||
func NewAppCmd() *AppCmd {
|
||||
return &AppCmd{}
|
||||
return &AppCmd{
|
||||
sock: gosock.NewTmpSock(teaconst.ProcessName),
|
||||
}
|
||||
}
|
||||
|
||||
type CommandHelpOption struct {
|
||||
@@ -31,25 +38,25 @@ type CommandHelpOption struct {
|
||||
Description string
|
||||
}
|
||||
|
||||
// 产品
|
||||
// Product 产品
|
||||
func (this *AppCmd) Product(product string) *AppCmd {
|
||||
this.product = product
|
||||
return this
|
||||
}
|
||||
|
||||
// 版本
|
||||
// Version 版本
|
||||
func (this *AppCmd) Version(version string) *AppCmd {
|
||||
this.version = version
|
||||
return this
|
||||
}
|
||||
|
||||
// 使用方法
|
||||
// Usage 使用方法
|
||||
func (this *AppCmd) Usage(usage string) *AppCmd {
|
||||
this.usage = usage
|
||||
return this
|
||||
}
|
||||
|
||||
// 选项
|
||||
// Option 选项
|
||||
func (this *AppCmd) Option(code string, description string) *AppCmd {
|
||||
this.options = append(this.options, &CommandHelpOption{
|
||||
Code: code,
|
||||
@@ -58,13 +65,13 @@ func (this *AppCmd) Option(code string, description string) *AppCmd {
|
||||
return this
|
||||
}
|
||||
|
||||
// 附加内容
|
||||
// Append 附加内容
|
||||
func (this *AppCmd) Append(appendString string) *AppCmd {
|
||||
this.appendStrings = append(this.appendStrings, appendString)
|
||||
return this
|
||||
}
|
||||
|
||||
// 打印
|
||||
// Print 打印
|
||||
func (this *AppCmd) Print() {
|
||||
fmt.Println(this.product + " v" + this.version)
|
||||
|
||||
@@ -103,7 +110,7 @@ func (this *AppCmd) Print() {
|
||||
}
|
||||
}
|
||||
|
||||
// 添加指令
|
||||
// On 添加指令
|
||||
func (this *AppCmd) On(arg string, callback func()) {
|
||||
this.directives = append(this.directives, &Directive{
|
||||
Arg: arg,
|
||||
@@ -111,7 +118,7 @@ func (this *AppCmd) On(arg string, callback func()) {
|
||||
})
|
||||
}
|
||||
|
||||
// 运行
|
||||
// Run 运行
|
||||
func (this *AppCmd) Run(main func()) {
|
||||
// 获取参数
|
||||
args := os.Args[1:]
|
||||
@@ -150,9 +157,6 @@ func (this *AppCmd) Run(main func()) {
|
||||
return
|
||||
}
|
||||
|
||||
// 记录PID
|
||||
_ = this.writePid()
|
||||
|
||||
// 日志
|
||||
writer := new(LogWriter)
|
||||
writer.Init()
|
||||
@@ -164,7 +168,7 @@ func (this *AppCmd) Run(main func()) {
|
||||
|
||||
// 版本号
|
||||
func (this *AppCmd) runVersion() {
|
||||
fmt.Println(this.product+" v"+this.version, "(build: "+runtime.Version(), runtime.GOOS, runtime.GOARCH+")")
|
||||
fmt.Println(this.product+" v"+this.version, "(build: "+runtime.Version(), runtime.GOOS, runtime.GOARCH, teaconst.Tag+")")
|
||||
}
|
||||
|
||||
// 帮助
|
||||
@@ -174,9 +178,9 @@ func (this *AppCmd) runHelp() {
|
||||
|
||||
// 启动
|
||||
func (this *AppCmd) runStart() {
|
||||
proc := this.checkPid()
|
||||
if proc != nil {
|
||||
fmt.Println(this.product+" already started, pid:", proc.Pid)
|
||||
var pid = this.getPID()
|
||||
if pid > 0 {
|
||||
fmt.Println(this.product+" already started, pid:", pid)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -192,18 +196,15 @@ func (this *AppCmd) runStart() {
|
||||
|
||||
// 停止
|
||||
func (this *AppCmd) runStop() {
|
||||
proc := this.checkPid()
|
||||
if proc == nil {
|
||||
var pid = this.getPID()
|
||||
if pid == 0 {
|
||||
fmt.Println(this.product + " not started yet")
|
||||
return
|
||||
}
|
||||
|
||||
// 停止进程
|
||||
_ = proc.Kill()
|
||||
_, _ = this.sock.Send(&gosock.Command{Code: "stop"})
|
||||
|
||||
// 在Windows上经常不能及时释放资源
|
||||
_ = DeletePid(Tea.Root + "/bin/pid")
|
||||
fmt.Println(this.product+" stopped ok, pid:", proc.Pid)
|
||||
fmt.Println(this.product+" stopped ok, pid:", types.String(pid))
|
||||
}
|
||||
|
||||
// 重启
|
||||
@@ -215,20 +216,24 @@ func (this *AppCmd) runRestart() {
|
||||
|
||||
// 状态
|
||||
func (this *AppCmd) runStatus() {
|
||||
proc := this.checkPid()
|
||||
if proc == nil {
|
||||
var pid = this.getPID()
|
||||
if pid == 0 {
|
||||
fmt.Println(this.product + " not started yet")
|
||||
} else {
|
||||
fmt.Println(this.product + " is running, pid: " + fmt.Sprintf("%d", proc.Pid))
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(this.product + " is running, pid: " + types.String(pid))
|
||||
}
|
||||
|
||||
// 检查PID
|
||||
func (this *AppCmd) checkPid() *os.Process {
|
||||
return CheckPid(Tea.Root + "/bin/pid")
|
||||
}
|
||||
// 获取当前的PID
|
||||
func (this *AppCmd) getPID() int {
|
||||
if !this.sock.IsListening() {
|
||||
return 0
|
||||
}
|
||||
|
||||
// 写入PID
|
||||
func (this *AppCmd) writePid() error {
|
||||
return WritePid(Tea.Root + "/bin/pid")
|
||||
reply, err := this.sock.Send(&gosock.Command{Code: "pid"})
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return maps.NewMap(reply.Params).GetInt("pid")
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
// +build !windows
|
||||
|
||||
package apps
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// lock file
|
||||
func LockFile(fp *os.File) error {
|
||||
return syscall.Flock(int(fp.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
|
||||
}
|
||||
|
||||
func UnlockFile(fp *os.File) error {
|
||||
return syscall.Flock(int(fp.Fd()), syscall.LOCK_UN)
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
// +build windows
|
||||
|
||||
package apps
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
)
|
||||
|
||||
// lock file
|
||||
func LockFile(fp *os.File) error {
|
||||
return errors.New("not implemented on windows")
|
||||
}
|
||||
|
||||
func UnlockFile(fp *os.File) error {
|
||||
return errors.New("not implemented on windows")
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
package apps
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var pidFileList = []*os.File{}
|
||||
|
||||
// 检查Pid
|
||||
func CheckPid(path string) *os.Process {
|
||||
// windows上打开的文件是不能删除的
|
||||
if runtime.GOOS == "windows" {
|
||||
if os.Remove(path) == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_ = file.Close()
|
||||
}()
|
||||
|
||||
// 是否能取得Lock
|
||||
err = LockFile(file)
|
||||
if err == nil {
|
||||
_ = UnlockFile(file)
|
||||
return nil
|
||||
}
|
||||
|
||||
pidBytes, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
pid := types.Int(string(pidBytes))
|
||||
|
||||
if pid <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
proc, _ := os.FindProcess(pid)
|
||||
return proc
|
||||
}
|
||||
|
||||
// 写入Pid
|
||||
func WritePid(path string) error {
|
||||
fp, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_RDONLY, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
err = LockFile(fp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
pidFileList = append(pidFileList, fp) // hold the file pointers
|
||||
|
||||
_, err = fp.WriteString(fmt.Sprintf("%d", os.Getpid()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 写入Ppid
|
||||
func WritePpid(path string) error {
|
||||
fp, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_RDONLY, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
err = LockFile(fp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
pidFileList = append(pidFileList, fp) // hold the file pointers
|
||||
|
||||
_, err = fp.WriteString(fmt.Sprintf("%d", os.Getppid()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 删除Pid
|
||||
func DeletePid(path string) error {
|
||||
_, err := os.Stat(path)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
for _, fp := range pidFileList {
|
||||
_ = UnlockFile(fp)
|
||||
_ = fp.Close()
|
||||
}
|
||||
return os.Remove(path)
|
||||
}
|
||||
8
internal/const/build.go
Normal file
8
internal/const/build.go
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
// +build community
|
||||
|
||||
package teaconst
|
||||
|
||||
const BuildCommunity = true
|
||||
const BuildPlus = false
|
||||
const Tag = "community"
|
||||
@@ -1,7 +1,7 @@
|
||||
package teaconst
|
||||
|
||||
const (
|
||||
Version = "0.2.5"
|
||||
Version = "0.2.7"
|
||||
|
||||
ProductName = "Edge API"
|
||||
ProcessName = "edge-api"
|
||||
@@ -18,9 +18,9 @@ const (
|
||||
|
||||
// 其他节点版本号,用来检测是否有需要升级的节点
|
||||
|
||||
NodeVersion = "0.2.5"
|
||||
NodeVersion = "0.2.7"
|
||||
UserNodeVersion = "0.0.10"
|
||||
AuthorityNodeVersion = "0.0.2"
|
||||
MonitorNodeVersion = "0.0.2"
|
||||
DNSNodeVersion = "0.0.2"
|
||||
DNSNodeVersion = "0.0.3"
|
||||
)
|
||||
|
||||
@@ -346,7 +346,7 @@ func (this *DBNodeInitializer) loop() error {
|
||||
logs.Println("[DB_NODE]create first table in database node failed: " + err.Error())
|
||||
|
||||
// 创建节点日志
|
||||
createLogErr := SharedNodeLogDAO.CreateLog(nil, nodeconfigs.NodeRoleDatabase, nodeId, 0, "error", "ACCESS_LOG", "can not create access log table: "+err.Error(), time.Now().Unix())
|
||||
createLogErr := SharedNodeLogDAO.CreateLog(nil, nodeconfigs.NodeRoleDatabase, nodeId, 0, 0, "error", "ACCESS_LOG", "can not create access log table: "+err.Error(), time.Now().Unix())
|
||||
if createLogErr != nil {
|
||||
logs.Println("[NODE_LOG]" + createLogErr.Error())
|
||||
}
|
||||
@@ -390,7 +390,7 @@ func (this *DBNodeInitializer) loop() error {
|
||||
logs.Println("[DB_NODE]create first table in database node failed: " + err.Error())
|
||||
|
||||
// 创建节点日志
|
||||
createLogErr := SharedNodeLogDAO.CreateLog(nil, nodeconfigs.NodeRoleDatabase, nodeId, 0, "error", "ACCESS_LOG", "can not create access log table: "+err.Error(), time.Now().Unix())
|
||||
createLogErr := SharedNodeLogDAO.CreateLog(nil, nodeconfigs.NodeRoleDatabase, nodeId, 0, 0, "error", "ACCESS_LOG", "can not create access log table: "+err.Error(), time.Now().Unix())
|
||||
if createLogErr != nil {
|
||||
logs.Println("[NODE_LOG]" + createLogErr.Error())
|
||||
}
|
||||
|
||||
@@ -236,6 +236,10 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
query.Between("remoteAddr", pieces[0], pieces[1])
|
||||
}
|
||||
} else {
|
||||
if regexp.MustCompile(`^ip:.+`).MatchString(keyword) {
|
||||
keyword = keyword[3:]
|
||||
}
|
||||
|
||||
useOriginKeyword := false
|
||||
|
||||
where := "JSON_EXTRACT(content, '$.remoteAddr') LIKE :keyword OR JSON_EXTRACT(content, '$.requestURI') LIKE :keyword OR JSON_EXTRACT(content, '$.host') LIKE :keyword"
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"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/maps"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -35,12 +36,12 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 初始化
|
||||
// Init 初始化
|
||||
func (this *HTTPAccessLogPolicyDAO) Init() {
|
||||
_ = this.DAOObject.Init()
|
||||
}
|
||||
|
||||
// 启用条目
|
||||
// EnableHTTPAccessLogPolicy 启用条目
|
||||
func (this *HTTPAccessLogPolicyDAO) EnableHTTPAccessLogPolicy(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -49,7 +50,7 @@ func (this *HTTPAccessLogPolicyDAO) EnableHTTPAccessLogPolicy(tx *dbs.Tx, id int
|
||||
return err
|
||||
}
|
||||
|
||||
// 禁用条目
|
||||
// DisableHTTPAccessLogPolicy 禁用条目
|
||||
func (this *HTTPAccessLogPolicyDAO) DisableHTTPAccessLogPolicy(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -58,7 +59,7 @@ func (this *HTTPAccessLogPolicyDAO) DisableHTTPAccessLogPolicy(tx *dbs.Tx, id in
|
||||
return err
|
||||
}
|
||||
|
||||
// 查找启用中的条目
|
||||
// FindEnabledHTTPAccessLogPolicy 查找启用中的条目
|
||||
func (this *HTTPAccessLogPolicyDAO) FindEnabledHTTPAccessLogPolicy(tx *dbs.Tx, id int64) (*HTTPAccessLogPolicy, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -70,7 +71,7 @@ func (this *HTTPAccessLogPolicyDAO) FindEnabledHTTPAccessLogPolicy(tx *dbs.Tx, i
|
||||
return result.(*HTTPAccessLogPolicy), err
|
||||
}
|
||||
|
||||
// 根据主键查找名称
|
||||
// FindHTTPAccessLogPolicyName 根据主键查找名称
|
||||
func (this *HTTPAccessLogPolicyDAO) FindHTTPAccessLogPolicyName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -78,51 +79,116 @@ func (this *HTTPAccessLogPolicyDAO) FindHTTPAccessLogPolicyName(tx *dbs.Tx, id i
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// 查找所有可用策略信息
|
||||
func (this *HTTPAccessLogPolicyDAO) FindAllEnabledAccessLogPolicies(tx *dbs.Tx) (result []*HTTPAccessLogPolicy, err error) {
|
||||
// CountAllEnabledPolicies 计算策略数量
|
||||
func (this *HTTPAccessLogPolicyDAO) CountAllEnabledPolicies(tx *dbs.Tx) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(HTTPAccessLogPolicyStateEnabled).
|
||||
Count()
|
||||
}
|
||||
|
||||
// ListEnabledPolicies 查找所有可用策略信息
|
||||
func (this *HTTPAccessLogPolicyDAO) ListEnabledPolicies(tx *dbs.Tx, offset int64, size int64) (result []*HTTPAccessLogPolicy, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(HTTPAccessLogPolicyStateEnabled).
|
||||
DescPk().
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// 组合配置
|
||||
func (this *HTTPAccessLogPolicyDAO) ComposeAccessLogPolicyConfig(tx *dbs.Tx, policyId int64) (*serverconfigs.HTTPAccessLogStoragePolicy, error) {
|
||||
policy, err := this.FindEnabledHTTPAccessLogPolicy(tx, policyId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if policy == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
config := &serverconfigs.HTTPAccessLogStoragePolicy{}
|
||||
config.Id = int64(policy.Id)
|
||||
config.IsOn = policy.IsOn == 1
|
||||
config.Name = policy.Name
|
||||
config.Type = policy.Type
|
||||
|
||||
// 选项
|
||||
if IsNotNull(policy.Options) {
|
||||
m := map[string]interface{}{}
|
||||
err = json.Unmarshal([]byte(policy.Options), &m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.Options = m
|
||||
}
|
||||
|
||||
// 条件
|
||||
if IsNotNull(policy.Conds) {
|
||||
condsConfig := &shared.HTTPRequestCondsConfig{}
|
||||
err = json.Unmarshal([]byte(policy.Conds), condsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.Conds = condsConfig
|
||||
}
|
||||
|
||||
return config, nil
|
||||
// FindAllEnabledAndOnPolicies 获取所有的策略信息
|
||||
func (this *HTTPAccessLogPolicyDAO) FindAllEnabledAndOnPolicies(tx *dbs.Tx) (result []*HTTPAccessLogPolicy, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(HTTPAccessLogPolicyStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// CreatePolicy 创建策略
|
||||
func (this *HTTPAccessLogPolicyDAO) CreatePolicy(tx *dbs.Tx, name string, policyType string, optionsJSON []byte, condsJSON []byte, isPublic bool) (policyId int64, err error) {
|
||||
var op = NewHTTPAccessLogPolicyOperator()
|
||||
op.Name = name
|
||||
op.Type = policyType
|
||||
if len(optionsJSON) > 0 {
|
||||
op.Options = optionsJSON
|
||||
}
|
||||
if len(condsJSON) > 0 {
|
||||
op.Conds = condsJSON
|
||||
}
|
||||
op.IsPublic = isPublic
|
||||
op.IsOn = true
|
||||
op.State = HTTPAccessLogPolicyStateEnabled
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// UpdatePolicy 修改策略
|
||||
func (this *HTTPAccessLogPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, name string, optionsJSON []byte, condsJSON []byte, isPublic bool, isOn bool) error {
|
||||
if policyId <= 0 {
|
||||
return errors.New("invalid policyId")
|
||||
}
|
||||
|
||||
oldOne, err := this.Query(tx).
|
||||
Pk(policyId).
|
||||
Find()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if oldOne == nil {
|
||||
return nil
|
||||
}
|
||||
var oldPolicy = oldOne.(*HTTPAccessLogPolicy)
|
||||
|
||||
var op = NewHTTPAccessLogPolicyOperator()
|
||||
op.Id = policyId
|
||||
op.Name = name
|
||||
if len(optionsJSON) > 0 {
|
||||
op.Options = optionsJSON
|
||||
} else {
|
||||
op.Options = "{}"
|
||||
}
|
||||
if len(condsJSON) > 0 {
|
||||
op.Conds = condsJSON
|
||||
} else {
|
||||
op.Conds = "{}"
|
||||
}
|
||||
|
||||
// 版本号
|
||||
if len(oldPolicy.Options) == 0 || len(optionsJSON) == 0 {
|
||||
op.Version = dbs.SQL("version+1")
|
||||
} else {
|
||||
var m1 = maps.Map{}
|
||||
_ = json.Unmarshal([]byte(oldPolicy.Options), &m1)
|
||||
|
||||
var m2 = maps.Map{}
|
||||
_ = json.Unmarshal(optionsJSON, &m2)
|
||||
|
||||
if bytes.Compare(m1.AsJSON(), m2.AsJSON()) != 0 {
|
||||
op.Version = dbs.SQL("version+1")
|
||||
}
|
||||
}
|
||||
|
||||
op.IsPublic = isPublic
|
||||
op.IsOn = isOn
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// CancelAllPublicPolicies 取消别的公用的策略
|
||||
func (this *HTTPAccessLogPolicyDAO) CancelAllPublicPolicies(tx *dbs.Tx) error {
|
||||
return this.Query(tx).
|
||||
State(HTTPAccessLogPolicyStateEnabled).
|
||||
Set("isPublic", 0).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// FindCurrentPublicPolicyId 取得当前的公用策略
|
||||
func (this *HTTPAccessLogPolicyDAO) FindCurrentPublicPolicyId(tx *dbs.Tx) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(HTTPAccessLogPolicyStateEnabled).
|
||||
Attr("isPublic", 1).
|
||||
ResultPk().
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package models
|
||||
|
||||
// 访问日志策略
|
||||
// HTTPAccessLogPolicy 访问日志策略
|
||||
type HTTPAccessLogPolicy struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
@@ -13,6 +13,8 @@ type HTTPAccessLogPolicy struct {
|
||||
Type string `field:"type"` // 存储类型
|
||||
Options string `field:"options"` // 存储选项
|
||||
Conds string `field:"conds"` // 请求条件
|
||||
IsPublic uint8 `field:"isPublic"` // 是否为公用
|
||||
Version uint32 `field:"version"` // 版本号
|
||||
}
|
||||
|
||||
type HTTPAccessLogPolicyOperator struct {
|
||||
@@ -27,6 +29,8 @@ type HTTPAccessLogPolicyOperator struct {
|
||||
Type interface{} // 存储类型
|
||||
Options interface{} // 存储选项
|
||||
Conds interface{} // 请求条件
|
||||
IsPublic interface{} // 是否为公用
|
||||
Version interface{} // 版本号
|
||||
}
|
||||
|
||||
func NewHTTPAccessLogPolicyOperator() *HTTPAccessLogPolicyOperator {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
_ "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/types"
|
||||
)
|
||||
|
||||
@@ -275,6 +276,17 @@ func (this *HTTPLocationDAO) FindEnabledLocationIdWithWebId(tx *dbs.Tx, webId in
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// FindEnabledLocationIdWithReverseProxyId 查找包含某个反向代理的Server
|
||||
func (this *HTTPLocationDAO) FindEnabledLocationIdWithReverseProxyId(tx *dbs.Tx, reverseProxyId int64) (serverId int64, err error) {
|
||||
return this.Query(tx).
|
||||
State(ServerStateEnabled).
|
||||
Where("JSON_CONTAINS(reverseProxy, :jsonQuery)").
|
||||
Param("jsonQuery", maps.Map{"reverseProxyId": reverseProxyId}.AsJSON()).
|
||||
ResultPk().
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *HTTPLocationDAO) NotifyUpdate(tx *dbs.Tx, locationId int64) error {
|
||||
webId, err := SharedHTTPWebDAO.FindEnabledWebIdWithLocationId(tx, locationId)
|
||||
|
||||
@@ -74,7 +74,7 @@ func (this *MetricChartDAO) FindMetricChartName(tx *dbs.Tx, chartId int64) (stri
|
||||
}
|
||||
|
||||
// CreateChart 创建图表
|
||||
func (this *MetricChartDAO) CreateChart(tx *dbs.Tx, itemId int64, name string, chartType string, widthDiv int32, maxItems int32, params maps.Map) (int64, error) {
|
||||
func (this *MetricChartDAO) CreateChart(tx *dbs.Tx, itemId int64, name string, chartType string, widthDiv int32, maxItems int32, params maps.Map, ignoreEmptyKeys bool, ignoredKeys []string) (int64, error) {
|
||||
op := NewMetricChartOperator()
|
||||
op.ItemId = itemId
|
||||
op.Name = name
|
||||
@@ -90,13 +90,25 @@ func (this *MetricChartDAO) CreateChart(tx *dbs.Tx, itemId int64, name string, c
|
||||
return 0, err
|
||||
}
|
||||
op.Params = paramsJSON
|
||||
op.IgnoreEmptyKeys = ignoreEmptyKeys
|
||||
|
||||
if len(ignoredKeys) == 0 {
|
||||
op.IgnoredKeys = "[]"
|
||||
} else {
|
||||
ignoredKeysJSON, err := json.Marshal(ignoredKeys)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.IgnoredKeys = ignoredKeysJSON
|
||||
}
|
||||
|
||||
op.IsOn = true
|
||||
op.State = MetricChartStateEnabled
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// UpdateChart 修改图表
|
||||
func (this *MetricChartDAO) UpdateChart(tx *dbs.Tx, chartId int64, name string, chartType string, widthDiv int32, maxItems int32, params maps.Map, isOn bool) error {
|
||||
func (this *MetricChartDAO) UpdateChart(tx *dbs.Tx, chartId int64, name string, chartType string, widthDiv int32, maxItems int32, params maps.Map, ignoreEmptyKeys bool, ignoredKeys []string, isOn bool) error {
|
||||
if chartId <= 0 {
|
||||
return errors.New("invalid chartId")
|
||||
}
|
||||
@@ -115,6 +127,17 @@ func (this *MetricChartDAO) UpdateChart(tx *dbs.Tx, chartId int64, name string,
|
||||
return err
|
||||
}
|
||||
op.Params = paramsJSON
|
||||
op.IgnoreEmptyKeys = ignoreEmptyKeys
|
||||
|
||||
if len(ignoredKeys) == 0 {
|
||||
op.IgnoredKeys = "[]"
|
||||
} else {
|
||||
ignoredKeysJSON, err := json.Marshal(ignoredKeys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.IgnoredKeys = ignoredKeysJSON
|
||||
}
|
||||
|
||||
op.IsOn = isOn
|
||||
|
||||
|
||||
@@ -2,31 +2,35 @@ package models
|
||||
|
||||
// MetricChart 指标图表
|
||||
type MetricChart struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
ItemId uint32 `field:"itemId"` // 指标ID
|
||||
Name string `field:"name"` // 名称
|
||||
Code string `field:"code"` // 代号
|
||||
Type string `field:"type"` // 图形类型
|
||||
WidthDiv int32 `field:"widthDiv"` // 宽度划分
|
||||
Params string `field:"params"` // 图形参数
|
||||
Order uint32 `field:"order"` // 排序
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
State uint8 `field:"state"` // 状态
|
||||
MaxItems uint32 `field:"maxItems"` // 最多条目
|
||||
Id uint32 `field:"id"` // ID
|
||||
ItemId uint32 `field:"itemId"` // 指标ID
|
||||
Name string `field:"name"` // 名称
|
||||
Code string `field:"code"` // 代号
|
||||
Type string `field:"type"` // 图形类型
|
||||
WidthDiv int32 `field:"widthDiv"` // 宽度划分
|
||||
Params string `field:"params"` // 图形参数
|
||||
Order uint32 `field:"order"` // 排序
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
State uint8 `field:"state"` // 状态
|
||||
MaxItems uint32 `field:"maxItems"` // 最多条目
|
||||
IgnoreEmptyKeys uint8 `field:"ignoreEmptyKeys"` // 忽略空的键值
|
||||
IgnoredKeys string `field:"ignoredKeys"` // 忽略键值
|
||||
}
|
||||
|
||||
type MetricChartOperator struct {
|
||||
Id interface{} // ID
|
||||
ItemId interface{} // 指标ID
|
||||
Name interface{} // 名称
|
||||
Code interface{} // 代号
|
||||
Type interface{} // 图形类型
|
||||
WidthDiv interface{} // 宽度划分
|
||||
Params interface{} // 图形参数
|
||||
Order interface{} // 排序
|
||||
IsOn interface{} // 是否启用
|
||||
State interface{} // 状态
|
||||
MaxItems interface{} // 最多条目
|
||||
Id interface{} // ID
|
||||
ItemId interface{} // 指标ID
|
||||
Name interface{} // 名称
|
||||
Code interface{} // 代号
|
||||
Type interface{} // 图形类型
|
||||
WidthDiv interface{} // 宽度划分
|
||||
Params interface{} // 图形参数
|
||||
Order interface{} // 排序
|
||||
IsOn interface{} // 是否启用
|
||||
State interface{} // 状态
|
||||
MaxItems interface{} // 最多条目
|
||||
IgnoreEmptyKeys interface{} // 忽略空的键值
|
||||
IgnoredKeys interface{} // 忽略键值
|
||||
}
|
||||
|
||||
func NewMetricChartOperator() *MetricChartOperator {
|
||||
|
||||
@@ -1 +1,17 @@
|
||||
package models
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
func (this *MetricChart) DecodeIgnoredKeys() []string {
|
||||
if len(this.IgnoredKeys) == 0 {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
var result = []string{}
|
||||
err := json.Unmarshal([]byte(this.IgnoredKeys), &result)
|
||||
if err != nil {
|
||||
// 这里忽略错误
|
||||
return result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ func (this *MetricItemDAO) UpdateItem(tx *dbs.Tx, itemId int64, name string, key
|
||||
|
||||
// 删除旧数据
|
||||
if versionChanged {
|
||||
err := SharedMetricStatDAO.DeleteOldItemStats(tx, itemId, types.Int32(oldItem.Version+1))
|
||||
err := SharedMetricStatDAO.DeleteOldVersionItemStats(tx, itemId, types.Int32(oldItem.Version+1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -81,11 +81,12 @@ func (this *MetricStatDAO) CreateStat(tx *dbs.Tx, hash string, clusterId int64,
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteOldItemStats 删除以前版本的统计数据
|
||||
func (this *MetricStatDAO) DeleteOldItemStats(tx *dbs.Tx, itemId int64, version int32) error {
|
||||
// DeleteOldVersionItemStats 删除以前版本的统计数据
|
||||
func (this *MetricStatDAO) DeleteOldVersionItemStats(tx *dbs.Tx, itemId int64, version int32) error {
|
||||
_, err := this.Query(tx).
|
||||
Attr("itemId", itemId).
|
||||
Where("version<:version").
|
||||
Param("version", version).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
@@ -98,6 +99,17 @@ func (this *MetricStatDAO) DeleteItemStats(tx *dbs.Tx, itemId int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteNodeItemStats 删除某个节点的统计数据
|
||||
func (this *MetricStatDAO) DeleteNodeItemStats(tx *dbs.Tx, nodeId int64, serverId int64, itemId int64, time string) error {
|
||||
_, err := this.Query(tx).
|
||||
Attr("nodeId", nodeId).
|
||||
Attr("serverId", serverId).
|
||||
Attr("itemId", itemId).
|
||||
Attr("time", time).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
// CountItemStats 计算统计数据数量
|
||||
func (this *MetricStatDAO) CountItemStats(tx *dbs.Tx, itemId int64, version int32) (int64, error) {
|
||||
return this.Query(tx).
|
||||
@@ -123,7 +135,7 @@ func (this *MetricStatDAO) ListItemStats(tx *dbs.Tx, itemId int64, version int32
|
||||
|
||||
// FindItemStatsAtLastTime 取得所有集群最近一次计时前 N 个数据
|
||||
// 适合每条数据中包含不同的Key的场景
|
||||
func (this *MetricStatDAO) FindItemStatsAtLastTime(tx *dbs.Tx, itemId int64, version int32, size int64) (result []*MetricStat, err error) {
|
||||
func (this *MetricStatDAO) FindItemStatsAtLastTime(tx *dbs.Tx, itemId int64, ignoreEmptyKeys bool, ignoreKeys []string, version int32, size int64) (result []*MetricStat, err error) {
|
||||
// 最近一次时间
|
||||
statOne, err := this.Query(tx).
|
||||
Attr("itemId", itemId).
|
||||
@@ -133,13 +145,13 @@ func (this *MetricStatDAO) FindItemStatsAtLastTime(tx *dbs.Tx, itemId int64, ver
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if statOne == nil {
|
||||
return nil, nil
|
||||
}
|
||||
var lastStat = statOne.(*MetricStat)
|
||||
var lastTime = lastStat.Time
|
||||
|
||||
_, err = this.Query(tx).
|
||||
var query = this.Query(tx).
|
||||
Attr("itemId", itemId).
|
||||
Attr("version", version).
|
||||
Attr("time", lastTime).
|
||||
@@ -149,14 +161,26 @@ func (this *MetricStatDAO) FindItemStatsAtLastTime(tx *dbs.Tx, itemId int64, ver
|
||||
Desc("value").
|
||||
Group("keys").
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
Slice(&result)
|
||||
if ignoreEmptyKeys {
|
||||
query.Where("NOT JSON_CONTAINS(`keys`, '\"\"')")
|
||||
}
|
||||
if len(ignoreKeys) > 0 {
|
||||
ignoreKeysJSON, err := json.Marshal(ignoreKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query.Where("NOT JSON_CONTAINS(:ignoredKeys, JSON_EXTRACT(`keys`, '$[0]'))") // TODO $[0] 需要换成keys中的primary key位置
|
||||
query.Param("ignoredKeys", string(ignoreKeysJSON))
|
||||
}
|
||||
_, err = query.
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindItemStatsWithClusterIdAndLastTime 取得集群最近一次计时前 N 个数据
|
||||
// 适合每条数据中包含不同的Key的场景
|
||||
func (this *MetricStatDAO) FindItemStatsWithClusterIdAndLastTime(tx *dbs.Tx, clusterId int64, itemId int64, version int32, size int64) (result []*MetricStat, err error) {
|
||||
func (this *MetricStatDAO) FindItemStatsWithClusterIdAndLastTime(tx *dbs.Tx, clusterId int64, itemId int64, ignoreEmptyKeys bool, ignoreKeys []string, version int32, size int64) (result []*MetricStat, err error) {
|
||||
// 最近一次时间
|
||||
statOne, err := this.Query(tx).
|
||||
Attr("itemId", itemId).
|
||||
@@ -172,7 +196,7 @@ func (this *MetricStatDAO) FindItemStatsWithClusterIdAndLastTime(tx *dbs.Tx, clu
|
||||
var lastStat = statOne.(*MetricStat)
|
||||
var lastTime = lastStat.Time
|
||||
|
||||
_, err = this.Query(tx).
|
||||
var query = this.Query(tx).
|
||||
Attr("clusterId", clusterId).
|
||||
Attr("itemId", itemId).
|
||||
Attr("version", version).
|
||||
@@ -183,14 +207,27 @@ func (this *MetricStatDAO) FindItemStatsWithClusterIdAndLastTime(tx *dbs.Tx, clu
|
||||
Desc("value").
|
||||
Group("keys").
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
Slice(&result)
|
||||
if ignoreEmptyKeys {
|
||||
query.Where("NOT JSON_CONTAINS(`keys`, '\"\"')")
|
||||
}
|
||||
if len(ignoreKeys) > 0 {
|
||||
ignoreKeysJSON, err := json.Marshal(ignoreKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query.Where("NOT JSON_CONTAINS(:ignoredKeys, JSON_EXTRACT(`keys`, '$[0]'))") // TODO $[0] 需要换成keys中的primary key位置
|
||||
query.Param("ignoredKeys", string(ignoreKeysJSON))
|
||||
}
|
||||
|
||||
_, err = query.
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindItemStatsWithNodeIdAndLastTime 取得节点最近一次计时前 N 个数据
|
||||
// 适合每条数据中包含不同的Key的场景
|
||||
func (this *MetricStatDAO) FindItemStatsWithNodeIdAndLastTime(tx *dbs.Tx, nodeId int64, itemId int64, version int32, size int64) (result []*MetricStat, err error) {
|
||||
func (this *MetricStatDAO) FindItemStatsWithNodeIdAndLastTime(tx *dbs.Tx, nodeId int64, itemId int64, ignoreEmptyKeys bool, ignoreKeys []string, version int32, size int64) (result []*MetricStat, err error) {
|
||||
// 最近一次时间
|
||||
statOne, err := this.Query(tx).
|
||||
Attr("itemId", itemId).
|
||||
@@ -205,8 +242,7 @@ func (this *MetricStatDAO) FindItemStatsWithNodeIdAndLastTime(tx *dbs.Tx, nodeId
|
||||
}
|
||||
var lastStat = statOne.(*MetricStat)
|
||||
var lastTime = lastStat.Time
|
||||
|
||||
_, err = this.Query(tx).
|
||||
var query = this.Query(tx).
|
||||
Attr("nodeId", nodeId).
|
||||
Attr("itemId", itemId).
|
||||
Attr("version", version).
|
||||
@@ -217,14 +253,27 @@ func (this *MetricStatDAO) FindItemStatsWithNodeIdAndLastTime(tx *dbs.Tx, nodeId
|
||||
Desc("value").
|
||||
Group("keys").
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
Slice(&result)
|
||||
if ignoreEmptyKeys {
|
||||
query.Where("NOT JSON_CONTAINS(`keys`, '\"\"')")
|
||||
}
|
||||
if len(ignoreKeys) > 0 {
|
||||
ignoreKeysJSON, err := json.Marshal(ignoreKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query.Where("NOT JSON_CONTAINS(:ignoredKeys, JSON_EXTRACT(`keys`, '$[0]'))") // TODO $[0] 需要换成keys中的primary key位置
|
||||
query.Param("ignoredKeys", string(ignoreKeysJSON))
|
||||
}
|
||||
|
||||
_, err = query.
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindItemStatsWithServerIdAndLastTime 取得节点最近一次计时前 N 个数据
|
||||
// 适合每条数据中包含不同的Key的场景
|
||||
func (this *MetricStatDAO) FindItemStatsWithServerIdAndLastTime(tx *dbs.Tx, serverId int64, itemId int64, version int32, size int64) (result []*MetricStat, err error) {
|
||||
func (this *MetricStatDAO) FindItemStatsWithServerIdAndLastTime(tx *dbs.Tx, serverId int64, itemId int64, ignoreEmptyKeys bool, ignoreKeys []string, version int32, size int64) (result []*MetricStat, err error) {
|
||||
// 最近一次时间
|
||||
statOne, err := this.Query(tx).
|
||||
Attr("itemId", itemId).
|
||||
@@ -240,7 +289,7 @@ func (this *MetricStatDAO) FindItemStatsWithServerIdAndLastTime(tx *dbs.Tx, serv
|
||||
var lastStat = statOne.(*MetricStat)
|
||||
var lastTime = lastStat.Time
|
||||
|
||||
_, err = this.Query(tx).
|
||||
var query = this.Query(tx).
|
||||
Attr("serverId", serverId).
|
||||
Attr("itemId", itemId).
|
||||
Attr("version", version).
|
||||
@@ -251,15 +300,28 @@ func (this *MetricStatDAO) FindItemStatsWithServerIdAndLastTime(tx *dbs.Tx, serv
|
||||
Desc("value").
|
||||
Group("keys").
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
Slice(&result)
|
||||
if ignoreEmptyKeys {
|
||||
query.Where("NOT JSON_CONTAINS(`keys`, '\"\"')")
|
||||
}
|
||||
if len(ignoreKeys) > 0 {
|
||||
ignoreKeysJSON, err := json.Marshal(ignoreKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query.Where("NOT JSON_CONTAINS(:ignoredKeys, JSON_EXTRACT(`keys`, '$[0]'))") // TODO $[0] 需要换成keys中的primary key位置
|
||||
query.Param("ignoredKeys", string(ignoreKeysJSON))
|
||||
}
|
||||
|
||||
_, err = query.
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindLatestItemStats 取得所有集群上最近 N 个时间的数据
|
||||
// 适合同个Key在不同时间段的变化场景
|
||||
func (this *MetricStatDAO) FindLatestItemStats(tx *dbs.Tx, itemId int64, version int32, size int64) (result []*MetricStat, err error) {
|
||||
_, err = this.Query(tx).
|
||||
func (this *MetricStatDAO) FindLatestItemStats(tx *dbs.Tx, itemId int64, ignoreEmptyKeys bool, ignoreKeys []string, version int32, size int64) (result []*MetricStat, err error) {
|
||||
var query = this.Query(tx).
|
||||
Attr("itemId", itemId).
|
||||
Attr("version", version).
|
||||
// TODO 增加更多聚合算法,比如 AVG、MEDIAN、MIN、MAX 等
|
||||
@@ -268,7 +330,20 @@ func (this *MetricStatDAO) FindLatestItemStats(tx *dbs.Tx, itemId int64, version
|
||||
Desc("time").
|
||||
Group("time").
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
Slice(&result)
|
||||
if ignoreEmptyKeys {
|
||||
query.Where("NOT JSON_CONTAINS(`keys`, '\"\"')")
|
||||
}
|
||||
if len(ignoreKeys) > 0 {
|
||||
ignoreKeysJSON, err := json.Marshal(ignoreKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query.Where("NOT JSON_CONTAINS(:ignoredKeys, JSON_EXTRACT(`keys`, '$[0]'))") // TODO $[0] 需要换成keys中的primary key位置
|
||||
query.Param("ignoredKeys", string(ignoreKeysJSON))
|
||||
}
|
||||
|
||||
_, err = query.
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -279,8 +354,8 @@ func (this *MetricStatDAO) FindLatestItemStats(tx *dbs.Tx, itemId int64, version
|
||||
|
||||
// FindLatestItemStatsWithClusterId 取得集群最近 N 个时间的数据
|
||||
// 适合同个Key在不同时间段的变化场景
|
||||
func (this *MetricStatDAO) FindLatestItemStatsWithClusterId(tx *dbs.Tx, clusterId int64, itemId int64, version int32, size int64) (result []*MetricStat, err error) {
|
||||
_, err = this.Query(tx).
|
||||
func (this *MetricStatDAO) FindLatestItemStatsWithClusterId(tx *dbs.Tx, clusterId int64, itemId int64, ignoreEmptyKeys bool, ignoreKeys []string, version int32, size int64) (result []*MetricStat, err error) {
|
||||
var query = this.Query(tx).
|
||||
Attr("clusterId", clusterId).
|
||||
Attr("itemId", itemId).
|
||||
Attr("version", version).
|
||||
@@ -290,7 +365,20 @@ func (this *MetricStatDAO) FindLatestItemStatsWithClusterId(tx *dbs.Tx, clusterI
|
||||
Desc("time").
|
||||
Group("time").
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
Slice(&result)
|
||||
if ignoreEmptyKeys {
|
||||
query.Where("NOT JSON_CONTAINS(`keys`, '\"\"')")
|
||||
}
|
||||
if len(ignoreKeys) > 0 {
|
||||
ignoreKeysJSON, err := json.Marshal(ignoreKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query.Where("NOT JSON_CONTAINS(:ignoredKeys, JSON_EXTRACT(`keys`, '$[0]'))") // TODO $[0] 需要换成keys中的primary key位置
|
||||
query.Param("ignoredKeys", string(ignoreKeysJSON))
|
||||
}
|
||||
|
||||
_, err = query.
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -301,8 +389,8 @@ func (this *MetricStatDAO) FindLatestItemStatsWithClusterId(tx *dbs.Tx, clusterI
|
||||
|
||||
// FindLatestItemStatsWithNodeId 取得节点最近 N 个时间的数据
|
||||
// 适合同个Key在不同时间段的变化场景
|
||||
func (this *MetricStatDAO) FindLatestItemStatsWithNodeId(tx *dbs.Tx, nodeId int64, itemId int64, version int32, size int64) (result []*MetricStat, err error) {
|
||||
_, err = this.Query(tx).
|
||||
func (this *MetricStatDAO) FindLatestItemStatsWithNodeId(tx *dbs.Tx, nodeId int64, itemId int64, ignoreEmptyKeys bool, ignoreKeys []string, version int32, size int64) (result []*MetricStat, err error) {
|
||||
var query = this.Query(tx).
|
||||
Attr("nodeId", nodeId).
|
||||
Attr("itemId", itemId).
|
||||
Attr("version", version).
|
||||
@@ -312,7 +400,20 @@ func (this *MetricStatDAO) FindLatestItemStatsWithNodeId(tx *dbs.Tx, nodeId int6
|
||||
Desc("time").
|
||||
Group("time").
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
Slice(&result)
|
||||
if ignoreEmptyKeys {
|
||||
query.Where("NOT JSON_CONTAINS(`keys`, '\"\"')")
|
||||
}
|
||||
if len(ignoreKeys) > 0 {
|
||||
ignoreKeysJSON, err := json.Marshal(ignoreKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query.Where("NOT JSON_CONTAINS(:ignoredKeys, JSON_EXTRACT(`keys`, '$[0]'))") // TODO $[0] 需要换成keys中的primary key位置
|
||||
query.Param("ignoredKeys", string(ignoreKeysJSON))
|
||||
}
|
||||
|
||||
_, err = query.
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -323,8 +424,8 @@ func (this *MetricStatDAO) FindLatestItemStatsWithNodeId(tx *dbs.Tx, nodeId int6
|
||||
|
||||
// FindLatestItemStatsWithServerId 取得服务最近 N 个时间的数据
|
||||
// 适合同个Key在不同时间段的变化场景
|
||||
func (this *MetricStatDAO) FindLatestItemStatsWithServerId(tx *dbs.Tx, serverId int64, itemId int64, version int32, size int64) (result []*MetricStat, err error) {
|
||||
_, err = this.Query(tx).
|
||||
func (this *MetricStatDAO) FindLatestItemStatsWithServerId(tx *dbs.Tx, serverId int64, itemId int64, ignoreEmptyKeys bool, ignoreKeys []string, version int32, size int64) (result []*MetricStat, err error) {
|
||||
var query = this.Query(tx).
|
||||
Attr("serverId", serverId).
|
||||
Attr("itemId", itemId).
|
||||
Attr("version", version).
|
||||
@@ -334,7 +435,20 @@ func (this *MetricStatDAO) FindLatestItemStatsWithServerId(tx *dbs.Tx, serverId
|
||||
Desc("time").
|
||||
Group("time").
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
Slice(&result)
|
||||
if ignoreEmptyKeys {
|
||||
query.Where("NOT JSON_CONTAINS(`keys`, '\"\"')")
|
||||
}
|
||||
if len(ignoreKeys) > 0 {
|
||||
ignoreKeysJSON, err := json.Marshal(ignoreKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query.Where("NOT JSON_CONTAINS(:ignoredKeys, JSON_EXTRACT(`keys`, '$[0]'))") // TODO $[0] 需要换成keys中的primary key位置
|
||||
query.Param("ignoredKeys", string(ignoreKeysJSON))
|
||||
}
|
||||
|
||||
_, err = query.
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -3,4 +3,16 @@ package models
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewMetricStatDAO_InsertMany(t *testing.T) {
|
||||
for i := 0; i <= 1; i++ {
|
||||
err := NewMetricStatDAO().CreateStat(nil, types.String(i) + "_v1", 18, 48, 23, 25, []string{"/html" + types.String(i)}, 1, "20210728", 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
t.Log("done")
|
||||
}
|
||||
|
||||
@@ -194,3 +194,42 @@ func (this *NSDomainDAO) FindDomainIdWithName(tx *dbs.Tx, clusterId int64, name
|
||||
ResultPk().
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// FindEnabledDomainTSIG 获取TSIG配置
|
||||
func (this *NSDomainDAO) FindEnabledDomainTSIG(tx *dbs.Tx, domainId int64) ([]byte, error) {
|
||||
tsig, err := this.Query(tx).
|
||||
Pk(domainId).
|
||||
Result("tsig").
|
||||
FindStringCol("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(tsig), nil
|
||||
}
|
||||
|
||||
// UpdateDomainTSIG 修改TSIG配置
|
||||
func (this *NSDomainDAO) UpdateDomainTSIG(tx *dbs.Tx, domainId int64, tsigJSON []byte) error {
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
Pk(domainId).
|
||||
Set("tsig", tsigJSON).
|
||||
Set("version", version).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更改
|
||||
func (this *NSDomainDAO) NotifyUpdate(tx *dbs.Tx, domainId int64) error {
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
Pk(domainId).
|
||||
Set("version", version).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ type NSDomain struct {
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Version uint64 `field:"version"` // 版本
|
||||
State uint8 `field:"state"` // 状态
|
||||
Tsig string `field:"tsig"` // TSIG配置
|
||||
}
|
||||
|
||||
type NSDomainOperator struct {
|
||||
@@ -21,6 +22,7 @@ type NSDomainOperator struct {
|
||||
CreatedAt interface{} // 创建时间
|
||||
Version interface{} // 版本
|
||||
State interface{} // 状态
|
||||
Tsig interface{} // TSIG配置
|
||||
}
|
||||
|
||||
func NewNSDomainOperator() *NSDomainOperator {
|
||||
|
||||
183
internal/db/models/nameservers/ns_key_dao.go
Normal file
183
internal/db/models/nameservers/ns_key_dao.go
Normal file
@@ -0,0 +1,183 @@
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
const (
|
||||
NSKeyStateEnabled = 1 // 已启用
|
||||
NSKeyStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type NSKeyDAO dbs.DAO
|
||||
|
||||
func NewNSKeyDAO() *NSKeyDAO {
|
||||
return dbs.NewDAO(&NSKeyDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNSKeys",
|
||||
Model: new(NSKey),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NSKeyDAO)
|
||||
}
|
||||
|
||||
var SharedNSKeyDAO *NSKeyDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNSKeyDAO = NewNSKeyDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableNSKey 启用条目
|
||||
func (this *NSKeyDAO) EnableNSKey(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSKeyStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableNSKey 禁用条目
|
||||
func (this *NSKeyDAO) DisableNSKey(tx *dbs.Tx, keyId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(keyId).
|
||||
Set("state", NSKeyStateDisabled).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, keyId)
|
||||
}
|
||||
|
||||
// FindEnabledNSKey 查找启用中的条目
|
||||
func (this *NSKeyDAO) FindEnabledNSKey(tx *dbs.Tx, id int64) (*NSKey, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", NSKeyStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*NSKey), err
|
||||
}
|
||||
|
||||
// FindNSKeyName 根据主键查找名称
|
||||
func (this *NSKeyDAO) FindNSKeyName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// CreateKey 创建Key
|
||||
func (this *NSKeyDAO) CreateKey(tx *dbs.Tx, domainId int64, zoneId int64, name string, algo dnsconfigs.KeyAlgorithmType, secret string, secretType string) (int64, error) {
|
||||
op := NewNSKeyOperator()
|
||||
op.DomainId = domainId
|
||||
op.ZoneId = zoneId
|
||||
op.Name = name
|
||||
op.Algo = algo
|
||||
op.Secret = secret
|
||||
op.SecretType = secretType
|
||||
op.State = NSKeyStateEnabled
|
||||
keyId, err := this.SaveInt64(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = this.NotifyUpdate(tx, keyId)
|
||||
if err != nil {
|
||||
return keyId, err
|
||||
}
|
||||
|
||||
return keyId, nil
|
||||
}
|
||||
|
||||
// UpdateKey 修改Key
|
||||
func (this *NSKeyDAO) UpdateKey(tx *dbs.Tx, keyId int64, name string, algo dnsconfigs.KeyAlgorithmType, secret string, secretType string, isOn bool) error {
|
||||
if keyId <= 0 {
|
||||
return errors.New("invalid keyId")
|
||||
}
|
||||
op := NewNSKeyOperator()
|
||||
op.Id = keyId
|
||||
op.Name = name
|
||||
op.Algo = algo
|
||||
op.Secret = secret
|
||||
op.SecretType = secretType
|
||||
op.IsOn = isOn
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, keyId)
|
||||
}
|
||||
|
||||
// CountEnabledKeys 计算Key的数量
|
||||
func (this *NSKeyDAO) CountEnabledKeys(tx *dbs.Tx, domainId int64, zoneId int64) (int64, error) {
|
||||
var query = this.Query(tx).
|
||||
State(NSKeyStateEnabled)
|
||||
if domainId > 0 {
|
||||
query.Attr("domainId", domainId)
|
||||
}
|
||||
if zoneId > 0 {
|
||||
query.Attr("zoneId", zoneId)
|
||||
}
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// ListEnabledKeys 列出单页Key
|
||||
func (this *NSKeyDAO) ListEnabledKeys(tx *dbs.Tx, domainId int64, zoneId int64, offset int64, size int64) (result []*NSKey, err error) {
|
||||
var query = this.Query(tx).
|
||||
State(NSKeyStateEnabled)
|
||||
if domainId > 0 {
|
||||
query.Attr("domainId", domainId)
|
||||
}
|
||||
if zoneId > 0 {
|
||||
query.Attr("zoneId", zoneId)
|
||||
}
|
||||
_, err = query.
|
||||
DescPk().
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// IncreaseVersion 增加版本
|
||||
func (this *NSKeyDAO) IncreaseVersion(tx *dbs.Tx) (int64, error) {
|
||||
return models.SharedSysLockerDAO.Increase(tx, "NS_KEY_VERSION", 1)
|
||||
}
|
||||
|
||||
// ListKeysAfterVersion 列出某个版本后的密钥
|
||||
func (this *NSKeyDAO) ListKeysAfterVersion(tx *dbs.Tx, version int64, size int64) (result []*NSKey, err error) {
|
||||
if size <= 0 {
|
||||
size = 10000
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Gte("version", version).
|
||||
Limit(size).
|
||||
Asc("version").
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *NSKeyDAO) NotifyUpdate(tx *dbs.Tx, keyId int64) error {
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.Query(tx).
|
||||
Pk(keyId).
|
||||
Set("version", version).
|
||||
UpdateQuickly()
|
||||
}
|
||||
6
internal/db/models/nameservers/ns_key_dao_test.go
Normal file
6
internal/db/models/nameservers/ns_key_dao_test.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
32
internal/db/models/nameservers/ns_key_model.go
Normal file
32
internal/db/models/nameservers/ns_key_model.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package nameservers
|
||||
|
||||
// NSKey 密钥管理
|
||||
type NSKey struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 状态
|
||||
Name string `field:"name"` // 名称
|
||||
DomainId uint64 `field:"domainId"` // 域名ID
|
||||
ZoneId uint64 `field:"zoneId"` // 子域ID
|
||||
Algo string `field:"algo"` // 算法
|
||||
Secret string `field:"secret"` // 密码
|
||||
SecretType string `field:"secretType"` // 密码类型
|
||||
Version uint64 `field:"version"` // 版本号
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type NSKeyOperator struct {
|
||||
Id interface{} // ID
|
||||
IsOn interface{} // 状态
|
||||
Name interface{} // 名称
|
||||
DomainId interface{} // 域名ID
|
||||
ZoneId interface{} // 子域ID
|
||||
Algo interface{} // 算法
|
||||
Secret interface{} // 密码
|
||||
SecretType interface{} // 密码类型
|
||||
Version interface{} // 版本号
|
||||
State interface{} // 状态
|
||||
}
|
||||
|
||||
func NewNSKeyOperator() *NSKeyOperator {
|
||||
return &NSKeyOperator{}
|
||||
}
|
||||
1
internal/db/models/nameservers/ns_key_model_ext.go
Normal file
1
internal/db/models/nameservers/ns_key_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package nameservers
|
||||
@@ -383,6 +383,7 @@ func (this *NSNodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64) (*dnsconfigs.
|
||||
|
||||
config := &dnsconfigs.NSNodeConfig{
|
||||
Id: int64(node.Id),
|
||||
NodeId: node.UniqueId,
|
||||
ClusterId: int64(node.ClusterId),
|
||||
}
|
||||
|
||||
|
||||
63
internal/db/models/nameservers/ns_zone_dao.go
Normal file
63
internal/db/models/nameservers/ns_zone_dao.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
const (
|
||||
NSZoneStateEnabled = 1 // 已启用
|
||||
NSZoneStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type NSZoneDAO dbs.DAO
|
||||
|
||||
func NewNSZoneDAO() *NSZoneDAO {
|
||||
return dbs.NewDAO(&NSZoneDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNSZones",
|
||||
Model: new(NSZone),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NSZoneDAO)
|
||||
}
|
||||
|
||||
var SharedNSZoneDAO *NSZoneDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNSZoneDAO = NewNSZoneDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableNSZone 启用条目
|
||||
func (this *NSZoneDAO) EnableNSZone(tx *dbs.Tx, id uint64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSZoneStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableNSZone 禁用条目
|
||||
func (this *NSZoneDAO) DisableNSZone(tx *dbs.Tx, id uint64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSZoneStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// FindEnabledNSZone 查找启用中的条目
|
||||
func (this *NSZoneDAO) FindEnabledNSZone(tx *dbs.Tx, id uint64) (*NSZone, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", NSZoneStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*NSZone), err
|
||||
}
|
||||
6
internal/db/models/nameservers/ns_zone_dao_test.go
Normal file
6
internal/db/models/nameservers/ns_zone_dao_test.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
26
internal/db/models/nameservers/ns_zone_model.go
Normal file
26
internal/db/models/nameservers/ns_zone_model.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package nameservers
|
||||
|
||||
// NSZone 域名子域
|
||||
type NSZone struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
DomainId uint64 `field:"domainId"` // 域名ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Order uint32 `field:"order"` // 排序
|
||||
Version uint64 `field:"version"` // 版本
|
||||
Tsig string `field:"tsig"` // TSIG配置
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type NSZoneOperator struct {
|
||||
Id interface{} // ID
|
||||
DomainId interface{} // 域名ID
|
||||
IsOn interface{} // 是否启用
|
||||
Order interface{} // 排序
|
||||
Version interface{} // 版本
|
||||
Tsig interface{} // TSIG配置
|
||||
State interface{} // 状态
|
||||
}
|
||||
|
||||
func NewNSZoneOperator() *NSZoneOperator {
|
||||
return &NSZoneOperator{}
|
||||
}
|
||||
1
internal/db/models/nameservers/ns_zone_model_ext.go
Normal file
1
internal/db/models/nameservers/ns_zone_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package nameservers
|
||||
@@ -380,7 +380,7 @@ func (this *NodeClusterDAO) FindAllEnabledClustersWithDNSDomainId(tx *dbs.Tx, dn
|
||||
_, err = this.Query(tx).
|
||||
State(NodeClusterStateEnabled).
|
||||
Attr("dnsDomainId", dnsDomainId).
|
||||
Result("id", "name", "dnsName", "dnsDomainId").
|
||||
Result("id", "name", "dnsName", "dnsDomainId", "isOn").
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
@@ -391,7 +391,7 @@ func (this *NodeClusterDAO) FindAllEnabledClustersHaveDNSDomain(tx *dbs.Tx) (res
|
||||
_, err = this.Query(tx).
|
||||
State(NodeClusterStateEnabled).
|
||||
Gt("dnsDomainId", 0).
|
||||
Result("id", "name", "dnsName", "dnsDomainId").
|
||||
Result("id", "name", "dnsName", "dnsDomainId", "isOn").
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
@@ -409,7 +409,7 @@ func (this *NodeClusterDAO) FindClusterGrantId(tx *dbs.Tx, clusterId int64) (int
|
||||
func (this *NodeClusterDAO) FindClusterDNSInfo(tx *dbs.Tx, clusterId int64) (*NodeCluster, error) {
|
||||
one, err := this.Query(tx).
|
||||
Pk(clusterId).
|
||||
Result("id", "name", "dnsName", "dnsDomainId", "dns").
|
||||
Result("id", "name", "dnsName", "dnsDomainId", "dns", "isOn").
|
||||
Find()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -499,7 +499,7 @@ func (this *NodeClusterDAO) CheckClusterDNS(tx *dbs.Tx, cluster *NodeCluster) (i
|
||||
// TODO 检查域名是否已解析
|
||||
|
||||
// 检查节点
|
||||
nodes, err := SharedNodeDAO.FindAllEnabledNodesDNSWithClusterId(tx, clusterId)
|
||||
nodes, err := SharedNodeDAO.FindAllEnabledNodesDNSWithClusterId(tx, clusterId, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -837,6 +837,36 @@ func (this *NodeClusterDAO) FindLatestNodeClusters(tx *dbs.Tx, size int64) (resu
|
||||
return
|
||||
}
|
||||
|
||||
// CheckNodeClusterIsOn 获取集群是否正在启用状态
|
||||
func (this *NodeClusterDAO) CheckNodeClusterIsOn(tx *dbs.Tx, clusterId int64) (bool, error) {
|
||||
return this.Query(tx).
|
||||
Pk(clusterId).
|
||||
State(NodeClusterStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Exist()
|
||||
}
|
||||
|
||||
// FindEnabledNodeClustersWithIds 查找一组集群
|
||||
func (this *NodeClusterDAO) FindEnabledNodeClustersWithIds(tx *dbs.Tx, clusterIds []int64) (result []*NodeCluster, err error) {
|
||||
if len(clusterIds) == 0 {
|
||||
return
|
||||
}
|
||||
for _, clusterId := range clusterIds {
|
||||
cluster, err := this.Query(tx).
|
||||
Pk(clusterId).
|
||||
State(NodeClusterStateEnabled).
|
||||
Find()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cluster == nil {
|
||||
continue
|
||||
}
|
||||
result = append(result, cluster.(*NodeCluster))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *NodeClusterDAO) NotifyUpdate(tx *dbs.Tx, clusterId int64) error {
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, clusterId, NodeTaskTypeConfigChanged)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package models
|
||||
|
||||
// 节点集群
|
||||
// NodeCluster 节点集群
|
||||
type NodeCluster struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
UseAllAPINodes uint8 `field:"useAllAPINodes"` // 是否使用所有API节点
|
||||
ApiNodes string `field:"apiNodes"` // 使用的API节点
|
||||
@@ -31,6 +32,7 @@ type NodeClusterOperator struct {
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
UseAllAPINodes interface{} // 是否使用所有API节点
|
||||
ApiNodes interface{} // 使用的API节点
|
||||
|
||||
@@ -163,7 +163,7 @@ func (this *NodeDAO) CreateNode(tx *dbs.Tx, adminId int64, name string, clusterI
|
||||
}
|
||||
|
||||
// UpdateNode 修改节点
|
||||
func (this *NodeDAO) UpdateNode(tx *dbs.Tx, nodeId int64, name string, clusterId int64, groupId int64, regionId int64, maxCPU int32, isOn bool, maxCacheDiskCapacityJSON []byte, maxCacheMemoryCapacityJSON []byte) error {
|
||||
func (this *NodeDAO) UpdateNode(tx *dbs.Tx, nodeId int64, name string, clusterId int64, secondaryClusterIds []int64, groupId int64, regionId int64, maxCPU int32, isOn bool, maxCacheDiskCapacityJSON []byte, maxCacheMemoryCapacityJSON []byte) error {
|
||||
if nodeId <= 0 {
|
||||
return errors.New("invalid nodeId")
|
||||
}
|
||||
@@ -171,6 +171,24 @@ func (this *NodeDAO) UpdateNode(tx *dbs.Tx, nodeId int64, name string, clusterId
|
||||
op.Id = nodeId
|
||||
op.Name = name
|
||||
op.ClusterId = clusterId
|
||||
|
||||
// 去重
|
||||
var filteredSecondaryClusterIds = []int64{}
|
||||
for _, secondaryClusterId := range secondaryClusterIds {
|
||||
if secondaryClusterId <= 0 {
|
||||
continue
|
||||
}
|
||||
if lists.ContainsInt64(filteredSecondaryClusterIds, secondaryClusterId) {
|
||||
continue
|
||||
}
|
||||
filteredSecondaryClusterIds = append(filteredSecondaryClusterIds, secondaryClusterId)
|
||||
}
|
||||
filteredSecondaryClusterIdsJSON, err := json.Marshal(filteredSecondaryClusterIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.SecondaryClusterIds = filteredSecondaryClusterIdsJSON
|
||||
|
||||
op.GroupId = groupId
|
||||
op.RegionId = regionId
|
||||
op.LatestVersion = dbs.SQL("latestVersion+1")
|
||||
@@ -182,7 +200,7 @@ func (this *NodeDAO) UpdateNode(tx *dbs.Tx, nodeId int64, name string, clusterId
|
||||
if len(maxCacheMemoryCapacityJSON) > 0 {
|
||||
op.MaxCacheMemoryCapacity = maxCacheMemoryCapacityJSON
|
||||
}
|
||||
err := this.Save(tx, op)
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -212,6 +230,7 @@ func (this *NodeDAO) ListEnabledNodesMatch(tx *dbs.Tx,
|
||||
keyword string,
|
||||
groupId int64,
|
||||
regionId int64,
|
||||
includeSecondaryNodes bool,
|
||||
order string,
|
||||
offset int64,
|
||||
size int64) (result []*Node, err error) {
|
||||
@@ -223,7 +242,13 @@ func (this *NodeDAO) ListEnabledNodesMatch(tx *dbs.Tx,
|
||||
|
||||
// 集群
|
||||
if clusterId > 0 {
|
||||
query.Attr("clusterId", clusterId)
|
||||
if includeSecondaryNodes {
|
||||
query.Where("(clusterId=:primaryClusterId OR JSON_CONTAINS(secondaryClusterIds, :primaryClusterIdString))").
|
||||
Param("primaryClusterId", clusterId).
|
||||
Param("primaryClusterIdString", types.String(clusterId))
|
||||
} else {
|
||||
query.Attr("clusterId", clusterId)
|
||||
}
|
||||
} else {
|
||||
query.Where("clusterId IN (SELECT id FROM " + SharedNodeClusterDAO.Table + " WHERE state=1)")
|
||||
}
|
||||
@@ -327,12 +352,51 @@ func (this *NodeDAO) FindNodeClusterId(tx *dbs.Tx, nodeId int64) (int64, error)
|
||||
return types.Int64(col), err
|
||||
}
|
||||
|
||||
// FindEnabledAndOnNodeClusterIds 获取节点所属所有可用而且启用的集群ID
|
||||
func (this *NodeDAO) FindEnabledAndOnNodeClusterIds(tx *dbs.Tx, nodeId int64) (result []int64, err error) {
|
||||
one, err := this.Query(tx).
|
||||
Pk(nodeId).
|
||||
Result("clusterId", "secondaryClusterIds").
|
||||
Find()
|
||||
if one == nil {
|
||||
return nil, err
|
||||
}
|
||||
var clusterId = int64(one.(*Node).ClusterId)
|
||||
if clusterId > 0 {
|
||||
result = append(result, clusterId)
|
||||
}
|
||||
|
||||
for _, clusterId := range one.(*Node).DecodeSecondaryClusterIds() {
|
||||
if lists.ContainsInt64(result, clusterId) {
|
||||
continue
|
||||
}
|
||||
|
||||
// 检查是否启用
|
||||
isOn, err := SharedNodeClusterDAO.CheckNodeClusterIsOn(tx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !isOn {
|
||||
continue
|
||||
}
|
||||
|
||||
result = append(result, clusterId)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FindAllNodeIdsMatch 匹配节点并返回节点ID
|
||||
func (this *NodeDAO) FindAllNodeIdsMatch(tx *dbs.Tx, clusterId int64, isOn configutils.BoolState) (result []int64, err error) {
|
||||
func (this *NodeDAO) FindAllNodeIdsMatch(tx *dbs.Tx, clusterId int64, includeSecondaryNodes bool, isOn configutils.BoolState) (result []int64, err error) {
|
||||
query := this.Query(tx)
|
||||
query.State(NodeStateEnabled)
|
||||
if clusterId > 0 {
|
||||
query.Attr("clusterId", clusterId)
|
||||
if includeSecondaryNodes {
|
||||
query.Where("(clusterId=:primaryClusterId OR JSON_CONTAINS(secondaryClusterIds, :primaryClusterIdString))").
|
||||
Param("primaryClusterId", clusterId).
|
||||
Param("primaryClusterIdString", types.String(clusterId))
|
||||
} else {
|
||||
query.Attr("clusterId", clusterId)
|
||||
}
|
||||
} else {
|
||||
query.Where("clusterId IN (SELECT id FROM " + SharedNodeClusterDAO.Table + " WHERE state=1)")
|
||||
}
|
||||
@@ -385,13 +449,20 @@ func (this *NodeDAO) CountAllEnabledNodesMatch(tx *dbs.Tx,
|
||||
activeState configutils.BoolState,
|
||||
keyword string,
|
||||
groupId int64,
|
||||
regionId int64) (int64, error) {
|
||||
regionId int64,
|
||||
includeSecondaryNodes bool) (int64, error) {
|
||||
query := this.Query(tx)
|
||||
query.State(NodeStateEnabled)
|
||||
|
||||
// 集群
|
||||
if clusterId > 0 {
|
||||
query.Attr("clusterId", clusterId)
|
||||
if includeSecondaryNodes {
|
||||
query.Where("(clusterId=:primaryClusterId OR JSON_CONTAINS(secondaryClusterIds, :primaryClusterIdString))").
|
||||
Param("primaryClusterId", clusterId).
|
||||
Param("primaryClusterIdString", types.String(clusterId))
|
||||
} else {
|
||||
query.Attr("clusterId", clusterId)
|
||||
}
|
||||
} else {
|
||||
query.Where("clusterId IN (SELECT id FROM " + SharedNodeClusterDAO.Table + " WHERE state=1)")
|
||||
}
|
||||
@@ -575,11 +646,13 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64) (*nodeconfigs.N
|
||||
continue
|
||||
}
|
||||
|
||||
serverConfig := &serverconfigs.ServerConfig{}
|
||||
err = json.Unmarshal([]byte(server.Config), serverConfig)
|
||||
serverConfig, err := SharedServerDAO.ComposeServerConfig(tx, server)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if serverConfig == nil {
|
||||
continue
|
||||
}
|
||||
config.Servers = append(config.Servers, serverConfig)
|
||||
}
|
||||
|
||||
@@ -598,34 +671,37 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64) (*nodeconfigs.N
|
||||
config.GlobalConfig = globalConfig
|
||||
}
|
||||
|
||||
// WAF
|
||||
clusterId := int64(node.ClusterId)
|
||||
httpFirewallPolicyId, err := SharedNodeClusterDAO.FindClusterHTTPFirewallPolicyId(tx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if httpFirewallPolicyId > 0 {
|
||||
firewallPolicy, err := SharedHTTPFirewallPolicyDAO.ComposeFirewallPolicy(tx, httpFirewallPolicyId)
|
||||
var primaryClusterId = int64(node.ClusterId)
|
||||
var clusterIds = []int64{primaryClusterId}
|
||||
clusterIds = append(clusterIds, node.DecodeSecondaryClusterIds()...)
|
||||
for _, clusterId := range clusterIds {
|
||||
httpFirewallPolicyId, err := SharedNodeClusterDAO.FindClusterHTTPFirewallPolicyId(tx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if firewallPolicy != nil {
|
||||
config.HTTPFirewallPolicy = firewallPolicy
|
||||
if httpFirewallPolicyId > 0 {
|
||||
firewallPolicy, err := SharedHTTPFirewallPolicyDAO.ComposeFirewallPolicy(tx, httpFirewallPolicyId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if firewallPolicy != nil {
|
||||
config.HTTPFirewallPolicies = append(config.HTTPFirewallPolicies, firewallPolicy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 缓存策略
|
||||
httpCachePolicyId, err := SharedNodeClusterDAO.FindClusterHTTPCachePolicyId(tx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if httpCachePolicyId > 0 {
|
||||
cachePolicy, err := SharedHTTPCachePolicyDAO.ComposeCachePolicy(tx, httpCachePolicyId)
|
||||
// 缓存策略
|
||||
httpCachePolicyId, err := SharedNodeClusterDAO.FindClusterHTTPCachePolicyId(tx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cachePolicy != nil {
|
||||
config.HTTPCachePolicy = cachePolicy
|
||||
if httpCachePolicyId > 0 {
|
||||
cachePolicy, err := SharedHTTPCachePolicyDAO.ComposeCachePolicy(tx, httpCachePolicyId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cachePolicy != nil {
|
||||
config.HTTPCachePolicies = append(config.HTTPCachePolicies, cachePolicy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -653,14 +729,14 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64) (*nodeconfigs.N
|
||||
}
|
||||
|
||||
// TOA
|
||||
toaConfig, err := SharedNodeClusterDAO.FindClusterTOAConfig(tx, clusterId)
|
||||
toaConfig, err := SharedNodeClusterDAO.FindClusterTOAConfig(tx, primaryClusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.TOA = toaConfig
|
||||
|
||||
// 系统服务
|
||||
services, err := SharedNodeClusterDAO.FindNodeClusterSystemServices(tx, clusterId)
|
||||
services, err := SharedNodeClusterDAO.FindNodeClusterSystemServices(tx, primaryClusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -669,7 +745,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64) (*nodeconfigs.N
|
||||
}
|
||||
|
||||
// 防火墙动作
|
||||
actions, err := SharedNodeClusterFirewallActionDAO.FindAllEnabledFirewallActions(tx, clusterId)
|
||||
actions, err := SharedNodeClusterFirewallActionDAO.FindAllEnabledFirewallActions(tx, primaryClusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -878,10 +954,20 @@ func (this *NodeDAO) CountAllEnabledNodesWithRegionId(tx *dbs.Tx, regionId int64
|
||||
}
|
||||
|
||||
// FindAllEnabledNodesDNSWithClusterId 获取一个集群的节点DNS信息
|
||||
func (this *NodeDAO) FindAllEnabledNodesDNSWithClusterId(tx *dbs.Tx, clusterId int64) (result []*Node, err error) {
|
||||
_, err = this.Query(tx).
|
||||
func (this *NodeDAO) FindAllEnabledNodesDNSWithClusterId(tx *dbs.Tx, clusterId int64, includeSecondaryNodes bool) (result []*Node, err error) {
|
||||
if clusterId <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var query = this.Query(tx)
|
||||
if includeSecondaryNodes {
|
||||
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).
|
||||
Attr("isOn", true).
|
||||
Attr("isUp", true).
|
||||
Result("id", "name", "dnsRoutes", "isOn").
|
||||
@@ -911,7 +997,7 @@ func (this *NodeDAO) FindEnabledNodeDNS(tx *dbs.Tx, nodeId int64) (*Node, error)
|
||||
Pk(nodeId).
|
||||
Result("id", "name", "dnsRoutes", "clusterId", "isOn").
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
if one == nil {
|
||||
return nil, err
|
||||
}
|
||||
return one.(*Node), nil
|
||||
@@ -1108,6 +1194,89 @@ func (this *NodeDAO) FindEnabledNodesWithIds(tx *dbs.Tx, nodeIds []int64) (resul
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteNodeFromCluster 从集群中删除节点
|
||||
func (this *NodeDAO) DeleteNodeFromCluster(tx *dbs.Tx, nodeId int64, clusterId int64) error {
|
||||
one, err := this.Query(tx).
|
||||
Pk(nodeId).
|
||||
Result("clusterId", "secondaryClusterIds").
|
||||
Find()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if one == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var node = one.(*Node)
|
||||
|
||||
var secondaryClusterIds = []int64{}
|
||||
for _, secondaryClusterId := range node.DecodeSecondaryClusterIds() {
|
||||
if secondaryClusterId == clusterId {
|
||||
continue
|
||||
}
|
||||
secondaryClusterIds = append(secondaryClusterIds, secondaryClusterId)
|
||||
}
|
||||
|
||||
var newClusterId = int64(node.ClusterId)
|
||||
|
||||
if newClusterId == clusterId {
|
||||
newClusterId = 0
|
||||
|
||||
// 选择一个从集群作为主集群
|
||||
if len(secondaryClusterIds) > 0 {
|
||||
newClusterId = secondaryClusterIds[0]
|
||||
secondaryClusterIds = secondaryClusterIds[1:]
|
||||
}
|
||||
}
|
||||
|
||||
secondaryClusterIdsJSON, err := json.Marshal(secondaryClusterIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op := NewNodeOperator()
|
||||
op.Id = nodeId
|
||||
op.ClusterId = newClusterId
|
||||
op.SecondaryClusterIds = secondaryClusterIdsJSON
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// TransferPrimaryClusterNodes 自动转移集群下的节点
|
||||
func (this *NodeDAO) TransferPrimaryClusterNodes(tx *dbs.Tx, primaryClusterId int64) error {
|
||||
if primaryClusterId <= 0 {
|
||||
return nil
|
||||
}
|
||||
ones, err := this.Query(tx).
|
||||
Attr("clusterId", primaryClusterId).
|
||||
Result("id", "secondaryClusterIds").
|
||||
State(NodeStateEnabled).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, one := range ones {
|
||||
var node = one.(*Node)
|
||||
clusterIds := node.DecodeSecondaryClusterIds()
|
||||
if len(clusterIds) == 0 {
|
||||
continue
|
||||
}
|
||||
var clusterId = clusterIds[0]
|
||||
var secondaryClusterIds = clusterIds[1:]
|
||||
secondaryClusterIdsJSON, err := json.Marshal(secondaryClusterIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = this.Query(tx).
|
||||
Pk(node.Id).
|
||||
Set("clusterId", clusterId).
|
||||
Set("secondaryClusterIds", secondaryClusterIdsJSON).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *NodeDAO) NotifyUpdate(tx *dbs.Tx, nodeId int64) error {
|
||||
clusterId, err := this.FindNodeClusterId(tx, nodeId)
|
||||
@@ -1122,25 +1291,25 @@ func (this *NodeDAO) NotifyUpdate(tx *dbs.Tx, nodeId int64) error {
|
||||
|
||||
// NotifyDNSUpdate 通知DNS更新
|
||||
func (this *NodeDAO) NotifyDNSUpdate(tx *dbs.Tx, nodeId int64) error {
|
||||
clusterId, err := this.Query(tx).
|
||||
Pk(nodeId).
|
||||
Result("clusterId").
|
||||
FindInt64Col(0) // 这里不需要加服务状态条件,因为我们即使删除也要删除对应的服务的DNS解析
|
||||
clusterIds, err := this.FindEnabledAndOnNodeClusterIds(tx, nodeId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if clusterId <= 0 {
|
||||
return nil
|
||||
for _, clusterId := range clusterIds {
|
||||
dnsInfo, err := SharedNodeClusterDAO.FindClusterDNSInfo(tx, clusterId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if dnsInfo == nil {
|
||||
continue
|
||||
}
|
||||
if len(dnsInfo.DnsName) == 0 || dnsInfo.DnsDomainId <= 0 {
|
||||
continue
|
||||
}
|
||||
err = dns.SharedDNSTaskDAO.CreateNodeTask(tx, nodeId, dns.DNSTaskTypeNodeChange)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
dnsInfo, err := SharedNodeClusterDAO.FindClusterDNSInfo(tx, clusterId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if dnsInfo == nil {
|
||||
return nil
|
||||
}
|
||||
if len(dnsInfo.DnsName) == 0 || dnsInfo.DnsDomainId <= 0 {
|
||||
return nil
|
||||
}
|
||||
return dns.SharedDNSTaskDAO.CreateNodeTask(tx, nodeId, dns.DNSTaskTypeNodeChange)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
func TestNodeDAO_FindAllNodeIdsMatch(t *testing.T) {
|
||||
var tx *dbs.Tx
|
||||
nodeIds, err := SharedNodeDAO.FindAllNodeIdsMatch(tx, 1, 0)
|
||||
nodeIds, err := SharedNodeDAO.FindAllNodeIdsMatch(tx, 1, true, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -24,3 +24,13 @@ func TestNodeDAO_UpdateNodeUp(t *testing.T) {
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestNodeDAO_FindEnabledNodeClusterIds(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
var tx *dbs.Tx
|
||||
clusterIds, err := NewNodeDAO().FindEnabledAndOnNodeClusterIds(tx, 48)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(clusterIds)
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ func (this *NodeIPAddressDAO) DisableAllAddressesWithNodeId(tx *dbs.Tx, nodeId i
|
||||
}
|
||||
_, err := this.Query(tx).
|
||||
Attr("nodeId", nodeId).
|
||||
Attr("role", role).
|
||||
Set("state", NodeIPAddressStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
stringutil "github.com/iwind/TeaGo/utils/string"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"strconv"
|
||||
@@ -36,8 +37,8 @@ func init() {
|
||||
}
|
||||
|
||||
// CreateLog 创建日志
|
||||
func (this *NodeLogDAO) CreateLog(tx *dbs.Tx, nodeRole nodeconfigs.NodeRole, nodeId int64, serverId int64, level string, tag string, description string, createdAt int64) error {
|
||||
hash := stringutil.Md5(nodeRole + "@" + strconv.FormatInt(nodeId, 10) + "@" + strconv.FormatInt(serverId, 10) + "@" + level + "@" + tag + "@" + description)
|
||||
func (this *NodeLogDAO) CreateLog(tx *dbs.Tx, nodeRole nodeconfigs.NodeRole, nodeId int64, serverId int64, originId int64, level string, tag string, description string, createdAt int64) error {
|
||||
hash := stringutil.Md5(nodeRole + "@" + types.String(nodeId) + "@" + types.String(serverId) + "@" + types.String(originId) + "@" + level + "@" + tag + "@" + description)
|
||||
|
||||
// 检查是否在重复最后一条,避免重复创建
|
||||
lastLog, err := this.Query(tx).
|
||||
@@ -62,6 +63,7 @@ func (this *NodeLogDAO) CreateLog(tx *dbs.Tx, nodeRole nodeconfigs.NodeRole, nod
|
||||
op.Role = nodeRole
|
||||
op.NodeId = nodeId
|
||||
op.ServerId = serverId
|
||||
op.OriginId = originId
|
||||
op.Level = level
|
||||
op.Tag = tag
|
||||
op.Description = description
|
||||
@@ -88,7 +90,7 @@ func (this *NodeLogDAO) DeleteExpiredLogs(tx *dbs.Tx, days int) error {
|
||||
}
|
||||
|
||||
// CountNodeLogs 计算节点日志数量
|
||||
func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx, role string, nodeId int64, serverId int64, dayFrom string, dayTo string, keyword string, level string) (int64, error) {
|
||||
func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx, role string, nodeId int64, serverId int64, originId int64, dayFrom string, dayTo string, keyword string, level string) (int64, error) {
|
||||
query := this.Query(tx).
|
||||
Attr("role", role)
|
||||
if nodeId > 0 {
|
||||
@@ -104,6 +106,9 @@ func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx, role string, nodeId int64, ser
|
||||
if serverId > 0 {
|
||||
query.Attr("serverId", serverId)
|
||||
}
|
||||
if originId > 0 {
|
||||
query.Attr("originId", originId)
|
||||
}
|
||||
if len(dayFrom) > 0 {
|
||||
dayFrom = strings.ReplaceAll(dayFrom, "-", "")
|
||||
query.Gte("day", dayFrom)
|
||||
@@ -128,6 +133,7 @@ func (this *NodeLogDAO) ListNodeLogs(tx *dbs.Tx,
|
||||
role string,
|
||||
nodeId int64,
|
||||
serverId int64,
|
||||
originId int64,
|
||||
allServers bool,
|
||||
dayFrom string,
|
||||
dayTo string,
|
||||
@@ -153,6 +159,9 @@ func (this *NodeLogDAO) ListNodeLogs(tx *dbs.Tx,
|
||||
} else if allServers {
|
||||
query.Where("serverId>0")
|
||||
}
|
||||
if originId > 0 {
|
||||
query.Attr("originId", originId)
|
||||
}
|
||||
if fixedState == configutils.BoolStateYes {
|
||||
query.Attr("isFixed", 1)
|
||||
} else if fixedState == configutils.BoolStateNo {
|
||||
|
||||
@@ -11,6 +11,7 @@ type NodeLog struct {
|
||||
NodeId uint32 `field:"nodeId"` // 节点ID
|
||||
Day string `field:"day"` // 日期
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
OriginId uint32 `field:"originId"` // 源站ID
|
||||
Hash string `field:"hash"` // 信息内容Hash
|
||||
Count uint32 `field:"count"` // 重复次数
|
||||
IsFixed uint8 `field:"isFixed"` // 是否已处理
|
||||
@@ -26,6 +27,7 @@ type NodeLogOperator struct {
|
||||
NodeId interface{} // 节点ID
|
||||
Day interface{} // 日期
|
||||
ServerId interface{} // 服务ID
|
||||
OriginId interface{} // 源站ID
|
||||
Hash interface{} // 信息内容Hash
|
||||
Count interface{} // 重复次数
|
||||
IsFixed interface{} // 是否已处理
|
||||
|
||||
@@ -14,7 +14,8 @@ type Node struct {
|
||||
Secret string `field:"secret"` // 密钥
|
||||
Name string `field:"name"` // 节点名
|
||||
Code string `field:"code"` // 代号
|
||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||
ClusterId uint32 `field:"clusterId"` // 主集群ID
|
||||
SecondaryClusterIds string `field:"secondaryClusterIds"` // 从集群ID
|
||||
RegionId uint32 `field:"regionId"` // 区域ID
|
||||
GroupId uint32 `field:"groupId"` // 分组ID
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
@@ -45,7 +46,8 @@ type NodeOperator struct {
|
||||
Secret interface{} // 密钥
|
||||
Name interface{} // 节点名
|
||||
Code interface{} // 代号
|
||||
ClusterId interface{} // 集群ID
|
||||
ClusterId interface{} // 主集群ID
|
||||
SecondaryClusterIds interface{} // 从集群ID
|
||||
RegionId interface{} // 区域ID
|
||||
GroupId interface{} // 分组ID
|
||||
CreatedAt interface{} // 创建时间
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// 安装状态
|
||||
// DecodeInstallStatus 安装状态
|
||||
func (this *Node) DecodeInstallStatus() (*NodeInstallStatus, error) {
|
||||
if len(this.InstallStatus) == 0 || this.InstallStatus == "null" {
|
||||
return NewNodeInstallStatus(), nil
|
||||
@@ -27,7 +27,7 @@ func (this *Node) DecodeInstallStatus() (*NodeInstallStatus, error) {
|
||||
return status, nil
|
||||
}
|
||||
|
||||
// 节点状态
|
||||
// DecodeStatus 节点状态
|
||||
func (this *Node) DecodeStatus() (*nodeconfigs.NodeStatus, error) {
|
||||
if len(this.Status) == 0 || this.Status == "null" {
|
||||
return nil, nil
|
||||
@@ -40,20 +40,21 @@ func (this *Node) DecodeStatus() (*nodeconfigs.NodeStatus, error) {
|
||||
return status, nil
|
||||
}
|
||||
|
||||
// 所有的DNS线路
|
||||
func (this *Node) DNSRouteCodes() (map[int64][]string, error) {
|
||||
// DNSRouteCodes 所有的DNS线路
|
||||
func (this *Node) DNSRouteCodes() map[int64][]string {
|
||||
routes := map[int64][]string{} // domainId => routes
|
||||
if len(this.DnsRoutes) == 0 || this.DnsRoutes == "null" {
|
||||
return routes, nil
|
||||
return routes
|
||||
}
|
||||
err := json.Unmarshal([]byte(this.DnsRoutes), &routes)
|
||||
if err != nil {
|
||||
return map[int64][]string{}, err
|
||||
// 忽略错误
|
||||
return routes
|
||||
}
|
||||
return routes, nil
|
||||
return routes
|
||||
}
|
||||
|
||||
// DNS线路
|
||||
// DNSRouteCodesForDomainId DNS线路
|
||||
func (this *Node) DNSRouteCodesForDomainId(dnsDomainId int64) ([]string, error) {
|
||||
routes := map[int64][]string{} // domainId => routes
|
||||
if len(this.DnsRoutes) == 0 || this.DnsRoutes == "null" {
|
||||
@@ -67,7 +68,7 @@ func (this *Node) DNSRouteCodesForDomainId(dnsDomainId int64) ([]string, error)
|
||||
return domainRoutes, nil
|
||||
}
|
||||
|
||||
// 连接的API
|
||||
// DecodeConnectedAPINodeIds 连接的API
|
||||
func (this *Node) DecodeConnectedAPINodeIds() ([]int64, error) {
|
||||
apiNodeIds := []int64{}
|
||||
if IsNotNull(this.ConnectedAPINodes) {
|
||||
@@ -78,3 +79,14 @@ func (this *Node) DecodeConnectedAPINodeIds() ([]int64, error) {
|
||||
}
|
||||
return apiNodeIds, nil
|
||||
}
|
||||
|
||||
// DecodeSecondaryClusterIds 从集群IDs
|
||||
func (this *Node) DecodeSecondaryClusterIds() []int64 {
|
||||
if len(this.SecondaryClusterIds) == 0 {
|
||||
return []int64{}
|
||||
}
|
||||
var result = []int64{}
|
||||
// 不需要处理错误
|
||||
_ = json.Unmarshal([]byte(this.SecondaryClusterIds), &result)
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -39,7 +40,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 创建单个节点任务
|
||||
// CreateNodeTask 创建单个节点任务
|
||||
func (this *NodeTaskDAO) CreateNodeTask(tx *dbs.Tx, clusterId int64, nodeId int64, taskType NodeTaskType) error {
|
||||
if clusterId <= 0 || nodeId <= 0 {
|
||||
return nil
|
||||
@@ -66,7 +67,7 @@ func (this *NodeTaskDAO) CreateNodeTask(tx *dbs.Tx, clusterId int64, nodeId int6
|
||||
return err
|
||||
}
|
||||
|
||||
// 创建集群任务
|
||||
// CreateClusterTask 创建集群任务
|
||||
func (this *NodeTaskDAO) CreateClusterTask(tx *dbs.Tx, clusterId int64, taskType NodeTaskType) error {
|
||||
if clusterId <= 0 {
|
||||
return nil
|
||||
@@ -95,15 +96,16 @@ func (this *NodeTaskDAO) CreateClusterTask(tx *dbs.Tx, clusterId int64, taskType
|
||||
return err
|
||||
}
|
||||
|
||||
// 分解集群任务
|
||||
// ExtractClusterTask 分解集群任务
|
||||
func (this *NodeTaskDAO) ExtractClusterTask(tx *dbs.Tx, clusterId int64, taskType NodeTaskType) error {
|
||||
nodeIds, err := SharedNodeDAO.FindAllNodeIdsMatch(tx, clusterId, configutils.BoolStateYes)
|
||||
nodeIds, err := SharedNodeDAO.FindAllNodeIdsMatch(tx, clusterId, true, configutils.BoolStateYes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Attr("clusterId", clusterId).
|
||||
Param("clusterIdString", types.String(clusterId)).
|
||||
Where("nodeId> 0").
|
||||
Attr("type", taskType).
|
||||
Delete()
|
||||
@@ -130,7 +132,7 @@ func (this *NodeTaskDAO) ExtractClusterTask(tx *dbs.Tx, clusterId int64, taskTyp
|
||||
return nil
|
||||
}
|
||||
|
||||
// 分解所有集群任务
|
||||
// ExtractAllClusterTasks 分解所有集群任务
|
||||
func (this *NodeTaskDAO) ExtractAllClusterTasks(tx *dbs.Tx) error {
|
||||
ones, err := this.Query(tx).
|
||||
Attr("nodeId", 0).
|
||||
@@ -148,7 +150,7 @@ func (this *NodeTaskDAO) ExtractAllClusterTasks(tx *dbs.Tx) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 删除集群所有相关任务
|
||||
// DeleteAllClusterTasks 删除集群所有相关任务
|
||||
func (this *NodeTaskDAO) DeleteAllClusterTasks(tx *dbs.Tx, clusterId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Attr("clusterId", clusterId).
|
||||
@@ -156,7 +158,7 @@ func (this *NodeTaskDAO) DeleteAllClusterTasks(tx *dbs.Tx, clusterId int64) erro
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除节点相关任务
|
||||
// DeleteNodeTasks 删除节点相关任务
|
||||
func (this *NodeTaskDAO) DeleteNodeTasks(tx *dbs.Tx, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Attr("nodeId", nodeId).
|
||||
@@ -164,7 +166,7 @@ func (this *NodeTaskDAO) DeleteNodeTasks(tx *dbs.Tx, nodeId int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 查询一个节点的所有任务
|
||||
// FindDoingNodeTasks 查询一个节点的所有任务
|
||||
func (this *NodeTaskDAO) FindDoingNodeTasks(tx *dbs.Tx, nodeId int64) (result []*NodeTask, err error) {
|
||||
if nodeId <= 0 {
|
||||
return
|
||||
@@ -177,7 +179,7 @@ func (this *NodeTaskDAO) FindDoingNodeTasks(tx *dbs.Tx, nodeId int64) (result []
|
||||
return
|
||||
}
|
||||
|
||||
// 修改节点任务的完成状态
|
||||
// UpdateNodeTaskDone 修改节点任务的完成状态
|
||||
func (this *NodeTaskDAO) UpdateNodeTaskDone(tx *dbs.Tx, taskId int64, isOk bool, errorMessage string) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(taskId).
|
||||
@@ -188,7 +190,7 @@ func (this *NodeTaskDAO) UpdateNodeTaskDone(tx *dbs.Tx, taskId int64, isOk bool,
|
||||
return err
|
||||
}
|
||||
|
||||
// 查找正在更新的集群IDs
|
||||
// FindAllDoingTaskClusterIds 查找正在更新的集群IDs
|
||||
func (this *NodeTaskDAO) FindAllDoingTaskClusterIds(tx *dbs.Tx) ([]int64, error) {
|
||||
ones, _, err := this.Query(tx).
|
||||
Result("DISTINCT(clusterId) AS clusterId").
|
||||
@@ -204,7 +206,7 @@ func (this *NodeTaskDAO) FindAllDoingTaskClusterIds(tx *dbs.Tx) ([]int64, error)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// 查询某个集群下所有的任务
|
||||
// FindAllDoingNodeTasksWithClusterId 查询某个集群下所有的任务
|
||||
func (this *NodeTaskDAO) FindAllDoingNodeTasksWithClusterId(tx *dbs.Tx, clusterId int64) (result []*NodeTask, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Attr("clusterId", clusterId).
|
||||
@@ -218,7 +220,7 @@ func (this *NodeTaskDAO) FindAllDoingNodeTasksWithClusterId(tx *dbs.Tx, clusterI
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否有正在执行的任务
|
||||
// ExistsDoingNodeTasks 检查是否有正在执行的任务
|
||||
func (this *NodeTaskDAO) ExistsDoingNodeTasks(tx *dbs.Tx) (bool, error) {
|
||||
return this.Query(tx).
|
||||
Where("(isDone=0 OR (isDone=1 AND isOk=0))").
|
||||
@@ -226,14 +228,14 @@ func (this *NodeTaskDAO) ExistsDoingNodeTasks(tx *dbs.Tx) (bool, error) {
|
||||
Exist()
|
||||
}
|
||||
|
||||
// 是否有错误的任务
|
||||
// ExistsErrorNodeTasks 是否有错误的任务
|
||||
func (this *NodeTaskDAO) ExistsErrorNodeTasks(tx *dbs.Tx) (bool, error) {
|
||||
return this.Query(tx).
|
||||
Where("(isDone=1 AND isOk=0)").
|
||||
Exist()
|
||||
}
|
||||
|
||||
// 删除任务
|
||||
// DeleteNodeTask 删除任务
|
||||
func (this *NodeTaskDAO) DeleteNodeTask(tx *dbs.Tx, taskId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(taskId).
|
||||
@@ -241,7 +243,7 @@ func (this *NodeTaskDAO) DeleteNodeTask(tx *dbs.Tx, taskId int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 计算正在执行的任务
|
||||
// CountDoingNodeTasks 计算正在执行的任务
|
||||
func (this *NodeTaskDAO) CountDoingNodeTasks(tx *dbs.Tx) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Attr("isDone", 0).
|
||||
@@ -249,7 +251,7 @@ func (this *NodeTaskDAO) CountDoingNodeTasks(tx *dbs.Tx) (int64, error) {
|
||||
Count()
|
||||
}
|
||||
|
||||
// 查找需要通知的任务
|
||||
// FindNotifyingNodeTasks 查找需要通知的任务
|
||||
func (this *NodeTaskDAO) FindNotifyingNodeTasks(tx *dbs.Tx, size int64) (result []*NodeTask, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Gt("nodeId", 0).
|
||||
@@ -261,7 +263,7 @@ func (this *NodeTaskDAO) FindNotifyingNodeTasks(tx *dbs.Tx, size int64) (result
|
||||
return
|
||||
}
|
||||
|
||||
// 设置任务已通知
|
||||
// UpdateTasksNotified 设置任务已通知
|
||||
func (this *NodeTaskDAO) UpdateTasksNotified(tx *dbs.Tx, taskIds []int64) error {
|
||||
if len(taskIds) == 0 {
|
||||
return nil
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
@@ -95,10 +96,18 @@ func (this *NodeValueDAO) ListValues(tx *dbs.Tx, role string, nodeId int64, item
|
||||
func (this *NodeValueDAO) ListValuesWithClusterId(tx *dbs.Tx, role string, clusterId int64, item string, key string, timeRange nodeconfigs.NodeValueRange) (result []*NodeValue, err error) {
|
||||
query := this.Query(tx).
|
||||
Attr("role", role).
|
||||
Attr("clusterId", clusterId).
|
||||
Attr("item", item).
|
||||
Result("AVG(JSON_EXTRACT(value, '$." + key + "')) AS value, MIN(createdAt) AS createdAt")
|
||||
|
||||
switch role {
|
||||
case nodeconfigs.NodeRoleNode:
|
||||
query.Where("nodeId IN (SELECT id FROM " + SharedNodeDAO.Table + " WHERE (clusterId=:clusterId OR JSON_CONTAINS(secondaryClusterIds, :clusterIdString)) AND state=1)")
|
||||
query.Param("clusterId", clusterId).
|
||||
Param("clusterIdString", types.String(clusterId))
|
||||
default:
|
||||
query.Attr("clusterId", clusterId)
|
||||
}
|
||||
|
||||
switch timeRange {
|
||||
// TODO 支持更多的时间范围
|
||||
case nodeconfigs.NodeValueRangeMinute:
|
||||
@@ -140,7 +149,6 @@ func (this *NodeValueDAO) ListValuesForUserNodes(tx *dbs.Tx, item string, key st
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// ListValuesForNSNodes 列出用户节点相关的平均数据
|
||||
func (this *NodeValueDAO) ListValuesForNSNodes(tx *dbs.Tx, item string, key string, timeRange nodeconfigs.NodeValueRange) (result []*NodeValue, err error) {
|
||||
query := this.Query(tx).
|
||||
|
||||
@@ -14,7 +14,7 @@ func TestNodeValueDAO_CreateValue(t *testing.T) {
|
||||
m := maps.Map{
|
||||
"hello": "world12344",
|
||||
}
|
||||
err := dao.CreateValue(nil, nodeconfigs.NodeRoleNode, 1, "test", m.AsJSON(), time.Now().Unix())
|
||||
err := dao.CreateValue(nil, 1, nodeconfigs.NodeRoleNode, 1, "test", m.AsJSON(), time.Now().Unix())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -38,12 +38,12 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 初始化
|
||||
// Init 初始化
|
||||
func (this *OriginDAO) Init() {
|
||||
_ = this.DAOObject.Init()
|
||||
}
|
||||
|
||||
// 启用条目
|
||||
// EnableOrigin 启用条目
|
||||
func (this *OriginDAO) EnableOrigin(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -52,7 +52,7 @@ func (this *OriginDAO) EnableOrigin(tx *dbs.Tx, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 禁用条目
|
||||
// DisableOrigin 禁用条目
|
||||
func (this *OriginDAO) DisableOrigin(tx *dbs.Tx, originId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(originId).
|
||||
@@ -65,7 +65,7 @@ func (this *OriginDAO) DisableOrigin(tx *dbs.Tx, originId int64) error {
|
||||
return this.NotifyUpdate(tx, originId)
|
||||
}
|
||||
|
||||
// 查找启用中的条目
|
||||
// FindEnabledOrigin 查找启用中的条目
|
||||
func (this *OriginDAO) FindEnabledOrigin(tx *dbs.Tx, id int64) (*Origin, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -77,7 +77,7 @@ func (this *OriginDAO) FindEnabledOrigin(tx *dbs.Tx, id int64) (*Origin, error)
|
||||
return result.(*Origin), err
|
||||
}
|
||||
|
||||
// 根据主键查找名称
|
||||
// FindOriginName 根据主键查找名称
|
||||
func (this *OriginDAO) FindOriginName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -85,7 +85,7 @@ func (this *OriginDAO) FindOriginName(tx *dbs.Tx, id int64) (string, error) {
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// 创建源站
|
||||
// CreateOrigin 创建源站
|
||||
func (this *OriginDAO) CreateOrigin(tx *dbs.Tx, adminId int64, userId int64, name string, addrJSON string, description string, weight int32, isOn bool, connTimeout *shared.TimeDuration, readTimeout *shared.TimeDuration, idleTimeout *shared.TimeDuration, maxConns int32, maxIdleConns int32) (originId int64, err error) {
|
||||
op := NewOriginOperator()
|
||||
op.AdminId = adminId
|
||||
@@ -139,7 +139,7 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx, adminId int64, userId int64, nam
|
||||
return types.Int64(op.Id), nil
|
||||
}
|
||||
|
||||
// 修改源站
|
||||
// UpdateOrigin 修改源站
|
||||
func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx, originId int64, name string, addrJSON string, description string, weight int32, isOn bool, connTimeout *shared.TimeDuration, readTimeout *shared.TimeDuration, idleTimeout *shared.TimeDuration, maxConns int32, maxIdleConns int32) error {
|
||||
if originId <= 0 {
|
||||
return errors.New("invalid originId")
|
||||
@@ -196,7 +196,7 @@ func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx, originId int64, name string, add
|
||||
return this.NotifyUpdate(tx, originId)
|
||||
}
|
||||
|
||||
// 将源站信息转换为配置
|
||||
// ComposeOriginConfig 将源站信息转换为配置
|
||||
func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64) (*serverconfigs.OriginConfig, error) {
|
||||
origin, err := this.FindEnabledOrigin(tx, originId)
|
||||
if err != nil {
|
||||
@@ -328,7 +328,7 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64) (*serverc
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// 通知更新
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *OriginDAO) NotifyUpdate(tx *dbs.Tx, originId int64) error {
|
||||
reverseProxyId, err := SharedReverseProxyDAO.FindReverseProxyContainsOriginId(tx, originId)
|
||||
if err != nil {
|
||||
|
||||
@@ -385,5 +385,15 @@ func (this *ReverseProxyDAO) NotifyUpdate(tx *dbs.Tx, reverseProxyId int64) erro
|
||||
if serverId > 0 {
|
||||
return SharedServerDAO.NotifyUpdate(tx, serverId)
|
||||
}
|
||||
|
||||
// locations
|
||||
locationId, err := SharedHTTPLocationDAO.FindEnabledLocationIdWithReverseProxyId(tx, reverseProxyId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if locationId > 0 {
|
||||
return SharedHTTPLocationDAO.NotifyUpdate(tx, locationId)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -710,21 +710,24 @@ func (this *ServerDAO) ListEnabledServersMatch(tx *dbs.Tx, offset int64, size in
|
||||
|
||||
// FindAllEnabledServersWithNode 获取节点中的所有服务
|
||||
func (this *ServerDAO) FindAllEnabledServersWithNode(tx *dbs.Tx, nodeId int64) (result []*Server, err error) {
|
||||
// 节点所在集群
|
||||
clusterId, err := SharedNodeDAO.FindNodeClusterId(tx, nodeId)
|
||||
// 节点所在主集群
|
||||
clusterIds, err := SharedNodeDAO.FindEnabledAndOnNodeClusterIds(tx, nodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if clusterId <= 0 {
|
||||
return nil, nil
|
||||
for _, clusterId := range clusterIds {
|
||||
ones, err := this.Query(tx).
|
||||
Attr("clusterId", clusterId).
|
||||
State(ServerStateEnabled).
|
||||
AscPk().
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, one := range ones {
|
||||
result = append(result, one.(*Server))
|
||||
}
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Attr("clusterId", clusterId).
|
||||
State(ServerStateEnabled).
|
||||
AscPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -772,8 +775,8 @@ func (this *ServerDAO) FindServerNodeFilters(tx *dbs.Tx, serverId int64) (isOk b
|
||||
return true, int64(server.ClusterId), nil
|
||||
}
|
||||
|
||||
// ComposeServerConfig 构造服务的Config
|
||||
func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, serverId int64) (*serverconfigs.ServerConfig, error) {
|
||||
// ComposeServerConfigWithServerId 构造服务的Config
|
||||
func (this *ServerDAO) ComposeServerConfigWithServerId(tx *dbs.Tx, serverId int64) (*serverconfigs.ServerConfig, error) {
|
||||
server, err := this.FindEnabledServer(tx, serverId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -781,9 +784,18 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, serverId int64) (*serverc
|
||||
if server == nil {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
return this.ComposeServerConfig(tx, server)
|
||||
}
|
||||
|
||||
// ComposeServerConfig 构造服务的Config
|
||||
func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server) (*serverconfigs.ServerConfig, error) {
|
||||
if server == nil {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
config := &serverconfigs.ServerConfig{}
|
||||
config.Id = serverId
|
||||
config.Id = int64(server.Id)
|
||||
config.ClusterId = int64(server.ClusterId)
|
||||
config.Type = server.Type
|
||||
config.IsOn = server.IsOn == 1
|
||||
config.Name = server.Name
|
||||
@@ -792,7 +804,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, serverId int64) (*serverc
|
||||
// ServerNames
|
||||
if len(server.ServerNames) > 0 && server.ServerNames != "null" {
|
||||
serverNames := []*serverconfigs.ServerNameConfig{}
|
||||
err = json.Unmarshal([]byte(server.ServerNames), &serverNames)
|
||||
err := json.Unmarshal([]byte(server.ServerNames), &serverNames)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -820,7 +832,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, serverId int64) (*serverc
|
||||
// HTTP
|
||||
if len(server.Http) > 0 && server.Http != "null" {
|
||||
httpConfig := &serverconfigs.HTTPProtocolConfig{}
|
||||
err = json.Unmarshal([]byte(server.Http), httpConfig)
|
||||
err := json.Unmarshal([]byte(server.Http), httpConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -830,7 +842,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, serverId int64) (*serverc
|
||||
// HTTPS
|
||||
if len(server.Https) > 0 && server.Https != "null" {
|
||||
httpsConfig := &serverconfigs.HTTPSProtocolConfig{}
|
||||
err = json.Unmarshal([]byte(server.Https), httpsConfig)
|
||||
err := json.Unmarshal([]byte(server.Https), httpsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -852,7 +864,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, serverId int64) (*serverc
|
||||
// TCP
|
||||
if len(server.Tcp) > 0 && server.Tcp != "null" {
|
||||
tcpConfig := &serverconfigs.TCPProtocolConfig{}
|
||||
err = json.Unmarshal([]byte(server.Tcp), tcpConfig)
|
||||
err := json.Unmarshal([]byte(server.Tcp), tcpConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -862,7 +874,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, serverId int64) (*serverc
|
||||
// TLS
|
||||
if len(server.Tls) > 0 && server.Tls != "null" {
|
||||
tlsConfig := &serverconfigs.TLSProtocolConfig{}
|
||||
err = json.Unmarshal([]byte(server.Tls), tlsConfig)
|
||||
err := json.Unmarshal([]byte(server.Tls), tlsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -884,7 +896,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, serverId int64) (*serverc
|
||||
// Unix
|
||||
if len(server.Unix) > 0 && server.Unix != "null" {
|
||||
unixConfig := &serverconfigs.UnixProtocolConfig{}
|
||||
err = json.Unmarshal([]byte(server.Unix), unixConfig)
|
||||
err := json.Unmarshal([]byte(server.Unix), unixConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -894,7 +906,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, serverId int64) (*serverc
|
||||
// UDP
|
||||
if len(server.Udp) > 0 && server.Udp != "null" {
|
||||
udpConfig := &serverconfigs.UDPProtocolConfig{}
|
||||
err = json.Unmarshal([]byte(server.Udp), udpConfig)
|
||||
err := json.Unmarshal([]byte(server.Udp), udpConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -915,7 +927,7 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, serverId int64) (*serverc
|
||||
// ReverseProxy
|
||||
if IsNotNull(server.ReverseProxy) {
|
||||
reverseProxyRef := &serverconfigs.ReverseProxyRef{}
|
||||
err = json.Unmarshal([]byte(server.ReverseProxy), reverseProxyRef)
|
||||
err := json.Unmarshal([]byte(server.ReverseProxy), reverseProxyRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -930,12 +942,31 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, serverId int64) (*serverc
|
||||
}
|
||||
}
|
||||
|
||||
// WAF策略
|
||||
clusterId := int64(server.ClusterId)
|
||||
httpFirewallPolicyId, err := SharedNodeClusterDAO.FindClusterHTTPFirewallPolicyId(tx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if httpFirewallPolicyId > 0 {
|
||||
config.HTTPFirewallPolicyId = httpFirewallPolicyId
|
||||
}
|
||||
|
||||
// 缓存策略
|
||||
httpCachePolicyId, err := SharedNodeClusterDAO.FindClusterHTTPCachePolicyId(tx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if httpCachePolicyId > 0 {
|
||||
config.HTTPCachePolicyId = httpCachePolicyId
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// RenewServerConfig 更新服务的Config配置
|
||||
func (this *ServerDAO) RenewServerConfig(tx *dbs.Tx, serverId int64, updateMd5 bool) (isChanged bool, err error) {
|
||||
serverConfig, err := this.ComposeServerConfig(tx, serverId)
|
||||
serverConfig, err := this.ComposeServerConfigWithServerId(tx, serverId)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
func TestServerDAO_ComposeServerConfig(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
var tx *dbs.Tx
|
||||
config, err := SharedServerDAO.ComposeServerConfig(tx, 1)
|
||||
config, err := SharedServerDAO.ComposeServerConfigWithServerId(tx, 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -22,7 +22,7 @@ func TestServerDAO_ComposeServerConfig(t *testing.T) {
|
||||
func TestServerDAO_ComposeServerConfig_AliasServerNames(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
var tx *dbs.Tx
|
||||
config, err := SharedServerDAO.ComposeServerConfig(tx, 14)
|
||||
config, err := SharedServerDAO.ComposeServerConfigWithServerId(tx, 14)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -32,7 +32,7 @@ func TestServerDAO_ComposeServerConfig_AliasServerNames(t *testing.T) {
|
||||
func TestServerDAO_UpdateServerConfig(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
var tx *dbs.Tx
|
||||
config, err := SharedServerDAO.ComposeServerConfig(tx, 1)
|
||||
config, err := SharedServerDAO.ComposeServerConfigWithServerId(tx, 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -134,5 +134,16 @@ func TestServerDAO_ExistServerNameInCluster(t *testing.T) {
|
||||
}
|
||||
t.Log(exist)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestServerDAO_FindAllEnabledServersWithNode(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
servers, err := SharedServerDAO.FindAllEnabledServersWithNode(nil, 48)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, server := range servers {
|
||||
t.Log("serverId:", server.Id, "clusterId:", server.ClusterId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,9 +46,9 @@ func FindAllProviderTypes() []maps.Map {
|
||||
if teaconst.IsPlus {
|
||||
typeMaps = append(typeMaps, []maps.Map{
|
||||
{
|
||||
"name": "集成EdgeDNS",
|
||||
"name": "自建EdgeDNS",
|
||||
"code": ProviderTypeLocalEdgeDNS,
|
||||
"description": "当前企业版提供的DNS服务。",
|
||||
"description": "当前企业版提供的自建DNS服务。",
|
||||
},
|
||||
// TODO 需要实现用户使用AccessId/AccessKey来连接DNS服务
|
||||
/**{
|
||||
|
||||
@@ -65,7 +65,7 @@ func (this *DeployManager) FindNodeFile(os string, arch string) *DeployFile {
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadNSNodeFiles 加载所有文件
|
||||
// LoadNSNodeFiles 加载所有NS节点安装文件
|
||||
func (this *DeployManager) LoadNSNodeFiles() []*DeployFile {
|
||||
keyMap := map[string]*DeployFile{} // key => File
|
||||
|
||||
@@ -99,3 +99,13 @@ func (this *DeployManager) LoadNSNodeFiles() []*DeployFile {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// FindNSNodeFile 查找特别平台的NS节点安装文件
|
||||
func (this *DeployManager) FindNSNodeFile(os string, arch string) *DeployFile {
|
||||
for _, file := range this.LoadNSNodeFiles() {
|
||||
if file.OS == os && file.Arch == arch {
|
||||
return file
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -16,3 +16,9 @@ func TestDeployManager_LoadNSNodeFiles(t *testing.T) {
|
||||
t.Logf("%#v", file)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeployManager_FindNSNodeFile(t *testing.T) {
|
||||
file := NewDeployManager().FindNSNodeFile("linux", "amd64")
|
||||
t.Log(file)
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/accesslogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/configs"
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
@@ -16,8 +17,10 @@ import (
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
stringutil "github.com/iwind/TeaGo/utils/string"
|
||||
"github.com/iwind/gosock/pkg/gosock"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"io/ioutil"
|
||||
@@ -36,11 +39,14 @@ var sharedAPIConfig *configs.APIConfig = nil
|
||||
type APINode struct {
|
||||
serviceInstanceMap map[string]interface{}
|
||||
serviceInstanceLocker sync.Mutex
|
||||
|
||||
sock *gosock.Sock
|
||||
}
|
||||
|
||||
func NewAPINode() *APINode {
|
||||
return &APINode{
|
||||
serviceInstanceMap: map[string]interface{}{},
|
||||
sock: gosock.NewTmpSock(teaconst.ProcessName),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +111,9 @@ func (this *APINode) Start() {
|
||||
// 状态变更计时器
|
||||
go NewNodeStatusExecutor().Listen()
|
||||
|
||||
// 访问日志存储管理器
|
||||
go accesslogs.SharedStorageManager.Start()
|
||||
|
||||
// 监听RPC服务
|
||||
remotelogs.Println("API_NODE", "starting RPC server ...")
|
||||
|
||||
@@ -469,37 +478,46 @@ func (this *APINode) listenPorts(apiNode *models.APINode) (isListening bool) {
|
||||
|
||||
// 监听本地sock
|
||||
func (this *APINode) listenSock() error {
|
||||
path := os.TempDir() + "/edge-api.sock"
|
||||
|
||||
// 检查是否已经存在
|
||||
_, err := os.Stat(path)
|
||||
if err == nil {
|
||||
conn, err := net.Dial("unix", path)
|
||||
if err != nil {
|
||||
_ = os.Remove(path)
|
||||
// 检查是否在运行
|
||||
if this.sock.IsListening() {
|
||||
reply, err := this.sock.Send(&gosock.Command{Code: "pid"})
|
||||
if err == nil {
|
||||
return errors.New("error: the process is already running, pid: " + maps.NewMap(reply.Params).GetString("pid"))
|
||||
} else {
|
||||
_ = conn.Close()
|
||||
return errors.New("error: the process is already running")
|
||||
}
|
||||
}
|
||||
|
||||
// 新的监听任务
|
||||
listener, err := net.Listen("unix", path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
events.On(events.EventQuit, func() {
|
||||
remotelogs.Println("API_NODE", "quit unix sock")
|
||||
_ = listener.Close()
|
||||
})
|
||||
|
||||
// 启动监听
|
||||
go func() {
|
||||
for {
|
||||
_, err := listener.Accept()
|
||||
if err != nil {
|
||||
return
|
||||
this.sock.OnCommand(func(cmd *gosock.Command) {
|
||||
switch cmd.Code {
|
||||
case "pid":
|
||||
_ = cmd.Reply(&gosock.Command{
|
||||
Code: "pid",
|
||||
Params: map[string]interface{}{
|
||||
"pid": os.Getpid(),
|
||||
},
|
||||
})
|
||||
case "stop":
|
||||
_ = cmd.ReplyOk()
|
||||
|
||||
// 退出主进程
|
||||
events.Notify(events.EventQuit)
|
||||
os.Exit(0)
|
||||
}
|
||||
})
|
||||
|
||||
err := this.sock.Listen()
|
||||
if err != nil {
|
||||
logs.Println("API_NODE", err.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
events.On(events.EventQuit, func() {
|
||||
logs.Println("API_NODE", "quit unix sock")
|
||||
_ = this.sock.Close()
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -393,11 +393,6 @@ func (this *APINode) registerServices(server *grpc.Server) {
|
||||
pb.RegisterMonitorNodeServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.AuthorityKeyService{}).(*services.AuthorityKeyService)
|
||||
pb.RegisterAuthorityKeyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&services.AuthorityNodeService{}).(*services.AuthorityNodeService)
|
||||
pb.RegisterAuthorityNodeServiceServer(server, instance)
|
||||
@@ -443,6 +438,11 @@ func (this *APINode) registerServices(server *grpc.Server) {
|
||||
pb.RegisterNSRouteServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSKeyService{}).(*nameservers.NSKeyService)
|
||||
pb.RegisterNSKeyServiceServer(server, instance)
|
||||
this.rest(instance)
|
||||
}
|
||||
{
|
||||
instance := this.serviceInstance(&nameservers.NSAccessLogService{}).(*nameservers.NSAccessLogService)
|
||||
pb.RegisterNSAccessLogServiceServer(server, instance)
|
||||
@@ -496,6 +496,8 @@ func (this *APINode) registerServices(server *grpc.Server) {
|
||||
this.rest(instance)
|
||||
}
|
||||
|
||||
APINodeServicesRegister(this, server)
|
||||
|
||||
// TODO check service names
|
||||
for serviceName := range server.GetServiceInfo() {
|
||||
index := strings.LastIndex(serviceName, ".")
|
||||
|
||||
9
internal/nodes/api_node_services_hook.go
Normal file
9
internal/nodes/api_node_services_hook.go
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
// +build community
|
||||
|
||||
package nodes
|
||||
|
||||
import "google.golang.org/grpc"
|
||||
|
||||
func APINodeServicesRegister(node *APINode, server *grpc.Server) {
|
||||
}
|
||||
@@ -100,7 +100,7 @@ Loop:
|
||||
for {
|
||||
select {
|
||||
case log := <-logChan:
|
||||
err := models.SharedNodeLogDAO.CreateLog(nil, nodeconfigs.NodeRoleAPI, log.NodeId, 0, log.Level, log.Tag, log.Description, log.CreatedAt)
|
||||
err := models.SharedNodeLogDAO.CreateLog(nil, nodeconfigs.NodeRoleAPI, log.NodeId, log.ServerId, log.OriginId, log.Level, log.Tag, log.Description, log.CreatedAt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -108,6 +108,7 @@ func (this *NSDomainService) FindEnabledNSDomain(ctx context.Context, req *pb.Fi
|
||||
Id: int64(domain.Id),
|
||||
Name: domain.Name,
|
||||
IsOn: domain.IsOn == 1,
|
||||
TsigJSON: []byte(domain.Tsig),
|
||||
CreatedAt: int64(domain.CreatedAt),
|
||||
NsCluster: &pb.NSCluster{
|
||||
Id: int64(cluster.Id),
|
||||
@@ -179,6 +180,7 @@ func (this *NSDomainService) ListEnabledNSDomains(ctx context.Context, req *pb.L
|
||||
Name: domain.Name,
|
||||
IsOn: domain.IsOn == 1,
|
||||
CreatedAt: int64(domain.CreatedAt),
|
||||
TsigJSON: []byte(domain.Tsig),
|
||||
NsCluster: &pb.NSCluster{
|
||||
Id: int64(cluster.Id),
|
||||
IsOn: cluster.IsOn == 1,
|
||||
@@ -200,7 +202,10 @@ func (this *NSDomainService) ListNSDomainsAfterVersion(ctx context.Context, req
|
||||
|
||||
// 集群ID
|
||||
var tx = this.NullTx()
|
||||
domains, err := nameservers.SharedNSDomainDAO.ListDomainsAfterVersion(tx, req.Version, 2000)
|
||||
if req.Size <= 0 {
|
||||
req.Size = 2000
|
||||
}
|
||||
domains, err := nameservers.SharedNSDomainDAO.ListDomainsAfterVersion(tx, req.Version, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -213,9 +218,40 @@ func (this *NSDomainService) ListNSDomainsAfterVersion(ctx context.Context, req
|
||||
IsOn: domain.IsOn == 1,
|
||||
IsDeleted: domain.State == nameservers.NSDomainStateDisabled,
|
||||
Version: int64(domain.Version),
|
||||
TsigJSON: []byte(domain.Tsig),
|
||||
NsCluster: &pb.NSCluster{Id: int64(domain.ClusterId)},
|
||||
User: nil,
|
||||
})
|
||||
}
|
||||
return &pb.ListNSDomainsAfterVersionResponse{NsDomains: pbDomains}, nil
|
||||
}
|
||||
|
||||
// FindEnabledNSDomainTSIG 查找TSIG配置
|
||||
func (this *NSDomainService) FindEnabledNSDomainTSIG(ctx context.Context, req *pb.FindEnabledNSDomainTSIGRequest) (*pb.FindEnabledNSDomainTSIGResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
tsig, err := nameservers.SharedNSDomainDAO.FindEnabledDomainTSIG(tx, req.NsDomainId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.FindEnabledNSDomainTSIGResponse{TsigJSON: tsig}, nil
|
||||
}
|
||||
|
||||
// UpdateNSDomainTSIG 修改TSIG配置
|
||||
func (this *NSDomainService) UpdateNSDomainTSIG(ctx context.Context, req *pb.UpdateNSDomainTSIGRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = nameservers.SharedNSDomainDAO.UpdateDomainTSIG(tx, req.NsDomainId, req.TsigJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
170
internal/rpc/services/nameservers/service_ns_key.go
Normal file
170
internal/rpc/services/nameservers/service_ns_key.go
Normal file
@@ -0,0 +1,170 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/nameservers"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
// NSKeyService NS密钥相关服务
|
||||
type NSKeyService struct {
|
||||
services.BaseService
|
||||
}
|
||||
|
||||
// CreateNSKey 创建密钥
|
||||
func (this *NSKeyService) CreateNSKey(ctx context.Context, req *pb.CreateNSKeyRequest) (*pb.CreateNSKeyResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
keyId, err := nameservers.SharedNSKeyDAO.CreateKey(tx, req.NsDomainId, req.NsZoneId, req.Name, req.Algo, req.Secret, req.SecretType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.CreateNSKeyResponse{NsKeyId: keyId}, nil
|
||||
}
|
||||
|
||||
// UpdateNSKey 修改密钥
|
||||
func (this *NSKeyService) UpdateNSKey(ctx context.Context, req *pb.UpdateNSKeyRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var tx = this.NullTx()
|
||||
err = nameservers.SharedNSKeyDAO.UpdateKey(tx, req.NsKeyId, req.Name, req.Algo, req.Secret, req.SecretType, req.IsOn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// DeleteNSKey 删除密钥
|
||||
func (this *NSKeyService) DeleteNSKey(ctx context.Context, req *pb.DeleteNSKeyRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = nameservers.SharedNSKeyDAO.DisableNSKey(tx, req.NsKeyId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindEnabledNSKey 查找单个密钥
|
||||
func (this *NSKeyService) FindEnabledNSKey(ctx context.Context, req *pb.FindEnabledNSKeyRequest) (*pb.FindEnabledNSKeyResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
key, err := nameservers.SharedNSKeyDAO.FindEnabledNSKey(tx, req.NsKeyId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if key == nil {
|
||||
return &pb.FindEnabledNSKeyResponse{NsKey: nil}, nil
|
||||
}
|
||||
return &pb.FindEnabledNSKeyResponse{
|
||||
NsKey: &pb.NSKey{
|
||||
Id: int64(key.Id),
|
||||
IsOn: key.IsOn == 1,
|
||||
Name: key.Name,
|
||||
Algo: key.Algo,
|
||||
Secret: key.Secret,
|
||||
SecretType: key.SecretType,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CountAllEnabledNSKeys 计算密钥数量
|
||||
func (this *NSKeyService) CountAllEnabledNSKeys(ctx context.Context, req *pb.CountAllEnabledNSKeysRequest) (*pb.RPCCountResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
count, err := nameservers.SharedNSKeyDAO.CountEnabledKeys(tx, req.NsDomainId, req.NsZoneId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// ListEnabledNSKeys 列出单页密钥
|
||||
func (this *NSKeyService) ListEnabledNSKeys(ctx context.Context, req *pb.ListEnabledNSKeysRequest) (*pb.ListEnabledNSKeysResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
keys, err := nameservers.SharedNSKeyDAO.ListEnabledKeys(tx, req.NsDomainId, req.NsZoneId, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbKeys = []*pb.NSKey{}
|
||||
for _, key := range keys {
|
||||
pbKeys = append(pbKeys, &pb.NSKey{
|
||||
Id: int64(key.Id),
|
||||
IsOn: key.IsOn == 1,
|
||||
Name: key.Name,
|
||||
Algo: key.Algo,
|
||||
Secret: key.Secret,
|
||||
SecretType: key.SecretType,
|
||||
})
|
||||
}
|
||||
return &pb.ListEnabledNSKeysResponse{NsKeys: pbKeys}, nil
|
||||
}
|
||||
|
||||
// ListNSKeysAfterVersion 根据版本列出一组密钥
|
||||
func (this *NSKeyService) ListNSKeysAfterVersion(ctx context.Context, req *pb.ListNSKeysAfterVersionRequest) (*pb.ListNSKeysAfterVersionResponse, error) {
|
||||
_, err := this.ValidateNSNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
if req.Size <= 0 {
|
||||
req.Size = 2000
|
||||
}
|
||||
keys, err := nameservers.SharedNSKeyDAO.ListKeysAfterVersion(tx, req.Version, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbKeys = []*pb.NSKey{}
|
||||
for _, key := range keys {
|
||||
var pbDomain *pb.NSDomain
|
||||
var pbZone *pb.NSZone
|
||||
|
||||
if key.DomainId > 0 {
|
||||
pbDomain = &pb.NSDomain{Id: int64(key.DomainId)}
|
||||
}
|
||||
if key.ZoneId > 0 {
|
||||
pbZone = &pb.NSZone{Id: int64(key.ZoneId)}
|
||||
}
|
||||
|
||||
pbKeys = append(pbKeys, &pb.NSKey{
|
||||
Id: int64(key.Id),
|
||||
IsOn: key.IsOn == 1,
|
||||
Name: "",
|
||||
Algo: key.Algo,
|
||||
Secret: key.Secret,
|
||||
SecretType: key.SecretType,
|
||||
IsDeleted: key.State == nameservers.NSKeyStateDisabled,
|
||||
Version: int64(key.Version),
|
||||
NsDomain: pbDomain,
|
||||
NsZone: pbZone,
|
||||
})
|
||||
}
|
||||
return &pb.ListNSKeysAfterVersionResponse{NsKeys: pbKeys}, nil
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
stringutil "github.com/iwind/TeaGo/utils/string"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// NSNodeService 域名服务器节点服务
|
||||
@@ -369,7 +370,7 @@ func (this *NSNodeService) FindCurrentNSNodeConfig(ctx context.Context, req *pb.
|
||||
|
||||
// CheckNSNodeLatestVersion 检查新版本
|
||||
func (this *NSNodeService) CheckNSNodeLatestVersion(ctx context.Context, req *pb.CheckNSNodeLatestVersionRequest) (*pb.CheckNSNodeLatestVersionResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
_, _, _, err := rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAdmin, rpcutils.UserTypeDNS)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -385,3 +386,31 @@ func (this *NSNodeService) CheckNSNodeLatestVersion(ctx context.Context, req *pb
|
||||
}
|
||||
return &pb.CheckNSNodeLatestVersionResponse{HasNewVersion: false}, nil
|
||||
}
|
||||
|
||||
// DownloadNSNodeInstallationFile 下载最新DNS节点安装文件
|
||||
func (this *NSNodeService) DownloadNSNodeInstallationFile(ctx context.Context, req *pb.DownloadNSNodeInstallationFileRequest) (*pb.DownloadNSNodeInstallationFileResponse, error) {
|
||||
_, err := this.ValidateNSNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file := installers.SharedDeployManager.FindNSNodeFile(req.Os, req.Arch)
|
||||
if file == nil {
|
||||
return &pb.DownloadNSNodeInstallationFileResponse{}, nil
|
||||
}
|
||||
|
||||
sum, err := file.Sum()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, offset, err := file.Read(req.ChunkOffset)
|
||||
|
||||
return &pb.DownloadNSNodeInstallationFileResponse{
|
||||
Sum: sum,
|
||||
Offset: offset,
|
||||
ChunkData: data,
|
||||
Version: file.Version,
|
||||
Filename: filepath.Base(file.Path),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -193,7 +193,10 @@ func (this *NSRecordService) ListNSRecordsAfterVersion(ctx context.Context, req
|
||||
|
||||
// 集群ID
|
||||
var tx = this.NullTx()
|
||||
records, err := nameservers.SharedNSRecordDAO.ListRecordsAfterVersion(tx, req.Version, 2000)
|
||||
if req.Size <= 0 {
|
||||
req.Size = 2000
|
||||
}
|
||||
records, err := nameservers.SharedNSRecordDAO.ListRecordsAfterVersion(tx, req.Version, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -751,7 +751,7 @@ func (this *AdminService) findMetricDataCharts(tx *dbs.Tx) (result []*pb.MetricD
|
||||
var pbStats = []*pb.MetricStat{}
|
||||
switch chart.Type {
|
||||
case serverconfigs.MetricChartTypeTimeLine:
|
||||
itemStats, err := models.SharedMetricStatDAO.FindLatestItemStats(tx, itemId, types.Int32(item.Version), 10)
|
||||
itemStats, err := models.SharedMetricStatDAO.FindLatestItemStats(tx, itemId, chart.IgnoreEmptyKeys == 1, chart.DecodeIgnoredKeys(), types.Int32(item.Version), 10)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -780,7 +780,7 @@ func (this *AdminService) findMetricDataCharts(tx *dbs.Tx) (result []*pb.MetricD
|
||||
})
|
||||
}
|
||||
default:
|
||||
itemStats, err := models.SharedMetricStatDAO.FindItemStatsAtLastTime(tx, itemId, types.Int32(item.Version), 10)
|
||||
itemStats, err := models.SharedMetricStatDAO.FindItemStatsAtLastTime(tx, itemId, chart.IgnoreEmptyKeys == 1, chart.DecodeIgnoredKeys(), types.Int32(item.Version), 10)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
// +build plus
|
||||
|
||||
package services
|
||||
|
||||
@@ -8,6 +9,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/authority"
|
||||
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
plusutils "github.com/TeaOSLab/EdgePlus/pkg/utils"
|
||||
)
|
||||
|
||||
// AuthorityKeyService 版本认证
|
||||
@@ -44,6 +46,15 @@ func (this *AuthorityKeyService) ReadAuthorityKey(ctx context.Context, req *pb.R
|
||||
return &pb.ReadAuthorityKeyResponse{AuthorityKey: nil}, nil
|
||||
}
|
||||
|
||||
if len(key.Value) == 0 {
|
||||
return &pb.ReadAuthorityKeyResponse{AuthorityKey: nil}, nil
|
||||
}
|
||||
|
||||
m, err := plusutils.Decode([]byte(key.Value))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
macAddresses := []string{}
|
||||
if len(key.MacAddresses) > 0 {
|
||||
err = json.Unmarshal([]byte(key.MacAddresses), &macAddresses)
|
||||
@@ -54,8 +65,8 @@ func (this *AuthorityKeyService) ReadAuthorityKey(ctx context.Context, req *pb.R
|
||||
|
||||
return &pb.ReadAuthorityKeyResponse{AuthorityKey: &pb.AuthorityKey{
|
||||
Value: key.Value,
|
||||
DayFrom: key.DayFrom,
|
||||
DayTo: key.DayTo,
|
||||
DayFrom: m.GetString("dayFrom"),
|
||||
DayTo: m.GetString("dayTo"),
|
||||
Hostname: key.Hostname,
|
||||
MacAddresses: macAddresses,
|
||||
Company: key.Company,
|
||||
@@ -171,7 +171,7 @@ func (this *AuthorityNodeService) FindEnabledAuthorityNode(ctx context.Context,
|
||||
|
||||
// FindCurrentAuthorityNode 获取当前认证节点的版本
|
||||
func (this *AuthorityNodeService) FindCurrentAuthorityNode(ctx context.Context, req *pb.FindCurrentAuthorityNodeRequest) (*pb.FindCurrentAuthorityNodeResponse, error) {
|
||||
_, err := this.ValidateAuthority(ctx)
|
||||
_, err := this.ValidateAuthorityNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -78,20 +78,26 @@ func (this *BaseService) ValidateNode(ctx context.Context) (nodeId int64, err er
|
||||
return
|
||||
}
|
||||
|
||||
// ValidateUser 校验用户节点
|
||||
func (this *BaseService) ValidateUser(ctx context.Context) (userId int64, err error) {
|
||||
// ValidateNSNode 校验DNS节点
|
||||
func (this *BaseService) ValidateNSNode(ctx context.Context) (nodeId int64, err error) {
|
||||
_, _, nodeId, err = rpcutils.ValidateRequest(ctx, rpcutils.UserTypeDNS)
|
||||
return
|
||||
}
|
||||
|
||||
// ValidateUserNode 校验用户节点
|
||||
func (this *BaseService) ValidateUserNode(ctx context.Context) (userId int64, err error) {
|
||||
_, _, userId, err = rpcutils.ValidateRequest(ctx, rpcutils.UserTypeUser)
|
||||
return
|
||||
}
|
||||
|
||||
// ValidateMonitor 校验监控节点
|
||||
func (this *BaseService) ValidateMonitor(ctx context.Context) (nodeId int64, err error) {
|
||||
// ValidateMonitorNode 校验监控节点
|
||||
func (this *BaseService) ValidateMonitorNode(ctx context.Context) (nodeId int64, err error) {
|
||||
_, _, nodeId, err = rpcutils.ValidateRequest(ctx, rpcutils.UserTypeMonitor)
|
||||
return
|
||||
}
|
||||
|
||||
// ValidateAuthority 校验认证节点
|
||||
func (this *BaseService) ValidateAuthority(ctx context.Context) (nodeId int64, err error) {
|
||||
// ValidateAuthorityNode 校验认证节点
|
||||
func (this *BaseService) ValidateAuthorityNode(ctx context.Context) (nodeId int64, err error) {
|
||||
_, _, nodeId, err = rpcutils.ValidateRequest(ctx, rpcutils.UserTypeAuthority)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -396,7 +396,7 @@ func (this *DNSDomainService) findClusterDNSChanges(cluster *models.NodeCluster,
|
||||
tx := this.NullTx()
|
||||
|
||||
// 节点域名
|
||||
nodes, err := models.SharedNodeDAO.FindAllEnabledNodesDNSWithClusterId(tx, clusterId)
|
||||
nodes, err := models.SharedNodeDAO.FindAllEnabledNodesDNSWithClusterId(tx, clusterId, true)
|
||||
if err != nil {
|
||||
return nil, nil, nil, 0, 0, false, false, err
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/accesslogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
@@ -31,6 +32,18 @@ func (this *HTTPAccessLogService) CreateHTTPAccessLogs(ctx context.Context, req
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 发送到访问日志策略
|
||||
policyId, err := models.SharedHTTPAccessLogPolicyDAO.FindCurrentPublicPolicyId(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if policyId > 0 {
|
||||
err = accesslogs.SharedStorageManager.Write(policyId, req.HttpAccessLogs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.CreateHTTPAccessLogsResponse{}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/accesslogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
@@ -10,32 +11,149 @@ type HTTPAccessLogPolicyService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// FindAllEnabledHTTPAccessLogPolicies 获取所有可用策略
|
||||
func (this *HTTPAccessLogPolicyService) FindAllEnabledHTTPAccessLogPolicies(ctx context.Context, req *pb.FindAllEnabledHTTPAccessLogPoliciesRequest) (*pb.FindAllEnabledHTTPAccessLogPoliciesResponse, error) {
|
||||
// 校验请求
|
||||
// CountAllEnabledHTTPAccessLogPolicies 计算访问日志策略数量
|
||||
func (this *HTTPAccessLogPolicyService) CountAllEnabledHTTPAccessLogPolicies(ctx context.Context, req *pb.CountAllEnabledHTTPAccessLogPoliciesRequest) (*pb.RPCCountResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
var tx = this.NullTx()
|
||||
count, err := models.SharedHTTPAccessLogPolicyDAO.CountAllEnabledPolicies(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
policies, err := models.SharedHTTPAccessLogPolicyDAO.FindAllEnabledAccessLogPolicies(tx)
|
||||
// ListEnabledHTTPAccessLogPolicies 列出单页访问日志策略
|
||||
func (this *HTTPAccessLogPolicyService) ListEnabledHTTPAccessLogPolicies(ctx context.Context, req *pb.ListEnabledHTTPAccessLogPoliciesRequest) (*pb.ListEnabledHTTPAccessLogPoliciesResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := []*pb.HTTPAccessLogPolicy{}
|
||||
var tx = this.NullTx()
|
||||
policies, err := models.SharedHTTPAccessLogPolicyDAO.ListEnabledPolicies(tx, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbPolicies = []*pb.HTTPAccessLogPolicy{}
|
||||
for _, policy := range policies {
|
||||
result = append(result, &pb.HTTPAccessLogPolicy{
|
||||
pbPolicies = append(pbPolicies, &pb.HTTPAccessLogPolicy{
|
||||
Id: int64(policy.Id),
|
||||
Name: policy.Name,
|
||||
IsOn: policy.IsOn == 1,
|
||||
Type: policy.Name,
|
||||
Type: policy.Type,
|
||||
OptionsJSON: []byte(policy.Options),
|
||||
CondsJSON: []byte(policy.Conds),
|
||||
IsPublic: policy.IsPublic == 1,
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.FindAllEnabledHTTPAccessLogPoliciesResponse{AccessLogPolicies: result}, nil
|
||||
return &pb.ListEnabledHTTPAccessLogPoliciesResponse{HttpAccessLogPolicies: pbPolicies}, nil
|
||||
}
|
||||
|
||||
// CreateHTTPAccessLogPolicy 创建访问日志策略
|
||||
func (this *HTTPAccessLogPolicyService) CreateHTTPAccessLogPolicy(ctx context.Context, req *pb.CreateHTTPAccessLogPolicyRequest) (*pb.CreateHTTPAccessLogPolicyResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 取消别的Public
|
||||
if req.IsPublic {
|
||||
err = models.SharedHTTPAccessLogPolicyDAO.CancelAllPublicPolicies(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 创建
|
||||
policyId, err := models.SharedHTTPAccessLogPolicyDAO.CreatePolicy(tx, req.Name, req.Type, req.OptionsJSON, req.CondsJSON, req.IsPublic)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.CreateHTTPAccessLogPolicyResponse{HttpAccessLogPolicyId: policyId}, nil
|
||||
}
|
||||
|
||||
// UpdateHTTPAccessLogPolicy 修改访问日志策略
|
||||
func (this *HTTPAccessLogPolicyService) UpdateHTTPAccessLogPolicy(ctx context.Context, req *pb.UpdateHTTPAccessLogPolicyRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 取消别的Public
|
||||
if req.IsPublic {
|
||||
err = models.SharedHTTPAccessLogPolicyDAO.CancelAllPublicPolicies(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 保存修改
|
||||
err = models.SharedHTTPAccessLogPolicyDAO.UpdatePolicy(tx, req.HttpAccessLogPolicyId, req.Name, req.OptionsJSON, req.CondsJSON, req.IsPublic, req.IsOn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindEnabledHTTPAccessLogPolicy 查找单个访问日志策略
|
||||
func (this *HTTPAccessLogPolicyService) FindEnabledHTTPAccessLogPolicy(ctx context.Context, req *pb.FindEnabledHTTPAccessLogPolicyRequest) (*pb.FindEnabledHTTPAccessLogPolicyResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
policy, err := models.SharedHTTPAccessLogPolicyDAO.FindEnabledHTTPAccessLogPolicy(tx, req.HttpAccessLogPolicyId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if policy == nil {
|
||||
return &pb.FindEnabledHTTPAccessLogPolicyResponse{HttpAccessLogPolicy: nil}, nil
|
||||
}
|
||||
return &pb.FindEnabledHTTPAccessLogPolicyResponse{HttpAccessLogPolicy: &pb.HTTPAccessLogPolicy{
|
||||
Id: int64(policy.Id),
|
||||
Name: policy.Name,
|
||||
IsOn: policy.IsOn == 1,
|
||||
Type: policy.Type,
|
||||
OptionsJSON: []byte(policy.Options),
|
||||
CondsJSON: []byte(policy.Conds),
|
||||
IsPublic: policy.IsPublic == 1,
|
||||
}}, nil
|
||||
}
|
||||
|
||||
// DeleteHTTPAccessLogPolicy 删除访问日志策略
|
||||
func (this *HTTPAccessLogPolicyService) DeleteHTTPAccessLogPolicy(ctx context.Context, req *pb.DeleteHTTPAccessLogPolicyRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = models.SharedHTTPAccessLogPolicyDAO.DisableHTTPAccessLogPolicy(tx, req.HttpAccessLogPolicyId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// WriteHTTPAccessLogPolicy 测试写入某个访问日志策略
|
||||
func (this *HTTPAccessLogPolicyService) WriteHTTPAccessLogPolicy(ctx context.Context, req *pb.WriteHTTPAccessLogPolicyRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = accesslogs.SharedStorageManager.Write(req.HttpAccessLogPolicyId, []*pb.HTTPAccessLog{req.HttpAccessLog})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@ import (
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// 消息媒介服务
|
||||
// MessageMediaService 消息媒介服务
|
||||
type MessageMediaService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// 获取所有支持的媒介
|
||||
// FindAllMessageMedias 获取所有支持的媒介
|
||||
func (this *MessageMediaService) FindAllMessageMedias(ctx context.Context, req *pb.FindAllMessageMediasRequest) (*pb.FindAllMessageMediasResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
@@ -37,9 +37,9 @@ func (this *MessageMediaService) FindAllMessageMedias(ctx context.Context, req *
|
||||
return &pb.FindAllMessageMediasResponse{MessageMedias: pbMedias}, nil
|
||||
}
|
||||
|
||||
// 设置所有支持的媒介
|
||||
// UpdateMessageMedias 设置所有支持的媒介
|
||||
func (this *MessageMediaService) UpdateMessageMedias(ctx context.Context, req *pb.UpdateMessageMediasRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateMonitor(ctx)
|
||||
_, err := this.ValidateMonitorNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ func (this *MessageTaskService) CreateMessageTask(ctx context.Context, req *pb.C
|
||||
|
||||
// FindSendingMessageTasks 查找要发送的任务
|
||||
func (this *MessageTaskService) FindSendingMessageTasks(ctx context.Context, req *pb.FindSendingMessageTasksRequest) (*pb.FindSendingMessageTasksResponse, error) {
|
||||
_, err := this.ValidateMonitor(ctx)
|
||||
_, err := this.ValidateMonitorNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -128,7 +128,7 @@ func (this *MessageTaskService) FindSendingMessageTasks(ctx context.Context, req
|
||||
|
||||
// UpdateMessageTaskStatus 修改任务状态
|
||||
func (this *MessageTaskService) UpdateMessageTaskStatus(ctx context.Context, req *pb.UpdateMessageTaskStatusRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateMonitor(ctx)
|
||||
_, err := this.ValidateMonitorNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ func (this *MetricChartService) CreateMetricChart(ctx context.Context, req *pb.C
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
chartId, err := models.SharedMetricChartDAO.CreateChart(tx, req.MetricItemId, req.Name, req.Type, req.WidthDiv, req.MaxItems, params)
|
||||
chartId, err := models.SharedMetricChartDAO.CreateChart(tx, req.MetricItemId, req.Name, req.Type, req.WidthDiv, req.MaxItems, params, req.IgnoreEmptyKeys, req.IgnoredKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -53,7 +53,7 @@ func (this *MetricChartService) UpdateMetricChart(ctx context.Context, req *pb.U
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
err = models.SharedMetricChartDAO.UpdateChart(tx, req.MetricChartId, req.Name, req.Type, req.WidthDiv, req.MaxItems, params, req.IsOn)
|
||||
err = models.SharedMetricChartDAO.UpdateChart(tx, req.MetricChartId, req.Name, req.Type, req.WidthDiv, req.MaxItems, params, req.IgnoreEmptyKeys, req.IgnoredKeys, req.IsOn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -77,14 +77,16 @@ func (this *MetricChartService) FindEnabledMetricChart(ctx context.Context, req
|
||||
}
|
||||
return &pb.FindEnabledMetricChartResponse{
|
||||
MetricChart: &pb.MetricChart{
|
||||
Id: int64(chart.Id),
|
||||
Name: chart.Name,
|
||||
Type: chart.Type,
|
||||
WidthDiv: types.Int32(chart.WidthDiv),
|
||||
MaxItems: types.Int32(chart.MaxItems),
|
||||
ParamsJSON: []byte(chart.Params),
|
||||
IsOn: chart.IsOn == 1,
|
||||
MetricItem: &pb.MetricItem{Id: int64(chart.ItemId)},
|
||||
Id: int64(chart.Id),
|
||||
Name: chart.Name,
|
||||
Type: chart.Type,
|
||||
WidthDiv: types.Int32(chart.WidthDiv),
|
||||
MaxItems: types.Int32(chart.MaxItems),
|
||||
ParamsJSON: []byte(chart.Params),
|
||||
IgnoreEmptyKeys: chart.IgnoreEmptyKeys == 1,
|
||||
IgnoredKeys: chart.DecodeIgnoredKeys(),
|
||||
IsOn: chart.IsOn == 1,
|
||||
MetricItem: &pb.MetricItem{Id: int64(chart.ItemId)},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -119,13 +121,15 @@ func (this *MetricChartService) ListEnabledMetricCharts(ctx context.Context, req
|
||||
var pbCharts []*pb.MetricChart
|
||||
for _, chart := range charts {
|
||||
pbCharts = append(pbCharts, &pb.MetricChart{
|
||||
Id: int64(chart.Id),
|
||||
Name: chart.Name,
|
||||
Type: chart.Type,
|
||||
WidthDiv: types.Int32(chart.WidthDiv),
|
||||
MaxItems: types.Int32(chart.MaxItems),
|
||||
ParamsJSON: []byte(chart.Params),
|
||||
IsOn: chart.IsOn == 1,
|
||||
Id: int64(chart.Id),
|
||||
Name: chart.Name,
|
||||
Type: chart.Type,
|
||||
WidthDiv: types.Int32(chart.WidthDiv),
|
||||
MaxItems: types.Int32(chart.MaxItems),
|
||||
ParamsJSON: []byte(chart.Params),
|
||||
IgnoreEmptyKeys: chart.IgnoreEmptyKeys == 1,
|
||||
IgnoredKeys: chart.DecodeIgnoredKeys(),
|
||||
IsOn: chart.IsOn == 1,
|
||||
})
|
||||
}
|
||||
return &pb.ListEnabledMetricChartsResponse{MetricCharts: pbCharts}, nil
|
||||
|
||||
@@ -22,7 +22,13 @@ func (this *MetricStatService) UploadMetricStats(ctx context.Context, req *pb.Up
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
clusterId, err := models.SharedNodeDAO.FindNodeClusterId(tx, nodeId)
|
||||
clusterId, err := models.SharedServerDAO.FindServerClusterId(tx, req.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 删除旧的数据
|
||||
err = models.SharedMetricStatDAO.DeleteNodeItemStats(tx, nodeId, req.ServerId, req.ItemId, req.Time)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ func (this *MonitorNodeService) FindEnabledMonitorNode(ctx context.Context, req
|
||||
|
||||
// FindCurrentMonitorNode 获取当前监控节点的版本
|
||||
func (this *MonitorNodeService) FindCurrentMonitorNode(ctx context.Context, req *pb.FindCurrentMonitorNodeRequest) (*pb.FindCurrentMonitorNodeResponse, error) {
|
||||
_, err := this.ValidateMonitor(ctx)
|
||||
_, err := this.ValidateMonitorNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
stringutil "github.com/iwind/TeaGo/utils/string"
|
||||
"net"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// NodeService 边缘节点相关服务
|
||||
@@ -49,10 +50,23 @@ func (this *NodeService) CreateNode(ctx context.Context, req *pb.CreateNodeReque
|
||||
}
|
||||
|
||||
// 保存DNS相关
|
||||
if req.DnsDomainId > 0 && len(req.DnsRoutes) > 0 {
|
||||
err = models.SharedNodeDAO.UpdateNodeDNS(tx, nodeId, map[int64][]string{
|
||||
req.DnsDomainId: req.DnsRoutes,
|
||||
})
|
||||
if len(req.DnsRoutes) > 0 {
|
||||
var routesMap = map[int64][]string{}
|
||||
var m = map[int64][]string{} // domainId => codes
|
||||
for _, route := range req.DnsRoutes {
|
||||
var pieces = strings.SplitN(route, "@", 2)
|
||||
if len(pieces) != 2 {
|
||||
continue
|
||||
}
|
||||
var code = pieces[0]
|
||||
var domainId = types.Int64(pieces[1])
|
||||
m[domainId] = append(m[domainId], code)
|
||||
}
|
||||
for domainId, codes := range m {
|
||||
routesMap[domainId] = codes
|
||||
}
|
||||
|
||||
err = models.SharedNodeDAO.UpdateNodeDNS(tx, nodeId, routesMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -135,7 +149,7 @@ func (this *NodeService) CountAllEnabledNodesMatch(ctx context.Context, req *pb.
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
count, err := models.SharedNodeDAO.CountAllEnabledNodesMatch(tx, req.NodeClusterId, configutils.ToBoolState(req.InstallState), configutils.ToBoolState(req.ActiveState), req.Keyword, req.NodeGroupId, req.NodeRegionId)
|
||||
count, err := models.SharedNodeDAO.CountAllEnabledNodesMatch(tx, req.NodeClusterId, configutils.ToBoolState(req.InstallState), configutils.ToBoolState(req.ActiveState), req.Keyword, req.NodeGroupId, req.NodeRegionId, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -188,18 +202,32 @@ func (this *NodeService) ListEnabledNodesMatch(ctx context.Context, req *pb.List
|
||||
order = "trafficOutDesc"
|
||||
}
|
||||
|
||||
nodes, err := models.SharedNodeDAO.ListEnabledNodesMatch(tx, req.NodeClusterId, configutils.ToBoolState(req.InstallState), configutils.ToBoolState(req.ActiveState), req.Keyword, req.NodeGroupId, req.NodeRegionId, order, req.Offset, req.Size)
|
||||
nodes, err := models.SharedNodeDAO.ListEnabledNodesMatch(tx, req.NodeClusterId, configutils.ToBoolState(req.InstallState), configutils.ToBoolState(req.ActiveState), req.Keyword, req.NodeGroupId, req.NodeRegionId, true, order, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := []*pb.Node{}
|
||||
for _, node := range nodes {
|
||||
// 集群信息
|
||||
// 主集群信息
|
||||
clusterName, err := models.SharedNodeClusterDAO.FindNodeClusterName(tx, int64(node.ClusterId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 从集群
|
||||
secondaryClusters, err := models.SharedNodeClusterDAO.FindEnabledNodeClustersWithIds(tx, node.DecodeSecondaryClusterIds())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbSecondaryClusters = []*pb.NodeCluster{}
|
||||
for _, secondaryCluster := range secondaryClusters {
|
||||
pbSecondaryClusters = append(pbSecondaryClusters, &pb.NodeCluster{
|
||||
Id: int64(secondaryCluster.Id),
|
||||
IsOn: secondaryCluster.IsOn == 1,
|
||||
Name: secondaryCluster.Name,
|
||||
})
|
||||
}
|
||||
|
||||
// 安装信息
|
||||
installStatus, err := node.DecodeInstallStatus()
|
||||
if err != nil {
|
||||
@@ -276,13 +304,14 @@ func (this *NodeService) ListEnabledNodesMatch(ctx context.Context, req *pb.List
|
||||
Id: int64(node.ClusterId),
|
||||
Name: clusterName,
|
||||
},
|
||||
InstallStatus: installStatusResult,
|
||||
MaxCPU: types.Int32(node.MaxCPU),
|
||||
IsOn: node.IsOn == 1,
|
||||
IsUp: node.IsUp == 1,
|
||||
NodeGroup: pbGroup,
|
||||
NodeRegion: pbRegion,
|
||||
DnsRoutes: pbRoutes,
|
||||
SecondaryNodeClusters: pbSecondaryClusters,
|
||||
InstallStatus: installStatusResult,
|
||||
MaxCPU: types.Int32(node.MaxCPU),
|
||||
IsOn: node.IsOn == 1,
|
||||
IsUp: node.IsUp == 1,
|
||||
NodeGroup: pbGroup,
|
||||
NodeRegion: pbRegion,
|
||||
DnsRoutes: pbRoutes,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -354,6 +383,22 @@ func (this *NodeService) DeleteNode(ctx context.Context, req *pb.DeleteNodeReque
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// DeleteNodeFromNodeCluster 从集群中删除节点
|
||||
func (this *NodeService) DeleteNodeFromNodeCluster(ctx context.Context, req *pb.DeleteNodeFromNodeClusterRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
err = models.SharedNodeDAO.DeleteNodeFromCluster(tx, req.NodeId, req.NodeClusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// UpdateNode 修改节点
|
||||
func (this *NodeService) UpdateNode(ctx context.Context, req *pb.UpdateNodeRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx, 0)
|
||||
@@ -385,7 +430,7 @@ func (this *NodeService) UpdateNode(ctx context.Context, req *pb.UpdateNodeReque
|
||||
}
|
||||
}
|
||||
|
||||
err = models.SharedNodeDAO.UpdateNode(tx, req.NodeId, req.Name, req.NodeClusterId, req.NodeGroupId, req.NodeRegionId, req.MaxCPU, req.IsOn, maxCacheDiskCapacityJSON, maxCacheMemoryCapacityJSON)
|
||||
err = models.SharedNodeDAO.UpdateNode(tx, req.NodeId, req.Name, req.NodeClusterId, req.SecondaryNodeClusterIds, req.NodeGroupId, req.NodeRegionId, req.MaxCPU, req.IsOn, maxCacheDiskCapacityJSON, maxCacheMemoryCapacityJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -410,10 +455,26 @@ func (this *NodeService) UpdateNode(ctx context.Context, req *pb.UpdateNodeReque
|
||||
}
|
||||
|
||||
// 保存DNS相关
|
||||
if req.DnsDomainId > 0 && len(req.DnsRoutes) > 0 {
|
||||
err = models.SharedNodeDAO.UpdateNodeDNS(tx, req.NodeId, map[int64][]string{
|
||||
req.DnsDomainId: req.DnsRoutes,
|
||||
})
|
||||
nodeDNS, err := models.SharedNodeDAO.FindEnabledNodeDNS(tx, req.NodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if nodeDNS != nil {
|
||||
var routesMap = nodeDNS.DNSRouteCodes()
|
||||
var m = map[int64][]string{} // domainId => codes
|
||||
for _, route := range req.DnsRoutes {
|
||||
var pieces = strings.SplitN(route, "@", 2)
|
||||
if len(pieces) != 2 {
|
||||
continue
|
||||
}
|
||||
var code = pieces[0]
|
||||
var domainId = types.Int64(pieces[1])
|
||||
m[domainId] = append(m[domainId], code)
|
||||
}
|
||||
for domainId, codes := range m {
|
||||
routesMap[domainId] = codes
|
||||
}
|
||||
err = models.SharedNodeDAO.UpdateNodeDNS(tx, req.NodeId, routesMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -439,12 +500,29 @@ func (this *NodeService) FindEnabledNode(ctx context.Context, req *pb.FindEnable
|
||||
return &pb.FindEnabledNodeResponse{Node: nil}, nil
|
||||
}
|
||||
|
||||
// 集群信息
|
||||
// 主集群信息
|
||||
clusterName, err := models.SharedNodeClusterDAO.FindNodeClusterName(tx, int64(node.ClusterId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 从集群信息
|
||||
var secondaryPBClusters []*pb.NodeCluster
|
||||
for _, secondaryClusterId := range node.DecodeSecondaryClusterIds() {
|
||||
cluster, err := models.SharedNodeClusterDAO.FindEnabledNodeCluster(tx, secondaryClusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cluster == nil {
|
||||
continue
|
||||
}
|
||||
secondaryPBClusters = append(secondaryPBClusters, &pb.NodeCluster{
|
||||
Id: int64(cluster.Id),
|
||||
IsOn: cluster.IsOn == 1,
|
||||
Name: cluster.Name,
|
||||
})
|
||||
}
|
||||
|
||||
// 认证信息
|
||||
login, err := models.SharedNodeLoginDAO.FindEnabledNodeLoginWithNodeId(tx, req.NodeId)
|
||||
if err != nil {
|
||||
@@ -542,6 +620,7 @@ func (this *NodeService) FindEnabledNode(ctx context.Context, req *pb.FindEnable
|
||||
Id: int64(node.ClusterId),
|
||||
Name: clusterName,
|
||||
},
|
||||
SecondaryNodeClusters: secondaryPBClusters,
|
||||
Login: respLogin,
|
||||
InstallStatus: installStatusResult,
|
||||
MaxCPU: types.Int32(node.MaxCPU),
|
||||
@@ -1117,7 +1196,7 @@ func (this *NodeService) FindAllEnabledNodesDNSWithNodeClusterId(ctx context.Con
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodes, err := models.SharedNodeDAO.FindAllEnabledNodesDNSWithClusterId(tx, req.NodeClusterId)
|
||||
nodes, err := models.SharedNodeDAO.FindAllEnabledNodesDNSWithClusterId(tx, req.NodeClusterId, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1155,10 +1234,11 @@ func (this *NodeService) FindAllEnabledNodesDNSWithNodeClusterId(ctx context.Con
|
||||
continue
|
||||
}
|
||||
result = append(result, &pb.NodeDNSInfo{
|
||||
Id: int64(node.Id),
|
||||
Name: node.Name,
|
||||
IpAddr: ip,
|
||||
Routes: pbRoutes,
|
||||
Id: int64(node.Id),
|
||||
Name: node.Name,
|
||||
IpAddr: ip,
|
||||
Routes: pbRoutes,
|
||||
NodeClusterId: req.NodeClusterId,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1189,7 +1269,11 @@ func (this *NodeService) FindEnabledNodeDNS(ctx context.Context, req *pb.FindEna
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clusterId := int64(node.ClusterId)
|
||||
var clusterId = int64(node.ClusterId)
|
||||
if req.NodeClusterId > 0 {
|
||||
clusterId = req.NodeClusterId
|
||||
}
|
||||
|
||||
clusterDNS, err := models.SharedNodeClusterDAO.FindClusterDNSInfo(tx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1256,14 +1340,26 @@ func (this *NodeService) UpdateNodeDNS(ctx context.Context, req *pb.UpdateNodeDN
|
||||
return nil, errors.New("node not found")
|
||||
}
|
||||
|
||||
routeCodeMap, err := node.DNSRouteCodes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
routeCodeMap := node.DNSRouteCodes()
|
||||
if req.DnsDomainId > 0 && len(req.Routes) > 0 {
|
||||
routeCodeMap[req.DnsDomainId] = req.Routes
|
||||
var m = map[int64][]string{} // domainId => codes
|
||||
for _, route := range req.Routes {
|
||||
var pieces = strings.SplitN(route, "@", 2)
|
||||
if len(pieces) != 2 {
|
||||
continue
|
||||
}
|
||||
var code = pieces[0]
|
||||
var domainId = types.Int64(pieces[1])
|
||||
m[domainId] = append(m[domainId], code)
|
||||
}
|
||||
for domainId, codes := range m {
|
||||
routeCodeMap[domainId] = codes
|
||||
}
|
||||
} else {
|
||||
delete(routeCodeMap, req.DnsDomainId)
|
||||
}
|
||||
|
||||
|
||||
err = models.SharedNodeDAO.UpdateNodeDNS(tx, req.NodeId, routeCodeMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -78,8 +78,19 @@ func (this *NodeClusterService) DeleteNodeCluster(ctx context.Context, req *pb.D
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.NodeClusterId <= 0 {
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
// 转移节点
|
||||
err = models.SharedNodeDAO.TransferPrimaryClusterNodes(tx, req.NodeClusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 删除集群
|
||||
err = models.SharedNodeClusterDAO.DisableNodeCluster(tx, req.NodeClusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -128,6 +139,7 @@ func (this *NodeClusterService) FindEnabledNodeCluster(ctx context.Context, req
|
||||
HttpFirewallPolicyId: int64(cluster.HttpFirewallPolicyId),
|
||||
DnsName: cluster.DnsName,
|
||||
DnsDomainId: int64(cluster.DnsDomainId),
|
||||
IsOn: cluster.IsOn == 1,
|
||||
}}, nil
|
||||
}
|
||||
|
||||
@@ -208,6 +220,7 @@ func (this *NodeClusterService) FindAllEnabledNodeClusters(ctx context.Context,
|
||||
CreatedAt: int64(cluster.CreatedAt),
|
||||
UniqueId: cluster.UniqueId,
|
||||
Secret: cluster.Secret,
|
||||
IsOn: cluster.IsOn == 1,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -259,6 +272,7 @@ func (this *NodeClusterService) ListEnabledNodeClusters(ctx context.Context, req
|
||||
Secret: cluster.Secret,
|
||||
DnsName: cluster.DnsName,
|
||||
DnsDomainId: int64(cluster.DnsDomainId),
|
||||
IsOn: cluster.IsOn == 1,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -372,6 +386,7 @@ func (this *NodeClusterService) FindAllEnabledNodeClustersWithNodeGrantId(ctx co
|
||||
CreatedAt: int64(cluster.CreatedAt),
|
||||
UniqueId: cluster.UniqueId,
|
||||
Secret: cluster.Secret,
|
||||
IsOn: cluster.IsOn == 1,
|
||||
})
|
||||
}
|
||||
return &pb.FindAllEnabledNodeClustersWithNodeGrantIdResponse{NodeClusters: result}, nil
|
||||
@@ -511,6 +526,7 @@ func (this *NodeClusterService) FindAllEnabledNodeClustersWithDNSDomainId(ctx co
|
||||
Name: cluster.Name,
|
||||
DnsName: cluster.DnsName,
|
||||
DnsDomainId: int64(cluster.DnsDomainId),
|
||||
IsOn: cluster.IsOn == 1,
|
||||
})
|
||||
}
|
||||
return &pb.FindAllEnabledNodeClustersWithDNSDomainIdResponse{NodeClusters: result}, nil
|
||||
@@ -666,6 +682,7 @@ func (this *NodeClusterService) FindAllEnabledNodeClustersWithHTTPCachePolicyId(
|
||||
result = append(result, &pb.NodeCluster{
|
||||
Id: int64(cluster.Id),
|
||||
Name: cluster.Name,
|
||||
IsOn: cluster.IsOn == 1,
|
||||
})
|
||||
}
|
||||
return &pb.FindAllEnabledNodeClustersWithHTTPCachePolicyIdResponse{
|
||||
@@ -707,6 +724,7 @@ func (this *NodeClusterService) FindAllEnabledNodeClustersWithHTTPFirewallPolicy
|
||||
result = append(result, &pb.NodeCluster{
|
||||
Id: int64(cluster.Id),
|
||||
Name: cluster.Name,
|
||||
IsOn: cluster.IsOn == 1,
|
||||
})
|
||||
}
|
||||
return &pb.FindAllEnabledNodeClustersWithHTTPFirewallPolicyIdResponse{
|
||||
@@ -884,6 +902,7 @@ func (this *NodeClusterService) FindLatestNodeClusters(ctx context.Context, req
|
||||
pbClusters = append(pbClusters, &pb.NodeCluster{
|
||||
Id: int64(cluster.Id),
|
||||
Name: cluster.Name,
|
||||
IsOn: cluster.IsOn == 1,
|
||||
})
|
||||
}
|
||||
return &pb.FindLatestNodeClustersResponse{NodeClusters: pbClusters}, nil
|
||||
|
||||
@@ -24,7 +24,7 @@ func (this *NodeLogService) CreateNodeLogs(ctx context.Context, req *pb.CreateNo
|
||||
tx := this.NullTx()
|
||||
|
||||
for _, nodeLog := range req.NodeLogs {
|
||||
err := models.SharedNodeLogDAO.CreateLog(tx, nodeLog.Role, nodeLog.NodeId, nodeLog.ServerId, nodeLog.Level, nodeLog.Tag, nodeLog.Description, nodeLog.CreatedAt)
|
||||
err := models.SharedNodeLogDAO.CreateLog(tx, nodeLog.Role, nodeLog.NodeId, nodeLog.ServerId, nodeLog.OriginId, nodeLog.Level, nodeLog.Tag, nodeLog.Description, nodeLog.CreatedAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -41,7 +41,7 @@ func (this *NodeLogService) CountNodeLogs(ctx context.Context, req *pb.CountNode
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
count, err := models.SharedNodeLogDAO.CountNodeLogs(tx, req.Role, req.NodeId, req.ServerId, req.DayFrom, req.DayTo, req.Keyword, req.Level)
|
||||
count, err := models.SharedNodeLogDAO.CountNodeLogs(tx, req.Role, req.NodeId, req.ServerId, req.OriginId, req.DayFrom, req.DayTo, req.Keyword, req.Level)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -57,7 +57,7 @@ func (this *NodeLogService) ListNodeLogs(ctx context.Context, req *pb.ListNodeLo
|
||||
|
||||
tx := this.NullTx()
|
||||
|
||||
logs, err := models.SharedNodeLogDAO.ListNodeLogs(tx, req.Role, req.NodeId, req.ServerId, req.AllServers, req.DayFrom, req.DayTo, req.Keyword, req.Level, types.Int8(req.FixedState), req.Offset, req.Size)
|
||||
logs, err := models.SharedNodeLogDAO.ListNodeLogs(tx, req.Role, req.NodeId, req.ServerId, req.OriginId, req.AllServers, req.DayFrom, req.DayTo, req.Keyword, req.Level, types.Int8(req.FixedState), req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -733,7 +733,7 @@ func (this *ServerService) FindEnabledServerConfig(ctx context.Context, req *pb.
|
||||
}
|
||||
}
|
||||
|
||||
config, err := models.SharedServerDAO.ComposeServerConfig(tx, req.ServerId)
|
||||
config, err := models.SharedServerDAO.ComposeServerConfigWithServerId(tx, req.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1080,7 +1080,7 @@ func (this *ServerService) FindEnabledServerDNS(ctx context.Context, req *pb.Fin
|
||||
|
||||
// CheckUserServer 检查服务是否属于某个用户
|
||||
func (this *ServerService) CheckUserServer(ctx context.Context, req *pb.CheckUserServerRequest) (*pb.RPCSuccess, error) {
|
||||
userId, err := this.ValidateUser(ctx)
|
||||
userId, err := this.ValidateUserNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -33,11 +33,6 @@ func (this *ServerDailyStatService) UploadServerDailyStats(ctx context.Context,
|
||||
|
||||
var clusterId int64
|
||||
switch role {
|
||||
case rpcutils.UserTypeNode:
|
||||
clusterId, err = models.SharedNodeDAO.FindNodeClusterId(tx, nodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case rpcutils.UserTypeDNS:
|
||||
clusterId, err = nameservers.SharedNSNodeDAO.FindNodeClusterId(tx, nodeId)
|
||||
if err != nil {
|
||||
@@ -48,6 +43,13 @@ func (this *ServerDailyStatService) UploadServerDailyStats(ctx context.Context,
|
||||
// 写入其他统计表
|
||||
// TODO 将来改成每小时入库一次
|
||||
for _, stat := range req.Stats {
|
||||
if role == rpcutils.UserTypeNode {
|
||||
clusterId, err = models.SharedServerDAO.FindServerClusterId(tx, stat.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 总体流量(按天)
|
||||
err = stats.SharedTrafficDailyStatDAO.IncreaseDailyStat(tx, timeutil.FormatTime("Ymd", stat.CreatedAt), stat.Bytes, stat.CachedBytes, stat.CountRequests, stat.CountCachedRequests, stat.CountAttackRequests, stat.AttackBytes)
|
||||
if err != nil {
|
||||
@@ -84,6 +86,13 @@ func (this *ServerDailyStatService) UploadServerDailyStats(ctx context.Context,
|
||||
|
||||
// 域名统计
|
||||
for _, stat := range req.DomainStats {
|
||||
if role == rpcutils.UserTypeNode {
|
||||
clusterId, err = models.SharedServerDAO.FindServerClusterId(tx, stat.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err := stats.SharedServerDomainHourlyStatDAO.IncreaseHourlyStat(tx, clusterId, nodeId, stat.ServerId, stat.Domain, timeutil.FormatTime("YmdH", stat.CreatedAt), stat.Bytes, stat.CachedBytes, stat.CountRequests, stat.CountCachedRequests, stat.CountAttackRequests, stat.AttackBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -61,13 +61,13 @@ func (this *ServerStatBoardService) ComposeServerStatNodeClusterBoard(ctx contex
|
||||
var result = &pb.ComposeServerStatNodeClusterBoardResponse{}
|
||||
|
||||
// 统计数字
|
||||
countActiveNodes, err := models.SharedNodeDAO.CountAllEnabledNodesMatch(tx, req.NodeClusterId, configutils.BoolStateAll, configutils.BoolStateYes, "", 0, 0)
|
||||
countActiveNodes, err := models.SharedNodeDAO.CountAllEnabledNodesMatch(tx, req.NodeClusterId, configutils.BoolStateAll, configutils.BoolStateYes, "", 0, 0, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.CountActiveNodes = countActiveNodes
|
||||
|
||||
countInactiveNodes, err := models.SharedNodeDAO.CountAllEnabledNodesMatch(tx, req.NodeClusterId, configutils.BoolStateAll, configutils.BoolStateNo, "", 0, 0)
|
||||
countInactiveNodes, err := models.SharedNodeDAO.CountAllEnabledNodesMatch(tx, req.NodeClusterId, configutils.BoolStateAll, configutils.BoolStateNo, "", 0, 0, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -605,11 +605,11 @@ func (this *ServerStatBoardService) findNodeClusterMetricDataCharts(tx *dbs.Tx,
|
||||
case serverconfigs.MetricChartTypeTimeLine:
|
||||
var itemStats []*models.MetricStat
|
||||
if serverId > 0 {
|
||||
itemStats, err = models.SharedMetricStatDAO.FindLatestItemStatsWithServerId(tx, serverId, itemId, types.Int32(item.Version), 10)
|
||||
itemStats, err = models.SharedMetricStatDAO.FindLatestItemStatsWithServerId(tx, serverId, itemId, chart.IgnoreEmptyKeys == 1, chart.DecodeIgnoredKeys(), types.Int32(item.Version), 10)
|
||||
} else if nodeId > 0 {
|
||||
itemStats, err = models.SharedMetricStatDAO.FindLatestItemStatsWithNodeId(tx, nodeId, itemId, types.Int32(item.Version), 10)
|
||||
itemStats, err = models.SharedMetricStatDAO.FindLatestItemStatsWithNodeId(tx, nodeId, itemId, chart.IgnoreEmptyKeys == 1, chart.DecodeIgnoredKeys(), types.Int32(item.Version), 10)
|
||||
} else {
|
||||
itemStats, err = models.SharedMetricStatDAO.FindLatestItemStatsWithClusterId(tx, clusterId, itemId, types.Int32(item.Version), 10)
|
||||
itemStats, err = models.SharedMetricStatDAO.FindLatestItemStatsWithClusterId(tx, clusterId, itemId, chart.IgnoreEmptyKeys == 1, chart.DecodeIgnoredKeys(), types.Int32(item.Version), 10)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -649,11 +649,11 @@ func (this *ServerStatBoardService) findNodeClusterMetricDataCharts(tx *dbs.Tx,
|
||||
default:
|
||||
var itemStats []*models.MetricStat
|
||||
if serverId > 0 {
|
||||
itemStats, err = models.SharedMetricStatDAO.FindItemStatsWithServerIdAndLastTime(tx, serverId, itemId, types.Int32(item.Version), 10)
|
||||
itemStats, err = models.SharedMetricStatDAO.FindItemStatsWithServerIdAndLastTime(tx, serverId, itemId, chart.IgnoreEmptyKeys == 1, chart.DecodeIgnoredKeys(), types.Int32(item.Version), 10)
|
||||
} else if nodeId > 0 {
|
||||
itemStats, err = models.SharedMetricStatDAO.FindItemStatsWithNodeIdAndLastTime(tx, nodeId, itemId, types.Int32(item.Version), 10)
|
||||
itemStats, err = models.SharedMetricStatDAO.FindItemStatsWithNodeIdAndLastTime(tx, nodeId, itemId, chart.IgnoreEmptyKeys == 1, chart.DecodeIgnoredKeys(), types.Int32(item.Version), 10)
|
||||
} else {
|
||||
itemStats, err = models.SharedMetricStatDAO.FindItemStatsWithClusterIdAndLastTime(tx, clusterId, itemId, types.Int32(item.Version), 10)
|
||||
itemStats, err = models.SharedMetricStatDAO.FindItemStatsWithClusterIdAndLastTime(tx, clusterId, itemId, chart.IgnoreEmptyKeys == 1, chart.DecodeIgnoredKeys(), types.Int32(item.Version), 10)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -6,16 +6,16 @@ import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
// 互斥锁管理
|
||||
// SysLockerService 互斥锁管理
|
||||
type SysLockerService struct {
|
||||
BaseService
|
||||
}
|
||||
|
||||
// 获得锁
|
||||
// SysLockerLock 获得锁
|
||||
func (this *SysLockerService) SysLockerLock(ctx context.Context, req *pb.SysLockerLockRequest) (*pb.SysLockerLockResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
_, err = this.ValidateMonitor(ctx)
|
||||
_, err = this.ValidateMonitorNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -41,11 +41,11 @@ func (this *SysLockerService) SysLockerLock(ctx context.Context, req *pb.SysLock
|
||||
return &pb.SysLockerLockResponse{Ok: ok}, nil
|
||||
}
|
||||
|
||||
// 释放锁
|
||||
// SysLockerUnlock 释放锁
|
||||
func (this *SysLockerService) SysLockerUnlock(ctx context.Context, req *pb.SysLockerUnlockRequest) (*pb.RPCSuccess, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||
if err != nil {
|
||||
_, err = this.ValidateMonitor(ctx)
|
||||
_, err = this.ValidateMonitorNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ func (this *UserService) LoginUser(ctx context.Context, req *pb.LoginUserRequest
|
||||
|
||||
// UpdateUserInfo 修改用户基本信息
|
||||
func (this *UserService) UpdateUserInfo(ctx context.Context, req *pb.UpdateUserInfoRequest) (*pb.RPCSuccess, error) {
|
||||
userId, err := this.ValidateUser(ctx)
|
||||
userId, err := this.ValidateUserNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -278,7 +278,7 @@ func (this *UserService) UpdateUserInfo(ctx context.Context, req *pb.UpdateUserI
|
||||
|
||||
// UpdateUserLogin 修改用户登录信息
|
||||
func (this *UserService) UpdateUserLogin(ctx context.Context, req *pb.UpdateUserLoginRequest) (*pb.RPCSuccess, error) {
|
||||
userId, err := this.ValidateUser(ctx)
|
||||
userId, err := this.ValidateUserNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -298,7 +298,7 @@ func (this *UserService) UpdateUserLogin(ctx context.Context, req *pb.UpdateUser
|
||||
|
||||
// ComposeUserDashboard 取得用户Dashboard数据
|
||||
func (this *UserService) ComposeUserDashboard(ctx context.Context, req *pb.ComposeUserDashboardRequest) (*pb.ComposeUserDashboardResponse, error) {
|
||||
userId, err := this.ValidateUser(ctx)
|
||||
userId, err := this.ValidateUserNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ func (this *UserNodeService) FindEnabledUserNode(ctx context.Context, req *pb.Fi
|
||||
|
||||
// FindCurrentUserNode 获取当前用户节点的版本
|
||||
func (this *UserNodeService) FindCurrentUserNode(ctx context.Context, req *pb.FindCurrentUserNodeRequest) (*pb.FindCurrentUserNodeResponse, error) {
|
||||
_, err := this.ValidateUser(ctx)
|
||||
_, err := this.ValidateUserNode(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,7 @@
|
||||
package setup
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
@@ -108,7 +109,7 @@ func (this *SQLDump) Dump(db *dbs.DB) (result *SQLDumpResult, err error) {
|
||||
}
|
||||
|
||||
// Apply 应用数据
|
||||
func (this *SQLDump) Apply(db *dbs.DB, newResult *SQLDumpResult) (ops []string, err error) {
|
||||
func (this *SQLDump) Apply(db *dbs.DB, newResult *SQLDumpResult, showLog bool) (ops []string, err error) {
|
||||
currentResult, err := this.Dump(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -119,6 +120,9 @@ func (this *SQLDump) Apply(db *dbs.DB, newResult *SQLDumpResult) (ops []string,
|
||||
oldTable := currentResult.FindTable(newTable.Name)
|
||||
if oldTable == nil {
|
||||
ops = append(ops, "+ table "+newTable.Name)
|
||||
if showLog {
|
||||
fmt.Println("+ table " + newTable.Name)
|
||||
}
|
||||
_, err = db.Exec(newTable.Definition)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -130,12 +134,18 @@ func (this *SQLDump) Apply(db *dbs.DB, newResult *SQLDumpResult) (ops []string,
|
||||
oldField := oldTable.FindField(newField.Name)
|
||||
if oldField == nil {
|
||||
ops = append(ops, "+ "+newTable.Name+" "+newField.Name)
|
||||
if showLog {
|
||||
fmt.Println("+ " + newTable.Name + " " + newField.Name)
|
||||
}
|
||||
_, err = db.Exec("ALTER TABLE " + newTable.Name + " ADD `" + newField.Name + "` " + newField.Definition)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if !newField.EqualDefinition(oldField.Definition) {
|
||||
ops = append(ops, "* "+newTable.Name+" "+newField.Name)
|
||||
if showLog {
|
||||
fmt.Println("* " + newTable.Name + " " + newField.Name)
|
||||
}
|
||||
_, err = db.Exec("ALTER TABLE " + newTable.Name + " MODIFY `" + newField.Name + "` " + newField.Definition)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -149,12 +159,18 @@ func (this *SQLDump) Apply(db *dbs.DB, newResult *SQLDumpResult) (ops []string,
|
||||
oldIndex := oldTable.FindIndex(newIndex.Name)
|
||||
if oldIndex == nil {
|
||||
ops = append(ops, "+ index "+newTable.Name+" "+newIndex.Name)
|
||||
if showLog {
|
||||
fmt.Println("+ index " + newTable.Name + " " + newIndex.Name)
|
||||
}
|
||||
_, err = db.Exec("ALTER TABLE " + newTable.Name + " ADD " + newIndex.Definition)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if oldIndex.Definition != newIndex.Definition {
|
||||
ops = append(ops, "* index "+newTable.Name+" "+newIndex.Name)
|
||||
if showLog {
|
||||
fmt.Println("* index " + newTable.Name + " " + newIndex.Name)
|
||||
}
|
||||
_, err = db.Exec("ALTER TABLE " + newTable.Name + " DROP KEY " + newIndex.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -171,6 +187,9 @@ func (this *SQLDump) Apply(db *dbs.DB, newResult *SQLDumpResult) (ops []string,
|
||||
newIndex := newTable.FindIndex(oldIndex.Name)
|
||||
if newIndex == nil {
|
||||
ops = append(ops, "- index "+oldTable.Name+" "+oldIndex.Name)
|
||||
if showLog {
|
||||
fmt.Println("- index " + oldTable.Name + " " + oldIndex.Name)
|
||||
}
|
||||
_, err = db.Exec("ALTER TABLE " + oldTable.Name + " DROP KEY " + oldIndex.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -184,6 +203,9 @@ func (this *SQLDump) Apply(db *dbs.DB, newResult *SQLDumpResult) (ops []string,
|
||||
newField := newTable.FindField(oldField.Name)
|
||||
if newField == nil {
|
||||
ops = append(ops, "- field "+oldTable.Name+" "+oldField.Name)
|
||||
if showLog {
|
||||
fmt.Println("- field " + oldTable.Name + " " + oldField.Name)
|
||||
}
|
||||
_, err = db.Exec("ALTER TABLE " + oldTable.Name + " DROP COLUMN `" + oldField.Name + "`")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -209,6 +231,9 @@ func (this *SQLDump) Apply(db *dbs.DB, newResult *SQLDumpResult) (ops []string,
|
||||
}
|
||||
if one == nil {
|
||||
ops = append(ops, "+ record "+newTable.Name+" "+strings.Join(valueStrings, ", "))
|
||||
if showLog {
|
||||
fmt.Println("+ record " + newTable.Name + " " + strings.Join(valueStrings, ", "))
|
||||
}
|
||||
params := []string{}
|
||||
args := []string{}
|
||||
values := []interface{}{}
|
||||
@@ -224,6 +249,9 @@ func (this *SQLDump) Apply(db *dbs.DB, newResult *SQLDumpResult) (ops []string,
|
||||
}
|
||||
} else if !record.ValuesEquals(one) {
|
||||
ops = append(ops, "* record "+newTable.Name+" "+strings.Join(valueStrings, ", "))
|
||||
if showLog {
|
||||
fmt.Println("* record " + newTable.Name + " " + strings.Join(valueStrings, ", "))
|
||||
}
|
||||
args := []string{}
|
||||
values := []interface{}{}
|
||||
for k, v := range record.Values {
|
||||
|
||||
@@ -64,7 +64,7 @@ func TestSQLDump_Apply(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ops, err := dump.Apply(db2, result)
|
||||
ops, err := dump.Apply(db2, result, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
|
||||
var LatestSQLResult = &SQLDumpResult{}
|
||||
|
||||
// 安装或升级SQL执行器
|
||||
// SQLExecutor 安装或升级SQL执行器
|
||||
type SQLExecutor struct {
|
||||
dbConfig *dbs.DBConfig
|
||||
}
|
||||
@@ -52,7 +52,7 @@ func (this *SQLExecutor) Run() error {
|
||||
}
|
||||
|
||||
sqlDump := NewSQLDump()
|
||||
_, err = sqlDump.Apply(db, LatestSQLResult)
|
||||
_, err = sqlDump.Apply(db, LatestSQLResult, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -379,6 +379,20 @@ func (this *SQLExecutor) checkMetricItems(db *dbs.DB) error {
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
err := createMetricItem("request_referer_host", serverconfigs.MetricItemCategoryHTTP, "请求来源统计", []string{"${referer.host}"}, 1, "day", "${countRequest}", []maps.Map{
|
||||
{
|
||||
"name": "请求来源排行",
|
||||
"type": "bar",
|
||||
"widthDiv": 0,
|
||||
"code": "request_referer_host_bar",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -234,16 +234,17 @@ func (this *DNSTaskExecutor) doNode(taskId int64, nodeId int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if node.ClusterId == 0 {
|
||||
isOk = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// 转交给cluster统一处理
|
||||
err = dnsmodels.SharedDNSTaskDAO.CreateClusterTask(tx, int64(node.ClusterId), dnsmodels.DNSTaskTypeClusterChange)
|
||||
clusterIds, err := models.SharedNodeDAO.FindEnabledAndOnNodeClusterIds(tx, nodeId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, clusterId := range clusterIds {
|
||||
err = dnsmodels.SharedDNSTaskDAO.CreateClusterTask(tx, clusterId, dnsmodels.DNSTaskTypeClusterChange)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
isOk = true
|
||||
|
||||
@@ -287,7 +288,7 @@ func (this *DNSTaskExecutor) doCluster(taskId int64, clusterId int64) error {
|
||||
|
||||
// 当前的节点记录
|
||||
newRecordKeys := []string{}
|
||||
nodes, err := models.SharedNodeDAO.FindAllEnabledNodesDNSWithClusterId(tx, clusterId)
|
||||
nodes, err := models.SharedNodeDAO.FindAllEnabledNodesDNSWithClusterId(tx, clusterId, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user