Compare commits
188 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07b377c2fb | ||
|
|
33a3795773 | ||
|
|
bddb3cae96 | ||
|
|
6a525c2b82 | ||
|
|
3a137c1c3f | ||
|
|
19867568a9 | ||
|
|
c2600b911b | ||
|
|
fe511ae7e5 | ||
|
|
876c631c85 | ||
|
|
a4cc138ef3 | ||
|
|
3f9a7a8a49 | ||
|
|
09d8ef00c2 | ||
|
|
b4f77ddc63 | ||
|
|
6a9045ba44 | ||
|
|
bc7ee19962 | ||
|
|
2484cd4ae6 | ||
|
|
57b8a96c6d | ||
|
|
6c8ab7cb94 | ||
|
|
b2c2bd247b | ||
|
|
29d9e6db81 | ||
|
|
24fcb48c75 | ||
|
|
4911198fe7 | ||
|
|
c2af796992 | ||
|
|
51c8572e53 | ||
|
|
c15cc6d75c | ||
|
|
c0a99a4ba3 | ||
|
|
62e26bed5a | ||
|
|
9e68a2915c | ||
|
|
5b809fda1f | ||
|
|
88b782940a | ||
|
|
85c596644d | ||
|
|
ffa2d884bd | ||
|
|
813ed18610 | ||
|
|
564b11eae7 | ||
|
|
d2af0307b9 | ||
|
|
4fa6b03238 | ||
|
|
4bda78aa8c | ||
|
|
6002cc96d9 | ||
|
|
56c09f5be7 | ||
|
|
e1fb8e4c74 | ||
|
|
14f055ce7c | ||
|
|
7b7f2b0a00 | ||
|
|
75662586fa | ||
|
|
c024331fa0 | ||
|
|
b01ea79c5c | ||
|
|
d59f80b3ec | ||
|
|
b87e48c1f9 | ||
|
|
0e7a7f168f | ||
|
|
2bbc09d3af | ||
|
|
97b50fab28 | ||
|
|
83c867cb65 | ||
|
|
3c4b7ca57b | ||
|
|
a2f98d2f25 | ||
|
|
71677a8638 | ||
|
|
95a2187f95 | ||
|
|
86bec813bf | ||
|
|
0d7bd6f04e | ||
|
|
d7117209b2 | ||
|
|
7a340ac68b | ||
|
|
353b1b4ad1 | ||
|
|
fdac8beb40 | ||
|
|
f098723a41 | ||
|
|
6ded627903 | ||
|
|
ed2d5ee5cc | ||
|
|
c677368482 | ||
|
|
51ccd614a7 | ||
|
|
9be7f61b8c | ||
|
|
14ad97c937 | ||
|
|
94609d8ef4 | ||
|
|
e34e38bcb2 | ||
|
|
b10d9fe842 | ||
|
|
992e725378 | ||
|
|
346de7ca7a | ||
|
|
b212e124c2 | ||
|
|
ee2781fe65 | ||
|
|
89c1edc9ee | ||
|
|
773f3e1a7e | ||
|
|
e6f6f4dcc2 | ||
|
|
174946aa4d | ||
|
|
93c594a785 | ||
|
|
2aea527dff | ||
|
|
fa30015ca5 | ||
|
|
d06c8cebf5 | ||
|
|
e4ef2e8253 | ||
|
|
665aa06cc7 | ||
|
|
88dfda82d6 | ||
|
|
243463df83 | ||
|
|
2dc1bfcb55 | ||
|
|
e6f7cafe7e | ||
|
|
26fe3558f4 | ||
|
|
ea09ef3d91 | ||
|
|
c4ca2521ee | ||
|
|
db5cdd2957 | ||
|
|
0f483b98ec | ||
|
|
0fe51abeb1 | ||
|
|
db6b7f57bb | ||
|
|
663ead19e4 | ||
|
|
bc8adb663a | ||
|
|
08b5dd7531 | ||
|
|
8177f3d7e4 | ||
|
|
bb5252caf6 | ||
|
|
bd4a47d2a1 | ||
|
|
300be4e936 | ||
|
|
c9dbfb79a7 | ||
|
|
589ae124f1 | ||
|
|
d72b440406 | ||
|
|
63e4e7cf9f | ||
|
|
ad416dddec | ||
|
|
4e18129c6c | ||
|
|
c03d9f1880 | ||
|
|
fe448e6556 | ||
|
|
adcb33fce4 | ||
|
|
e58c3774b6 | ||
|
|
cd7e01c2f0 | ||
|
|
d884777a55 | ||
|
|
c48aba1c99 | ||
|
|
8cc0faf1d7 | ||
|
|
9851b1a146 | ||
|
|
36162c603d | ||
|
|
cc2782584e | ||
|
|
1c1e82ee38 | ||
|
|
4b3a9cedfa | ||
|
|
e9497ee65d | ||
|
|
29fae55dc6 | ||
|
|
54fdf3b762 | ||
|
|
f609008984 | ||
|
|
f9b6838dc6 | ||
|
|
6d2ecb9af3 | ||
|
|
7c4a01137b | ||
|
|
418c15f79f | ||
|
|
d13176b8a5 | ||
|
|
b2752ddd5a | ||
|
|
7aea2fd48c | ||
|
|
803f11659c | ||
|
|
073926ff67 | ||
|
|
65b4832c94 | ||
|
|
5f793f1f76 | ||
|
|
0ce1df25bc | ||
|
|
06ad9cc63b | ||
|
|
57247d0f5b | ||
|
|
813267c50f | ||
|
|
b8078e73b2 | ||
|
|
f958c57984 | ||
|
|
30bfbdc01e | ||
|
|
314362c24d | ||
|
|
8582715be7 | ||
|
|
74e585263c | ||
|
|
35cb10fffe | ||
|
|
7c84794ac4 | ||
|
|
5859f5df91 | ||
|
|
e370944233 | ||
|
|
a23a2ed826 | ||
|
|
3f9c250dff | ||
|
|
06c9c9403b | ||
|
|
0e580a0890 | ||
|
|
7aba622403 | ||
|
|
72cc8389e6 | ||
|
|
39cf470b0c | ||
|
|
6e71dda713 | ||
|
|
10909e28c8 | ||
|
|
6bd6e350b9 | ||
|
|
d2ae7834ae | ||
|
|
c1ffd25c8b | ||
|
|
931e55162b | ||
|
|
fa2bac6d1d | ||
|
|
2f7b7240dd | ||
|
|
da67e726a2 | ||
|
|
6cb5529c3f | ||
|
|
473d0d9439 | ||
|
|
bf0db231fc | ||
|
|
5644906b77 | ||
|
|
3e32fe8e10 | ||
|
|
8459f106e9 | ||
|
|
b768bbce5d | ||
|
|
9e7beb39c0 | ||
|
|
94287f5857 | ||
|
|
60690dfd01 | ||
|
|
fb00a7931e | ||
|
|
42a6494bde | ||
|
|
85a46a9827 | ||
|
|
088636553c | ||
|
|
95de3b12e2 | ||
|
|
b66b8d198a | ||
|
|
e968a79886 | ||
|
|
4fc5d5b549 | ||
|
|
77606709b3 | ||
|
|
3529ceefcd | ||
|
|
7e851f07b1 |
29
LICENSE
Normal file
29
LICENSE
Normal file
@@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2020, LiuXiangChao
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,76 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
function build() {
|
||||
ROOT=$(dirname $0)
|
||||
ROOT=$(dirname "$0")
|
||||
NAME="edge-api"
|
||||
DIST=$ROOT/"../dist/${NAME}"
|
||||
OS=${1}
|
||||
ARCH=${2}
|
||||
TAG=${3}
|
||||
NODE_ARCHITECTS=("amd64" "386" "arm64" "mips64" "mips64le")
|
||||
NODE_ARCHITECTS=("amd64" "arm64")
|
||||
|
||||
if [ -z $OS ]; then
|
||||
if [ -z "$OS" ]; then
|
||||
echo "usage: build.sh OS ARCH"
|
||||
exit
|
||||
fi
|
||||
if [ -z $ARCH ]; then
|
||||
if [ -z "$ARCH" ]; then
|
||||
echo "usage: build.sh OS ARCH"
|
||||
exit
|
||||
fi
|
||||
if [ -z $TAG ]; then
|
||||
if [ -z "$TAG" ]; then
|
||||
TAG="community"
|
||||
fi
|
||||
|
||||
VERSION=$(lookup-version $ROOT/../internal/const/const.go)
|
||||
VERSION=$(lookup-version "$ROOT"/../internal/const/const.go)
|
||||
ZIP="${NAME}-${OS}-${ARCH}-${TAG}-v${VERSION}.zip"
|
||||
|
||||
# build edge-node
|
||||
NodeVersion=$(lookup-version $ROOT"/../../EdgeNode/internal/const/const.go")
|
||||
NodeVersion=$(lookup-version "$ROOT""/../../EdgeNode/internal/const/const.go")
|
||||
echo "building edge-node v${NodeVersion} ..."
|
||||
EDGE_NODE_BUILD_SCRIPT=$ROOT"/../../EdgeNode/build/build.sh"
|
||||
if [ ! -f $EDGE_NODE_BUILD_SCRIPT ]; then
|
||||
if [ ! -f "$EDGE_NODE_BUILD_SCRIPT" ]; then
|
||||
echo "unable to find edge-node build script 'EdgeNode/build/build.sh'"
|
||||
exit
|
||||
fi
|
||||
cd $ROOT"/../../EdgeNode/build"
|
||||
cd "$ROOT""/../../EdgeNode/build" || exit
|
||||
echo "=============================="
|
||||
for arch in "${NODE_ARCHITECTS[@]}"; do
|
||||
if [ ! -f $ROOT"/../../EdgeNode/dist/edge-node-linux-${arch}-${TAG}-v${NodeVersion}.zip" ]; then
|
||||
./build.sh linux $arch $TAG
|
||||
if [ ! -f "$ROOT""/../../EdgeNode/dist/edge-node-linux-${arch}-${TAG}-v${NodeVersion}.zip" ]; then
|
||||
./build.sh linux "$arch" $TAG
|
||||
else
|
||||
echo "use built node linux/$arch/v${NodeVersion}"
|
||||
fi
|
||||
done
|
||||
echo "=============================="
|
||||
cd -
|
||||
cd - || exit
|
||||
|
||||
rm -f $ROOT/deploy/*.zip
|
||||
rm -f "$ROOT"/deploy/*.zip
|
||||
for arch in "${NODE_ARCHITECTS[@]}"; do
|
||||
cp $ROOT"/../../EdgeNode/dist/edge-node-linux-${arch}-${TAG}-v${NodeVersion}.zip" $ROOT/deploy/edge-node-linux-${arch}-v${NodeVersion}.zip
|
||||
cp "$ROOT""/../../EdgeNode/dist/edge-node-linux-${arch}-${TAG}-v${NodeVersion}.zip" "$ROOT"/deploy/edge-node-linux-"${arch}"-v"${NodeVersion}".zip
|
||||
done
|
||||
|
||||
# build edge-dns
|
||||
if [ "$TAG" = "plus" ]; then
|
||||
DNS_ROOT=$ROOT"/../../EdgeDNS"
|
||||
if [ -d $DNS_ROOT ]; then
|
||||
DNSNodeVersion=$(lookup-version $ROOT"/../../EdgeDNS/internal/const/const.go")
|
||||
if [ -d "$DNS_ROOT" ]; then
|
||||
DNSNodeVersion=$(lookup-version "$ROOT""/../../EdgeDNS/internal/const/const.go")
|
||||
echo "building edge-dns ${DNSNodeVersion} ..."
|
||||
EDGE_DNS_NODE_BUILD_SCRIPT=$ROOT"/../../EdgeDNS/build/build.sh"
|
||||
if [ ! -f $EDGE_DNS_NODE_BUILD_SCRIPT ]; then
|
||||
if [ ! -f "$EDGE_DNS_NODE_BUILD_SCRIPT" ]; then
|
||||
echo "unable to find edge-dns build script 'EdgeDNS/build/build.sh'"
|
||||
exit
|
||||
fi
|
||||
cd $ROOT"/../../EdgeDNS/build"
|
||||
cd "$ROOT""/../../EdgeDNS/build" || exit
|
||||
echo "=============================="
|
||||
architects=("amd64")
|
||||
architects=("amd64" "arm64")
|
||||
for arch in "${architects[@]}"; do
|
||||
./build.sh linux $arch $TAG
|
||||
./build.sh linux "$arch" $TAG
|
||||
done
|
||||
echo "=============================="
|
||||
cd -
|
||||
cd - || exit
|
||||
|
||||
for arch in "${architects[@]}"; do
|
||||
cp $ROOT"/../../EdgeDNS/dist/edge-dns-linux-${arch}-v${DNSNodeVersion}.zip" $ROOT/deploy/edge-dns-linux-${arch}-v${DNSNodeVersion}.zip
|
||||
cp "$ROOT""/../../EdgeDNS/dist/edge-dns-linux-${arch}-v${DNSNodeVersion}.zip" "$ROOT"/deploy/edge-dns-linux-"${arch}"-v"${DNSNodeVersion}".zip
|
||||
done
|
||||
fi
|
||||
fi
|
||||
@@ -78,48 +78,48 @@ function build() {
|
||||
# build sql
|
||||
if [ $TAG = "plus" ]; then
|
||||
echo "building sql ..."
|
||||
${ROOT}/sql.sh
|
||||
"${ROOT}"/sql.sh
|
||||
fi
|
||||
|
||||
# copy files
|
||||
echo "copying ..."
|
||||
if [ ! -d $DIST ]; then
|
||||
mkdir $DIST
|
||||
mkdir $DIST/bin
|
||||
mkdir $DIST/configs
|
||||
mkdir $DIST/logs
|
||||
if [ ! -d "$DIST" ]; then
|
||||
mkdir "$DIST"
|
||||
mkdir "$DIST"/bin
|
||||
mkdir "$DIST"/configs
|
||||
mkdir "$DIST"/logs
|
||||
fi
|
||||
cp $ROOT/configs/api.template.yaml $DIST/configs/
|
||||
cp $ROOT/configs/db.template.yaml $DIST/configs/
|
||||
cp -R $ROOT/deploy $DIST/
|
||||
rm -f $dist/deploy/.gitignore
|
||||
cp -R $ROOT/installers $DIST/
|
||||
cp -R $ROOT/resources $DIST/
|
||||
rm -f $DIST/resources/ipdata/ip2region/global_region.csv
|
||||
rm -f $DIST/resources/ipdata/ip2region/ip.merge.txt
|
||||
cp "$ROOT"/configs/api.template.yaml "$DIST"/configs/
|
||||
cp "$ROOT"/configs/db.template.yaml "$DIST"/configs/
|
||||
cp -R "$ROOT"/deploy "$DIST/"
|
||||
rm -f "$DIST"/deploy/.gitignore
|
||||
cp -R "$ROOT"/installers "$DIST"/
|
||||
cp -R "$ROOT"/resources "$DIST"/
|
||||
rm -f "$DIST"/resources/ipdata/ip2region/global_region.csv
|
||||
rm -f "$DIST"/resources/ipdata/ip2region/ip.merge.txt
|
||||
|
||||
# building edge installer
|
||||
echo "building node installer ..."
|
||||
architects=("amd64" "386" "arm64")
|
||||
architects=("amd64" "arm64")
|
||||
for arch in "${architects[@]}"; do
|
||||
# TODO support arm, mips ...
|
||||
env GOOS=linux GOARCH=${arch} go build -tags $TAG --ldflags="-s -w" -o $ROOT/installers/edge-installer-helper-linux-${arch} $ROOT/../cmd/installer-helper/main.go
|
||||
env GOOS=linux GOARCH="${arch}" go build -trimpath -tags $TAG --ldflags="-s -w" -o "$ROOT"/installers/edge-installer-helper-linux-"${arch}" "$ROOT"/../cmd/installer-helper/main.go
|
||||
done
|
||||
|
||||
# building edge dns installer
|
||||
echo "building dns node installer ..."
|
||||
architects=("amd64" "386" "arm64")
|
||||
architects=("amd64" "arm64")
|
||||
for arch in "${architects[@]}"; do
|
||||
# TODO support arm, mips ...
|
||||
env GOOS=linux GOARCH=${arch} go build -tags $TAG --ldflags="-s -w" -o $ROOT/installers/edge-installer-dns-helper-linux-${arch} $ROOT/../cmd/installer-dns-helper/main.go
|
||||
env GOOS=linux GOARCH="${arch}" go build -trimpath -tags $TAG --ldflags="-s -w" -o "$ROOT"/installers/edge-installer-dns-helper-linux-"${arch}" "$ROOT"/../cmd/installer-dns-helper/main.go
|
||||
done
|
||||
|
||||
# building api node
|
||||
env GOOS=$OS GOARCH=$ARCH go build -tags $TAG --ldflags="-s -w" -o $DIST/bin/edge-api $ROOT/../cmd/edge-api/main.go
|
||||
env GOOS="$OS" GOARCH="$ARCH" go build -trimpath -tags $TAG --ldflags="-s -w" -o "$DIST"/bin/edge-api "$ROOT"/../cmd/edge-api/main.go
|
||||
|
||||
# delete hidden files
|
||||
find $DIST -name ".DS_Store" -delete
|
||||
find $DIST -name ".gitignore" -delete
|
||||
find "$DIST" -name ".DS_Store" -delete
|
||||
find "$DIST" -name ".gitignore" -delete
|
||||
|
||||
echo "zip files"
|
||||
cd "${DIST}/../" || exit
|
||||
@@ -135,15 +135,15 @@ function build() {
|
||||
|
||||
function lookup-version() {
|
||||
FILE=$1
|
||||
VERSION_DATA=$(cat $FILE)
|
||||
VERSION_DATA=$(cat "$FILE")
|
||||
re="Version[ ]+=[ ]+\"([0-9.]+)\""
|
||||
if [[ $VERSION_DATA =~ $re ]]; then
|
||||
VERSION=${BASH_REMATCH[1]}
|
||||
echo $VERSION
|
||||
echo "$VERSION"
|
||||
else
|
||||
echo "could not match version"
|
||||
exit
|
||||
fi
|
||||
}
|
||||
|
||||
build $1 $2 $3
|
||||
build "$1" "$2" "$3"
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/apps"
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
@@ -11,7 +12,9 @@ import (
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"github.com/iwind/gosock/pkg/gosock"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
@@ -20,12 +23,12 @@ func main() {
|
||||
if !Tea.IsTesting() {
|
||||
Tea.Env = "prod"
|
||||
}
|
||||
app := apps.NewAppCmd()
|
||||
var app = apps.NewAppCmd()
|
||||
app.Version(teaconst.Version)
|
||||
app.Product(teaconst.ProductName)
|
||||
app.Usage(teaconst.ProcessName + " [start|stop|restart|setup|upgrade|service|daemon]")
|
||||
app.Usage(teaconst.ProcessName + " [start|stop|restart|setup|upgrade|service|daemon|issues]")
|
||||
app.On("setup", func() {
|
||||
setupCmd := setup.NewSetupFromCmd()
|
||||
var setupCmd = setup.NewSetupFromCmd()
|
||||
err := setupCmd.Run()
|
||||
result := maps.Map{}
|
||||
if err != nil {
|
||||
@@ -97,6 +100,82 @@ func main() {
|
||||
}
|
||||
}
|
||||
})
|
||||
app.On("db.stmt.prepare", func() {
|
||||
var sock = gosock.NewTmpSock(teaconst.ProcessName)
|
||||
reply, err := sock.Send(&gosock.Command{Code: "db.stmt.prepare"})
|
||||
if err != nil {
|
||||
fmt.Println("[ERROR]" + err.Error())
|
||||
} else {
|
||||
var isOn = maps.NewMap(reply.Params).GetBool("isOn")
|
||||
if isOn {
|
||||
fmt.Println("show statements: on")
|
||||
} else {
|
||||
fmt.Println("show statements: off")
|
||||
}
|
||||
}
|
||||
})
|
||||
app.On("db.stmt.count", func() {
|
||||
var sock = gosock.NewTmpSock(teaconst.ProcessName)
|
||||
reply, err := sock.Send(&gosock.Command{Code: "db.stmt.count"})
|
||||
if err != nil {
|
||||
fmt.Println("[ERROR]" + err.Error())
|
||||
} else {
|
||||
var count = maps.NewMap(reply.Params).GetInt("count")
|
||||
fmt.Println("prepared statements count: " + types.String(count))
|
||||
}
|
||||
})
|
||||
app.On("issues", func() {
|
||||
var flagSet = flag.NewFlagSet("issues", flag.ExitOnError)
|
||||
var formatJSON = false
|
||||
flagSet.BoolVar(&formatJSON, "json", false, "")
|
||||
_ = flagSet.Parse(os.Args[2:])
|
||||
|
||||
data, err := ioutil.ReadFile(Tea.LogFile("issues.log"))
|
||||
if err != nil {
|
||||
if formatJSON {
|
||||
fmt.Print("[]")
|
||||
} else {
|
||||
fmt.Println("no issues yet")
|
||||
}
|
||||
} else {
|
||||
var issueMaps = []maps.Map{}
|
||||
err = json.Unmarshal(data, &issueMaps)
|
||||
if err != nil {
|
||||
if formatJSON {
|
||||
fmt.Print("[]")
|
||||
} else {
|
||||
fmt.Println("no issues yet")
|
||||
}
|
||||
} else {
|
||||
if formatJSON {
|
||||
fmt.Print(string(data))
|
||||
} else {
|
||||
if len(issueMaps) == 0 {
|
||||
fmt.Println("no issues yet")
|
||||
} else {
|
||||
for i, issue := range issueMaps {
|
||||
fmt.Println("issue " + types.String(i+1) + ": " + issue.GetString("message"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
app.On("instance", func() {
|
||||
var sock = gosock.NewTmpSock(teaconst.ProcessName)
|
||||
reply, err := sock.Send(&gosock.Command{Code: "instance"})
|
||||
if err != nil {
|
||||
fmt.Println("[ERROR]" + err.Error())
|
||||
} else {
|
||||
replyJSON, err := json.MarshalIndent(reply.Params, "", " ")
|
||||
if err != nil {
|
||||
fmt.Println("[ERROR]marshal result failed: " + err.Error())
|
||||
} else {
|
||||
fmt.Println(string(replyJSON))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
app.Run(func() {
|
||||
nodes.NewAPINode().Start()
|
||||
})
|
||||
|
||||
3
dist/.gitignore
vendored
3
dist/.gitignore
vendored
@@ -1 +1,2 @@
|
||||
*.zip
|
||||
*.zip
|
||||
edge-api
|
||||
46
go.mod
46
go.mod
@@ -1,31 +1,47 @@
|
||||
module github.com/TeaOSLab/EdgeAPI
|
||||
|
||||
go 1.15
|
||||
go 1.18
|
||||
|
||||
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
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1183
|
||||
github.com/andybalholm/brotli v1.0.4
|
||||
github.com/cespare/xxhash/v2 v2.1.1
|
||||
github.com/go-acme/lego/v4 v4.5.2
|
||||
github.com/go-ole/go-ole v1.2.4 // indirect
|
||||
github.com/go-sql-driver/mysql v1.5.0
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/iwind/TeaGo v0.0.0-20211026123858-7de7a21cad24
|
||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/lionsoul2014/ip2region v2.2.0-release+incompatible
|
||||
github.com/iwind/TeaGo v0.0.0-20220408111647-f36b9bba3570
|
||||
github.com/iwind/gosock v0.0.0-20220505115348-f88412125a62
|
||||
github.com/mozillazg/go-pinyin v0.18.0
|
||||
github.com/pkg/sftp v1.12.0
|
||||
github.com/shirou/gopsutil v3.21.5+incompatible
|
||||
github.com/tklauser/go-sysconf v0.3.6 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22
|
||||
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced // indirect
|
||||
google.golang.org/grpc v1.38.0
|
||||
google.golang.org/protobuf v1.26.0
|
||||
github.com/shirou/gopsutil/v3 v3.22.2
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292
|
||||
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8
|
||||
google.golang.org/grpc v1.45.0
|
||||
google.golang.org/protobuf v1.27.1
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/cenkalti/backoff/v4 v4.1.1 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/miekg/dns v1.1.43 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.9 // indirect
|
||||
github.com/tklauser/numcpus v0.3.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
)
|
||||
|
||||
99
go.sum
99
go.sum
@@ -43,8 +43,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
|
||||
github.com/DataDog/sketches-go v0.0.0-20190923095040-43f19ad77ff7/go.mod h1:Q5DbzQ+3AkgGwymQO7aZFNP7ns2lZKGtvRBzRXfdi60=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.1.1/go.mod h1:kX6YddBkXqqywAe8c9LyvgTCyFuZCTMF4cRPQhc3Fy8=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
@@ -52,6 +50,7 @@ github.com/aliyun/alibaba-cloud-sdk-go v1.61.1183 h1:dkj8/dxOQ4L1XpwCzRLqukvUBbx
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1183/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA=
|
||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
@@ -67,7 +66,6 @@ github.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7F
|
||||
github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ=
|
||||
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
@@ -78,6 +76,10 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
||||
github.com/cloudflare/cloudflare-go v0.20.0/go.mod h1:sPWL/lIC6biLEdyGZwBQ1rGQKF1FhM7N60fuNiFdYTI=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
@@ -101,7 +103,8 @@ github.com/dnsimple/dnsimple-go v0.70.1/go.mod h1:F9WHww9cC76hrnwGFfAfrqdW99j3MO
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/exoscale/egoscale v0.67.0/go.mod h1:wi0myUxPsV8SdEtdJHQJxFLL/wEw9fiw9Gs1PWRkvkM=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
@@ -122,8 +125,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
|
||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-redis/redis/v8 v8.0.0-beta.7/go.mod h1:FGJAWDWFht1sQ4qxyJHZZbVyvnVcKQN0E3u5/5lRz+g=
|
||||
@@ -132,8 +135,6 @@ github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gG
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o=
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
|
||||
github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b/go.mod h1:Xo4aNUOrJnVruqWQJBtW6+bTBDTniY8yZum5rF3b5jw=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
@@ -161,6 +162,7 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
|
||||
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/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/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=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
@@ -173,8 +175,10 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/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-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
@@ -201,6 +205,7 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
@@ -231,13 +236,13 @@ github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhK
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/infobloxopen/infoblox-go-client v1.1.1/go.mod h1:BXiw7S2b9qJoM8MS40vfgCNB2NLHGusk1DtO16BD9zI=
|
||||
github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/TeaGo v0.0.0-20210628135026-38575a4ab060/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/TeaGo v0.0.0-20210831140440-a2a442471b13 h1:HuEJ5xJfujW1Q6rNDhOu5LQXEBB2qLPah3jYslT8Gz4=
|
||||
github.com/iwind/TeaGo v0.0.0-20210831140440-a2a442471b13/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/TeaGo v0.0.0-20211026123858-7de7a21cad24 h1:1cGulkD2SNJJRok5OKwyhP/Ddm+PgSWKOupn0cR36/A=
|
||||
github.com/iwind/TeaGo v0.0.0-20211026123858-7de7a21cad24/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
|
||||
github.com/iwind/TeaGo v0.0.0-20220408111647-f36b9bba3570 h1:zqz2FiMMkSHXWO1EsTRJDPTwX9xQ4uuyD5GAE4JGlhM=
|
||||
github.com/iwind/TeaGo v0.0.0-20220408111647-f36b9bba3570/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
|
||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3 h1:aBSonas7vFcgTj9u96/bWGILGv1ZbUSTLiOzcI1ZT6c=
|
||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
|
||||
github.com/iwind/gosock v0.0.0-20220505115348-f88412125a62 h1:HJH6RDheAY156DnIfJSD/bEvqyXzsZuE2gzs8PuUjoo=
|
||||
github.com/iwind/gosock v0.0.0-20220505115348-f88412125a62/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
|
||||
github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
|
||||
github.com/jarcoal/httpmock v1.0.6/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
@@ -250,8 +255,6 @@ github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
@@ -277,12 +280,12 @@ github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c
|
||||
github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg=
|
||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||
github.com/linode/linodego v0.31.1/go.mod h1:BR0gVkCJffEdIGJSl6bHR80Ty+Uvg/2jkjmrWaFectM=
|
||||
github.com/lionsoul2014/ip2region v2.2.0-release+incompatible h1:1qp9iks+69h7IGLazAplzS9Ca14HAxuD5c0rbFdPGy4=
|
||||
github.com/lionsoul2014/ip2region v2.2.0-release+incompatible/go.mod h1:+ZBN7PBoh5gG6/y0ZQ85vJDBe21WnfbRrQQwTfliJJI=
|
||||
github.com/liquidweb/go-lwApi v0.0.0-20190605172801-52a4864d2738/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs=
|
||||
github.com/liquidweb/go-lwApi v0.0.5/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs=
|
||||
github.com/liquidweb/liquidweb-cli v0.6.9/go.mod h1:cE1uvQ+x24NGUL75D0QagOFCG8Wdvmwu8aL9TLmA/eQ=
|
||||
github.com/liquidweb/liquidweb-go v1.6.3/go.mod h1:SuXXp+thr28LnjEw18AYtWwIbWMHSUiajPQs8T9c/Rc=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
@@ -322,7 +325,6 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
@@ -371,6 +373,8 @@ github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
@@ -390,14 +394,15 @@ github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
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/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sacloud/libsacloud v1.36.2/go.mod h1:P7YAOVmnIn3DKHqCZcUKYUXmSwGBm3yS7IBEjKVSrjg=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210127161313-bd30bebeac4f/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
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/shirou/gopsutil/v3 v3.22.2 h1:wCrArWFkHYIdDxx/FSfF5RB4dpJYW6t7rcp3+zL8uks=
|
||||
github.com/shirou/gopsutil/v3 v3.22.2/go.mod h1:WapW1AOOPlHyXr+yOyw3uYx36enocrtSoSBy0L5vUHY=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
@@ -436,10 +441,10 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4=
|
||||
github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
|
||||
github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
|
||||
github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
|
||||
github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo=
|
||||
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
|
||||
github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
|
||||
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/transip/gotransip/v6 v6.6.1/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g=
|
||||
github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
|
||||
@@ -456,13 +461,15 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opentelemetry.io/otel v0.7.0/go.mod h1:aZMyHG5TqDOXEgH2tyLiXSUKly1jT3yqE9PmrzIeCdo=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
@@ -482,8 +489,9 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -507,7 +515,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
@@ -516,7 +523,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -551,8 +557,9 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -588,6 +595,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -611,19 +619,23 @@ golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs=
|
||||
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
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=
|
||||
@@ -631,8 +643,9 @@ 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.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -674,7 +687,6 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -714,9 +726,10 @@ 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-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced h1:c5geK1iMU3cDKtFrCVQIcjR3W+JOZMuhIyICMCTbtus=
|
||||
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
|
||||
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e h1:fNKDNuUyC4WH+inqDMpfXDdfvwfYILbsX+oskGZ8hxg=
|
||||
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
@@ -726,9 +739,10 @@ 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/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=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M=
|
||||
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@@ -739,8 +753,9 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
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=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -12,8 +12,9 @@ import (
|
||||
)
|
||||
|
||||
type BaseStorage struct {
|
||||
isOk bool
|
||||
version int
|
||||
isOk bool
|
||||
version int
|
||||
firewallOnly bool
|
||||
}
|
||||
|
||||
func (this *BaseStorage) SetVersion(version int) {
|
||||
@@ -32,6 +33,10 @@ func (this *BaseStorage) SetOk(isOk bool) {
|
||||
this.isOk = isOk
|
||||
}
|
||||
|
||||
func (this *BaseStorage) SetFirewallOnly(firewallOnly bool) {
|
||||
this.firewallOnly = firewallOnly
|
||||
}
|
||||
|
||||
// Marshal 对日志进行编码
|
||||
func (this *BaseStorage) Marshal(accessLog *pb.HTTPAccessLog) ([]byte, error) {
|
||||
return json.Marshal(accessLog)
|
||||
@@ -39,7 +44,7 @@ func (this *BaseStorage) Marshal(accessLog *pb.HTTPAccessLog) ([]byte, error) {
|
||||
|
||||
// FormatVariables 格式化字符串中的变量
|
||||
func (this *BaseStorage) FormatVariables(s string) string {
|
||||
now := time.Now()
|
||||
var now = time.Now()
|
||||
return configutils.ParseVariables(s, func(varName string) (value string) {
|
||||
switch varName {
|
||||
case "year":
|
||||
|
||||
@@ -61,6 +61,10 @@ func (this *CommandStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
return err
|
||||
}
|
||||
for _, accessLog := range accessLogs {
|
||||
if this.firewallOnly && accessLog.FirewallPolicyId == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
data, err := this.Marshal(accessLog)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
|
||||
@@ -59,6 +59,10 @@ func (this *ESStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
indexName := this.FormatVariables(this.config.Index)
|
||||
typeName := this.FormatVariables(this.config.MappingType)
|
||||
for _, accessLog := range accessLogs {
|
||||
if this.firewallOnly && accessLog.FirewallPolicyId == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(accessLog.RequestId) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -57,6 +57,9 @@ func (this *FileStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
defer this.writeLocker.Unlock()
|
||||
|
||||
for _, accessLog := range accessLogs {
|
||||
if this.firewallOnly && accessLog.FirewallPolicyId == 0 {
|
||||
continue
|
||||
}
|
||||
data, err := this.Marshal(accessLog)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
|
||||
@@ -12,6 +12,9 @@ type StorageInterface interface {
|
||||
// SetVersion 设置版本
|
||||
SetVersion(version int)
|
||||
|
||||
// SetFirewallOnly 设置是否只处理防火墙相关的访问日志
|
||||
SetFirewallOnly(firewallOnly bool)
|
||||
|
||||
IsOk() bool
|
||||
|
||||
SetOk(ok bool)
|
||||
|
||||
@@ -58,7 +58,7 @@ func (this *StorageManager) Loop() error {
|
||||
}
|
||||
var policyIds = []int64{}
|
||||
for _, policy := range policies {
|
||||
if policy.IsOn == 1 {
|
||||
if policy.IsOn {
|
||||
policyIds = append(policyIds, int64(policy.Id))
|
||||
}
|
||||
}
|
||||
@@ -92,7 +92,7 @@ func (this *StorageManager) Loop() error {
|
||||
}
|
||||
|
||||
if len(policy.Options) > 0 {
|
||||
err = json.Unmarshal([]byte(policy.Options), storage.Config())
|
||||
err = json.Unmarshal(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)
|
||||
@@ -101,6 +101,7 @@ func (this *StorageManager) Loop() error {
|
||||
}
|
||||
|
||||
storage.SetVersion(types.Int(policy.Version))
|
||||
storage.SetFirewallOnly(policy.FirewallOnly == 1)
|
||||
err := storage.Start()
|
||||
if err != nil {
|
||||
remotelogs.Error("ACCESS_LOG_STORAGE_MANAGER", "start policy '"+types.String(policyId)+"' failed: "+err.Error())
|
||||
@@ -110,12 +111,13 @@ func (this *StorageManager) Loop() error {
|
||||
remotelogs.Println("ACCESS_LOG_STORAGE_MANAGER", "restart policy '"+types.String(policyId)+"'")
|
||||
}
|
||||
} else {
|
||||
storage, err := this.createStorage(policy.Type, []byte(policy.Options))
|
||||
storage, err := this.createStorage(policy.Type, 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))
|
||||
storage.SetFirewallOnly(policy.FirewallOnly == 1)
|
||||
this.storageMap[policyId] = storage
|
||||
err = storage.Start()
|
||||
if err != nil {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package accesslogs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
@@ -95,7 +97,10 @@ func (this *SyslogStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
|
||||
args = append(args, "-S", "10240")
|
||||
|
||||
cmd := exec.Command(this.exe, args...)
|
||||
var cmd = exec.Command(this.exe, args...)
|
||||
var stderrBuffer = &bytes.Buffer{}
|
||||
cmd.Stderr = stderrBuffer
|
||||
|
||||
w, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -106,9 +111,12 @@ func (this *SyslogStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
}
|
||||
|
||||
for _, accessLog := range accessLogs {
|
||||
if this.firewallOnly && accessLog.FirewallPolicyId == 0 {
|
||||
continue
|
||||
}
|
||||
data, err := this.Marshal(accessLog)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
remotelogs.Error("ACCESS_LOG_POLICY_SYSLOG", "marshal accesslog failed: "+err.Error())
|
||||
continue
|
||||
}
|
||||
_, err = w.Write(data)
|
||||
@@ -118,14 +126,15 @@ func (this *SyslogStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
|
||||
_, err = w.Write([]byte("\n"))
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
remotelogs.Error("ACCESS_LOG_POLICY_SYSLOG", "write accesslog failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
_ = w.Close()
|
||||
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.New("send syslog failed: " + err.Error() + ", stderr: " + stderrBuffer.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -60,6 +60,9 @@ func (this *TCPStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
defer this.writeLocker.Unlock()
|
||||
|
||||
for _, accessLog := range accessLogs {
|
||||
if this.firewallOnly && accessLog.FirewallPolicyId == 0 {
|
||||
continue
|
||||
}
|
||||
data, err := this.Marshal(accessLog)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
|
||||
@@ -1,51 +1,108 @@
|
||||
package apps
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/sizes"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/files"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"github.com/iwind/TeaGo/utils/time"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type LogWriter struct {
|
||||
fileAppender *files.Appender
|
||||
fp *os.File
|
||||
c chan string
|
||||
}
|
||||
|
||||
func (this *LogWriter) Init() {
|
||||
// 创建目录
|
||||
dir := files.NewFile(Tea.LogDir())
|
||||
var dir = files.NewFile(Tea.LogDir())
|
||||
if !dir.Exists() {
|
||||
err := dir.Mkdir()
|
||||
if err != nil {
|
||||
log.Println("[error]" + err.Error())
|
||||
log.Println("[LOG]create log dir failed: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
logFile := files.NewFile(Tea.LogFile("run.log"))
|
||||
|
||||
// 打开要写入的日志文件
|
||||
appender, err := logFile.Appender()
|
||||
var logPath = Tea.LogFile("run.log")
|
||||
fp, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
log.Println("[LOG]open log file failed: " + err.Error())
|
||||
} else {
|
||||
this.fileAppender = appender
|
||||
this.fp = fp
|
||||
}
|
||||
|
||||
this.c = make(chan string, 1024)
|
||||
|
||||
// 异步写入文件
|
||||
var maxFileSize = 2 * sizes.G // 文件最大尺寸,超出此尺寸则清空
|
||||
if fp != nil {
|
||||
goman.New(func() {
|
||||
var totalSize int64 = 0
|
||||
stat, err := fp.Stat()
|
||||
if err == nil {
|
||||
totalSize = stat.Size()
|
||||
}
|
||||
|
||||
for message := range this.c {
|
||||
totalSize += int64(len(message))
|
||||
_, err := fp.WriteString(timeutil.Format("Y/m/d H:i:s ") + message + "\n")
|
||||
if err != nil {
|
||||
log.Println("[LOG]write log failed: " + err.Error())
|
||||
} else {
|
||||
// 如果太大则Truncate
|
||||
if totalSize > maxFileSize {
|
||||
_ = fp.Truncate(0)
|
||||
totalSize = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (this *LogWriter) Write(message string) {
|
||||
log.Println(message)
|
||||
backgroundEnv, _ := os.LookupEnv("EdgeBackground")
|
||||
if backgroundEnv != "on" {
|
||||
// 文件和行号
|
||||
var file string
|
||||
var line int
|
||||
if Tea.IsTesting() {
|
||||
var callDepth = 3
|
||||
var ok bool
|
||||
_, file, line, ok = runtime.Caller(callDepth)
|
||||
if ok {
|
||||
file = this.packagePath(file)
|
||||
}
|
||||
}
|
||||
|
||||
if this.fileAppender != nil {
|
||||
_, err := this.fileAppender.AppendString(timeutil.Format("Y/m/d H:i:s ") + message + "\n")
|
||||
if err != nil {
|
||||
log.Println("[error]" + err.Error())
|
||||
if len(file) > 0 {
|
||||
log.Println(message + " (" + file + ":" + strconv.Itoa(line) + ")")
|
||||
} else {
|
||||
log.Println(message)
|
||||
}
|
||||
}
|
||||
|
||||
this.c <- message
|
||||
}
|
||||
|
||||
func (this *LogWriter) Close() {
|
||||
if this.fileAppender != nil {
|
||||
_ = this.fileAppender.Close()
|
||||
if this.fp != nil {
|
||||
_ = this.fp.Close()
|
||||
}
|
||||
|
||||
close(this.c)
|
||||
}
|
||||
|
||||
func (this *LogWriter) packagePath(path string) string {
|
||||
var pieces = strings.Split(path, "/")
|
||||
if len(pieces) >= 2 {
|
||||
return strings.Join(pieces[len(pieces)-2:], "/")
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package configs
|
||||
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
"github.com/go-yaml/yaml"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"gopkg.in/yaml.v3"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package teaconst
|
||||
|
||||
const (
|
||||
Version = "0.4.3"
|
||||
Version = "0.4.10"
|
||||
|
||||
ProductName = "Edge API"
|
||||
ProcessName = "edge-api"
|
||||
@@ -18,10 +18,13 @@ const (
|
||||
|
||||
// 其他节点版本号,用来检测是否有需要升级的节点
|
||||
|
||||
NodeVersion = "0.4.3"
|
||||
UserNodeVersion = "0.3.1"
|
||||
NodeVersion = "0.4.10"
|
||||
UserNodeVersion = "0.3.6"
|
||||
AuthorityNodeVersion = "0.0.2"
|
||||
MonitorNodeVersion = "0.0.3"
|
||||
DNSNodeVersion = "0.2.1"
|
||||
ReportNodeVersion = "0.1.0"
|
||||
MonitorNodeVersion = "0.0.4"
|
||||
DNSNodeVersion = "0.2.4"
|
||||
ReportNodeVersion = "0.1.1"
|
||||
|
||||
// SQLVersion SQL版本号
|
||||
SQLVersion = "2"
|
||||
)
|
||||
|
||||
@@ -2,9 +2,18 @@
|
||||
|
||||
package teaconst
|
||||
|
||||
var (
|
||||
IsPlus = false
|
||||
MaxNodes int32 = 0
|
||||
NodeId int64 = 0
|
||||
Debug = false
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
IsPlus = false
|
||||
MaxNodes int32 = 0
|
||||
NodeId int64 = 0
|
||||
Debug = false
|
||||
InstanceCode = fmt.Sprintf("%x", sha1.Sum([]byte("INSTANCE"+types.String(time.Now().UnixNano())+"@"+types.String(rands.Int64()))))
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ package db
|
||||
import (
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
@@ -42,3 +43,13 @@ func TestDB_Instance(t *testing.T) {
|
||||
}
|
||||
time.Sleep(100 * time.Second)
|
||||
}
|
||||
|
||||
func TestDB_Reuse(t *testing.T) {
|
||||
var dao = models.NewVersionDAO()
|
||||
for i := 0; i < 20_000; i++ {
|
||||
_, _, err := dao.Query(nil).Attr("version", i).Reuse(true).FindOne()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package accounts
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@@ -79,7 +80,7 @@ func (this *UserAccountLogDAO) CountAccountLogs(tx *dbs.Tx, userId int64, accoun
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(userId IN (SELECT id FROM " + models.SharedUserDAO.Table + " WHERE state=1 AND (username LIKE :keyword OR fullname LIKE :keyword)) OR description LIKE :keyword)")
|
||||
query.Param("keyword", "%"+keyword+"%")
|
||||
query.Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
if len(eventType) > 0 {
|
||||
query.Attr("eventType", eventType)
|
||||
@@ -98,7 +99,7 @@ func (this *UserAccountLogDAO) ListAccountLogs(tx *dbs.Tx, userId int64, account
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(userId IN (SELECT id FROM " + models.SharedUserDAO.Table + " WHERE state=1 AND (username LIKE :keyword OR fullname LIKE :keyword)) OR description LIKE :keyword)")
|
||||
query.Param("keyword", "%"+keyword+"%")
|
||||
query.Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
if len(eventType) > 0 {
|
||||
query.Attr("eventType", eventType)
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
package accounts
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// UserAccountLog 用户账户日志
|
||||
type UserAccountLog struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
AccountId uint64 `field:"accountId"` // 账户ID
|
||||
Delta float64 `field:"delta"` // 操作余额的数量(可为负)
|
||||
DeltaFrozen float64 `field:"deltaFrozen"` // 操作冻结的数量(可为负)
|
||||
Total float64 `field:"total"` // 操作后余额
|
||||
TotalFrozen float64 `field:"totalFrozen"` // 操作后冻结余额
|
||||
EventType string `field:"eventType"` // 类型
|
||||
Description string `field:"description"` // 描述文字
|
||||
Day string `field:"day"` // YYYYMMDD
|
||||
CreatedAt uint64 `field:"createdAt"` // 时间
|
||||
Params string `field:"params"` // 参数
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
AccountId uint64 `field:"accountId"` // 账户ID
|
||||
Delta float64 `field:"delta"` // 操作余额的数量(可为负)
|
||||
DeltaFrozen float64 `field:"deltaFrozen"` // 操作冻结的数量(可为负)
|
||||
Total float64 `field:"total"` // 操作后余额
|
||||
TotalFrozen float64 `field:"totalFrozen"` // 操作后冻结余额
|
||||
EventType string `field:"eventType"` // 类型
|
||||
Description string `field:"description"` // 描述文字
|
||||
Day string `field:"day"` // YYYYMMDD
|
||||
CreatedAt uint64 `field:"createdAt"` // 时间
|
||||
Params dbs.JSON `field:"params"` // 参数
|
||||
}
|
||||
|
||||
type UserAccountLogOperator struct {
|
||||
|
||||
@@ -29,7 +29,7 @@ func init() {
|
||||
|
||||
// 创建认证信息
|
||||
func (this *ACMEAuthenticationDAO) CreateAuth(tx *dbs.Tx, taskId int64, domain string, token string, key string) error {
|
||||
op := NewACMEAuthenticationOperator()
|
||||
var op = NewACMEAuthenticationOperator()
|
||||
op.TaskId = taskId
|
||||
op.Domain = domain
|
||||
op.Token = token
|
||||
|
||||
@@ -3,7 +3,7 @@ package acme
|
||||
// ACMEProviderAccount ACME提供商
|
||||
type ACMEProviderAccount struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
ProviderCode string `field:"providerCode"` // 代号
|
||||
Error string `field:"error"` // 最后一条错误信息
|
||||
|
||||
@@ -125,11 +125,11 @@ func (this *ACMETaskDAO) CountAllEnabledACMETasks(tx *dbs.Tx, adminId int64, use
|
||||
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(domains LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("domains LIKE :keyword").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
|
||||
return query.State(ACMETaskStateEnabled).
|
||||
@@ -155,7 +155,7 @@ func (this *ACMETaskDAO) ListEnabledACMETasks(tx *dbs.Tx, adminId int64, userId
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(domains LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
_, err = query.
|
||||
State(ACMETaskStateEnabled).
|
||||
@@ -169,7 +169,7 @@ func (this *ACMETaskDAO) ListEnabledACMETasks(tx *dbs.Tx, adminId int64, userId
|
||||
|
||||
// CreateACMETask 创建任务
|
||||
func (this *ACMETaskDAO) CreateACMETask(tx *dbs.Tx, adminId int64, userId int64, authType acmeutils.AuthType, acmeUserId int64, dnsProviderId int64, dnsDomain string, domains []string, autoRenew bool, authURL string) (int64, error) {
|
||||
op := NewACMETaskOperator()
|
||||
var op = NewACMETaskOperator()
|
||||
op.AdminId = adminId
|
||||
op.UserId = userId
|
||||
op.AuthType = authType
|
||||
@@ -204,7 +204,7 @@ func (this *ACMETaskDAO) UpdateACMETask(tx *dbs.Tx, acmeTaskId int64, acmeUserId
|
||||
return errors.New("invalid acmeTaskId")
|
||||
}
|
||||
|
||||
op := NewACMETaskOperator()
|
||||
var op = NewACMETaskOperator()
|
||||
op.Id = acmeTaskId
|
||||
op.AcmeUserId = acmeUserId
|
||||
op.DnsProviderId = dnsProviderId
|
||||
@@ -240,7 +240,7 @@ func (this *ACMETaskDAO) UpdateACMETaskCert(tx *dbs.Tx, taskId int64, certId int
|
||||
return errors.New("invalid taskId")
|
||||
}
|
||||
|
||||
op := NewACMETaskOperator()
|
||||
var op = NewACMETaskOperator()
|
||||
op.Id = taskId
|
||||
op.CertId = certId
|
||||
err := this.Save(tx, op)
|
||||
@@ -271,7 +271,7 @@ func (this *ACMETaskDAO) runTaskWithoutLog(tx *dbs.Tx, taskId int64) (isOk bool,
|
||||
errMsg = "找不到要执行的任务"
|
||||
return
|
||||
}
|
||||
if task.IsOn != 1 {
|
||||
if !task.IsOn {
|
||||
errMsg = "任务没有启用"
|
||||
return
|
||||
}
|
||||
@@ -330,7 +330,7 @@ func (this *ACMETaskDAO) runTaskWithoutLog(tx *dbs.Tx, taskId int64) (isOk bool,
|
||||
})
|
||||
|
||||
if len(user.Registration) > 0 {
|
||||
err = remoteUser.SetRegistration([]byte(user.Registration))
|
||||
err = remoteUser.SetRegistration(user.Registration)
|
||||
if err != nil {
|
||||
errMsg = "设置注册信息时出错:" + err.Error()
|
||||
return
|
||||
@@ -453,7 +453,7 @@ func (this *ACMETaskDAO) runTaskWithoutLog(tx *dbs.Tx, taskId int64) (isOk bool,
|
||||
return
|
||||
}
|
||||
|
||||
err = models.SharedSSLCertDAO.UpdateCert(tx, resultCertId, cert.IsOn == 1, cert.Name, cert.Description, cert.ServerName, cert.IsCA == 1, certData, keyData, sslConfig.TimeBeginAt, sslConfig.TimeEndAt, sslConfig.DNSNames, sslConfig.CommonNames)
|
||||
err = models.SharedSSLCertDAO.UpdateCert(tx, resultCertId, cert.IsOn, cert.Name, cert.Description, cert.ServerName, cert.IsCA, certData, keyData, sslConfig.TimeBeginAt, sslConfig.TimeEndAt, sslConfig.DNSNames, sslConfig.CommonNames)
|
||||
if err != nil {
|
||||
errMsg = "证书生成成功,但是修改数据库中的证书信息时出错:" + err.Error()
|
||||
return
|
||||
|
||||
@@ -29,7 +29,7 @@ func init() {
|
||||
|
||||
// 生成日志
|
||||
func (this *ACMETaskLogDAO) CreateACMETaskLog(tx *dbs.Tx, taskId int64, isOk bool, errMsg string) error {
|
||||
op := NewACMETaskLogOperator()
|
||||
var op = NewACMETaskLogOperator()
|
||||
op.TaskId = taskId
|
||||
op.Error = errMsg
|
||||
op.IsOk = isOk
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package acme
|
||||
|
||||
// ACME任务运行日志
|
||||
// ACMETaskLog ACME任务运行日志
|
||||
type ACMETaskLog struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
TaskId uint64 `field:"taskId"` // 任务ID
|
||||
IsOk uint8 `field:"isOk"` // 是否成功
|
||||
IsOk bool `field:"isOk"` // 是否成功
|
||||
Error string `field:"error"` // 错误信息
|
||||
CreatedAt uint64 `field:"createdAt"` // 运行时间
|
||||
}
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
package acme
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// ACMETask ACME任务
|
||||
type ACMETask struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
AcmeUserId uint32 `field:"acmeUserId"` // ACME用户ID
|
||||
DnsDomain string `field:"dnsDomain"` // DNS主域名
|
||||
DnsProviderId uint64 `field:"dnsProviderId"` // DNS服务商
|
||||
Domains string `field:"domains"` // 证书域名
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
CertId uint64 `field:"certId"` // 生成的证书ID
|
||||
AutoRenew uint8 `field:"autoRenew"` // 是否自动更新
|
||||
AuthType string `field:"authType"` // 认证类型
|
||||
AuthURL string `field:"authURL"` // 认证URL
|
||||
Id uint64 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
AcmeUserId uint32 `field:"acmeUserId"` // ACME用户ID
|
||||
DnsDomain string `field:"dnsDomain"` // DNS主域名
|
||||
DnsProviderId uint64 `field:"dnsProviderId"` // DNS服务商
|
||||
Domains dbs.JSON `field:"domains"` // 证书域名
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
CertId uint64 `field:"certId"` // 生成的证书ID
|
||||
AutoRenew uint8 `field:"autoRenew"` // 是否自动更新
|
||||
AuthType string `field:"authType"` // 认证类型
|
||||
AuthURL string `field:"authURL"` // 认证URL
|
||||
}
|
||||
|
||||
type ACMETaskOperator struct {
|
||||
|
||||
@@ -5,13 +5,13 @@ import (
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
)
|
||||
|
||||
// 将域名解析成字符串数组
|
||||
// DecodeDomains 将域名解析成字符串数组
|
||||
func (this *ACMETask) DecodeDomains() []string {
|
||||
if len(this.Domains) == 0 || this.Domains == "null" {
|
||||
if len(this.Domains) == 0 {
|
||||
return nil
|
||||
}
|
||||
result := []string{}
|
||||
err := json.Unmarshal([]byte(this.Domains), &result)
|
||||
err := json.Unmarshal(this.Domains, &result)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return nil
|
||||
|
||||
@@ -83,7 +83,7 @@ func (this *ACMEUserDAO) CreateACMEUser(tx *dbs.Tx, adminId int64, userId int64,
|
||||
}
|
||||
privateKeyText := base64.StdEncoding.EncodeToString(privateKeyData)
|
||||
|
||||
op := NewACMEUserOperator()
|
||||
var op = NewACMEUserOperator()
|
||||
op.AdminId = adminId
|
||||
op.UserId = userId
|
||||
op.ProviderCode = providerCode
|
||||
@@ -104,7 +104,7 @@ func (this *ACMEUserDAO) UpdateACMEUser(tx *dbs.Tx, acmeUserId int64, descriptio
|
||||
if acmeUserId <= 0 {
|
||||
return errors.New("invalid acmeUserId")
|
||||
}
|
||||
op := NewACMEUserOperator()
|
||||
var op = NewACMEUserOperator()
|
||||
op.Id = acmeUserId
|
||||
op.Description = description
|
||||
err := this.Save(tx, op)
|
||||
@@ -116,7 +116,7 @@ func (this *ACMEUserDAO) UpdateACMEUserRegistration(tx *dbs.Tx, acmeUserId int64
|
||||
if acmeUserId <= 0 {
|
||||
return errors.New("invalid acmeUserId")
|
||||
}
|
||||
op := NewACMEUserOperator()
|
||||
var op = NewACMEUserOperator()
|
||||
op.Id = acmeUserId
|
||||
op.Registration = registrationJSON
|
||||
err := this.Save(tx, op)
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
package acme
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// ACMEUser ACME用户
|
||||
type ACMEUser struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
PrivateKey string `field:"privateKey"` // 私钥
|
||||
Email string `field:"email"` // E-mail
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
Description string `field:"description"` // 备注介绍
|
||||
Registration string `field:"registration"` // 注册信息
|
||||
ProviderCode string `field:"providerCode"` // 服务商代号
|
||||
AccountId uint64 `field:"accountId"` // 提供商ID
|
||||
Id uint64 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
PrivateKey string `field:"privateKey"` // 私钥
|
||||
Email string `field:"email"` // E-mail
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
Description string `field:"description"` // 备注介绍
|
||||
Registration dbs.JSON `field:"registration"` // 注册信息
|
||||
ProviderCode string `field:"providerCode"` // 服务商代号
|
||||
AccountId uint64 `field:"accountId"` // 提供商ID
|
||||
}
|
||||
|
||||
type ACMEUserOperator struct {
|
||||
|
||||
@@ -115,7 +115,7 @@ func (this *AdminDAO) UpdateAdminPassword(tx *dbs.Tx, adminId int64, password st
|
||||
if adminId <= 0 {
|
||||
return errors.New("invalid adminId")
|
||||
}
|
||||
op := NewAdminOperator()
|
||||
var op = NewAdminOperator()
|
||||
op.Id = adminId
|
||||
op.Password = stringutil.Md5(password)
|
||||
err := this.Save(tx, op)
|
||||
@@ -124,7 +124,7 @@ func (this *AdminDAO) UpdateAdminPassword(tx *dbs.Tx, adminId int64, password st
|
||||
|
||||
// CreateAdmin 创建管理员
|
||||
func (this *AdminDAO) CreateAdmin(tx *dbs.Tx, username string, canLogin bool, password string, fullname string, isSuper bool, modulesJSON []byte) (int64, error) {
|
||||
op := NewAdminOperator()
|
||||
var op = NewAdminOperator()
|
||||
op.IsOn = true
|
||||
op.State = AdminStateEnabled
|
||||
op.Username = username
|
||||
@@ -149,7 +149,7 @@ func (this *AdminDAO) UpdateAdminInfo(tx *dbs.Tx, adminId int64, fullname string
|
||||
if adminId <= 0 {
|
||||
return errors.New("invalid adminId")
|
||||
}
|
||||
op := NewAdminOperator()
|
||||
var op = NewAdminOperator()
|
||||
op.Id = adminId
|
||||
op.Fullname = fullname
|
||||
err := this.Save(tx, op)
|
||||
@@ -161,7 +161,7 @@ func (this *AdminDAO) UpdateAdmin(tx *dbs.Tx, adminId int64, username string, ca
|
||||
if adminId <= 0 {
|
||||
return errors.New("invalid adminId")
|
||||
}
|
||||
op := NewAdminOperator()
|
||||
var op = NewAdminOperator()
|
||||
op.Id = adminId
|
||||
op.Fullname = fullname
|
||||
op.Username = username
|
||||
@@ -198,7 +198,7 @@ func (this *AdminDAO) UpdateAdminLogin(tx *dbs.Tx, adminId int64, username strin
|
||||
if adminId <= 0 {
|
||||
return errors.New("invalid adminId")
|
||||
}
|
||||
op := NewAdminOperator()
|
||||
var op = NewAdminOperator()
|
||||
op.Id = adminId
|
||||
op.Username = username
|
||||
if len(password) > 0 {
|
||||
@@ -213,7 +213,7 @@ func (this *AdminDAO) UpdateAdminModules(tx *dbs.Tx, adminId int64, allowModules
|
||||
if adminId <= 0 {
|
||||
return errors.New("invalid adminId")
|
||||
}
|
||||
op := NewAdminOperator()
|
||||
var op = NewAdminOperator()
|
||||
op.Id = adminId
|
||||
op.Modules = allowModulesJSON
|
||||
err := this.Save(tx, op)
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// Admin 管理员
|
||||
type Admin struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Username string `field:"username"` // 用户名
|
||||
Password string `field:"password"` // 密码
|
||||
Fullname string `field:"fullname"` // 全名
|
||||
IsSuper uint8 `field:"isSuper"` // 是否为超级管理员
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
Modules string `field:"modules"` // 允许的模块
|
||||
CanLogin uint8 `field:"canLogin"` // 是否可以登录
|
||||
Theme string `field:"theme"` // 模板设置
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Username string `field:"username"` // 用户名
|
||||
Password string `field:"password"` // 密码
|
||||
Fullname string `field:"fullname"` // 全名
|
||||
IsSuper bool `field:"isSuper"` // 是否为超级管理员
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
Modules dbs.JSON `field:"modules"` // 允许的模块
|
||||
CanLogin uint8 `field:"canLogin"` // 是否可以登录
|
||||
Theme string `field:"theme"` // 模板设置
|
||||
}
|
||||
|
||||
type AdminOperator struct {
|
||||
|
||||
@@ -56,7 +56,7 @@ func (this *APIAccessTokenDAO) GenerateAccessToken(tx *dbs.Tx, adminId int64, us
|
||||
token = rands.String(128) // TODO 增强安全性,将来使用 base64_encode(encrypt(salt+random)) 算法来代替
|
||||
expiresAt = time.Now().Unix() + 7200
|
||||
|
||||
op := NewAPIAccessTokenOperator()
|
||||
var op = NewAPIAccessTokenOperator()
|
||||
|
||||
if accessToken != nil {
|
||||
op.Id = accessToken.(*APIAccessToken).Id
|
||||
|
||||
@@ -3,6 +3,8 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/configs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@@ -49,16 +51,29 @@ func (this *APINodeDAO) EnableAPINode(tx *dbs.Tx, id int64) error {
|
||||
Pk(id).
|
||||
Set("state", APINodeStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, id)
|
||||
}
|
||||
|
||||
// DisableAPINode 禁用条目
|
||||
func (this *APINodeDAO) DisableAPINode(tx *dbs.Tx, id int64) error {
|
||||
func (this *APINodeDAO) DisableAPINode(tx *dbs.Tx, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Pk(nodeId).
|
||||
Set("state", APINodeStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = this.NotifyUpdate(tx, nodeId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除运行日志
|
||||
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleAPI, nodeId)
|
||||
}
|
||||
|
||||
// FindEnabledAPINode 查找启用中的条目
|
||||
@@ -119,7 +134,7 @@ func (this *APINodeDAO) CreateAPINode(tx *dbs.Tx, name string, description strin
|
||||
return
|
||||
}
|
||||
|
||||
op := NewAPINodeOperator()
|
||||
var op = NewAPINodeOperator()
|
||||
op.IsOn = isOn
|
||||
op.UniqueId = uniqueId
|
||||
op.Secret = secret
|
||||
@@ -149,16 +164,33 @@ func (this *APINodeDAO) CreateAPINode(tx *dbs.Tx, name string, description strin
|
||||
return
|
||||
}
|
||||
|
||||
err = this.NotifyUpdate(tx, types.Int64(op.Id))
|
||||
if err != nil {
|
||||
remotelogs.Error("API_NODE_DAO", err.Error())
|
||||
}
|
||||
|
||||
return types.Int64(op.Id), nil
|
||||
}
|
||||
|
||||
// UpdateAPINode 修改API节点
|
||||
func (this *APINodeDAO) UpdateAPINode(tx *dbs.Tx, nodeId int64, name string, description string, httpJSON []byte, httpsJSON []byte, restIsOn bool, restHTTPJSON []byte, restHTTPSJSON []byte, accessAddrsJSON []byte, isOn bool) error {
|
||||
func (this *APINodeDAO) UpdateAPINode(tx *dbs.Tx, nodeId int64, name string, description string, httpJSON []byte, httpsJSON []byte, restIsOn bool, restHTTPJSON []byte, restHTTPSJSON []byte, accessAddrsJSON []byte, isOn bool, isPrimary bool) error {
|
||||
if nodeId <= 0 {
|
||||
return errors.New("invalid nodeId")
|
||||
}
|
||||
|
||||
op := NewAPINodeOperator()
|
||||
// 取消别的Primary
|
||||
if isPrimary {
|
||||
err := this.Query(tx).
|
||||
Neq("id", nodeId).
|
||||
Attr("isPrimary", true).
|
||||
Set("isPrimary", false).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var op = NewAPINodeOperator()
|
||||
op.Id = nodeId
|
||||
op.Name = name
|
||||
op.Description = description
|
||||
@@ -191,8 +223,13 @@ func (this *APINodeDAO) UpdateAPINode(tx *dbs.Tx, nodeId int64, name string, des
|
||||
op.AccessAddrs = "[]"
|
||||
}
|
||||
|
||||
op.IsPrimary = isPrimary
|
||||
|
||||
err := this.Save(tx, op)
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, nodeId)
|
||||
}
|
||||
|
||||
// FindAllEnabledAPINodes 列出所有可用API节点
|
||||
@@ -294,23 +331,6 @@ func (this *APINodeDAO) UpdateAPINodeStatus(tx *dbs.Tx, apiNodeId int64, statusJ
|
||||
return err
|
||||
}
|
||||
|
||||
// 生成唯一ID
|
||||
func (this *APINodeDAO) genUniqueId(tx *dbs.Tx) (string, error) {
|
||||
for {
|
||||
uniqueId := rands.HexString(32)
|
||||
ok, err := this.Query(tx).
|
||||
Attr("uniqueId", uniqueId).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
return uniqueId, nil
|
||||
}
|
||||
}
|
||||
|
||||
// CountAllLowerVersionNodes 计算所有节点中低于某个版本的节点数量
|
||||
func (this *APINodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
@@ -384,3 +404,114 @@ func (this *APINodeDAO) FindAllEnabledAPIAccessIPs(tx *dbs.Tx, cacheMap *utils.C
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// CheckAPINodeIsPrimary 检查当前节点是否为Primary节点
|
||||
func (this *APINodeDAO) CheckAPINodeIsPrimary(tx *dbs.Tx) (bool, error) {
|
||||
config, err := configs.SharedAPIConfig()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
isPrimary, err := this.Query(tx).
|
||||
State(APINodeStateEnabled).
|
||||
Attr("uniqueId", config.NodeId).
|
||||
Attr("isPrimary", true).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if isPrimary {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// 检查是否有别的Primary节点
|
||||
count, err := this.Query(tx).
|
||||
State(APINodeStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Attr("isPrimary", true).
|
||||
Count()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if count == 0 {
|
||||
err = this.ResetPrimaryAPINode(tx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// CheckAPINodeIsPrimaryWithoutErr 检查当前节点是否为Primary节点,并忽略错误
|
||||
func (this *APINodeDAO) CheckAPINodeIsPrimaryWithoutErr() bool {
|
||||
b, err := this.CheckAPINodeIsPrimary(nil)
|
||||
return b && err == nil
|
||||
}
|
||||
|
||||
// ResetPrimaryAPINode 重置Primary节点
|
||||
func (this *APINodeDAO) ResetPrimaryAPINode(tx *dbs.Tx) error {
|
||||
// 当前是否有Primary节点
|
||||
apiNode, err := this.Query(tx).
|
||||
State(APINodeStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Attr("isPrimary", true).
|
||||
Find()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if apiNode == nil {
|
||||
// 选择一个作为Primary
|
||||
// TODO 将来需要考虑API节点离线的情况
|
||||
apiNodeId, err := this.Query(tx).
|
||||
State(APINodeStateEnabled).
|
||||
Attr("isOn", true).
|
||||
ResultPk().
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if apiNodeId > 0 {
|
||||
err = this.Query(tx).
|
||||
Pk(apiNodeId).
|
||||
Set("isPrimary", true).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知变更
|
||||
func (this *APINodeDAO) NotifyUpdate(tx *dbs.Tx, apiNodeId int64) error {
|
||||
// suppress IDE warning
|
||||
_ = apiNodeId
|
||||
|
||||
err := this.ResetPrimaryAPINode(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 生成唯一ID
|
||||
func (this *APINodeDAO) genUniqueId(tx *dbs.Tx) (string, error) {
|
||||
for {
|
||||
uniqueId := rands.HexString(32)
|
||||
ok, err := this.Query(tx).
|
||||
Attr("uniqueId", uniqueId).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
return uniqueId, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,16 @@ func TestAPINodeDAO_FindAllEnabledAPIAccessIPs(t *testing.T) {
|
||||
t.Log(NewAPINodeDAO().FindAllEnabledAPIAccessIPs(nil, cacheMap))
|
||||
}
|
||||
|
||||
func TestAPINodeDAO_CheckAPINodeIsPrimary(t *testing.T) {
|
||||
var dao = NewAPINodeDAO()
|
||||
t.Log(dao.CheckAPINodeIsPrimary(nil))
|
||||
}
|
||||
|
||||
func TestAPINodeDAO_ResetPrimaryAPINode(t *testing.T) {
|
||||
var dao = NewAPINodeDAO()
|
||||
t.Log(dao.ResetPrimaryAPINode(nil))
|
||||
}
|
||||
|
||||
func BenchmarkAPINodeDAO_New(b *testing.B) {
|
||||
runtime.GOMAXPROCS(1)
|
||||
for i := 0; i < b.N; i++ {
|
||||
|
||||
@@ -1,26 +1,29 @@
|
||||
package models
|
||||
|
||||
// API节点
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// APINode API节点
|
||||
type APINode struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
ClusterId uint32 `field:"clusterId"` // 专用集群ID
|
||||
UniqueId string `field:"uniqueId"` // 唯一ID
|
||||
Secret string `field:"secret"` // 密钥
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Http string `field:"http"` // 监听的HTTP配置
|
||||
Https string `field:"https"` // 监听的HTTPS配置
|
||||
RestIsOn uint8 `field:"restIsOn"` // 是否开放REST
|
||||
RestHTTP string `field:"restHTTP"` // REST HTTP配置
|
||||
RestHTTPS string `field:"restHTTPS"` // REST HTTPS配置
|
||||
AccessAddrs string `field:"accessAddrs"` // 外部访问地址
|
||||
Order uint32 `field:"order"` // 排序
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
Weight uint32 `field:"weight"` // 权重
|
||||
Status string `field:"status"` // 运行状态
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
ClusterId uint32 `field:"clusterId"` // 专用集群ID
|
||||
UniqueId string `field:"uniqueId"` // 唯一ID
|
||||
Secret string `field:"secret"` // 密钥
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Http dbs.JSON `field:"http"` // 监听的HTTP配置
|
||||
Https dbs.JSON `field:"https"` // 监听的HTTPS配置
|
||||
RestIsOn uint8 `field:"restIsOn"` // 是否开放REST
|
||||
RestHTTP dbs.JSON `field:"restHTTP"` // REST HTTP配置
|
||||
RestHTTPS dbs.JSON `field:"restHTTPS"` // REST HTTPS配置
|
||||
AccessAddrs dbs.JSON `field:"accessAddrs"` // 外部访问地址
|
||||
Order uint32 `field:"order"` // 排序
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
Weight uint32 `field:"weight"` // 权重
|
||||
Status dbs.JSON `field:"status"` // 运行状态
|
||||
IsPrimary bool `field:"isPrimary"` // 是否为主API节点
|
||||
}
|
||||
|
||||
type APINodeOperator struct {
|
||||
@@ -43,6 +46,7 @@ type APINodeOperator struct {
|
||||
AdminId interface{} // 管理员ID
|
||||
Weight interface{} // 权重
|
||||
Status interface{} // 运行状态
|
||||
IsPrimary interface{} // 是否为主API节点
|
||||
}
|
||||
|
||||
func NewAPINodeOperator() *APINodeOperator {
|
||||
|
||||
@@ -13,7 +13,7 @@ func (this *APINode) DecodeHTTP() (*serverconfigs.HTTPProtocolConfig, error) {
|
||||
return nil, nil
|
||||
}
|
||||
config := &serverconfigs.HTTPProtocolConfig{}
|
||||
err := json.Unmarshal([]byte(this.Http), config)
|
||||
err := json.Unmarshal(this.Http, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -32,7 +32,7 @@ func (this *APINode) DecodeHTTPS(tx *dbs.Tx, cacheMap *utils.CacheMap) (*serverc
|
||||
return nil, nil
|
||||
}
|
||||
config := &serverconfigs.HTTPSProtocolConfig{}
|
||||
err := json.Unmarshal([]byte(this.Https), config)
|
||||
err := json.Unmarshal(this.Https, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -70,7 +70,7 @@ func (this *APINode) DecodeAccessAddrs() ([]*serverconfigs.NetworkAddressConfig,
|
||||
}
|
||||
|
||||
addrConfigs := []*serverconfigs.NetworkAddressConfig{}
|
||||
err := json.Unmarshal([]byte(this.AccessAddrs), &addrConfigs)
|
||||
err := json.Unmarshal(this.AccessAddrs, &addrConfigs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -105,7 +105,7 @@ func (this *APINode) DecodeRestHTTP() (*serverconfigs.HTTPProtocolConfig, error)
|
||||
return nil, nil
|
||||
}
|
||||
config := &serverconfigs.HTTPProtocolConfig{}
|
||||
err := json.Unmarshal([]byte(this.RestHTTP), config)
|
||||
err := json.Unmarshal(this.RestHTTP, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -130,7 +130,7 @@ func (this *APINode) DecodeRestHTTPS(tx *dbs.Tx, cacheMap *utils.CacheMap) (*ser
|
||||
return nil, nil
|
||||
}
|
||||
config := &serverconfigs.HTTPSProtocolConfig{}
|
||||
err := json.Unmarshal([]byte(this.RestHTTPS), config)
|
||||
err := json.Unmarshal(this.RestHTTPS, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ func (this *ApiTokenDAO) FindEnabledTokenWithRole(tx *dbs.Tx, role string) (*Api
|
||||
|
||||
// CreateAPIToken 保存API Token
|
||||
func (this *ApiTokenDAO) CreateAPIToken(tx *dbs.Tx, nodeId string, secret string, role nodeconfigs.NodeRole) error {
|
||||
op := NewApiTokenOperator()
|
||||
var op = NewApiTokenOperator()
|
||||
op.NodeId = nodeId
|
||||
op.Secret = secret
|
||||
op.Role = role
|
||||
|
||||
@@ -42,7 +42,7 @@ func (this *AuthorityKeyDAO) UpdateKey(tx *dbs.Tx, value string, dayFrom string,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op := NewAuthorityKeyOperator()
|
||||
var op = NewAuthorityKeyOperator()
|
||||
if one != nil {
|
||||
op.Id = one.(*AuthorityKey).Id
|
||||
}
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
package authority
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// AuthorityKey 企业版认证信息
|
||||
type AuthorityKey struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Value string `field:"value"` // Key值
|
||||
DayFrom string `field:"dayFrom"` // 开始日期
|
||||
DayTo string `field:"dayTo"` // 结束日期
|
||||
Hostname string `field:"hostname"` // Hostname
|
||||
MacAddresses string `field:"macAddresses"` // MAC地址
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 创建/修改时间
|
||||
Company string `field:"company"` // 公司组织
|
||||
Id uint32 `field:"id"` // ID
|
||||
Value string `field:"value"` // Key值
|
||||
DayFrom string `field:"dayFrom"` // 开始日期
|
||||
DayTo string `field:"dayTo"` // 结束日期
|
||||
Hostname string `field:"hostname"` // Hostname
|
||||
MacAddresses dbs.JSON `field:"macAddresses"` // MAC地址
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 创建/修改时间
|
||||
Company string `field:"company"` // 公司组织
|
||||
}
|
||||
|
||||
type AuthorityKeyOperator struct {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package authority
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
@@ -119,7 +120,7 @@ func (this *AuthorityNodeDAO) CreateAuthorityNode(tx *dbs.Tx, name string, descr
|
||||
return
|
||||
}
|
||||
|
||||
op := NewAuthorityNodeOperator()
|
||||
var op = NewAuthorityNodeOperator()
|
||||
op.IsOn = isOn
|
||||
op.UniqueId = uniqueId
|
||||
op.Secret = secret
|
||||
@@ -140,7 +141,7 @@ func (this *AuthorityNodeDAO) UpdateAuthorityNode(tx *dbs.Tx, nodeId int64, name
|
||||
return errors.New("invalid nodeId")
|
||||
}
|
||||
|
||||
op := NewAuthorityNodeOperator()
|
||||
var op = NewAuthorityNodeOperator()
|
||||
op.Id = nodeId
|
||||
op.Name = name
|
||||
op.Description = description
|
||||
@@ -188,13 +189,19 @@ func (this *AuthorityNodeDAO) GenUniqueId(tx *dbs.Tx) (string, error) {
|
||||
}
|
||||
|
||||
// UpdateNodeStatus 更改节点状态
|
||||
func (this *AuthorityNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, statusJSON []byte) error {
|
||||
if statusJSON == nil {
|
||||
func (this *AuthorityNodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, nodeStatus *nodeconfigs.NodeStatus) error {
|
||||
if nodeStatus == nil {
|
||||
return nil
|
||||
}
|
||||
_, err := this.Query(tx).
|
||||
|
||||
nodeStatusJSON, err := json.Marshal(nodeStatus)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Pk(nodeId).
|
||||
Set("status", string(statusJSON)).
|
||||
Set("status", nodeStatusJSON).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
package authority
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// AuthorityNode 监控节点
|
||||
type AuthorityNode struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
UniqueId string `field:"uniqueId"` // 唯一ID
|
||||
Secret string `field:"secret"` // 密钥
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Order uint32 `field:"order"` // 排序
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
Weight uint32 `field:"weight"` // 权重
|
||||
Status string `field:"status"` // 运行状态
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
UniqueId string `field:"uniqueId"` // 唯一ID
|
||||
Secret string `field:"secret"` // 密钥
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Order uint32 `field:"order"` // 排序
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
Weight uint32 `field:"weight"` // 权重
|
||||
Status dbs.JSON `field:"status"` // 运行状态
|
||||
}
|
||||
|
||||
type AuthorityNodeOperator struct {
|
||||
|
||||
@@ -125,7 +125,7 @@ func (this *ClientBrowserDAO) CreateBrowser(tx *dbs.Tx, browserName string) (int
|
||||
return browserId, nil
|
||||
}
|
||||
|
||||
op := NewClientBrowserOperator()
|
||||
var op = NewClientBrowserOperator()
|
||||
op.Name = browserName
|
||||
codes := []string{browserName}
|
||||
codesJSON, err := json.Marshal(codes)
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package models
|
||||
|
||||
// 终端浏览器信息
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// ClientBrowser 终端浏览器信息
|
||||
type ClientBrowser struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Name string `field:"name"` // 浏览器名称
|
||||
Codes string `field:"codes"` // 代号
|
||||
State uint8 `field:"state"` // 状态
|
||||
Id uint32 `field:"id"` // ID
|
||||
Name string `field:"name"` // 浏览器名称
|
||||
Codes dbs.JSON `field:"codes"` // 代号
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type ClientBrowserOperator struct {
|
||||
|
||||
@@ -125,7 +125,7 @@ func (this *ClientSystemDAO) CreateSystem(tx *dbs.Tx, systemName string) (int64,
|
||||
return systemId, nil
|
||||
}
|
||||
|
||||
op := NewClientSystemOperator()
|
||||
var op = NewClientSystemOperator()
|
||||
op.Name = systemName
|
||||
|
||||
codes := []string{systemName}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package models
|
||||
|
||||
// 终端操作系统信息
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// ClientSystem 终端操作系统信息
|
||||
type ClientSystem struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Name string `field:"name"` // 系统名称
|
||||
Codes string `field:"codes"` // 代号
|
||||
State uint8 `field:"state"` //
|
||||
Id uint32 `field:"id"` // ID
|
||||
Name string `field:"name"` // 系统名称
|
||||
Codes dbs.JSON `field:"codes"` // 代号
|
||||
State uint8 `field:"state"` //
|
||||
}
|
||||
|
||||
type ClientSystemOperator struct {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/base64"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/encrypt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -49,12 +50,17 @@ func (this *DBNodeDAO) EnableDBNode(tx *dbs.Tx, id int64) error {
|
||||
}
|
||||
|
||||
// DisableDBNode 禁用条目
|
||||
func (this *DBNodeDAO) DisableDBNode(tx *dbs.Tx, id int64) error {
|
||||
func (this *DBNodeDAO) DisableDBNode(tx *dbs.Tx, nodeId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Pk(nodeId).
|
||||
Set("state", DBNodeStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除运行日志
|
||||
return SharedNodeLogDAO.DeleteNodeLogs(tx, nodeconfigs.NodeRoleDatabase, nodeId)
|
||||
}
|
||||
|
||||
// FindEnabledDBNode 查找启用中的条目
|
||||
@@ -103,7 +109,7 @@ func (this *DBNodeDAO) ListEnabledNodes(tx *dbs.Tx, offset int64, size int64) (r
|
||||
|
||||
// CreateDBNode 创建节点
|
||||
func (this *DBNodeDAO) CreateDBNode(tx *dbs.Tx, isOn bool, name string, description string, host string, port int32, database string, username string, password string, charset string) (int64, error) {
|
||||
op := NewDBNodeOperator()
|
||||
var op = NewDBNodeOperator()
|
||||
op.State = NodeStateEnabled
|
||||
op.IsOn = isOn
|
||||
op.Name = name
|
||||
@@ -126,7 +132,7 @@ func (this *DBNodeDAO) UpdateNode(tx *dbs.Tx, nodeId int64, isOn bool, name stri
|
||||
if nodeId <= 0 {
|
||||
return errors.New("invalid nodeId")
|
||||
}
|
||||
op := NewDBNodeOperator()
|
||||
var op = NewDBNodeOperator()
|
||||
op.Id = nodeId
|
||||
op.IsOn = isOn
|
||||
op.Name = name
|
||||
|
||||
@@ -29,8 +29,7 @@ type httpAccessLogDefinition struct {
|
||||
}
|
||||
|
||||
// HTTP服务访问
|
||||
var httpAccessLogDAOMapping = map[int64]*HTTPAccessLogDAOWrapper{} // dbNodeId => DAO
|
||||
var httpAccessLogTableMapping = map[string]*httpAccessLogDefinition{} // tableName_crc(dsn) => true
|
||||
var httpAccessLogDAOMapping = map[int64]*HTTPAccessLogDAOWrapper{} // dbNodeId => DAO
|
||||
|
||||
// DNS服务访问
|
||||
var nsAccessLogDAOMapping = map[int64]*NSAccessLogDAOWrapper{} // dbNodeId => DAO
|
||||
@@ -57,6 +56,25 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
func AllAccessLogDBs() []*dbs.DB {
|
||||
accessLogLocker.Lock()
|
||||
defer accessLogLocker.Unlock()
|
||||
|
||||
var result = []*dbs.DB{}
|
||||
for _, db := range accessLogDBMapping {
|
||||
result = append(result, db)
|
||||
}
|
||||
|
||||
if len(result) == 0 {
|
||||
db, _ := dbs.Default()
|
||||
if db != nil {
|
||||
result = append(result, db)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// 获取获取DAO
|
||||
func randomHTTPAccessLogDAO() (dao *HTTPAccessLogDAOWrapper) {
|
||||
accessLogLocker.RLock()
|
||||
@@ -86,36 +104,6 @@ func randomNSAccessLogDAO() (dao *NSAccessLogDAOWrapper) {
|
||||
return
|
||||
}
|
||||
|
||||
// 检查表格是否存在
|
||||
func findHTTPAccessLogTableName(db *dbs.DB, day string) (tableName string, hasRemoteAddr bool, hasDomain bool, ok bool, err error) {
|
||||
if !regexp.MustCompile(`^\d{8}$`).MatchString(day) {
|
||||
err = errors.New("invalid day '" + day + "', should be YYYYMMDD")
|
||||
return
|
||||
}
|
||||
|
||||
config, err := db.Config()
|
||||
if err != nil {
|
||||
return "", false, false, false, err
|
||||
}
|
||||
|
||||
tableName = "edgeHTTPAccessLogs_" + day
|
||||
cacheKey := tableName + "_" + fmt.Sprintf("%d", crc32.ChecksumIEEE([]byte(config.Dsn)))
|
||||
|
||||
accessLogLocker.RLock()
|
||||
def, ok := httpAccessLogTableMapping[cacheKey]
|
||||
accessLogLocker.RUnlock()
|
||||
if ok {
|
||||
return tableName, def.HasRemoteAddr, def.HasDomain, true, nil
|
||||
}
|
||||
|
||||
def, err = findHTTPAccessLogTable(db, day, false)
|
||||
if err != nil {
|
||||
return tableName, false, false, false, err
|
||||
}
|
||||
|
||||
return tableName, def.HasRemoteAddr, def.HasDomain, def.Exists, nil
|
||||
}
|
||||
|
||||
func findNSAccessLogTableName(db *dbs.DB, day string) (tableName string, ok bool, err error) {
|
||||
if !regexp.MustCompile(`^\d{8}$`).MatchString(day) {
|
||||
err = errors.New("invalid day '" + day + "', should be YYYYMMDD")
|
||||
@@ -145,75 +133,6 @@ func findNSAccessLogTableName(db *dbs.DB, day string) (tableName string, ok bool
|
||||
return tableName, utils.ContainsStringInsensitive(tableNames, tableName), nil
|
||||
}
|
||||
|
||||
// 根据日期获取表名
|
||||
func findHTTPAccessLogTable(db *dbs.DB, day string, force bool) (*httpAccessLogDefinition, error) {
|
||||
config, err := db.Config()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tableName := "edgeHTTPAccessLogs_" + day
|
||||
cacheKey := tableName + "_" + fmt.Sprintf("%d", crc32.ChecksumIEEE([]byte(config.Dsn)))
|
||||
|
||||
if !force {
|
||||
accessLogLocker.RLock()
|
||||
definition, ok := httpAccessLogTableMapping[cacheKey]
|
||||
accessLogLocker.RUnlock()
|
||||
if ok {
|
||||
return definition, nil
|
||||
}
|
||||
}
|
||||
|
||||
tableNames, err := db.TableNames()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if utils.ContainsStringInsensitive(tableNames, tableName) {
|
||||
table, err := db.FindTable(tableName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
accessLogLocker.Lock()
|
||||
var definition = &httpAccessLogDefinition{
|
||||
Name: tableName,
|
||||
HasRemoteAddr: table.FindFieldWithName("remoteAddr") != nil,
|
||||
HasDomain: table.FindFieldWithName("domain") != nil,
|
||||
Exists: true,
|
||||
}
|
||||
httpAccessLogTableMapping[cacheKey] = definition
|
||||
accessLogLocker.Unlock()
|
||||
return definition, nil
|
||||
}
|
||||
|
||||
if !force {
|
||||
return &httpAccessLogDefinition{
|
||||
Name: tableName,
|
||||
HasRemoteAddr: true,
|
||||
HasDomain: true,
|
||||
Exists: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 创建表格
|
||||
_, err = db.Exec("CREATE TABLE `" + tableName + "` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `serverId` int(11) unsigned DEFAULT '0' COMMENT '服务ID',\n `nodeId` int(11) unsigned DEFAULT '0' COMMENT '节点ID',\n `status` int(3) unsigned DEFAULT '0' COMMENT '状态码',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `content` json DEFAULT NULL COMMENT '日志内容',\n `requestId` varchar(128) DEFAULT NULL COMMENT '请求ID',\n `firewallPolicyId` int(11) unsigned DEFAULT '0' COMMENT 'WAF策略ID',\n `firewallRuleGroupId` int(11) unsigned DEFAULT '0' COMMENT 'WAF分组ID',\n `firewallRuleSetId` int(11) unsigned DEFAULT '0' COMMENT 'WAF集ID',\n `firewallRuleId` int(11) unsigned DEFAULT '0' COMMENT 'WAF规则ID',\n `remoteAddr` varchar(64) DEFAULT NULL COMMENT 'IP地址',\n `domain` varchar(128) DEFAULT NULL COMMENT '域名',\n `requestBody` mediumblob COMMENT '请求内容',\n `responseBody` mediumblob COMMENT '响应内容',\n PRIMARY KEY (`id`),\n KEY `serverId` (`serverId`),\n KEY `nodeId` (`nodeId`),\n KEY `serverId_status` (`serverId`,`status`),\n KEY `requestId` (`requestId`),\n KEY `firewallPolicyId` (`firewallPolicyId`),\n KEY `firewallRuleGroupId` (`firewallRuleGroupId`),\n KEY `firewallRuleSetId` (`firewallRuleSetId`),\n KEY `firewallRuleId` (`firewallRuleId`),\n KEY `remoteAddr` (`remoteAddr`),\n KEY `domain` (`domain`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='访问日志';")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
accessLogLocker.Lock()
|
||||
var definition = &httpAccessLogDefinition{
|
||||
Name: tableName,
|
||||
HasRemoteAddr: true,
|
||||
Exists: true,
|
||||
}
|
||||
httpAccessLogTableMapping[cacheKey] = definition
|
||||
accessLogLocker.Unlock()
|
||||
|
||||
return definition, nil
|
||||
}
|
||||
|
||||
func findNSAccessLogTable(db *dbs.DB, day string, force bool) (string, error) {
|
||||
config, err := db.Config()
|
||||
if err != nil {
|
||||
@@ -337,7 +256,7 @@ func (this *DBNodeInitializer) loop() error {
|
||||
}
|
||||
|
||||
if db == nil {
|
||||
config := &dbs.DBConfig{
|
||||
var config = &dbs.DBConfig{
|
||||
Driver: "mysql",
|
||||
Dsn: dsn,
|
||||
Prefix: "edge",
|
||||
@@ -351,22 +270,17 @@ func (this *DBNodeInitializer) loop() error {
|
||||
// 检查表是否存在
|
||||
// httpAccessLog
|
||||
{
|
||||
tableDef, err := findHTTPAccessLogTable(db, timeutil.Format("Ymd"), true)
|
||||
tableDef, err := SharedHTTPAccessLogManager.FindLastTable(db, timeutil.Format("Ymd"), true)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "1050") { // 非表格已存在错误
|
||||
remotelogs.Error("DB_NODE", "create first table in database node failed: "+err.Error())
|
||||
remotelogs.Error("DB_NODE", "create first table in database node failed: "+err.Error())
|
||||
|
||||
// 创建节点日志
|
||||
createLogErr := SharedNodeLogDAO.CreateLog(nil, nodeconfigs.NodeRoleDatabase, nodeId, 0, 0, "error", "ACCESS_LOG", "can not create access log table: "+err.Error(), time.Now().Unix(), "", nil)
|
||||
if createLogErr != nil {
|
||||
remotelogs.Error("NODE_LOG", createLogErr.Error())
|
||||
}
|
||||
|
||||
continue
|
||||
} else {
|
||||
err = nil
|
||||
continue
|
||||
// 创建节点日志
|
||||
createLogErr := SharedNodeLogDAO.CreateLog(nil, nodeconfigs.NodeRoleDatabase, nodeId, 0, 0, "error", "ACCESS_LOG", "can not create access log table: "+err.Error(), time.Now().Unix(), "", nil)
|
||||
if createLogErr != nil {
|
||||
remotelogs.Error("NODE_LOG", createLogErr.Error())
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
daoObject := dbs.DAOObject{
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestDBNodeInitializer_loop(t *testing.T) {
|
||||
@@ -14,32 +12,3 @@ func TestDBNodeInitializer_loop(t *testing.T) {
|
||||
}
|
||||
t.Log(len(accessLogDBMapping), len(httpAccessLogDAOMapping))
|
||||
}
|
||||
|
||||
func TestFindAccessLogTable(t *testing.T) {
|
||||
before := time.Now()
|
||||
db := SharedHTTPAccessLogDAO.Instance
|
||||
tableName, err := findHTTPAccessLogTable(db, "20201010", false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(tableName)
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
|
||||
before = time.Now()
|
||||
tableName, err = findHTTPAccessLogTable(db, "20201010", false)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(tableName)
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
}
|
||||
|
||||
func BenchmarkFindAccessLogTable(b *testing.B) {
|
||||
db := SharedHTTPAccessLogDAO.Instance
|
||||
|
||||
runtime.GOMAXPROCS(1)
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = findHTTPAccessLogTable(db, "20201010", false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package models
|
||||
|
||||
// 数据库节点
|
||||
// DBNode 数据库节点
|
||||
type DBNode struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Role string `field:"role"` // 数据库角色
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
|
||||
@@ -91,7 +91,7 @@ func (this *DNSDomainDAO) FindDNSDomainName(tx *dbs.Tx, id int64) (string, error
|
||||
|
||||
// CreateDomain 创建域名
|
||||
func (this *DNSDomainDAO) CreateDomain(tx *dbs.Tx, adminId int64, userId int64, providerId int64, name string) (int64, error) {
|
||||
op := NewDNSDomainOperator()
|
||||
var op = NewDNSDomainOperator()
|
||||
op.ProviderId = providerId
|
||||
op.AdminId = adminId
|
||||
op.UserId = userId
|
||||
@@ -111,7 +111,7 @@ func (this *DNSDomainDAO) UpdateDomain(tx *dbs.Tx, domainId int64, name string,
|
||||
if domainId <= 0 {
|
||||
return errors.New("invalid domainId")
|
||||
}
|
||||
op := NewDNSDomainOperator()
|
||||
var op = NewDNSDomainOperator()
|
||||
op.Id = domainId
|
||||
op.Name = name
|
||||
op.IsOn = isOn
|
||||
@@ -146,7 +146,7 @@ func (this *DNSDomainDAO) UpdateDomainData(tx *dbs.Tx, domainId int64, data stri
|
||||
if domainId <= 0 {
|
||||
return errors.New("invalid domainId")
|
||||
}
|
||||
op := NewDNSDomainOperator()
|
||||
var op = NewDNSDomainOperator()
|
||||
op.Id = domainId
|
||||
op.Data = data
|
||||
err := this.Save(tx, op)
|
||||
@@ -158,7 +158,7 @@ func (this *DNSDomainDAO) UpdateDomainRecords(tx *dbs.Tx, domainId int64, record
|
||||
if domainId <= 0 {
|
||||
return errors.New("invalid domainId")
|
||||
}
|
||||
op := NewDNSDomainOperator()
|
||||
var op = NewDNSDomainOperator()
|
||||
op.Id = domainId
|
||||
op.Records = recordsJSON
|
||||
op.DataUpdatedAt = time.Now().Unix()
|
||||
@@ -171,7 +171,7 @@ func (this *DNSDomainDAO) UpdateDomainRoutes(tx *dbs.Tx, domainId int64, routesJ
|
||||
if domainId <= 0 {
|
||||
return errors.New("invalid domainId")
|
||||
}
|
||||
op := NewDNSDomainOperator()
|
||||
var op = NewDNSDomainOperator()
|
||||
op.Id = domainId
|
||||
op.Routes = routesJSON
|
||||
op.DataUpdatedAt = time.Now().Unix()
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
package dns
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// DNSDomain 管理的域名
|
||||
type DNSDomain struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
ProviderId uint32 `field:"providerId"` // 服务商ID
|
||||
IsOn uint8 `field:"isOn"` // 是否可用
|
||||
Name string `field:"name"` // 域名
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
DataUpdatedAt uint64 `field:"dataUpdatedAt"` // 数据更新时间
|
||||
DataError string `field:"dataError"` // 数据更新错误
|
||||
Data string `field:"data"` // 原始数据信息
|
||||
Records string `field:"records"` // 所有解析记录
|
||||
Routes string `field:"routes"` // 线路数据
|
||||
IsUp uint8 `field:"isUp"` // 是否在线
|
||||
State uint8 `field:"state"` // 状态
|
||||
IsDeleted uint8 `field:"isDeleted"` // 是否已删除
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
ProviderId uint32 `field:"providerId"` // 服务商ID
|
||||
IsOn bool `field:"isOn"` // 是否可用
|
||||
Name string `field:"name"` // 域名
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
DataUpdatedAt uint64 `field:"dataUpdatedAt"` // 数据更新时间
|
||||
DataError string `field:"dataError"` // 数据更新错误
|
||||
Data string `field:"data"` // 原始数据信息
|
||||
Records dbs.JSON `field:"records"` // 所有解析记录
|
||||
Routes dbs.JSON `field:"routes"` // 线路数据
|
||||
IsUp bool `field:"isUp"` // 是否在线
|
||||
State uint8 `field:"state"` // 状态
|
||||
IsDeleted bool `field:"isDeleted"` // 是否已删除
|
||||
}
|
||||
|
||||
type DNSDomainOperator struct {
|
||||
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
|
||||
// DecodeRoutes 获取所有的线路
|
||||
func (this *DNSDomain) DecodeRoutes() ([]*dnstypes.Route, error) {
|
||||
if len(this.Routes) == 0 || this.Routes == "null" {
|
||||
if len(this.Routes) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
result := []*dnstypes.Route{}
|
||||
err := json.Unmarshal([]byte(this.Routes), &result)
|
||||
err := json.Unmarshal(this.Routes, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -35,11 +35,11 @@ func (this *DNSDomain) ContainsRouteCode(route string) (bool, error) {
|
||||
// DecodeRecords 获取所有的记录
|
||||
func (this *DNSDomain) DecodeRecords() ([]*dnstypes.Record, error) {
|
||||
records := this.Records
|
||||
if len(records) == 0 || records == "null" {
|
||||
if len(records) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
result := []*dnstypes.Record{}
|
||||
err := json.Unmarshal([]byte(records), &result)
|
||||
err := json.Unmarshal(records, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ func (this *DNSProviderDAO) FindEnabledDNSProvider(tx *dbs.Tx, id int64) (*DNSPr
|
||||
|
||||
// CreateDNSProvider 创建服务商
|
||||
func (this *DNSProviderDAO) CreateDNSProvider(tx *dbs.Tx, adminId int64, userId int64, providerType string, name string, apiParamsJSON []byte) (int64, error) {
|
||||
op := NewDNSProviderOperator()
|
||||
var op = NewDNSProviderOperator()
|
||||
op.AdminId = adminId
|
||||
op.UserId = userId
|
||||
op.Type = providerType
|
||||
@@ -90,7 +90,7 @@ func (this *DNSProviderDAO) UpdateDNSProvider(tx *dbs.Tx, dnsProviderId int64, n
|
||||
return errors.New("invalid dnsProviderId")
|
||||
}
|
||||
|
||||
op := NewDNSProviderOperator()
|
||||
var op = NewDNSProviderOperator()
|
||||
op.Id = dnsProviderId
|
||||
op.Name = name
|
||||
|
||||
@@ -107,22 +107,39 @@ func (this *DNSProviderDAO) UpdateDNSProvider(tx *dbs.Tx, dnsProviderId int64, n
|
||||
}
|
||||
|
||||
// CountAllEnabledDNSProviders 计算服务商数量
|
||||
func (this *DNSProviderDAO) CountAllEnabledDNSProviders(tx *dbs.Tx, adminId int64, userId int64, keyword string) (int64, error) {
|
||||
func (this *DNSProviderDAO) CountAllEnabledDNSProviders(tx *dbs.Tx, adminId int64, userId int64, keyword string, domain string, providerType string) (int64, error) {
|
||||
var query = dbutils.NewQuery(tx, this, adminId, userId)
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
|
||||
if len(domain) > 0 {
|
||||
query.Where("id IN (SELECT providerId FROM " + SharedDNSDomainDAO.Table + " WHERE state=1 AND name=:domain)")
|
||||
query.Param("domain", domain)
|
||||
}
|
||||
|
||||
if len(providerType) > 0 {
|
||||
query.Attr("type", providerType)
|
||||
}
|
||||
|
||||
return query.State(DNSProviderStateEnabled).
|
||||
Count()
|
||||
}
|
||||
|
||||
// ListEnabledDNSProviders 列出单页服务商
|
||||
func (this *DNSProviderDAO) ListEnabledDNSProviders(tx *dbs.Tx, adminId int64, userId int64, keyword string, offset int64, size int64) (result []*DNSProvider, err error) {
|
||||
func (this *DNSProviderDAO) ListEnabledDNSProviders(tx *dbs.Tx, adminId int64, userId int64, keyword string, domain string, providerType string, offset int64, size int64) (result []*DNSProvider, err error) {
|
||||
var query = dbutils.NewQuery(tx, this, adminId, userId)
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
if len(domain) > 0 {
|
||||
query.Where("id IN (SELECT providerId FROM " + SharedDNSDomainDAO.Table + " WHERE state=1 AND name=:domain)")
|
||||
query.Param("domain", domain)
|
||||
}
|
||||
if len(providerType) > 0 {
|
||||
query.Attr("type", providerType)
|
||||
}
|
||||
_, err = query.
|
||||
State(DNSProviderStateEnabled).
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
package dns
|
||||
|
||||
// DNS服务商
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// DNSProvider DNS服务商
|
||||
type DNSProvider struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Name string `field:"name"` // 名称
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
Type string `field:"type"` // 供应商类型
|
||||
ApiParams string `field:"apiParams"` // API参数
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
DataUpdatedAt uint64 `field:"dataUpdatedAt"` // 数据同步时间
|
||||
Id uint32 `field:"id"` // ID
|
||||
Name string `field:"name"` // 名称
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
Type string `field:"type"` // 供应商类型
|
||||
ApiParams dbs.JSON `field:"apiParams"` // API参数
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
DataUpdatedAt uint64 `field:"dataUpdatedAt"` // 数据同步时间
|
||||
}
|
||||
|
||||
type DNSProviderOperator struct {
|
||||
|
||||
@@ -5,12 +5,12 @@ import (
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// 获取API参数
|
||||
// DecodeAPIParams 获取API参数
|
||||
func (this *DNSProvider) DecodeAPIParams() (maps.Map, error) {
|
||||
if len(this.ApiParams) == 0 || this.ApiParams == "null" {
|
||||
if len(this.ApiParams) == 0 {
|
||||
return maps.Map{}, nil
|
||||
}
|
||||
result := maps.Map{}
|
||||
err := json.Unmarshal([]byte(this.ApiParams), &result)
|
||||
err := json.Unmarshal(this.ApiParams, &result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
@@ -12,10 +12,11 @@ import (
|
||||
type DNSTaskType = string
|
||||
|
||||
const (
|
||||
DNSTaskTypeClusterChange DNSTaskType = "clusterChange"
|
||||
DNSTaskTypeNodeChange DNSTaskType = "nodeChange"
|
||||
DNSTaskTypeServerChange DNSTaskType = "serverChange"
|
||||
DNSTaskTypeDomainChange DNSTaskType = "domainChange"
|
||||
DNSTaskTypeClusterChange DNSTaskType = "clusterChange"
|
||||
DNSTaskTypeClusterRemoveDomain DNSTaskType = "clusterRemoveDomain" // 从集群中移除域名
|
||||
DNSTaskTypeNodeChange DNSTaskType = "nodeChange"
|
||||
DNSTaskTypeServerChange DNSTaskType = "serverChange"
|
||||
DNSTaskTypeDomainChange DNSTaskType = "domainChange"
|
||||
)
|
||||
|
||||
type DNSTaskDAO dbs.DAO
|
||||
@@ -40,20 +41,21 @@ func init() {
|
||||
}
|
||||
|
||||
// CreateDNSTask 生成任务
|
||||
func (this *DNSTaskDAO) CreateDNSTask(tx *dbs.Tx, clusterId int64, serverId int64, nodeId int64, domainId int64, taskType string) error {
|
||||
func (this *DNSTaskDAO) CreateDNSTask(tx *dbs.Tx, clusterId int64, serverId int64, nodeId int64, domainId int64, recordName string, taskType string) error {
|
||||
if clusterId <= 0 && serverId <= 0 && nodeId <= 0 && domainId <= 0 {
|
||||
return nil
|
||||
}
|
||||
err := this.Query(tx).InsertOrUpdateQuickly(maps.Map{
|
||||
"clusterId": clusterId,
|
||||
"serverId": serverId,
|
||||
"nodeId": nodeId,
|
||||
"domainId": domainId,
|
||||
"updatedAt": time.Now().Unix(),
|
||||
"type": taskType,
|
||||
"isDone": false,
|
||||
"isOk": false,
|
||||
"error": "",
|
||||
"clusterId": clusterId,
|
||||
"serverId": serverId,
|
||||
"nodeId": nodeId,
|
||||
"domainId": domainId,
|
||||
"recordName": recordName,
|
||||
"updatedAt": time.Now().Unix(),
|
||||
"type": taskType,
|
||||
"isDone": false,
|
||||
"isOk": false,
|
||||
"error": "",
|
||||
}, maps.Map{
|
||||
"updatedAt": time.Now().Unix(),
|
||||
"isDone": false,
|
||||
@@ -63,24 +65,29 @@ func (this *DNSTaskDAO) CreateDNSTask(tx *dbs.Tx, clusterId int64, serverId int6
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateClusterTask 生成集群任务
|
||||
// CreateClusterTask 生成集群变更任务
|
||||
func (this *DNSTaskDAO) CreateClusterTask(tx *dbs.Tx, clusterId int64, taskType DNSTaskType) error {
|
||||
return this.CreateDNSTask(tx, clusterId, 0, 0, 0, taskType)
|
||||
return this.CreateDNSTask(tx, clusterId, 0, 0, 0, "", taskType)
|
||||
}
|
||||
|
||||
// CreateClusterRemoveTask 生成集群删除域名任务
|
||||
func (this *DNSTaskDAO) CreateClusterRemoveTask(tx *dbs.Tx, clusterId int64, domainId int64, recordName string) error {
|
||||
return this.CreateDNSTask(tx, clusterId, 0, 0, domainId, recordName, DNSTaskTypeClusterRemoveDomain)
|
||||
}
|
||||
|
||||
// CreateNodeTask 生成节点任务
|
||||
func (this *DNSTaskDAO) CreateNodeTask(tx *dbs.Tx, nodeId int64, taskType DNSTaskType) error {
|
||||
return this.CreateDNSTask(tx, 0, 0, nodeId, 0, taskType)
|
||||
return this.CreateDNSTask(tx, 0, 0, nodeId, 0, "", taskType)
|
||||
}
|
||||
|
||||
// CreateServerTask 生成服务任务
|
||||
func (this *DNSTaskDAO) CreateServerTask(tx *dbs.Tx, serverId int64, taskType DNSTaskType) error {
|
||||
return this.CreateDNSTask(tx, 0, serverId, 0, 0, taskType)
|
||||
func (this *DNSTaskDAO) CreateServerTask(tx *dbs.Tx, clusterId int64, serverId int64, taskType DNSTaskType) error {
|
||||
return this.CreateDNSTask(tx, clusterId, serverId, 0, 0, "", taskType)
|
||||
}
|
||||
|
||||
// CreateDomainTask 生成域名更新任务
|
||||
func (this *DNSTaskDAO) CreateDomainTask(tx *dbs.Tx, domainId int64, taskType DNSTaskType) error {
|
||||
return this.CreateDNSTask(tx, 0, 0, 0, domainId, taskType)
|
||||
return this.CreateDNSTask(tx, 0, 0, 0, domainId, "", taskType)
|
||||
}
|
||||
|
||||
// FindAllDoingTasks 查找所有正在执行的任务
|
||||
@@ -101,6 +108,7 @@ func (this *DNSTaskDAO) FindAllDoingOrErrorTasks(tx *dbs.Tx, nodeClusterId int64
|
||||
}
|
||||
_, err = query.
|
||||
Where("(isDone=0 OR (isDone=1 AND isOk=0))").
|
||||
Asc("updatedAt").
|
||||
AscPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
@@ -135,7 +143,7 @@ func (this *DNSTaskDAO) UpdateDNSTaskError(tx *dbs.Tx, taskId int64, err string)
|
||||
if taskId <= 0 {
|
||||
return errors.New("invalid taskId")
|
||||
}
|
||||
op := NewDNSTaskOperator()
|
||||
var op = NewDNSTaskOperator()
|
||||
op.Id = taskId
|
||||
op.IsDone = true
|
||||
op.Error = err
|
||||
@@ -148,7 +156,7 @@ func (this *DNSTaskDAO) UpdateDNSTaskDone(tx *dbs.Tx, taskId int64) error {
|
||||
if taskId <= 0 {
|
||||
return errors.New("invalid taskId")
|
||||
}
|
||||
op := NewDNSTaskOperator()
|
||||
var op = NewDNSTaskOperator()
|
||||
op.Id = taskId
|
||||
op.IsDone = true
|
||||
op.IsOk = true
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
package dns
|
||||
|
||||
// DNS更新任务
|
||||
// DNSTask DNS更新任务
|
||||
type DNSTask struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
NodeId uint32 `field:"nodeId"` // 节点ID
|
||||
DomainId uint32 `field:"domainId"` // 域名ID
|
||||
Type string `field:"type"` // 任务类型
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 更新时间
|
||||
IsDone uint8 `field:"isDone"` // 是否已完成
|
||||
IsOk uint8 `field:"isOk"` // 是否成功
|
||||
Error string `field:"error"` // 错误信息
|
||||
Id uint64 `field:"id"` // ID
|
||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
NodeId uint32 `field:"nodeId"` // 节点ID
|
||||
DomainId uint32 `field:"domainId"` // 域名ID
|
||||
RecordName string `field:"recordName"` // 记录名
|
||||
Type string `field:"type"` // 任务类型
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 更新时间
|
||||
IsDone bool `field:"isDone"` // 是否已完成
|
||||
IsOk bool `field:"isOk"` // 是否成功
|
||||
Error string `field:"error"` // 错误信息
|
||||
}
|
||||
|
||||
type DNSTaskOperator struct {
|
||||
Id interface{} // ID
|
||||
ClusterId interface{} // 集群ID
|
||||
ServerId interface{} // 服务ID
|
||||
NodeId interface{} // 节点ID
|
||||
DomainId interface{} // 域名ID
|
||||
Type interface{} // 任务类型
|
||||
UpdatedAt interface{} // 更新时间
|
||||
IsDone interface{} // 是否已完成
|
||||
IsOk interface{} // 是否成功
|
||||
Error interface{} // 错误信息
|
||||
Id interface{} // ID
|
||||
ClusterId interface{} // 集群ID
|
||||
ServerId interface{} // 服务ID
|
||||
NodeId interface{} // 节点ID
|
||||
DomainId interface{} // 域名ID
|
||||
RecordName interface{} // 记录名
|
||||
Type interface{} // 任务类型
|
||||
UpdatedAt interface{} // 更新时间
|
||||
IsDone interface{} // 是否已完成
|
||||
IsOk interface{} // 是否成功
|
||||
Error interface{} // 错误信息
|
||||
}
|
||||
|
||||
func NewDNSTaskOperator() *DNSTaskOperator {
|
||||
|
||||
@@ -153,7 +153,7 @@ func CheckClusterDNS(tx *dbs.Tx, cluster *models.NodeCluster) (issues []*pb.DNSI
|
||||
}
|
||||
|
||||
// 检查IP地址
|
||||
ipAddr, _, err := models.SharedNodeIPAddressDAO.FindFirstNodeAccessIPAddress(tx, nodeId, nodeconfigs.NodeRoleNode)
|
||||
ipAddr, _, err := models.SharedNodeIPAddressDAO.FindFirstNodeAccessIPAddress(tx, nodeId, true, nodeconfigs.NodeRoleNode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 创建文件Chunk
|
||||
// CreateFileChunk 创建文件Chunk
|
||||
func (this *FileChunkDAO) CreateFileChunk(tx *dbs.Tx, fileId int64, data []byte) (int64, error) {
|
||||
op := NewFileChunkOperator()
|
||||
var op = NewFileChunkOperator()
|
||||
op.FileId = fileId
|
||||
op.Data = data
|
||||
err := this.Save(tx, op)
|
||||
@@ -41,7 +41,7 @@ func (this *FileChunkDAO) CreateFileChunk(tx *dbs.Tx, fileId int64, data []byte)
|
||||
return types.Int64(op.Id), nil
|
||||
}
|
||||
|
||||
// 列出所有的文件Chunk
|
||||
// FindAllFileChunks 列出所有的文件Chunk
|
||||
func (this *FileChunkDAO) FindAllFileChunks(tx *dbs.Tx, fileId int64) (result []*FileChunk, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Attr("fileId", fileId).
|
||||
@@ -51,7 +51,7 @@ func (this *FileChunkDAO) FindAllFileChunks(tx *dbs.Tx, fileId int64) (result []
|
||||
return
|
||||
}
|
||||
|
||||
// 读取文件的所有片段ID
|
||||
// FindAllFileChunkIds 读取文件的所有片段ID
|
||||
func (this *FileChunkDAO) FindAllFileChunkIds(tx *dbs.Tx, fileId int64) ([]int64, error) {
|
||||
ones, err := this.Query(tx).
|
||||
Attr("fileId", fileId).
|
||||
@@ -68,7 +68,7 @@ func (this *FileChunkDAO) FindAllFileChunkIds(tx *dbs.Tx, fileId int64) ([]int64
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// 删除以前的文件
|
||||
// DeleteFileChunks 删除以前的文件
|
||||
func (this *FileChunkDAO) DeleteFileChunks(tx *dbs.Tx, fileId int64) error {
|
||||
if fileId <= 0 {
|
||||
return errors.New("invalid fileId")
|
||||
@@ -79,7 +79,7 @@ func (this *FileChunkDAO) DeleteFileChunks(tx *dbs.Tx, fileId int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 根据ID查找片段
|
||||
// FindFileChunk 根据ID查找片段
|
||||
func (this *FileChunkDAO) FindFileChunk(tx *dbs.Tx, chunkId int64) (*FileChunk, error) {
|
||||
one, err := this.Query(tx).
|
||||
Pk(chunkId).
|
||||
|
||||
@@ -4,7 +4,7 @@ package models
|
||||
type FileChunk struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
FileId uint32 `field:"fileId"` // 文件ID
|
||||
Data string `field:"data"` // 分块内容
|
||||
Data []byte `field:"data"` // 分块内容
|
||||
}
|
||||
|
||||
type FileChunkOperator struct {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -33,7 +34,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 启用条目
|
||||
// EnableFile 启用条目
|
||||
func (this *FileDAO) EnableFile(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -42,7 +43,7 @@ func (this *FileDAO) EnableFile(tx *dbs.Tx, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 禁用条目
|
||||
// DisableFile 禁用条目
|
||||
func (this *FileDAO) DisableFile(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -51,7 +52,7 @@ func (this *FileDAO) DisableFile(tx *dbs.Tx, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 查找启用中的条目
|
||||
// FindEnabledFile 查找启用中的条目
|
||||
func (this *FileDAO) FindEnabledFile(tx *dbs.Tx, id int64) (*File, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -63,9 +64,9 @@ func (this *FileDAO) FindEnabledFile(tx *dbs.Tx, id int64) (*File, error) {
|
||||
return result.(*File), err
|
||||
}
|
||||
|
||||
// 创建文件
|
||||
func (this *FileDAO) CreateFile(tx *dbs.Tx, adminId int64, userId int64, businessType, description string, filename string, size int64, isPublic bool) (int64, error) {
|
||||
op := NewFileOperator()
|
||||
// CreateFile 创建文件
|
||||
func (this *FileDAO) CreateFile(tx *dbs.Tx, adminId int64, userId int64, businessType string, description string, filename string, size int64, mimeType string, isPublic bool) (int64, error) {
|
||||
var op = NewFileOperator()
|
||||
op.AdminId = adminId
|
||||
op.UserId = userId
|
||||
op.Type = businessType
|
||||
@@ -74,6 +75,8 @@ func (this *FileDAO) CreateFile(tx *dbs.Tx, adminId int64, userId int64, busines
|
||||
op.Size = size
|
||||
op.Filename = filename
|
||||
op.IsPublic = isPublic
|
||||
op.Code = utils.Sha1RandomString()
|
||||
op.MimeType = mimeType
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -82,7 +85,22 @@ func (this *FileDAO) CreateFile(tx *dbs.Tx, adminId int64, userId int64, busines
|
||||
return types.Int64(op.Id), nil
|
||||
}
|
||||
|
||||
// 将文件置为已完成
|
||||
// CheckUserFile 检查用户ID
|
||||
func (this *FileDAO) CheckUserFile(tx *dbs.Tx, userId int64, fileId int64) error {
|
||||
b, err := this.Query(tx).
|
||||
Pk(fileId).
|
||||
Attr("userId", userId).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !b {
|
||||
return ErrNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateFileIsFinished 将文件置为已完成
|
||||
func (this *FileDAO) UpdateFileIsFinished(tx *dbs.Tx, fileId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(fileId).
|
||||
|
||||
@@ -1,28 +1,32 @@
|
||||
package models
|
||||
|
||||
// 文件管理
|
||||
// File 文件管理
|
||||
type File struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
Code string `field:"code"` // 代号
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
Description string `field:"description"` // 文件描述
|
||||
Filename string `field:"filename"` // 文件名
|
||||
Size uint32 `field:"size"` // 文件尺寸
|
||||
MimeType string `field:"mimeType"` // Mime类型
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Order uint32 `field:"order"` // 排序
|
||||
Type string `field:"type"` // 类型
|
||||
State uint8 `field:"state"` // 状态
|
||||
IsFinished uint8 `field:"isFinished"` // 是否已完成上传
|
||||
IsPublic uint8 `field:"isPublic"` // 是否可以公开访问
|
||||
IsFinished bool `field:"isFinished"` // 是否已完成上传
|
||||
IsPublic bool `field:"isPublic"` // 是否可以公开访问
|
||||
}
|
||||
|
||||
type FileOperator struct {
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
Code interface{} // 代号
|
||||
UserId interface{} // 用户ID
|
||||
Description interface{} // 文件描述
|
||||
Filename interface{} // 文件名
|
||||
Size interface{} // 文件尺寸
|
||||
MimeType interface{} // Mime类型
|
||||
CreatedAt interface{} // 创建时间
|
||||
Order interface{} // 排序
|
||||
Type interface{} // 类型
|
||||
|
||||
@@ -3,6 +3,7 @@ package models
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
@@ -22,6 +23,7 @@ import (
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -34,13 +36,25 @@ type HTTPAccessLogDAO dbs.DAO
|
||||
var SharedHTTPAccessLogDAO *HTTPAccessLogDAO
|
||||
|
||||
// 队列
|
||||
var oldAccessLogQueue = make(chan *pb.HTTPAccessLog)
|
||||
var accessLogQueue = make(chan *pb.HTTPAccessLog, 10_000)
|
||||
var accessLogQueueMaxLength = 100_000
|
||||
var accessLogQueuePercent = 100 // 0-100
|
||||
var accessLogCountPerSecond = 10_000 // 0 表示不限制
|
||||
var accessLogConfigJSON = []byte{}
|
||||
var accessLogQueueChanged = make(chan zero.Zero, 1)
|
||||
var (
|
||||
oldAccessLogQueue = make(chan *pb.HTTPAccessLog)
|
||||
accessLogQueue = make(chan *pb.HTTPAccessLog, 10_000)
|
||||
accessLogQueueMaxLength = 100_000
|
||||
accessLogQueuePercent = 100 // 0-100
|
||||
accessLogCountPerSecond = 10_000 // 0 表示不限制
|
||||
accessLogConfigJSON = []byte{}
|
||||
accessLogQueueChanged = make(chan zero.Zero, 1)
|
||||
|
||||
accessLogEnableAutoPartial = true // 是否启用自动分表
|
||||
accessLogRowsPerTable int64 = 500_000 // 自动分表的单表最大值
|
||||
)
|
||||
|
||||
type accessLogTableQuery struct {
|
||||
daoWrapper *HTTPAccessLogDAOWrapper
|
||||
name string
|
||||
hasRemoteAddrField bool
|
||||
hasDomainField bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
@@ -120,7 +134,7 @@ func (this *HTTPAccessLogDAO) CreateHTTPAccessLogs(tx *dbs.Tx, accessLogs []*pb.
|
||||
|
||||
// DumpAccessLogsFromQueue 从队列导入访问日志
|
||||
func (this *HTTPAccessLogDAO) DumpAccessLogsFromQueue(tx *dbs.Tx, size int) error {
|
||||
dao := randomHTTPAccessLogDAO()
|
||||
var dao = randomHTTPAccessLogDAO()
|
||||
if dao == nil {
|
||||
dao = &HTTPAccessLogDAOWrapper{
|
||||
DAO: SharedHTTPAccessLogDAO,
|
||||
@@ -168,8 +182,8 @@ Loop:
|
||||
|
||||
// CreateHTTPAccessLog 写入单条访问日志
|
||||
func (this *HTTPAccessLogDAO) CreateHTTPAccessLog(tx *dbs.Tx, dao *HTTPAccessLogDAO, accessLog *pb.HTTPAccessLog) error {
|
||||
day := timeutil.Format("Ymd", time.Unix(accessLog.Timestamp, 0))
|
||||
tableDef, err := findHTTPAccessLogTable(dao.Instance, day, false)
|
||||
var day = timeutil.FormatTime("Ymd", accessLog.Timestamp)
|
||||
tableDef, err := SharedHTTPAccessLogManager.FindLastTable(dao.Instance, day, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -203,36 +217,46 @@ func (this *HTTPAccessLogDAO) CreateHTTPAccessLog(tx *dbs.Tx, dao *HTTPAccessLog
|
||||
}
|
||||
fields["content"] = content
|
||||
|
||||
_, err = dao.Query(tx).
|
||||
var lastId int64
|
||||
lastId, err = dao.Query(tx).
|
||||
Table(tableDef.Name).
|
||||
Sets(fields).
|
||||
Insert()
|
||||
if err != nil {
|
||||
// 是否为 Error 1146: Table 'xxx.xxx' doesn't exist 如果是,则创建表之后重试
|
||||
if strings.Contains(err.Error(), "1146") {
|
||||
tableDef, err = findHTTPAccessLogTable(dao.Instance, day, true)
|
||||
// 错误重试
|
||||
if CheckSQLErrCode(err, 1146) { // Error 1146: Table 'xxx' doesn't exist
|
||||
err = SharedHTTPAccessLogManager.CreateTable(dao.Instance, tableDef.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = dao.Query(tx).
|
||||
|
||||
// 重新尝试
|
||||
lastId, err = dao.Query(tx).
|
||||
Table(tableDef.Name).
|
||||
Sets(fields).
|
||||
Insert()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
remotelogs.Error("HTTP_ACCESS_LOG", err.Error())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if accessLogEnableAutoPartial && accessLogRowsPerTable > 0 && lastId >= accessLogRowsPerTable {
|
||||
SharedHTTPAccessLogManager.ResetTable(dao.Instance, day)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListAccessLogs 读取往前的 单页访问日志
|
||||
func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx, lastRequestId string,
|
||||
func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx,
|
||||
partition int32,
|
||||
lastRequestId string,
|
||||
size int64,
|
||||
day string,
|
||||
hourFrom string,
|
||||
hourTo string,
|
||||
clusterId int64,
|
||||
nodeId int64,
|
||||
serverId int64,
|
||||
@@ -255,23 +279,42 @@ func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx, lastRequestId string,
|
||||
size = 1000
|
||||
}
|
||||
|
||||
result, nextLastRequestId, err = this.listAccessLogs(tx, lastRequestId, size, day, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
|
||||
result, nextLastRequestId, err = this.listAccessLogs(tx, partition, lastRequestId, size, day, hourFrom, hourTo, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
|
||||
if err != nil || int64(len(result)) < size {
|
||||
return
|
||||
}
|
||||
|
||||
moreResult, _, _ := this.listAccessLogs(tx, nextLastRequestId, 1, day, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
|
||||
moreResult, _, _ := this.listAccessLogs(tx, partition, nextLastRequestId, 1, day, hourFrom, hourTo, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
|
||||
hasMore = len(moreResult) > 0
|
||||
return
|
||||
}
|
||||
|
||||
// 读取往前的单页访问日志
|
||||
func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, size int64, day string, clusterId int64, nodeId int64, serverId int64, reverse bool, hasError bool, firewallPolicyId int64, firewallRuleGroupId int64, firewallRuleSetId int64, hasFirewallPolicy bool, userId int64, keyword string, ip string, domain string) (result []*HTTPAccessLog, nextLastRequestId string, err error) {
|
||||
func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx,
|
||||
partition int32,
|
||||
lastRequestId string,
|
||||
size int64,
|
||||
day string,
|
||||
hourFrom string,
|
||||
hourTo string,
|
||||
clusterId int64,
|
||||
nodeId int64,
|
||||
serverId int64,
|
||||
reverse bool,
|
||||
hasError bool,
|
||||
firewallPolicyId int64,
|
||||
firewallRuleGroupId int64,
|
||||
firewallRuleSetId int64,
|
||||
hasFirewallPolicy bool,
|
||||
userId int64,
|
||||
keyword string,
|
||||
ip string,
|
||||
domain string) (result []*HTTPAccessLog, nextLastRequestId string, err error) {
|
||||
if size <= 0 {
|
||||
return nil, lastRequestId, nil
|
||||
}
|
||||
|
||||
serverIds := []int64{}
|
||||
var serverIds = []int64{}
|
||||
if userId > 0 {
|
||||
serverIds, err = SharedServerDAO.FindAllEnabledServerIdsWithUserId(tx, userId)
|
||||
if err != nil {
|
||||
@@ -283,7 +326,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
}
|
||||
|
||||
accessLogLocker.RLock()
|
||||
daoList := []*HTTPAccessLogDAOWrapper{}
|
||||
var daoList = []*HTTPAccessLogDAOWrapper{}
|
||||
for _, daoWrapper := range httpAccessLogDAOMapping {
|
||||
daoList = append(daoList, daoWrapper)
|
||||
}
|
||||
@@ -296,42 +339,86 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
}}
|
||||
}
|
||||
|
||||
locker := sync.Mutex{}
|
||||
// 查询某个集群下的节点
|
||||
var nodeIds = []int64{}
|
||||
if clusterId > 0 {
|
||||
nodeIds, err = SharedNodeDAO.FindAllEnabledNodeIdsWithClusterId(tx, clusterId)
|
||||
if err != nil {
|
||||
remotelogs.Error("DB_NODE", err.Error())
|
||||
return
|
||||
}
|
||||
sort.Slice(nodeIds, func(i, j int) bool {
|
||||
return nodeIds[i] < nodeIds[j]
|
||||
})
|
||||
}
|
||||
|
||||
count := len(daoList)
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(count)
|
||||
// 准备查询
|
||||
var tableQueries = []*accessLogTableQuery{}
|
||||
var maxTableName = ""
|
||||
for _, daoWrapper := range daoList {
|
||||
go func(daoWrapper *HTTPAccessLogDAOWrapper) {
|
||||
var instance = daoWrapper.DAO.Instance
|
||||
def, err := SharedHTTPAccessLogManager.FindPartitionTable(instance, day, partition)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if !def.Exists {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(maxTableName) == 0 || def.Name > maxTableName {
|
||||
maxTableName = def.Name
|
||||
}
|
||||
|
||||
tableQueries = append(tableQueries, &accessLogTableQuery{
|
||||
daoWrapper: daoWrapper,
|
||||
name: def.Name,
|
||||
hasRemoteAddrField: def.HasRemoteAddr,
|
||||
hasDomainField: def.HasDomain,
|
||||
})
|
||||
}
|
||||
|
||||
// 检查各个分表是否一致
|
||||
if partition < 0 {
|
||||
var newTableQueries = []*accessLogTableQuery{}
|
||||
for _, tableQuery := range tableQueries {
|
||||
if tableQuery.name != maxTableName {
|
||||
continue
|
||||
}
|
||||
newTableQueries = append(newTableQueries, tableQuery)
|
||||
}
|
||||
tableQueries = newTableQueries
|
||||
}
|
||||
|
||||
if len(tableQueries) == 0 {
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
var locker = sync.Mutex{}
|
||||
|
||||
// 这里正则表达式中的括号不能轻易变更,因为后面有引用
|
||||
// TODO 支持多个查询条件的组合,比如 status:200 proto:HTTP/1.1
|
||||
var statusPrefixReg = regexp.MustCompile(`status:\s*(\d{3})\b`)
|
||||
var statusRangeReg = regexp.MustCompile(`status:\s*(\d{3})-(\d{3})\b`)
|
||||
var urlReg = regexp.MustCompile(`^(http|https)://`)
|
||||
var requestPathReg = regexp.MustCompile(`requestPath:(\S+)`)
|
||||
var protoReg = regexp.MustCompile(`proto:(\S+)`)
|
||||
var schemeReg = regexp.MustCompile(`scheme:(\S+)`)
|
||||
|
||||
var count = len(tableQueries)
|
||||
var wg = &sync.WaitGroup{}
|
||||
wg.Add(count)
|
||||
for _, tableQuery := range tableQueries {
|
||||
go func(tableQuery *accessLogTableQuery, keyword string) {
|
||||
defer wg.Done()
|
||||
|
||||
dao := daoWrapper.DAO
|
||||
|
||||
tableName, hasRemoteAddrField, hasDomainField, exists, err := findHTTPAccessLogTableName(dao.Instance, day)
|
||||
if err != nil {
|
||||
logs.Println("[DB_NODE]" + err.Error())
|
||||
return
|
||||
}
|
||||
if !exists {
|
||||
// 表格不存在则跳过
|
||||
return
|
||||
}
|
||||
|
||||
query := dao.Query(tx)
|
||||
var dao = tableQuery.daoWrapper.DAO
|
||||
var query = dao.Query(tx)
|
||||
|
||||
// 条件
|
||||
if nodeId > 0 {
|
||||
query.Attr("nodeId", nodeId)
|
||||
} else if clusterId > 0 {
|
||||
nodeIds, err := SharedNodeDAO.FindAllEnabledNodeIdsWithClusterId(tx, clusterId)
|
||||
if err != nil {
|
||||
remotelogs.Error("DBNODE", err.Error())
|
||||
return
|
||||
}
|
||||
if len(nodeIds) > 0 {
|
||||
sort.Slice(nodeIds, func(i, j int) bool {
|
||||
return nodeIds[i] < nodeIds[j]
|
||||
})
|
||||
var nodeIdStrings = []string{}
|
||||
for _, subNodeId := range nodeIds {
|
||||
nodeIdStrings = append(nodeIdStrings, types.String(subNodeId))
|
||||
@@ -370,7 +457,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
// keyword
|
||||
if len(ip) > 0 {
|
||||
// TODO 支持IP范围
|
||||
if hasRemoteAddrField {
|
||||
if tableQuery.hasRemoteAddrField {
|
||||
// IP格式
|
||||
if strings.Contains(ip, ",") || strings.Contains(ip, "-") {
|
||||
rangeConfig, err := shared.ParseIPRange(ip)
|
||||
@@ -380,6 +467,9 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 去掉IPv6的[]
|
||||
ip = strings.Trim(ip, "[]")
|
||||
|
||||
query.Attr("remoteAddr", ip)
|
||||
query.UseIndex("remoteAddr")
|
||||
}
|
||||
@@ -389,7 +479,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
}
|
||||
}
|
||||
if len(domain) > 0 {
|
||||
if hasDomainField {
|
||||
if tableQuery.hasDomainField {
|
||||
if strings.Contains(domain, "*") {
|
||||
domain = strings.ReplaceAll(domain, "*", "%")
|
||||
domain = regexp.MustCompile(`[^a-zA-Z0-9-.%]`).ReplaceAllString(domain, "")
|
||||
@@ -404,24 +494,60 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
Param("host1", domain)
|
||||
}
|
||||
}
|
||||
|
||||
if len(keyword) > 0 {
|
||||
// remoteAddr
|
||||
if hasRemoteAddrField && net.ParseIP(keyword) != nil {
|
||||
var isSpecialKeyword = false
|
||||
|
||||
if tableQuery.hasRemoteAddrField && net.ParseIP(keyword) != nil { // ip
|
||||
isSpecialKeyword = true
|
||||
query.Attr("remoteAddr", keyword)
|
||||
} else if hasRemoteAddrField && regexp.MustCompile(`^ip:.+`).MatchString(keyword) {
|
||||
} else if tableQuery.hasRemoteAddrField && regexp.MustCompile(`^ip:.+`).MatchString(keyword) { // ip:x.x.x.x
|
||||
isSpecialKeyword = true
|
||||
keyword = keyword[3:]
|
||||
pieces := strings.SplitN(keyword, ",", 2)
|
||||
if len(pieces) == 1 || len(pieces[1]) == 0 {
|
||||
if len(pieces) == 1 || len(pieces[1]) == 0 || pieces[0] == pieces[1] {
|
||||
query.Attr("remoteAddr", pieces[0])
|
||||
} else {
|
||||
query.Between("INET_ATON(remoteAddr)", utils.IP2Long(pieces[0]), utils.IP2Long(pieces[1]))
|
||||
}
|
||||
} else {
|
||||
} else if statusRangeReg.MatchString(keyword) { // status:200-400
|
||||
isSpecialKeyword = true
|
||||
var matches = statusRangeReg.FindStringSubmatch(keyword)
|
||||
query.Between("status", types.Int(matches[1]), types.Int(matches[2]))
|
||||
} else if statusPrefixReg.MatchString(keyword) { // status:200
|
||||
isSpecialKeyword = true
|
||||
var matches = statusPrefixReg.FindStringSubmatch(keyword)
|
||||
query.Attr("status", matches[1])
|
||||
} else if requestPathReg.MatchString(keyword) {
|
||||
isSpecialKeyword = true
|
||||
var matches = requestPathReg.FindStringSubmatch(keyword)
|
||||
query.Where("JSON_EXTRACT(content, '$.requestPath')=:keyword").
|
||||
Param("keyword", matches[1])
|
||||
} else if protoReg.MatchString(keyword) {
|
||||
isSpecialKeyword = true
|
||||
var matches = protoReg.FindStringSubmatch(keyword)
|
||||
query.Where("JSON_EXTRACT(content, '$.proto')=:keyword").
|
||||
Param("keyword", strings.ToUpper(matches[1]))
|
||||
} else if schemeReg.MatchString(keyword) {
|
||||
isSpecialKeyword = true
|
||||
var matches = schemeReg.FindStringSubmatch(keyword)
|
||||
query.Where("JSON_EXTRACT(content, '$.scheme')=:keyword").
|
||||
Param("keyword", strings.ToLower(matches[1]))
|
||||
} else if urlReg.MatchString(keyword) { // https://xxx/yyy
|
||||
u, err := url.Parse(keyword)
|
||||
if err == nil {
|
||||
isSpecialKeyword = true
|
||||
query.Attr("domain", u.Host)
|
||||
query.Where("JSON_EXTRACT(content, '$.requestURI') LIKE :keyword").
|
||||
Param("keyword", dbutils.QuoteLikePrefix("\""+u.RequestURI()))
|
||||
}
|
||||
}
|
||||
if !isSpecialKeyword {
|
||||
if regexp.MustCompile(`^ip:.+`).MatchString(keyword) {
|
||||
keyword = keyword[3:]
|
||||
}
|
||||
|
||||
useOriginKeyword := false
|
||||
var useOriginKeyword = false
|
||||
|
||||
where := "JSON_EXTRACT(content, '$.remoteAddr') LIKE :keyword OR JSON_EXTRACT(content, '$.requestURI') LIKE :keyword OR JSON_EXTRACT(content, '$.host') LIKE :keyword OR JSON_EXTRACT(content, '$.userAgent') LIKE :keyword"
|
||||
|
||||
@@ -447,13 +573,13 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
|
||||
// 响应状态码
|
||||
if regexp.MustCompile(`^\d{3}$`).MatchString(keyword) {
|
||||
where += " OR JSON_EXTRACT(content, '$.status')=:intKeyword"
|
||||
where += " OR status=:intKeyword"
|
||||
query.Param("intKeyword", types.Int(keyword))
|
||||
}
|
||||
|
||||
if regexp.MustCompile(`^\d{3}-\d{3}$`).MatchString(keyword) {
|
||||
pieces := strings.Split(keyword, "-")
|
||||
where += " OR JSON_EXTRACT(content, '$.status') BETWEEN :intKeyword1 AND :intKeyword2"
|
||||
where += " OR status BETWEEN :intKeyword1 AND :intKeyword2"
|
||||
query.Param("intKeyword1", types.Int(pieces[0]))
|
||||
query.Param("intKeyword2", types.Int(pieces[1]))
|
||||
}
|
||||
@@ -464,13 +590,27 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
}
|
||||
|
||||
query.Where("("+where+")").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
if useOriginKeyword {
|
||||
query.Param("originKeyword", keyword)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// hourFrom - hourTo
|
||||
if len(hourFrom) > 0 && len(hourTo) > 0 {
|
||||
var hourFromInt = types.Int(hourFrom)
|
||||
var hourToInt = types.Int(hourTo)
|
||||
if hourFromInt >= 0 && hourFromInt <= 23 && hourToInt >= hourFromInt && hourToInt <= 23 {
|
||||
var y = types.Int(day[:4])
|
||||
var m = types.Int(day[4:6])
|
||||
var d = types.Int(day[6:])
|
||||
var timeFrom = time.Date(y, time.Month(m), d, hourFromInt, 0, 0, 0, time.Local)
|
||||
var timeTo = time.Date(y, time.Month(m), d, hourToInt, 59, 59, 0, time.Local)
|
||||
query.Between("createdAt", timeFrom.Unix(), timeTo.Unix())
|
||||
}
|
||||
}
|
||||
|
||||
// offset
|
||||
if len(lastRequestId) > 0 {
|
||||
if !reverse {
|
||||
@@ -490,20 +630,21 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
|
||||
// 开始查询
|
||||
ones, err := query.
|
||||
Table(tableName).
|
||||
Table(tableQuery.name).
|
||||
Limit(size).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
logs.Println("[DB_NODE]" + err.Error())
|
||||
remotelogs.Println("DB_NODE", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
locker.Lock()
|
||||
for _, one := range ones {
|
||||
accessLog := one.(*HTTPAccessLog)
|
||||
var accessLog = one.(*HTTPAccessLog)
|
||||
result = append(result, accessLog)
|
||||
}
|
||||
locker.Unlock()
|
||||
}(daoWrapper)
|
||||
}(tableQuery, keyword)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
@@ -524,7 +665,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
result = result[:size]
|
||||
}
|
||||
|
||||
requestId := result[len(result)-1].RequestId
|
||||
var requestId = result[len(result)-1].RequestId
|
||||
if reverse {
|
||||
lists.Reverse(result)
|
||||
}
|
||||
@@ -556,28 +697,36 @@ func (this *HTTPAccessLogDAO) FindAccessLogWithRequestId(tx *dbs.Tx, requestId s
|
||||
}}
|
||||
}
|
||||
|
||||
count := len(daoList)
|
||||
wg := &sync.WaitGroup{}
|
||||
// 准备查询
|
||||
var day = timeutil.FormatTime("Ymd", types.Int64(requestId[:10]))
|
||||
var tableQueries = []*accessLogTableQuery{}
|
||||
for _, daoWrapper := range daoList {
|
||||
var instance = daoWrapper.DAO.Instance
|
||||
tableDefs, err := SharedHTTPAccessLogManager.FindTables(instance, day)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, def := range tableDefs {
|
||||
tableQueries = append(tableQueries, &accessLogTableQuery{
|
||||
daoWrapper: daoWrapper,
|
||||
name: def.Name,
|
||||
hasRemoteAddrField: def.HasRemoteAddr,
|
||||
hasDomainField: def.HasDomain,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var count = len(tableQueries)
|
||||
var wg = &sync.WaitGroup{}
|
||||
wg.Add(count)
|
||||
var result *HTTPAccessLog = nil
|
||||
day := timeutil.FormatTime("Ymd", types.Int64(requestId[:10]))
|
||||
for _, daoWrapper := range daoList {
|
||||
go func(daoWrapper *HTTPAccessLogDAOWrapper) {
|
||||
for _, tableQuery := range tableQueries {
|
||||
go func(tableQuery *accessLogTableQuery) {
|
||||
defer wg.Done()
|
||||
|
||||
dao := daoWrapper.DAO
|
||||
|
||||
tableName, _, _, exists, err := findHTTPAccessLogTableName(dao.Instance, day)
|
||||
if err != nil {
|
||||
logs.Println("[DB_NODE]" + err.Error())
|
||||
return
|
||||
}
|
||||
if !exists {
|
||||
return
|
||||
}
|
||||
|
||||
var dao = tableQuery.daoWrapper.DAO
|
||||
one, err := dao.Query(tx).
|
||||
Table(tableName).
|
||||
Table(tableQuery.name).
|
||||
Attr("requestId", requestId).
|
||||
Find()
|
||||
if err != nil {
|
||||
@@ -587,7 +736,7 @@ func (this *HTTPAccessLogDAO) FindAccessLogWithRequestId(tx *dbs.Tx, requestId s
|
||||
if one != nil {
|
||||
result = one.(*HTTPAccessLog)
|
||||
}
|
||||
}(daoWrapper)
|
||||
}(tableQuery)
|
||||
}
|
||||
wg.Wait()
|
||||
return result, nil
|
||||
@@ -623,11 +772,18 @@ func (this *HTTPAccessLogDAO) SetupQueue() {
|
||||
config.MaxLength = 100_000
|
||||
}
|
||||
|
||||
accessLogEnableAutoPartial = config.EnableAutoPartial
|
||||
if config.RowsPerTable > 0 {
|
||||
accessLogRowsPerTable = config.RowsPerTable
|
||||
}
|
||||
|
||||
if accessLogQueueMaxLength != config.MaxLength {
|
||||
accessLogQueueMaxLength = config.MaxLength
|
||||
oldAccessLogQueue = accessLogQueue
|
||||
accessLogQueue = make(chan *pb.HTTPAccessLog, config.MaxLength)
|
||||
}
|
||||
|
||||
remotelogs.Println("HTTP_ACCESS_LOG_QUEUE", "change queue max length: "+types.String(config.MaxLength)+", percent: "+types.String(config.Percent)+", countPerSecond: "+types.String(config.CountPerSecond))
|
||||
if Tea.IsTesting() {
|
||||
remotelogs.Println("HTTP_ACCESS_LOG_QUEUE", "change queue "+string(configJSON))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
@@ -53,7 +54,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "", 10, timeutil.Format("Ymd"), 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, -1, "", 10, timeutil.Format("Ymd"), "", "", 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -80,7 +81,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Page(t *testing.T) {
|
||||
times := 0 // 防止循环次数太多
|
||||
for {
|
||||
before := time.Now()
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, lastRequestId, 2, timeutil.Format("Ymd"), 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, -1, lastRequestId, 2, timeutil.Format("Ymd"), "", "", 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
cost := time.Since(before).Seconds()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -111,7 +112,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Reverse(t *testing.T) {
|
||||
}
|
||||
|
||||
before := time.Now()
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "16023261176446590001000000000000003500000004", 2, timeutil.Format("Ymd"), 0, 0, 0, true, false, 0, 0, 0, false, 0, "", "", "")
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, -1, "16023261176446590001000000000000003500000004", 2, timeutil.Format("Ymd"), "", "", 0, 0, 0, true, false, 0, 0, 0, false, 0, "", "", "")
|
||||
cost := time.Since(before).Seconds()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -136,7 +137,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Page_NotExists(t *testing.T) {
|
||||
times := 0 // 防止循环次数太多
|
||||
for {
|
||||
before := time.Now()
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, lastRequestId, 2, timeutil.Format("Ymd", time.Now().AddDate(0, 0, 1)), 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, -1, lastRequestId, 2, timeutil.Format("Ymd", time.Now().AddDate(0, 0, 1)), "", "", 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
cost := time.Since(before).Seconds()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -157,3 +158,13 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Page_NotExists(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHTTPAccessLogDAO_JSONEncode(b *testing.B) {
|
||||
var accessLog = &pb.HTTPAccessLog{
|
||||
RequestPath: "/hello/world",
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = json.Marshal(accessLog)
|
||||
}
|
||||
}
|
||||
|
||||
439
internal/db/models/http_access_log_manager.go
Normal file
439
internal/db/models/http_access_log_manager.go
Normal file
@@ -0,0 +1,439 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// 访问日志的两个表格形式
|
||||
// 括号位置需要固定,会用来读取日期和分区
|
||||
var accessLogTableMainReg = regexp.MustCompile(`_(\d{8})$`)
|
||||
var accessLogTablePartialReg = regexp.MustCompile(`_(\d{8})_(\d{4})$`)
|
||||
|
||||
var SharedHTTPAccessLogManager = NewHTTPAccessLogManager()
|
||||
|
||||
type HTTPAccessLogManager struct {
|
||||
currentTableMapping map[string]*httpAccessLogDefinition // dsn => def
|
||||
|
||||
locker sync.Mutex
|
||||
}
|
||||
|
||||
func NewHTTPAccessLogManager() *HTTPAccessLogManager {
|
||||
return &HTTPAccessLogManager{
|
||||
currentTableMapping: map[string]*httpAccessLogDefinition{},
|
||||
}
|
||||
}
|
||||
|
||||
// FindTableNames 读取数据库中某日所有日志表名称
|
||||
func (this *HTTPAccessLogManager) FindTableNames(db *dbs.DB, day string) ([]string, error) {
|
||||
var results = []string{}
|
||||
|
||||
// 需要防止用户设置了表名自动小写
|
||||
for _, prefix := range []string{"edgeHTTPAccessLogs_" + day + "%", "edgehttpaccesslogs_" + day + "%"} {
|
||||
ones, columnNames, err := db.FindPreparedOnes(`SHOW TABLES LIKE '` + prefix + `'`)
|
||||
if err != nil {
|
||||
return nil, errors.New("query table names error: " + err.Error())
|
||||
}
|
||||
|
||||
var columnName = columnNames[0]
|
||||
|
||||
for _, one := range ones {
|
||||
var tableName = one[columnName].(string)
|
||||
|
||||
if lists.ContainsString(results, tableName) {
|
||||
continue
|
||||
}
|
||||
|
||||
if accessLogTableMainReg.MatchString(tableName) || accessLogTablePartialReg.MatchString(tableName) {
|
||||
results = append(results, tableName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 排序
|
||||
// 这里不能直接使用sort.Strings(),因为表名里面可能大小写混合
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
var name1 = results[i]
|
||||
var name2 = results[j]
|
||||
if len(name1) < len(name2) {
|
||||
return true
|
||||
}
|
||||
return strings.ToLower(name1) < strings.ToLower(name2)
|
||||
})
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// FindTables 读取数据库中某日所有日志表
|
||||
func (this *HTTPAccessLogManager) FindTables(db *dbs.DB, day string) ([]*httpAccessLogDefinition, error) {
|
||||
var results = []*httpAccessLogDefinition{}
|
||||
var tableNames = []string{}
|
||||
|
||||
config, err := db.Config()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var cachePrefix = config.Dsn
|
||||
|
||||
// 需要防止用户设置了表名自动小写
|
||||
for _, prefix := range []string{"edgeHTTPAccessLogs_" + day + "%", "edgehttpaccesslogs_" + day + "%"} {
|
||||
ones, columnNames, err := db.FindPreparedOnes(`SHOW TABLES LIKE '` + prefix + `'`)
|
||||
if err != nil {
|
||||
return nil, errors.New("query table names error: " + err.Error())
|
||||
}
|
||||
|
||||
var columnName = columnNames[0]
|
||||
|
||||
for _, one := range ones {
|
||||
var tableName = one[columnName].(string)
|
||||
|
||||
if lists.ContainsString(tableNames, tableName) {
|
||||
continue
|
||||
}
|
||||
|
||||
if accessLogTableMainReg.MatchString(tableName) {
|
||||
tableNames = append(tableNames, tableName)
|
||||
|
||||
// 查找已有的表格信息,避免SHOW FIELDS
|
||||
var tableDay = tableName[strings.LastIndex(tableName, "_")+1:]
|
||||
var cacheKey = this.composeTableCacheKey(cachePrefix, tableDay)
|
||||
this.locker.Lock()
|
||||
currentTableDef, ok := this.currentTableMapping[cacheKey]
|
||||
this.locker.Unlock()
|
||||
if ok {
|
||||
results = append(results, &httpAccessLogDefinition{
|
||||
Name: tableName,
|
||||
HasRemoteAddr: currentTableDef.HasRemoteAddr,
|
||||
HasDomain: currentTableDef.HasDomain,
|
||||
Exists: true,
|
||||
})
|
||||
} else {
|
||||
hasRemoteAddrField, hasDomainField, err := this.checkTableFields(db, tableName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
results = append(results, &httpAccessLogDefinition{
|
||||
Name: tableName,
|
||||
HasRemoteAddr: hasRemoteAddrField,
|
||||
HasDomain: hasDomainField,
|
||||
Exists: true,
|
||||
})
|
||||
}
|
||||
} else if accessLogTablePartialReg.MatchString(tableName) {
|
||||
tableNames = append(tableNames, tableName)
|
||||
|
||||
results = append(results, &httpAccessLogDefinition{
|
||||
Name: tableName,
|
||||
HasRemoteAddr: true,
|
||||
HasDomain: true,
|
||||
Exists: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 排序
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return results[i].Name < results[j].Name
|
||||
})
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (this *HTTPAccessLogManager) FindPartitionTable(db *dbs.DB, day string, partition int32) (*httpAccessLogDefinition, error) {
|
||||
var tableNames []string
|
||||
if partition < 0 {
|
||||
tableList, err := this.FindTables(db, day)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(tableList) > 0 {
|
||||
return tableList[len(tableList)-1], nil
|
||||
}
|
||||
|
||||
return &httpAccessLogDefinition{
|
||||
Name: "",
|
||||
HasRemoteAddr: false,
|
||||
HasDomain: false,
|
||||
Exists: false,
|
||||
}, nil
|
||||
} else if partition == 0 {
|
||||
tableNames = []string{"edgeHTTPAccessLogs_" + day, "edgehttpaccesslogs_" + day}
|
||||
} else {
|
||||
tableNames = []string{"edgeHTTPAccessLogs_" + day + "_" + fmt.Sprintf("%04d", partition), "edgehttpaccesslogs_" + day + "_" + fmt.Sprintf("%04d", partition)}
|
||||
}
|
||||
for _, tableName := range tableNames {
|
||||
hasRemoteField, hasDomainField, err := this.checkTableFields(db, tableName)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
return &httpAccessLogDefinition{
|
||||
Name: tableName,
|
||||
HasRemoteAddr: hasRemoteField,
|
||||
HasDomain: hasDomainField,
|
||||
Exists: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &httpAccessLogDefinition{
|
||||
Name: "",
|
||||
HasRemoteAddr: false,
|
||||
HasDomain: false,
|
||||
Exists: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// FindLastTable 根据日期获取上一个可以使用的表名
|
||||
// 表名组成
|
||||
// - PREFIX_DAY
|
||||
// - PREFIX_DAY_0001
|
||||
func (this *HTTPAccessLogManager) FindLastTable(db *dbs.DB, day string, force bool) (*httpAccessLogDefinition, error) {
|
||||
this.locker.Lock()
|
||||
defer this.locker.Unlock()
|
||||
|
||||
config, err := db.Config()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var cachePrefix = config.Dsn
|
||||
var cacheKey = this.composeTableCacheKey(cachePrefix, day)
|
||||
def, ok := this.currentTableMapping[cacheKey]
|
||||
if ok {
|
||||
return def, nil
|
||||
}
|
||||
|
||||
def, err = this.findTableWithoutCache(db, day, force)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 只有存在的表格才缓存
|
||||
if def != nil && def.Exists {
|
||||
this.currentTableMapping[cacheKey] = def
|
||||
|
||||
// 清除过时缓存
|
||||
for oldCacheKey := range this.currentTableMapping {
|
||||
var dayIndex = strings.LastIndex(oldCacheKey, "_")
|
||||
if dayIndex > 0 {
|
||||
var oldPrefix = oldCacheKey[:dayIndex]
|
||||
var oldDay = oldCacheKey[dayIndex+1:]
|
||||
if oldPrefix == cachePrefix && oldDay < day {
|
||||
delete(this.currentTableMapping, oldCacheKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return def, nil
|
||||
}
|
||||
|
||||
// CreateTable 创建访问日志表格
|
||||
func (this *HTTPAccessLogManager) CreateTable(db *dbs.DB, tableName string) error {
|
||||
_, err := db.Exec("CREATE TABLE `" + tableName + "` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `serverId` int(11) unsigned DEFAULT '0' COMMENT '服务ID',\n `nodeId` int(11) unsigned DEFAULT '0' COMMENT '节点ID',\n `status` int(3) unsigned DEFAULT '0' COMMENT '状态码',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `content` json DEFAULT NULL COMMENT '日志内容',\n `requestId` varchar(128) DEFAULT NULL COMMENT '请求ID',\n `firewallPolicyId` int(11) unsigned DEFAULT '0' COMMENT 'WAF策略ID',\n `firewallRuleGroupId` int(11) unsigned DEFAULT '0' COMMENT 'WAF分组ID',\n `firewallRuleSetId` int(11) unsigned DEFAULT '0' COMMENT 'WAF集ID',\n `firewallRuleId` int(11) unsigned DEFAULT '0' COMMENT 'WAF规则ID',\n `remoteAddr` varchar(64) DEFAULT NULL COMMENT 'IP地址',\n `domain` varchar(128) DEFAULT NULL COMMENT '域名',\n `requestBody` mediumblob COMMENT '请求内容',\n `responseBody` mediumblob COMMENT '响应内容',\n PRIMARY KEY (`id`),\n KEY `serverId` (`serverId`),\n KEY `nodeId` (`nodeId`),\n KEY `serverId_status` (`serverId`,`status`),\n KEY `requestId` (`requestId`),\n KEY `firewallPolicyId` (`firewallPolicyId`),\n KEY `firewallRuleGroupId` (`firewallRuleGroupId`),\n KEY `firewallRuleSetId` (`firewallRuleSetId`),\n KEY `firewallRuleId` (`firewallRuleId`),\n KEY `remoteAddr` (`remoteAddr`),\n KEY `domain` (`domain`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='访问日志';")
|
||||
if err != nil {
|
||||
if CheckSQLErrCode(err, 1050) { // Error 1050: Table 'xxx' already exists
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResetTable 清除某个数据库表名缓存
|
||||
func (this *HTTPAccessLogManager) ResetTable(db *dbs.DB, day string) {
|
||||
this.locker.Lock()
|
||||
defer this.locker.Unlock()
|
||||
|
||||
config, err := db.Config()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
delete(this.currentTableMapping, this.composeTableCacheKey(config.Dsn, day))
|
||||
}
|
||||
|
||||
// TablePartition 从表名中获取分区
|
||||
func (this *HTTPAccessLogManager) TablePartition(tableName string) (partition int32) {
|
||||
if accessLogTablePartialReg.MatchString(tableName) {
|
||||
return types.Int32(accessLogTablePartialReg.FindStringSubmatch(tableName)[2])
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// FindLatestPartition 读取最后一个分区
|
||||
func (this *HTTPAccessLogManager) FindLatestPartition(day string) (int32, error) {
|
||||
var dbList = AllAccessLogDBs()
|
||||
if len(dbList) == 0 {
|
||||
return 0, errors.New("no valid database")
|
||||
}
|
||||
|
||||
var partitions = []int32{}
|
||||
var locker sync.Mutex
|
||||
|
||||
var wg = sync.WaitGroup{}
|
||||
wg.Add(len(dbList))
|
||||
|
||||
var lastErr error
|
||||
for _, db := range dbList {
|
||||
go func(db *dbs.DB) {
|
||||
defer wg.Done()
|
||||
|
||||
names, err := this.FindTableNames(db, day)
|
||||
if err != nil {
|
||||
lastErr = err
|
||||
}
|
||||
for _, name := range names {
|
||||
var partition = this.TablePartition(name)
|
||||
locker.Lock()
|
||||
if !lists.Contains(partitions, partition) {
|
||||
partitions = append(partitions, partition)
|
||||
}
|
||||
locker.Unlock()
|
||||
}
|
||||
}(db)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
if lastErr != nil {
|
||||
return 0, lastErr
|
||||
}
|
||||
|
||||
if len(partitions) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return partitions[len(partitions)-1], nil
|
||||
}
|
||||
|
||||
// 查找某个表格
|
||||
func (this *HTTPAccessLogManager) findTableWithoutCache(db *dbs.DB, day string, force bool) (*httpAccessLogDefinition, error) {
|
||||
tableNames, err := this.FindTableNames(db, day)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var prefix = "edgeHTTPAccessLogs_" + day
|
||||
|
||||
if len(tableNames) == 0 {
|
||||
if force {
|
||||
err := this.CreateTable(db, prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &httpAccessLogDefinition{
|
||||
Name: prefix,
|
||||
HasRemoteAddr: true,
|
||||
HasDomain: true,
|
||||
Exists: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &httpAccessLogDefinition{
|
||||
Name: prefix,
|
||||
HasRemoteAddr: true,
|
||||
HasDomain: true,
|
||||
Exists: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var lastTableName = tableNames[len(tableNames)-1]
|
||||
if !force || !accessLogEnableAutoPartial || accessLogRowsPerTable <= 0 {
|
||||
hasRemoteAddrField, hasDomainField, err := this.checkTableFields(db, lastTableName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &httpAccessLogDefinition{
|
||||
Name: lastTableName,
|
||||
HasRemoteAddr: hasRemoteAddrField,
|
||||
HasDomain: hasDomainField,
|
||||
Exists: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 检查是否生成下个分表
|
||||
lastId, err := db.FindCol(0, "SELECT id FROM "+lastTableName+" ORDER BY id DESC LIMIT 1")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if lastId != nil {
|
||||
var lastInt64Id = types.Int64(lastId)
|
||||
if accessLogRowsPerTable > 0 && lastInt64Id >= accessLogRowsPerTable {
|
||||
// create next partial table
|
||||
var nextTableName = ""
|
||||
if accessLogTableMainReg.MatchString(lastTableName) {
|
||||
nextTableName = prefix + "_0001"
|
||||
} else if accessLogTablePartialReg.MatchString(lastTableName) {
|
||||
var matches = accessLogTablePartialReg.FindStringSubmatch(lastTableName)
|
||||
if len(matches) < 3 {
|
||||
return nil, errors.New("fatal error: invalid 'accessLogTablePartialReg'")
|
||||
}
|
||||
var lastPartial = matches[2]
|
||||
nextTableName = prefix + "_" + fmt.Sprintf("%04d", types.Int(lastPartial)+1)
|
||||
} else {
|
||||
nextTableName = prefix + "_0001"
|
||||
}
|
||||
|
||||
err = this.CreateTable(db, nextTableName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &httpAccessLogDefinition{
|
||||
Name: nextTableName,
|
||||
HasRemoteAddr: true,
|
||||
HasDomain: true,
|
||||
Exists: true,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// 检查字段
|
||||
hasRemoteAddrField, hasDomainField, err := this.checkTableFields(db, lastTableName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &httpAccessLogDefinition{
|
||||
Name: lastTableName,
|
||||
HasRemoteAddr: hasRemoteAddrField,
|
||||
HasDomain: hasDomainField,
|
||||
Exists: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TODO 考虑缓存检查结果
|
||||
func (this *HTTPAccessLogManager) checkTableFields(db *dbs.DB, tableName string) (hasRemoteAddrField bool, hasDomainField bool, err error) {
|
||||
fields, _, err := db.FindPreparedOnes("SHOW FIELDS FROM " + tableName)
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
for _, field := range fields {
|
||||
var fieldName = field.GetString("Field")
|
||||
if strings.ToLower(fieldName) == strings.ToLower("remoteAddr") {
|
||||
hasRemoteAddrField = true
|
||||
}
|
||||
if strings.ToLower(fieldName) == "domain" {
|
||||
hasDomainField = true
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 组合表格的缓存Key
|
||||
func (this *HTTPAccessLogManager) composeTableCacheKey(dsn string, day string) string {
|
||||
// 注意:格式一定要固定,下面清除缓存的时候需要用到
|
||||
return dsn + "_" + day
|
||||
}
|
||||
189
internal/db/models/http_access_log_manager_test.go
Normal file
189
internal/db/models/http_access_log_manager_test.go
Normal file
@@ -0,0 +1,189 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package models_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestNewHTTPAccessLogManager(t *testing.T) {
|
||||
var config = &dbs.DBConfig{
|
||||
Driver: "mysql",
|
||||
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
|
||||
Prefix: "edge",
|
||||
Connections: struct {
|
||||
Pool int `yaml:"pool"`
|
||||
Max int `yaml:"max"`
|
||||
Life string `yaml:"life"`
|
||||
LifeDuration time.Duration `yaml:",omitempty"`
|
||||
}{},
|
||||
Models: struct {
|
||||
Package string `yaml:"package"`
|
||||
}{},
|
||||
}
|
||||
|
||||
db, err := dbs.NewInstanceFromConfig(config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
_ = db.Close()
|
||||
}()
|
||||
|
||||
var manager = models.SharedHTTPAccessLogManager
|
||||
err = manager.CreateTable(db, "accessLog_1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPAccessLogManager_FindTableNames(t *testing.T) {
|
||||
var config = &dbs.DBConfig{
|
||||
Driver: "mysql",
|
||||
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
|
||||
Prefix: "edge",
|
||||
Connections: struct {
|
||||
Pool int `yaml:"pool"`
|
||||
Max int `yaml:"max"`
|
||||
Life string `yaml:"life"`
|
||||
LifeDuration time.Duration `yaml:",omitempty"`
|
||||
}{},
|
||||
Models: struct {
|
||||
Package string `yaml:"package"`
|
||||
}{},
|
||||
}
|
||||
|
||||
db, err := dbs.NewInstanceFromConfig(config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
_ = db.Close()
|
||||
}()
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
var before = time.Now()
|
||||
tables, err := models.SharedHTTPAccessLogManager.FindTables(db, "20220306")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
data, err := json.Marshal(tables)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(string(data))
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPAccessLogManager_FindTables(t *testing.T) {
|
||||
var config = &dbs.DBConfig{
|
||||
Driver: "mysql",
|
||||
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
|
||||
Prefix: "edge",
|
||||
Connections: struct {
|
||||
Pool int `yaml:"pool"`
|
||||
Max int `yaml:"max"`
|
||||
Life string `yaml:"life"`
|
||||
LifeDuration time.Duration `yaml:",omitempty"`
|
||||
}{},
|
||||
Models: struct {
|
||||
Package string `yaml:"package"`
|
||||
}{},
|
||||
}
|
||||
|
||||
db, err := dbs.NewInstanceFromConfig(config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
_ = db.Close()
|
||||
}()
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
var before = time.Now()
|
||||
tables, err := models.SharedHTTPAccessLogManager.FindTables(db, "20220306")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
data, err := json.Marshal(tables)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(string(data))
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPAccessLogManager_FindLastTable(t *testing.T) {
|
||||
var config = &dbs.DBConfig{
|
||||
Driver: "mysql",
|
||||
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
|
||||
Prefix: "edge",
|
||||
Connections: struct {
|
||||
Pool int `yaml:"pool"`
|
||||
Max int `yaml:"max"`
|
||||
Life string `yaml:"life"`
|
||||
LifeDuration time.Duration `yaml:",omitempty"`
|
||||
}{},
|
||||
Models: struct {
|
||||
Package string `yaml:"package"`
|
||||
}{},
|
||||
}
|
||||
|
||||
db, err := dbs.NewInstanceFromConfig(config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
_ = db.Close()
|
||||
}()
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
var before = time.Now()
|
||||
tableDef, err := models.SharedHTTPAccessLogManager.FindLastTable(db, "20220306", false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
data, err := json.Marshal(tableDef)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(string(data))
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPAccessLogManager_FindPartitionTable(t *testing.T) {
|
||||
var config = &dbs.DBConfig{
|
||||
Driver: "mysql",
|
||||
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
|
||||
Prefix: "edge",
|
||||
Connections: struct {
|
||||
Pool int `yaml:"pool"`
|
||||
Max int `yaml:"max"`
|
||||
Life string `yaml:"life"`
|
||||
LifeDuration time.Duration `yaml:",omitempty"`
|
||||
}{},
|
||||
Models: struct {
|
||||
Package string `yaml:"package"`
|
||||
}{},
|
||||
}
|
||||
|
||||
db, err := dbs.NewInstanceFromConfig(config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
_ = db.Close()
|
||||
}()
|
||||
|
||||
t.Log(models.SharedHTTPAccessLogManager.FindPartitionTable(db, timeutil.Format("Ymd", time.Now().AddDate(0, 0, -1)), -1))
|
||||
t.Log(models.SharedHTTPAccessLogManager.FindPartitionTable(db, timeutil.Format("Ymd", time.Now().AddDate(0, 0, -1)), 0))
|
||||
t.Log(models.SharedHTTPAccessLogManager.FindPartitionTable(db, timeutil.Format("Ymd", time.Now().AddDate(0, 0, -1)), 1))
|
||||
}
|
||||
@@ -1,22 +1,24 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPAccessLog 访问日志
|
||||
type HTTPAccessLog struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
NodeId uint32 `field:"nodeId"` // 节点ID
|
||||
Status uint32 `field:"status"` // 状态码
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Content string `field:"content"` // 日志内容
|
||||
RequestId string `field:"requestId"` // 请求ID
|
||||
FirewallPolicyId uint32 `field:"firewallPolicyId"` // WAF策略ID
|
||||
FirewallRuleGroupId uint32 `field:"firewallRuleGroupId"` // WAF分组ID
|
||||
FirewallRuleSetId uint32 `field:"firewallRuleSetId"` // WAF集ID
|
||||
FirewallRuleId uint32 `field:"firewallRuleId"` // WAF规则ID
|
||||
RemoteAddr string `field:"remoteAddr"` // IP地址
|
||||
Domain string `field:"domain"` // 域名
|
||||
RequestBody string `field:"requestBody"` // 请求内容
|
||||
ResponseBody string `field:"responseBody"` // 响应内容
|
||||
Id uint64 `field:"id"` // ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
NodeId uint32 `field:"nodeId"` // 节点ID
|
||||
Status uint32 `field:"status"` // 状态码
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Content dbs.JSON `field:"content"` // 日志内容
|
||||
RequestId string `field:"requestId"` // 请求ID
|
||||
FirewallPolicyId uint32 `field:"firewallPolicyId"` // WAF策略ID
|
||||
FirewallRuleGroupId uint32 `field:"firewallRuleGroupId"` // WAF分组ID
|
||||
FirewallRuleSetId uint32 `field:"firewallRuleSetId"` // WAF集ID
|
||||
FirewallRuleId uint32 `field:"firewallRuleId"` // WAF规则ID
|
||||
RemoteAddr string `field:"remoteAddr"` // IP地址
|
||||
Domain string `field:"domain"` // 域名
|
||||
RequestBody []byte `field:"requestBody"` // 请求内容
|
||||
ResponseBody []byte `field:"responseBody"` // 响应内容
|
||||
}
|
||||
|
||||
type HTTPAccessLogOperator struct {
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
// ToPB 转换成PB对象
|
||||
func (this *HTTPAccessLog) ToPB() (*pb.HTTPAccessLog, error) {
|
||||
p := &pb.HTTPAccessLog{}
|
||||
err := json.Unmarshal([]byte(this.Content), p)
|
||||
err := json.Unmarshal(this.Content, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.RequestId = this.RequestId
|
||||
p.RequestBody = []byte(this.RequestBody)
|
||||
p.RequestBody = this.RequestBody
|
||||
return p, nil
|
||||
}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"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 (
|
||||
@@ -109,7 +106,7 @@ func (this *HTTPAccessLogPolicyDAO) FindAllEnabledAndOnPolicies(tx *dbs.Tx) (res
|
||||
}
|
||||
|
||||
// CreatePolicy 创建策略
|
||||
func (this *HTTPAccessLogPolicyDAO) CreatePolicy(tx *dbs.Tx, name string, policyType string, optionsJSON []byte, condsJSON []byte, isPublic bool) (policyId int64, err error) {
|
||||
func (this *HTTPAccessLogPolicyDAO) CreatePolicy(tx *dbs.Tx, name string, policyType string, optionsJSON []byte, condsJSON []byte, isPublic bool, firewallOnly bool) (policyId int64, err error) {
|
||||
var op = NewHTTPAccessLogPolicyOperator()
|
||||
op.Name = name
|
||||
op.Type = policyType
|
||||
@@ -121,12 +118,13 @@ func (this *HTTPAccessLogPolicyDAO) CreatePolicy(tx *dbs.Tx, name string, policy
|
||||
}
|
||||
op.IsPublic = isPublic
|
||||
op.IsOn = true
|
||||
op.FirewallOnly = firewallOnly
|
||||
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 {
|
||||
func (this *HTTPAccessLogPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, name string, optionsJSON []byte, condsJSON []byte, isPublic bool, firewallOnly bool, isOn bool) error {
|
||||
if policyId <= 0 {
|
||||
return errors.New("invalid policyId")
|
||||
}
|
||||
@@ -140,7 +138,6 @@ func (this *HTTPAccessLogPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, nam
|
||||
if oldOne == nil {
|
||||
return nil
|
||||
}
|
||||
var oldPolicy = oldOne.(*HTTPAccessLogPolicy)
|
||||
|
||||
var op = NewHTTPAccessLogPolicyOperator()
|
||||
op.Id = policyId
|
||||
@@ -156,22 +153,11 @@ func (this *HTTPAccessLogPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, nam
|
||||
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")
|
||||
}
|
||||
}
|
||||
// 版本号总是加1
|
||||
op.Version = dbs.SQL("version+1")
|
||||
|
||||
op.IsPublic = isPublic
|
||||
op.FirewallOnly = firewallOnly
|
||||
op.IsOn = isOn
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
@@ -1,36 +1,40 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPAccessLogPolicy 访问日志策略
|
||||
type HTTPAccessLogPolicy struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Name string `field:"name"` // 名称
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Type string `field:"type"` // 存储类型
|
||||
Options string `field:"options"` // 存储选项
|
||||
Conds string `field:"conds"` // 请求条件
|
||||
IsPublic uint8 `field:"isPublic"` // 是否为公用
|
||||
Version uint32 `field:"version"` // 版本号
|
||||
Id uint32 `field:"id"` // ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Name string `field:"name"` // 名称
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Type string `field:"type"` // 存储类型
|
||||
Options dbs.JSON `field:"options"` // 存储选项
|
||||
Conds dbs.JSON `field:"conds"` // 请求条件
|
||||
IsPublic bool `field:"isPublic"` // 是否为公用
|
||||
FirewallOnly uint8 `field:"firewallOnly"` // 是否只记录防火墙相关
|
||||
Version uint32 `field:"version"` // 版本号
|
||||
}
|
||||
|
||||
type HTTPAccessLogPolicyOperator struct {
|
||||
Id interface{} // ID
|
||||
TemplateId interface{} // 模版ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
Name interface{} // 名称
|
||||
IsOn interface{} // 是否启用
|
||||
Type interface{} // 存储类型
|
||||
Options interface{} // 存储选项
|
||||
Conds interface{} // 请求条件
|
||||
IsPublic interface{} // 是否为公用
|
||||
Version interface{} // 版本号
|
||||
Id interface{} // ID
|
||||
TemplateId interface{} // 模版ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
Name interface{} // 名称
|
||||
IsOn interface{} // 是否启用
|
||||
Type interface{} // 存储类型
|
||||
Options interface{} // 存储选项
|
||||
Conds interface{} // 请求条件
|
||||
IsPublic interface{} // 是否为公用
|
||||
FirewallOnly interface{} // 是否只记录防火墙相关
|
||||
Version interface{} // 版本号
|
||||
}
|
||||
|
||||
func NewHTTPAccessLogPolicyOperator() *HTTPAccessLogPolicyOperator {
|
||||
|
||||
@@ -69,7 +69,7 @@ func (this *HTTPAuthPolicyDAO) FindEnabledHTTPAuthPolicy(tx *dbs.Tx, id int64) (
|
||||
|
||||
// CreateHTTPAuthPolicy 创建策略
|
||||
func (this *HTTPAuthPolicyDAO) CreateHTTPAuthPolicy(tx *dbs.Tx, name string, methodType string, paramsJSON []byte) (int64, error) {
|
||||
op := NewHTTPAuthPolicyOperator()
|
||||
var op = NewHTTPAuthPolicyOperator()
|
||||
op.Name = name
|
||||
op.Type = methodType
|
||||
op.Params = paramsJSON
|
||||
@@ -83,7 +83,7 @@ func (this *HTTPAuthPolicyDAO) UpdateHTTPAuthPolicy(tx *dbs.Tx, policyId int64,
|
||||
if policyId <= 0 {
|
||||
return errors.New("invalid policyId")
|
||||
}
|
||||
op := NewHTTPAuthPolicyOperator()
|
||||
var op = NewHTTPAuthPolicyOperator()
|
||||
op.Id = policyId
|
||||
op.Name = name
|
||||
op.Params = paramsJSON
|
||||
@@ -116,13 +116,13 @@ func (this *HTTPAuthPolicyDAO) ComposePolicyConfig(tx *dbs.Tx, policyId int64, c
|
||||
var config = &serverconfigs.HTTPAuthPolicy{
|
||||
Id: int64(policy.Id),
|
||||
Name: policy.Name,
|
||||
IsOn: policy.IsOn == 1,
|
||||
IsOn: policy.IsOn,
|
||||
Type: policy.Type,
|
||||
}
|
||||
|
||||
var params map[string]interface{}
|
||||
if IsNotNull(policy.Params) {
|
||||
err = json.Unmarshal([]byte(policy.Params), ¶ms)
|
||||
err = json.Unmarshal(policy.Params, ¶ms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPAuthPolicy HTTP认证策略
|
||||
type HTTPAuthPolicy struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Type string `field:"type"` // 类型
|
||||
Params string `field:"params"` // 参数
|
||||
State uint8 `field:"state"` // 状态
|
||||
Id uint64 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Type string `field:"type"` // 类型
|
||||
Params dbs.JSON `field:"params"` // 参数
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type HTTPAuthPolicyOperator struct {
|
||||
|
||||
@@ -80,10 +80,10 @@ func (this *HTTPBrotliPolicyDAO) ComposeBrotliConfig(tx *dbs.Tx, policyId int64)
|
||||
|
||||
config := &serverconfigs.HTTPBrotliCompressionConfig{}
|
||||
config.Id = int64(policy.Id)
|
||||
config.IsOn = policy.IsOn == 1
|
||||
config.IsOn = policy.IsOn
|
||||
if IsNotNull(policy.MinLength) {
|
||||
minLengthConfig := &shared.SizeCapacity{}
|
||||
err = json.Unmarshal([]byte(policy.MinLength), minLengthConfig)
|
||||
err = json.Unmarshal(policy.MinLength, minLengthConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func (this *HTTPBrotliPolicyDAO) ComposeBrotliConfig(tx *dbs.Tx, policyId int64)
|
||||
}
|
||||
if IsNotNull(policy.MaxLength) {
|
||||
maxLengthConfig := &shared.SizeCapacity{}
|
||||
err = json.Unmarshal([]byte(policy.MaxLength), maxLengthConfig)
|
||||
err = json.Unmarshal(policy.MaxLength, maxLengthConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -101,7 +101,7 @@ func (this *HTTPBrotliPolicyDAO) ComposeBrotliConfig(tx *dbs.Tx, policyId int64)
|
||||
|
||||
if IsNotNull(policy.Conds) {
|
||||
condsConfig := &shared.HTTPRequestCondsConfig{}
|
||||
err = json.Unmarshal([]byte(policy.Conds), condsConfig)
|
||||
err = json.Unmarshal(policy.Conds, condsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -113,7 +113,7 @@ func (this *HTTPBrotliPolicyDAO) ComposeBrotliConfig(tx *dbs.Tx, policyId int64)
|
||||
|
||||
// CreatePolicy 创建策略
|
||||
func (this *HTTPBrotliPolicyDAO) CreatePolicy(tx *dbs.Tx, level int, minLengthJSON []byte, maxLengthJSON []byte, condsJSON []byte) (int64, error) {
|
||||
op := NewHTTPBrotliPolicyOperator()
|
||||
var op = NewHTTPBrotliPolicyOperator()
|
||||
op.State = HTTPBrotliPolicyStateEnabled
|
||||
op.IsOn = true
|
||||
op.Level = level
|
||||
@@ -138,7 +138,7 @@ func (this *HTTPBrotliPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, level
|
||||
if policyId <= 0 {
|
||||
return errors.New("invalid policyId")
|
||||
}
|
||||
op := NewHTTPBrotliPolicyOperator()
|
||||
var op = NewHTTPBrotliPolicyOperator()
|
||||
op.Id = policyId
|
||||
op.Level = level
|
||||
if len(minLengthJSON) > 0 {
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPBrotliPolicy Gzip配置
|
||||
type HTTPBrotliPolicy struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Level uint32 `field:"level"` // 压缩级别
|
||||
MinLength string `field:"minLength"` // 可压缩最小值
|
||||
MaxLength string `field:"maxLength"` // 可压缩最大值
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Conds string `field:"conds"` // 条件
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Level uint32 `field:"level"` // 压缩级别
|
||||
MinLength dbs.JSON `field:"minLength"` // 可压缩最小值
|
||||
MaxLength dbs.JSON `field:"maxLength"` // 可压缩最大值
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Conds dbs.JSON `field:"conds"` // 条件
|
||||
}
|
||||
|
||||
type HTTPBrotliPolicyOperator struct {
|
||||
|
||||
@@ -2,6 +2,7 @@ package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
@@ -95,8 +96,8 @@ func (this *HTTPCachePolicyDAO) FindAllEnabledCachePolicies(tx *dbs.Tx) (result
|
||||
}
|
||||
|
||||
// CreateCachePolicy 创建缓存策略
|
||||
func (this *HTTPCachePolicyDAO) CreateCachePolicy(tx *dbs.Tx, isOn bool, name string, description string, capacityJSON []byte, maxKeys int64, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte) (int64, error) {
|
||||
op := NewHTTPCachePolicyOperator()
|
||||
func (this *HTTPCachePolicyDAO) CreateCachePolicy(tx *dbs.Tx, isOn bool, name string, description string, capacityJSON []byte, maxKeys int64, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte, syncCompressionCache bool) (int64, error) {
|
||||
var op = NewHTTPCachePolicyOperator()
|
||||
op.State = HTTPCachePolicyStateEnabled
|
||||
op.IsOn = isOn
|
||||
op.Name = name
|
||||
@@ -112,6 +113,7 @@ func (this *HTTPCachePolicyDAO) CreateCachePolicy(tx *dbs.Tx, isOn bool, name st
|
||||
if len(storageOptionsJSON) > 0 {
|
||||
op.Options = storageOptionsJSON
|
||||
}
|
||||
op.SyncCompressionCache = syncCompressionCache
|
||||
|
||||
// 默认的缓存条件
|
||||
cacheRef := &serverconfigs.HTTPCacheRef{
|
||||
@@ -182,13 +184,19 @@ func (this *HTTPCachePolicyDAO) CreateDefaultCachePolicy(tx *dbs.Tx, name string
|
||||
|
||||
var storageOptions = &serverconfigs.HTTPFileCacheStorage{
|
||||
Dir: "/opt/cache",
|
||||
MemoryPolicy: &serverconfigs.HTTPCachePolicy{
|
||||
Capacity: &shared.SizeCapacity{
|
||||
Count: 1,
|
||||
Unit: shared.SizeCapacityUnitGB,
|
||||
},
|
||||
},
|
||||
}
|
||||
storageOptionsJSON, err := json.Marshal(storageOptions)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
policyId, err := this.CreateCachePolicy(tx, true, "\""+name+"\"缓存策略", "默认创建的缓存策略", capacityJSON, 0, maxSizeJSON, serverconfigs.CachePolicyStorageFile, storageOptionsJSON)
|
||||
policyId, err := this.CreateCachePolicy(tx, true, "\""+name+"\"缓存策略", "默认创建的缓存策略", capacityJSON, 0, maxSizeJSON, serverconfigs.CachePolicyStorageFile, storageOptionsJSON, false)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -196,12 +204,12 @@ func (this *HTTPCachePolicyDAO) CreateDefaultCachePolicy(tx *dbs.Tx, name string
|
||||
}
|
||||
|
||||
// UpdateCachePolicy 修改缓存策略
|
||||
func (this *HTTPCachePolicyDAO) UpdateCachePolicy(tx *dbs.Tx, policyId int64, isOn bool, name string, description string, capacityJSON []byte, maxKeys int64, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte) error {
|
||||
func (this *HTTPCachePolicyDAO) UpdateCachePolicy(tx *dbs.Tx, policyId int64, isOn bool, name string, description string, capacityJSON []byte, maxKeys int64, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte, syncCompressionCache bool) error {
|
||||
if policyId <= 0 {
|
||||
return errors.New("invalid policyId")
|
||||
}
|
||||
|
||||
op := NewHTTPCachePolicyOperator()
|
||||
var op = NewHTTPCachePolicyOperator()
|
||||
op.Id = policyId
|
||||
op.IsOn = isOn
|
||||
op.Name = name
|
||||
@@ -217,6 +225,7 @@ func (this *HTTPCachePolicyDAO) UpdateCachePolicy(tx *dbs.Tx, policyId int64, is
|
||||
if len(storageOptionsJSON) > 0 {
|
||||
op.Options = storageOptionsJSON
|
||||
}
|
||||
op.SyncCompressionCache = syncCompressionCache
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -244,14 +253,15 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
|
||||
}
|
||||
config := &serverconfigs.HTTPCachePolicy{}
|
||||
config.Id = int64(policy.Id)
|
||||
config.IsOn = policy.IsOn == 1
|
||||
config.IsOn = policy.IsOn
|
||||
config.Name = policy.Name
|
||||
config.Description = policy.Description
|
||||
config.SyncCompressionCache = policy.SyncCompressionCache == 1
|
||||
|
||||
// capacity
|
||||
if IsNotNull(policy.Capacity) {
|
||||
capacityConfig := &shared.SizeCapacity{}
|
||||
err = json.Unmarshal([]byte(policy.Capacity), capacityConfig)
|
||||
err = json.Unmarshal(policy.Capacity, capacityConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -263,7 +273,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
|
||||
// max size
|
||||
if IsNotNull(policy.MaxSize) {
|
||||
maxSizeConfig := &shared.SizeCapacity{}
|
||||
err = json.Unmarshal([]byte(policy.MaxSize), maxSizeConfig)
|
||||
err = json.Unmarshal(policy.MaxSize, maxSizeConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -275,7 +285,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
|
||||
// options
|
||||
if IsNotNull(policy.Options) {
|
||||
m := map[string]interface{}{}
|
||||
err = json.Unmarshal([]byte(policy.Options), &m)
|
||||
err = json.Unmarshal(policy.Options, &m)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
@@ -285,7 +295,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
|
||||
// refs
|
||||
if IsNotNull(policy.Refs) {
|
||||
refs := []*serverconfigs.HTTPCacheRef{}
|
||||
err = json.Unmarshal([]byte(policy.Refs), &refs)
|
||||
err = json.Unmarshal(policy.Refs, &refs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -300,7 +310,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
|
||||
}
|
||||
|
||||
// CountAllEnabledHTTPCachePolicies 计算可用缓存策略数量
|
||||
func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, clusterId int64, keyword string) (int64, error) {
|
||||
func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, clusterId int64, keyword string, storageType string) (int64, error) {
|
||||
query := this.Query(tx).
|
||||
State(HTTPCachePolicyStateEnabled)
|
||||
if clusterId > 0 {
|
||||
@@ -309,13 +319,16 @@ func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, clu
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
if len(storageType) > 0 {
|
||||
query.Attr("type", storageType)
|
||||
}
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// ListEnabledHTTPCachePolicies 列出单页的缓存策略
|
||||
func (this *HTTPCachePolicyDAO) ListEnabledHTTPCachePolicies(tx *dbs.Tx, clusterId int64, keyword string, offset int64, size int64) ([]*serverconfigs.HTTPCachePolicy, error) {
|
||||
func (this *HTTPCachePolicyDAO) ListEnabledHTTPCachePolicies(tx *dbs.Tx, clusterId int64, keyword string, storageType string, offset int64, size int64) ([]*serverconfigs.HTTPCachePolicy, error) {
|
||||
query := this.Query(tx).
|
||||
State(HTTPCachePolicyStateEnabled)
|
||||
if clusterId > 0 {
|
||||
@@ -324,7 +337,10 @@ func (this *HTTPCachePolicyDAO) ListEnabledHTTPCachePolicies(tx *dbs.Tx, cluster
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
if len(storageType) > 0 {
|
||||
query.Attr("type", storageType)
|
||||
}
|
||||
ones, err := query.
|
||||
ResultPk().
|
||||
|
||||
@@ -1,40 +1,44 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPCachePolicy HTTP缓存策略
|
||||
type HTTPCachePolicy struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Capacity string `field:"capacity"` // 容量数据
|
||||
MaxKeys uint64 `field:"maxKeys"` // 最多Key值
|
||||
MaxSize string `field:"maxSize"` // 最大缓存内容尺寸
|
||||
Type string `field:"type"` // 存储类型
|
||||
Options string `field:"options"` // 存储选项
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
Description string `field:"description"` // 描述
|
||||
Refs string `field:"refs"` // 默认的缓存设置
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Capacity dbs.JSON `field:"capacity"` // 容量数据
|
||||
MaxKeys uint64 `field:"maxKeys"` // 最多Key值
|
||||
MaxSize dbs.JSON `field:"maxSize"` // 最大缓存内容尺寸
|
||||
Type string `field:"type"` // 存储类型
|
||||
Options dbs.JSON `field:"options"` // 存储选项
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
Description string `field:"description"` // 描述
|
||||
Refs dbs.JSON `field:"refs"` // 默认的缓存设置
|
||||
SyncCompressionCache uint8 `field:"syncCompressionCache"` // 是否同步写入压缩缓存
|
||||
}
|
||||
|
||||
type HTTPCachePolicyOperator struct {
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
TemplateId interface{} // 模版ID
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
Capacity interface{} // 容量数据
|
||||
MaxKeys interface{} // 最多Key值
|
||||
MaxSize interface{} // 最大缓存内容尺寸
|
||||
Type interface{} // 存储类型
|
||||
Options interface{} // 存储选项
|
||||
CreatedAt interface{} // 创建时间
|
||||
State interface{} // 状态
|
||||
Description interface{} // 描述
|
||||
Refs interface{} // 默认的缓存设置
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
TemplateId interface{} // 模版ID
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
Capacity interface{} // 容量数据
|
||||
MaxKeys interface{} // 最多Key值
|
||||
MaxSize interface{} // 最大缓存内容尺寸
|
||||
Type interface{} // 存储类型
|
||||
Options interface{} // 存储选项
|
||||
CreatedAt interface{} // 创建时间
|
||||
State interface{} // 状态
|
||||
Description interface{} // 描述
|
||||
Refs interface{} // 默认的缓存设置
|
||||
SyncCompressionCache interface{} // 是否同步写入压缩缓存
|
||||
}
|
||||
|
||||
func NewHTTPCachePolicyOperator() *HTTPCachePolicyOperator {
|
||||
|
||||
254
internal/db/models/http_cache_task_dao.go
Normal file
254
internal/db/models/http_cache_task_dao.go
Normal file
@@ -0,0 +1,254 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
HTTPCacheTaskStateEnabled = 1 // 已启用
|
||||
HTTPCacheTaskStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type HTTPCacheTaskType = string
|
||||
|
||||
const (
|
||||
HTTPCacheTaskTypePurge HTTPCacheTaskType = "purge"
|
||||
HTTPCacheTaskTypeFetch HTTPCacheTaskType = "fetch"
|
||||
)
|
||||
|
||||
type HTTPCacheTaskDAO dbs.DAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
// 清理数据任务
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedHTTPCacheTaskDAO.Clean(nil, 30) // 只保留N天
|
||||
if err != nil {
|
||||
remotelogs.Error("HTTPCacheTaskDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func NewHTTPCacheTaskDAO() *HTTPCacheTaskDAO {
|
||||
return dbs.NewDAO(&HTTPCacheTaskDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeHTTPCacheTasks",
|
||||
Model: new(HTTPCacheTask),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*HTTPCacheTaskDAO)
|
||||
}
|
||||
|
||||
var SharedHTTPCacheTaskDAO *HTTPCacheTaskDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedHTTPCacheTaskDAO = NewHTTPCacheTaskDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableHTTPCacheTask 启用条目
|
||||
func (this *HTTPCacheTaskDAO) EnableHTTPCacheTask(tx *dbs.Tx, taskId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(taskId).
|
||||
Set("state", HTTPCacheTaskStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableHTTPCacheTask 禁用条目
|
||||
func (this *HTTPCacheTaskDAO) DisableHTTPCacheTask(tx *dbs.Tx, taskId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(taskId).
|
||||
Set("state", HTTPCacheTaskStateDisabled).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyChange(tx, taskId)
|
||||
}
|
||||
|
||||
// FindEnabledHTTPCacheTask 查找启用中的条目
|
||||
func (this *HTTPCacheTaskDAO) FindEnabledHTTPCacheTask(tx *dbs.Tx, taskId int64) (*HTTPCacheTask, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(taskId).
|
||||
Attr("state", HTTPCacheTaskStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*HTTPCacheTask), err
|
||||
}
|
||||
|
||||
// CreateTask 创建任务
|
||||
func (this *HTTPCacheTaskDAO) CreateTask(tx *dbs.Tx, userId int64, taskType HTTPCacheTaskType, keyType string, description string) (int64, error) {
|
||||
var op = NewHTTPCacheTaskOperator()
|
||||
op.UserId = userId
|
||||
op.Type = taskType
|
||||
op.KeyType = keyType
|
||||
op.IsOk = false
|
||||
op.IsDone = false
|
||||
op.IsReady = false
|
||||
op.Description = description
|
||||
op.Day = timeutil.Format("Ymd")
|
||||
op.State = HTTPCacheTaskStateEnabled
|
||||
taskId, err := this.SaveInt64(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = this.NotifyChange(tx, taskId)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return taskId, nil
|
||||
}
|
||||
|
||||
// ResetTask 重置服务状态
|
||||
func (this *HTTPCacheTaskDAO) ResetTask(tx *dbs.Tx, taskId int64) error {
|
||||
if taskId <= 0 {
|
||||
return errors.New("invalid 'taskId'")
|
||||
}
|
||||
|
||||
var op = NewHTTPCacheTaskOperator()
|
||||
op.Id = taskId
|
||||
op.IsOk = false
|
||||
op.IsDone = false
|
||||
op.DoneAt = 0
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// UpdateTaskReady 设置任务为已准备
|
||||
func (this *HTTPCacheTaskDAO) UpdateTaskReady(tx *dbs.Tx, taskId int64) error {
|
||||
return this.Query(tx).
|
||||
Pk(taskId).
|
||||
Set("isReady", true).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// CountTasks 查询所有任务数量
|
||||
func (this *HTTPCacheTaskDAO) CountTasks(tx *dbs.Tx, userId int64) (int64, error) {
|
||||
var query = this.Query(tx).
|
||||
State(HTTPCacheTaskStateEnabled).
|
||||
Attr("isReady", true)
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
}
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// CountDoingTasks 查询正在执行的任务数量
|
||||
func (this *HTTPCacheTaskDAO) CountDoingTasks(tx *dbs.Tx, userId int64) (int64, error) {
|
||||
var query = this.Query(tx).
|
||||
State(HTTPCacheTaskStateEnabled).
|
||||
Attr("isReady", true).
|
||||
Attr("isDone", false)
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
}
|
||||
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// ListTasks 列出单页任务
|
||||
func (this *HTTPCacheTaskDAO) ListTasks(tx *dbs.Tx, userId int64, offset int64, size int64) (result []*HTTPCacheTask, err error) {
|
||||
var query = this.Query(tx).
|
||||
State(HTTPCacheTaskStateEnabled).
|
||||
Attr("isReady", true)
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
}
|
||||
_, err = query.
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
DescPk().
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// ListDoingTasks 列出需要执行的任务
|
||||
func (this *HTTPCacheTaskDAO) ListDoingTasks(tx *dbs.Tx, size int64) (result []*HTTPCacheTask, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(HTTPCacheTaskStateEnabled).
|
||||
Attr("isDone", false).
|
||||
Attr("isReady", true).
|
||||
Limit(size).
|
||||
AscPk(). // 按照先创建先执行的原则
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateTaskStatus 标记任务已完成
|
||||
func (this *HTTPCacheTaskDAO) UpdateTaskStatus(tx *dbs.Tx, taskId int64, isDone bool, isOk bool) error {
|
||||
if taskId <= 0 {
|
||||
return errors.New("invalid taskId '" + types.String(taskId) + "'")
|
||||
}
|
||||
var op = NewHTTPCacheTaskOperator()
|
||||
op.Id = taskId
|
||||
op.IsDone = isDone
|
||||
op.IsOk = isOk
|
||||
|
||||
if isDone {
|
||||
op.DoneAt = time.Now().Unix()
|
||||
}
|
||||
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// CheckUserTask 检查用户任务
|
||||
func (this *HTTPCacheTaskDAO) CheckUserTask(tx *dbs.Tx, userId int64, taskId int64) error {
|
||||
b, err := this.Query(tx).
|
||||
Pk(taskId).
|
||||
Attr("userId", userId).
|
||||
State(HTTPCacheTaskStateEnabled).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !b {
|
||||
return ErrNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Clean 清理以往的任务
|
||||
func (this *HTTPCacheTaskDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
if days <= 0 {
|
||||
days = 30
|
||||
}
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days))
|
||||
|
||||
// 删除Key
|
||||
err := SharedHTTPCacheTaskKeyDAO.Clean(tx, days)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除任务
|
||||
_, err = this.Query(tx).
|
||||
Lte("day", day).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
// NotifyChange 发送通知
|
||||
func (this *HTTPCacheTaskDAO) NotifyChange(tx *dbs.Tx, taskId int64) error {
|
||||
// TODO
|
||||
return nil
|
||||
}
|
||||
19
internal/db/models/http_cache_task_dao_test.go
Normal file
19
internal/db/models/http_cache_task_dao_test.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package models_test
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHTTPCacheTaskDAO_Clean(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
err := models.SharedHTTPCacheTaskDAO.Clean(nil, 30)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
218
internal/db/models/http_cache_task_key_dao.go
Normal file
218
internal/db/models/http_cache_task_key_dao.go
Normal file
@@ -0,0 +1,218 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
type HTTPCacheTaskKeyDAO dbs.DAO
|
||||
|
||||
func NewHTTPCacheTaskKeyDAO() *HTTPCacheTaskKeyDAO {
|
||||
return dbs.NewDAO(&HTTPCacheTaskKeyDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeHTTPCacheTaskKeys",
|
||||
Model: new(HTTPCacheTaskKey),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*HTTPCacheTaskKeyDAO)
|
||||
}
|
||||
|
||||
var SharedHTTPCacheTaskKeyDAO *HTTPCacheTaskKeyDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedHTTPCacheTaskKeyDAO = NewHTTPCacheTaskKeyDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// CreateKey 创建Key
|
||||
// 参数:
|
||||
// - clusterId 集群ID
|
||||
// - nodeMapJSON 集群下节点映射,格式类似于 `{ "节点1":true, ... }`
|
||||
func (this *HTTPCacheTaskKeyDAO) CreateKey(tx *dbs.Tx, taskId int64, key string, taskType HTTPCacheTaskType, keyType string, clusterId int64) (int64, error) {
|
||||
var op = NewHTTPCacheTaskKeyOperator()
|
||||
op.TaskId = taskId
|
||||
op.Key = key
|
||||
op.Type = taskType
|
||||
op.KeyType = keyType
|
||||
op.ClusterId = clusterId
|
||||
|
||||
op.Nodes = "{}"
|
||||
op.Errors = "{}"
|
||||
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// UpdateKeyStatus 修改Key状态
|
||||
func (this *HTTPCacheTaskKeyDAO) UpdateKeyStatus(tx *dbs.Tx, keyId int64, nodeId int64, errString string, nodesJSON []byte) error {
|
||||
if keyId <= 0 {
|
||||
return errors.New("invalid 'keyId'")
|
||||
}
|
||||
|
||||
if len(nodesJSON) == 0 {
|
||||
nodesJSON = []byte("{}")
|
||||
}
|
||||
|
||||
taskId, err := this.Query(tx).
|
||||
Pk(keyId).
|
||||
Result("taskId").
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var jsonPath = "$.\"" + types.String(nodeId) + "\""
|
||||
|
||||
var query = this.Query(tx).
|
||||
Pk(keyId).
|
||||
Set("nodes", dbs.SQL("JSON_SET(nodes, :jsonPath1, true)")).
|
||||
Param("jsonPath1", jsonPath)
|
||||
|
||||
if len(errString) > 0 {
|
||||
query.Set("errors", dbs.SQL("JSON_SET(errors, :jsonPath2, :jsonValue2)")).
|
||||
Param("jsonPath2", jsonPath).
|
||||
Param("jsonValue2", errString)
|
||||
} else {
|
||||
query.Set("errors", dbs.SQL("JSON_REMOVE(errors, :jsonPath2)")).
|
||||
Param("jsonPath2", jsonPath)
|
||||
}
|
||||
|
||||
err = query.
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 检查是否已完成
|
||||
isDone, err := this.Query(tx).
|
||||
Pk(keyId).
|
||||
Where("JSON_CONTAINS(nodes, :nodesJSON)").
|
||||
Param("nodesJSON", nodesJSON).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if isDone {
|
||||
err = this.Query(tx).
|
||||
Pk(keyId).
|
||||
Set("isDone", isDone).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 检查任务是否已经完成
|
||||
taskIsNotDone, err := this.Query(tx).
|
||||
Attr("taskId", taskId).
|
||||
Attr("isDone", false).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var taskIsDone = !taskIsNotDone
|
||||
var hasErrors = true
|
||||
if taskIsDone {
|
||||
// 已经完成,是否有错误
|
||||
hasErrors, err = this.Query(tx).
|
||||
Attr("taskId", taskId).
|
||||
Where("JSON_LENGTH(errors)>0").
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = SharedHTTPCacheTaskDAO.UpdateTaskStatus(tx, taskId, taskIsDone, !hasErrors)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindAllTaskKeys 查询某个任务下的所有Key
|
||||
func (this *HTTPCacheTaskKeyDAO) FindAllTaskKeys(tx *dbs.Tx, taskId int64) (result []*HTTPCacheTaskKey, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Attr("taskId", taskId).
|
||||
AscPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindDoingTaskKeys 查询要执行的任务
|
||||
func (this *HTTPCacheTaskKeyDAO) FindDoingTaskKeys(tx *dbs.Tx, nodeId int64, size int64) (result []*HTTPCacheTaskKey, err error) {
|
||||
// 集群ID
|
||||
clusterIds, err := SharedNodeDAO.FindEnabledAndOnNodeClusterIds(tx, nodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(clusterIds) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Attr("clusterId", clusterIds).
|
||||
Attr("isDone", false).
|
||||
Where("NOT JSON_CONTAINS_PATH(nodes, 'one', :jsonPath1)").
|
||||
Param("jsonPath1", "$.\""+types.String(nodeId)+"\"").
|
||||
Where("taskId IN (SELECT id FROM " + SharedHTTPCacheTaskDAO.Table + " WHERE state=1 AND isReady=1 AND isDone=0)").
|
||||
Limit(size).
|
||||
AscPk().
|
||||
Reuse(false).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ResetCacheKeysWithTaskId 重置任务下的Key状态
|
||||
func (this *HTTPCacheTaskKeyDAO) ResetCacheKeysWithTaskId(tx *dbs.Tx, taskId int64) error {
|
||||
return this.Query(tx).
|
||||
Attr("taskId", taskId).
|
||||
Set("isDone", false).
|
||||
Set("nodes", "{}").
|
||||
Set("errors", "{}").
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// CountUserTasksInDay 读取某个用户当前数量
|
||||
// day YYYYMMDD
|
||||
func (this *HTTPCacheTaskKeyDAO) CountUserTasksInDay(tx *dbs.Tx, userId int64, day string, taskType HTTPCacheTaskType) (int64, error) {
|
||||
if userId <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// 这里需要包含已删除的
|
||||
return this.Query(tx).
|
||||
Where("taskId IN (SELECT id FROM "+SharedHTTPCacheTaskDAO.Table+" WHERE userId=:userId AND day=:day AND type=:type)").
|
||||
Param("userId", userId).
|
||||
Param("day", day).
|
||||
Param("type", taskType).
|
||||
Count()
|
||||
}
|
||||
|
||||
// Clean 清理以往的任务
|
||||
func (this *HTTPCacheTaskKeyDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
if days <= 0 {
|
||||
days = 30
|
||||
}
|
||||
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days))
|
||||
_, err := this.Query(tx).
|
||||
Where("taskId IN (SELECT id FROM "+SharedHTTPCacheTaskDAO.Table+" WHERE day<=:day)").
|
||||
Param("day", day).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
54
internal/db/models/http_cache_task_key_dao_test.go
Normal file
54
internal/db/models/http_cache_task_key_dao_test.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package models_test
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHTTPCacheTaskKeyDAO_CreateKey(t *testing.T) {
|
||||
var dao = models.NewHTTPCacheTaskKeyDAO()
|
||||
var tx *dbs.Tx
|
||||
_, err := dao.CreateKey(tx, 1, "a", "purge", "key", 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestHTTPCacheTaskKeyDAO_UpdateKeyStatus(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var dao = models.NewHTTPCacheTaskKeyDAO()
|
||||
var tx *dbs.Tx
|
||||
var errString = "" // "this is error"
|
||||
err := dao.UpdateKeyStatus(tx, 3, 1, errString, []byte(`{"1":true}`))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestHTTPCacheTaskKeyDAO_CountUserTasksInDay(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var dao = models.NewHTTPCacheTaskKeyDAO()
|
||||
var tx *dbs.Tx
|
||||
{
|
||||
count, err := dao.CountUserTasksInDay(tx, 1, timeutil.Format("Ymd"), models.HTTPCacheTaskTypePurge)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("count:", count)
|
||||
}
|
||||
{
|
||||
count, err := dao.CountUserTasksInDay(tx, 1, timeutil.Format("Ymd"), models.HTTPCacheTaskTypeFetch)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("count:", count)
|
||||
}
|
||||
}
|
||||
32
internal/db/models/http_cache_task_key_model.go
Normal file
32
internal/db/models/http_cache_task_key_model.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPCacheTaskKey 缓存任务Key
|
||||
type HTTPCacheTaskKey struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
TaskId uint64 `field:"taskId"` // 任务ID
|
||||
Key string `field:"key"` // Key
|
||||
KeyType string `field:"keyType"` // Key类型:key|prefix
|
||||
Type string `field:"type"` // 操作类型
|
||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||
Nodes dbs.JSON `field:"nodes"` // 节点
|
||||
Errors dbs.JSON `field:"errors"` // 错误信息
|
||||
IsDone bool `field:"isDone"` // 是否已完成
|
||||
}
|
||||
|
||||
type HTTPCacheTaskKeyOperator struct {
|
||||
Id interface{} // ID
|
||||
TaskId interface{} // 任务ID
|
||||
Key interface{} // Key
|
||||
KeyType interface{} // Key类型:key|prefix
|
||||
Type interface{} // 操作类型
|
||||
ClusterId interface{} // 集群ID
|
||||
Nodes interface{} // 节点
|
||||
Errors interface{} // 错误信息
|
||||
IsDone interface{} // 是否已完成
|
||||
}
|
||||
|
||||
func NewHTTPCacheTaskKeyOperator() *HTTPCacheTaskKeyOperator {
|
||||
return &HTTPCacheTaskKeyOperator{}
|
||||
}
|
||||
20
internal/db/models/http_cache_task_key_model_ext.go
Normal file
20
internal/db/models/http_cache_task_key_model_ext.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package models
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
// DecodeNodes 解析已完成节点信息
|
||||
func (this *HTTPCacheTaskKey) DecodeNodes() map[string]bool {
|
||||
var result = map[string]bool{}
|
||||
var nodesJSON = this.Nodes
|
||||
if IsNull(nodesJSON) {
|
||||
return result
|
||||
}
|
||||
|
||||
err := json.Unmarshal(nodesJSON, &result)
|
||||
if err != nil {
|
||||
// ignore error
|
||||
return result
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
36
internal/db/models/http_cache_task_model.go
Normal file
36
internal/db/models/http_cache_task_model.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package models
|
||||
|
||||
// HTTPCacheTask 缓存相关任务
|
||||
type HTTPCacheTask struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
Type string `field:"type"` // 任务类型:purge|fetch
|
||||
KeyType string `field:"keyType"` // Key类型
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
DoneAt uint64 `field:"doneAt"` // 完成时间
|
||||
Day string `field:"day"` // 创建日期YYYYMMDD
|
||||
IsDone bool `field:"isDone"` // 是否已完成
|
||||
IsOk bool `field:"isOk"` // 是否完全成功
|
||||
IsReady uint8 `field:"isReady"` // 是否已准备好
|
||||
Description string `field:"description"` // 描述
|
||||
}
|
||||
|
||||
type HTTPCacheTaskOperator struct {
|
||||
Id interface{} // ID
|
||||
UserId interface{} // 用户ID
|
||||
Type interface{} // 任务类型:purge|fetch
|
||||
KeyType interface{} // Key类型
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
DoneAt interface{} // 完成时间
|
||||
Day interface{} // 创建日期YYYYMMDD
|
||||
IsDone interface{} // 是否已完成
|
||||
IsOk interface{} // 是否完全成功
|
||||
IsReady interface{} // 是否已准备好
|
||||
Description interface{} // 描述
|
||||
}
|
||||
|
||||
func NewHTTPCacheTaskOperator() *HTTPCacheTaskOperator {
|
||||
return &HTTPCacheTaskOperator{}
|
||||
}
|
||||
1
internal/db/models/http_cache_task_model_ext.go
Normal file
1
internal/db/models/http_cache_task_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package models
|
||||
@@ -80,10 +80,10 @@ func (this *HTTPDeflatePolicyDAO) ComposeDeflateConfig(tx *dbs.Tx, policyId int6
|
||||
|
||||
config := &serverconfigs.HTTPDeflateCompressionConfig{}
|
||||
config.Id = int64(policy.Id)
|
||||
config.IsOn = policy.IsOn == 1
|
||||
config.IsOn = policy.IsOn
|
||||
if IsNotNull(policy.MinLength) {
|
||||
minLengthConfig := &shared.SizeCapacity{}
|
||||
err = json.Unmarshal([]byte(policy.MinLength), minLengthConfig)
|
||||
err = json.Unmarshal(policy.MinLength, minLengthConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func (this *HTTPDeflatePolicyDAO) ComposeDeflateConfig(tx *dbs.Tx, policyId int6
|
||||
}
|
||||
if IsNotNull(policy.MaxLength) {
|
||||
maxLengthConfig := &shared.SizeCapacity{}
|
||||
err = json.Unmarshal([]byte(policy.MaxLength), maxLengthConfig)
|
||||
err = json.Unmarshal(policy.MaxLength, maxLengthConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -101,7 +101,7 @@ func (this *HTTPDeflatePolicyDAO) ComposeDeflateConfig(tx *dbs.Tx, policyId int6
|
||||
|
||||
if IsNotNull(policy.Conds) {
|
||||
condsConfig := &shared.HTTPRequestCondsConfig{}
|
||||
err = json.Unmarshal([]byte(policy.Conds), condsConfig)
|
||||
err = json.Unmarshal(policy.Conds, condsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -113,7 +113,7 @@ func (this *HTTPDeflatePolicyDAO) ComposeDeflateConfig(tx *dbs.Tx, policyId int6
|
||||
|
||||
// CreatePolicy 创建策略
|
||||
func (this *HTTPDeflatePolicyDAO) CreatePolicy(tx *dbs.Tx, level int, minLengthJSON []byte, maxLengthJSON []byte, condsJSON []byte) (int64, error) {
|
||||
op := NewHTTPDeflatePolicyOperator()
|
||||
var op = NewHTTPDeflatePolicyOperator()
|
||||
op.State = HTTPDeflatePolicyStateEnabled
|
||||
op.IsOn = true
|
||||
op.Level = level
|
||||
@@ -138,7 +138,7 @@ func (this *HTTPDeflatePolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, level
|
||||
if policyId <= 0 {
|
||||
return errors.New("invalid policyId")
|
||||
}
|
||||
op := NewHTTPDeflatePolicyOperator()
|
||||
var op = NewHTTPDeflatePolicyOperator()
|
||||
op.Id = policyId
|
||||
op.Level = level
|
||||
if len(minLengthJSON) > 0 {
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPDeflatePolicy Gzip配置
|
||||
type HTTPDeflatePolicy struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Level uint32 `field:"level"` // 压缩级别
|
||||
MinLength string `field:"minLength"` // 可压缩最小值
|
||||
MaxLength string `field:"maxLength"` // 可压缩最大值
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Conds string `field:"conds"` // 条件
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Level uint32 `field:"level"` // 压缩级别
|
||||
MinLength dbs.JSON `field:"minLength"` // 可压缩最小值
|
||||
MaxLength dbs.JSON `field:"maxLength"` // 可压缩最大值
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Conds dbs.JSON `field:"conds"` // 条件
|
||||
}
|
||||
|
||||
type HTTPDeflatePolicyOperator struct {
|
||||
|
||||
@@ -81,12 +81,12 @@ func (this *HTTPFastcgiDAO) ComposeFastcgiConfig(tx *dbs.Tx, fastcgiId int64) (*
|
||||
}
|
||||
config := &serverconfigs.HTTPFastcgiConfig{}
|
||||
config.Id = int64(fastcgi.Id)
|
||||
config.IsOn = fastcgi.IsOn == 1
|
||||
config.IsOn = fastcgi.IsOn
|
||||
config.Address = fastcgi.Address
|
||||
|
||||
if IsNotNull(fastcgi.Params) {
|
||||
params := []*serverconfigs.HTTPFastcgiParam{}
|
||||
err = json.Unmarshal([]byte(fastcgi.Params), ¶ms)
|
||||
err = json.Unmarshal(fastcgi.Params, ¶ms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -95,7 +95,7 @@ func (this *HTTPFastcgiDAO) ComposeFastcgiConfig(tx *dbs.Tx, fastcgiId int64) (*
|
||||
|
||||
if IsNotNull(fastcgi.ReadTimeout) {
|
||||
duration := &shared.TimeDuration{}
|
||||
err = json.Unmarshal([]byte(fastcgi.ReadTimeout), duration)
|
||||
err = json.Unmarshal(fastcgi.ReadTimeout, duration)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -104,7 +104,7 @@ func (this *HTTPFastcgiDAO) ComposeFastcgiConfig(tx *dbs.Tx, fastcgiId int64) (*
|
||||
|
||||
if IsNotNull(fastcgi.ConnTimeout) {
|
||||
duration := &shared.TimeDuration{}
|
||||
err = json.Unmarshal([]byte(fastcgi.ConnTimeout), duration)
|
||||
err = json.Unmarshal(fastcgi.ConnTimeout, duration)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -121,7 +121,7 @@ func (this *HTTPFastcgiDAO) ComposeFastcgiConfig(tx *dbs.Tx, fastcgiId int64) (*
|
||||
|
||||
// CreateFastcgi 创建Fastcgi
|
||||
func (this *HTTPFastcgiDAO) CreateFastcgi(tx *dbs.Tx, adminId int64, userId int64, isOn bool, address string, paramsJSON []byte, readTimeoutJSON []byte, connTimeoutJSON []byte, poolSize int32, pathInfoPattern string) (int64, error) {
|
||||
op := NewHTTPFastcgiOperator()
|
||||
var op = NewHTTPFastcgiOperator()
|
||||
op.AdminId = adminId
|
||||
op.UserId = userId
|
||||
op.IsOn = isOn
|
||||
@@ -147,7 +147,7 @@ func (this *HTTPFastcgiDAO) UpdateFastcgi(tx *dbs.Tx, fastcgiId int64, isOn bool
|
||||
if fastcgiId <= 0 {
|
||||
return errors.New("invalid 'fastcgiId'")
|
||||
}
|
||||
op := NewHTTPFastcgiOperator()
|
||||
var op = NewHTTPFastcgiOperator()
|
||||
op.Id = fastcgiId
|
||||
op.IsOn = isOn
|
||||
op.Address = address
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPFastcgi Fastcgi设置
|
||||
type HTTPFastcgi struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Address string `field:"address"` // 地址
|
||||
Params string `field:"params"` // 参数
|
||||
ReadTimeout string `field:"readTimeout"` // 读取超时
|
||||
ConnTimeout string `field:"connTimeout"` // 连接超时
|
||||
PoolSize uint32 `field:"poolSize"` // 连接池尺寸
|
||||
PathInfoPattern string `field:"pathInfoPattern"` // PATH_INFO匹配
|
||||
State uint8 `field:"state"` // 状态
|
||||
Id uint64 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Address string `field:"address"` // 地址
|
||||
Params dbs.JSON `field:"params"` // 参数
|
||||
ReadTimeout dbs.JSON `field:"readTimeout"` // 读取超时
|
||||
ConnTimeout dbs.JSON `field:"connTimeout"` // 连接超时
|
||||
PoolSize uint32 `field:"poolSize"` // 连接池尺寸
|
||||
PathInfoPattern string `field:"pathInfoPattern"` // PATH_INFO匹配
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type HTTPFastcgiOperator struct {
|
||||
|
||||
@@ -2,6 +2,7 @@ package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
@@ -116,7 +117,7 @@ func (this *HTTPFirewallPolicyDAO) FindAllEnabledFirewallPolicies(tx *dbs.Tx) (r
|
||||
|
||||
// CreateFirewallPolicy 创建策略
|
||||
func (this *HTTPFirewallPolicyDAO) CreateFirewallPolicy(tx *dbs.Tx, userId int64, serverGroupId int64, serverId int64, isOn bool, name string, description string, inboundJSON []byte, outboundJSON []byte) (int64, error) {
|
||||
op := NewHTTPFirewallPolicyOperator()
|
||||
var op = NewHTTPFirewallPolicyOperator()
|
||||
op.UserId = userId
|
||||
op.GroupId = serverGroupId
|
||||
op.ServerId = serverId
|
||||
@@ -130,14 +131,31 @@ func (this *HTTPFirewallPolicyDAO) CreateFirewallPolicy(tx *dbs.Tx, userId int64
|
||||
if len(outboundJSON) > 0 {
|
||||
op.Outbound = outboundJSON
|
||||
}
|
||||
op.UseLocalFirewall = true
|
||||
|
||||
{
|
||||
synFloodJSON, err := json.Marshal(firewallconfigs.DefaultSYNFloodConfig())
|
||||
if userId <= 0 && serverGroupId <=0 && serverId <= 0 {
|
||||
// synFlood
|
||||
var synFloodConfig = firewallconfigs.DefaultSYNFloodConfig()
|
||||
synFloodJSON, err := json.Marshal(synFloodConfig)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.SynFlood = synFloodJSON
|
||||
|
||||
// block options
|
||||
var blockOptions = firewallconfigs.DefaultHTTPFirewallBlockAction()
|
||||
blockOptionsJSON, err := json.Marshal(blockOptions)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.BlockOptions = blockOptionsJSON
|
||||
|
||||
// captcha options
|
||||
var captchaOptions = firewallconfigs.DefaultHTTPFirewallCaptchaAction()
|
||||
captchaOptionsJSON, err := json.Marshal(captchaOptions)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.CaptchaOptions = captchaOptionsJSON
|
||||
}
|
||||
|
||||
err := this.Save(tx, op)
|
||||
@@ -159,8 +177,8 @@ func (this *HTTPFirewallPolicyDAO) CreateDefaultFirewallPolicy(tx *dbs.Tx, name
|
||||
groupCodes = append(groupCodes, group.Code)
|
||||
}
|
||||
|
||||
inboundConfig := &firewallconfigs.HTTPFirewallInboundConfig{IsOn: true}
|
||||
outboundConfig := &firewallconfigs.HTTPFirewallOutboundConfig{IsOn: true}
|
||||
var inboundConfig = &firewallconfigs.HTTPFirewallInboundConfig{IsOn: true}
|
||||
var outboundConfig = &firewallconfigs.HTTPFirewallOutboundConfig{IsOn: true}
|
||||
if templatePolicy.Inbound != nil {
|
||||
for _, group := range templatePolicy.Inbound.Groups {
|
||||
isOn := lists.ContainsString(groupCodes, group.Code)
|
||||
@@ -206,6 +224,7 @@ func (this *HTTPFirewallPolicyDAO) CreateDefaultFirewallPolicy(tx *dbs.Tx, name
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return policyId, nil
|
||||
}
|
||||
|
||||
@@ -214,7 +233,7 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicyInboundAndOutbound(tx *db
|
||||
if policyId <= 0 {
|
||||
return errors.New("invalid policyId")
|
||||
}
|
||||
op := NewHTTPFirewallPolicyOperator()
|
||||
var op = NewHTTPFirewallPolicyOperator()
|
||||
op.Id = policyId
|
||||
if len(inboundJSON) > 0 {
|
||||
op.Inbound = inboundJSON
|
||||
@@ -243,7 +262,7 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicyInbound(tx *dbs.Tx, polic
|
||||
if policyId <= 0 {
|
||||
return errors.New("invalid policyId")
|
||||
}
|
||||
op := NewHTTPFirewallPolicyOperator()
|
||||
var op = NewHTTPFirewallPolicyOperator()
|
||||
op.Id = policyId
|
||||
if len(inboundJSON) > 0 {
|
||||
op.Inbound = inboundJSON
|
||||
@@ -259,11 +278,23 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicyInbound(tx *dbs.Tx, polic
|
||||
}
|
||||
|
||||
// UpdateFirewallPolicy 修改策略
|
||||
func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx, policyId int64, isOn bool, name string, description string, inboundJSON []byte, outboundJSON []byte, blockOptionsJSON []byte, mode firewallconfigs.FirewallMode, useLocalFirewall bool, synFloodConfig *firewallconfigs.SYNFloodConfig) error {
|
||||
func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx,
|
||||
policyId int64,
|
||||
isOn bool,
|
||||
name string,
|
||||
description string,
|
||||
inboundJSON []byte,
|
||||
outboundJSON []byte,
|
||||
blockOptionsJSON []byte,
|
||||
captchaOptionsJSON []byte,
|
||||
mode firewallconfigs.FirewallMode,
|
||||
useLocalFirewall bool,
|
||||
synFloodConfig *firewallconfigs.SYNFloodConfig,
|
||||
logConfig *firewallconfigs.HTTPFirewallPolicyLogConfig) error {
|
||||
if policyId <= 0 {
|
||||
return errors.New("invalid policyId")
|
||||
}
|
||||
op := NewHTTPFirewallPolicyOperator()
|
||||
var op = NewHTTPFirewallPolicyOperator()
|
||||
op.Id = policyId
|
||||
op.IsOn = isOn
|
||||
op.Name = name
|
||||
@@ -279,9 +310,12 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx, policyId int
|
||||
} else {
|
||||
op.Outbound = "null"
|
||||
}
|
||||
if len(blockOptionsJSON) > 0 {
|
||||
if IsNotNull(blockOptionsJSON) {
|
||||
op.BlockOptions = blockOptionsJSON
|
||||
}
|
||||
if IsNotNull(captchaOptionsJSON) {
|
||||
op.CaptchaOptions = captchaOptionsJSON
|
||||
}
|
||||
|
||||
if synFloodConfig != nil {
|
||||
synFloodConfigJSON, err := json.Marshal(synFloodConfig)
|
||||
@@ -293,6 +327,16 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx, policyId int
|
||||
op.SynFlood = "null"
|
||||
}
|
||||
|
||||
if logConfig != nil {
|
||||
logJSON, err := json.Marshal(logConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.Log = logJSON
|
||||
} else {
|
||||
op.Log = "null"
|
||||
}
|
||||
|
||||
op.UseLocalFirewall = useLocalFirewall
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
@@ -311,7 +355,7 @@ func (this *HTTPFirewallPolicyDAO) CountAllEnabledFirewallPolicies(tx *dbs.Tx, c
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
return query.
|
||||
State(HTTPFirewallPolicyStateEnabled).
|
||||
@@ -330,7 +374,7 @@ func (this *HTTPFirewallPolicyDAO) ListEnabledFirewallPolicies(tx *dbs.Tx, clust
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
_, err = query.
|
||||
State(HTTPFirewallPolicyStateEnabled).
|
||||
@@ -364,9 +408,9 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
config := &firewallconfigs.HTTPFirewallPolicy{}
|
||||
var config = &firewallconfigs.HTTPFirewallPolicy{}
|
||||
config.Id = int64(policy.Id)
|
||||
config.IsOn = policy.IsOn == 1
|
||||
config.IsOn = policy.IsOn
|
||||
config.Name = policy.Name
|
||||
config.Description = policy.Description
|
||||
config.UseLocalFirewall = policy.UseLocalFirewall == 1
|
||||
@@ -379,7 +423,7 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
|
||||
// Inbound
|
||||
inbound := &firewallconfigs.HTTPFirewallInboundConfig{}
|
||||
if IsNotNull(policy.Inbound) {
|
||||
err = json.Unmarshal([]byte(policy.Inbound), inbound)
|
||||
err = json.Unmarshal(policy.Inbound, inbound)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -407,7 +451,7 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
|
||||
// Outbound
|
||||
outbound := &firewallconfigs.HTTPFirewallOutboundConfig{}
|
||||
if IsNotNull(policy.Outbound) {
|
||||
err = json.Unmarshal([]byte(policy.Outbound), outbound)
|
||||
err = json.Unmarshal(policy.Outbound, outbound)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -434,24 +478,46 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
|
||||
|
||||
// Block动作配置
|
||||
if IsNotNull(policy.BlockOptions) {
|
||||
blockAction := &firewallconfigs.HTTPFirewallBlockAction{}
|
||||
err = json.Unmarshal([]byte(policy.BlockOptions), blockAction)
|
||||
var blockAction = &firewallconfigs.HTTPFirewallBlockAction{}
|
||||
err = json.Unmarshal(policy.BlockOptions, blockAction)
|
||||
if err != nil {
|
||||
return config, err
|
||||
}
|
||||
config.BlockOptions = blockAction
|
||||
}
|
||||
|
||||
// Captcha动作配置
|
||||
if IsNotNull(policy.CaptchaOptions) {
|
||||
var captchaAction = &firewallconfigs.HTTPFirewallCaptchaAction{}
|
||||
err = json.Unmarshal(policy.CaptchaOptions, captchaAction)
|
||||
if err != nil {
|
||||
return config, err
|
||||
}
|
||||
config.CaptchaOptions = captchaAction
|
||||
}
|
||||
|
||||
// syn flood
|
||||
if len(policy.SynFlood) > 0 {
|
||||
if IsNotNull(policy.SynFlood) {
|
||||
var synFloodConfig = &firewallconfigs.SYNFloodConfig{}
|
||||
err = json.Unmarshal([]byte(policy.SynFlood), synFloodConfig)
|
||||
err = json.Unmarshal(policy.SynFlood, synFloodConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.SYNFlood = synFloodConfig
|
||||
}
|
||||
|
||||
// log
|
||||
if IsNotNull(policy.Log) {
|
||||
var logConfig = &firewallconfigs.HTTPFirewallPolicyLogConfig{}
|
||||
err = json.Unmarshal(policy.Log, logConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.Log = logConfig
|
||||
} else {
|
||||
config.Log = firewallconfigs.DefaultHTTPFirewallPolicyLogConfig
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, config)
|
||||
}
|
||||
@@ -492,6 +558,7 @@ func (this *HTTPFirewallPolicyDAO) CheckUserFirewallPolicy(tx *dbs.Tx, userId in
|
||||
}
|
||||
|
||||
// FindEnabledFirewallPolicyIdsWithIPListId 查找包含某个IPList的所有策略
|
||||
// TODO 改成通过 serverId 查询
|
||||
func (this *HTTPFirewallPolicyDAO) FindEnabledFirewallPolicyIdsWithIPListId(tx *dbs.Tx, ipListId int64) ([]int64, error) {
|
||||
ones, err := this.Query(tx).
|
||||
ResultPk().
|
||||
@@ -510,6 +577,7 @@ func (this *HTTPFirewallPolicyDAO) FindEnabledFirewallPolicyIdsWithIPListId(tx *
|
||||
}
|
||||
|
||||
// FindEnabledFirewallPolicyWithIPListId 查找使用某个IPList的策略
|
||||
// TODO 改成通过 serverId 查询
|
||||
func (this *HTTPFirewallPolicyDAO) FindEnabledFirewallPolicyWithIPListId(tx *dbs.Tx, ipListId int64) (*HTTPFirewallPolicy, error) {
|
||||
one, err := this.Query(tx).
|
||||
State(HTTPFirewallPolicyStateEnabled).
|
||||
|
||||
@@ -1,24 +1,28 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPFirewallPolicy HTTP防火墙
|
||||
type HTTPFirewallPolicy struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
GroupId uint32 `field:"groupId"` // 服务分组ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Inbound string `field:"inbound"` // 入站规则
|
||||
Outbound string `field:"outbound"` // 出站规则
|
||||
BlockOptions string `field:"blockOptions"` // BLOCK选项
|
||||
Mode string `field:"mode"` // 模式
|
||||
UseLocalFirewall uint8 `field:"useLocalFirewall"` // 是否自动使用本地防火墙
|
||||
SynFlood string `field:"synFlood"` // SynFlood防御设置
|
||||
Id uint32 `field:"id"` // ID
|
||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
GroupId uint32 `field:"groupId"` // 服务分组ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Inbound dbs.JSON `field:"inbound"` // 入站规则
|
||||
Outbound dbs.JSON `field:"outbound"` // 出站规则
|
||||
BlockOptions dbs.JSON `field:"blockOptions"` // BLOCK选项
|
||||
CaptchaOptions dbs.JSON `field:"captchaOptions"` // 验证码选项
|
||||
Mode string `field:"mode"` // 模式
|
||||
UseLocalFirewall uint8 `field:"useLocalFirewall"` // 是否自动使用本地防火墙
|
||||
SynFlood dbs.JSON `field:"synFlood"` // SynFlood防御设置
|
||||
Log dbs.JSON `field:"log"` // 日志配置
|
||||
}
|
||||
|
||||
type HTTPFirewallPolicyOperator struct {
|
||||
@@ -36,9 +40,11 @@ type HTTPFirewallPolicyOperator struct {
|
||||
Inbound interface{} // 入站规则
|
||||
Outbound interface{} // 出站规则
|
||||
BlockOptions interface{} // BLOCK选项
|
||||
CaptchaOptions interface{} // 验证码选项
|
||||
Mode interface{} // 模式
|
||||
UseLocalFirewall interface{} // 是否自动使用本地防火墙
|
||||
SynFlood interface{} // SynFlood防御设置
|
||||
Log interface{} // 日志配置
|
||||
}
|
||||
|
||||
func NewHTTPFirewallPolicyOperator() *HTTPFirewallPolicyOperator {
|
||||
|
||||
@@ -35,12 +35,12 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 初始化
|
||||
// Init 初始化
|
||||
func (this *HTTPFirewallRuleDAO) Init() {
|
||||
_ = this.DAOObject.Init()
|
||||
}
|
||||
|
||||
// 启用条目
|
||||
// EnableHTTPFirewallRule 启用条目
|
||||
func (this *HTTPFirewallRuleDAO) EnableHTTPFirewallRule(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -49,7 +49,7 @@ func (this *HTTPFirewallRuleDAO) EnableHTTPFirewallRule(tx *dbs.Tx, id int64) er
|
||||
return err
|
||||
}
|
||||
|
||||
// 禁用条目
|
||||
// DisableHTTPFirewallRule 禁用条目
|
||||
func (this *HTTPFirewallRuleDAO) DisableHTTPFirewallRule(tx *dbs.Tx, ruleId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(ruleId).
|
||||
@@ -61,7 +61,7 @@ func (this *HTTPFirewallRuleDAO) DisableHTTPFirewallRule(tx *dbs.Tx, ruleId int6
|
||||
return this.NotifyUpdate(tx, ruleId)
|
||||
}
|
||||
|
||||
// 查找启用中的条目
|
||||
// FindEnabledHTTPFirewallRule 查找启用中的条目
|
||||
func (this *HTTPFirewallRuleDAO) FindEnabledHTTPFirewallRule(tx *dbs.Tx, id int64) (*HTTPFirewallRule, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -73,7 +73,7 @@ func (this *HTTPFirewallRuleDAO) FindEnabledHTTPFirewallRule(tx *dbs.Tx, id int6
|
||||
return result.(*HTTPFirewallRule), err
|
||||
}
|
||||
|
||||
// 组合配置
|
||||
// ComposeFirewallRule 组合配置
|
||||
func (this *HTTPFirewallRuleDAO) ComposeFirewallRule(tx *dbs.Tx, ruleId int64) (*firewallconfigs.HTTPFirewallRule, error) {
|
||||
rule, err := this.FindEnabledHTTPFirewallRule(tx, ruleId)
|
||||
if err != nil {
|
||||
@@ -84,12 +84,12 @@ func (this *HTTPFirewallRuleDAO) ComposeFirewallRule(tx *dbs.Tx, ruleId int64) (
|
||||
}
|
||||
config := &firewallconfigs.HTTPFirewallRule{}
|
||||
config.Id = int64(rule.Id)
|
||||
config.IsOn = rule.IsOn == 1
|
||||
config.IsOn = rule.IsOn
|
||||
config.Param = rule.Param
|
||||
|
||||
paramFilters := []*firewallconfigs.ParamFilter{}
|
||||
if IsNotNull(rule.ParamFilters) {
|
||||
err = json.Unmarshal([]byte(rule.ParamFilters), ¶mFilters)
|
||||
err = json.Unmarshal(rule.ParamFilters, ¶mFilters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -98,11 +98,11 @@ func (this *HTTPFirewallRuleDAO) ComposeFirewallRule(tx *dbs.Tx, ruleId int64) (
|
||||
|
||||
config.Operator = rule.Operator
|
||||
config.Value = rule.Value
|
||||
config.IsCaseInsensitive = rule.IsCaseInsensitive == 1
|
||||
config.IsCaseInsensitive = rule.IsCaseInsensitive
|
||||
|
||||
if IsNotNull(rule.CheckpointOptions) {
|
||||
checkpointOptions := map[string]interface{}{}
|
||||
err = json.Unmarshal([]byte(rule.CheckpointOptions), &checkpointOptions)
|
||||
err = json.Unmarshal(rule.CheckpointOptions, &checkpointOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -114,9 +114,9 @@ func (this *HTTPFirewallRuleDAO) ComposeFirewallRule(tx *dbs.Tx, ruleId int64) (
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// 从配置中配置规则
|
||||
// CreateOrUpdateRuleFromConfig 从配置中配置规则
|
||||
func (this *HTTPFirewallRuleDAO) CreateOrUpdateRuleFromConfig(tx *dbs.Tx, ruleConfig *firewallconfigs.HTTPFirewallRule) (int64, error) {
|
||||
op := NewHTTPFirewallRuleOperator()
|
||||
var op = NewHTTPFirewallRuleOperator()
|
||||
op.Id = ruleConfig.Id
|
||||
op.State = HTTPFirewallRuleStateEnabled
|
||||
op.IsOn = ruleConfig.IsOn
|
||||
@@ -160,7 +160,7 @@ func (this *HTTPFirewallRuleDAO) CreateOrUpdateRuleFromConfig(tx *dbs.Tx, ruleCo
|
||||
return types.Int64(op.Id), nil
|
||||
}
|
||||
|
||||
// 通知更新
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *HTTPFirewallRuleDAO) NotifyUpdate(tx *dbs.Tx, ruleId int64) error {
|
||||
setId, err := SharedHTTPFirewallRuleSetDAO.FindEnabledRuleSetIdWithRuleId(tx, ruleId)
|
||||
if err != nil {
|
||||
|
||||
@@ -91,15 +91,15 @@ func (this *HTTPFirewallRuleGroupDAO) ComposeFirewallRuleGroup(tx *dbs.Tx, group
|
||||
}
|
||||
config := &firewallconfigs.HTTPFirewallRuleGroup{}
|
||||
config.Id = int64(group.Id)
|
||||
config.IsOn = group.IsOn == 1
|
||||
config.IsOn = group.IsOn
|
||||
config.Name = group.Name
|
||||
config.Description = group.Description
|
||||
config.Code = group.Code
|
||||
config.IsTemplate = group.IsTemplate == 1
|
||||
config.IsTemplate = group.IsTemplate
|
||||
|
||||
if IsNotNull(group.Sets) {
|
||||
setRefs := []*firewallconfigs.HTTPFirewallRuleSetRef{}
|
||||
err = json.Unmarshal([]byte(group.Sets), &setRefs)
|
||||
err = json.Unmarshal(group.Sets, &setRefs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -120,7 +120,7 @@ func (this *HTTPFirewallRuleGroupDAO) ComposeFirewallRuleGroup(tx *dbs.Tx, group
|
||||
|
||||
// CreateGroupFromConfig 从配置中创建分组
|
||||
func (this *HTTPFirewallRuleGroupDAO) CreateGroupFromConfig(tx *dbs.Tx, groupConfig *firewallconfigs.HTTPFirewallRuleGroup) (int64, error) {
|
||||
op := NewHTTPFirewallRuleGroupOperator()
|
||||
var op = NewHTTPFirewallRuleGroupOperator()
|
||||
op.IsOn = groupConfig.IsOn
|
||||
op.Name = groupConfig.Name
|
||||
op.Description = groupConfig.Description
|
||||
@@ -166,7 +166,7 @@ func (this *HTTPFirewallRuleGroupDAO) UpdateGroupIsOn(tx *dbs.Tx, groupId int64,
|
||||
|
||||
// CreateGroup 创建分组
|
||||
func (this *HTTPFirewallRuleGroupDAO) CreateGroup(tx *dbs.Tx, isOn bool, name string, code string, description string) (int64, error) {
|
||||
op := NewHTTPFirewallRuleGroupOperator()
|
||||
var op = NewHTTPFirewallRuleGroupOperator()
|
||||
op.State = HTTPFirewallRuleStateEnabled
|
||||
op.IsOn = isOn
|
||||
op.Name = name
|
||||
@@ -184,7 +184,7 @@ func (this *HTTPFirewallRuleGroupDAO) UpdateGroup(tx *dbs.Tx, groupId int64, isO
|
||||
if groupId <= 0 {
|
||||
return errors.New("invalid groupId")
|
||||
}
|
||||
op := NewHTTPFirewallRuleGroupOperator()
|
||||
var op = NewHTTPFirewallRuleGroupOperator()
|
||||
op.Id = groupId
|
||||
op.IsOn = isOn
|
||||
op.Name = name
|
||||
@@ -202,7 +202,7 @@ func (this *HTTPFirewallRuleGroupDAO) UpdateGroupSets(tx *dbs.Tx, groupId int64,
|
||||
if groupId <= 0 {
|
||||
return errors.New("invalid groupId")
|
||||
}
|
||||
op := NewHTTPFirewallRuleGroupOperator()
|
||||
var op = NewHTTPFirewallRuleGroupOperator()
|
||||
op.Id = groupId
|
||||
op.Sets = setRefsJSON
|
||||
err := this.Save(tx, op)
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPFirewallRuleGroup 防火墙规则分组
|
||||
type HTTPFirewallRuleGroup struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Code string `field:"code"` // 代号
|
||||
IsTemplate uint8 `field:"isTemplate"` // 是否为预置模板
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
Sets string `field:"sets"` // 规则集列表
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
Code string `field:"code"` // 代号
|
||||
IsTemplate bool `field:"isTemplate"` // 是否为预置模板
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
State uint8 `field:"state"` // 状态
|
||||
Sets dbs.JSON `field:"sets"` // 规则集列表
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
}
|
||||
|
||||
type HTTPFirewallRuleGroupOperator struct {
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
package models
|
||||
|
||||
// 防火墙规则
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPFirewallRule 防火墙规则
|
||||
type HTTPFirewallRule struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Description string `field:"description"` // 说明
|
||||
Param string `field:"param"` // 参数
|
||||
ParamFilters string `field:"paramFilters"` // 处理器
|
||||
Operator string `field:"operator"` // 操作符
|
||||
Value string `field:"value"` // 对比值
|
||||
IsCaseInsensitive uint8 `field:"isCaseInsensitive"` // 是否大小写不敏感
|
||||
CheckpointOptions string `field:"checkpointOptions"` // 检查点参数
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Description string `field:"description"` // 说明
|
||||
Param string `field:"param"` // 参数
|
||||
ParamFilters dbs.JSON `field:"paramFilters"` // 处理器
|
||||
Operator string `field:"operator"` // 操作符
|
||||
Value string `field:"value"` // 对比值
|
||||
IsCaseInsensitive bool `field:"isCaseInsensitive"` // 是否大小写不敏感
|
||||
CheckpointOptions dbs.JSON `field:"checkpointOptions"` // 检查点参数
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
}
|
||||
|
||||
type HTTPFirewallRuleOperator struct {
|
||||
|
||||
@@ -94,7 +94,7 @@ func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int
|
||||
}
|
||||
config := &firewallconfigs.HTTPFirewallRuleSet{}
|
||||
config.Id = int64(set.Id)
|
||||
config.IsOn = set.IsOn == 1
|
||||
config.IsOn = set.IsOn
|
||||
config.Name = set.Name
|
||||
config.Description = set.Description
|
||||
config.Code = set.Code
|
||||
@@ -103,7 +103,7 @@ func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int
|
||||
|
||||
if IsNotNull(set.Rules) {
|
||||
ruleRefs := []*firewallconfigs.HTTPFirewallRuleRef{}
|
||||
err = json.Unmarshal([]byte(set.Rules), &ruleRefs)
|
||||
err = json.Unmarshal(set.Rules, &ruleRefs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -121,7 +121,7 @@ func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int
|
||||
|
||||
var actionConfigs = []*firewallconfigs.HTTPFirewallActionConfig{}
|
||||
if len(set.Actions) > 0 {
|
||||
err = json.Unmarshal([]byte(set.Actions), &actionConfigs)
|
||||
err = json.Unmarshal(set.Actions, &actionConfigs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -133,7 +133,7 @@ func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int
|
||||
|
||||
// CreateOrUpdateSetFromConfig 从配置中创建规则集
|
||||
func (this *HTTPFirewallRuleSetDAO) CreateOrUpdateSetFromConfig(tx *dbs.Tx, setConfig *firewallconfigs.HTTPFirewallRuleSet) (int64, error) {
|
||||
op := NewHTTPFirewallRuleSetOperator()
|
||||
var op = NewHTTPFirewallRuleSetOperator()
|
||||
op.State = HTTPFirewallRuleSetStateEnabled
|
||||
op.Id = setConfig.Id
|
||||
op.IsOn = setConfig.IsOn
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
package models
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPFirewallRuleSet 防火墙规则集
|
||||
type HTTPFirewallRuleSet struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Code string `field:"code"` // 代号
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Rules string `field:"rules"` // 规则列表
|
||||
Connector string `field:"connector"` // 规则之间的关系
|
||||
State uint8 `field:"state"` // 状态
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
Action string `field:"action"` // 执行的动作(过期)
|
||||
ActionOptions string `field:"actionOptions"` // 动作的选项(过期)
|
||||
Actions string `field:"actions"` // 一组动作
|
||||
IgnoreLocal uint8 `field:"ignoreLocal"` // 忽略局域网请求
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Code string `field:"code"` // 代号
|
||||
Name string `field:"name"` // 名称
|
||||
Description string `field:"description"` // 描述
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Rules dbs.JSON `field:"rules"` // 规则列表
|
||||
Connector string `field:"connector"` // 规则之间的关系
|
||||
State uint8 `field:"state"` // 状态
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
Action string `field:"action"` // 执行的动作(过期)
|
||||
ActionOptions dbs.JSON `field:"actionOptions"` // 动作的选项(过期)
|
||||
Actions dbs.JSON `field:"actions"` // 一组动作
|
||||
IgnoreLocal uint8 `field:"ignoreLocal"` // 忽略局域网请求
|
||||
}
|
||||
|
||||
type HTTPFirewallRuleSetOperator struct {
|
||||
|
||||
@@ -88,10 +88,10 @@ func (this *HTTPGzipDAO) ComposeGzipConfig(tx *dbs.Tx, gzipId int64) (*servercon
|
||||
|
||||
config := &serverconfigs.HTTPGzipCompressionConfig{}
|
||||
config.Id = int64(gzip.Id)
|
||||
config.IsOn = gzip.IsOn == 1
|
||||
config.IsOn = gzip.IsOn
|
||||
if IsNotNull(gzip.MinLength) {
|
||||
minLengthConfig := &shared.SizeCapacity{}
|
||||
err = json.Unmarshal([]byte(gzip.MinLength), minLengthConfig)
|
||||
err = json.Unmarshal(gzip.MinLength, minLengthConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -99,7 +99,7 @@ func (this *HTTPGzipDAO) ComposeGzipConfig(tx *dbs.Tx, gzipId int64) (*servercon
|
||||
}
|
||||
if IsNotNull(gzip.MaxLength) {
|
||||
maxLengthConfig := &shared.SizeCapacity{}
|
||||
err = json.Unmarshal([]byte(gzip.MaxLength), maxLengthConfig)
|
||||
err = json.Unmarshal(gzip.MaxLength, maxLengthConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -109,7 +109,7 @@ func (this *HTTPGzipDAO) ComposeGzipConfig(tx *dbs.Tx, gzipId int64) (*servercon
|
||||
|
||||
if IsNotNull(gzip.Conds) {
|
||||
condsConfig := &shared.HTTPRequestCondsConfig{}
|
||||
err = json.Unmarshal([]byte(gzip.Conds), condsConfig)
|
||||
err = json.Unmarshal(gzip.Conds, condsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -121,7 +121,7 @@ func (this *HTTPGzipDAO) ComposeGzipConfig(tx *dbs.Tx, gzipId int64) (*servercon
|
||||
|
||||
// CreateGzip 创建Gzip
|
||||
func (this *HTTPGzipDAO) CreateGzip(tx *dbs.Tx, level int, minLengthJSON []byte, maxLengthJSON []byte, condsJSON []byte) (int64, error) {
|
||||
op := NewHTTPGzipOperator()
|
||||
var op = NewHTTPGzipOperator()
|
||||
op.State = HTTPGzipStateEnabled
|
||||
op.IsOn = true
|
||||
op.Level = level
|
||||
@@ -146,7 +146,7 @@ func (this *HTTPGzipDAO) UpdateGzip(tx *dbs.Tx, gzipId int64, level int, minLeng
|
||||
if gzipId <= 0 {
|
||||
return errors.New("invalid gzipId")
|
||||
}
|
||||
op := NewHTTPGzipOperator()
|
||||
var op = NewHTTPGzipOperator()
|
||||
op.Id = gzipId
|
||||
op.Level = level
|
||||
if len(minLengthJSON) > 0 {
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
package models
|
||||
|
||||
// Gzip配置
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// HTTPGzip Gzip配置
|
||||
type HTTPGzip struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Level uint32 `field:"level"` // 压缩级别
|
||||
MinLength string `field:"minLength"` // 可压缩最小值
|
||||
MaxLength string `field:"maxLength"` // 可压缩最大值
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Conds string `field:"conds"` // 条件
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Level uint32 `field:"level"` // 压缩级别
|
||||
MinLength dbs.JSON `field:"minLength"` // 可压缩最小值
|
||||
MaxLength dbs.JSON `field:"maxLength"` // 可压缩最大值
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Conds dbs.JSON `field:"conds"` // 条件
|
||||
}
|
||||
|
||||
type HTTPGzipOperator struct {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user