Compare commits
154 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a62711e520 | ||
|
|
ffce574b39 | ||
|
|
4b1a9f9a45 | ||
|
|
7a86ecb44b | ||
|
|
89a113431a | ||
|
|
ce62d0769b | ||
|
|
a72dc2e011 | ||
|
|
91ca2d6b6b | ||
|
|
0de6fa5ce8 | ||
|
|
84e2628769 | ||
|
|
fc28798c9f | ||
|
|
24c21c5513 | ||
|
|
8445e811a5 | ||
|
|
d54621d500 | ||
|
|
ef045e90f2 | ||
|
|
5205136809 | ||
|
|
179a7760fa | ||
|
|
640e69524c | ||
|
|
3620ab3dc6 | ||
|
|
5789b1afb9 | ||
|
|
6f9f9dfb6f | ||
|
|
171bafce6a | ||
|
|
7c7fecab26 | ||
|
|
7afdf5a2d9 | ||
|
|
ee9718ac77 | ||
|
|
15e10182da | ||
|
|
4341c5b738 | ||
|
|
cf9b31b8eb | ||
|
|
564d440cd1 | ||
|
|
bad9231ab3 | ||
|
|
a78333c490 | ||
|
|
ace44173ec | ||
|
|
5155ce97af | ||
|
|
e2bf3ba1a4 | ||
|
|
9abc65bd2b | ||
|
|
a99156ea49 | ||
|
|
d35db163ae | ||
|
|
e7b0f0df90 | ||
|
|
eab09fa37a | ||
|
|
ec3f89ecf5 | ||
|
|
d58106c7ca | ||
|
|
5da924118d | ||
|
|
51e37f0c52 | ||
|
|
7e9e764322 | ||
|
|
75e41fff4d | ||
|
|
8a9842edaf | ||
|
|
4e8629d74a | ||
|
|
2e02aa556e | ||
|
|
974c95c20a | ||
|
|
3c0e6a900b | ||
|
|
fb420f8fce | ||
|
|
705e80f6c7 | ||
|
|
9a4be1f5a7 | ||
|
|
7d82c3abf6 | ||
|
|
55034efa87 | ||
|
|
3ff45d6f49 | ||
|
|
2b2c285c90 | ||
|
|
29ad1bc741 | ||
|
|
a263ab5938 | ||
|
|
6b34d32a8f | ||
|
|
3ff6ca5905 | ||
|
|
59ce71f72e | ||
|
|
49da653ed8 | ||
|
|
12db6910dc | ||
|
|
3ce1aa14b5 | ||
|
|
c67fbfa849 | ||
|
|
72b94c5035 | ||
|
|
01ea13d283 | ||
|
|
91378b26dd | ||
|
|
46dc74195b | ||
|
|
63316b6b23 | ||
|
|
1b8600e04d | ||
|
|
11141d022f | ||
|
|
8fd29bd81c | ||
|
|
820779e614 | ||
|
|
d45dc35ea6 | ||
|
|
b3280ee290 | ||
|
|
ff0e89aa5f | ||
|
|
6ff5ba67e8 | ||
|
|
e7474523ba | ||
|
|
0b928aed14 | ||
|
|
52dcd3da1f | ||
|
|
0260d6f735 | ||
|
|
364636ea61 | ||
|
|
12f816cb5e | ||
|
|
ef70d3465d | ||
|
|
a3a9e726cb | ||
|
|
0c65774c82 | ||
|
|
fa31e547a2 | ||
|
|
c406536511 | ||
|
|
35f48e4f5d | ||
|
|
851e982ab9 | ||
|
|
956186613f | ||
|
|
aeb2a0c4f9 | ||
|
|
4f05671af2 | ||
|
|
6b6170b183 | ||
|
|
29f2aa2654 | ||
|
|
ed234b58bc | ||
|
|
cfcad531f4 | ||
|
|
12ffdfd849 | ||
|
|
c2be7d70b8 | ||
|
|
efe723bc51 | ||
|
|
501559e3b8 | ||
|
|
de8b3c2195 | ||
|
|
31aeb21e09 | ||
|
|
f1cf89a78c | ||
|
|
d6df5e1c48 | ||
|
|
049b9b52dd | ||
|
|
c53259008e | ||
|
|
6e0a0a099d | ||
|
|
f4313de55f | ||
|
|
fd3823255c | ||
|
|
79823f4317 | ||
|
|
99fd015066 | ||
|
|
f63c2d867d | ||
|
|
eefb497c20 | ||
|
|
1c8564d817 | ||
|
|
1359997f48 | ||
|
|
4a52d43273 | ||
|
|
fb68de23c1 | ||
|
|
c1b7cf11c3 | ||
|
|
311751596c | ||
|
|
4132dee4bc | ||
|
|
8e886cd410 | ||
|
|
d6f896298d | ||
|
|
2ca8aa4b44 | ||
|
|
783052a0b4 | ||
|
|
5bda9e4b51 | ||
|
|
f7cbf051bd | ||
|
|
4d7e82d0a2 | ||
|
|
bf2ffeb15c | ||
|
|
7b3290800d | ||
|
|
eaebb6df5a | ||
|
|
acdddf5e12 | ||
|
|
1224758b5b | ||
|
|
5b32343a2c | ||
|
|
8afd21f2f4 | ||
|
|
3e76bf6e5a | ||
|
|
ed74adebac | ||
|
|
1400dff676 | ||
|
|
8e3360b368 | ||
|
|
e80441639c | ||
|
|
07bf994b68 | ||
|
|
344ef4d597 | ||
|
|
144b9b9519 | ||
|
|
38841d6d75 | ||
|
|
6d1603e253 | ||
|
|
6ce23c9913 | ||
|
|
fd8c9adbf7 | ||
|
|
ea40dc7534 | ||
|
|
37c8a8c955 | ||
|
|
2a0e4bba4b | ||
|
|
dd252b7b87 | ||
|
|
2de63863a7 |
@@ -76,8 +76,10 @@ function build() {
|
||||
fi
|
||||
|
||||
# build sql
|
||||
echo "building sql ..."
|
||||
${ROOT}/sql.sh
|
||||
if [ $TAG = "plus" ]; then
|
||||
echo "building sql ..."
|
||||
${ROOT}/sql.sh
|
||||
fi
|
||||
|
||||
# copy files
|
||||
echo "copying ..."
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/gosock/pkg/gosock"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
@@ -68,6 +69,34 @@ func main() {
|
||||
}
|
||||
fmt.Println("done")
|
||||
})
|
||||
app.On("goman", func() {
|
||||
var sock = gosock.NewTmpSock(teaconst.ProcessName)
|
||||
reply, err := sock.Send(&gosock.Command{Code: "goman"})
|
||||
if err != nil {
|
||||
fmt.Println("[ERROR]" + err.Error())
|
||||
} else {
|
||||
instancesJSON, err := json.MarshalIndent(reply.Params, "", " ")
|
||||
if err != nil {
|
||||
fmt.Println("[ERROR]" + err.Error())
|
||||
} else {
|
||||
fmt.Println(string(instancesJSON))
|
||||
}
|
||||
}
|
||||
})
|
||||
app.On("debug", func() {
|
||||
var sock = gosock.NewTmpSock(teaconst.ProcessName)
|
||||
reply, err := sock.Send(&gosock.Command{Code: "debug"})
|
||||
if err != nil {
|
||||
fmt.Println("[ERROR]" + err.Error())
|
||||
} else {
|
||||
var isDebug = maps.NewMap(reply.Params).GetBool("debug")
|
||||
if isDebug {
|
||||
fmt.Println("debug on")
|
||||
} else {
|
||||
fmt.Println("debug off")
|
||||
}
|
||||
}
|
||||
})
|
||||
app.Run(func() {
|
||||
nodes.NewAPINode().Start()
|
||||
})
|
||||
|
||||
6
go.mod
6
go.mod
@@ -4,20 +4,20 @@ go 1.15
|
||||
|
||||
replace github.com/TeaOSLab/EdgeCommon => ../EdgeCommon
|
||||
|
||||
|
||||
require (
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
|
||||
github.com/TeaOSLab/EdgeCommon v0.0.0-00010101000000-000000000000
|
||||
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-20210831140440-a2a442471b13
|
||||
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.11 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/lionsoul2014/ip2region v2.2.0-release+incompatible
|
||||
github.com/mozillazg/go-pinyin v0.18.0
|
||||
github.com/pkg/sftp v1.12.0
|
||||
|
||||
8
go.sum
8
go.sum
@@ -50,6 +50,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1183 h1:dkj8/dxOQ4L1XpwCzRLqukvUBbxuNdz3FeyvHFnRjmo=
|
||||
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/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=
|
||||
@@ -232,6 +234,8 @@ github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f/go.mod h1:KU4mS7QNiZ7Q
|
||||
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/gosock v0.0.0-20210722083328-12b2d66abec3 h1:aBSonas7vFcgTj9u96/bWGILGv1ZbUSTLiOzcI1ZT6c=
|
||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
|
||||
github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
|
||||
@@ -248,6 +252,8 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
|
||||
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=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
@@ -318,6 +324,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
|
||||
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=
|
||||
github.com/mozillazg/go-pinyin v0.18.0 h1:hQompXO23/0ohH8YNjvfsAITnCQImCiR/Fny8EhIeW0=
|
||||
github.com/mozillazg/go-pinyin v0.18.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
|
||||
@@ -13,9 +13,7 @@ import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -57,14 +55,12 @@ func (this *ESStorage) Write(accessLogs []*pb.HTTPAccessLog) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var requestId int64 = 1_0000_0000_0000_0000
|
||||
|
||||
bulk := &strings.Builder{}
|
||||
indexName := this.FormatVariables(this.config.Index)
|
||||
typeName := this.FormatVariables(this.config.MappingType)
|
||||
for _, accessLog := range accessLogs {
|
||||
if len(accessLog.RequestId) == 0 {
|
||||
accessLog.RequestId = strconv.FormatInt(time.Now().UnixNano(), 10) + strconv.FormatInt(atomic.AddInt64(&requestId, 1), 10) + fmt.Sprintf("%08d", 1)
|
||||
continue
|
||||
}
|
||||
|
||||
opData, err := json.Marshal(map[string]interface{}{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
//go:build community
|
||||
// +build community
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package accesslogs
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package configs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
"github.com/go-yaml/yaml"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
@@ -11,9 +10,8 @@ import (
|
||||
)
|
||||
|
||||
var sharedAPIConfig *APIConfig = nil
|
||||
var PaddingId string
|
||||
|
||||
// API节点配置
|
||||
// APIConfig API节点配置
|
||||
type APIConfig struct {
|
||||
NodeId string `yaml:"nodeId" json:"nodeId"`
|
||||
Secret string `yaml:"secret" json:"secret"`
|
||||
@@ -21,7 +19,7 @@ type APIConfig struct {
|
||||
numberId int64 // 数字ID
|
||||
}
|
||||
|
||||
// 获取共享配置
|
||||
// SharedAPIConfig 获取共享配置
|
||||
func SharedAPIConfig() (*APIConfig, error) {
|
||||
sharedLocker.Lock()
|
||||
defer sharedLocker.Unlock()
|
||||
@@ -72,7 +70,7 @@ func SharedAPIConfig() (*APIConfig, error) {
|
||||
{
|
||||
dbConfigFile := Tea.ConfigFile("db.yaml")
|
||||
_, err := os.Stat(dbConfigFile)
|
||||
if err == nil {
|
||||
if err != nil {
|
||||
paths := []string{}
|
||||
homeDir, homeErr := os.UserHomeDir()
|
||||
if homeErr == nil {
|
||||
@@ -96,18 +94,18 @@ func SharedAPIConfig() (*APIConfig, error) {
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// 设置数字ID
|
||||
// SetNumberId 设置数字ID
|
||||
func (this *APIConfig) SetNumberId(numberId int64) {
|
||||
this.numberId = numberId
|
||||
PaddingId = fmt.Sprintf("%08d", numberId)
|
||||
teaconst.NodeId = numberId
|
||||
}
|
||||
|
||||
// 获取数字ID
|
||||
// NumberId 获取数字ID
|
||||
func (this *APIConfig) NumberId() int64 {
|
||||
return this.numberId
|
||||
}
|
||||
|
||||
// 保存到文件
|
||||
// WriteFile 保存到文件
|
||||
func (this *APIConfig) WriteFile(path string) error {
|
||||
data, err := yaml.Marshal(this)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
// +build community
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package teaconst
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package teaconst
|
||||
|
||||
const (
|
||||
Version = "0.3.3"
|
||||
Version = "0.4.3"
|
||||
|
||||
ProductName = "Edge API"
|
||||
ProcessName = "edge-api"
|
||||
@@ -18,10 +18,10 @@ const (
|
||||
|
||||
// 其他节点版本号,用来检测是否有需要升级的节点
|
||||
|
||||
NodeVersion = "0.3.3"
|
||||
UserNodeVersion = "0.0.10"
|
||||
NodeVersion = "0.4.3"
|
||||
UserNodeVersion = "0.3.1"
|
||||
AuthorityNodeVersion = "0.0.2"
|
||||
MonitorNodeVersion = "0.0.3"
|
||||
DNSNodeVersion = "0.2.0"
|
||||
DNSNodeVersion = "0.2.1"
|
||||
ReportNodeVersion = "0.1.0"
|
||||
)
|
||||
|
||||
@@ -5,4 +5,6 @@ package teaconst
|
||||
var (
|
||||
IsPlus = false
|
||||
MaxNodes int32 = 0
|
||||
NodeId int64 = 0
|
||||
Debug = false
|
||||
)
|
||||
|
||||
80
internal/db/models/accounts/user_account_daily_stat_dao.go
Normal file
80
internal/db/models/accounts/user_account_daily_stat_dao.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type UserAccountDailyStatDAO dbs.DAO
|
||||
|
||||
func NewUserAccountDailyStatDAO() *UserAccountDailyStatDAO {
|
||||
return dbs.NewDAO(&UserAccountDailyStatDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeUserAccountDailyStats",
|
||||
Model: new(UserAccountDailyStat),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*UserAccountDailyStatDAO)
|
||||
}
|
||||
|
||||
var SharedUserAccountDailyStatDAO *UserAccountDailyStatDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedUserAccountDailyStatDAO = NewUserAccountDailyStatDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateDailyStat 更新当天统计数据
|
||||
func (this *UserAccountDailyStatDAO) UpdateDailyStat(tx *dbs.Tx) error {
|
||||
var day = timeutil.Format("Ymd")
|
||||
var month = timeutil.Format("Ym")
|
||||
income, err := SharedUserAccountLogDAO.SumDailyEventTypes(tx, day, userconfigs.AccountIncomeEventTypes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
expense, err := SharedUserAccountLogDAO.SumDailyEventTypes(tx, day, userconfigs.AccountExpenseEventTypes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if expense < 0 {
|
||||
expense = -expense
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
InsertOrUpdateQuickly(maps.Map{
|
||||
"day": day,
|
||||
"month": month,
|
||||
"income": income,
|
||||
"expense": expense,
|
||||
}, maps.Map{
|
||||
"income": income,
|
||||
"expense": expense,
|
||||
})
|
||||
}
|
||||
|
||||
// FindDailyStats 查看按天统计
|
||||
func (this *UserAccountDailyStatDAO) FindDailyStats(tx *dbs.Tx, dayFrom string, dayTo string) (result []*UserAccountDailyStat, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Between("day", dayFrom, dayTo).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindMonthlyStats 查看某月统计
|
||||
func (this *UserAccountDailyStatDAO) FindMonthlyStats(tx *dbs.Tx, dayFrom string, dayTo string) (result []*UserAccountDailyStat, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Result("SUM(income) AS income", "SUM(expense) AS expense", "month").
|
||||
Between("day", dayFrom, dayTo).
|
||||
Group("month").
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
22
internal/db/models/accounts/user_account_daily_stat_model.go
Normal file
22
internal/db/models/accounts/user_account_daily_stat_model.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package accounts
|
||||
|
||||
// UserAccountDailyStat 账户每日统计
|
||||
type UserAccountDailyStat struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Day string `field:"day"` // YYYYMMDD
|
||||
Month string `field:"month"` // YYYYMM
|
||||
Income float64 `field:"income"` // 收入
|
||||
Expense float64 `field:"expense"` // 支出
|
||||
}
|
||||
|
||||
type UserAccountDailyStatOperator struct {
|
||||
Id interface{} // ID
|
||||
Day interface{} // YYYYMMDD
|
||||
Month interface{} // YYYYMM
|
||||
Income interface{} // 收入
|
||||
Expense interface{} // 支出
|
||||
}
|
||||
|
||||
func NewUserAccountDailyStatOperator() *UserAccountDailyStatOperator {
|
||||
return &UserAccountDailyStatOperator{}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package accounts
|
||||
253
internal/db/models/accounts/user_account_dao.go
Normal file
253
internal/db/models/accounts/user_account_dao.go
Normal file
@@ -0,0 +1,253 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
goman.New(func() {
|
||||
// 自动支付账单任务
|
||||
var ticker = time.NewTicker(12 * time.Hour)
|
||||
for range ticker.C {
|
||||
if SharedUserAccountDAO.Instance != nil {
|
||||
err := SharedUserAccountDAO.Instance.RunTx(func(tx *dbs.Tx) error {
|
||||
return SharedUserAccountDAO.PayBills(tx)
|
||||
})
|
||||
if err != nil {
|
||||
remotelogs.Error("USER_ACCOUNT_DAO", "pay bills task failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
type UserAccountDAO dbs.DAO
|
||||
|
||||
func NewUserAccountDAO() *UserAccountDAO {
|
||||
return dbs.NewDAO(&UserAccountDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeUserAccounts",
|
||||
Model: new(UserAccount),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*UserAccountDAO)
|
||||
}
|
||||
|
||||
var SharedUserAccountDAO *UserAccountDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedUserAccountDAO = NewUserAccountDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// FindUserAccountWithUserId 根据用户ID查找用户账户
|
||||
func (this *UserAccountDAO) FindUserAccountWithUserId(tx *dbs.Tx, userId int64) (*UserAccount, error) {
|
||||
if userId <= 0 {
|
||||
return nil, errors.New("invalid userId '" + types.String(userId) + "'")
|
||||
}
|
||||
|
||||
// 用户是否存在
|
||||
user, err := models.SharedUserDAO.FindEnabledUser(tx, userId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if user == nil {
|
||||
return nil, errors.New("invalid userId '" + types.String(userId) + "'")
|
||||
}
|
||||
|
||||
account, err := this.Query(tx).
|
||||
Attr("userId", userId).
|
||||
Find()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if account != nil {
|
||||
return account.(*UserAccount), nil
|
||||
}
|
||||
|
||||
var op = NewUserAccountOperator()
|
||||
op.UserId = userId
|
||||
_, err = this.SaveInt64(tx, op)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.FindUserAccountWithUserId(tx, userId)
|
||||
}
|
||||
|
||||
// FindUserAccountWithAccountId 根据ID查找用户账户
|
||||
func (this *UserAccountDAO) FindUserAccountWithAccountId(tx *dbs.Tx, accountId int64) (*UserAccount, error) {
|
||||
one, err := this.Query(tx).
|
||||
Pk(accountId).
|
||||
Find()
|
||||
if one != nil {
|
||||
return one.(*UserAccount), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// UpdateUserAccount 操作用户账户
|
||||
func (this *UserAccountDAO) UpdateUserAccount(tx *dbs.Tx, accountId int64, delta float32, eventType userconfigs.AccountEventType, description string, params maps.Map) error {
|
||||
account, err := this.FindUserAccountWithAccountId(tx, accountId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if account == nil {
|
||||
return errors.New("invalid account id '" + types.String(accountId) + "'")
|
||||
}
|
||||
var userId = int64(account.UserId)
|
||||
var deltaFloat64 = float64(delta)
|
||||
if deltaFloat64 < 0 && account.Total < -deltaFloat64 {
|
||||
return errors.New("not enough account quota to decrease")
|
||||
}
|
||||
|
||||
// 操作账户
|
||||
err = this.Query(tx).
|
||||
Pk(account.Id).
|
||||
Set("total", dbs.SQL("total+:delta")).
|
||||
Param("delta", delta).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 生成日志
|
||||
err = SharedUserAccountLogDAO.CreateAccountLog(tx, userId, accountId, delta, 0, eventType, description, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateUserAccountFrozen 操作用户账户冻结余额
|
||||
func (this *UserAccountDAO) UpdateUserAccountFrozen(tx *dbs.Tx, userId int64, delta float32, eventType userconfigs.AccountEventType, description string, params maps.Map) error {
|
||||
account, err := this.FindUserAccountWithUserId(tx, userId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var deltaFloat64 = float64(delta)
|
||||
if deltaFloat64 < 0 && account.TotalFrozen < -deltaFloat64 {
|
||||
return errors.New("not enough account frozen quota to decrease")
|
||||
}
|
||||
|
||||
// 操作账户
|
||||
err = this.Query(tx).
|
||||
Pk(account.Id).
|
||||
Set("totalFrozen", dbs.SQL("total+:delta")).
|
||||
Param("delta", delta).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 生成日志
|
||||
err = SharedUserAccountLogDAO.CreateAccountLog(tx, userId, int64(account.Id), 0, delta, eventType, description, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CountAllAccounts 计算所有账户数量
|
||||
func (this *UserAccountDAO) CountAllAccounts(tx *dbs.Tx, keyword string) (int64, error) {
|
||||
var query = this.Query(tx)
|
||||
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))")
|
||||
query.Param("keyword", keyword)
|
||||
} else {
|
||||
query.Where("userId IN (SELECT id FROM " + models.SharedUserDAO.Table + " WHERE state=1)")
|
||||
}
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// ListAccounts 列出单页账户
|
||||
func (this *UserAccountDAO) ListAccounts(tx *dbs.Tx, keyword string, offset int64, size int64) (result []*UserAccount, err error) {
|
||||
var query = this.Query(tx)
|
||||
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))")
|
||||
query.Param("keyword", keyword)
|
||||
} else {
|
||||
query.Where("userId IN (SELECT id FROM " + models.SharedUserDAO.Table + " WHERE state=1)")
|
||||
}
|
||||
_, err = query.
|
||||
DescPk().
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// PayBills 尝试自动支付账单
|
||||
func (this *UserAccountDAO) PayBills(tx *dbs.Tx) error {
|
||||
bills, err := models.SharedUserBillDAO.FindUnpaidBills(tx, 10000)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 先支付久远的
|
||||
lists.Reverse(bills)
|
||||
|
||||
for _, bill := range bills {
|
||||
if bill.Amount <= 0 {
|
||||
err = models.SharedUserBillDAO.UpdateUserBillIsPaid(tx, int64(bill.Id), true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
account, err := SharedUserAccountDAO.FindUserAccountWithUserId(tx, int64(bill.UserId))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if account == nil || account.Total < bill.Amount {
|
||||
continue
|
||||
}
|
||||
|
||||
// 扣款
|
||||
err = SharedUserAccountDAO.UpdateUserAccount(tx, int64(account.Id), -float32(bill.Amount), userconfigs.AccountEventTypePayBill, "支付账单"+bill.Code, maps.Map{"billId": bill.Id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 改为已支付
|
||||
err = models.SharedUserBillDAO.UpdateUserBillIsPaid(tx, int64(bill.Id), true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckUserAccount 检查用户账户
|
||||
func (this *UserAccountDAO) CheckUserAccount(tx *dbs.Tx, userId int64, accountId int64) error {
|
||||
exists, err := this.Query(tx).
|
||||
Pk(accountId).
|
||||
Attr("userId", userId).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
return models.ErrNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
18
internal/db/models/accounts/user_account_dao_test.go
Normal file
18
internal/db/models/accounts/user_account_dao_test.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUserAccountDAO_PayBills(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
err := NewUserAccountDAO().PayBills(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
128
internal/db/models/accounts/user_account_log_dao.go
Normal file
128
internal/db/models/accounts/user_account_log_dao.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type UserAccountLogDAO dbs.DAO
|
||||
|
||||
func NewUserAccountLogDAO() *UserAccountLogDAO {
|
||||
return dbs.NewDAO(&UserAccountLogDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeUserAccountLogs",
|
||||
Model: new(UserAccountLog),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*UserAccountLogDAO)
|
||||
}
|
||||
|
||||
var SharedUserAccountLogDAO *UserAccountLogDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedUserAccountLogDAO = NewUserAccountLogDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// CreateAccountLog 生成用户账户日志
|
||||
func (this *UserAccountLogDAO) CreateAccountLog(tx *dbs.Tx, userId int64, accountId int64, delta float32, deltaFrozen float32, eventType userconfigs.AccountEventType, description string, params maps.Map) error {
|
||||
var op = NewUserAccountLogOperator()
|
||||
op.UserId = userId
|
||||
op.AccountId = accountId
|
||||
op.Delta = delta
|
||||
op.DeltaFrozen = deltaFrozen
|
||||
|
||||
account, err := SharedUserAccountDAO.FindUserAccountWithAccountId(tx, accountId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if account == nil {
|
||||
return errors.New("invalid account id '" + types.String(accountId) + "'")
|
||||
}
|
||||
op.Total = account.Total
|
||||
op.TotalFrozen = account.TotalFrozen
|
||||
|
||||
op.EventType = eventType
|
||||
op.Description = description
|
||||
|
||||
if params == nil {
|
||||
params = maps.Map{}
|
||||
}
|
||||
op.Params = params.AsJSON()
|
||||
|
||||
op.Day = timeutil.Format("Ymd")
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return SharedUserAccountDailyStatDAO.UpdateDailyStat(tx)
|
||||
}
|
||||
|
||||
// CountAccountLogs 计算日志数量
|
||||
func (this *UserAccountLogDAO) CountAccountLogs(tx *dbs.Tx, userId int64, accountId int64, keyword string, eventType string) (int64, error) {
|
||||
var query = this.Query(tx)
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
}
|
||||
if accountId > 0 {
|
||||
query.Attr("accountId", accountId)
|
||||
}
|
||||
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+"%")
|
||||
}
|
||||
if len(eventType) > 0 {
|
||||
query.Attr("eventType", eventType)
|
||||
}
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// ListAccountLogs 列出单页日志
|
||||
func (this *UserAccountLogDAO) ListAccountLogs(tx *dbs.Tx, userId int64, accountId int64, keyword string, eventType string, offset int64, size int64) (result []*UserAccountLog, err error) {
|
||||
var query = this.Query(tx)
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
}
|
||||
if accountId > 0 {
|
||||
query.Attr("accountId", accountId)
|
||||
}
|
||||
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+"%")
|
||||
}
|
||||
if len(eventType) > 0 {
|
||||
query.Attr("eventType", eventType)
|
||||
}
|
||||
_, err = query.
|
||||
DescPk().
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// SumDailyEventTypes 统计某天数据总和
|
||||
func (this *UserAccountLogDAO) SumDailyEventTypes(tx *dbs.Tx, day string, eventTypes []userconfigs.AccountEventType) (float32, error) {
|
||||
if len(eventTypes) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
result, err := this.Query(tx).
|
||||
Attr("day", day).
|
||||
Attr("eventType", eventTypes).
|
||||
Sum("delta", 0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return types.Float32(result), nil
|
||||
}
|
||||
6
internal/db/models/accounts/user_account_log_dao_test.go
Normal file
6
internal/db/models/accounts/user_account_log_dao_test.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
36
internal/db/models/accounts/user_account_log_model.go
Normal file
36
internal/db/models/accounts/user_account_log_model.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package accounts
|
||||
|
||||
// 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"` // 参数
|
||||
}
|
||||
|
||||
type UserAccountLogOperator struct {
|
||||
Id interface{} // ID
|
||||
UserId interface{} // 用户ID
|
||||
AccountId interface{} // 账户ID
|
||||
Delta interface{} // 操作余额的数量(可为负)
|
||||
DeltaFrozen interface{} // 操作冻结的数量(可为负)
|
||||
Total interface{} // 操作后余额
|
||||
TotalFrozen interface{} // 操作后冻结余额
|
||||
EventType interface{} // 类型
|
||||
Description interface{} // 描述文字
|
||||
Day interface{} // YYYYMMDD
|
||||
CreatedAt interface{} // 时间
|
||||
Params interface{} // 参数
|
||||
}
|
||||
|
||||
func NewUserAccountLogOperator() *UserAccountLogOperator {
|
||||
return &UserAccountLogOperator{}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package accounts
|
||||
20
internal/db/models/accounts/user_account_model.go
Normal file
20
internal/db/models/accounts/user_account_model.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package accounts
|
||||
|
||||
// UserAccount 用户账号
|
||||
type UserAccount struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
Total float64 `field:"total"` // 可用总余额
|
||||
TotalFrozen float64 `field:"totalFrozen"` // 冻结余额
|
||||
}
|
||||
|
||||
type UserAccountOperator struct {
|
||||
Id interface{} // ID
|
||||
UserId interface{} // 用户ID
|
||||
Total interface{} // 可用总余额
|
||||
TotalFrozen interface{} // 冻结余额
|
||||
}
|
||||
|
||||
func NewUserAccountOperator() *UserAccountOperator {
|
||||
return &UserAccountOperator{}
|
||||
}
|
||||
1
internal/db/models/accounts/user_account_model_ext.go
Normal file
1
internal/db/models/accounts/user_account_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package accounts
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
acmeutils "github.com/TeaOSLab/EdgeAPI/internal/acme"
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
|
||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||
@@ -400,6 +401,7 @@ func (this *ACMETaskDAO) runTaskWithoutLog(tx *dbs.Tx, taskId int64) (isOk bool,
|
||||
client := utils.SharedHttpClient(5 * time.Second)
|
||||
req, err := http.NewRequest(http.MethodPost, task.AuthURL, bytes.NewReader(authJSON))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("User-Agent", teaconst.ProductName+"/"+teaconst.Version)
|
||||
if err != nil {
|
||||
remotelogs.Error("ACME", "parse auth url failed '"+task.AuthURL+"': "+err.Error())
|
||||
} else {
|
||||
|
||||
76
internal/db/models/api_method_stat_dao.go
Normal file
76
internal/db/models/api_method_stat_dao.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type APIMethodStatDAO dbs.DAO
|
||||
|
||||
func NewAPIMethodStatDAO() *APIMethodStatDAO {
|
||||
return dbs.NewDAO(&APIMethodStatDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeAPIMethodStats",
|
||||
Model: new(APIMethodStat),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*APIMethodStatDAO)
|
||||
}
|
||||
|
||||
var SharedAPIMethodStatDAO *APIMethodStatDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedAPIMethodStatDAO = NewAPIMethodStatDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// CreateStat 记录统计数据
|
||||
func (this *APIMethodStatDAO) CreateStat(tx *dbs.Tx, method string, tag string, costMs float64) error {
|
||||
var day = timeutil.Format("Ymd")
|
||||
return this.Query(tx).
|
||||
Param("costMs", costMs).
|
||||
InsertOrUpdateQuickly(map[string]interface{}{
|
||||
"apiNodeId": teaconst.NodeId,
|
||||
"method": method,
|
||||
"tag": tag,
|
||||
"costMs": costMs,
|
||||
"peekMs": costMs,
|
||||
"countCalls": 1,
|
||||
"day": day,
|
||||
}, map[string]interface{}{
|
||||
"costMs": dbs.SQL("(costMs*countCalls+:costMs)/(countCalls+1)"),
|
||||
"peekMs": dbs.SQL("IF(peekMs>:costMs, peekMs, :costMs)"),
|
||||
"countCalls": dbs.SQL("countCalls+1"),
|
||||
})
|
||||
}
|
||||
|
||||
// FindAllStatsWithDay 查询当前统计
|
||||
func (this *APIMethodStatDAO) FindAllStatsWithDay(tx *dbs.Tx, day string) (result []*APIMethodStat, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Attr("day", day).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// CountAllStatsWithDay 统计当天数量
|
||||
func (this *APIMethodStatDAO) CountAllStatsWithDay(tx *dbs.Tx, day string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Attr("day", day).
|
||||
Count()
|
||||
}
|
||||
|
||||
// Clean 清理数据
|
||||
func (this *APIMethodStatDAO) Clean(tx *dbs.Tx) error {
|
||||
var day = timeutil.Format("Ymd")
|
||||
_, err := this.Query(tx).
|
||||
Param("day", day).
|
||||
Where("day<:day").
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
19
internal/db/models/api_method_stat_dao_test.go
Normal file
19
internal/db/models/api_method_stat_dao_test.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAPIMethodStatDAO_CreateStat(t *testing.T) {
|
||||
var dao = NewAPIMethodStatDAO()
|
||||
var tx *dbs.Tx
|
||||
|
||||
err := dao.CreateStat(tx, "/pb.Hello/World", "tag", 1.123)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
28
internal/db/models/api_method_stat_model.go
Normal file
28
internal/db/models/api_method_stat_model.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package models
|
||||
|
||||
// APIMethodStat API方法统计
|
||||
type APIMethodStat struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
ApiNodeId uint32 `field:"apiNodeId"` // API节点ID
|
||||
Method string `field:"method"` // 方法
|
||||
Tag string `field:"tag"` // 标签方法
|
||||
CostMs float64 `field:"costMs"` // 耗时Ms
|
||||
PeekMs float64 `field:"peekMs"` // 峰值耗时
|
||||
CountCalls uint64 `field:"countCalls"` // 调用次数
|
||||
Day string `field:"day"` // 日期
|
||||
}
|
||||
|
||||
type APIMethodStatOperator struct {
|
||||
Id interface{} // ID
|
||||
ApiNodeId interface{} // API节点ID
|
||||
Method interface{} // 方法
|
||||
Tag interface{} // 标签方法
|
||||
CostMs interface{} // 耗时Ms
|
||||
PeekMs interface{} // 峰值耗时
|
||||
CountCalls interface{} // 调用次数
|
||||
Day interface{} // 日期
|
||||
}
|
||||
|
||||
func NewAPIMethodStatOperator() *APIMethodStatOperator {
|
||||
return &APIMethodStatOperator{}
|
||||
}
|
||||
1
internal/db/models/api_method_stat_model_ext.go
Normal file
1
internal/db/models/api_method_stat_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package models
|
||||
@@ -8,10 +8,13 @@ import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -59,7 +62,15 @@ func (this *APINodeDAO) DisableAPINode(tx *dbs.Tx, id int64) error {
|
||||
}
|
||||
|
||||
// FindEnabledAPINode 查找启用中的条目
|
||||
func (this *APINodeDAO) FindEnabledAPINode(tx *dbs.Tx, id int64) (*APINode, error) {
|
||||
func (this *APINodeDAO) FindEnabledAPINode(tx *dbs.Tx, id int64, cacheMap *utils.CacheMap) (*APINode, error) {
|
||||
var cacheKey = this.Table + ":FindEnabledAPINode:" + types.String(id)
|
||||
if cacheMap != nil {
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return cache.(*APINode), nil
|
||||
}
|
||||
}
|
||||
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", APINodeStateEnabled).
|
||||
@@ -67,6 +78,11 @@ func (this *APINodeDAO) FindEnabledAPINode(tx *dbs.Tx, id int64) (*APINode, erro
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, result)
|
||||
}
|
||||
|
||||
return result.(*APINode), err
|
||||
}
|
||||
|
||||
@@ -219,7 +235,6 @@ func (this *APINodeDAO) CountAllEnabledAndOnAPINodes(tx *dbs.Tx) (int64, error)
|
||||
Count()
|
||||
}
|
||||
|
||||
|
||||
// CountAllEnabledAndOnOfflineAPINodes 计算API节点数量
|
||||
func (this *APINodeDAO) CountAllEnabledAndOnOfflineAPINodes(tx *dbs.Tx) (int64, error) {
|
||||
return this.Query(tx).
|
||||
@@ -305,3 +320,67 @@ func (this *APINodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) (i
|
||||
Param("version", utils.VersionToLong(version)).
|
||||
Count()
|
||||
}
|
||||
|
||||
// CountAllEnabledAPINodesWithSSLPolicyIds 计算使用SSL策略的所有API节点数量
|
||||
func (this *APINodeDAO) CountAllEnabledAPINodesWithSSLPolicyIds(tx *dbs.Tx, sslPolicyIds []int64) (count int64, err error) {
|
||||
if len(sslPolicyIds) == 0 {
|
||||
return
|
||||
}
|
||||
policyStringIds := []string{}
|
||||
for _, policyId := range sslPolicyIds {
|
||||
policyStringIds = append(policyStringIds, strconv.FormatInt(policyId, 10))
|
||||
}
|
||||
return this.Query(tx).
|
||||
State(APINodeStateEnabled).
|
||||
Where("(FIND_IN_SET(JSON_EXTRACT(https, '$.sslPolicyRef.sslPolicyId'), :policyIds) OR FIND_IN_SET(JSON_EXTRACT(restHTTPS, '$.sslPolicyRef.sslPolicyId'), :policyIds))").
|
||||
Param("policyIds", strings.Join(policyStringIds, ",")).
|
||||
Count()
|
||||
}
|
||||
|
||||
// FindAllEnabledAPIAccessIPs 获取所有的API可访问IP地址
|
||||
func (this *APINodeDAO) FindAllEnabledAPIAccessIPs(tx *dbs.Tx, cacheMap *utils.CacheMap) ([]string, error) {
|
||||
var cacheKey = this.Table + ":FindAllEnabledAPIAccessIPs"
|
||||
if cacheMap != nil {
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return cache.([]string), nil
|
||||
}
|
||||
}
|
||||
|
||||
ones, _, err := this.Query(tx).
|
||||
State(APINodeStateEnabled).
|
||||
Result("JSON_EXTRACT(accessAddrs, '$[*].host') AS host").
|
||||
FindOnes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var result = []string{}
|
||||
for _, one := range ones {
|
||||
var host = one.GetString("host")
|
||||
if len(host) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
var ips = []string{}
|
||||
err = json.Unmarshal([]byte(host), &ips)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, ip := range ips {
|
||||
if !lists.ContainsString(result, ip) {
|
||||
if net.ParseIP(ip) == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
result = append(result, ip)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, result)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"runtime"
|
||||
@@ -27,6 +28,12 @@ func TestAPINodeDAO_FindEnabledAPINodeIdWithAddr(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAPINodeDAO_FindAllEnabledAPIAccessIPs(t *testing.T) {
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
t.Log(NewAPINodeDAO().FindAllEnabledAPIAccessIPs(nil, cacheMap))
|
||||
t.Log(NewAPINodeDAO().FindAllEnabledAPIAccessIPs(nil, cacheMap))
|
||||
}
|
||||
|
||||
func BenchmarkAPINodeDAO_New(b *testing.B) {
|
||||
runtime.GOMAXPROCS(1)
|
||||
for i := 0; i < b.N; i++ {
|
||||
|
||||
@@ -2,9 +2,9 @@ package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// DecodeHTTP 解析HTTP配置
|
||||
@@ -27,11 +27,7 @@ func (this *APINode) DecodeHTTP() (*serverconfigs.HTTPProtocolConfig, error) {
|
||||
}
|
||||
|
||||
// DecodeHTTPS 解析HTTPS配置
|
||||
func (this *APINode) DecodeHTTPS(tx *dbs.Tx, cacheMap maps.Map) (*serverconfigs.HTTPSProtocolConfig, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = maps.Map{}
|
||||
}
|
||||
|
||||
func (this *APINode) DecodeHTTPS(tx *dbs.Tx, cacheMap *utils.CacheMap) (*serverconfigs.HTTPSProtocolConfig, error) {
|
||||
if !IsNotNull(this.Https) {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -123,9 +119,9 @@ func (this *APINode) DecodeRestHTTP() (*serverconfigs.HTTPProtocolConfig, error)
|
||||
}
|
||||
|
||||
// DecodeRestHTTPS 解析HTTPS配置
|
||||
func (this *APINode) DecodeRestHTTPS(tx *dbs.Tx, cacheMap maps.Map) (*serverconfigs.HTTPSProtocolConfig, error) {
|
||||
func (this *APINode) DecodeRestHTTPS(tx *dbs.Tx, cacheMap *utils.CacheMap) (*serverconfigs.HTTPSProtocolConfig, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = maps.Map{}
|
||||
cacheMap = utils.NewCacheMap()
|
||||
}
|
||||
if this.RestIsOn != 1 {
|
||||
return nil, nil
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build community
|
||||
// +build community
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package authority
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -85,7 +86,7 @@ func (this *ClientBrowserDAO) FindBrowserIdWithNameCacheable(tx *dbs.Tx, browser
|
||||
|
||||
browserId, err := this.Query(tx).
|
||||
Where("JSON_CONTAINS(codes, :browserName)").
|
||||
Param("browserName", "\""+browserName+"\""). // 查询的需要是个JSON字符串,所以这里加双引号
|
||||
Param("browserName", strconv.Quote(browserName)). // 查询的需要是个JSON字符串,所以这里加双引号
|
||||
ResultPk().
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -85,7 +86,7 @@ func (this *ClientSystemDAO) FindSystemIdWithNameCacheable(tx *dbs.Tx, systemNam
|
||||
|
||||
systemId, err := this.Query(tx).
|
||||
Where("JSON_CONTAINS(codes, :systemName)").
|
||||
Param("systemName", "\""+systemName+"\""). // 查询的需要是个JSON字符串,所以这里加双引号
|
||||
Param("systemName", strconv.Quote(systemName)). // 查询的需要是个JSON字符串,所以这里加双引号
|
||||
ResultPk().
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
|
||||
@@ -3,7 +3,9 @@ package models
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
@@ -49,7 +51,9 @@ type NSAccessLogDAOWrapper struct {
|
||||
func init() {
|
||||
initializer := NewDBNodeInitializer()
|
||||
dbs.OnReadyDone(func() {
|
||||
go initializer.Start()
|
||||
goman.New(func() {
|
||||
initializer.Start()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -138,7 +142,7 @@ func findNSAccessLogTableName(db *dbs.DB, day string) (tableName string, ok bool
|
||||
return tableName, false, err
|
||||
}
|
||||
|
||||
return tableName, lists.ContainsString(tableNames, tableName), nil
|
||||
return tableName, utils.ContainsStringInsensitive(tableNames, tableName), nil
|
||||
}
|
||||
|
||||
// 根据日期获取表名
|
||||
@@ -165,7 +169,7 @@ func findHTTPAccessLogTable(db *dbs.DB, day string, force bool) (*httpAccessLogD
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if lists.ContainsString(tableNames, tableName) {
|
||||
if utils.ContainsStringInsensitive(tableNames, tableName) {
|
||||
table, err := db.FindTable(tableName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -193,7 +197,7 @@ func findHTTPAccessLogTable(db *dbs.DB, day string, force bool) (*httpAccessLogD
|
||||
}
|
||||
|
||||
// 创建表格
|
||||
_, 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` blob COMMENT '请求内容',\n `responseBody` blob 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='访问日志';")
|
||||
_, 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
|
||||
}
|
||||
@@ -233,7 +237,7 @@ func findNSAccessLogTable(db *dbs.DB, day string, force bool) (string, error) {
|
||||
return tableName, err
|
||||
}
|
||||
|
||||
if lists.ContainsString(tableNames, tableName) {
|
||||
if utils.ContainsStringInsensitive(tableNames, tableName) {
|
||||
accessLogLocker.Lock()
|
||||
nsAccessLogTableMapping[cacheKey] = true
|
||||
accessLogLocker.Unlock()
|
||||
@@ -353,7 +357,7 @@ func (this *DBNodeInitializer) loop() 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())
|
||||
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())
|
||||
}
|
||||
@@ -361,6 +365,7 @@ func (this *DBNodeInitializer) loop() error {
|
||||
continue
|
||||
} else {
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,7 +402,7 @@ func (this *DBNodeInitializer) loop() 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())
|
||||
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())
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/dnsclients/dnstypes"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -58,14 +59,13 @@ func (this *DNSDomainDAO) DisableDNSDomain(tx *dbs.Tx, id int64) error {
|
||||
}
|
||||
|
||||
// FindEnabledDNSDomain 查找启用中的条目
|
||||
func (this *DNSDomainDAO) FindEnabledDNSDomain(tx *dbs.Tx, domainId int64, cacheMap maps.Map) (*DNSDomain, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = maps.Map{}
|
||||
}
|
||||
func (this *DNSDomainDAO) FindEnabledDNSDomain(tx *dbs.Tx, domainId int64, cacheMap *utils.CacheMap) (*DNSDomain, error) {
|
||||
var cacheKey = this.Table + ":record:" + types.String(domainId)
|
||||
var cache = cacheMap.Get(cacheKey)
|
||||
if cache != nil {
|
||||
return cache.(*DNSDomain), nil
|
||||
if cacheMap != nil {
|
||||
cache, _ := cacheMap.Get(cacheKey)
|
||||
if cache != nil {
|
||||
return cache.(*DNSDomain), nil
|
||||
}
|
||||
}
|
||||
|
||||
result, err := this.Query(tx).
|
||||
@@ -75,7 +75,9 @@ func (this *DNSDomainDAO) FindEnabledDNSDomain(tx *dbs.Tx, domainId int64, cache
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
cacheMap[cacheKey] = result
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, result)
|
||||
}
|
||||
return result.(*DNSDomain), err
|
||||
}
|
||||
|
||||
@@ -214,7 +216,7 @@ func (this *DNSDomainDAO) FindDomainRouteName(tx *dbs.Tx, domainId int64, routeC
|
||||
// ExistAvailableDomains 判断是否有域名可选
|
||||
func (this *DNSDomainDAO) ExistAvailableDomains(tx *dbs.Tx) (bool, error) {
|
||||
subQuery, err := SharedDNSProviderDAO.Query(tx).
|
||||
Where("state=1"). // 这里要使用非变量
|
||||
Where("state=1"). // 这里要使用非变量
|
||||
ResultPk().
|
||||
AsSQL()
|
||||
if err != nil {
|
||||
@@ -263,7 +265,6 @@ func (this *DNSDomainDAO) ExistDomainRecord(tx *dbs.Tx, domainId int64, recordNa
|
||||
func (this *DNSDomainDAO) FindEnabledDomainWithName(tx *dbs.Tx, providerId int64, domainName string) (*DNSDomain, error) {
|
||||
one, err := this.Query(tx).
|
||||
State(DNSDomainStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Attr("providerId", providerId).
|
||||
Attr("name", domainName).
|
||||
Find()
|
||||
@@ -280,3 +281,11 @@ func (this *DNSDomainDAO) UpdateDomainIsUp(tx *dbs.Tx, domainId int64, isUp bool
|
||||
Set("isUp", isUp).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// UpdateDomainIsDeleted 设置域名为删除
|
||||
func (this *DNSDomainDAO) UpdateDomainIsDeleted(tx *dbs.Tx, domainId int64, isDeleted bool) error {
|
||||
return this.Query(tx).
|
||||
Pk(domainId).
|
||||
Set("isDeleted", isDeleted).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ type DNSDomain struct {
|
||||
Routes string `field:"routes"` // 线路数据
|
||||
IsUp uint8 `field:"isUp"` // 是否在线
|
||||
State uint8 `field:"state"` // 状态
|
||||
IsDeleted uint8 `field:"isDeleted"` // 是否已删除
|
||||
}
|
||||
|
||||
type DNSDomainOperator struct {
|
||||
@@ -33,6 +34,7 @@ type DNSDomainOperator struct {
|
||||
Routes interface{} // 线路数据
|
||||
IsUp interface{} // 是否在线
|
||||
State interface{} // 状态
|
||||
IsDeleted interface{} // 是否已删除
|
||||
}
|
||||
|
||||
func NewDNSDomainOperator() *DNSDomainOperator {
|
||||
|
||||
@@ -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, nodeconfigs.NodeRoleNode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,24 +1,29 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/configs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/zero"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"net"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -28,10 +33,53 @@ 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)
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedHTTPAccessLogDAO = NewHTTPAccessLogDAO()
|
||||
})
|
||||
|
||||
// 队列相关
|
||||
dbs.OnReadyDone(func() {
|
||||
// 检查队列变化
|
||||
goman.New(func() {
|
||||
var ticker = time.NewTicker(60 * time.Second)
|
||||
|
||||
// 先执行一次初始化
|
||||
SharedHTTPAccessLogDAO.SetupQueue()
|
||||
|
||||
// 循环执行
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
SharedHTTPAccessLogDAO.SetupQueue()
|
||||
case <-accessLogQueueChanged:
|
||||
SharedHTTPAccessLogDAO.SetupQueue()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 导出队列内容
|
||||
goman.New(func() {
|
||||
var ticker = time.NewTicker(1 * time.Second)
|
||||
for range ticker.C {
|
||||
var tx *dbs.Tx
|
||||
err := SharedHTTPAccessLogDAO.DumpAccessLogsFromQueue(tx, accessLogCountPerSecond)
|
||||
if err != nil {
|
||||
remotelogs.Error("HTTP_ACCESS_LOG_QUEUE", "dump access logs failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func NewHTTPAccessLogDAO() *HTTPAccessLogDAO {
|
||||
@@ -47,6 +95,31 @@ func NewHTTPAccessLogDAO() *HTTPAccessLogDAO {
|
||||
|
||||
// CreateHTTPAccessLogs 创建访问日志
|
||||
func (this *HTTPAccessLogDAO) CreateHTTPAccessLogs(tx *dbs.Tx, accessLogs []*pb.HTTPAccessLog) error {
|
||||
// 写入队列
|
||||
var queue = accessLogQueue // 这样写非常重要,防止在写入过程中队列有切换
|
||||
for _, accessLog := range accessLogs {
|
||||
if accessLog.FirewallPolicyId == 0 { // 如果是WAF记录,则采取采样率
|
||||
// 采样率
|
||||
if accessLogQueuePercent <= 0 {
|
||||
return nil
|
||||
}
|
||||
if accessLogQueuePercent < 100 && rands.Int(1, 100) > accessLogQueuePercent {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
case queue <- accessLog:
|
||||
default:
|
||||
// 超出的丢弃
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DumpAccessLogsFromQueue 从队列导入访问日志
|
||||
func (this *HTTPAccessLogDAO) DumpAccessLogsFromQueue(tx *dbs.Tx, size int) error {
|
||||
dao := randomHTTPAccessLogDAO()
|
||||
if dao == nil {
|
||||
dao = &HTTPAccessLogDAOWrapper{
|
||||
@@ -54,75 +127,102 @@ func (this *HTTPAccessLogDAO) CreateHTTPAccessLogs(tx *dbs.Tx, accessLogs []*pb.
|
||||
NodeId: 0,
|
||||
}
|
||||
}
|
||||
return this.CreateHTTPAccessLogsWithDAO(tx, dao, accessLogs)
|
||||
|
||||
if size <= 0 {
|
||||
size = 1_000_000
|
||||
}
|
||||
|
||||
// 复制变量,防止中途改变
|
||||
var oldQueue = oldAccessLogQueue
|
||||
var newQueue = accessLogQueue
|
||||
|
||||
Loop:
|
||||
for i := 0; i < size; i++ {
|
||||
// old
|
||||
select {
|
||||
case accessLog := <-oldQueue:
|
||||
err := this.CreateHTTPAccessLog(tx, dao.DAO, accessLog)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
continue Loop
|
||||
default:
|
||||
|
||||
}
|
||||
|
||||
// new
|
||||
select {
|
||||
case accessLog := <-newQueue:
|
||||
err := this.CreateHTTPAccessLog(tx, dao.DAO, accessLog)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
continue Loop
|
||||
default:
|
||||
break Loop
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateHTTPAccessLogsWithDAO 使用特定的DAO创建访问日志
|
||||
func (this *HTTPAccessLogDAO) CreateHTTPAccessLogsWithDAO(tx *dbs.Tx, daoWrapper *HTTPAccessLogDAOWrapper, accessLogs []*pb.HTTPAccessLog) error {
|
||||
if daoWrapper == nil {
|
||||
return errors.New("dao should not be nil")
|
||||
}
|
||||
if len(accessLogs) == 0 {
|
||||
return nil
|
||||
// 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)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dao := daoWrapper.DAO
|
||||
fields := map[string]interface{}{}
|
||||
fields["serverId"] = accessLog.ServerId
|
||||
fields["nodeId"] = accessLog.NodeId
|
||||
fields["status"] = accessLog.Status
|
||||
fields["createdAt"] = accessLog.Timestamp
|
||||
fields["requestId"] = accessLog.RequestId
|
||||
fields["firewallPolicyId"] = accessLog.FirewallPolicyId
|
||||
fields["firewallRuleGroupId"] = accessLog.FirewallRuleGroupId
|
||||
fields["firewallRuleSetId"] = accessLog.FirewallRuleSetId
|
||||
fields["firewallRuleId"] = accessLog.FirewallRuleId
|
||||
|
||||
// TODO 改成事务批量提交,以加快速度
|
||||
if len(accessLog.RequestBody) > 0 {
|
||||
fields["requestBody"] = accessLog.RequestBody
|
||||
accessLog.RequestBody = nil
|
||||
}
|
||||
|
||||
for _, accessLog := range accessLogs {
|
||||
day := timeutil.Format("Ymd", time.Unix(accessLog.Timestamp, 0))
|
||||
tableDef, err := findHTTPAccessLogTable(dao.Instance, day, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tableDef.HasRemoteAddr {
|
||||
fields["remoteAddr"] = accessLog.RemoteAddr
|
||||
}
|
||||
if tableDef.HasDomain {
|
||||
fields["domain"] = accessLog.Host
|
||||
}
|
||||
|
||||
fields := map[string]interface{}{}
|
||||
fields["serverId"] = accessLog.ServerId
|
||||
fields["nodeId"] = accessLog.NodeId
|
||||
fields["status"] = accessLog.Status
|
||||
fields["createdAt"] = accessLog.Timestamp
|
||||
fields["requestId"] = accessLog.RequestId + strconv.FormatInt(time.Now().UnixNano(), 10) + configs.PaddingId
|
||||
fields["firewallPolicyId"] = accessLog.FirewallPolicyId
|
||||
fields["firewallRuleGroupId"] = accessLog.FirewallRuleGroupId
|
||||
fields["firewallRuleSetId"] = accessLog.FirewallRuleSetId
|
||||
fields["firewallRuleId"] = accessLog.FirewallRuleId
|
||||
content, err := json.Marshal(accessLog)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fields["content"] = content
|
||||
|
||||
// TODO 根据集群、服务设置获取IP
|
||||
if tableDef.HasRemoteAddr {
|
||||
fields["remoteAddr"] = accessLog.RemoteAddr
|
||||
}
|
||||
if tableDef.HasDomain {
|
||||
fields["domain"] = accessLog.Host
|
||||
}
|
||||
|
||||
content, err := json.Marshal(accessLog)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fields["content"] = content
|
||||
|
||||
_, 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 err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = dao.Query(tx).
|
||||
Table(tableDef.Name).
|
||||
Sets(fields).
|
||||
Insert()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
logs.Println("HTTP_ACCESS_LOG", err.Error())
|
||||
_, 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 err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = dao.Query(tx).
|
||||
Table(tableDef.Name).
|
||||
Sets(fields).
|
||||
Insert()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
remotelogs.Error("HTTP_ACCESS_LOG", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,6 +233,8 @@ func (this *HTTPAccessLogDAO) CreateHTTPAccessLogsWithDAO(tx *dbs.Tx, daoWrapper
|
||||
func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx, lastRequestId string,
|
||||
size int64,
|
||||
day string,
|
||||
clusterId int64,
|
||||
nodeId int64,
|
||||
serverId int64,
|
||||
reverse bool,
|
||||
hasError bool,
|
||||
@@ -153,18 +255,18 @@ func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx, lastRequestId string,
|
||||
size = 1000
|
||||
}
|
||||
|
||||
result, nextLastRequestId, err = this.listAccessLogs(tx, lastRequestId, size, day, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
|
||||
result, nextLastRequestId, err = this.listAccessLogs(tx, lastRequestId, size, day, 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, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
|
||||
moreResult, _, _ := this.listAccessLogs(tx, nextLastRequestId, 1, day, 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, 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, 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) {
|
||||
if size <= 0 {
|
||||
return nil, lastRequestId, nil
|
||||
}
|
||||
@@ -206,18 +308,42 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
dao := daoWrapper.DAO
|
||||
|
||||
tableName, hasRemoteAddrField, hasDomainField, exists, err := findHTTPAccessLogTableName(dao.Instance, day)
|
||||
if !exists {
|
||||
// 表格不存在则跳过
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
logs.Println("[DB_NODE]" + err.Error())
|
||||
return
|
||||
}
|
||||
if !exists {
|
||||
// 表格不存在则跳过
|
||||
return
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
query.Where("nodeId IN (" + strings.Join(nodeIdStrings, ",") + ")")
|
||||
query.Reuse(false)
|
||||
} else {
|
||||
// 如果没有节点,则直接返回空
|
||||
return
|
||||
}
|
||||
}
|
||||
if serverId > 0 {
|
||||
query.Attr("serverId", serverId)
|
||||
} else if userId > 0 && len(serverIds) > 0 {
|
||||
@@ -332,6 +458,11 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
query.Param("intKeyword2", types.Int(pieces[1]))
|
||||
}
|
||||
|
||||
if regexp.MustCompile(`^\d{20,}\s*\.?$`).MatchString(keyword) {
|
||||
where += " OR requestId=:requestId"
|
||||
query.Param("requestId", strings.TrimRight(keyword, ". "))
|
||||
}
|
||||
|
||||
query.Where("("+where+")").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
if useOriginKeyword {
|
||||
@@ -407,7 +538,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
||||
|
||||
// FindAccessLogWithRequestId 根据请求ID获取访问日志
|
||||
func (this *HTTPAccessLogDAO) FindAccessLogWithRequestId(tx *dbs.Tx, requestId string) (*HTTPAccessLog, error) {
|
||||
if !regexp.MustCompile(`^\d{30,}`).MatchString(requestId) {
|
||||
if !regexp.MustCompile(`^\d{11,}`).MatchString(requestId) {
|
||||
return nil, errors.New("invalid requestId")
|
||||
}
|
||||
|
||||
@@ -461,3 +592,42 @@ func (this *HTTPAccessLogDAO) FindAccessLogWithRequestId(tx *dbs.Tx, requestId s
|
||||
wg.Wait()
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SetupQueue 建立队列
|
||||
func (this *HTTPAccessLogDAO) SetupQueue() {
|
||||
configJSON, err := SharedSysSettingDAO.ReadSetting(nil, systemconfigs.SettingCodeAccessLogQueue)
|
||||
if err != nil {
|
||||
remotelogs.Error("HTTP_ACCESS_LOG_QUEUE", "read settings failed: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if len(configJSON) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if bytes.Compare(accessLogConfigJSON, configJSON) == 0 {
|
||||
return
|
||||
}
|
||||
accessLogConfigJSON = configJSON
|
||||
|
||||
var config = &serverconfigs.AccessLogQueueConfig{}
|
||||
err = json.Unmarshal(configJSON, config)
|
||||
if err != nil {
|
||||
remotelogs.Error("HTTP_ACCESS_LOG_QUEUE", "decode settings failed: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
accessLogQueuePercent = config.Percent
|
||||
accessLogCountPerSecond = config.CountPerSecond
|
||||
if config.MaxLength <= 0 {
|
||||
config.MaxLength = 100_000
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
@@ -10,7 +10,9 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCreateHTTPAccessLogs(t *testing.T) {
|
||||
func TestCreateHTTPAccessLog(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
|
||||
err := NewDBNodeInitializer().loop()
|
||||
@@ -26,9 +28,19 @@ func TestCreateHTTPAccessLogs(t *testing.T) {
|
||||
}
|
||||
dao := randomHTTPAccessLogDAO()
|
||||
t.Log("dao:", dao)
|
||||
err = SharedHTTPAccessLogDAO.CreateHTTPAccessLogsWithDAO(tx, dao, []*pb.HTTPAccessLog{accessLog})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
// 先初始化
|
||||
_ = SharedHTTPAccessLogDAO.CreateHTTPAccessLog(tx, dao.DAO, accessLog)
|
||||
|
||||
var before = time.Now()
|
||||
defer func() {
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
}()
|
||||
for i := 0; i < 1000; i++ {
|
||||
err = SharedHTTPAccessLogDAO.CreateHTTPAccessLog(tx, dao.DAO, accessLog)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
@@ -41,7 +53,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "", 10, timeutil.Format("Ymd"), 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "", 10, timeutil.Format("Ymd"), 0, 0, 0, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -68,7 +80,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, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, 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)
|
||||
@@ -99,7 +111,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Reverse(t *testing.T) {
|
||||
}
|
||||
|
||||
before := time.Now()
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "16023261176446590001000000000000003500000004", 2, timeutil.Format("Ymd"), 0, true, false, 0, 0, 0, false, 0, "", "", "")
|
||||
accessLogs, requestId, hasMore, err := SharedHTTPAccessLogDAO.ListAccessLogs(tx, "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)
|
||||
@@ -124,7 +136,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, false, false, 0, 0, 0, false, 0, "", "", "")
|
||||
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, "", "", "")
|
||||
cost := time.Since(before).Seconds()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -13,5 +13,6 @@ func (this *HTTPAccessLog) ToPB() (*pb.HTTPAccessLog, error) {
|
||||
return nil, err
|
||||
}
|
||||
p.RequestId = this.RequestId
|
||||
p.RequestBody = []byte(this.RequestBody)
|
||||
return p, nil
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
@@ -96,12 +96,12 @@ func (this *HTTPAuthPolicyDAO) UpdateHTTPAuthPolicy(tx *dbs.Tx, policyId int64,
|
||||
}
|
||||
|
||||
// ComposePolicyConfig 组合配置
|
||||
func (this *HTTPAuthPolicyDAO) ComposePolicyConfig(tx *dbs.Tx, policyId int64, cacheMap maps.Map) (*serverconfigs.HTTPAuthPolicy, error) {
|
||||
func (this *HTTPAuthPolicyDAO) ComposePolicyConfig(tx *dbs.Tx, policyId int64, cacheMap *utils.CacheMap) (*serverconfigs.HTTPAuthPolicy, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = maps.Map{}
|
||||
cacheMap = utils.NewCacheMap()
|
||||
}
|
||||
var cacheKey = this.Table + ":config:" + types.String(policyId)
|
||||
var cache = cacheMap.Get(cacheKey)
|
||||
var cache, _ = cacheMap.Get(cacheKey)
|
||||
if cache != nil {
|
||||
return cache.(*serverconfigs.HTTPAuthPolicy), nil
|
||||
}
|
||||
@@ -130,7 +130,9 @@ func (this *HTTPAuthPolicyDAO) ComposePolicyConfig(tx *dbs.Tx, policyId int64, c
|
||||
}
|
||||
config.Params = params
|
||||
|
||||
cacheMap[cacheKey] = config
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, config)
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
@@ -225,12 +225,12 @@ func (this *HTTPCachePolicyDAO) UpdateCachePolicy(tx *dbs.Tx, policyId int64, is
|
||||
}
|
||||
|
||||
// ComposeCachePolicy 组合配置
|
||||
func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, cacheMap maps.Map) (*serverconfigs.HTTPCachePolicy, error) {
|
||||
func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, cacheMap *utils.CacheMap) (*serverconfigs.HTTPCachePolicy, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = maps.Map{}
|
||||
cacheMap = utils.NewCacheMap()
|
||||
}
|
||||
var cacheKey = this.Table + ":config:" + types.String(policyId)
|
||||
var cache = cacheMap.Get(cacheKey)
|
||||
var cache, _ = cacheMap.Get(cacheKey)
|
||||
if cache != nil {
|
||||
return cache.(*serverconfigs.HTTPCachePolicy), nil
|
||||
}
|
||||
@@ -292,15 +292,21 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
|
||||
config.CacheRefs = refs
|
||||
}
|
||||
|
||||
cacheMap[cacheKey] = config
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, config)
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// CountAllEnabledHTTPCachePolicies 计算可用缓存策略数量
|
||||
func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, keyword string) (int64, error) {
|
||||
func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, clusterId int64, keyword string) (int64, error) {
|
||||
query := this.Query(tx).
|
||||
State(HTTPCachePolicyStateEnabled)
|
||||
if clusterId > 0 {
|
||||
query.Where("id IN (SELECT cachePolicyId FROM " + SharedNodeClusterDAO.Table + " WHERE id=:clusterId)")
|
||||
query.Param("clusterId", clusterId)
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
@@ -309,9 +315,13 @@ func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, key
|
||||
}
|
||||
|
||||
// ListEnabledHTTPCachePolicies 列出单页的缓存策略
|
||||
func (this *HTTPCachePolicyDAO) ListEnabledHTTPCachePolicies(tx *dbs.Tx, keyword string, offset int64, size int64) ([]*serverconfigs.HTTPCachePolicy, error) {
|
||||
func (this *HTTPCachePolicyDAO) ListEnabledHTTPCachePolicies(tx *dbs.Tx, clusterId int64, keyword string, offset int64, size int64) ([]*serverconfigs.HTTPCachePolicy, error) {
|
||||
query := this.Query(tx).
|
||||
State(HTTPCachePolicyStateEnabled)
|
||||
if clusterId > 0 {
|
||||
query.Where("id IN (SELECT cachePolicyId FROM " + SharedNodeClusterDAO.Table + " WHERE id=:clusterId)")
|
||||
query.Param("clusterId", clusterId)
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
|
||||
@@ -3,6 +3,7 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
@@ -62,6 +63,11 @@ func (this *HTTPFirewallPolicyDAO) DisableHTTPFirewallPolicy(tx *dbs.Tx, policyI
|
||||
return err
|
||||
}
|
||||
|
||||
err = this.NotifyDisable(tx, policyId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, policyId)
|
||||
}
|
||||
|
||||
@@ -85,6 +91,19 @@ func (this *HTTPFirewallPolicyDAO) FindHTTPFirewallPolicyName(tx *dbs.Tx, id int
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// FindEnabledHTTPFirewallPolicyBasic 获取WAF策略基本信息
|
||||
func (this *HTTPFirewallPolicyDAO) FindEnabledHTTPFirewallPolicyBasic(tx *dbs.Tx, policyId int64) (*HTTPFirewallPolicy, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(policyId).
|
||||
Result("id", "name", "serverId", "isOn").
|
||||
Attr("state", HTTPFirewallPolicyStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*HTTPFirewallPolicy), err
|
||||
}
|
||||
|
||||
// FindAllEnabledFirewallPolicies 查找所有可用策略
|
||||
func (this *HTTPFirewallPolicyDAO) FindAllEnabledFirewallPolicies(tx *dbs.Tx) (result []*HTTPFirewallPolicy, err error) {
|
||||
_, err = this.Query(tx).
|
||||
@@ -111,6 +130,16 @@ 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 err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.SynFlood = synFloodJSON
|
||||
}
|
||||
|
||||
err := this.Save(tx, op)
|
||||
return types.Int64(op.Id), err
|
||||
}
|
||||
@@ -230,7 +259,7 @@ 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) error {
|
||||
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 {
|
||||
if policyId <= 0 {
|
||||
return errors.New("invalid policyId")
|
||||
}
|
||||
@@ -253,6 +282,18 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx, policyId int
|
||||
if len(blockOptionsJSON) > 0 {
|
||||
op.BlockOptions = blockOptionsJSON
|
||||
}
|
||||
|
||||
if synFloodConfig != nil {
|
||||
synFloodConfigJSON, err := json.Marshal(synFloodConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.SynFlood = synFloodConfigJSON
|
||||
} else {
|
||||
op.SynFlood = "null"
|
||||
}
|
||||
|
||||
op.UseLocalFirewall = useLocalFirewall
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -262,8 +303,12 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx, policyId int
|
||||
}
|
||||
|
||||
// CountAllEnabledFirewallPolicies 计算所有可用的策略数量
|
||||
func (this *HTTPFirewallPolicyDAO) CountAllEnabledFirewallPolicies(tx *dbs.Tx, keyword string) (int64, error) {
|
||||
func (this *HTTPFirewallPolicyDAO) CountAllEnabledFirewallPolicies(tx *dbs.Tx, clusterId int64, keyword string) (int64, error) {
|
||||
query := this.Query(tx)
|
||||
if clusterId > 0 {
|
||||
query.Where("id IN (SELECT httpFirewallPolicyId FROM " + SharedNodeClusterDAO.Table + " WHERE id=:clusterId)")
|
||||
query.Param("clusterId", clusterId)
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
@@ -277,8 +322,12 @@ func (this *HTTPFirewallPolicyDAO) CountAllEnabledFirewallPolicies(tx *dbs.Tx, k
|
||||
}
|
||||
|
||||
// ListEnabledFirewallPolicies 列出单页的策略
|
||||
func (this *HTTPFirewallPolicyDAO) ListEnabledFirewallPolicies(tx *dbs.Tx, keyword string, offset int64, size int64) (result []*HTTPFirewallPolicy, err error) {
|
||||
func (this *HTTPFirewallPolicyDAO) ListEnabledFirewallPolicies(tx *dbs.Tx, clusterId int64, keyword string, offset int64, size int64) (result []*HTTPFirewallPolicy, err error) {
|
||||
query := this.Query(tx)
|
||||
if clusterId > 0 {
|
||||
query.Where("id IN (SELECT httpFirewallPolicyId FROM " + SharedNodeClusterDAO.Table + " WHERE id=:clusterId)")
|
||||
query.Param("clusterId", clusterId)
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
@@ -297,12 +346,12 @@ func (this *HTTPFirewallPolicyDAO) ListEnabledFirewallPolicies(tx *dbs.Tx, keywo
|
||||
}
|
||||
|
||||
// ComposeFirewallPolicy 组合策略配置
|
||||
func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId int64, cacheMap maps.Map) (*firewallconfigs.HTTPFirewallPolicy, error) {
|
||||
func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId int64, cacheMap *utils.CacheMap) (*firewallconfigs.HTTPFirewallPolicy, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = maps.Map{}
|
||||
cacheMap = utils.NewCacheMap()
|
||||
}
|
||||
var cacheKey = this.Table + ":config:" + types.String(policyId)
|
||||
var cache = cacheMap.Get(cacheKey)
|
||||
var cache, _ = cacheMap.Get(cacheKey)
|
||||
if cache != nil {
|
||||
return cache.(*firewallconfigs.HTTPFirewallPolicy), nil
|
||||
}
|
||||
@@ -320,6 +369,7 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
|
||||
config.IsOn = policy.IsOn == 1
|
||||
config.Name = policy.Name
|
||||
config.Description = policy.Description
|
||||
config.UseLocalFirewall = policy.UseLocalFirewall == 1
|
||||
|
||||
if len(policy.Mode) == 0 {
|
||||
policy.Mode = firewallconfigs.FirewallModeDefend
|
||||
@@ -392,7 +442,19 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
|
||||
config.BlockOptions = blockAction
|
||||
}
|
||||
|
||||
cacheMap[cacheKey] = config
|
||||
// syn flood
|
||||
if len(policy.SynFlood) > 0 {
|
||||
var synFloodConfig = &firewallconfigs.SYNFloodConfig{}
|
||||
err = json.Unmarshal([]byte(policy.SynFlood), synFloodConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.SYNFlood = synFloodConfig
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, config)
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
@@ -447,6 +509,19 @@ func (this *HTTPFirewallPolicyDAO) FindEnabledFirewallPolicyIdsWithIPListId(tx *
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// FindEnabledFirewallPolicyWithIPListId 查找使用某个IPList的策略
|
||||
func (this *HTTPFirewallPolicyDAO) FindEnabledFirewallPolicyWithIPListId(tx *dbs.Tx, ipListId int64) (*HTTPFirewallPolicy, error) {
|
||||
one, err := this.Query(tx).
|
||||
State(HTTPFirewallPolicyStateEnabled).
|
||||
Where("(JSON_CONTAINS(inbound, :listQuery, '$.whiteListRef') OR JSON_CONTAINS(inbound, :listQuery, '$.blackListRef'))").
|
||||
Param("listQuery", maps.Map{"isOn": true, "listId": ipListId}.AsJSON()).
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
}
|
||||
return one.(*HTTPFirewallPolicy), err
|
||||
}
|
||||
|
||||
// FindEnabledFirewallPolicyIdWithRuleGroupId 查找包含某个规则分组的策略ID
|
||||
func (this *HTTPFirewallPolicyDAO) FindEnabledFirewallPolicyIdWithRuleGroupId(tx *dbs.Tx, ruleGroupId int64) (int64, error) {
|
||||
return this.Query(tx).
|
||||
@@ -466,6 +541,23 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicyServerId(tx *dbs.Tx, poli
|
||||
return err
|
||||
}
|
||||
|
||||
// FindFirewallPolicyIdsWithServerId 查找服务独立关联的策略IDs
|
||||
func (this *HTTPFirewallPolicyDAO) FindFirewallPolicyIdsWithServerId(tx *dbs.Tx, serverId int64) ([]int64, error) {
|
||||
var result = []int64{}
|
||||
ones, err := this.Query(tx).
|
||||
Attr("serverId", serverId).
|
||||
State(HTTPFirewallPolicyStateEnabled).
|
||||
Result("id").
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, one := range ones {
|
||||
result = append(result, int64(one.(*HTTPFirewallPolicy).Id))
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *HTTPFirewallPolicyDAO) NotifyUpdate(tx *dbs.Tx, policyId int64) error {
|
||||
webIds, err := SharedHTTPWebDAO.FindAllWebIdsWithHTTPFirewallPolicyId(tx, policyId)
|
||||
@@ -492,3 +584,65 @@ func (this *HTTPFirewallPolicyDAO) NotifyUpdate(tx *dbs.Tx, policyId int64) erro
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NotifyDisable 通知禁用
|
||||
func (this *HTTPFirewallPolicyDAO) NotifyDisable(tx *dbs.Tx, policyId int64) error {
|
||||
if policyId <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 禁用IP名单
|
||||
inboundString, err := this.Query(tx).
|
||||
Pk(policyId).
|
||||
Result("inbound").
|
||||
FindStringCol("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(inboundString) > 0 {
|
||||
var inboundConfig = &firewallconfigs.HTTPFirewallInboundConfig{}
|
||||
err = json.Unmarshal([]byte(inboundString), inboundConfig)
|
||||
if err != nil {
|
||||
// 不处理错误
|
||||
return nil
|
||||
}
|
||||
|
||||
if inboundConfig.AllowListRef != nil && inboundConfig.AllowListRef.ListId > 0 {
|
||||
err = SharedIPListDAO.DisableIPList(tx, inboundConfig.AllowListRef.ListId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = SharedIPItemDAO.DisableIPItemsWithListId(tx, inboundConfig.AllowListRef.ListId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if inboundConfig.DenyListRef != nil && inboundConfig.DenyListRef.ListId > 0 {
|
||||
err = SharedIPListDAO.DisableIPList(tx, inboundConfig.DenyListRef.ListId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = SharedIPItemDAO.DisableIPItemsWithListId(tx, inboundConfig.DenyListRef.ListId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if inboundConfig.GreyListRef != nil && inboundConfig.GreyListRef.ListId > 0 {
|
||||
err = SharedIPListDAO.DisableIPList(tx, inboundConfig.GreyListRef.ListId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = SharedIPItemDAO.DisableIPItemsWithListId(tx, inboundConfig.GreyListRef.ListId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,39 +2,43 @@ package models
|
||||
|
||||
// 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"` // 模式
|
||||
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防御设置
|
||||
}
|
||||
|
||||
type HTTPFirewallPolicyOperator struct {
|
||||
Id interface{} // ID
|
||||
TemplateId interface{} // 模版ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
ServerId interface{} // 服务ID
|
||||
GroupId interface{} // 服务分组ID
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
Description interface{} // 描述
|
||||
Inbound interface{} // 入站规则
|
||||
Outbound interface{} // 出站规则
|
||||
BlockOptions interface{} // BLOCK选项
|
||||
Mode interface{} // 模式
|
||||
Id interface{} // ID
|
||||
TemplateId interface{} // 模版ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
ServerId interface{} // 服务ID
|
||||
GroupId interface{} // 服务分组ID
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
Description interface{} // 描述
|
||||
Inbound interface{} // 入站规则
|
||||
Outbound interface{} // 出站规则
|
||||
BlockOptions interface{} // BLOCK选项
|
||||
Mode interface{} // 模式
|
||||
UseLocalFirewall interface{} // 是否自动使用本地防火墙
|
||||
SynFlood interface{} // SynFlood防御设置
|
||||
}
|
||||
|
||||
func NewHTTPFirewallPolicyOperator() *HTTPFirewallPolicyOperator {
|
||||
|
||||
@@ -95,6 +95,7 @@ func (this *HTTPFirewallRuleGroupDAO) ComposeFirewallRuleGroup(tx *dbs.Tx, group
|
||||
config.Name = group.Name
|
||||
config.Description = group.Description
|
||||
config.Code = group.Code
|
||||
config.IsTemplate = group.IsTemplate == 1
|
||||
|
||||
if IsNotNull(group.Sets) {
|
||||
setRefs := []*firewallconfigs.HTTPFirewallRuleSetRef{}
|
||||
@@ -125,6 +126,7 @@ func (this *HTTPFirewallRuleGroupDAO) CreateGroupFromConfig(tx *dbs.Tx, groupCon
|
||||
op.Description = groupConfig.Description
|
||||
op.State = HTTPFirewallRuleGroupStateEnabled
|
||||
op.Code = groupConfig.Code
|
||||
op.IsTemplate = groupConfig.IsTemplate
|
||||
|
||||
// sets
|
||||
setRefs := []*firewallconfigs.HTTPFirewallRuleSetRef{}
|
||||
@@ -178,7 +180,7 @@ func (this *HTTPFirewallRuleGroupDAO) CreateGroup(tx *dbs.Tx, isOn bool, name st
|
||||
}
|
||||
|
||||
// UpdateGroup 修改分组
|
||||
func (this *HTTPFirewallRuleGroupDAO) UpdateGroup(tx *dbs.Tx, groupId int64, isOn bool, name string, description string) error {
|
||||
func (this *HTTPFirewallRuleGroupDAO) UpdateGroup(tx *dbs.Tx, groupId int64, isOn bool, name string, code string, description string) error {
|
||||
if groupId <= 0 {
|
||||
return errors.New("invalid groupId")
|
||||
}
|
||||
@@ -186,6 +188,7 @@ func (this *HTTPFirewallRuleGroupDAO) UpdateGroup(tx *dbs.Tx, groupId int64, isO
|
||||
op.Id = groupId
|
||||
op.IsOn = isOn
|
||||
op.Name = name
|
||||
op.Code = code
|
||||
op.Description = description
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package models
|
||||
|
||||
// 防火墙规则分组
|
||||
// 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"` // 状态
|
||||
@@ -20,6 +21,7 @@ type HTTPFirewallRuleGroupOperator struct {
|
||||
Name interface{} // 名称
|
||||
Description interface{} // 描述
|
||||
Code interface{} // 代号
|
||||
IsTemplate interface{} // 是否为预置模板
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
State interface{} // 状态
|
||||
|
||||
@@ -99,6 +99,7 @@ func (this *HTTPFirewallRuleSetDAO) ComposeFirewallRuleSet(tx *dbs.Tx, setId int
|
||||
config.Description = set.Description
|
||||
config.Code = set.Code
|
||||
config.Connector = set.Connector
|
||||
config.IgnoreLocal = set.IgnoreLocal == 1
|
||||
|
||||
if IsNotNull(set.Rules) {
|
||||
ruleRefs := []*firewallconfigs.HTTPFirewallRuleRef{}
|
||||
@@ -139,6 +140,7 @@ func (this *HTTPFirewallRuleSetDAO) CreateOrUpdateSetFromConfig(tx *dbs.Tx, setC
|
||||
op.Name = setConfig.Name
|
||||
op.Description = setConfig.Description
|
||||
op.Connector = setConfig.Connector
|
||||
op.IgnoreLocal = setConfig.IgnoreLocal
|
||||
|
||||
if len(setConfig.Actions) == 0 {
|
||||
op.Actions = "[]"
|
||||
|
||||
@@ -16,6 +16,7 @@ type HTTPFirewallRuleSet struct {
|
||||
Action string `field:"action"` // 执行的动作(过期)
|
||||
ActionOptions string `field:"actionOptions"` // 动作的选项(过期)
|
||||
Actions string `field:"actions"` // 一组动作
|
||||
IgnoreLocal uint8 `field:"ignoreLocal"` // 忽略局域网请求
|
||||
}
|
||||
|
||||
type HTTPFirewallRuleSetOperator struct {
|
||||
@@ -33,6 +34,7 @@ type HTTPFirewallRuleSetOperator struct {
|
||||
Action interface{} // 执行的动作(过期)
|
||||
ActionOptions interface{} // 动作的选项(过期)
|
||||
Actions interface{} // 一组动作
|
||||
IgnoreLocal interface{} // 忽略局域网请求
|
||||
}
|
||||
|
||||
func NewHTTPFirewallRuleSetOperator() *HTTPFirewallRuleSetOperator {
|
||||
|
||||
@@ -2,7 +2,7 @@ package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
@@ -80,22 +80,69 @@ func (this *HTTPHeaderDAO) FindHTTPHeaderName(tx *dbs.Tx, id int64) (string, err
|
||||
}
|
||||
|
||||
// CreateHeader 创建Header
|
||||
func (this *HTTPHeaderDAO) CreateHeader(tx *dbs.Tx, name string, value string) (int64, error) {
|
||||
func (this *HTTPHeaderDAO) CreateHeader(tx *dbs.Tx, userId int64, name string, value string, status []int, disableRedirect bool, shouldAppend bool, shouldReplace bool, replaceValues []*shared.HTTPHeaderReplaceValue, methods []string, domains []string) (int64, error) {
|
||||
op := NewHTTPHeaderOperator()
|
||||
op.UserId = userId
|
||||
op.State = HTTPHeaderStateEnabled
|
||||
op.IsOn = true
|
||||
op.Name = name
|
||||
op.Value = value
|
||||
|
||||
statusConfig := &shared.HTTPStatusConfig{
|
||||
Always: true,
|
||||
// status
|
||||
var statusConfig *shared.HTTPStatusConfig
|
||||
if len(status) == 0 {
|
||||
statusConfig = &shared.HTTPStatusConfig{
|
||||
Always: true,
|
||||
}
|
||||
} else {
|
||||
statusConfig = &shared.HTTPStatusConfig{
|
||||
Always: false,
|
||||
Codes: status,
|
||||
}
|
||||
}
|
||||
|
||||
statusJSON, err := json.Marshal(statusConfig)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.Status = statusJSON
|
||||
|
||||
op.DisableRedirect = disableRedirect
|
||||
op.ShouldAppend = shouldAppend
|
||||
op.ShouldReplace = shouldReplace
|
||||
|
||||
if len(replaceValues) == 0 {
|
||||
op.ReplaceValues = "[]"
|
||||
} else {
|
||||
replaceValuesJSON, err := json.Marshal(replaceValues)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.ReplaceValues = replaceValuesJSON
|
||||
}
|
||||
|
||||
// methods
|
||||
if len(methods) == 0 {
|
||||
op.Methods = "[]"
|
||||
} else {
|
||||
methodsJSON, err := json.Marshal(methods)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.Methods = methodsJSON
|
||||
}
|
||||
|
||||
// domains
|
||||
if len(domains) == 0 {
|
||||
op.Domains = "[]"
|
||||
} else {
|
||||
domainsJSON, err := json.Marshal(domains)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.Domains = domainsJSON
|
||||
}
|
||||
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -104,7 +151,7 @@ func (this *HTTPHeaderDAO) CreateHeader(tx *dbs.Tx, name string, value string) (
|
||||
}
|
||||
|
||||
// UpdateHeader 修改Header
|
||||
func (this *HTTPHeaderDAO) UpdateHeader(tx *dbs.Tx, headerId int64, name string, value string) error {
|
||||
func (this *HTTPHeaderDAO) UpdateHeader(tx *dbs.Tx, headerId int64, name string, value string, status []int, disableRedirect bool, shouldAppend bool, shouldReplace bool, replaceValues []*shared.HTTPHeaderReplaceValue, methods []string, domains []string) error {
|
||||
if headerId <= 0 {
|
||||
return errors.New("invalid headerId")
|
||||
}
|
||||
@@ -113,7 +160,63 @@ func (this *HTTPHeaderDAO) UpdateHeader(tx *dbs.Tx, headerId int64, name string,
|
||||
op.Id = headerId
|
||||
op.Name = name
|
||||
op.Value = value
|
||||
err := this.Save(tx, op)
|
||||
|
||||
// status
|
||||
var statusConfig *shared.HTTPStatusConfig
|
||||
if len(status) == 0 {
|
||||
statusConfig = &shared.HTTPStatusConfig{
|
||||
Always: true,
|
||||
}
|
||||
} else {
|
||||
statusConfig = &shared.HTTPStatusConfig{
|
||||
Always: false,
|
||||
Codes: status,
|
||||
}
|
||||
}
|
||||
|
||||
statusJSON, err := json.Marshal(statusConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.Status = statusJSON
|
||||
|
||||
op.DisableRedirect = disableRedirect
|
||||
op.ShouldAppend = shouldAppend
|
||||
op.ShouldReplace = shouldReplace
|
||||
|
||||
if len(replaceValues) == 0 {
|
||||
op.ReplaceValues = "[]"
|
||||
} else {
|
||||
replaceValuesJSON, err := json.Marshal(replaceValues)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.ReplaceValues = replaceValuesJSON
|
||||
}
|
||||
|
||||
// methods
|
||||
if len(methods) == 0 {
|
||||
op.Methods = "[]"
|
||||
} else {
|
||||
methodsJSON, err := json.Marshal(methods)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.Methods = methodsJSON
|
||||
}
|
||||
|
||||
// domains
|
||||
if len(domains) == 0 {
|
||||
op.Domains = "[]"
|
||||
} else {
|
||||
domainsJSON, err := json.Marshal(domains)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.Domains = domainsJSON
|
||||
}
|
||||
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -136,7 +239,21 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
|
||||
config.IsOn = header.IsOn == 1
|
||||
config.Name = header.Name
|
||||
config.Value = header.Value
|
||||
config.DisableRedirect = header.DisableRedirect == 1
|
||||
config.ShouldAppend = header.ShouldAppend == 1
|
||||
|
||||
// replace
|
||||
config.ShouldReplace = header.ShouldReplace == 1
|
||||
if len(header.ReplaceValues) > 0 {
|
||||
var values = []*shared.HTTPHeaderReplaceValue{}
|
||||
err = json.Unmarshal([]byte(header.ReplaceValues), &values)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.ReplaceValues = values
|
||||
}
|
||||
|
||||
// status
|
||||
if len(header.Status) > 0 {
|
||||
status := &shared.HTTPStatusConfig{}
|
||||
err = json.Unmarshal([]byte(header.Status), status)
|
||||
@@ -146,6 +263,26 @@ func (this *HTTPHeaderDAO) ComposeHeaderConfig(tx *dbs.Tx, headerId int64) (*sha
|
||||
config.Status = status
|
||||
}
|
||||
|
||||
// methods
|
||||
if len(header.Methods) > 0 {
|
||||
var methods = []string{}
|
||||
err = json.Unmarshal([]byte(header.Methods), &methods)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.Methods = methods
|
||||
}
|
||||
|
||||
// domains
|
||||
if len(header.Domains) > 0 {
|
||||
var domains = []string{}
|
||||
err = json.Unmarshal([]byte(header.Domains), &domains)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.Domains = domains
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,32 +1,44 @@
|
||||
package models
|
||||
|
||||
// HTTP Header
|
||||
// HTTPHeader HTTP Header
|
||||
type HTTPHeader 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"` // 名称
|
||||
Value string `field:"value"` // 值
|
||||
Order uint32 `field:"order"` // 排序
|
||||
Status string `field:"status"` // 状态码设置
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
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"` // 名称
|
||||
Value string `field:"value"` // 值
|
||||
Order uint32 `field:"order"` // 排序
|
||||
Status string `field:"status"` // 状态码设置
|
||||
DisableRedirect uint8 `field:"disableRedirect"` // 是否不支持跳转
|
||||
ShouldAppend uint8 `field:"shouldAppend"` // 是否为附加
|
||||
ShouldReplace uint8 `field:"shouldReplace"` // 是否替换变量
|
||||
ReplaceValues string `field:"replaceValues"` // 替换的值
|
||||
Methods string `field:"methods"` // 支持的方法
|
||||
Domains string `field:"domains"` // 支持的域名
|
||||
State uint8 `field:"state"` // 状态
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
}
|
||||
|
||||
type HTTPHeaderOperator struct {
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
TemplateId interface{} // 模版ID
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
Value interface{} // 值
|
||||
Order interface{} // 排序
|
||||
Status interface{} // 状态码设置
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
TemplateId interface{} // 模版ID
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
Value interface{} // 值
|
||||
Order interface{} // 排序
|
||||
Status interface{} // 状态码设置
|
||||
DisableRedirect interface{} // 是否不支持跳转
|
||||
ShouldAppend interface{} // 是否为附加
|
||||
ShouldReplace interface{} // 是否替换变量
|
||||
ReplaceValues interface{} // 替换的值
|
||||
Methods interface{} // 支持的方法
|
||||
Domains interface{} // 支持的域名
|
||||
State interface{} // 状态
|
||||
CreatedAt interface{} // 创建时间
|
||||
}
|
||||
|
||||
func NewHTTPHeaderOperator() *HTTPHeaderOperator {
|
||||
|
||||
@@ -186,48 +186,6 @@ func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(tx *dbs.Tx, headerPol
|
||||
config.Id = int64(policy.Id)
|
||||
config.IsOn = policy.IsOn == 1
|
||||
|
||||
// AddHeaders
|
||||
if len(policy.AddHeaders) > 0 {
|
||||
refs := []*shared.HTTPHeaderRef{}
|
||||
err = json.Unmarshal([]byte(policy.AddHeaders), &refs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(refs) > 0 {
|
||||
for _, ref := range refs {
|
||||
headerConfig, err := SharedHTTPHeaderDAO.ComposeHeaderConfig(tx, ref.HeaderId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.AddHeaders = append(config.AddHeaders, headerConfig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AddTrailers
|
||||
if len(policy.AddTrailers) > 0 {
|
||||
refs := []*shared.HTTPHeaderRef{}
|
||||
err = json.Unmarshal([]byte(policy.AddTrailers), &refs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(refs) > 0 {
|
||||
resultRefs := []*shared.HTTPHeaderRef{}
|
||||
for _, ref := range refs {
|
||||
headerConfig, err := SharedHTTPHeaderDAO.ComposeHeaderConfig(tx, ref.HeaderId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if headerConfig == nil {
|
||||
continue
|
||||
}
|
||||
resultRefs = append(resultRefs, ref)
|
||||
config.AddTrailers = append(config.AddTrailers, headerConfig)
|
||||
}
|
||||
config.AddHeaderRefs = resultRefs
|
||||
}
|
||||
}
|
||||
|
||||
// SetHeaders
|
||||
if len(policy.SetHeaders) > 0 {
|
||||
refs := []*shared.HTTPHeaderRef{}
|
||||
@@ -252,30 +210,6 @@ func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(tx *dbs.Tx, headerPol
|
||||
}
|
||||
}
|
||||
|
||||
// ReplaceHeaders
|
||||
if len(policy.ReplaceHeaders) > 0 {
|
||||
refs := []*shared.HTTPHeaderRef{}
|
||||
err = json.Unmarshal([]byte(policy.ReplaceHeaders), &refs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(refs) > 0 {
|
||||
resultRefs := []*shared.HTTPHeaderRef{}
|
||||
for _, ref := range refs {
|
||||
headerConfig, err := SharedHTTPHeaderDAO.ComposeHeaderConfig(tx, ref.HeaderId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if headerConfig == nil {
|
||||
continue
|
||||
}
|
||||
resultRefs = append(resultRefs, ref)
|
||||
config.ReplaceHeaders = append(config.ReplaceHeaders, headerConfig)
|
||||
}
|
||||
config.ReplaceHeaderRefs = resultRefs
|
||||
}
|
||||
}
|
||||
|
||||
// Delete Headers
|
||||
if len(policy.DeleteHeaders) > 0 {
|
||||
headers := []string{}
|
||||
|
||||
@@ -3,6 +3,7 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@@ -85,7 +86,7 @@ func (this *HTTPLocationDAO) FindHTTPLocationName(tx *dbs.Tx, id int64) (string,
|
||||
}
|
||||
|
||||
// CreateLocation 创建路由规则
|
||||
func (this *HTTPLocationDAO) CreateLocation(tx *dbs.Tx, parentId int64, name string, pattern string, description string, isBreak bool, condsJSON []byte) (int64, error) {
|
||||
func (this *HTTPLocationDAO) CreateLocation(tx *dbs.Tx, parentId int64, name string, pattern string, description string, isBreak bool, condsJSON []byte, domains []string) (int64, error) {
|
||||
op := NewHTTPLocationOperator()
|
||||
op.IsOn = true
|
||||
op.State = HTTPLocationStateEnabled
|
||||
@@ -99,7 +100,16 @@ func (this *HTTPLocationDAO) CreateLocation(tx *dbs.Tx, parentId int64, name str
|
||||
op.Conds = condsJSON
|
||||
}
|
||||
|
||||
err := this.Save(tx, op)
|
||||
if domains == nil {
|
||||
domains = []string{}
|
||||
}
|
||||
domainsJSON, err := json.Marshal(domains)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.Domains = domainsJSON
|
||||
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -107,7 +117,7 @@ func (this *HTTPLocationDAO) CreateLocation(tx *dbs.Tx, parentId int64, name str
|
||||
}
|
||||
|
||||
// UpdateLocation 修改路由规则
|
||||
func (this *HTTPLocationDAO) UpdateLocation(tx *dbs.Tx, locationId int64, name string, pattern string, description string, isOn bool, isBreak bool, condsJSON []byte) error {
|
||||
func (this *HTTPLocationDAO) UpdateLocation(tx *dbs.Tx, locationId int64, name string, pattern string, description string, isOn bool, isBreak bool, condsJSON []byte, domains []string) error {
|
||||
if locationId <= 0 {
|
||||
return errors.New("invalid locationId")
|
||||
}
|
||||
@@ -123,7 +133,16 @@ func (this *HTTPLocationDAO) UpdateLocation(tx *dbs.Tx, locationId int64, name s
|
||||
op.Conds = condsJSON
|
||||
}
|
||||
|
||||
err := this.Save(tx, op)
|
||||
if domains == nil {
|
||||
domains = []string{}
|
||||
}
|
||||
domainsJSON, err := json.Marshal(domains)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.Domains = domainsJSON
|
||||
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -131,12 +150,12 @@ func (this *HTTPLocationDAO) UpdateLocation(tx *dbs.Tx, locationId int64, name s
|
||||
}
|
||||
|
||||
// ComposeLocationConfig 组合配置
|
||||
func (this *HTTPLocationDAO) ComposeLocationConfig(tx *dbs.Tx, locationId int64, cacheMap maps.Map) (*serverconfigs.HTTPLocationConfig, error) {
|
||||
func (this *HTTPLocationDAO) ComposeLocationConfig(tx *dbs.Tx, locationId int64, cacheMap *utils.CacheMap) (*serverconfigs.HTTPLocationConfig, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = maps.Map{}
|
||||
cacheMap = utils.NewCacheMap()
|
||||
}
|
||||
var cacheKey = this.Table + ":config:" + types.String(locationId)
|
||||
var cacheConfig = cacheMap.Get(cacheKey)
|
||||
var cacheConfig, _ = cacheMap.Get(cacheKey)
|
||||
if cacheConfig != nil {
|
||||
return cacheConfig.(*serverconfigs.HTTPLocationConfig), nil
|
||||
}
|
||||
@@ -194,7 +213,21 @@ func (this *HTTPLocationDAO) ComposeLocationConfig(tx *dbs.Tx, locationId int64,
|
||||
config.Conds = conds
|
||||
}
|
||||
|
||||
cacheMap[cacheKey] = config
|
||||
// domains
|
||||
if len(location.Domains) > 0 {
|
||||
var domains = []string{}
|
||||
err = json.Unmarshal([]byte(location.Domains), &domains)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(domains) > 0 {
|
||||
config.Domains = domains
|
||||
}
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, config)
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
@@ -259,7 +292,7 @@ func (this *HTTPLocationDAO) UpdateLocationWeb(tx *dbs.Tx, locationId int64, web
|
||||
}
|
||||
|
||||
// ConvertLocationRefs 转换引用为配置
|
||||
func (this *HTTPLocationDAO) ConvertLocationRefs(tx *dbs.Tx, refs []*serverconfigs.HTTPLocationRef, cacheMap maps.Map) (locations []*serverconfigs.HTTPLocationConfig, err error) {
|
||||
func (this *HTTPLocationDAO) ConvertLocationRefs(tx *dbs.Tx, refs []*serverconfigs.HTTPLocationRef, cacheMap *utils.CacheMap) (locations []*serverconfigs.HTTPLocationConfig, err error) {
|
||||
for _, ref := range refs {
|
||||
config, err := this.ComposeLocationConfig(tx, ref.LocationId, cacheMap)
|
||||
if err != nil {
|
||||
|
||||
@@ -18,6 +18,7 @@ type HTTPLocation struct {
|
||||
UrlPrefix string `field:"urlPrefix"` // URL前缀
|
||||
IsBreak uint8 `field:"isBreak"` // 是否终止匹配
|
||||
Conds string `field:"conds"` // 匹配条件
|
||||
Domains string `field:"domains"` // 专属域名
|
||||
}
|
||||
|
||||
type HTTPLocationOperator struct {
|
||||
@@ -37,6 +38,7 @@ type HTTPLocationOperator struct {
|
||||
UrlPrefix interface{} // URL前缀
|
||||
IsBreak interface{} // 是否终止匹配
|
||||
Conds interface{} // 匹配条件
|
||||
Domains interface{} // 专属域名
|
||||
}
|
||||
|
||||
func NewHTTPLocationOperator() *HTTPLocationOperator {
|
||||
|
||||
@@ -3,12 +3,12 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
@@ -133,12 +133,12 @@ func (this *HTTPPageDAO) UpdatePage(tx *dbs.Tx, pageId int64, statusList []strin
|
||||
}
|
||||
|
||||
// ComposePageConfig 组合配置
|
||||
func (this *HTTPPageDAO) ComposePageConfig(tx *dbs.Tx, pageId int64, cacheMap maps.Map) (*serverconfigs.HTTPPageConfig, error) {
|
||||
func (this *HTTPPageDAO) ComposePageConfig(tx *dbs.Tx, pageId int64, cacheMap *utils.CacheMap) (*serverconfigs.HTTPPageConfig, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = maps.Map{}
|
||||
cacheMap = utils.NewCacheMap()
|
||||
}
|
||||
var cacheKey = this.Table + ":config:" + types.String(pageId)
|
||||
var cache = cacheMap.Get(cacheKey)
|
||||
var cache, _ = cacheMap.Get(cacheKey)
|
||||
if cache != nil {
|
||||
return cache.(*serverconfigs.HTTPPageConfig), nil
|
||||
}
|
||||
@@ -175,7 +175,9 @@ func (this *HTTPPageDAO) ComposePageConfig(tx *dbs.Tx, pageId int64, cacheMap ma
|
||||
}
|
||||
}
|
||||
|
||||
cacheMap[cacheKey] = config
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, config)
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
@@ -77,12 +77,12 @@ func (this *HTTPRewriteRuleDAO) FindEnabledHTTPRewriteRule(tx *dbs.Tx, id int64)
|
||||
}
|
||||
|
||||
// ComposeRewriteRule 构造配置
|
||||
func (this *HTTPRewriteRuleDAO) ComposeRewriteRule(tx *dbs.Tx, rewriteRuleId int64, cacheMap maps.Map) (*serverconfigs.HTTPRewriteRule, error) {
|
||||
func (this *HTTPRewriteRuleDAO) ComposeRewriteRule(tx *dbs.Tx, rewriteRuleId int64, cacheMap *utils.CacheMap) (*serverconfigs.HTTPRewriteRule, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = maps.Map{}
|
||||
cacheMap = utils.NewCacheMap()
|
||||
}
|
||||
var cacheKey = this.Table + ":config:" + types.String(rewriteRuleId)
|
||||
var cache = cacheMap.Get(cacheKey)
|
||||
var cache, _ = cacheMap.Get(cacheKey)
|
||||
if cache != nil {
|
||||
return cache.(*serverconfigs.HTTPRewriteRule), nil
|
||||
}
|
||||
@@ -116,7 +116,9 @@ func (this *HTTPRewriteRuleDAO) ComposeRewriteRule(tx *dbs.Tx, rewriteRuleId int
|
||||
config.Conds = conds
|
||||
}
|
||||
|
||||
cacheMap[cacheKey] = config
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, config)
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
@@ -75,12 +76,12 @@ func (this *HTTPWebDAO) FindEnabledHTTPWeb(tx *dbs.Tx, id int64) (*HTTPWeb, erro
|
||||
}
|
||||
|
||||
// ComposeWebConfig 组合配置
|
||||
func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap maps.Map) (*serverconfigs.HTTPWebConfig, error) {
|
||||
func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *utils.CacheMap) (*serverconfigs.HTTPWebConfig, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = maps.Map{}
|
||||
cacheMap = utils.NewCacheMap()
|
||||
}
|
||||
var cacheKey = this.Table + ":config:" + types.String(webId)
|
||||
var cache = cacheMap.Get(cacheKey)
|
||||
var cache, _ = cacheMap.Get(cacheKey)
|
||||
if cache != nil {
|
||||
return cache.(*serverconfigs.HTTPWebConfig), nil
|
||||
}
|
||||
@@ -418,7 +419,36 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap maps.
|
||||
config.RemoteAddr = remoteAddrConfig
|
||||
}
|
||||
|
||||
cacheMap[cacheKey] = config
|
||||
// mergeSlashes
|
||||
config.MergeSlashes = web.MergeSlashes == 1
|
||||
|
||||
// 请求限制
|
||||
if len(web.RequestLimit) > 0 {
|
||||
var requestLimitConfig = &serverconfigs.HTTPRequestLimitConfig{}
|
||||
if len(web.RequestLimit) > 0 {
|
||||
err = json.Unmarshal([]byte(web.RequestLimit), requestLimitConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.RequestLimit = requestLimitConfig
|
||||
}
|
||||
}
|
||||
|
||||
// 请求脚本
|
||||
if len(web.RequestScripts) > 0 {
|
||||
var requestScriptsConfig = &serverconfigs.HTTPRequestScriptsConfig{}
|
||||
if len(web.RequestScripts) > 0 {
|
||||
err = json.Unmarshal([]byte(web.RequestScripts), requestScriptsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.RequestScripts = requestScriptsConfig
|
||||
}
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, config)
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
@@ -1034,6 +1064,8 @@ func (this *HTTPWebDAO) UpdateWebHostRedirects(tx *dbs.Tx, webId int64, hostRedi
|
||||
return this.NotifyUpdate(tx, webId)
|
||||
}
|
||||
|
||||
// 通用设置
|
||||
|
||||
// FindWebHostRedirects 查找主机跳转
|
||||
func (this *HTTPWebDAO) FindWebHostRedirects(tx *dbs.Tx, webId int64) ([]byte, error) {
|
||||
col, err := this.Query(tx).
|
||||
@@ -1046,6 +1078,96 @@ func (this *HTTPWebDAO) FindWebHostRedirects(tx *dbs.Tx, webId int64) ([]byte, e
|
||||
return []byte(col), nil
|
||||
}
|
||||
|
||||
// UpdateWebCommon 修改通用设置
|
||||
func (this *HTTPWebDAO) UpdateWebCommon(tx *dbs.Tx, webId int64, mergeSlashes bool) error {
|
||||
if webId <= 0 {
|
||||
return errors.New("invalid webId")
|
||||
}
|
||||
var op = NewHTTPWebOperator()
|
||||
op.Id = webId
|
||||
op.MergeSlashes = mergeSlashes
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, webId)
|
||||
}
|
||||
|
||||
// UpdateWebRequestLimit 修改服务的请求限制
|
||||
func (this *HTTPWebDAO) UpdateWebRequestLimit(tx *dbs.Tx, webId int64, config *serverconfigs.HTTPRequestLimitConfig) error {
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = this.Query(tx).
|
||||
Pk(webId).
|
||||
Set("requestLimit", configJSON).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, webId)
|
||||
}
|
||||
|
||||
// FindWebRequestLimit 获取服务的请求限制
|
||||
func (this *HTTPWebDAO) FindWebRequestLimit(tx *dbs.Tx, webId int64) (*serverconfigs.HTTPRequestLimitConfig, error) {
|
||||
configString, err := this.Query(tx).
|
||||
Pk(webId).
|
||||
Result("requestLimit").
|
||||
FindStringCol("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var config = &serverconfigs.HTTPRequestLimitConfig{}
|
||||
if len(configString) == 0 {
|
||||
return config, nil
|
||||
}
|
||||
err = json.Unmarshal([]byte(configString), config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// UpdateWebRequestScripts 修改服务的请求脚本设置
|
||||
func (this *HTTPWebDAO) UpdateWebRequestScripts(tx *dbs.Tx, webId int64, config *serverconfigs.HTTPRequestScriptsConfig) error {
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = this.Query(tx).
|
||||
Pk(webId).
|
||||
Set("requestScripts", configJSON).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, webId)
|
||||
}
|
||||
|
||||
// FindWebRequestScripts 查找服务的脚本设置
|
||||
func (this *HTTPWebDAO) FindWebRequestScripts(tx *dbs.Tx, webId int64) (*serverconfigs.HTTPRequestScriptsConfig, error) {
|
||||
configString, err := this.Query(tx).
|
||||
Pk(webId).
|
||||
Result("requestScripts").
|
||||
FindStringCol("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var config = &serverconfigs.HTTPRequestScriptsConfig{}
|
||||
if len(configString) == 0 {
|
||||
return config, nil
|
||||
}
|
||||
err = json.Unmarshal([]byte(configString), config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *HTTPWebDAO) NotifyUpdate(tx *dbs.Tx, webId int64) error {
|
||||
// server
|
||||
|
||||
@@ -32,6 +32,9 @@ type HTTPWeb struct {
|
||||
Auth string `field:"auth"` // 认证策略配置
|
||||
Webp string `field:"webp"` // WebP配置
|
||||
RemoteAddr string `field:"remoteAddr"` // 客户端IP配置
|
||||
MergeSlashes uint8 `field:"mergeSlashes"` // 是否合并路径中的斜杠
|
||||
RequestLimit string `field:"requestLimit"` // 请求限制
|
||||
RequestScripts string `field:"requestScripts"` // 请求脚本
|
||||
}
|
||||
|
||||
type HTTPWebOperator struct {
|
||||
@@ -65,6 +68,9 @@ type HTTPWebOperator struct {
|
||||
Auth interface{} // 认证策略配置
|
||||
Webp interface{} // WebP配置
|
||||
RemoteAddr interface{} // 客户端IP配置
|
||||
MergeSlashes interface{} // 是否合并路径中的斜杠
|
||||
RequestLimit interface{} // 请求限制
|
||||
RequestScripts interface{} // 请求脚本
|
||||
}
|
||||
|
||||
func NewHTTPWebOperator() *HTTPWebOperator {
|
||||
|
||||
@@ -2,8 +2,11 @@ package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -18,6 +21,20 @@ const (
|
||||
IPItemStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
goman.New(func() {
|
||||
var ticker = time.NewTicker(1 * time.Minute)
|
||||
for range ticker.C {
|
||||
err := SharedIPItemDAO.CleanExpiredIPItems(nil)
|
||||
if err != nil {
|
||||
remotelogs.Error("IPItemDAO", "clean expired ip items failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
type IPItemType = string
|
||||
|
||||
const (
|
||||
@@ -75,6 +92,41 @@ func (this *IPItemDAO) DisableIPItem(tx *dbs.Tx, id int64) error {
|
||||
return this.NotifyUpdate(tx, id)
|
||||
}
|
||||
|
||||
// DisableIPItemsWithListId 禁用某个IP名单内的所有IP
|
||||
func (this *IPItemDAO) DisableIPItemsWithListId(tx *dbs.Tx, listId int64) error {
|
||||
for {
|
||||
ones, err := this.Query(tx).
|
||||
ResultPk().
|
||||
Attr("listId", listId).
|
||||
State(IPItemStateEnabled).
|
||||
Limit(1000).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(ones) == 0 {
|
||||
break
|
||||
}
|
||||
for _, one := range ones {
|
||||
var itemId = one.(*IPItem).Id
|
||||
version, err := SharedIPListDAO.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = this.Query(tx).
|
||||
Pk(itemId).
|
||||
State(IPItemStateEnabled).
|
||||
Set("version", version).
|
||||
Set("state", IPItemStateDisabled).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindEnabledIPItem 查找启用中的条目
|
||||
func (this *IPItemDAO) FindEnabledIPItem(tx *dbs.Tx, id int64) (*IPItem, error) {
|
||||
result, err := this.Query(tx).
|
||||
@@ -87,24 +139,40 @@ func (this *IPItemDAO) FindEnabledIPItem(tx *dbs.Tx, id int64) (*IPItem, error)
|
||||
return result.(*IPItem), err
|
||||
}
|
||||
|
||||
// DisableOldIPItem 根据IP删除以前的旧记录
|
||||
func (this *IPItemDAO) DisableOldIPItem(tx *dbs.Tx, listId int64, ipFrom string, ipTo string) error {
|
||||
return this.Query(tx).
|
||||
// DeleteOldItem 根据IP删除以前的旧记录
|
||||
func (this *IPItemDAO) DeleteOldItem(tx *dbs.Tx, listId int64, ipFrom string, ipTo string) error {
|
||||
_, err := this.Query(tx).
|
||||
UseIndex("ipFrom").
|
||||
Attr("listId", listId).
|
||||
Attr("ipFrom", ipFrom).
|
||||
Attr("ipTo", ipTo).
|
||||
Set("state", IPItemStateDisabled).
|
||||
UpdateQuickly()
|
||||
Delete()
|
||||
// 这里不通知更新
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateIPItem 创建IP
|
||||
func (this *IPItemDAO) CreateIPItem(tx *dbs.Tx, listId int64, ipFrom string, ipTo string, expiredAt int64, reason string, itemType IPItemType, eventLevel string) (int64, error) {
|
||||
func (this *IPItemDAO) CreateIPItem(tx *dbs.Tx,
|
||||
listId int64,
|
||||
ipFrom string,
|
||||
ipTo string,
|
||||
expiredAt int64,
|
||||
reason string,
|
||||
itemType IPItemType,
|
||||
eventLevel string,
|
||||
nodeId int64,
|
||||
serverId int64,
|
||||
sourceNodeId int64,
|
||||
sourceServerId int64,
|
||||
sourceHTTPFirewallPolicyId int64,
|
||||
sourceHTTPFirewallRuleGroupId int64,
|
||||
sourceHTTPFirewallRuleSetId int64) (int64, error) {
|
||||
version, err := SharedIPListDAO.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
op := NewIPItemOperator()
|
||||
var op = NewIPItemOperator()
|
||||
op.ListId = listId
|
||||
op.IpFrom = ipFrom
|
||||
op.IpTo = ipTo
|
||||
@@ -118,6 +186,20 @@ func (this *IPItemDAO) CreateIPItem(tx *dbs.Tx, listId int64, ipFrom string, ipT
|
||||
expiredAt = 0
|
||||
}
|
||||
op.ExpiredAt = expiredAt
|
||||
|
||||
op.NodeId = nodeId
|
||||
op.ServerId = serverId
|
||||
op.SourceNodeId = sourceNodeId
|
||||
op.SourceServerId = sourceServerId
|
||||
op.SourceHTTPFirewallPolicyId = sourceHTTPFirewallPolicyId
|
||||
op.SourceHTTPFirewallRuleGroupId = sourceHTTPFirewallRuleGroupId
|
||||
op.SourceHTTPFirewallRuleSetId = sourceHTTPFirewallRuleSetId
|
||||
|
||||
var autoAdded = listId == firewallconfigs.GlobalListId || sourceNodeId > 0 || sourceServerId > 0 || sourceHTTPFirewallPolicyId > 0
|
||||
if autoAdded {
|
||||
op.IsRead = 0
|
||||
}
|
||||
|
||||
op.State = IPItemStateEnabled
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
@@ -125,6 +207,11 @@ func (this *IPItemDAO) CreateIPItem(tx *dbs.Tx, listId int64, ipFrom string, ipT
|
||||
}
|
||||
itemId := types.Int64(op.Id)
|
||||
|
||||
// 自动加入名单不需要即时更新,防止数量过多而导致性能问题
|
||||
if autoAdded {
|
||||
return itemId, nil
|
||||
}
|
||||
|
||||
err = this.NotifyUpdate(tx, itemId)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -223,9 +310,8 @@ func (this *IPItemDAO) ListIPItemsAfterVersion(tx *dbs.Tx, version int64, size i
|
||||
_, err = this.Query(tx).
|
||||
// 这里不要设置状态参数,因为我们要知道哪些是删除的
|
||||
Gt("version", version).
|
||||
Where("(expiredAt=0 OR expiredAt>:expiredAt)").
|
||||
Param("expiredAt", time.Now().Unix()).
|
||||
Asc("version").
|
||||
Asc("id").
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
@@ -264,6 +350,7 @@ func (this *IPItemDAO) FindEnabledItemContainsIP(tx *dbs.Tx, listId int64, ip ui
|
||||
// FindEnabledItemsWithIP 根据IP查找Item
|
||||
func (this *IPItemDAO) FindEnabledItemsWithIP(tx *dbs.Tx, ip string) (result []*IPItem, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(IPItemStateEnabled).
|
||||
Attr("ipFrom", ip).
|
||||
Attr("ipTo", "").
|
||||
Where("(expiredAt=0 OR expiredAt>:nowTime)").
|
||||
@@ -283,6 +370,106 @@ func (this *IPItemDAO) ExistsEnabledItem(tx *dbs.Tx, itemId int64) (bool, error)
|
||||
Exist()
|
||||
}
|
||||
|
||||
// CountAllEnabledIPItems 计算数量
|
||||
func (this *IPItemDAO) CountAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64, unread bool) (int64, error) {
|
||||
var query = this.Query(tx)
|
||||
if len(ip) > 0 {
|
||||
query.Attr("ipFrom", ip)
|
||||
}
|
||||
if listId > 0 {
|
||||
query.Attr("listId", listId)
|
||||
} else {
|
||||
query.Where("(listId=" + types.String(firewallconfigs.GlobalListId) + " OR listId IN (SELECT id FROM " + SharedIPListDAO.Table + " WHERE state=1))")
|
||||
}
|
||||
if unread {
|
||||
query.Attr("isRead", 0)
|
||||
}
|
||||
return query.
|
||||
State(IPItemStateEnabled).
|
||||
Where("(expiredAt=0 OR expiredAt>:expiredAt)").
|
||||
Param("expiredAt", time.Now().Unix()).
|
||||
Count()
|
||||
}
|
||||
|
||||
// ListAllEnabledIPItems 搜索所有IP
|
||||
func (this *IPItemDAO) ListAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64, unread bool, offset int64, size int64) (result []*IPItem, err error) {
|
||||
var query = this.Query(tx)
|
||||
if len(ip) > 0 {
|
||||
query.Attr("ipFrom", ip)
|
||||
}
|
||||
if listId > 0 {
|
||||
query.Attr("listId", listId)
|
||||
} else {
|
||||
query.Where("(listId=" + types.String(firewallconfigs.GlobalListId) + " OR listId IN (SELECT id FROM " + SharedIPListDAO.Table + " WHERE state=1))")
|
||||
}
|
||||
if unread {
|
||||
query.Attr("isRead", 0)
|
||||
}
|
||||
_, err = query.
|
||||
State(IPItemStateEnabled).
|
||||
Where("(expiredAt=0 OR expiredAt>:expiredAt)").
|
||||
Param("expiredAt", time.Now().Unix()).
|
||||
DescPk().
|
||||
Offset(offset).
|
||||
Size(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateItemsRead 设置所有未已读
|
||||
func (this *IPItemDAO) UpdateItemsRead(tx *dbs.Tx) error {
|
||||
return this.Query(tx).
|
||||
Attr("isRead", 0).
|
||||
Set("isRead", 1).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// CleanExpiredIPItems 清除过期数据
|
||||
func (this *IPItemDAO) CleanExpiredIPItems(tx *dbs.Tx) error {
|
||||
// 删除 N 天之前过期的数据
|
||||
_, err := this.Query(tx).
|
||||
Where("expiredAt<=:timestamp").
|
||||
State(IPItemStateDisabled).
|
||||
Param("timestamp", time.Now().Unix()-7*86400). // N 天之前过期的
|
||||
Limit(10000). // 限制条数,防止数量过多导致超时
|
||||
Delete()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 将过期的设置为已删除,这样是为了在 expiredAt<UNIX_TIMESTAMP()边缘节点让过期的IP有一个执行删除的机会
|
||||
ones, _, err := this.Query(tx).
|
||||
ResultPk().
|
||||
Where("(expiredAt>0 AND expiredAt<=:timestamp)").
|
||||
Param("timestamp", time.Now().Unix()).
|
||||
State(IPItemStateEnabled).
|
||||
Limit(500).
|
||||
FindOnes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, one := range ones {
|
||||
var expiredId = one.GetInt64("id")
|
||||
newVersion, err := SharedIPListDAO.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 这里不重置过期时间用于清理
|
||||
_, err = this.Query(tx).
|
||||
Pk(expiredId).
|
||||
Set("state", IPItemStateDisabled).
|
||||
Set("version", newVersion).
|
||||
Update()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *IPItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64) error {
|
||||
// 获取ListId
|
||||
@@ -295,6 +482,37 @@ func (this *IPItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if listId == firewallconfigs.GlobalListId {
|
||||
sourceNodeId, err := this.Query(tx).
|
||||
Pk(itemId).
|
||||
Result("sourceNodeId").
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if sourceNodeId > 0 {
|
||||
clusterIds, err := SharedNodeDAO.FindEnabledNodeClusterIds(tx, sourceNodeId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, clusterId := range clusterIds {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeIPItemChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
clusterIds, err := SharedNodeClusterDAO.FindAllEnabledNodeClusterIds(tx)
|
||||
for _, clusterId := range clusterIds {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeIPItemChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
httpFirewallPolicyIds, err := SharedHTTPFirewallPolicyDAO.FindEnabledFirewallPolicyIdsWithIPListId(tx, listId)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -338,7 +556,7 @@ func (this *IPItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64) error {
|
||||
|
||||
if len(resultClusterIds) > 0 {
|
||||
for _, clusterId := range resultClusterIds {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeIPItemChanged)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeIPItemChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestIPItemDAO_NotifyClustersUpdate(t *testing.T) {
|
||||
@@ -16,3 +20,45 @@ func TestIPItemDAO_NotifyClustersUpdate(t *testing.T) {
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestIPItemDAO_DisableIPItemsWithListId(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
err := SharedIPItemDAO.DisableIPItemsWithListId(tx, 67)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestIPItemDAO_ListIPItemsAfterVersion(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
_, err := SharedIPItemDAO.ListIPItemsAfterVersion(tx, 0, 100)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestIPItemDAO_CreateManyIPs(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
var dao = NewIPItemDAO()
|
||||
var n = 10
|
||||
for i := 0; i < n; i++ {
|
||||
itemId, err := dao.CreateIPItem(tx, firewallconfigs.GlobalListId, "192."+types.String(rands.Int(0, 255))+"."+types.String(rands.Int(0, 255))+"."+types.String(rands.Int(0, 255)), "", time.Now().Unix()+86400, "test", IPItemTypeIPv4, "warning", 0, 0, 0, 0, 0, 0, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_ = itemId
|
||||
/**err = dao.Query(tx).Pk(itemId).Set("state", 0).UpdateQuickly()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}**/
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
@@ -1,38 +1,54 @@
|
||||
package models
|
||||
|
||||
// IP
|
||||
// IPItem IP
|
||||
type IPItem struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
ListId uint32 `field:"listId"` // 所属名单ID
|
||||
Type string `field:"type"` // 类型
|
||||
IpFrom string `field:"ipFrom"` // 开始IP
|
||||
IpTo string `field:"ipTo"` // 结束IP
|
||||
IpFromLong uint64 `field:"ipFromLong"` // 开始IP整型
|
||||
IpToLong uint64 `field:"ipToLong"` // 结束IP整型
|
||||
Version uint64 `field:"version"` // 版本
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
|
||||
Reason string `field:"reason"` // 加入说明
|
||||
EventLevel string `field:"eventLevel"` // 事件级别
|
||||
State uint8 `field:"state"` // 状态
|
||||
ExpiredAt uint64 `field:"expiredAt"` // 过期时间
|
||||
Id uint64 `field:"id"` // ID
|
||||
ListId uint32 `field:"listId"` // 所属名单ID
|
||||
Type string `field:"type"` // 类型
|
||||
IpFrom string `field:"ipFrom"` // 开始IP
|
||||
IpTo string `field:"ipTo"` // 结束IP
|
||||
IpFromLong uint64 `field:"ipFromLong"` // 开始IP整型
|
||||
IpToLong uint64 `field:"ipToLong"` // 结束IP整型
|
||||
Version uint64 `field:"version"` // 版本
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
|
||||
Reason string `field:"reason"` // 加入说明
|
||||
EventLevel string `field:"eventLevel"` // 事件级别
|
||||
State uint8 `field:"state"` // 状态
|
||||
ExpiredAt uint64 `field:"expiredAt"` // 过期时间
|
||||
ServerId uint32 `field:"serverId"` // 有效范围服务ID
|
||||
NodeId uint32 `field:"nodeId"` // 有效范围节点ID
|
||||
SourceNodeId uint32 `field:"sourceNodeId"` // 来源节点ID
|
||||
SourceServerId uint32 `field:"sourceServerId"` // 来源服务ID
|
||||
SourceHTTPFirewallPolicyId uint32 `field:"sourceHTTPFirewallPolicyId"` // 来源策略ID
|
||||
SourceHTTPFirewallRuleGroupId uint32 `field:"sourceHTTPFirewallRuleGroupId"` // 来源规则集分组ID
|
||||
SourceHTTPFirewallRuleSetId uint32 `field:"sourceHTTPFirewallRuleSetId"` // 来源规则集ID
|
||||
IsRead uint8 `field:"isRead"` // 是否已读
|
||||
}
|
||||
|
||||
type IPItemOperator struct {
|
||||
Id interface{} // ID
|
||||
ListId interface{} // 所属名单ID
|
||||
Type interface{} // 类型
|
||||
IpFrom interface{} // 开始IP
|
||||
IpTo interface{} // 结束IP
|
||||
IpFromLong interface{} // 开始IP整型
|
||||
IpToLong interface{} // 结束IP整型
|
||||
Version interface{} // 版本
|
||||
CreatedAt interface{} // 创建时间
|
||||
UpdatedAt interface{} // 修改时间
|
||||
Reason interface{} // 加入说明
|
||||
EventLevel interface{} // 事件级别
|
||||
State interface{} // 状态
|
||||
ExpiredAt interface{} // 过期时间
|
||||
Id interface{} // ID
|
||||
ListId interface{} // 所属名单ID
|
||||
Type interface{} // 类型
|
||||
IpFrom interface{} // 开始IP
|
||||
IpTo interface{} // 结束IP
|
||||
IpFromLong interface{} // 开始IP整型
|
||||
IpToLong interface{} // 结束IP整型
|
||||
Version interface{} // 版本
|
||||
CreatedAt interface{} // 创建时间
|
||||
UpdatedAt interface{} // 修改时间
|
||||
Reason interface{} // 加入说明
|
||||
EventLevel interface{} // 事件级别
|
||||
State interface{} // 状态
|
||||
ExpiredAt interface{} // 过期时间
|
||||
ServerId interface{} // 有效范围服务ID
|
||||
NodeId interface{} // 有效范围节点ID
|
||||
SourceNodeId interface{} // 来源节点ID
|
||||
SourceServerId interface{} // 来源服务ID
|
||||
SourceHTTPFirewallPolicyId interface{} // 来源策略ID
|
||||
SourceHTTPFirewallRuleGroupId interface{} // 来源规则集分组ID
|
||||
SourceHTTPFirewallRuleSetId interface{} // 来源规则集ID
|
||||
IsRead interface{} // 是否已读
|
||||
}
|
||||
|
||||
func NewIPItemOperator() *IPItemOperator {
|
||||
|
||||
@@ -2,7 +2,9 @@ package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ipconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
@@ -16,7 +18,16 @@ const (
|
||||
IPListStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
var listTypeCacheMap = map[int64]string{} // listId => type
|
||||
var listTypeCacheMap = map[int64]*IPList{} // listId => *IPList
|
||||
var DefaultGlobalIPList = &IPList{
|
||||
Id: uint32(firewallconfigs.GlobalListId),
|
||||
Name: "全局封锁名单",
|
||||
IsPublic: 1,
|
||||
IsGlobal: 1,
|
||||
Type: "black",
|
||||
State: IPListStateEnabled,
|
||||
IsOn: 1,
|
||||
}
|
||||
|
||||
type IPListDAO dbs.DAO
|
||||
|
||||
@@ -58,7 +69,19 @@ func (this *IPListDAO) DisableIPList(tx *dbs.Tx, id int64) error {
|
||||
}
|
||||
|
||||
// FindEnabledIPList 查找启用中的条目
|
||||
func (this *IPListDAO) FindEnabledIPList(tx *dbs.Tx, id int64) (*IPList, error) {
|
||||
func (this *IPListDAO) FindEnabledIPList(tx *dbs.Tx, id int64, cacheMap *utils.CacheMap) (*IPList, error) {
|
||||
if id == firewallconfigs.GlobalListId {
|
||||
return DefaultGlobalIPList, nil
|
||||
}
|
||||
|
||||
var cacheKey = this.Table + ":FindEnabledIPList:" + types.String(id)
|
||||
if cacheMap != nil {
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return cache.(*IPList), nil
|
||||
}
|
||||
}
|
||||
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", IPListStateEnabled).
|
||||
@@ -66,6 +89,11 @@ func (this *IPListDAO) FindEnabledIPList(tx *dbs.Tx, id int64) (*IPList, error)
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, result)
|
||||
}
|
||||
|
||||
return result.(*IPList), err
|
||||
}
|
||||
|
||||
@@ -77,38 +105,39 @@ func (this *IPListDAO) FindIPListName(tx *dbs.Tx, id int64) (string, error) {
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// FindIPListTypeCacheable 获取名单类型
|
||||
func (this *IPListDAO) FindIPListTypeCacheable(tx *dbs.Tx, listId int64) (string, error) {
|
||||
// FindIPListCacheable 获取名单
|
||||
func (this *IPListDAO) FindIPListCacheable(tx *dbs.Tx, listId int64) (*IPList, error) {
|
||||
// 全局黑名单
|
||||
if listId == firewallconfigs.GlobalListId {
|
||||
return DefaultGlobalIPList, nil
|
||||
}
|
||||
|
||||
// 检查缓存
|
||||
SharedCacheLocker.RLock()
|
||||
listType, ok := listTypeCacheMap[listId]
|
||||
list, ok := listTypeCacheMap[listId]
|
||||
SharedCacheLocker.RUnlock()
|
||||
if ok {
|
||||
return listType, nil
|
||||
return list, nil
|
||||
}
|
||||
|
||||
listType, err := this.Query(tx).
|
||||
one, err := this.Query(tx).
|
||||
Pk(listId).
|
||||
Result("type").
|
||||
FindStringCol("")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(listType) == 0 {
|
||||
return "", nil
|
||||
Result("isGlobal", "type", "state", "id", "isPublic", "isGlobal").
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 保存缓存
|
||||
SharedCacheLocker.Lock()
|
||||
listTypeCacheMap[listId] = listType
|
||||
listTypeCacheMap[listId] = one.(*IPList)
|
||||
SharedCacheLocker.Unlock()
|
||||
|
||||
return listType, nil
|
||||
return one.(*IPList), nil
|
||||
}
|
||||
|
||||
// CreateIPList 创建名单
|
||||
func (this *IPListDAO) CreateIPList(tx *dbs.Tx, userId int64, listType ipconfigs.IPListType, name string, code string, timeoutJSON []byte, description string, isPublic bool) (int64, error) {
|
||||
func (this *IPListDAO) CreateIPList(tx *dbs.Tx, userId int64, listType ipconfigs.IPListType, name string, code string, timeoutJSON []byte, description string, isPublic bool, isGlobal bool) (int64, error) {
|
||||
op := NewIPListOperator()
|
||||
op.IsOn = true
|
||||
op.UserId = userId
|
||||
@@ -121,6 +150,7 @@ func (this *IPListDAO) CreateIPList(tx *dbs.Tx, userId int64, listType ipconfigs
|
||||
}
|
||||
op.Description = description
|
||||
op.IsPublic = isPublic
|
||||
op.IsGlobal = isGlobal
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -254,7 +284,7 @@ func (this *IPListDAO) NotifyUpdate(tx *dbs.Tx, listId int64, taskType NodeTaskT
|
||||
|
||||
if len(resultClusterIds) > 0 {
|
||||
for _, clusterId := range resultClusterIds {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, taskType)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, taskType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ type IPList struct {
|
||||
Actions string `field:"actions"` // IP触发的动作
|
||||
Description string `field:"description"` // 描述
|
||||
IsPublic uint8 `field:"isPublic"` // 是否公用
|
||||
IsGlobal uint8 `field:"isGlobal"` // 是否全局
|
||||
}
|
||||
|
||||
type IPListOperator struct {
|
||||
@@ -31,6 +32,7 @@ type IPListOperator struct {
|
||||
Actions interface{} // IP触发的动作
|
||||
Description interface{} // 描述
|
||||
IsPublic interface{} // 是否公用
|
||||
IsGlobal interface{} // 是否全局
|
||||
}
|
||||
|
||||
func NewIPListOperator() *IPListOperator {
|
||||
|
||||
@@ -26,6 +26,8 @@ const (
|
||||
type MessageType = string
|
||||
|
||||
const (
|
||||
// 这里的命名问题(首字母大写)为历史遗留问题,暂不修改
|
||||
|
||||
MessageTypeHealthCheckFailed MessageType = "HealthCheckFailed" // 节点健康检查失败
|
||||
MessageTypeHealthCheckNodeUp MessageType = "HealthCheckNodeUp" // 因健康检查节点上线
|
||||
MessageTypeHealthCheckNodeDown MessageType = "HealthCheckNodeDown" // 因健康检查节点下线
|
||||
@@ -36,8 +38,9 @@ const (
|
||||
MessageTypeSSLCertACMETaskFailed MessageType = "SSLCertACMETaskFailed" // SSL证书任务执行失败
|
||||
MessageTypeSSLCertACMETaskSuccess MessageType = "SSLCertACMETaskSuccess" // SSL证书任务执行成功
|
||||
MessageTypeLogCapacityOverflow MessageType = "LogCapacityOverflow" // 日志超出最大限制
|
||||
MessageTypeServerNamesAuditingSuccess MessageType = "ServerNamesAuditingSuccess" // 服务域名审核成功
|
||||
MessageTypeServerNamesAuditingFailed MessageType = "ServerNamesAuditingFailed" // 服务域名审核失败
|
||||
MessageTypeServerNamesAuditingSuccess MessageType = "ServerNamesAuditingSuccess" // 服务域名审核成功(用户)
|
||||
MessageTypeServerNamesAuditingFailed MessageType = "ServerNamesAuditingFailed" // 服务域名审核失败(用户)
|
||||
MessageTypeServerNamesRequireAuditing MessageType = "serverNamesRequireAuditing" // 服务域名需要审核(管理员)
|
||||
MessageTypeThresholdSatisfied MessageType = "ThresholdSatisfied" // 满足阈值
|
||||
MessageTypeFirewallEvent MessageType = "FirewallEvent" // 防火墙事件
|
||||
MessageTypeIPAddrUp MessageType = "IPAddrUp" // IP地址上线
|
||||
|
||||
@@ -3,6 +3,7 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -55,12 +56,12 @@ func (this *MessageMediaInstanceDAO) DisableMessageMediaInstance(tx *dbs.Tx, id
|
||||
}
|
||||
|
||||
// FindEnabledMessageMediaInstance 查找启用中的条目
|
||||
func (this *MessageMediaInstanceDAO) FindEnabledMessageMediaInstance(tx *dbs.Tx, instanceId int64, cacheMap maps.Map) (*MessageMediaInstance, error) {
|
||||
func (this *MessageMediaInstanceDAO) FindEnabledMessageMediaInstance(tx *dbs.Tx, instanceId int64, cacheMap *utils.CacheMap) (*MessageMediaInstance, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = maps.Map{}
|
||||
cacheMap = utils.NewCacheMap()
|
||||
}
|
||||
var cacheKey = this.Table + ":record:" + types.String(instanceId)
|
||||
var cache = cacheMap.Get(cacheKey)
|
||||
var cache, _ = cacheMap.Get(cacheKey)
|
||||
if cache != nil {
|
||||
return cache.(*MessageMediaInstance), nil
|
||||
}
|
||||
@@ -73,7 +74,9 @@ func (this *MessageMediaInstanceDAO) FindEnabledMessageMediaInstance(tx *dbs.Tx,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cacheMap[cacheKey] = result
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, result)
|
||||
}
|
||||
|
||||
return result.(*MessageMediaInstance), err
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/numberutils"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"regexp"
|
||||
)
|
||||
@@ -57,13 +57,13 @@ func (this *MessageRecipientDAO) DisableMessageRecipient(tx *dbs.Tx, id int64) e
|
||||
}
|
||||
|
||||
// FindEnabledMessageRecipient 查找启用中的条目
|
||||
func (this *MessageRecipientDAO) FindEnabledMessageRecipient(tx *dbs.Tx, recipientId int64, cacheMap maps.Map,
|
||||
func (this *MessageRecipientDAO) FindEnabledMessageRecipient(tx *dbs.Tx, recipientId int64, cacheMap *utils.CacheMap,
|
||||
) (*MessageRecipient, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = maps.Map{}
|
||||
cacheMap = utils.NewCacheMap()
|
||||
}
|
||||
var cacheKey = this.Table + ":record:" + types.String(recipientId)
|
||||
var cache = cacheMap.Get(cacheKey)
|
||||
var cache, _ = cacheMap.Get(cacheKey)
|
||||
if cache != nil {
|
||||
return cache.(*MessageRecipient), nil
|
||||
}
|
||||
@@ -76,7 +76,9 @@ func (this *MessageRecipientDAO) FindEnabledMessageRecipient(tx *dbs.Tx, recipie
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cacheMap[cacheKey] = result
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, result)
|
||||
}
|
||||
|
||||
return result.(*MessageRecipient), err
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package models
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@@ -46,14 +47,14 @@ func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
// 清理数据任务
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
go func() {
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedMessageTaskDAO.CleanExpiredMessageTasks(nil, 30) // 只保留30天
|
||||
if err != nil {
|
||||
remotelogs.Error("SharedMessageTaskDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
@@ -16,14 +17,14 @@ func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
// 清理数据任务
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
go func() {
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedMessageTaskLogDAO.CleanExpiredLogs(nil, 30) // 只保留30天
|
||||
if err != nil {
|
||||
remotelogs.Error("SharedMessageTaskLogDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@@ -77,6 +78,12 @@ func (this *MetricItemDAO) DisableMetricItem(tx *dbs.Tx, itemId int64) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = SharedMetricSumStatDAO.DeleteItemStats(tx, itemId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -229,7 +236,16 @@ func (this *MetricItemDAO) ListEnabledItems(tx *dbs.Tx, category serverconfigs.M
|
||||
}
|
||||
|
||||
// FindAllPublicItems 取得公用的指标
|
||||
func (this *MetricItemDAO) FindAllPublicItems(tx *dbs.Tx, category string) (result []*MetricItem, err error) {
|
||||
func (this *MetricItemDAO) FindAllPublicItems(tx *dbs.Tx, category string, cacheMap *utils.CacheMap) (result []*MetricItem, err error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = utils.NewCacheMap()
|
||||
}
|
||||
var cacheKey = this.Table + ":FindAllPublicItems:" + category
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return cache.([]*MetricItem), nil
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
State(MetricItemStateEnabled).
|
||||
Attr("userId", 0).
|
||||
@@ -238,6 +254,14 @@ func (this *MetricItemDAO) FindAllPublicItems(tx *dbs.Tx, category string) (resu
|
||||
DescPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, result)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -310,7 +334,7 @@ func (this *MetricItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64, isPublic bool)
|
||||
return err
|
||||
}
|
||||
for _, clusterId := range clusterIds {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeConfigChanged)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeConfigChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -322,7 +346,7 @@ func (this *MetricItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64, isPublic bool)
|
||||
return err
|
||||
}
|
||||
for _, clusterId := range clusterIds {
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeConfigChanged)
|
||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeConfigChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
@@ -20,14 +22,14 @@ func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
// 清理数据任务
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
go func() {
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedMetricStatDAO.Clean(nil, 120) // 只保留120天
|
||||
err := SharedMetricStatDAO.Clean(nil)
|
||||
if err != nil {
|
||||
logs.Println("SharedMetricStatDAO: clean expired data failed: " + err.Error())
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -461,12 +463,39 @@ func (this *MetricStatDAO) FindLatestItemStatsWithServerId(tx *dbs.Tx, serverId
|
||||
}
|
||||
|
||||
// Clean 清理数据
|
||||
func (this *MetricStatDAO) Clean(tx *dbs.Tx, days int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Lt("createdDay", timeutil.FormatTime("Ymd", time.Now().Unix()-days*86400)).
|
||||
Delete()
|
||||
if err != nil {
|
||||
return err
|
||||
func (this *MetricStatDAO) Clean(tx *dbs.Tx) error {
|
||||
for _, category := range serverconfigs.FindAllMetricItemCategoryCodes() {
|
||||
var offset int64 = 0
|
||||
var size int64 = 100
|
||||
for {
|
||||
items, err := SharedMetricItemDAO.ListEnabledItems(tx, category, offset, size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, item := range items {
|
||||
var config = &serverconfigs.MetricItemConfig{
|
||||
Id: int64(item.Id),
|
||||
Period: int(item.Period),
|
||||
PeriodUnit: item.PeriodUnit,
|
||||
}
|
||||
var expiresDay = config.ServerExpiresDay()
|
||||
_, err := this.Query(tx).
|
||||
Attr("itemId", item.Id).
|
||||
Lte("createdDay", expiresDay).
|
||||
UseIndex("createdDay").
|
||||
Limit(100_000). // 一次性不要删除太多,防止阻塞其他操作
|
||||
Delete()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(items) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
offset += size
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package models
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
@@ -10,14 +11,24 @@ import (
|
||||
)
|
||||
|
||||
func TestNewMetricStatDAO_InsertMany(t *testing.T) {
|
||||
for i := 0; i <= 10_000_000; i++ {
|
||||
for i := 0; i <= 1; i++ {
|
||||
err := NewMetricStatDAO().CreateStat(nil, types.String(i)+"_v1", 18, int64(rands.Int(0, 10000)), int64(rands.Int(0, 10000)), int64(rands.Int(0, 100)), []string{"/html" + types.String(i)}, 1, timeutil.Format("Ymd"), 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i % 10000 == 0 {
|
||||
if i%10000 == 0 {
|
||||
t.Log(i)
|
||||
}
|
||||
}
|
||||
t.Log("done")
|
||||
}
|
||||
|
||||
func TestMetricStatDAO_Clean(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
err := NewMetricStatDAO().Clean(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
@@ -1,14 +1,35 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
type MetricSumStatDAO 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 := SharedMetricSumStatDAO.Clean(nil)
|
||||
if err != nil {
|
||||
logs.Println("SharedMetricSumStatDAO: clean expired data failed: " + err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func NewMetricSumStatDAO() *MetricSumStatDAO {
|
||||
return dbs.NewDAO(&MetricSumStatDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
@@ -32,14 +53,15 @@ func init() {
|
||||
func (this *MetricSumStatDAO) UpdateSum(tx *dbs.Tx, clusterId int64, nodeId int64, serverId int64, time string, itemId int64, version int32, count int64, total float32) error {
|
||||
return this.Query(tx).
|
||||
InsertOrUpdateQuickly(maps.Map{
|
||||
"clusterId": clusterId,
|
||||
"nodeId": nodeId,
|
||||
"serverId": serverId,
|
||||
"itemId": itemId,
|
||||
"version": version,
|
||||
"time": time,
|
||||
"count": count,
|
||||
"total": total,
|
||||
"clusterId": clusterId,
|
||||
"nodeId": nodeId,
|
||||
"serverId": serverId,
|
||||
"itemId": itemId,
|
||||
"version": version,
|
||||
"time": time,
|
||||
"count": count,
|
||||
"total": total,
|
||||
"createdDay": timeutil.Format("Ymd"),
|
||||
}, maps.Map{
|
||||
"count": count,
|
||||
"total": total,
|
||||
@@ -84,6 +106,7 @@ func (this *MetricSumStatDAO) FindSumAtTime(tx *dbs.Tx, time string, itemId int6
|
||||
// FindServerSum 查找某个服务的统计数据
|
||||
func (this *MetricSumStatDAO) FindServerSum(tx *dbs.Tx, serverId int64, time string, itemId int64, version int32) (count int64, total float32, err error) {
|
||||
one, err := this.Query(tx).
|
||||
UseIndex("server_item_time").
|
||||
Attr("serverId", serverId).
|
||||
Attr("time", time).
|
||||
Attr("itemId", itemId).
|
||||
@@ -102,6 +125,7 @@ func (this *MetricSumStatDAO) FindServerSum(tx *dbs.Tx, serverId int64, time str
|
||||
// FindClusterSum 查找集群上的统计数据
|
||||
func (this *MetricSumStatDAO) FindClusterSum(tx *dbs.Tx, clusterId int64, time string, itemId int64, version int32) (count int64, total float32, err error) {
|
||||
one, err := this.Query(tx).
|
||||
UseIndex("cluster_item_time").
|
||||
Attr("clusterId", clusterId).
|
||||
Attr("time", time).
|
||||
Attr("itemId", itemId).
|
||||
@@ -120,6 +144,7 @@ func (this *MetricSumStatDAO) FindClusterSum(tx *dbs.Tx, clusterId int64, time s
|
||||
// FindNodeSum 查找节点上的统计数据
|
||||
func (this *MetricSumStatDAO) FindNodeSum(tx *dbs.Tx, nodeId int64, time string, itemId int64, version int32) (count int64, total float32, err error) {
|
||||
one, err := this.Query(tx).
|
||||
UseIndex("node_item_time").
|
||||
Attr("nodeId", nodeId).
|
||||
Attr("time", time).
|
||||
Attr("itemId", itemId).
|
||||
@@ -134,3 +159,50 @@ func (this *MetricSumStatDAO) FindNodeSum(tx *dbs.Tx, nodeId int64, time string,
|
||||
}
|
||||
return int64(one.(*MetricSumStat).Count), float32(one.(*MetricSumStat).Total), nil
|
||||
}
|
||||
|
||||
// DeleteItemStats 删除某个指标相关的统计数据
|
||||
func (this *MetricSumStatDAO) DeleteItemStats(tx *dbs.Tx, itemId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Attr("itemId", itemId).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
// Clean 清理数据
|
||||
func (this *MetricSumStatDAO) Clean(tx *dbs.Tx) error {
|
||||
for _, category := range serverconfigs.FindAllMetricItemCategoryCodes() {
|
||||
var offset int64 = 0
|
||||
var size int64 = 100
|
||||
for {
|
||||
items, err := SharedMetricItemDAO.ListEnabledItems(tx, category, offset, size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, item := range items {
|
||||
var config = &serverconfigs.MetricItemConfig{
|
||||
Id: int64(item.Id),
|
||||
Period: int(item.Period),
|
||||
PeriodUnit: item.PeriodUnit,
|
||||
}
|
||||
var expiresDay = config.ServerExpiresDay()
|
||||
_, err := this.Query(tx).
|
||||
Attr("itemId", item.Id).
|
||||
Where("(createdDay IS NULL OR createdDay<:day)").
|
||||
Param("day", expiresDay).
|
||||
UseIndex("createdDay").
|
||||
Limit(100_000). // 一次性不要删除太多,防止阻塞其他操作
|
||||
Delete()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(items) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
offset += size
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,4 +3,15 @@ package models
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMetricSumStatDAO_Clean(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
err := NewMetricSumStatDAO().Clean(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,27 +2,29 @@ package models
|
||||
|
||||
// MetricSumStat 指标统计总和数据
|
||||
type MetricSumStat struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||
NodeId uint32 `field:"nodeId"` // 节点ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
ItemId uint64 `field:"itemId"` // 指标
|
||||
Count uint64 `field:"count"` // 数量
|
||||
Total float64 `field:"total"` // 总和
|
||||
Time string `field:"time"` // 分钟值YYYYMMDDHHII
|
||||
Version uint32 `field:"version"` // 版本号
|
||||
Id uint64 `field:"id"` // ID
|
||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||
NodeId uint32 `field:"nodeId"` // 节点ID
|
||||
ServerId uint32 `field:"serverId"` // 服务ID
|
||||
ItemId uint64 `field:"itemId"` // 指标
|
||||
Count uint64 `field:"count"` // 数量
|
||||
Total float64 `field:"total"` // 总和
|
||||
Time string `field:"time"` // 分钟值YYYYMMDDHHII
|
||||
Version uint32 `field:"version"` // 版本号
|
||||
CreatedDay string `field:"createdDay"` // 创建日期YYYYMMDD
|
||||
}
|
||||
|
||||
type MetricSumStatOperator struct {
|
||||
Id interface{} // ID
|
||||
ClusterId interface{} // 集群ID
|
||||
NodeId interface{} // 节点ID
|
||||
ServerId interface{} // 服务ID
|
||||
ItemId interface{} // 指标
|
||||
Count interface{} // 数量
|
||||
Total interface{} // 总和
|
||||
Time interface{} // 分钟值YYYYMMDDHHII
|
||||
Version interface{} // 版本号
|
||||
Id interface{} // ID
|
||||
ClusterId interface{} // 集群ID
|
||||
NodeId interface{} // 节点ID
|
||||
ServerId interface{} // 服务ID
|
||||
ItemId interface{} // 指标
|
||||
Count interface{} // 数量
|
||||
Total interface{} // 总和
|
||||
Time interface{} // 分钟值YYYYMMDDHHII
|
||||
Version interface{} // 版本号
|
||||
CreatedDay interface{} // 创建日期YYYYMMDD
|
||||
}
|
||||
|
||||
func NewMetricSumStatOperator() *MetricSumStatOperator {
|
||||
|
||||
@@ -282,7 +282,7 @@ func (this *NSDomainDAO) NotifyUpdate(tx *dbs.Tx, domainId int64) error {
|
||||
return err
|
||||
}
|
||||
if clusterId > 0 {
|
||||
return models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, models.NSNodeTaskTypeDomainChanged)
|
||||
return models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, 0, models.NSNodeTaskTypeDomainChanged)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -199,7 +199,7 @@ func (this *NSKeyDAO) NotifyUpdate(tx *dbs.Tx, keyId int64) error {
|
||||
return err
|
||||
}
|
||||
if clusterId > 0 {
|
||||
err = models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, models.NSNodeTaskTypeKeyChanged)
|
||||
err = models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, 0, models.NSNodeTaskTypeKeyChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ func (this *NSRecordDAO) NotifyUpdate(tx *dbs.Tx, recordId int64) error {
|
||||
}
|
||||
|
||||
if clusterId > 0 {
|
||||
err = models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, models.NSNodeTaskTypeRecordChanged)
|
||||
err = models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, 0, models.NSNodeTaskTypeRecordChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package nameservers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@@ -19,14 +20,14 @@ func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
// 清理数据任务
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
go func() {
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedNSRecordHourlyStatDAO.Clean(nil, 60) // 只保留60天
|
||||
err := SharedNSRecordHourlyStatDAO.Clean(nil, 30) // 只保留N天
|
||||
if err != nil {
|
||||
remotelogs.Error("NodeClusterTrafficDailyStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -259,7 +259,7 @@ func (this *NSRouteDAO) NotifyUpdate(tx *dbs.Tx) error {
|
||||
return err
|
||||
}
|
||||
for _, clusterId := range clusterIds {
|
||||
err = models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, models.NSNodeTaskTypeRouteChanged)
|
||||
err = models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, 0, models.NSNodeTaskTypeRouteChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
@@ -177,7 +178,7 @@ func (this *NodeClusterDAO) CreateCluster(tx *dbs.Tx, adminId int64, name string
|
||||
}
|
||||
|
||||
// UpdateCluster 修改集群
|
||||
func (this *NodeClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name string, grantId int64, installDir string, timezone string) error {
|
||||
func (this *NodeClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name string, grantId int64, installDir string, timezone string, nodeMaxThreads int32, nodeTCPMaxConnections int32, autoOpenPorts bool) error {
|
||||
if clusterId <= 0 {
|
||||
return errors.New("invalid clusterId")
|
||||
}
|
||||
@@ -187,6 +188,18 @@ func (this *NodeClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name stri
|
||||
op.GrantId = grantId
|
||||
op.InstallDir = installDir
|
||||
op.TimeZone = timezone
|
||||
|
||||
if nodeMaxThreads < 0 {
|
||||
nodeMaxThreads = 0
|
||||
}
|
||||
op.NodeMaxThreads = nodeMaxThreads
|
||||
|
||||
if nodeTCPMaxConnections < 0 {
|
||||
nodeTCPMaxConnections = 0
|
||||
}
|
||||
op.NodeTCPMaxConnections = nodeTCPMaxConnections
|
||||
op.AutoOpenPorts = autoOpenPorts
|
||||
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -262,7 +275,7 @@ func (this *NodeClusterDAO) FindAllAPINodeAddrsWithCluster(tx *dbs.Tx, clusterId
|
||||
return nil, err
|
||||
}
|
||||
for _, apiNodeId := range apiNodeIds {
|
||||
apiNode, err := SharedAPINodeDAO.FindEnabledAPINode(tx, apiNodeId)
|
||||
apiNode, err := SharedAPINodeDAO.FindEnabledAPINode(tx, apiNodeId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -407,14 +420,13 @@ func (this *NodeClusterDAO) FindClusterGrantId(tx *dbs.Tx, clusterId int64) (int
|
||||
}
|
||||
|
||||
// FindClusterDNSInfo 查找DNS信息
|
||||
func (this *NodeClusterDAO) FindClusterDNSInfo(tx *dbs.Tx, clusterId int64, cacheMap maps.Map) (*NodeCluster, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = maps.Map{}
|
||||
}
|
||||
func (this *NodeClusterDAO) FindClusterDNSInfo(tx *dbs.Tx, clusterId int64, cacheMap *utils.CacheMap) (*NodeCluster, error) {
|
||||
var cacheKey = this.Table + ":FindClusterDNSInfo:" + types.String(clusterId)
|
||||
var cache = cacheMap.Get(cacheKey)
|
||||
if cache != nil {
|
||||
return cache.(*NodeCluster), nil
|
||||
if cacheMap != nil {
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return cache.(*NodeCluster), nil
|
||||
}
|
||||
}
|
||||
|
||||
one, err := this.Query(tx).
|
||||
@@ -427,7 +439,9 @@ func (this *NodeClusterDAO) FindClusterDNSInfo(tx *dbs.Tx, clusterId int64, cach
|
||||
if one == nil {
|
||||
return nil, nil
|
||||
}
|
||||
cacheMap[cacheKey] = one
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, one)
|
||||
}
|
||||
return one.(*NodeCluster), nil
|
||||
}
|
||||
|
||||
@@ -487,7 +501,15 @@ func (this *NodeClusterDAO) FindClusterAdminId(tx *dbs.Tx, clusterId int64) (int
|
||||
}
|
||||
|
||||
// FindClusterTOAConfig 查找集群的TOA设置
|
||||
func (this *NodeClusterDAO) FindClusterTOAConfig(tx *dbs.Tx, clusterId int64) (*nodeconfigs.TOAConfig, error) {
|
||||
func (this *NodeClusterDAO) FindClusterTOAConfig(tx *dbs.Tx, clusterId int64, cacheMap *utils.CacheMap) (*nodeconfigs.TOAConfig, error) {
|
||||
var cacheKey = this.Table + ":FindClusterTOAConfig:" + types.String(clusterId)
|
||||
if cacheMap != nil {
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return cache.(*nodeconfigs.TOAConfig), nil
|
||||
}
|
||||
}
|
||||
|
||||
toa, err := this.Query(tx).
|
||||
Pk(clusterId).
|
||||
Result("toa").
|
||||
@@ -504,6 +526,11 @@ func (this *NodeClusterDAO) FindClusterTOAConfig(tx *dbs.Tx, clusterId int64) (*
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, config)
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
@@ -573,6 +600,22 @@ func (this *NodeClusterDAO) FindAllEnabledNodeClusterIdsWithHTTPFirewallPolicyId
|
||||
return
|
||||
}
|
||||
|
||||
// FindAllEnabledNodeClusterIds 查找所有可用的集群
|
||||
func (this *NodeClusterDAO) FindAllEnabledNodeClusterIds(tx *dbs.Tx) ([]int64, error) {
|
||||
ones, err := this.Query(tx).
|
||||
State(NodeClusterStateEnabled).
|
||||
ResultPk().
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var result = []int64{}
|
||||
for _, one := range ones {
|
||||
result = append(result, int64(one.(*NodeCluster).Id))
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// FindAllEnabledNodeClusterIdsWithCachePolicyId 查找使用缓存策略的所有集群Ids
|
||||
func (this *NodeClusterDAO) FindAllEnabledNodeClusterIdsWithCachePolicyId(tx *dbs.Tx, cachePolicyId int64) (result []int64, err error) {
|
||||
ones, err := this.Query(tx).
|
||||
@@ -587,12 +630,12 @@ func (this *NodeClusterDAO) FindAllEnabledNodeClusterIdsWithCachePolicyId(tx *db
|
||||
}
|
||||
|
||||
// FindClusterHTTPFirewallPolicyId 获取集群的WAF策略ID
|
||||
func (this *NodeClusterDAO) FindClusterHTTPFirewallPolicyId(tx *dbs.Tx, clusterId int64, cacheMap maps.Map) (int64, error) {
|
||||
func (this *NodeClusterDAO) FindClusterHTTPFirewallPolicyId(tx *dbs.Tx, clusterId int64, cacheMap *utils.CacheMap) (int64, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = maps.Map{}
|
||||
cacheMap = utils.NewCacheMap()
|
||||
}
|
||||
var cacheKey = this.Table + ":FindClusterHTTPFirewallPolicyId:" + types.String(clusterId)
|
||||
var cache = cacheMap.Get(cacheKey)
|
||||
var cache, _ = cacheMap.Get(cacheKey)
|
||||
if cache != nil {
|
||||
return cache.(int64), nil
|
||||
}
|
||||
@@ -605,7 +648,9 @@ func (this *NodeClusterDAO) FindClusterHTTPFirewallPolicyId(tx *dbs.Tx, clusterI
|
||||
return 0, err
|
||||
}
|
||||
|
||||
cacheMap[cacheKey] = firewallPolicyId
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, firewallPolicyId)
|
||||
}
|
||||
|
||||
return firewallPolicyId, nil
|
||||
}
|
||||
@@ -623,12 +668,12 @@ func (this *NodeClusterDAO) UpdateNodeClusterHTTPCachePolicyId(tx *dbs.Tx, clust
|
||||
}
|
||||
|
||||
// FindClusterHTTPCachePolicyId 获取集群的缓存策略ID
|
||||
func (this *NodeClusterDAO) FindClusterHTTPCachePolicyId(tx *dbs.Tx, clusterId int64, cacheMap maps.Map) (int64, error) {
|
||||
func (this *NodeClusterDAO) FindClusterHTTPCachePolicyId(tx *dbs.Tx, clusterId int64, cacheMap *utils.CacheMap) (int64, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = maps.Map{}
|
||||
cacheMap = utils.NewCacheMap()
|
||||
}
|
||||
var cacheKey = this.Table + ":FindClusterHTTPCachePolicyId:" + types.String(clusterId)
|
||||
var cache = cacheMap.Get(cacheKey)
|
||||
var cache, _ = cacheMap.Get(cacheKey)
|
||||
if cache != nil {
|
||||
return cache.(int64), nil
|
||||
}
|
||||
@@ -641,7 +686,9 @@ func (this *NodeClusterDAO) FindClusterHTTPCachePolicyId(tx *dbs.Tx, clusterId i
|
||||
return 0, err
|
||||
}
|
||||
|
||||
cacheMap[cacheKey] = cachePolicyId
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, cachePolicyId)
|
||||
}
|
||||
|
||||
return cachePolicyId, nil
|
||||
}
|
||||
@@ -720,10 +767,19 @@ func (this *NodeClusterDAO) FindNodeClusterSystemServiceParams(tx *dbs.Tx, clust
|
||||
}
|
||||
|
||||
// FindNodeClusterSystemServices 查找集群的所有服务设置
|
||||
func (this *NodeClusterDAO) FindNodeClusterSystemServices(tx *dbs.Tx, clusterId int64) (services map[string]maps.Map, err error) {
|
||||
func (this *NodeClusterDAO) FindNodeClusterSystemServices(tx *dbs.Tx, clusterId int64, cacheMap *utils.CacheMap) (services map[string]maps.Map, err error) {
|
||||
if clusterId <= 0 {
|
||||
return nil, errors.New("invalid clusterId")
|
||||
}
|
||||
|
||||
var cacheKey = this.Table + ":FindNodeClusterSystemServices:" + types.String(clusterId)
|
||||
if cacheMap != nil {
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return cache.(map[string]maps.Map), nil
|
||||
}
|
||||
}
|
||||
|
||||
service, err := this.Query(tx).
|
||||
Pk(clusterId).
|
||||
Result("systemServices").
|
||||
@@ -738,6 +794,11 @@ func (this *NodeClusterDAO) FindNodeClusterSystemServices(tx *dbs.Tx, clusterId
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, servicesMap)
|
||||
}
|
||||
|
||||
return servicesMap, nil
|
||||
}
|
||||
|
||||
@@ -815,31 +876,32 @@ func (this *NodeClusterDAO) ExistsEnabledCluster(tx *dbs.Tx, clusterId int64) (b
|
||||
Exist()
|
||||
}
|
||||
|
||||
// FindClusterTimezone 查找时区
|
||||
func (this *NodeClusterDAO) FindClusterTimezone(tx *dbs.Tx, clusterId int64, cacheMap maps.Map) (string, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = maps.Map{}
|
||||
}
|
||||
var cacheKey = this.Table + ":FindEnabledTimeZone:" + types.String(clusterId)
|
||||
var cache = cacheMap.Get(cacheKey)
|
||||
if cache != nil {
|
||||
return cache.(string), nil
|
||||
// FindClusterBasicInfo 查找集群基础信息
|
||||
func (this *NodeClusterDAO) FindClusterBasicInfo(tx *dbs.Tx, clusterId int64, cacheMap *utils.CacheMap) (*NodeCluster, error) {
|
||||
var cacheKey = this.Table + ":FindClusterBasicInfo:" + types.String(clusterId)
|
||||
if cacheMap != nil {
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return cache.(*NodeCluster), nil
|
||||
}
|
||||
}
|
||||
|
||||
timeZone, err := this.Query(tx).
|
||||
cluster, err := this.Query(tx).
|
||||
Pk(clusterId).
|
||||
Result("timeZone").
|
||||
FindStringCol("")
|
||||
if err != nil {
|
||||
return "", err
|
||||
Result("timeZone", "nodeMaxThreads", "nodeTCPMaxConnections", "cachePolicyId", "httpFirewallPolicyId", "autoOpenPorts").
|
||||
Find()
|
||||
if err != nil || cluster == nil {
|
||||
return nil, err
|
||||
}
|
||||
cacheMap[cacheKey] = timeZone
|
||||
return timeZone, nil
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, cluster)
|
||||
}
|
||||
return cluster.(*NodeCluster), nil
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *NodeClusterDAO) NotifyUpdate(tx *dbs.Tx, clusterId int64) error {
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeConfigChanged)
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeConfigChanged)
|
||||
}
|
||||
|
||||
// NotifyDNSUpdate 通知DNS更新
|
||||
|
||||
@@ -2,11 +2,13 @@ package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -35,7 +37,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 启用条目
|
||||
// EnableFirewallAction 启用条目
|
||||
func (this *NodeClusterFirewallActionDAO) EnableFirewallAction(tx *dbs.Tx, id uint32) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -44,7 +46,7 @@ func (this *NodeClusterFirewallActionDAO) EnableFirewallAction(tx *dbs.Tx, id ui
|
||||
return err
|
||||
}
|
||||
|
||||
// 禁用条目
|
||||
// DisableFirewallAction 禁用条目
|
||||
func (this *NodeClusterFirewallActionDAO) DisableFirewallAction(tx *dbs.Tx, actionId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(actionId).
|
||||
@@ -56,7 +58,7 @@ func (this *NodeClusterFirewallActionDAO) DisableFirewallAction(tx *dbs.Tx, acti
|
||||
return this.NotifyUpdate(tx, actionId)
|
||||
}
|
||||
|
||||
// 查找启用中的条目
|
||||
// FindEnabledFirewallAction 查找启用中的条目
|
||||
func (this *NodeClusterFirewallActionDAO) FindEnabledFirewallAction(tx *dbs.Tx, actionId int64) (*NodeClusterFirewallAction, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(actionId).
|
||||
@@ -68,7 +70,7 @@ func (this *NodeClusterFirewallActionDAO) FindEnabledFirewallAction(tx *dbs.Tx,
|
||||
return result.(*NodeClusterFirewallAction), err
|
||||
}
|
||||
|
||||
// 根据主键查找名称
|
||||
// FindFirewallActionName 根据主键查找名称
|
||||
func (this *NodeClusterFirewallActionDAO) FindFirewallActionName(tx *dbs.Tx, id uint32) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -76,7 +78,7 @@ func (this *NodeClusterFirewallActionDAO) FindFirewallActionName(tx *dbs.Tx, id
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// 创建动作
|
||||
// CreateFirewallAction 创建动作
|
||||
func (this *NodeClusterFirewallActionDAO) CreateFirewallAction(tx *dbs.Tx, adminId int64, clusterId int64, name string, eventLevel, actionType firewallconfigs.FirewallActionType, params maps.Map) (int64, error) {
|
||||
if params == nil {
|
||||
params = maps.Map{}
|
||||
@@ -101,7 +103,7 @@ func (this *NodeClusterFirewallActionDAO) CreateFirewallAction(tx *dbs.Tx, admin
|
||||
return actionId, nil
|
||||
}
|
||||
|
||||
// 修改动作
|
||||
// UpdateFirewallAction 修改动作
|
||||
func (this *NodeClusterFirewallActionDAO) UpdateFirewallAction(tx *dbs.Tx, actionId int64, name string, eventLevel string, actionType firewallconfigs.FirewallActionType, params maps.Map) error {
|
||||
if actionId <= 0 {
|
||||
return errors.New("invalid actionId")
|
||||
@@ -124,17 +126,33 @@ func (this *NodeClusterFirewallActionDAO) UpdateFirewallAction(tx *dbs.Tx, actio
|
||||
return this.NotifyUpdate(tx, actionId)
|
||||
}
|
||||
|
||||
// 查找所有集群的动作
|
||||
func (this *NodeClusterFirewallActionDAO) FindAllEnabledFirewallActions(tx *dbs.Tx, clusterId int64) (result []*NodeClusterFirewallAction, err error) {
|
||||
// FindAllEnabledFirewallActions 查找所有集群的动作
|
||||
func (this *NodeClusterFirewallActionDAO) FindAllEnabledFirewallActions(tx *dbs.Tx, clusterId int64, cacheMap *utils.CacheMap) (result []*NodeClusterFirewallAction, err error) {
|
||||
var cacheKey = this.Table + ":FindAllEnabledFirewallActions:" + types.String(clusterId)
|
||||
if cacheMap != nil {
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return cache.([]*NodeClusterFirewallAction), nil
|
||||
}
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Attr("clusterId", clusterId).
|
||||
State(NodeClusterFirewallActionStateEnabled).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, result)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 组合配置
|
||||
// ComposeFirewallActionConfig 组合配置
|
||||
func (this *NodeClusterFirewallActionDAO) ComposeFirewallActionConfig(tx *dbs.Tx, action *NodeClusterFirewallAction) (*firewallconfigs.FirewallActionConfig, error) {
|
||||
if action == nil {
|
||||
return nil, nil
|
||||
@@ -153,7 +171,7 @@ func (this *NodeClusterFirewallActionDAO) ComposeFirewallActionConfig(tx *dbs.Tx
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// 计算动作数量
|
||||
// CountAllEnabledFirewallActions 计算动作数量
|
||||
func (this *NodeClusterFirewallActionDAO) CountAllEnabledFirewallActions(tx *dbs.Tx, clusterId int64) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(NodeClusterFirewallActionStateEnabled).
|
||||
@@ -161,7 +179,7 @@ func (this *NodeClusterFirewallActionDAO) CountAllEnabledFirewallActions(tx *dbs
|
||||
Count()
|
||||
}
|
||||
|
||||
// 通知更新
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *NodeClusterFirewallActionDAO) NotifyUpdate(tx *dbs.Tx, actionId int64) error {
|
||||
clusterId, err := this.Query(tx).
|
||||
Pk(actionId).
|
||||
|
||||
@@ -2,10 +2,12 @@ package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -112,16 +114,32 @@ func (this *NodeClusterMetricItemDAO) FindAllClusterItems(tx *dbs.Tx, clusterId
|
||||
}
|
||||
|
||||
// FindAllClusterItemIds 查找某个集群的指标Ids
|
||||
func (this *NodeClusterMetricItemDAO) FindAllClusterItemIds(tx *dbs.Tx, clusterId int64) (result []int64, err error) {
|
||||
func (this *NodeClusterMetricItemDAO) FindAllClusterItemIds(tx *dbs.Tx, clusterId int64, cacheMap *utils.CacheMap) (result []int64, err error) {
|
||||
var cacheKey = this.Table + ":FindAllClusterItemIds:" + types.String(clusterId)
|
||||
if cacheMap != nil {
|
||||
cache, ok := cacheMap.Get(cacheKey)
|
||||
if ok {
|
||||
return cache.([]int64), nil
|
||||
}
|
||||
}
|
||||
|
||||
ones, err := this.Query(tx).
|
||||
Attr("clusterId", clusterId).
|
||||
State(NodeClusterMetricItemStateEnabled).
|
||||
Result("itemId").
|
||||
DescPk().
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, one := range ones {
|
||||
result = append(result, int64(one.(*NodeClusterMetricItem).ItemId))
|
||||
}
|
||||
|
||||
if cacheMap != nil {
|
||||
cacheMap.Put(cacheKey, result)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -159,5 +177,5 @@ func (this *NodeClusterMetricItemDAO) ExistsClusterItem(tx *dbs.Tx, clusterId in
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *NodeClusterMetricItemDAO) NotifyUpdate(tx *dbs.Tx, clusterId int64) error {
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeConfigChanged)
|
||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeConfigChanged)
|
||||
}
|
||||
|
||||
@@ -2,59 +2,65 @@ package models
|
||||
|
||||
// NodeCluster 节点集群
|
||||
type NodeCluster struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
UseAllAPINodes uint8 `field:"useAllAPINodes"` // 是否使用所有API节点
|
||||
ApiNodes string `field:"apiNodes"` // 使用的API节点
|
||||
InstallDir string `field:"installDir"` // 安装目录
|
||||
Order uint32 `field:"order"` // 排序
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
GrantId uint32 `field:"grantId"` // 默认认证方式
|
||||
State uint8 `field:"state"` // 状态
|
||||
AutoRegister uint8 `field:"autoRegister"` // 是否开启自动注册
|
||||
UniqueId string `field:"uniqueId"` // 唯一ID
|
||||
Secret string `field:"secret"` // 密钥
|
||||
HealthCheck string `field:"healthCheck"` // 健康检查
|
||||
DnsName string `field:"dnsName"` // DNS名称
|
||||
DnsDomainId uint32 `field:"dnsDomainId"` // 域名ID
|
||||
Dns string `field:"dns"` // DNS配置
|
||||
Toa string `field:"toa"` // TOA配置
|
||||
CachePolicyId uint32 `field:"cachePolicyId"` // 缓存策略ID
|
||||
HttpFirewallPolicyId uint32 `field:"httpFirewallPolicyId"` // WAF策略ID
|
||||
AccessLog string `field:"accessLog"` // 访问日志设置
|
||||
SystemServices string `field:"systemServices"` // 系统服务设置
|
||||
TimeZone string `field:"timeZone"` // 时区
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 名称
|
||||
UseAllAPINodes uint8 `field:"useAllAPINodes"` // 是否使用所有API节点
|
||||
ApiNodes string `field:"apiNodes"` // 使用的API节点
|
||||
InstallDir string `field:"installDir"` // 安装目录
|
||||
Order uint32 `field:"order"` // 排序
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
GrantId uint32 `field:"grantId"` // 默认认证方式
|
||||
State uint8 `field:"state"` // 状态
|
||||
AutoRegister uint8 `field:"autoRegister"` // 是否开启自动注册
|
||||
UniqueId string `field:"uniqueId"` // 唯一ID
|
||||
Secret string `field:"secret"` // 密钥
|
||||
HealthCheck string `field:"healthCheck"` // 健康检查
|
||||
DnsName string `field:"dnsName"` // DNS名称
|
||||
DnsDomainId uint32 `field:"dnsDomainId"` // 域名ID
|
||||
Dns string `field:"dns"` // DNS配置
|
||||
Toa string `field:"toa"` // TOA配置
|
||||
CachePolicyId uint32 `field:"cachePolicyId"` // 缓存策略ID
|
||||
HttpFirewallPolicyId uint32 `field:"httpFirewallPolicyId"` // WAF策略ID
|
||||
AccessLog string `field:"accessLog"` // 访问日志设置
|
||||
SystemServices string `field:"systemServices"` // 系统服务设置
|
||||
TimeZone string `field:"timeZone"` // 时区
|
||||
NodeMaxThreads uint32 `field:"nodeMaxThreads"` // 节点最大线程数
|
||||
NodeTCPMaxConnections uint32 `field:"nodeTCPMaxConnections"` // TCP最大连接数
|
||||
AutoOpenPorts uint8 `field:"autoOpenPorts"` // 是否自动尝试开放端口
|
||||
}
|
||||
|
||||
type NodeClusterOperator struct {
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
UseAllAPINodes interface{} // 是否使用所有API节点
|
||||
ApiNodes interface{} // 使用的API节点
|
||||
InstallDir interface{} // 安装目录
|
||||
Order interface{} // 排序
|
||||
CreatedAt interface{} // 创建时间
|
||||
GrantId interface{} // 默认认证方式
|
||||
State interface{} // 状态
|
||||
AutoRegister interface{} // 是否开启自动注册
|
||||
UniqueId interface{} // 唯一ID
|
||||
Secret interface{} // 密钥
|
||||
HealthCheck interface{} // 健康检查
|
||||
DnsName interface{} // DNS名称
|
||||
DnsDomainId interface{} // 域名ID
|
||||
Dns interface{} // DNS配置
|
||||
Toa interface{} // TOA配置
|
||||
CachePolicyId interface{} // 缓存策略ID
|
||||
HttpFirewallPolicyId interface{} // WAF策略ID
|
||||
AccessLog interface{} // 访问日志设置
|
||||
SystemServices interface{} // 系统服务设置
|
||||
TimeZone interface{} // 时区
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
UserId interface{} // 用户ID
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
UseAllAPINodes interface{} // 是否使用所有API节点
|
||||
ApiNodes interface{} // 使用的API节点
|
||||
InstallDir interface{} // 安装目录
|
||||
Order interface{} // 排序
|
||||
CreatedAt interface{} // 创建时间
|
||||
GrantId interface{} // 默认认证方式
|
||||
State interface{} // 状态
|
||||
AutoRegister interface{} // 是否开启自动注册
|
||||
UniqueId interface{} // 唯一ID
|
||||
Secret interface{} // 密钥
|
||||
HealthCheck interface{} // 健康检查
|
||||
DnsName interface{} // DNS名称
|
||||
DnsDomainId interface{} // 域名ID
|
||||
Dns interface{} // DNS配置
|
||||
Toa interface{} // TOA配置
|
||||
CachePolicyId interface{} // 缓存策略ID
|
||||
HttpFirewallPolicyId interface{} // WAF策略ID
|
||||
AccessLog interface{} // 访问日志设置
|
||||
SystemServices interface{} // 系统服务设置
|
||||
TimeZone interface{} // 时区
|
||||
NodeMaxThreads interface{} // 节点最大线程数
|
||||
NodeTCPMaxConnections interface{} // TCP最大连接数
|
||||
AutoOpenPorts interface{} // 是否自动尝试开放端口
|
||||
}
|
||||
|
||||
func NewNodeClusterOperator() *NodeClusterOperator {
|
||||
|
||||
@@ -315,7 +315,7 @@ func (this *NodeDAO) ListEnabledNodesMatch(tx *dbs.Tx,
|
||||
case configutils.BoolStateAll:
|
||||
// 所有
|
||||
case configutils.BoolStateYes:
|
||||
query.Where("JSON_EXTRACT(status, '$.isActive') AND UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')<=60")
|
||||
query.Where("isActive AND UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')<=60")
|
||||
case configutils.BoolStateNo:
|
||||
query.Where("(status IS NULL OR NOT JSON_EXTRACT(status, '$.isActive') OR UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')>60)")
|
||||
}
|
||||
@@ -518,11 +518,11 @@ func (this *NodeDAO) FindAllEnabledNodeIdsWithClusterId(tx *dbs.Tx, clusterId in
|
||||
func (this *NodeDAO) FindAllInactiveNodesWithClusterId(tx *dbs.Tx, clusterId int64) (result []*Node, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(NodeStateEnabled).
|
||||
Result("id", "name", "status").
|
||||
Attr("clusterId", clusterId).
|
||||
Attr("isOn", true). // 只监控启用的节点
|
||||
Attr("isInstalled", true). // 只监控已经安装的节点
|
||||
Attr("isActive", true). // 当前已经在线的
|
||||
Where("(status IS NULL OR (JSON_EXTRACT(status, '$.isActive')=false AND UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')>10) OR UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')>120)").
|
||||
Attr("isActive", false).
|
||||
Result("id", "name").
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
@@ -569,7 +569,7 @@ func (this *NodeDAO) CountAllEnabledNodesMatch(tx *dbs.Tx,
|
||||
case configutils.BoolStateAll:
|
||||
// 所有
|
||||
case configutils.BoolStateYes:
|
||||
query.Where("JSON_EXTRACT(status, '$.isActive') AND UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')<=60")
|
||||
query.Where("isActive AND UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')<=60")
|
||||
case configutils.BoolStateNo:
|
||||
query.Where("(status IS NULL OR NOT JSON_EXTRACT(status, '$.isActive') OR UNIX_TIMESTAMP()-JSON_EXTRACT(status, '$.updatedAt')>60)")
|
||||
}
|
||||
@@ -597,6 +597,7 @@ func (this *NodeDAO) CountAllEnabledNodesMatch(tx *dbs.Tx,
|
||||
func (this *NodeDAO) UpdateNodeStatus(tx *dbs.Tx, nodeId int64, statusJSON []byte) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(nodeId).
|
||||
Set("isActive", true).
|
||||
Set("status", string(statusJSON)).
|
||||
Update()
|
||||
return err
|
||||
@@ -701,7 +702,11 @@ func (this *NodeDAO) UpdateNodeInstallStatus(tx *dbs.Tx, nodeId int64, status *N
|
||||
|
||||
// ComposeNodeConfig 组合配置
|
||||
// TODO 提升运行速度
|
||||
func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap maps.Map) (*nodeconfigs.NodeConfig, error) {
|
||||
func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils.CacheMap) (*nodeconfigs.NodeConfig, error) {
|
||||
if cacheMap == nil {
|
||||
cacheMap = utils.NewCacheMap()
|
||||
}
|
||||
|
||||
node, err := this.FindEnabledNode(tx, nodeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -722,6 +727,13 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap maps.M
|
||||
RegionId: int64(node.RegionId),
|
||||
}
|
||||
|
||||
// API节点IP
|
||||
apiNodeIPs, err := SharedAPINodeDAO.FindAllEnabledAPIAccessIPs(tx, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.AllowedIPs = append(config.AllowedIPs, apiNodeIPs...)
|
||||
|
||||
// 获取所有的服务
|
||||
servers, err := SharedServerDAO.FindAllEnabledServersWithNode(tx, int64(node.Id))
|
||||
if err != nil {
|
||||
@@ -729,7 +741,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap maps.M
|
||||
}
|
||||
|
||||
for _, server := range servers {
|
||||
serverConfig, err := SharedServerDAO.ComposeServerConfig(tx, server, cacheMap)
|
||||
serverConfig, err := SharedServerDAO.ComposeServerConfig(tx, server, cacheMap, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -745,10 +757,19 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap maps.M
|
||||
|
||||
// 全局设置
|
||||
// TODO 根据用户的不同读取不同的全局设置
|
||||
settingJSON, err := SharedSysSettingDAO.ReadSetting(tx, systemconfigs.SettingCodeServerGlobalConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var settingCacheKey = "SharedSysSettingDAO:" + systemconfigs.SettingCodeServerGlobalConfig
|
||||
settingJSONCache, ok := cacheMap.Get(settingCacheKey)
|
||||
var settingJSON = []byte{}
|
||||
if ok {
|
||||
settingJSON = settingJSONCache.([]byte)
|
||||
} else {
|
||||
settingJSON, err = SharedSysSettingDAO.ReadSetting(tx, systemconfigs.SettingCodeServerGlobalConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cacheMap.Put(settingCacheKey, settingJSON)
|
||||
}
|
||||
|
||||
if len(settingJSON) > 0 {
|
||||
globalConfig := &serverconfigs.GlobalConfig{}
|
||||
err = json.Unmarshal(settingJSON, globalConfig)
|
||||
@@ -761,11 +782,17 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap maps.M
|
||||
var primaryClusterId = int64(node.ClusterId)
|
||||
var clusterIds = []int64{primaryClusterId}
|
||||
clusterIds = append(clusterIds, node.DecodeSecondaryClusterIds()...)
|
||||
var clusterIndex = 0
|
||||
for _, clusterId := range clusterIds {
|
||||
httpFirewallPolicyId, err := SharedNodeClusterDAO.FindClusterHTTPFirewallPolicyId(tx, clusterId, cacheMap)
|
||||
nodeCluster, err := SharedNodeClusterDAO.FindClusterBasicInfo(tx, clusterId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if nodeCluster == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var httpFirewallPolicyId = int64(nodeCluster.HttpFirewallPolicyId)
|
||||
if httpFirewallPolicyId > 0 {
|
||||
firewallPolicy, err := SharedHTTPFirewallPolicyDAO.ComposeFirewallPolicy(tx, httpFirewallPolicyId, cacheMap)
|
||||
if err != nil {
|
||||
@@ -777,10 +804,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap maps.M
|
||||
}
|
||||
|
||||
// 缓存策略
|
||||
httpCachePolicyId, err := SharedNodeClusterDAO.FindClusterHTTPCachePolicyId(tx, clusterId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var httpCachePolicyId = int64(nodeCluster.CachePolicyId)
|
||||
if httpCachePolicyId > 0 {
|
||||
cachePolicy, err := SharedHTTPCachePolicyDAO.ComposeCachePolicy(tx, httpCachePolicyId, cacheMap)
|
||||
if err != nil {
|
||||
@@ -792,13 +816,21 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap maps.M
|
||||
}
|
||||
|
||||
// 时区
|
||||
timeZone, err := SharedNodeClusterDAO.FindClusterTimezone(tx, clusterId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if len(config.TimeZone) == 0 {
|
||||
var timeZone = nodeCluster.TimeZone
|
||||
if len(timeZone) > 0 {
|
||||
config.TimeZone = timeZone
|
||||
}
|
||||
}
|
||||
if len(timeZone) > 0 {
|
||||
config.TimeZone = timeZone
|
||||
|
||||
// 最大线程数、TCP连接数
|
||||
if clusterIndex == 0 {
|
||||
config.MaxThreads = int(nodeCluster.NodeMaxThreads)
|
||||
config.TCPMaxConnections = int(nodeCluster.NodeTCPMaxConnections)
|
||||
config.AutoOpenPorts = nodeCluster.AutoOpenPorts == 1
|
||||
}
|
||||
|
||||
clusterIndex++
|
||||
}
|
||||
|
||||
// 缓存最大容量设置
|
||||
@@ -825,14 +857,14 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap maps.M
|
||||
}
|
||||
|
||||
// TOA
|
||||
toaConfig, err := SharedNodeClusterDAO.FindClusterTOAConfig(tx, primaryClusterId)
|
||||
toaConfig, err := SharedNodeClusterDAO.FindClusterTOAConfig(tx, primaryClusterId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.TOA = toaConfig
|
||||
|
||||
// 系统服务
|
||||
services, err := SharedNodeClusterDAO.FindNodeClusterSystemServices(tx, primaryClusterId)
|
||||
services, err := SharedNodeClusterDAO.FindNodeClusterSystemServices(tx, primaryClusterId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -841,7 +873,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap maps.M
|
||||
}
|
||||
|
||||
// 防火墙动作
|
||||
actions, err := SharedNodeClusterFirewallActionDAO.FindAllEnabledFirewallActions(tx, primaryClusterId)
|
||||
actions, err := SharedNodeClusterFirewallActionDAO.FindAllEnabledFirewallActions(tx, primaryClusterId, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -856,7 +888,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap maps.M
|
||||
}
|
||||
|
||||
// 集群指标
|
||||
metricItemIds, err := SharedNodeClusterMetricItemDAO.FindAllClusterItemIds(tx, int64(node.ClusterId))
|
||||
metricItemIds, err := SharedNodeClusterMetricItemDAO.FindAllClusterItemIds(tx, int64(node.ClusterId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -872,7 +904,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap maps.M
|
||||
}
|
||||
|
||||
// 公用指标
|
||||
publicMetricItems, err := SharedMetricItemDAO.FindAllPublicItems(tx, serverconfigs.MetricItemCategoryHTTP)
|
||||
publicMetricItems, err := SharedMetricItemDAO.FindAllPublicItems(tx, serverconfigs.MetricItemCategoryHTTP, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -885,6 +917,18 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap maps.M
|
||||
|
||||
config.MetricItems = metricItems
|
||||
|
||||
// 产品
|
||||
adminUIConfig, err := SharedSysSettingDAO.ReadAdminUIConfig(tx, cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if adminUIConfig != nil {
|
||||
config.ProductConfig = &nodeconfigs.ProductConfig{
|
||||
Name: adminUIConfig.ProductName,
|
||||
Version: adminUIConfig.Version,
|
||||
}
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
@@ -1427,7 +1471,7 @@ func (this *NodeDAO) NotifyUpdate(tx *dbs.Tx, nodeId int64) error {
|
||||
return err
|
||||
}
|
||||
if clusterId > 0 {
|
||||
return SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, NodeTaskTypeConfigChanged)
|
||||
return SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, 0, NodeTaskTypeConfigChanged, 0)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -46,13 +46,13 @@ func TestNodeDAO_ComposeNodeConfig(t *testing.T) {
|
||||
}()
|
||||
|
||||
var tx *dbs.Tx
|
||||
var cacheMap = maps.Map{}
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
nodeConfig, err := SharedNodeDAO.ComposeNodeConfig(tx, 48, cacheMap)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(len(nodeConfig.Servers), "servers")
|
||||
t.Log(len(cacheMap), "items")
|
||||
t.Log(cacheMap.Len(), "items")
|
||||
|
||||
// old: 77ms => new: 56ms
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ func (this *NodeGrantDAO) FindNodeGrantName(tx *dbs.Tx, id uint32) (string, erro
|
||||
}
|
||||
|
||||
// CreateGrant 创建认证信息
|
||||
func (this *NodeGrantDAO) CreateGrant(tx *dbs.Tx, adminId int64, name string, method string, username string, password string, privateKey string, description string, nodeId int64) (grantId int64, err error) {
|
||||
func (this *NodeGrantDAO) CreateGrant(tx *dbs.Tx, adminId int64, name string, method string, username string, password string, privateKey string, passphrase string, description string, nodeId int64, su bool) (grantId int64, err error) {
|
||||
op := NewNodeGrantOperator()
|
||||
op.AdminId = adminId
|
||||
op.Name = name
|
||||
@@ -83,11 +83,12 @@ func (this *NodeGrantDAO) CreateGrant(tx *dbs.Tx, adminId int64, name string, me
|
||||
case "user":
|
||||
op.Username = username
|
||||
op.Password = password
|
||||
op.Su = false // TODO 需要做到前端可以配置
|
||||
case "privateKey":
|
||||
op.Username = username
|
||||
op.PrivateKey = privateKey
|
||||
op.Passphrase = passphrase
|
||||
}
|
||||
op.Su = su
|
||||
op.Description = description
|
||||
op.NodeId = nodeId
|
||||
op.State = NodeGrantStateEnabled
|
||||
@@ -96,7 +97,7 @@ func (this *NodeGrantDAO) CreateGrant(tx *dbs.Tx, adminId int64, name string, me
|
||||
}
|
||||
|
||||
// UpdateGrant 修改认证信息
|
||||
func (this *NodeGrantDAO) UpdateGrant(tx *dbs.Tx, grantId int64, name string, method string, username string, password string, privateKey string, description string, nodeId int64) error {
|
||||
func (this *NodeGrantDAO) UpdateGrant(tx *dbs.Tx, grantId int64, name string, method string, username string, password string, privateKey string, passphrase string, description string, nodeId int64, su bool) error {
|
||||
if grantId <= 0 {
|
||||
return errors.New("invalid grantId")
|
||||
}
|
||||
@@ -110,11 +111,12 @@ func (this *NodeGrantDAO) UpdateGrant(tx *dbs.Tx, grantId int64, name string, me
|
||||
case "user":
|
||||
op.Username = username
|
||||
op.Password = password
|
||||
op.Su = false // TODO 需要做到前端可以配置
|
||||
case "privateKey":
|
||||
op.Username = username
|
||||
op.PrivateKey = privateKey
|
||||
op.Passphrase = passphrase
|
||||
}
|
||||
op.Su = su
|
||||
op.Description = description
|
||||
op.NodeId = nodeId
|
||||
err := this.Save(tx, op)
|
||||
|
||||
@@ -9,7 +9,8 @@ type NodeGrant struct {
|
||||
Username string `field:"username"` // 用户名
|
||||
Password string `field:"password"` // 密码
|
||||
Su uint8 `field:"su"` // 是否需要su
|
||||
PrivateKey string `field:"privateKey"` // 密钥
|
||||
PrivateKey string `field:"privateKey"` // 私钥
|
||||
Passphrase string `field:"passphrase"` // 私钥密码
|
||||
Description string `field:"description"` // 备注
|
||||
NodeId uint32 `field:"nodeId"` // 专有节点
|
||||
Role string `field:"role"` // 角色
|
||||
@@ -25,7 +26,8 @@ type NodeGrantOperator struct {
|
||||
Username interface{} // 用户名
|
||||
Password interface{} // 密码
|
||||
Su interface{} // 是否需要su
|
||||
PrivateKey interface{} // 密钥
|
||||
PrivateKey interface{} // 私钥
|
||||
Passphrase interface{} // 私钥密码
|
||||
Description interface{} // 备注
|
||||
NodeId interface{} // 专有节点
|
||||
Role interface{} // 角色
|
||||
|
||||
@@ -102,8 +102,24 @@ func (this *NodeIPAddressDAO) FindAddressName(tx *dbs.Tx, id int64) (string, err
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// FindAddressIsHealthy 判断IP地址是否健康
|
||||
func (this *NodeIPAddressDAO) FindAddressIsHealthy(tx *dbs.Tx, addressId int64) (isHealthy bool, err error) {
|
||||
if addressId <= 0 {
|
||||
return false, nil
|
||||
}
|
||||
one, err := this.Query(tx).
|
||||
Pk(addressId).
|
||||
Result("isHealthy").
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return false, err
|
||||
}
|
||||
var addr = one.(*NodeIPAddress)
|
||||
return addr.IsHealthy == 1, nil
|
||||
}
|
||||
|
||||
// CreateAddress 创建IP地址
|
||||
func (this *NodeIPAddressDAO) CreateAddress(tx *dbs.Tx, adminId int64, nodeId int64, role nodeconfigs.NodeRole, name string, ip string, canAccess bool, isUp bool) (addressId int64, err error) {
|
||||
func (this *NodeIPAddressDAO) CreateAddress(tx *dbs.Tx, adminId int64, nodeId int64, role nodeconfigs.NodeRole, name string, ip string, canAccess bool, isUp bool, groupId int64) (addressId int64, err error) {
|
||||
if len(role) == 0 {
|
||||
role = nodeconfigs.NodeRoleNode
|
||||
}
|
||||
@@ -115,6 +131,7 @@ func (this *NodeIPAddressDAO) CreateAddress(tx *dbs.Tx, adminId int64, nodeId in
|
||||
op.Ip = ip
|
||||
op.CanAccess = canAccess
|
||||
op.IsUp = isUp
|
||||
op.GroupId = groupId
|
||||
|
||||
op.State = NodeIPAddressStateEnabled
|
||||
addressId, err = this.SaveInt64(tx, op)
|
||||
@@ -216,11 +233,11 @@ func (this *NodeIPAddressDAO) FindAllEnabledAddressesWithNode(tx *dbs.Tx, nodeId
|
||||
}
|
||||
|
||||
// FindFirstNodeAccessIPAddress 查找节点的第一个可访问的IP地址
|
||||
func (this *NodeIPAddressDAO) FindFirstNodeAccessIPAddress(tx *dbs.Tx, nodeId int64, role nodeconfigs.NodeRole) (string, error) {
|
||||
func (this *NodeIPAddressDAO) FindFirstNodeAccessIPAddress(tx *dbs.Tx, nodeId int64, role nodeconfigs.NodeRole) (ip string, addrId int64, err error) {
|
||||
if len(role) == 0 {
|
||||
role = nodeconfigs.NodeRoleNode
|
||||
}
|
||||
return this.Query(tx).
|
||||
one, err := this.Query(tx).
|
||||
Attr("nodeId", nodeId).
|
||||
Attr("role", role).
|
||||
State(NodeIPAddressStateEnabled).
|
||||
@@ -229,8 +246,17 @@ func (this *NodeIPAddressDAO) FindFirstNodeAccessIPAddress(tx *dbs.Tx, nodeId in
|
||||
Attr("isUp", true).
|
||||
Desc("order").
|
||||
AscPk().
|
||||
Result("ip").
|
||||
FindStringCol("")
|
||||
Result("id", "ip").
|
||||
Find()
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
if one == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var addr = one.(*NodeIPAddress)
|
||||
return addr.Ip, int64(addr.Id), nil
|
||||
}
|
||||
|
||||
// FindFirstNodeAccessIPAddressId 查找节点的第一个可访问的IP地址ID
|
||||
@@ -400,6 +426,10 @@ func (this *NodeIPAddressDAO) UpdateAddressIsUp(tx *dbs.Tx, addressId int64, isU
|
||||
var err = this.Query(tx).
|
||||
Pk(addressId).
|
||||
Set("isUp", isUp).
|
||||
Set("countUp", 0).
|
||||
Set("countDown", 0).
|
||||
Set("backupIP", "").
|
||||
Set("backupThresholdId", 0).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -413,6 +443,7 @@ func (this *NodeIPAddressDAO) UpdateAddressBackupIP(tx *dbs.Tx, addressId int64,
|
||||
return errors.New("invalid addressId")
|
||||
}
|
||||
var op = NewNodeIPAddressOperator()
|
||||
op.IsUp = true // IP必须在线备用IP才会有用
|
||||
op.Id = addressId
|
||||
op.BackupThresholdId = thresholdId
|
||||
op.BackupIP = ip
|
||||
@@ -423,6 +454,71 @@ func (this *NodeIPAddressDAO) UpdateAddressBackupIP(tx *dbs.Tx, addressId int64,
|
||||
return this.NotifyUpdate(tx, addressId)
|
||||
}
|
||||
|
||||
// UpdateAddressHealthCount 计算IP健康状态
|
||||
func (this *NodeIPAddressDAO) UpdateAddressHealthCount(tx *dbs.Tx, addrId int64, isUp bool, maxUp int, maxDown int) (changed bool, err error) {
|
||||
if addrId <= 0 {
|
||||
return false, errors.New("invalid address id")
|
||||
}
|
||||
one, err := this.Query(tx).
|
||||
Pk(addrId).
|
||||
Result("isHealthy", "countUp", "countDown").
|
||||
Find()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if one == nil {
|
||||
return false, nil
|
||||
}
|
||||
oldIsHealthy := one.(*NodeIPAddress).IsHealthy == 1
|
||||
|
||||
// 如果新老状态一致,则不做任何事情
|
||||
if oldIsHealthy == isUp {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
countUp := int(one.(*NodeIPAddress).CountUp)
|
||||
countDown := int(one.(*NodeIPAddress).CountDown)
|
||||
|
||||
op := NewNodeIPAddressOperator()
|
||||
op.Id = addrId
|
||||
|
||||
if isUp {
|
||||
countUp++
|
||||
countDown = 0
|
||||
|
||||
if countUp >= maxUp {
|
||||
changed = true
|
||||
//op.IsUp = true
|
||||
op.IsHealthy = true
|
||||
}
|
||||
} else {
|
||||
countDown++
|
||||
countUp = 0
|
||||
|
||||
if countDown >= maxDown {
|
||||
changed = true
|
||||
//op.IsUp = false
|
||||
op.IsHealthy = false
|
||||
}
|
||||
}
|
||||
|
||||
op.CountUp = countUp
|
||||
op.CountDown = countDown
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if changed {
|
||||
err = this.NotifyUpdate(tx, addrId)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *NodeIPAddressDAO) NotifyUpdate(tx *dbs.Tx, addressId int64) error {
|
||||
address, err := this.Query(tx).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build community
|
||||
// +build community
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package models
|
||||
|
||||
|
||||
@@ -40,3 +40,25 @@ func TestNodeIPAddressDAO_LoopTasks(t *testing.T) {
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
|
||||
func TestNodeIPAddressDAO_FindAddressIsHealthy(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
isHealthy, err := SharedNodeIPAddressDAO.FindAddressIsHealthy(tx, 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("isHealthy:", isHealthy)
|
||||
}
|
||||
|
||||
func TestNodeIPAddressDAO_UpdateAddressHealthCount(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
isChanged, err := SharedNodeIPAddressDAO.UpdateAddressHealthCount(tx, 1, true, 3, 3)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("isChanged:", isChanged)
|
||||
}
|
||||
|
||||
44
internal/db/models/node_ip_address_group_dao.go
Normal file
44
internal/db/models/node_ip_address_group_dao.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
type NodeIPAddressGroupDAO dbs.DAO
|
||||
|
||||
func NewNodeIPAddressGroupDAO() *NodeIPAddressGroupDAO {
|
||||
return dbs.NewDAO(&NodeIPAddressGroupDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNodeIPAddressGroups",
|
||||
Model: new(NodeIPAddressGroup),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NodeIPAddressGroupDAO)
|
||||
}
|
||||
|
||||
var SharedNodeIPAddressGroupDAO *NodeIPAddressGroupDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNodeIPAddressGroupDAO = NewNodeIPAddressGroupDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// FindNodeIPAddressGroupName 根据主键查找名称
|
||||
func (this *NodeIPAddressGroupDAO) FindNodeIPAddressGroupName(tx *dbs.Tx, id uint32) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// CreateGroup 创建分组
|
||||
func (this *NodeIPAddressGroupDAO) CreateGroup(tx *dbs.Tx, name string, value string) (int64, error) {
|
||||
var op = NewNodeIPAddressGroupOperator()
|
||||
op.Name = name
|
||||
op.Value = value
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
6
internal/db/models/node_ip_address_group_dao_test.go
Normal file
6
internal/db/models/node_ip_address_group_dao_test.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
18
internal/db/models/node_ip_address_group_model.go
Normal file
18
internal/db/models/node_ip_address_group_model.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package models
|
||||
|
||||
// NodeIPAddressGroup IP地址分组
|
||||
type NodeIPAddressGroup struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Name string `field:"name"` // 分组名
|
||||
Value string `field:"value"` // IP值
|
||||
}
|
||||
|
||||
type NodeIPAddressGroupOperator struct {
|
||||
Id interface{} // ID
|
||||
Name interface{} // 分组名
|
||||
Value interface{} // IP值
|
||||
}
|
||||
|
||||
func NewNodeIPAddressGroupOperator() *NodeIPAddressGroupOperator {
|
||||
return &NodeIPAddressGroupOperator{}
|
||||
}
|
||||
1
internal/db/models/node_ip_address_group_model_ext.go
Normal file
1
internal/db/models/node_ip_address_group_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package models
|
||||
@@ -5,6 +5,7 @@ type NodeIPAddress struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
NodeId uint32 `field:"nodeId"` // 节点ID
|
||||
Role string `field:"role"` // 节点角色
|
||||
GroupId uint32 `field:"groupId"` // 所属分组ID
|
||||
Name string `field:"name"` // 名称
|
||||
Ip string `field:"ip"` // IP地址
|
||||
Description string `field:"description"` // 描述
|
||||
@@ -13,16 +14,20 @@ type NodeIPAddress struct {
|
||||
CanAccess uint8 `field:"canAccess"` // 是否可以访问
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
IsUp uint8 `field:"isUp"` // 是否上线
|
||||
IsHealthy uint8 `field:"isHealthy"` // 是否健康
|
||||
Thresholds string `field:"thresholds"` // 上线阈值
|
||||
Connectivity string `field:"connectivity"` // 连通性状态
|
||||
BackupIP string `field:"backupIP"` // 备用IP
|
||||
BackupThresholdId uint32 `field:"backupThresholdId"` // 触发备用IP的阈值
|
||||
CountUp uint32 `field:"countUp"` // UP状态次数
|
||||
CountDown uint32 `field:"countDown"` // DOWN状态次数
|
||||
}
|
||||
|
||||
type NodeIPAddressOperator struct {
|
||||
Id interface{} // ID
|
||||
NodeId interface{} // 节点ID
|
||||
Role interface{} // 节点角色
|
||||
GroupId interface{} // 所属分组ID
|
||||
Name interface{} // 名称
|
||||
Ip interface{} // IP地址
|
||||
Description interface{} // 描述
|
||||
@@ -31,10 +36,13 @@ type NodeIPAddressOperator struct {
|
||||
CanAccess interface{} // 是否可以访问
|
||||
IsOn interface{} // 是否启用
|
||||
IsUp interface{} // 是否上线
|
||||
IsHealthy interface{} // 是否健康
|
||||
Thresholds interface{} // 上线阈值
|
||||
Connectivity interface{} // 连通性状态
|
||||
BackupIP interface{} // 备用IP
|
||||
BackupThresholdId interface{} // 触发备用IP的阈值
|
||||
CountUp interface{} // UP状态次数
|
||||
CountDown interface{} // DOWN状态次数
|
||||
}
|
||||
|
||||
func NewNodeIPAddressOperator() *NodeIPAddressOperator {
|
||||
|
||||
@@ -41,8 +41,25 @@ func init() {
|
||||
}
|
||||
|
||||
// CreateLog 创建日志
|
||||
func (this *NodeLogDAO) CreateLog(tx *dbs.Tx, nodeRole nodeconfigs.NodeRole, nodeId int64, serverId int64, originId int64, level string, tag string, description string, createdAt int64) error {
|
||||
hash := stringutil.Md5(nodeRole + "@" + types.String(nodeId) + "@" + types.String(serverId) + "@" + types.String(originId) + "@" + level + "@" + tag + "@" + description)
|
||||
func (this *NodeLogDAO) CreateLog(tx *dbs.Tx, nodeRole nodeconfigs.NodeRole, nodeId int64, serverId int64, originId int64, level string, tag string, description string, createdAt int64, logType string, paramsJSON []byte) error {
|
||||
// 修复以前同样的日志
|
||||
if nodeId > 0 && level == "success" && len(logType) > 0 && len(paramsJSON) > 0 {
|
||||
err := this.Query(tx).
|
||||
Attr("nodeId", nodeId).
|
||||
Attr("serverId", serverId).
|
||||
Attr("type", logType).
|
||||
Attr("level", "error").
|
||||
Attr("isFixed", 0).
|
||||
JSONContains("params", string(paramsJSON)).
|
||||
Set("isFixed", 1).
|
||||
Set("isRead", 1).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
hash := stringutil.Md5(nodeRole + "@" + types.String(nodeId) + "@" + types.String(serverId) + "@" + types.String(originId) + "@" + level + "@" + tag + "@" + description + "@" + string(paramsJSON))
|
||||
|
||||
// 检查是否在重复最后一条,避免重复创建
|
||||
lastLog, err := this.Query(tx).
|
||||
@@ -76,10 +93,31 @@ func (this *NodeLogDAO) CreateLog(tx *dbs.Tx, nodeRole nodeconfigs.NodeRole, nod
|
||||
op.Hash = hash
|
||||
op.Count = 1
|
||||
op.IsRead = level != "error"
|
||||
|
||||
op.Type = logType
|
||||
if len(paramsJSON) > 0 {
|
||||
op.Params = paramsJSON
|
||||
}
|
||||
|
||||
err = this.Save(tx, op)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteExpiredLogsWithLevel 清除超出一定日期的某级别日志
|
||||
func (this *NodeLogDAO) DeleteExpiredLogsWithLevel(tx *dbs.Tx, level string, days int) error {
|
||||
if days <= 0 {
|
||||
return errors.New("invalid days '" + strconv.Itoa(days) + "'")
|
||||
}
|
||||
date := time.Now().AddDate(0, 0, -days)
|
||||
expireDay := timeutil.Format("Ymd", date)
|
||||
_, err := this.Query(tx).
|
||||
Attr("level", level).
|
||||
Where("day<=:day").
|
||||
Param("day", expireDay).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteExpiredLogs 清除超出一定日期的日志
|
||||
func (this *NodeLogDAO) DeleteExpiredLogs(tx *dbs.Tx, days int) error {
|
||||
if days <= 0 {
|
||||
@@ -97,6 +135,7 @@ func (this *NodeLogDAO) DeleteExpiredLogs(tx *dbs.Tx, days int) error {
|
||||
// CountNodeLogs 计算节点日志数量
|
||||
func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx,
|
||||
role string,
|
||||
nodeClusterId int64,
|
||||
nodeId int64,
|
||||
serverId int64,
|
||||
originId int64,
|
||||
@@ -104,7 +143,8 @@ func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx,
|
||||
dayTo string,
|
||||
keyword string,
|
||||
level string,
|
||||
isUnread bool) (int64, error) {
|
||||
isUnread bool,
|
||||
tag string) (int64, error) {
|
||||
query := this.Query(tx)
|
||||
if len(role) > 0 {
|
||||
query.Attr("role", role)
|
||||
@@ -112,11 +152,16 @@ func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx,
|
||||
if nodeId > 0 {
|
||||
query.Attr("nodeId", nodeId)
|
||||
} else {
|
||||
switch role {
|
||||
case nodeconfigs.NodeRoleNode:
|
||||
query.Where("nodeId IN (SELECT id FROM " + SharedNodeDAO.Table + " WHERE state=1 AND clusterId>0)")
|
||||
case nodeconfigs.NodeRoleDNS:
|
||||
query.Where("nodeId IN (SELECT id FROM edgeNSNodes WHERE state=1 AND clusterId > 0)") // 没有用 SharedNSNodeDAO() 因为有包循环引用的问题
|
||||
if nodeClusterId > 0 {
|
||||
query.Where("nodeId IN (SELECT id FROM " + SharedNodeDAO.Table + " WHERE clusterId=:nodeClusterId AND state=1)")
|
||||
query.Param("nodeClusterId", nodeClusterId)
|
||||
} else {
|
||||
switch role {
|
||||
case nodeconfigs.NodeRoleNode:
|
||||
query.Where("nodeId IN (SELECT id FROM " + SharedNodeDAO.Table + " WHERE state=1 AND clusterId>0)")
|
||||
case nodeconfigs.NodeRoleDNS:
|
||||
query.Where("nodeId IN (SELECT id FROM edgeNSNodes WHERE state=1 AND clusterId > 0)") // 没有用 SharedNSNodeDAO() 因为有包循环引用的问题
|
||||
}
|
||||
}
|
||||
}
|
||||
if serverId > 0 {
|
||||
@@ -143,6 +188,9 @@ func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx,
|
||||
if isUnread {
|
||||
query.Attr("isRead", 0)
|
||||
}
|
||||
if len(tag) > 0 {
|
||||
query.Like("tag", "%"+tag+"%")
|
||||
}
|
||||
|
||||
return query.Count()
|
||||
}
|
||||
@@ -150,6 +198,7 @@ func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx,
|
||||
// ListNodeLogs 列出单页日志
|
||||
func (this *NodeLogDAO) ListNodeLogs(tx *dbs.Tx,
|
||||
role string,
|
||||
nodeClusterId int64,
|
||||
nodeId int64,
|
||||
serverId int64,
|
||||
originId int64,
|
||||
@@ -160,6 +209,7 @@ func (this *NodeLogDAO) ListNodeLogs(tx *dbs.Tx,
|
||||
level string,
|
||||
fixedState configutils.BoolState,
|
||||
isUnread bool,
|
||||
tag string,
|
||||
offset int64,
|
||||
size int64) (result []*NodeLog, err error) {
|
||||
query := this.Query(tx)
|
||||
@@ -169,11 +219,16 @@ func (this *NodeLogDAO) ListNodeLogs(tx *dbs.Tx,
|
||||
if nodeId > 0 {
|
||||
query.Attr("nodeId", nodeId)
|
||||
} else {
|
||||
switch role {
|
||||
case nodeconfigs.NodeRoleNode:
|
||||
query.Where("nodeId IN (SELECT id FROM " + SharedNodeDAO.Table + " WHERE state=1 AND clusterId>0)")
|
||||
case nodeconfigs.NodeRoleDNS:
|
||||
query.Where("nodeId IN (SELECT id FROM edgeNSNodes WHERE state=1 AND clusterId>0)") // 没有用 SharedNSNodeDAO() 因为有包循环引用的问题
|
||||
if nodeClusterId > 0 {
|
||||
query.Where("nodeId IN (SELECT id FROM " + SharedNodeDAO.Table + " WHERE clusterId=:nodeClusterId AND state=1)")
|
||||
query.Param("nodeClusterId", nodeClusterId)
|
||||
} else {
|
||||
switch role {
|
||||
case nodeconfigs.NodeRoleNode:
|
||||
query.Where("nodeId IN (SELECT id FROM " + SharedNodeDAO.Table + " WHERE state=1 AND clusterId>0)")
|
||||
case nodeconfigs.NodeRoleDNS:
|
||||
query.Where("nodeId IN (SELECT id FROM edgeNSNodes WHERE state=1 AND clusterId>0)") // 没有用 SharedNSNodeDAO() 因为有包循环引用的问题
|
||||
}
|
||||
}
|
||||
}
|
||||
if serverId > 0 {
|
||||
@@ -202,11 +257,19 @@ func (this *NodeLogDAO) ListNodeLogs(tx *dbs.Tx,
|
||||
Param("keyword", "%"+keyword+"%")
|
||||
}
|
||||
if len(level) > 0 {
|
||||
query.Attr("level", level)
|
||||
var pieces = strings.Split(level, ",")
|
||||
if len(pieces) == 1 {
|
||||
query.Attr("level", pieces[0])
|
||||
} else {
|
||||
query.Attr("level", pieces)
|
||||
}
|
||||
}
|
||||
if isUnread {
|
||||
query.Attr("isRead", 0)
|
||||
}
|
||||
if len(tag) > 0 {
|
||||
query.Like("tag", "%"+tag+"%")
|
||||
}
|
||||
_, err = query.
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
@@ -238,6 +301,7 @@ func (this *NodeLogDAO) UpdateNodeLogFixed(tx *dbs.Tx, logId int64) error {
|
||||
Attr("hash", hash).
|
||||
Attr("isFixed", false).
|
||||
Set("isFixed", true).
|
||||
Set("isRead", true).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -266,3 +330,11 @@ func (this *NodeLogDAO) UpdateNodeLogsRead(tx *dbs.Tx, nodeLogIds []int64) error
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateAllNodeLogsRead 设置所有日志为已读
|
||||
func (this *NodeLogDAO) UpdateAllNodeLogsRead(tx *dbs.Tx) error {
|
||||
return this.Query(tx).
|
||||
Attr("isRead", false).
|
||||
Set("isRead", true).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ package models
|
||||
type NodeLog struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
Role string `field:"role"` // 节点角色
|
||||
Type string `field:"type"` // 类型
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Tag string `field:"tag"` // 标签
|
||||
Description string `field:"description"` // 描述
|
||||
@@ -16,11 +17,13 @@ type NodeLog struct {
|
||||
Count uint32 `field:"count"` // 重复次数
|
||||
IsFixed uint8 `field:"isFixed"` // 是否已处理
|
||||
IsRead uint8 `field:"isRead"` // 是否已读
|
||||
Params string `field:"params"` // 参数
|
||||
}
|
||||
|
||||
type NodeLogOperator struct {
|
||||
Id interface{} // ID
|
||||
Role interface{} // 节点角色
|
||||
Type interface{} // 类型
|
||||
CreatedAt interface{} // 创建时间
|
||||
Tag interface{} // 标签
|
||||
Description interface{} // 描述
|
||||
@@ -33,6 +36,7 @@ type NodeLogOperator struct {
|
||||
Count interface{} // 重复次数
|
||||
IsFixed interface{} // 是否已处理
|
||||
IsRead interface{} // 是否已读
|
||||
Params interface{} // 参数
|
||||
}
|
||||
|
||||
func NewNodeLogOperator() *NodeLogOperator {
|
||||
|
||||
@@ -35,7 +35,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 启用条目
|
||||
// EnableNodePriceItem 启用条目
|
||||
func (this *NodePriceItemDAO) EnableNodePriceItem(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -44,7 +44,7 @@ func (this *NodePriceItemDAO) EnableNodePriceItem(tx *dbs.Tx, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 禁用条目
|
||||
// DisableNodePriceItem 禁用条目
|
||||
func (this *NodePriceItemDAO) DisableNodePriceItem(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -53,7 +53,7 @@ func (this *NodePriceItemDAO) DisableNodePriceItem(tx *dbs.Tx, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 查找启用中的条目
|
||||
// FindEnabledNodePriceItem 查找启用中的条目
|
||||
func (this *NodePriceItemDAO) FindEnabledNodePriceItem(tx *dbs.Tx, id int64) (*NodePriceItem, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -65,7 +65,7 @@ func (this *NodePriceItemDAO) FindEnabledNodePriceItem(tx *dbs.Tx, id int64) (*N
|
||||
return result.(*NodePriceItem), err
|
||||
}
|
||||
|
||||
// 根据主键查找名称
|
||||
// FindNodePriceItemName 根据主键查找名称
|
||||
func (this *NodePriceItemDAO) FindNodePriceItemName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -73,7 +73,7 @@ func (this *NodePriceItemDAO) FindNodePriceItemName(tx *dbs.Tx, id int64) (strin
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// 创建价格
|
||||
// CreateItem 创建价格
|
||||
func (this *NodePriceItemDAO) CreateItem(tx *dbs.Tx, name string, itemType string, bitsFrom, bitsTo int64) (int64, error) {
|
||||
op := NewNodePriceItemOperator()
|
||||
op.Name = name
|
||||
@@ -85,7 +85,7 @@ func (this *NodePriceItemDAO) CreateItem(tx *dbs.Tx, name string, itemType strin
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// 修改价格
|
||||
// UpdateItem 修改价格
|
||||
func (this *NodePriceItemDAO) UpdateItem(tx *dbs.Tx, itemId int64, name string, bitsFrom, bitsTo int64) error {
|
||||
if itemId <= 0 {
|
||||
return errors.New("invalid itemId")
|
||||
@@ -98,7 +98,7 @@ func (this *NodePriceItemDAO) UpdateItem(tx *dbs.Tx, itemId int64, name string,
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// 列出某个区域的所有价格
|
||||
// FindAllEnabledRegionPrices 列出某个区域的所有价格
|
||||
func (this *NodePriceItemDAO) FindAllEnabledRegionPrices(tx *dbs.Tx, priceType string) (result []*NodePriceItem, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Attr("type", priceType).
|
||||
@@ -109,7 +109,7 @@ func (this *NodePriceItemDAO) FindAllEnabledRegionPrices(tx *dbs.Tx, priceType s
|
||||
return
|
||||
}
|
||||
|
||||
// 列出某个区域的所有启用的价格
|
||||
// FindAllEnabledAndOnRegionPrices 列出某个区域的所有启用的价格
|
||||
func (this *NodePriceItemDAO) FindAllEnabledAndOnRegionPrices(tx *dbs.Tx, priceType string) (result []*NodePriceItem, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Attr("type", priceType).
|
||||
@@ -121,7 +121,7 @@ func (this *NodePriceItemDAO) FindAllEnabledAndOnRegionPrices(tx *dbs.Tx, priceT
|
||||
return
|
||||
}
|
||||
|
||||
// 根据字节查找付费项目
|
||||
// SearchItemsWithBytes 根据字节查找付费项目
|
||||
func (this *NodePriceItemDAO) SearchItemsWithBytes(items []*NodePriceItem, bytes int64) int64 {
|
||||
bytes *= 8
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package models
|
||||
|
||||
// 区域计费设置
|
||||
// NodePriceItem 区域计费设置
|
||||
type NodePriceItem struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn uint8 `field:"isOn"` // 是否启用
|
||||
|
||||
@@ -35,7 +35,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// 启用条目
|
||||
// EnableNodeRegion 启用条目
|
||||
func (this *NodeRegionDAO) EnableNodeRegion(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -44,7 +44,7 @@ func (this *NodeRegionDAO) EnableNodeRegion(tx *dbs.Tx, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 禁用条目
|
||||
// DisableNodeRegion 禁用条目
|
||||
func (this *NodeRegionDAO) DisableNodeRegion(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -53,7 +53,7 @@ func (this *NodeRegionDAO) DisableNodeRegion(tx *dbs.Tx, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 查找启用中的条目
|
||||
// FindEnabledNodeRegion 查找启用中的条目
|
||||
func (this *NodeRegionDAO) FindEnabledNodeRegion(tx *dbs.Tx, id int64) (*NodeRegion, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -65,7 +65,7 @@ func (this *NodeRegionDAO) FindEnabledNodeRegion(tx *dbs.Tx, id int64) (*NodeReg
|
||||
return result.(*NodeRegion), err
|
||||
}
|
||||
|
||||
// 根据主键查找名称
|
||||
// FindNodeRegionName 根据主键查找名称
|
||||
func (this *NodeRegionDAO) FindNodeRegionName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
@@ -73,7 +73,7 @@ func (this *NodeRegionDAO) FindNodeRegionName(tx *dbs.Tx, id int64) (string, err
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// 创建区域
|
||||
// CreateRegion 创建区域
|
||||
func (this *NodeRegionDAO) CreateRegion(tx *dbs.Tx, adminId int64, name string, description string) (int64, error) {
|
||||
op := NewNodeRegionOperator()
|
||||
op.AdminId = adminId
|
||||
@@ -84,7 +84,7 @@ func (this *NodeRegionDAO) CreateRegion(tx *dbs.Tx, adminId int64, name string,
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// 修改区域
|
||||
// UpdateRegion 修改区域
|
||||
func (this *NodeRegionDAO) UpdateRegion(tx *dbs.Tx, regionId int64, name string, description string, isOn bool) error {
|
||||
if regionId <= 0 {
|
||||
return errors.New("invalid regionId")
|
||||
@@ -97,7 +97,7 @@ func (this *NodeRegionDAO) UpdateRegion(tx *dbs.Tx, regionId int64, name string,
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// 列出所有区域
|
||||
// FindAllEnabledRegions 列出所有区域
|
||||
func (this *NodeRegionDAO) FindAllEnabledRegions(tx *dbs.Tx) (result []*NodeRegion, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(NodeRegionStateEnabled).
|
||||
@@ -108,7 +108,7 @@ func (this *NodeRegionDAO) FindAllEnabledRegions(tx *dbs.Tx) (result []*NodeRegi
|
||||
return
|
||||
}
|
||||
|
||||
// 列出所有价格
|
||||
// FindAllEnabledRegionPrices 列出所有价格
|
||||
func (this *NodeRegionDAO) FindAllEnabledRegionPrices(tx *dbs.Tx) (result []*NodeRegion, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(NodeRegionStateEnabled).
|
||||
@@ -120,7 +120,7 @@ func (this *NodeRegionDAO) FindAllEnabledRegionPrices(tx *dbs.Tx) (result []*Nod
|
||||
return
|
||||
}
|
||||
|
||||
// 列出所有启用的区域
|
||||
// FindAllEnabledAndOnRegions 列出所有启用的区域
|
||||
func (this *NodeRegionDAO) FindAllEnabledAndOnRegions(tx *dbs.Tx) (result []*NodeRegion, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(NodeRegionStateEnabled).
|
||||
@@ -132,7 +132,7 @@ func (this *NodeRegionDAO) FindAllEnabledAndOnRegions(tx *dbs.Tx) (result []*Nod
|
||||
return
|
||||
}
|
||||
|
||||
// 排序
|
||||
// UpdateRegionOrders 排序
|
||||
func (this *NodeRegionDAO) UpdateRegionOrders(tx *dbs.Tx, regionIds []int64) error {
|
||||
order := len(regionIds)
|
||||
for _, regionId := range regionIds {
|
||||
@@ -148,7 +148,7 @@ func (this *NodeRegionDAO) UpdateRegionOrders(tx *dbs.Tx, regionIds []int64) err
|
||||
return nil
|
||||
}
|
||||
|
||||
// 修改价格项价格
|
||||
// UpdateRegionItemPrice 修改价格项价格
|
||||
func (this *NodeRegionDAO) UpdateRegionItemPrice(tx *dbs.Tx, regionId int64, itemId int64, price float32) error {
|
||||
one, err := this.Query(tx).
|
||||
Pk(regionId).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package models
|
||||
|
||||
// 节点区域
|
||||
// NodeRegion 节点区域
|
||||
type NodeRegion struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user