Compare commits
90 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
35cb10fffe | ||
|
|
7c84794ac4 | ||
|
|
5859f5df91 | ||
|
|
e370944233 | ||
|
|
a23a2ed826 | ||
|
|
3f9c250dff | ||
|
|
06c9c9403b | ||
|
|
0e580a0890 | ||
|
|
7aba622403 | ||
|
|
72cc8389e6 | ||
|
|
39cf470b0c | ||
|
|
6e71dda713 | ||
|
|
10909e28c8 | ||
|
|
6bd6e350b9 | ||
|
|
d2ae7834ae | ||
|
|
c1ffd25c8b | ||
|
|
931e55162b | ||
|
|
fa2bac6d1d | ||
|
|
2f7b7240dd | ||
|
|
da67e726a2 | ||
|
|
6cb5529c3f | ||
|
|
473d0d9439 | ||
|
|
bf0db231fc | ||
|
|
5644906b77 | ||
|
|
3e32fe8e10 | ||
|
|
8459f106e9 | ||
|
|
b768bbce5d | ||
|
|
9e7beb39c0 | ||
|
|
94287f5857 | ||
|
|
60690dfd01 | ||
|
|
fb00a7931e | ||
|
|
42a6494bde | ||
|
|
85a46a9827 | ||
|
|
088636553c | ||
|
|
95de3b12e2 | ||
|
|
b66b8d198a | ||
|
|
e968a79886 | ||
|
|
4fc5d5b549 | ||
|
|
77606709b3 | ||
|
|
3529ceefcd | ||
|
|
7e851f07b1 | ||
|
|
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 |
@@ -83,6 +83,20 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
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() {
|
app.Run(func() {
|
||||||
nodes.NewAPINode().Start()
|
nodes.NewAPINode().Start()
|
||||||
})
|
})
|
||||||
|
|||||||
20
go.mod
20
go.mod
@@ -5,27 +5,23 @@ go 1.15
|
|||||||
replace github.com/TeaOSLab/EdgeCommon => ../EdgeCommon
|
replace github.com/TeaOSLab/EdgeCommon => ../EdgeCommon
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
|
|
||||||
github.com/TeaOSLab/EdgeCommon v0.0.0-00010101000000-000000000000
|
github.com/TeaOSLab/EdgeCommon v0.0.0-00010101000000-000000000000
|
||||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1183
|
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1183
|
||||||
github.com/andybalholm/brotli v1.0.4
|
github.com/andybalholm/brotli v1.0.4
|
||||||
github.com/cespare/xxhash/v2 v2.1.1
|
github.com/cespare/xxhash/v2 v2.1.1
|
||||||
github.com/go-acme/lego/v4 v4.5.2
|
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-sql-driver/mysql v1.5.0
|
||||||
github.com/go-yaml/yaml v2.1.0+incompatible
|
|
||||||
github.com/golang/protobuf v1.5.2
|
github.com/golang/protobuf v1.5.2
|
||||||
github.com/iwind/TeaGo v0.0.0-20211026123858-7de7a21cad24
|
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475
|
||||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3
|
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3
|
||||||
github.com/json-iterator/go v1.1.12 // 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/mozillazg/go-pinyin v0.18.0
|
||||||
github.com/pkg/sftp v1.12.0
|
github.com/pkg/sftp v1.12.0
|
||||||
github.com/shirou/gopsutil v3.21.5+incompatible
|
github.com/shirou/gopsutil/v3 v3.22.2 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.6 // indirect
|
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
|
golang.org/x/crypto v0.0.0-20220214200702-86341886e292
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22
|
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8
|
||||||
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced // indirect
|
google.golang.org/grpc v1.45.0
|
||||||
google.golang.org/grpc v1.38.0
|
google.golang.org/protobuf v1.27.1
|
||||||
google.golang.org/protobuf v1.26.0
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||||
)
|
)
|
||||||
|
|||||||
96
go.sum
96
go.sum
@@ -43,8 +43,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
|
|||||||
github.com/DataDog/sketches-go v0.0.0-20190923095040-43f19ad77ff7/go.mod h1:Q5DbzQ+3AkgGwymQO7aZFNP7ns2lZKGtvRBzRXfdi60=
|
github.com/DataDog/sketches-go v0.0.0-20190923095040-43f19ad77ff7/go.mod h1:Q5DbzQ+3AkgGwymQO7aZFNP7ns2lZKGtvRBzRXfdi60=
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks=
|
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks=
|
||||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
|
|
||||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
|
||||||
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.1.1/go.mod h1:kX6YddBkXqqywAe8c9LyvgTCyFuZCTMF4cRPQhc3Fy8=
|
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.1.1/go.mod h1:kX6YddBkXqqywAe8c9LyvgTCyFuZCTMF4cRPQhc3Fy8=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
@@ -52,6 +50,7 @@ github.com/aliyun/alibaba-cloud-sdk-go v1.61.1183 h1:dkj8/dxOQ4L1XpwCzRLqukvUBbx
|
|||||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1183/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA=
|
github.com/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 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||||
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
github.com/armon/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-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=
|
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||||
@@ -78,6 +77,10 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
|||||||
github.com/cloudflare/cloudflare-go v0.20.0/go.mod h1:sPWL/lIC6biLEdyGZwBQ1rGQKF1FhM7N60fuNiFdYTI=
|
github.com/cloudflare/cloudflare-go v0.20.0/go.mod h1:sPWL/lIC6biLEdyGZwBQ1rGQKF1FhM7N60fuNiFdYTI=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
@@ -101,7 +104,8 @@ github.com/dnsimple/dnsimple-go v0.70.1/go.mod h1:F9WHww9cC76hrnwGFfAfrqdW99j3MO
|
|||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/exoscale/egoscale v0.67.0/go.mod h1:wi0myUxPsV8SdEtdJHQJxFLL/wEw9fiw9Gs1PWRkvkM=
|
github.com/exoscale/egoscale v0.67.0/go.mod h1:wi0myUxPsV8SdEtdJHQJxFLL/wEw9fiw9Gs1PWRkvkM=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
@@ -122,8 +126,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
|
|||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
|
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||||
github.com/go-redis/redis/v8 v8.0.0-beta.7/go.mod h1:FGJAWDWFht1sQ4qxyJHZZbVyvnVcKQN0E3u5/5lRz+g=
|
github.com/go-redis/redis/v8 v8.0.0-beta.7/go.mod h1:FGJAWDWFht1sQ4qxyJHZZbVyvnVcKQN0E3u5/5lRz+g=
|
||||||
@@ -132,8 +136,6 @@ github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gG
|
|||||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o=
|
|
||||||
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
|
|
||||||
github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b/go.mod h1:Xo4aNUOrJnVruqWQJBtW6+bTBDTniY8yZum5rF3b5jw=
|
github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b/go.mod h1:Xo4aNUOrJnVruqWQJBtW6+bTBDTniY8yZum5rF3b5jw=
|
||||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
@@ -161,6 +163,7 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
|
|||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
@@ -175,6 +178,9 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||||
|
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||||
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
|
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
|
||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||||
@@ -201,6 +207,7 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
|
|||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||||
@@ -231,11 +238,8 @@ github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhK
|
|||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/infobloxopen/infoblox-go-client v1.1.1/go.mod h1:BXiw7S2b9qJoM8MS40vfgCNB2NLHGusk1DtO16BD9zI=
|
github.com/infobloxopen/infoblox-go-client v1.1.1/go.mod h1:BXiw7S2b9qJoM8MS40vfgCNB2NLHGusk1DtO16BD9zI=
|
||||||
github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||||
github.com/iwind/TeaGo v0.0.0-20210628135026-38575a4ab060/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475 h1:EseyfFaQOjWanGiby9KMw7PjDBMg/95tLDgIw/ns0Cw=
|
||||||
github.com/iwind/TeaGo v0.0.0-20210831140440-a2a442471b13 h1:HuEJ5xJfujW1Q6rNDhOu5LQXEBB2qLPah3jYslT8Gz4=
|
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
|
||||||
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 h1:aBSonas7vFcgTj9u96/bWGILGv1ZbUSTLiOzcI1ZT6c=
|
||||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
|
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=
|
github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
|
||||||
@@ -250,8 +254,6 @@ github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
|
|||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.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 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
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.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
@@ -277,12 +279,11 @@ github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c
|
|||||||
github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg=
|
github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg=
|
||||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||||
github.com/linode/linodego v0.31.1/go.mod h1:BR0gVkCJffEdIGJSl6bHR80Ty+Uvg/2jkjmrWaFectM=
|
github.com/linode/linodego v0.31.1/go.mod h1:BR0gVkCJffEdIGJSl6bHR80Ty+Uvg/2jkjmrWaFectM=
|
||||||
github.com/lionsoul2014/ip2region v2.2.0-release+incompatible h1:1qp9iks+69h7IGLazAplzS9Ca14HAxuD5c0rbFdPGy4=
|
|
||||||
github.com/lionsoul2014/ip2region v2.2.0-release+incompatible/go.mod h1:+ZBN7PBoh5gG6/y0ZQ85vJDBe21WnfbRrQQwTfliJJI=
|
|
||||||
github.com/liquidweb/go-lwApi v0.0.0-20190605172801-52a4864d2738/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs=
|
github.com/liquidweb/go-lwApi v0.0.0-20190605172801-52a4864d2738/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs=
|
||||||
github.com/liquidweb/go-lwApi v0.0.5/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs=
|
github.com/liquidweb/go-lwApi v0.0.5/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs=
|
||||||
github.com/liquidweb/liquidweb-cli v0.6.9/go.mod h1:cE1uvQ+x24NGUL75D0QagOFCG8Wdvmwu8aL9TLmA/eQ=
|
github.com/liquidweb/liquidweb-cli v0.6.9/go.mod h1:cE1uvQ+x24NGUL75D0QagOFCG8Wdvmwu8aL9TLmA/eQ=
|
||||||
github.com/liquidweb/liquidweb-go v1.6.3/go.mod h1:SuXXp+thr28LnjEw18AYtWwIbWMHSUiajPQs8T9c/Rc=
|
github.com/liquidweb/liquidweb-go v1.6.3/go.mod h1:SuXXp+thr28LnjEw18AYtWwIbWMHSUiajPQs8T9c/Rc=
|
||||||
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
@@ -322,7 +323,6 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
|
|||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/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 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
@@ -371,6 +371,7 @@ github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw
|
|||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||||
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||||
github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||||
@@ -390,14 +391,17 @@ github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa
|
|||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA=
|
github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA=
|
||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
github.com/sacloud/libsacloud v1.36.2/go.mod h1:P7YAOVmnIn3DKHqCZcUKYUXmSwGBm3yS7IBEjKVSrjg=
|
github.com/sacloud/libsacloud v1.36.2/go.mod h1:P7YAOVmnIn3DKHqCZcUKYUXmSwGBm3yS7IBEjKVSrjg=
|
||||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210127161313-bd30bebeac4f/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
|
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210127161313-bd30bebeac4f/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
github.com/shirou/gopsutil v3.21.5+incompatible h1:OloQyEerMi7JUrXiNzy8wQ5XN+baemxSl12QgIzt0jc=
|
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||||
github.com/shirou/gopsutil v3.21.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
|
github.com/shirou/gopsutil/v3 v3.22.2 h1:wCrArWFkHYIdDxx/FSfF5RB4dpJYW6t7rcp3+zL8uks=
|
||||||
|
github.com/shirou/gopsutil/v3 v3.22.2/go.mod h1:WapW1AOOPlHyXr+yOyw3uYx36enocrtSoSBy0L5vUHY=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
@@ -438,8 +442,12 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4=
|
github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4=
|
||||||
github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
|
github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
|
||||||
|
github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo=
|
||||||
|
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
|
||||||
github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
|
github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
|
||||||
github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
|
github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
|
||||||
|
github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
|
||||||
|
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/transip/gotransip/v6 v6.6.1/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g=
|
github.com/transip/gotransip/v6 v6.6.1/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g=
|
||||||
github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
|
github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
|
||||||
@@ -456,13 +464,15 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
|
|||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opentelemetry.io/otel v0.7.0/go.mod h1:aZMyHG5TqDOXEgH2tyLiXSUKly1jT3yqE9PmrzIeCdo=
|
go.opentelemetry.io/otel v0.7.0/go.mod h1:aZMyHG5TqDOXEgH2tyLiXSUKly1jT3yqE9PmrzIeCdo=
|
||||||
|
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
@@ -482,8 +492,9 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh
|
|||||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
|
|
||||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
|
||||||
|
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@@ -507,7 +518,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
|
|||||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
@@ -516,7 +526,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
|||||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@@ -551,8 +560,10 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
|
|
||||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
|
||||||
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@@ -588,6 +599,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -611,6 +623,7 @@ golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -619,11 +632,17 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
|
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs=
|
||||||
|
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs=
|
||||||
|
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@@ -631,8 +650,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
|||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
@@ -674,7 +694,6 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK
|
|||||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@@ -714,9 +733,12 @@ google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4
|
|||||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced h1:c5geK1iMU3cDKtFrCVQIcjR3W+JOZMuhIyICMCTbtus=
|
google.golang.org/genproto v0.0.0-20220303160752-862486edd9cc h1:fb/ViRpv3ln/LvbqZtTpoOd1YQDNH12gaGZreoSFovE=
|
||||||
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
|
google.golang.org/genproto v0.0.0-20220303160752-862486edd9cc/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||||
|
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e h1:fNKDNuUyC4WH+inqDMpfXDdfvwfYILbsX+oskGZ8hxg=
|
||||||
|
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
@@ -726,9 +748,12 @@ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
|
|||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||||
google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0=
|
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg=
|
||||||
|
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||||
|
google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M=
|
||||||
|
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
@@ -739,8 +764,9 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
|||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
|
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||||
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
//go:build community
|
//go:build !plus
|
||||||
// +build community
|
// +build !plus
|
||||||
|
|
||||||
package accesslogs
|
package accesslogs
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ package configs
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||||
"github.com/go-yaml/yaml"
|
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
// +build community
|
//go:build !plus
|
||||||
|
// +build !plus
|
||||||
|
|
||||||
package teaconst
|
package teaconst
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package teaconst
|
package teaconst
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version = "0.4.0"
|
Version = "0.4.5"
|
||||||
|
|
||||||
ProductName = "Edge API"
|
ProductName = "Edge API"
|
||||||
ProcessName = "edge-api"
|
ProcessName = "edge-api"
|
||||||
@@ -18,10 +18,13 @@ const (
|
|||||||
|
|
||||||
// 其他节点版本号,用来检测是否有需要升级的节点
|
// 其他节点版本号,用来检测是否有需要升级的节点
|
||||||
|
|
||||||
NodeVersion = "0.4.0"
|
NodeVersion = "0.4.5"
|
||||||
UserNodeVersion = "0.2.1"
|
UserNodeVersion = "0.3.2"
|
||||||
AuthorityNodeVersion = "0.0.2"
|
AuthorityNodeVersion = "0.0.2"
|
||||||
MonitorNodeVersion = "0.0.3"
|
MonitorNodeVersion = "0.0.3"
|
||||||
DNSNodeVersion = "0.2.1"
|
DNSNodeVersion = "0.2.1"
|
||||||
ReportNodeVersion = "0.1.0"
|
ReportNodeVersion = "0.1.0"
|
||||||
|
|
||||||
|
// SQLVersion SQL版本号
|
||||||
|
SQLVersion = "5"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,4 +6,5 @@ var (
|
|||||||
IsPlus = false
|
IsPlus = false
|
||||||
MaxNodes int32 = 0
|
MaxNodes int32 = 0
|
||||||
NodeId int64 = 0
|
NodeId int64 = 0
|
||||||
|
Debug = false
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
acmeutils "github.com/TeaOSLab/EdgeAPI/internal/acme"
|
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"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
|
||||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
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)
|
client := utils.SharedHttpClient(5 * time.Second)
|
||||||
req, err := http.NewRequest(http.MethodPost, task.AuthURL, bytes.NewReader(authJSON))
|
req, err := http.NewRequest(http.MethodPost, task.AuthURL, bytes.NewReader(authJSON))
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
req.Header.Set("User-Agent", teaconst.ProductName+"/"+teaconst.Version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
remotelogs.Error("ACME", "parse auth url failed '"+task.AuthURL+"': "+err.Error())
|
remotelogs.Error("ACME", "parse auth url failed '"+task.AuthURL+"': "+err.Error())
|
||||||
} else {
|
} 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
|
||||||
@@ -62,7 +62,15 @@ func (this *APINodeDAO) DisableAPINode(tx *dbs.Tx, id int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FindEnabledAPINode 查找启用中的条目
|
// 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).
|
result, err := this.Query(tx).
|
||||||
Pk(id).
|
Pk(id).
|
||||||
Attr("state", APINodeStateEnabled).
|
Attr("state", APINodeStateEnabled).
|
||||||
@@ -70,6 +78,11 @@ func (this *APINodeDAO) FindEnabledAPINode(tx *dbs.Tx, id int64) (*APINode, erro
|
|||||||
if result == nil {
|
if result == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cacheMap != nil {
|
||||||
|
cacheMap.Put(cacheKey, result)
|
||||||
|
}
|
||||||
|
|
||||||
return result.(*APINode), err
|
return result.(*APINode), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
//go:build community
|
//go:build !plus
|
||||||
// +build community
|
// +build !plus
|
||||||
|
|
||||||
package authority
|
package authority
|
||||||
|
|
||||||
|
|||||||
@@ -29,8 +29,7 @@ type httpAccessLogDefinition struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HTTP服务访问
|
// HTTP服务访问
|
||||||
var httpAccessLogDAOMapping = map[int64]*HTTPAccessLogDAOWrapper{} // dbNodeId => DAO
|
var httpAccessLogDAOMapping = map[int64]*HTTPAccessLogDAOWrapper{} // dbNodeId => DAO
|
||||||
var httpAccessLogTableMapping = map[string]*httpAccessLogDefinition{} // tableName_crc(dsn) => true
|
|
||||||
|
|
||||||
// DNS服务访问
|
// DNS服务访问
|
||||||
var nsAccessLogDAOMapping = map[int64]*NSAccessLogDAOWrapper{} // dbNodeId => DAO
|
var nsAccessLogDAOMapping = map[int64]*NSAccessLogDAOWrapper{} // dbNodeId => DAO
|
||||||
@@ -86,36 +85,6 @@ func randomNSAccessLogDAO() (dao *NSAccessLogDAOWrapper) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查表格是否存在
|
|
||||||
func findHTTPAccessLogTableName(db *dbs.DB, day string) (tableName string, hasRemoteAddr bool, hasDomain bool, ok bool, err error) {
|
|
||||||
if !regexp.MustCompile(`^\d{8}$`).MatchString(day) {
|
|
||||||
err = errors.New("invalid day '" + day + "', should be YYYYMMDD")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
config, err := db.Config()
|
|
||||||
if err != nil {
|
|
||||||
return "", false, false, false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tableName = "edgeHTTPAccessLogs_" + day
|
|
||||||
cacheKey := tableName + "_" + fmt.Sprintf("%d", crc32.ChecksumIEEE([]byte(config.Dsn)))
|
|
||||||
|
|
||||||
accessLogLocker.RLock()
|
|
||||||
def, ok := httpAccessLogTableMapping[cacheKey]
|
|
||||||
accessLogLocker.RUnlock()
|
|
||||||
if ok {
|
|
||||||
return tableName, def.HasRemoteAddr, def.HasDomain, true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
def, err = findHTTPAccessLogTable(db, day, false)
|
|
||||||
if err != nil {
|
|
||||||
return tableName, false, false, false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return tableName, def.HasRemoteAddr, def.HasDomain, def.Exists, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func findNSAccessLogTableName(db *dbs.DB, day string) (tableName string, ok bool, err error) {
|
func findNSAccessLogTableName(db *dbs.DB, day string) (tableName string, ok bool, err error) {
|
||||||
if !regexp.MustCompile(`^\d{8}$`).MatchString(day) {
|
if !regexp.MustCompile(`^\d{8}$`).MatchString(day) {
|
||||||
err = errors.New("invalid day '" + day + "', should be YYYYMMDD")
|
err = errors.New("invalid day '" + day + "', should be YYYYMMDD")
|
||||||
@@ -145,75 +114,6 @@ func findNSAccessLogTableName(db *dbs.DB, day string) (tableName string, ok bool
|
|||||||
return tableName, utils.ContainsStringInsensitive(tableNames, tableName), nil
|
return tableName, utils.ContainsStringInsensitive(tableNames, tableName), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据日期获取表名
|
|
||||||
func findHTTPAccessLogTable(db *dbs.DB, day string, force bool) (*httpAccessLogDefinition, error) {
|
|
||||||
config, err := db.Config()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tableName := "edgeHTTPAccessLogs_" + day
|
|
||||||
cacheKey := tableName + "_" + fmt.Sprintf("%d", crc32.ChecksumIEEE([]byte(config.Dsn)))
|
|
||||||
|
|
||||||
if !force {
|
|
||||||
accessLogLocker.RLock()
|
|
||||||
definition, ok := httpAccessLogTableMapping[cacheKey]
|
|
||||||
accessLogLocker.RUnlock()
|
|
||||||
if ok {
|
|
||||||
return definition, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tableNames, err := db.TableNames()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if utils.ContainsStringInsensitive(tableNames, tableName) {
|
|
||||||
table, err := db.FindTable(tableName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
accessLogLocker.Lock()
|
|
||||||
var definition = &httpAccessLogDefinition{
|
|
||||||
Name: tableName,
|
|
||||||
HasRemoteAddr: table.FindFieldWithName("remoteAddr") != nil,
|
|
||||||
HasDomain: table.FindFieldWithName("domain") != nil,
|
|
||||||
Exists: true,
|
|
||||||
}
|
|
||||||
httpAccessLogTableMapping[cacheKey] = definition
|
|
||||||
accessLogLocker.Unlock()
|
|
||||||
return definition, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if !force {
|
|
||||||
return &httpAccessLogDefinition{
|
|
||||||
Name: tableName,
|
|
||||||
HasRemoteAddr: true,
|
|
||||||
HasDomain: true,
|
|
||||||
Exists: false,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建表格
|
|
||||||
_, err = db.Exec("CREATE TABLE `" + tableName + "` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `serverId` int(11) unsigned DEFAULT '0' COMMENT '服务ID',\n `nodeId` int(11) unsigned DEFAULT '0' COMMENT '节点ID',\n `status` int(3) unsigned DEFAULT '0' COMMENT '状态码',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `content` json DEFAULT NULL COMMENT '日志内容',\n `requestId` varchar(128) DEFAULT NULL COMMENT '请求ID',\n `firewallPolicyId` int(11) unsigned DEFAULT '0' COMMENT 'WAF策略ID',\n `firewallRuleGroupId` int(11) unsigned DEFAULT '0' COMMENT 'WAF分组ID',\n `firewallRuleSetId` int(11) unsigned DEFAULT '0' COMMENT 'WAF集ID',\n `firewallRuleId` int(11) unsigned DEFAULT '0' COMMENT 'WAF规则ID',\n `remoteAddr` varchar(64) DEFAULT NULL COMMENT 'IP地址',\n `domain` varchar(128) DEFAULT NULL COMMENT '域名',\n `requestBody` mediumblob COMMENT '请求内容',\n `responseBody` mediumblob COMMENT '响应内容',\n PRIMARY KEY (`id`),\n KEY `serverId` (`serverId`),\n KEY `nodeId` (`nodeId`),\n KEY `serverId_status` (`serverId`,`status`),\n KEY `requestId` (`requestId`),\n KEY `firewallPolicyId` (`firewallPolicyId`),\n KEY `firewallRuleGroupId` (`firewallRuleGroupId`),\n KEY `firewallRuleSetId` (`firewallRuleSetId`),\n KEY `firewallRuleId` (`firewallRuleId`),\n KEY `remoteAddr` (`remoteAddr`),\n KEY `domain` (`domain`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='访问日志';")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
accessLogLocker.Lock()
|
|
||||||
var definition = &httpAccessLogDefinition{
|
|
||||||
Name: tableName,
|
|
||||||
HasRemoteAddr: true,
|
|
||||||
Exists: true,
|
|
||||||
}
|
|
||||||
httpAccessLogTableMapping[cacheKey] = definition
|
|
||||||
accessLogLocker.Unlock()
|
|
||||||
|
|
||||||
return definition, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func findNSAccessLogTable(db *dbs.DB, day string, force bool) (string, error) {
|
func findNSAccessLogTable(db *dbs.DB, day string, force bool) (string, error) {
|
||||||
config, err := db.Config()
|
config, err := db.Config()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -351,22 +251,17 @@ func (this *DBNodeInitializer) loop() error {
|
|||||||
// 检查表是否存在
|
// 检查表是否存在
|
||||||
// httpAccessLog
|
// httpAccessLog
|
||||||
{
|
{
|
||||||
tableDef, err := findHTTPAccessLogTable(db, timeutil.Format("Ymd"), true)
|
tableDef, err := SharedHTTPAccessLogManager.FindTable(db, timeutil.Format("Ymd"), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !strings.Contains(err.Error(), "1050") { // 非表格已存在错误
|
remotelogs.Error("DB_NODE", "create first table in database node failed: "+err.Error())
|
||||||
remotelogs.Error("DB_NODE", "create first table in database node failed: "+err.Error())
|
|
||||||
|
|
||||||
// 创建节点日志
|
// 创建节点日志
|
||||||
createLogErr := SharedNodeLogDAO.CreateLog(nil, nodeconfigs.NodeRoleDatabase, nodeId, 0, 0, "error", "ACCESS_LOG", "can not create access log table: "+err.Error(), time.Now().Unix(), "", nil)
|
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 {
|
if createLogErr != nil {
|
||||||
remotelogs.Error("NODE_LOG", createLogErr.Error())
|
remotelogs.Error("NODE_LOG", createLogErr.Error())
|
||||||
}
|
|
||||||
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
err = nil
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
daoObject := dbs.DAOObject{
|
daoObject := dbs.DAOObject{
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDBNodeInitializer_loop(t *testing.T) {
|
func TestDBNodeInitializer_loop(t *testing.T) {
|
||||||
@@ -14,32 +12,3 @@ func TestDBNodeInitializer_loop(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Log(len(accessLogDBMapping), len(httpAccessLogDAOMapping))
|
t.Log(len(accessLogDBMapping), len(httpAccessLogDAOMapping))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFindAccessLogTable(t *testing.T) {
|
|
||||||
before := time.Now()
|
|
||||||
db := SharedHTTPAccessLogDAO.Instance
|
|
||||||
tableName, err := findHTTPAccessLogTable(db, "20201010", false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
t.Log(tableName)
|
|
||||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
|
||||||
|
|
||||||
before = time.Now()
|
|
||||||
tableName, err = findHTTPAccessLogTable(db, "20201010", false)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
t.Log(tableName)
|
|
||||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkFindAccessLogTable(b *testing.B) {
|
|
||||||
db := SharedHTTPAccessLogDAO.Instance
|
|
||||||
|
|
||||||
runtime.GOMAXPROCS(1)
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_, _ = findHTTPAccessLogTable(db, "20201010", false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -34,13 +34,25 @@ type HTTPAccessLogDAO dbs.DAO
|
|||||||
var SharedHTTPAccessLogDAO *HTTPAccessLogDAO
|
var SharedHTTPAccessLogDAO *HTTPAccessLogDAO
|
||||||
|
|
||||||
// 队列
|
// 队列
|
||||||
var oldAccessLogQueue = make(chan *pb.HTTPAccessLog)
|
var (
|
||||||
var accessLogQueue = make(chan *pb.HTTPAccessLog, 10_000)
|
oldAccessLogQueue = make(chan *pb.HTTPAccessLog)
|
||||||
var accessLogQueueMaxLength = 100_000
|
accessLogQueue = make(chan *pb.HTTPAccessLog, 10_000)
|
||||||
var accessLogQueuePercent = 100 // 0-100
|
accessLogQueueMaxLength = 100_000
|
||||||
var accessLogCountPerSecond = 10_000 // 0 表示不限制
|
accessLogQueuePercent = 100 // 0-100
|
||||||
var accessLogConfigJSON = []byte{}
|
accessLogCountPerSecond = 10_000 // 0 表示不限制
|
||||||
var accessLogQueueChanged = make(chan zero.Zero, 1)
|
accessLogConfigJSON = []byte{}
|
||||||
|
accessLogQueueChanged = make(chan zero.Zero, 1)
|
||||||
|
|
||||||
|
accessLogEnableAutoPartial = true // 是否启用自动分表
|
||||||
|
accessLogRowsPerTable int64 = 500_000 // 自动分表的单表最大值
|
||||||
|
)
|
||||||
|
|
||||||
|
type accessLogTableQuery struct {
|
||||||
|
daoWrapper *HTTPAccessLogDAOWrapper
|
||||||
|
name string
|
||||||
|
hasRemoteAddrField bool
|
||||||
|
hasDomainField bool
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
dbs.OnReady(func() {
|
dbs.OnReady(func() {
|
||||||
@@ -120,7 +132,7 @@ func (this *HTTPAccessLogDAO) CreateHTTPAccessLogs(tx *dbs.Tx, accessLogs []*pb.
|
|||||||
|
|
||||||
// DumpAccessLogsFromQueue 从队列导入访问日志
|
// DumpAccessLogsFromQueue 从队列导入访问日志
|
||||||
func (this *HTTPAccessLogDAO) DumpAccessLogsFromQueue(tx *dbs.Tx, size int) error {
|
func (this *HTTPAccessLogDAO) DumpAccessLogsFromQueue(tx *dbs.Tx, size int) error {
|
||||||
dao := randomHTTPAccessLogDAO()
|
var dao = randomHTTPAccessLogDAO()
|
||||||
if dao == nil {
|
if dao == nil {
|
||||||
dao = &HTTPAccessLogDAOWrapper{
|
dao = &HTTPAccessLogDAOWrapper{
|
||||||
DAO: SharedHTTPAccessLogDAO,
|
DAO: SharedHTTPAccessLogDAO,
|
||||||
@@ -168,8 +180,8 @@ Loop:
|
|||||||
|
|
||||||
// CreateHTTPAccessLog 写入单条访问日志
|
// CreateHTTPAccessLog 写入单条访问日志
|
||||||
func (this *HTTPAccessLogDAO) CreateHTTPAccessLog(tx *dbs.Tx, dao *HTTPAccessLogDAO, accessLog *pb.HTTPAccessLog) error {
|
func (this *HTTPAccessLogDAO) CreateHTTPAccessLog(tx *dbs.Tx, dao *HTTPAccessLogDAO, accessLog *pb.HTTPAccessLog) error {
|
||||||
day := timeutil.Format("Ymd", time.Unix(accessLog.Timestamp, 0))
|
var day = timeutil.Format("Ymd", time.Unix(accessLog.Timestamp, 0))
|
||||||
tableDef, err := findHTTPAccessLogTable(dao.Instance, day, false)
|
tableDef, err := SharedHTTPAccessLogManager.FindTable(dao.Instance, day, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -203,27 +215,17 @@ func (this *HTTPAccessLogDAO) CreateHTTPAccessLog(tx *dbs.Tx, dao *HTTPAccessLog
|
|||||||
}
|
}
|
||||||
fields["content"] = content
|
fields["content"] = content
|
||||||
|
|
||||||
_, err = dao.Query(tx).
|
var lastId int64
|
||||||
|
lastId, err = dao.Query(tx).
|
||||||
Table(tableDef.Name).
|
Table(tableDef.Name).
|
||||||
Sets(fields).
|
Sets(fields).
|
||||||
Insert()
|
Insert()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// 是否为 Error 1146: Table 'xxx.xxx' doesn't exist 如果是,则创建表之后重试
|
return err
|
||||||
if strings.Contains(err.Error(), "1146") {
|
}
|
||||||
tableDef, err = findHTTPAccessLogTable(dao.Instance, day, true)
|
|
||||||
if err != nil {
|
if accessLogEnableAutoPartial && accessLogRowsPerTable > 0 && lastId%accessLogRowsPerTable == 0 {
|
||||||
return err
|
SharedHTTPAccessLogManager.ResetTable(dao.Instance, day)
|
||||||
}
|
|
||||||
_, err = dao.Query(tx).
|
|
||||||
Table(tableDef.Name).
|
|
||||||
Sets(fields).
|
|
||||||
Insert()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
remotelogs.Error("HTTP_ACCESS_LOG", err.Error())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -233,6 +235,10 @@ func (this *HTTPAccessLogDAO) CreateHTTPAccessLog(tx *dbs.Tx, dao *HTTPAccessLog
|
|||||||
func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx, lastRequestId string,
|
func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx, lastRequestId string,
|
||||||
size int64,
|
size int64,
|
||||||
day string,
|
day string,
|
||||||
|
hourFrom string,
|
||||||
|
hourTo string,
|
||||||
|
clusterId int64,
|
||||||
|
nodeId int64,
|
||||||
serverId int64,
|
serverId int64,
|
||||||
reverse bool,
|
reverse bool,
|
||||||
hasError bool,
|
hasError bool,
|
||||||
@@ -253,18 +259,36 @@ func (this *HTTPAccessLogDAO) ListAccessLogs(tx *dbs.Tx, lastRequestId string,
|
|||||||
size = 1000
|
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, hourFrom, hourTo, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
|
||||||
if err != nil || int64(len(result)) < size {
|
if err != nil || int64(len(result)) < size {
|
||||||
return
|
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, hourFrom, hourTo, clusterId, nodeId, serverId, reverse, hasError, firewallPolicyId, firewallRuleGroupId, firewallRuleSetId, hasFirewallPolicy, userId, keyword, ip, domain)
|
||||||
hasMore = len(moreResult) > 0
|
hasMore = len(moreResult) > 0
|
||||||
return
|
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,
|
||||||
|
hourFrom string,
|
||||||
|
hourTo string,
|
||||||
|
clusterId int64,
|
||||||
|
nodeId int64,
|
||||||
|
serverId int64,
|
||||||
|
reverse bool,
|
||||||
|
hasError bool,
|
||||||
|
firewallPolicyId int64,
|
||||||
|
firewallRuleGroupId int64,
|
||||||
|
firewallRuleSetId int64,
|
||||||
|
hasFirewallPolicy bool,
|
||||||
|
userId int64,
|
||||||
|
keyword string,
|
||||||
|
ip string,
|
||||||
|
domain string) (result []*HTTPAccessLog, nextLastRequestId string, err error) {
|
||||||
if size <= 0 {
|
if size <= 0 {
|
||||||
return nil, lastRequestId, nil
|
return nil, lastRequestId, nil
|
||||||
}
|
}
|
||||||
@@ -294,30 +318,69 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
locker := sync.Mutex{}
|
// 查询某个集群下的节点
|
||||||
|
var nodeIds = []int64{}
|
||||||
|
if clusterId > 0 {
|
||||||
|
nodeIds, err = SharedNodeDAO.FindAllEnabledNodeIdsWithClusterId(tx, clusterId)
|
||||||
|
if err != nil {
|
||||||
|
remotelogs.Error("DBNODE", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sort.Slice(nodeIds, func(i, j int) bool {
|
||||||
|
return nodeIds[i] < nodeIds[j]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
count := len(daoList)
|
// 准备查询
|
||||||
wg := &sync.WaitGroup{}
|
var tableQueries = []*accessLogTableQuery{}
|
||||||
wg.Add(count)
|
|
||||||
for _, daoWrapper := range daoList {
|
for _, daoWrapper := range daoList {
|
||||||
go func(daoWrapper *HTTPAccessLogDAOWrapper) {
|
var instance = daoWrapper.DAO.Instance
|
||||||
|
tableDefs, err := SharedHTTPAccessLogManager.FindTables(instance, day)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
for _, def := range tableDefs {
|
||||||
|
tableQueries = append(tableQueries, &accessLogTableQuery{
|
||||||
|
daoWrapper: daoWrapper,
|
||||||
|
name: def.Name,
|
||||||
|
hasRemoteAddrField: def.HasRemoteAddr,
|
||||||
|
hasDomainField: def.HasDomain,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var locker = sync.Mutex{}
|
||||||
|
|
||||||
|
var statusPrefixReg = regexp.MustCompile(`status:\s*(\d{3})\b`)
|
||||||
|
var statusRangeReg = regexp.MustCompile(`status:\s*(\d{3})-(\d{3})\b`)
|
||||||
|
|
||||||
|
var count = len(tableQueries)
|
||||||
|
var wg = &sync.WaitGroup{}
|
||||||
|
wg.Add(count)
|
||||||
|
for _, tableQuery := range tableQueries {
|
||||||
|
go func(tableQuery *accessLogTableQuery) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
dao := daoWrapper.DAO
|
var dao = tableQuery.daoWrapper.DAO
|
||||||
|
var query = dao.Query(tx)
|
||||||
tableName, hasRemoteAddrField, hasDomainField, exists, err := findHTTPAccessLogTableName(dao.Instance, day)
|
|
||||||
if err != nil {
|
|
||||||
logs.Println("[DB_NODE]" + err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !exists {
|
|
||||||
// 表格不存在则跳过
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
query := dao.Query(tx)
|
|
||||||
|
|
||||||
// 条件
|
// 条件
|
||||||
|
if nodeId > 0 {
|
||||||
|
query.Attr("nodeId", nodeId)
|
||||||
|
} else if clusterId > 0 {
|
||||||
|
if len(nodeIds) > 0 {
|
||||||
|
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 {
|
if serverId > 0 {
|
||||||
query.Attr("serverId", serverId)
|
query.Attr("serverId", serverId)
|
||||||
} else if userId > 0 && len(serverIds) > 0 {
|
} else if userId > 0 && len(serverIds) > 0 {
|
||||||
@@ -344,7 +407,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
|||||||
// keyword
|
// keyword
|
||||||
if len(ip) > 0 {
|
if len(ip) > 0 {
|
||||||
// TODO 支持IP范围
|
// TODO 支持IP范围
|
||||||
if hasRemoteAddrField {
|
if tableQuery.hasRemoteAddrField {
|
||||||
// IP格式
|
// IP格式
|
||||||
if strings.Contains(ip, ",") || strings.Contains(ip, "-") {
|
if strings.Contains(ip, ",") || strings.Contains(ip, "-") {
|
||||||
rangeConfig, err := shared.ParseIPRange(ip)
|
rangeConfig, err := shared.ParseIPRange(ip)
|
||||||
@@ -354,6 +417,9 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// 去掉IPv6的[]
|
||||||
|
ip = strings.Trim(ip, "[]")
|
||||||
|
|
||||||
query.Attr("remoteAddr", ip)
|
query.Attr("remoteAddr", ip)
|
||||||
query.UseIndex("remoteAddr")
|
query.UseIndex("remoteAddr")
|
||||||
}
|
}
|
||||||
@@ -363,7 +429,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(domain) > 0 {
|
if len(domain) > 0 {
|
||||||
if hasDomainField {
|
if tableQuery.hasDomainField {
|
||||||
if strings.Contains(domain, "*") {
|
if strings.Contains(domain, "*") {
|
||||||
domain = strings.ReplaceAll(domain, "*", "%")
|
domain = strings.ReplaceAll(domain, "*", "%")
|
||||||
domain = regexp.MustCompile(`[^a-zA-Z0-9-.%]`).ReplaceAllString(domain, "")
|
domain = regexp.MustCompile(`[^a-zA-Z0-9-.%]`).ReplaceAllString(domain, "")
|
||||||
@@ -378,11 +444,12 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
|||||||
Param("host1", domain)
|
Param("host1", domain)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(keyword) > 0 {
|
if len(keyword) > 0 {
|
||||||
// remoteAddr
|
// remoteAddr
|
||||||
if hasRemoteAddrField && net.ParseIP(keyword) != nil {
|
if tableQuery.hasRemoteAddrField && net.ParseIP(keyword) != nil {
|
||||||
query.Attr("remoteAddr", keyword)
|
query.Attr("remoteAddr", keyword)
|
||||||
} else if hasRemoteAddrField && regexp.MustCompile(`^ip:.+`).MatchString(keyword) {
|
} else if tableQuery.hasRemoteAddrField && regexp.MustCompile(`^ip:.+`).MatchString(keyword) {
|
||||||
keyword = keyword[3:]
|
keyword = keyword[3:]
|
||||||
pieces := strings.SplitN(keyword, ",", 2)
|
pieces := strings.SplitN(keyword, ",", 2)
|
||||||
if len(pieces) == 1 || len(pieces[1]) == 0 {
|
if len(pieces) == 1 || len(pieces[1]) == 0 {
|
||||||
@@ -390,12 +457,21 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
|||||||
} else {
|
} else {
|
||||||
query.Between("INET_ATON(remoteAddr)", utils.IP2Long(pieces[0]), utils.IP2Long(pieces[1]))
|
query.Between("INET_ATON(remoteAddr)", utils.IP2Long(pieces[0]), utils.IP2Long(pieces[1]))
|
||||||
}
|
}
|
||||||
|
} else if statusRangeReg.MatchString(keyword) {
|
||||||
|
var matches = statusRangeReg.FindStringSubmatch(keyword)
|
||||||
|
query.Between("status", types.Int(matches[1]), types.Int(matches[2]))
|
||||||
|
|
||||||
|
// TODO 处理剩余的关键词
|
||||||
|
} else if statusPrefixReg.MatchString(keyword) {
|
||||||
|
var matches = statusPrefixReg.FindStringSubmatch(keyword)
|
||||||
|
query.Attr("status", matches[1])
|
||||||
|
// TODO 处理剩余的关键词
|
||||||
} else {
|
} else {
|
||||||
if regexp.MustCompile(`^ip:.+`).MatchString(keyword) {
|
if regexp.MustCompile(`^ip:.+`).MatchString(keyword) {
|
||||||
keyword = keyword[3:]
|
keyword = keyword[3:]
|
||||||
}
|
}
|
||||||
|
|
||||||
useOriginKeyword := false
|
var useOriginKeyword = false
|
||||||
|
|
||||||
where := "JSON_EXTRACT(content, '$.remoteAddr') LIKE :keyword OR JSON_EXTRACT(content, '$.requestURI') LIKE :keyword OR JSON_EXTRACT(content, '$.host') LIKE :keyword OR JSON_EXTRACT(content, '$.userAgent') LIKE :keyword"
|
where := "JSON_EXTRACT(content, '$.remoteAddr') LIKE :keyword OR JSON_EXTRACT(content, '$.requestURI') LIKE :keyword OR JSON_EXTRACT(content, '$.host') LIKE :keyword OR JSON_EXTRACT(content, '$.userAgent') LIKE :keyword"
|
||||||
|
|
||||||
@@ -421,13 +497,13 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
|||||||
|
|
||||||
// 响应状态码
|
// 响应状态码
|
||||||
if regexp.MustCompile(`^\d{3}$`).MatchString(keyword) {
|
if regexp.MustCompile(`^\d{3}$`).MatchString(keyword) {
|
||||||
where += " OR JSON_EXTRACT(content, '$.status')=:intKeyword"
|
where += " OR status=:intKeyword"
|
||||||
query.Param("intKeyword", types.Int(keyword))
|
query.Param("intKeyword", types.Int(keyword))
|
||||||
}
|
}
|
||||||
|
|
||||||
if regexp.MustCompile(`^\d{3}-\d{3}$`).MatchString(keyword) {
|
if regexp.MustCompile(`^\d{3}-\d{3}$`).MatchString(keyword) {
|
||||||
pieces := strings.Split(keyword, "-")
|
pieces := strings.Split(keyword, "-")
|
||||||
where += " OR JSON_EXTRACT(content, '$.status') BETWEEN :intKeyword1 AND :intKeyword2"
|
where += " OR status BETWEEN :intKeyword1 AND :intKeyword2"
|
||||||
query.Param("intKeyword1", types.Int(pieces[0]))
|
query.Param("intKeyword1", types.Int(pieces[0]))
|
||||||
query.Param("intKeyword2", types.Int(pieces[1]))
|
query.Param("intKeyword2", types.Int(pieces[1]))
|
||||||
}
|
}
|
||||||
@@ -445,6 +521,20 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hourFrom - hourTo
|
||||||
|
if len(hourFrom) > 0 && len(hourTo) > 0 {
|
||||||
|
var hourFromInt = types.Int(hourFrom)
|
||||||
|
var hourToInt = types.Int(hourTo)
|
||||||
|
if hourFromInt >= 0 && hourFromInt <= 23 && hourToInt >= hourFromInt && hourToInt <= 23 {
|
||||||
|
var y = types.Int(day[:4])
|
||||||
|
var m = types.Int(day[4:6])
|
||||||
|
var d = types.Int(day[6:])
|
||||||
|
var timeFrom = time.Date(y, time.Month(m), d, hourFromInt, 0, 0, 0, time.Local)
|
||||||
|
var timeTo = time.Date(y, time.Month(m), d, hourToInt, 59, 59, 0, time.Local)
|
||||||
|
query.Between("createdAt", timeFrom.Unix(), timeTo.Unix())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// offset
|
// offset
|
||||||
if len(lastRequestId) > 0 {
|
if len(lastRequestId) > 0 {
|
||||||
if !reverse {
|
if !reverse {
|
||||||
@@ -464,20 +554,21 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
|||||||
|
|
||||||
// 开始查询
|
// 开始查询
|
||||||
ones, err := query.
|
ones, err := query.
|
||||||
Table(tableName).
|
Table(tableQuery.name).
|
||||||
Limit(size).
|
Limit(size).
|
||||||
FindAll()
|
FindAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Println("[DB_NODE]" + err.Error())
|
logs.Println("[DB_NODE]" + err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
locker.Lock()
|
locker.Lock()
|
||||||
for _, one := range ones {
|
for _, one := range ones {
|
||||||
accessLog := one.(*HTTPAccessLog)
|
accessLog := one.(*HTTPAccessLog)
|
||||||
result = append(result, accessLog)
|
result = append(result, accessLog)
|
||||||
}
|
}
|
||||||
locker.Unlock()
|
locker.Unlock()
|
||||||
}(daoWrapper)
|
}(tableQuery)
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
@@ -498,7 +589,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx, lastRequestId string, s
|
|||||||
result = result[:size]
|
result = result[:size]
|
||||||
}
|
}
|
||||||
|
|
||||||
requestId := result[len(result)-1].RequestId
|
var requestId = result[len(result)-1].RequestId
|
||||||
if reverse {
|
if reverse {
|
||||||
lists.Reverse(result)
|
lists.Reverse(result)
|
||||||
}
|
}
|
||||||
@@ -530,28 +621,36 @@ func (this *HTTPAccessLogDAO) FindAccessLogWithRequestId(tx *dbs.Tx, requestId s
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
count := len(daoList)
|
// 准备查询
|
||||||
wg := &sync.WaitGroup{}
|
var day = timeutil.FormatTime("Ymd", types.Int64(requestId[:10]))
|
||||||
|
var tableQueries = []*accessLogTableQuery{}
|
||||||
|
for _, daoWrapper := range daoList {
|
||||||
|
var instance = daoWrapper.DAO.Instance
|
||||||
|
tableDefs, err := SharedHTTPAccessLogManager.FindTables(instance, day)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, def := range tableDefs {
|
||||||
|
tableQueries = append(tableQueries, &accessLogTableQuery{
|
||||||
|
daoWrapper: daoWrapper,
|
||||||
|
name: def.Name,
|
||||||
|
hasRemoteAddrField: def.HasRemoteAddr,
|
||||||
|
hasDomainField: def.HasDomain,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var count = len(tableQueries)
|
||||||
|
var wg = &sync.WaitGroup{}
|
||||||
wg.Add(count)
|
wg.Add(count)
|
||||||
var result *HTTPAccessLog = nil
|
var result *HTTPAccessLog = nil
|
||||||
day := timeutil.FormatTime("Ymd", types.Int64(requestId[:10]))
|
for _, tableQuery := range tableQueries {
|
||||||
for _, daoWrapper := range daoList {
|
go func(tableQuery *accessLogTableQuery) {
|
||||||
go func(daoWrapper *HTTPAccessLogDAOWrapper) {
|
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
dao := daoWrapper.DAO
|
var dao = tableQuery.daoWrapper.DAO
|
||||||
|
|
||||||
tableName, _, _, exists, err := findHTTPAccessLogTableName(dao.Instance, day)
|
|
||||||
if err != nil {
|
|
||||||
logs.Println("[DB_NODE]" + err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !exists {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
one, err := dao.Query(tx).
|
one, err := dao.Query(tx).
|
||||||
Table(tableName).
|
Table(tableQuery.name).
|
||||||
Attr("requestId", requestId).
|
Attr("requestId", requestId).
|
||||||
Find()
|
Find()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -561,7 +660,7 @@ func (this *HTTPAccessLogDAO) FindAccessLogWithRequestId(tx *dbs.Tx, requestId s
|
|||||||
if one != nil {
|
if one != nil {
|
||||||
result = one.(*HTTPAccessLog)
|
result = one.(*HTTPAccessLog)
|
||||||
}
|
}
|
||||||
}(daoWrapper)
|
}(tableQuery)
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
return result, nil
|
return result, nil
|
||||||
@@ -597,11 +696,18 @@ func (this *HTTPAccessLogDAO) SetupQueue() {
|
|||||||
config.MaxLength = 100_000
|
config.MaxLength = 100_000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
accessLogEnableAutoPartial = config.EnableAutoPartial
|
||||||
|
if config.RowsPerTable > 0 {
|
||||||
|
accessLogRowsPerTable = config.RowsPerTable
|
||||||
|
}
|
||||||
|
|
||||||
if accessLogQueueMaxLength != config.MaxLength {
|
if accessLogQueueMaxLength != config.MaxLength {
|
||||||
accessLogQueueMaxLength = config.MaxLength
|
accessLogQueueMaxLength = config.MaxLength
|
||||||
oldAccessLogQueue = accessLogQueue
|
oldAccessLogQueue = accessLogQueue
|
||||||
accessLogQueue = make(chan *pb.HTTPAccessLog, config.MaxLength)
|
accessLogQueue = make(chan *pb.HTTPAccessLog, config.MaxLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
remotelogs.Println("HTTP_ACCESS_LOG_QUEUE", "change queue max length: "+types.String(config.MaxLength)+", percent: "+types.String(config.Percent)+", countPerSecond: "+types.String(config.CountPerSecond))
|
if Tea.IsTesting() {
|
||||||
|
remotelogs.Println("HTTP_ACCESS_LOG_QUEUE", "change queue "+string(configJSON))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs(t *testing.T) {
|
|||||||
t.Fatal(err)
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Page(t *testing.T) {
|
|||||||
times := 0 // 防止循环次数太多
|
times := 0 // 防止循环次数太多
|
||||||
for {
|
for {
|
||||||
before := time.Now()
|
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()
|
cost := time.Since(before).Seconds()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -111,7 +111,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Reverse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
before := time.Now()
|
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()
|
cost := time.Since(before).Seconds()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -136,7 +136,7 @@ func TestHTTPAccessLogDAO_ListAccessLogs_Page_NotExists(t *testing.T) {
|
|||||||
times := 0 // 防止循环次数太多
|
times := 0 // 防止循环次数太多
|
||||||
for {
|
for {
|
||||||
before := time.Now()
|
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()
|
cost := time.Since(before).Seconds()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
297
internal/db/models/http_access_log_manager.go
Normal file
297
internal/db/models/http_access_log_manager.go
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||||
|
"github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
"github.com/iwind/TeaGo/lists"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
"regexp"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 访问日志的两个表格形式
|
||||||
|
var accessLogTableMainReg = regexp.MustCompile(`_(\d{8})$`)
|
||||||
|
var accessLogTablePartialReg = regexp.MustCompile(`_(\d{8})_(\d{4})$`)
|
||||||
|
|
||||||
|
var SharedHTTPAccessLogManager = NewHTTPAccessLogManager()
|
||||||
|
|
||||||
|
type HTTPAccessLogManager struct {
|
||||||
|
currentTableMapping map[string]*httpAccessLogDefinition // dsn => def
|
||||||
|
|
||||||
|
locker sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHTTPAccessLogManager() *HTTPAccessLogManager {
|
||||||
|
return &HTTPAccessLogManager{
|
||||||
|
currentTableMapping: map[string]*httpAccessLogDefinition{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindTableNames 读取数据库中某日所有日志表名称
|
||||||
|
func (this *HTTPAccessLogManager) FindTableNames(db *dbs.DB, day string) ([]string, error) {
|
||||||
|
var results = []string{}
|
||||||
|
|
||||||
|
// 需要防止用户设置了表名自动小写
|
||||||
|
for _, prefix := range []string{"edgeHTTPAccessLogs_" + day + "%", "edgehttpaccesslogs_" + day + "%"} {
|
||||||
|
ones, columnNames, err := db.FindOnes(`SHOW TABLES LIKE '` + prefix + `'`)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("query table names error: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
var columnName = columnNames[0]
|
||||||
|
|
||||||
|
for _, one := range ones {
|
||||||
|
var tableName = one[columnName].(string)
|
||||||
|
|
||||||
|
if lists.ContainsString(results, tableName) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if accessLogTableMainReg.MatchString(tableName) || accessLogTablePartialReg.MatchString(tableName) {
|
||||||
|
results = append(results, tableName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 排序
|
||||||
|
sort.Strings(results)
|
||||||
|
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindTables 读取数据库中某日所有日志表
|
||||||
|
func (this *HTTPAccessLogManager) FindTables(db *dbs.DB, day string) ([]*httpAccessLogDefinition, error) {
|
||||||
|
var results = []*httpAccessLogDefinition{}
|
||||||
|
var tableNames = []string{}
|
||||||
|
|
||||||
|
// 需要防止用户设置了表名自动小写
|
||||||
|
for _, prefix := range []string{"edgeHTTPAccessLogs_" + day + "%", "edgehttpaccesslogs_" + day + "%"} {
|
||||||
|
ones, columnNames, err := db.FindOnes(`SHOW TABLES LIKE '` + prefix + `'`)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("query table names error: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
var columnName = columnNames[0]
|
||||||
|
|
||||||
|
for _, one := range ones {
|
||||||
|
var tableName = one[columnName].(string)
|
||||||
|
|
||||||
|
if lists.ContainsString(tableNames, tableName) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if accessLogTableMainReg.MatchString(tableName) {
|
||||||
|
tableNames = append(tableNames, tableName)
|
||||||
|
|
||||||
|
hasRemoteAddrField, hasDomainField, err := this.checkTableFields(db, tableName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
results = append(results, &httpAccessLogDefinition{
|
||||||
|
Name: tableName,
|
||||||
|
HasRemoteAddr: hasRemoteAddrField,
|
||||||
|
HasDomain: hasDomainField,
|
||||||
|
Exists: true,
|
||||||
|
})
|
||||||
|
} else if accessLogTablePartialReg.MatchString(tableName) {
|
||||||
|
tableNames = append(tableNames, tableName)
|
||||||
|
|
||||||
|
results = append(results, &httpAccessLogDefinition{
|
||||||
|
Name: tableName,
|
||||||
|
HasRemoteAddr: true,
|
||||||
|
HasDomain: true,
|
||||||
|
Exists: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 排序
|
||||||
|
sort.Slice(results, func(i, j int) bool {
|
||||||
|
return results[i].Name < results[j].Name
|
||||||
|
})
|
||||||
|
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindTable 根据日期获取表名
|
||||||
|
// 表名组成
|
||||||
|
// - PREFIX_DAY
|
||||||
|
// - PREFIX_DAY_0001
|
||||||
|
func (this *HTTPAccessLogManager) FindTable(db *dbs.DB, day string, force bool) (*httpAccessLogDefinition, error) {
|
||||||
|
this.locker.Lock()
|
||||||
|
defer this.locker.Unlock()
|
||||||
|
|
||||||
|
config, err := db.Config()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var cacheKey = config.Dsn
|
||||||
|
def, ok := this.currentTableMapping[cacheKey]
|
||||||
|
if ok {
|
||||||
|
return def, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
def, err = this.findTableWithoutCache(db, day, force)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentTableMapping[cacheKey] = def
|
||||||
|
return def, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateTable 创建访问日志表格
|
||||||
|
func (this *HTTPAccessLogManager) CreateTable(db *dbs.DB, tableName string) error {
|
||||||
|
_, err := db.Exec("CREATE TABLE `" + tableName + "` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `serverId` int(11) unsigned DEFAULT '0' COMMENT '服务ID',\n `nodeId` int(11) unsigned DEFAULT '0' COMMENT '节点ID',\n `status` int(3) unsigned DEFAULT '0' COMMENT '状态码',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `content` json DEFAULT NULL COMMENT '日志内容',\n `requestId` varchar(128) DEFAULT NULL COMMENT '请求ID',\n `firewallPolicyId` int(11) unsigned DEFAULT '0' COMMENT 'WAF策略ID',\n `firewallRuleGroupId` int(11) unsigned DEFAULT '0' COMMENT 'WAF分组ID',\n `firewallRuleSetId` int(11) unsigned DEFAULT '0' COMMENT 'WAF集ID',\n `firewallRuleId` int(11) unsigned DEFAULT '0' COMMENT 'WAF规则ID',\n `remoteAddr` varchar(64) DEFAULT NULL COMMENT 'IP地址',\n `domain` varchar(128) DEFAULT NULL COMMENT '域名',\n `requestBody` mediumblob COMMENT '请求内容',\n `responseBody` mediumblob COMMENT '响应内容',\n PRIMARY KEY (`id`),\n KEY `serverId` (`serverId`),\n KEY `nodeId` (`nodeId`),\n KEY `serverId_status` (`serverId`,`status`),\n KEY `requestId` (`requestId`),\n KEY `firewallPolicyId` (`firewallPolicyId`),\n KEY `firewallRuleGroupId` (`firewallRuleGroupId`),\n KEY `firewallRuleSetId` (`firewallRuleSetId`),\n KEY `firewallRuleId` (`firewallRuleId`),\n KEY `remoteAddr` (`remoteAddr`),\n KEY `domain` (`domain`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='访问日志';")
|
||||||
|
if err != nil {
|
||||||
|
// 快速判断错误方法
|
||||||
|
mysqlErr, ok := err.(*mysql.MySQLError)
|
||||||
|
if ok && mysqlErr.Number == 1050 { // Error 1050: Table 'xxx' already exists
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 防止二次包装过程中错误丢失的保底错误判断方法
|
||||||
|
if strings.Contains(err.Error(), "Error 1050") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetTable 清除某个数据库表名缓存
|
||||||
|
func (this *HTTPAccessLogManager) ResetTable(db *dbs.DB, day string) {
|
||||||
|
this.locker.Lock()
|
||||||
|
defer this.locker.Unlock()
|
||||||
|
|
||||||
|
config, err := db.Config()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delete(this.currentTableMapping, config.Dsn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找某个表格
|
||||||
|
func (this *HTTPAccessLogManager) findTableWithoutCache(db *dbs.DB, day string, force bool) (*httpAccessLogDefinition, error) {
|
||||||
|
tableNames, err := this.FindTableNames(db, day)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var prefix = "edgeHTTPAccessLogs_" + day
|
||||||
|
|
||||||
|
if len(tableNames) == 0 {
|
||||||
|
if force {
|
||||||
|
err := this.CreateTable(db, prefix)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &httpAccessLogDefinition{
|
||||||
|
Name: prefix,
|
||||||
|
HasRemoteAddr: true,
|
||||||
|
HasDomain: true,
|
||||||
|
Exists: true,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &httpAccessLogDefinition{
|
||||||
|
Name: prefix,
|
||||||
|
HasRemoteAddr: true,
|
||||||
|
HasDomain: true,
|
||||||
|
Exists: false,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastTableName = tableNames[len(tableNames)-1]
|
||||||
|
if !force || !accessLogEnableAutoPartial || accessLogRowsPerTable <= 0 {
|
||||||
|
hasRemoteAddrField, hasDomainField, err := this.checkTableFields(db, lastTableName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &httpAccessLogDefinition{
|
||||||
|
Name: lastTableName,
|
||||||
|
HasRemoteAddr: hasRemoteAddrField,
|
||||||
|
HasDomain: hasDomainField,
|
||||||
|
Exists: true,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否生成下个分表
|
||||||
|
lastId, err := db.FindCol(0, "SELECT id FROM "+lastTableName+" ORDER BY id DESC LIMIT 1")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if lastId != nil {
|
||||||
|
var lastInt64Id = types.Int64(lastId)
|
||||||
|
if accessLogRowsPerTable > 0 && lastInt64Id >= accessLogRowsPerTable {
|
||||||
|
// create next partial table
|
||||||
|
var nextTableName = ""
|
||||||
|
if accessLogTableMainReg.MatchString(lastTableName) {
|
||||||
|
nextTableName = prefix + "_0001"
|
||||||
|
} else if accessLogTablePartialReg.MatchString(lastTableName) {
|
||||||
|
var matches = accessLogTablePartialReg.FindStringSubmatch(lastTableName)
|
||||||
|
if len(matches) < 3 {
|
||||||
|
return nil, errors.New("fatal error: invalid 'accessLogTablePartialReg'")
|
||||||
|
}
|
||||||
|
var lastPartial = matches[2]
|
||||||
|
nextTableName = prefix + "_" + fmt.Sprintf("%04d", types.Int(lastPartial)+1)
|
||||||
|
} else {
|
||||||
|
nextTableName = prefix + "_0001"
|
||||||
|
}
|
||||||
|
|
||||||
|
err = this.CreateTable(db, nextTableName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &httpAccessLogDefinition{
|
||||||
|
Name: nextTableName,
|
||||||
|
HasRemoteAddr: true,
|
||||||
|
HasDomain: true,
|
||||||
|
Exists: true,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查字段
|
||||||
|
hasRemoteAddrField, hasDomainField, err := this.checkTableFields(db, lastTableName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &httpAccessLogDefinition{
|
||||||
|
Name: lastTableName,
|
||||||
|
HasRemoteAddr: hasRemoteAddrField,
|
||||||
|
HasDomain: hasDomainField,
|
||||||
|
Exists: true,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO 考虑缓存检查结果
|
||||||
|
func (this *HTTPAccessLogManager) checkTableFields(db *dbs.DB, tableName string) (hasRemoteAddrField bool, hasDomainField bool, err error) {
|
||||||
|
fields, _, err := db.FindOnes("SHOW FIELDS FROM " + tableName)
|
||||||
|
if err != nil {
|
||||||
|
return false, false, err
|
||||||
|
}
|
||||||
|
for _, field := range fields {
|
||||||
|
var fieldName = field.GetString("Field")
|
||||||
|
if strings.ToLower(fieldName) == strings.ToLower("remoteAddr") {
|
||||||
|
hasRemoteAddrField = true
|
||||||
|
}
|
||||||
|
if strings.ToLower(fieldName) == "domain" {
|
||||||
|
hasDomainField = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
148
internal/db/models/http_access_log_manager_test.go
Normal file
148
internal/db/models/http_access_log_manager_test.go
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package models_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewHTTPAccessLogManager(t *testing.T) {
|
||||||
|
var config = &dbs.DBConfig{
|
||||||
|
Driver: "mysql",
|
||||||
|
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
|
||||||
|
Prefix: "edge",
|
||||||
|
Connections: struct {
|
||||||
|
Pool int `yaml:"pool"`
|
||||||
|
Max int `yaml:"max"`
|
||||||
|
Life string `yaml:"life"`
|
||||||
|
LifeDuration time.Duration `yaml:",omitempty"`
|
||||||
|
}{},
|
||||||
|
Models: struct {
|
||||||
|
Package string `yaml:"package"`
|
||||||
|
}{},
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := dbs.NewInstanceFromConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var manager = models.SharedHTTPAccessLogManager
|
||||||
|
err = manager.CreateTable(db, "accessLog_1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHTTPAccessLogManager_FindTableNames(t *testing.T) {
|
||||||
|
var config = &dbs.DBConfig{
|
||||||
|
Driver: "mysql",
|
||||||
|
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
|
||||||
|
Prefix: "edge",
|
||||||
|
Connections: struct {
|
||||||
|
Pool int `yaml:"pool"`
|
||||||
|
Max int `yaml:"max"`
|
||||||
|
Life string `yaml:"life"`
|
||||||
|
LifeDuration time.Duration `yaml:",omitempty"`
|
||||||
|
}{},
|
||||||
|
Models: struct {
|
||||||
|
Package string `yaml:"package"`
|
||||||
|
}{},
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := dbs.NewInstanceFromConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
var before = time.Now()
|
||||||
|
tables, err := models.SharedHTTPAccessLogManager.FindTables(db, "20220306")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
data, err := json.Marshal(tables)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(string(data))
|
||||||
|
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func TestHTTPAccessLogManager_FindTables(t *testing.T) {
|
||||||
|
var config = &dbs.DBConfig{
|
||||||
|
Driver: "mysql",
|
||||||
|
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
|
||||||
|
Prefix: "edge",
|
||||||
|
Connections: struct {
|
||||||
|
Pool int `yaml:"pool"`
|
||||||
|
Max int `yaml:"max"`
|
||||||
|
Life string `yaml:"life"`
|
||||||
|
LifeDuration time.Duration `yaml:",omitempty"`
|
||||||
|
}{},
|
||||||
|
Models: struct {
|
||||||
|
Package string `yaml:"package"`
|
||||||
|
}{},
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := dbs.NewInstanceFromConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
var before = time.Now()
|
||||||
|
tables, err := models.SharedHTTPAccessLogManager.FindTables(db, "20220306")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
data, err := json.Marshal(tables)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(string(data))
|
||||||
|
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHTTPAccessLogManager_FindTable(t *testing.T) {
|
||||||
|
var config = &dbs.DBConfig{
|
||||||
|
Driver: "mysql",
|
||||||
|
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge_log?charset=utf8mb4&timeout=30s",
|
||||||
|
Prefix: "edge",
|
||||||
|
Connections: struct {
|
||||||
|
Pool int `yaml:"pool"`
|
||||||
|
Max int `yaml:"max"`
|
||||||
|
Life string `yaml:"life"`
|
||||||
|
LifeDuration time.Duration `yaml:",omitempty"`
|
||||||
|
}{},
|
||||||
|
Models: struct {
|
||||||
|
Package string `yaml:"package"`
|
||||||
|
}{},
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := dbs.NewInstanceFromConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
var before = time.Now()
|
||||||
|
tableDef, err := models.SharedHTTPAccessLogManager.FindTable(db, "20220306", false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
data, err := json.Marshal(tableDef)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(string(data))
|
||||||
|
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -95,7 +95,7 @@ func (this *HTTPCachePolicyDAO) FindAllEnabledCachePolicies(tx *dbs.Tx) (result
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateCachePolicy 创建缓存策略
|
// CreateCachePolicy 创建缓存策略
|
||||||
func (this *HTTPCachePolicyDAO) CreateCachePolicy(tx *dbs.Tx, isOn bool, name string, description string, capacityJSON []byte, maxKeys int64, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte) (int64, error) {
|
func (this *HTTPCachePolicyDAO) CreateCachePolicy(tx *dbs.Tx, isOn bool, name string, description string, capacityJSON []byte, maxKeys int64, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte, syncCompressionCache bool) (int64, error) {
|
||||||
op := NewHTTPCachePolicyOperator()
|
op := NewHTTPCachePolicyOperator()
|
||||||
op.State = HTTPCachePolicyStateEnabled
|
op.State = HTTPCachePolicyStateEnabled
|
||||||
op.IsOn = isOn
|
op.IsOn = isOn
|
||||||
@@ -112,6 +112,7 @@ func (this *HTTPCachePolicyDAO) CreateCachePolicy(tx *dbs.Tx, isOn bool, name st
|
|||||||
if len(storageOptionsJSON) > 0 {
|
if len(storageOptionsJSON) > 0 {
|
||||||
op.Options = storageOptionsJSON
|
op.Options = storageOptionsJSON
|
||||||
}
|
}
|
||||||
|
op.SyncCompressionCache = syncCompressionCache
|
||||||
|
|
||||||
// 默认的缓存条件
|
// 默认的缓存条件
|
||||||
cacheRef := &serverconfigs.HTTPCacheRef{
|
cacheRef := &serverconfigs.HTTPCacheRef{
|
||||||
@@ -182,13 +183,19 @@ func (this *HTTPCachePolicyDAO) CreateDefaultCachePolicy(tx *dbs.Tx, name string
|
|||||||
|
|
||||||
var storageOptions = &serverconfigs.HTTPFileCacheStorage{
|
var storageOptions = &serverconfigs.HTTPFileCacheStorage{
|
||||||
Dir: "/opt/cache",
|
Dir: "/opt/cache",
|
||||||
|
MemoryPolicy: &serverconfigs.HTTPCachePolicy{
|
||||||
|
Capacity: &shared.SizeCapacity{
|
||||||
|
Count: 1,
|
||||||
|
Unit: shared.SizeCapacityUnitGB,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
storageOptionsJSON, err := json.Marshal(storageOptions)
|
storageOptionsJSON, err := json.Marshal(storageOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
policyId, err := this.CreateCachePolicy(tx, true, "\""+name+"\"缓存策略", "默认创建的缓存策略", capacityJSON, 0, maxSizeJSON, serverconfigs.CachePolicyStorageFile, storageOptionsJSON)
|
policyId, err := this.CreateCachePolicy(tx, true, "\""+name+"\"缓存策略", "默认创建的缓存策略", capacityJSON, 0, maxSizeJSON, serverconfigs.CachePolicyStorageFile, storageOptionsJSON, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@@ -196,7 +203,7 @@ func (this *HTTPCachePolicyDAO) CreateDefaultCachePolicy(tx *dbs.Tx, name string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateCachePolicy 修改缓存策略
|
// UpdateCachePolicy 修改缓存策略
|
||||||
func (this *HTTPCachePolicyDAO) UpdateCachePolicy(tx *dbs.Tx, policyId int64, isOn bool, name string, description string, capacityJSON []byte, maxKeys int64, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte) error {
|
func (this *HTTPCachePolicyDAO) UpdateCachePolicy(tx *dbs.Tx, policyId int64, isOn bool, name string, description string, capacityJSON []byte, maxKeys int64, maxSizeJSON []byte, storageType string, storageOptionsJSON []byte, syncCompressionCache bool) error {
|
||||||
if policyId <= 0 {
|
if policyId <= 0 {
|
||||||
return errors.New("invalid policyId")
|
return errors.New("invalid policyId")
|
||||||
}
|
}
|
||||||
@@ -217,6 +224,7 @@ func (this *HTTPCachePolicyDAO) UpdateCachePolicy(tx *dbs.Tx, policyId int64, is
|
|||||||
if len(storageOptionsJSON) > 0 {
|
if len(storageOptionsJSON) > 0 {
|
||||||
op.Options = storageOptionsJSON
|
op.Options = storageOptionsJSON
|
||||||
}
|
}
|
||||||
|
op.SyncCompressionCache = syncCompressionCache
|
||||||
err := this.Save(tx, op)
|
err := this.Save(tx, op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -247,6 +255,7 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
|
|||||||
config.IsOn = policy.IsOn == 1
|
config.IsOn = policy.IsOn == 1
|
||||||
config.Name = policy.Name
|
config.Name = policy.Name
|
||||||
config.Description = policy.Description
|
config.Description = policy.Description
|
||||||
|
config.SyncCompressionCache = policy.SyncCompressionCache == 1
|
||||||
|
|
||||||
// capacity
|
// capacity
|
||||||
if IsNotNull(policy.Capacity) {
|
if IsNotNull(policy.Capacity) {
|
||||||
@@ -300,24 +309,38 @@ func (this *HTTPCachePolicyDAO) ComposeCachePolicy(tx *dbs.Tx, policyId int64, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CountAllEnabledHTTPCachePolicies 计算可用缓存策略数量
|
// CountAllEnabledHTTPCachePolicies 计算可用缓存策略数量
|
||||||
func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, keyword string) (int64, error) {
|
func (this *HTTPCachePolicyDAO) CountAllEnabledHTTPCachePolicies(tx *dbs.Tx, clusterId int64, keyword string, storageType string) (int64, error) {
|
||||||
query := this.Query(tx).
|
query := this.Query(tx).
|
||||||
State(HTTPCachePolicyStateEnabled)
|
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 {
|
if len(keyword) > 0 {
|
||||||
query.Where("(name LIKE :keyword)").
|
query.Where("(name LIKE :keyword)").
|
||||||
Param("keyword", "%"+keyword+"%")
|
Param("keyword", "%"+keyword+"%")
|
||||||
}
|
}
|
||||||
|
if len(storageType) > 0 {
|
||||||
|
query.Attr("type", storageType)
|
||||||
|
}
|
||||||
return query.Count()
|
return query.Count()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListEnabledHTTPCachePolicies 列出单页的缓存策略
|
// 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, storageType string, offset int64, size int64) ([]*serverconfigs.HTTPCachePolicy, error) {
|
||||||
query := this.Query(tx).
|
query := this.Query(tx).
|
||||||
State(HTTPCachePolicyStateEnabled)
|
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 {
|
if len(keyword) > 0 {
|
||||||
query.Where("(name LIKE :keyword)").
|
query.Where("(name LIKE :keyword)").
|
||||||
Param("keyword", "%"+keyword+"%")
|
Param("keyword", "%"+keyword+"%")
|
||||||
}
|
}
|
||||||
|
if len(storageType) > 0 {
|
||||||
|
query.Attr("type", storageType)
|
||||||
|
}
|
||||||
ones, err := query.
|
ones, err := query.
|
||||||
ResultPk().
|
ResultPk().
|
||||||
Offset(offset).
|
Offset(offset).
|
||||||
|
|||||||
@@ -2,39 +2,41 @@ package models
|
|||||||
|
|
||||||
// HTTPCachePolicy HTTP缓存策略
|
// HTTPCachePolicy HTTP缓存策略
|
||||||
type HTTPCachePolicy struct {
|
type HTTPCachePolicy struct {
|
||||||
Id uint32 `field:"id"` // ID
|
Id uint32 `field:"id"` // ID
|
||||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||||
UserId uint32 `field:"userId"` // 用户ID
|
UserId uint32 `field:"userId"` // 用户ID
|
||||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||||
IsOn uint8 `field:"isOn"` // 是否启用
|
IsOn uint8 `field:"isOn"` // 是否启用
|
||||||
Name string `field:"name"` // 名称
|
Name string `field:"name"` // 名称
|
||||||
Capacity string `field:"capacity"` // 容量数据
|
Capacity string `field:"capacity"` // 容量数据
|
||||||
MaxKeys uint64 `field:"maxKeys"` // 最多Key值
|
MaxKeys uint64 `field:"maxKeys"` // 最多Key值
|
||||||
MaxSize string `field:"maxSize"` // 最大缓存内容尺寸
|
MaxSize string `field:"maxSize"` // 最大缓存内容尺寸
|
||||||
Type string `field:"type"` // 存储类型
|
Type string `field:"type"` // 存储类型
|
||||||
Options string `field:"options"` // 存储选项
|
Options string `field:"options"` // 存储选项
|
||||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||||
State uint8 `field:"state"` // 状态
|
State uint8 `field:"state"` // 状态
|
||||||
Description string `field:"description"` // 描述
|
Description string `field:"description"` // 描述
|
||||||
Refs string `field:"refs"` // 默认的缓存设置
|
Refs string `field:"refs"` // 默认的缓存设置
|
||||||
|
SyncCompressionCache uint8 `field:"syncCompressionCache"` // 是否同步写入压缩缓存
|
||||||
}
|
}
|
||||||
|
|
||||||
type HTTPCachePolicyOperator struct {
|
type HTTPCachePolicyOperator struct {
|
||||||
Id interface{} // ID
|
Id interface{} // ID
|
||||||
AdminId interface{} // 管理员ID
|
AdminId interface{} // 管理员ID
|
||||||
UserId interface{} // 用户ID
|
UserId interface{} // 用户ID
|
||||||
TemplateId interface{} // 模版ID
|
TemplateId interface{} // 模版ID
|
||||||
IsOn interface{} // 是否启用
|
IsOn interface{} // 是否启用
|
||||||
Name interface{} // 名称
|
Name interface{} // 名称
|
||||||
Capacity interface{} // 容量数据
|
Capacity interface{} // 容量数据
|
||||||
MaxKeys interface{} // 最多Key值
|
MaxKeys interface{} // 最多Key值
|
||||||
MaxSize interface{} // 最大缓存内容尺寸
|
MaxSize interface{} // 最大缓存内容尺寸
|
||||||
Type interface{} // 存储类型
|
Type interface{} // 存储类型
|
||||||
Options interface{} // 存储选项
|
Options interface{} // 存储选项
|
||||||
CreatedAt interface{} // 创建时间
|
CreatedAt interface{} // 创建时间
|
||||||
State interface{} // 状态
|
State interface{} // 状态
|
||||||
Description interface{} // 描述
|
Description interface{} // 描述
|
||||||
Refs interface{} // 默认的缓存设置
|
Refs interface{} // 默认的缓存设置
|
||||||
|
SyncCompressionCache interface{} // 是否同步写入压缩缓存
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHTTPCachePolicyOperator() *HTTPCachePolicyOperator {
|
func NewHTTPCachePolicyOperator() *HTTPCachePolicyOperator {
|
||||||
|
|||||||
@@ -130,6 +130,16 @@ func (this *HTTPFirewallPolicyDAO) CreateFirewallPolicy(tx *dbs.Tx, userId int64
|
|||||||
if len(outboundJSON) > 0 {
|
if len(outboundJSON) > 0 {
|
||||||
op.Outbound = outboundJSON
|
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)
|
err := this.Save(tx, op)
|
||||||
return types.Int64(op.Id), err
|
return types.Int64(op.Id), err
|
||||||
}
|
}
|
||||||
@@ -249,7 +259,7 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicyInbound(tx *dbs.Tx, polic
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateFirewallPolicy 修改策略
|
// 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 {
|
if policyId <= 0 {
|
||||||
return errors.New("invalid policyId")
|
return errors.New("invalid policyId")
|
||||||
}
|
}
|
||||||
@@ -272,6 +282,18 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx, policyId int
|
|||||||
if len(blockOptionsJSON) > 0 {
|
if len(blockOptionsJSON) > 0 {
|
||||||
op.BlockOptions = blockOptionsJSON
|
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)
|
err := this.Save(tx, op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -281,8 +303,12 @@ func (this *HTTPFirewallPolicyDAO) UpdateFirewallPolicy(tx *dbs.Tx, policyId int
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CountAllEnabledFirewallPolicies 计算所有可用的策略数量
|
// 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)
|
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 {
|
if len(keyword) > 0 {
|
||||||
query.Where("(name LIKE :keyword)").
|
query.Where("(name LIKE :keyword)").
|
||||||
Param("keyword", "%"+keyword+"%")
|
Param("keyword", "%"+keyword+"%")
|
||||||
@@ -296,8 +322,12 @@ func (this *HTTPFirewallPolicyDAO) CountAllEnabledFirewallPolicies(tx *dbs.Tx, k
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListEnabledFirewallPolicies 列出单页的策略
|
// 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)
|
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 {
|
if len(keyword) > 0 {
|
||||||
query.Where("(name LIKE :keyword)").
|
query.Where("(name LIKE :keyword)").
|
||||||
Param("keyword", "%"+keyword+"%")
|
Param("keyword", "%"+keyword+"%")
|
||||||
@@ -339,6 +369,7 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
|
|||||||
config.IsOn = policy.IsOn == 1
|
config.IsOn = policy.IsOn == 1
|
||||||
config.Name = policy.Name
|
config.Name = policy.Name
|
||||||
config.Description = policy.Description
|
config.Description = policy.Description
|
||||||
|
config.UseLocalFirewall = policy.UseLocalFirewall == 1
|
||||||
|
|
||||||
if len(policy.Mode) == 0 {
|
if len(policy.Mode) == 0 {
|
||||||
policy.Mode = firewallconfigs.FirewallModeDefend
|
policy.Mode = firewallconfigs.FirewallModeDefend
|
||||||
@@ -411,6 +442,16 @@ func (this *HTTPFirewallPolicyDAO) ComposeFirewallPolicy(tx *dbs.Tx, policyId in
|
|||||||
config.BlockOptions = blockAction
|
config.BlockOptions = blockAction
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 {
|
if cacheMap != nil {
|
||||||
cacheMap.Put(cacheKey, config)
|
cacheMap.Put(cacheKey, config)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,39 +2,43 @@ package models
|
|||||||
|
|
||||||
// HTTPFirewallPolicy HTTP防火墙
|
// HTTPFirewallPolicy HTTP防火墙
|
||||||
type HTTPFirewallPolicy struct {
|
type HTTPFirewallPolicy struct {
|
||||||
Id uint32 `field:"id"` // ID
|
Id uint32 `field:"id"` // ID
|
||||||
TemplateId uint32 `field:"templateId"` // 模版ID
|
TemplateId uint32 `field:"templateId"` // 模版ID
|
||||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||||
UserId uint32 `field:"userId"` // 用户ID
|
UserId uint32 `field:"userId"` // 用户ID
|
||||||
ServerId uint32 `field:"serverId"` // 服务ID
|
ServerId uint32 `field:"serverId"` // 服务ID
|
||||||
GroupId uint32 `field:"groupId"` // 服务分组ID
|
GroupId uint32 `field:"groupId"` // 服务分组ID
|
||||||
State uint8 `field:"state"` // 状态
|
State uint8 `field:"state"` // 状态
|
||||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||||
IsOn uint8 `field:"isOn"` // 是否启用
|
IsOn uint8 `field:"isOn"` // 是否启用
|
||||||
Name string `field:"name"` // 名称
|
Name string `field:"name"` // 名称
|
||||||
Description string `field:"description"` // 描述
|
Description string `field:"description"` // 描述
|
||||||
Inbound string `field:"inbound"` // 入站规则
|
Inbound string `field:"inbound"` // 入站规则
|
||||||
Outbound string `field:"outbound"` // 出站规则
|
Outbound string `field:"outbound"` // 出站规则
|
||||||
BlockOptions string `field:"blockOptions"` // BLOCK选项
|
BlockOptions string `field:"blockOptions"` // BLOCK选项
|
||||||
Mode string `field:"mode"` // 模式
|
Mode string `field:"mode"` // 模式
|
||||||
|
UseLocalFirewall uint8 `field:"useLocalFirewall"` // 是否自动使用本地防火墙
|
||||||
|
SynFlood string `field:"synFlood"` // SynFlood防御设置
|
||||||
}
|
}
|
||||||
|
|
||||||
type HTTPFirewallPolicyOperator struct {
|
type HTTPFirewallPolicyOperator struct {
|
||||||
Id interface{} // ID
|
Id interface{} // ID
|
||||||
TemplateId interface{} // 模版ID
|
TemplateId interface{} // 模版ID
|
||||||
AdminId interface{} // 管理员ID
|
AdminId interface{} // 管理员ID
|
||||||
UserId interface{} // 用户ID
|
UserId interface{} // 用户ID
|
||||||
ServerId interface{} // 服务ID
|
ServerId interface{} // 服务ID
|
||||||
GroupId interface{} // 服务分组ID
|
GroupId interface{} // 服务分组ID
|
||||||
State interface{} // 状态
|
State interface{} // 状态
|
||||||
CreatedAt interface{} // 创建时间
|
CreatedAt interface{} // 创建时间
|
||||||
IsOn interface{} // 是否启用
|
IsOn interface{} // 是否启用
|
||||||
Name interface{} // 名称
|
Name interface{} // 名称
|
||||||
Description interface{} // 描述
|
Description interface{} // 描述
|
||||||
Inbound interface{} // 入站规则
|
Inbound interface{} // 入站规则
|
||||||
Outbound interface{} // 出站规则
|
Outbound interface{} // 出站规则
|
||||||
BlockOptions interface{} // BLOCK选项
|
BlockOptions interface{} // BLOCK选项
|
||||||
Mode interface{} // 模式
|
Mode interface{} // 模式
|
||||||
|
UseLocalFirewall interface{} // 是否自动使用本地防火墙
|
||||||
|
SynFlood interface{} // SynFlood防御设置
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHTTPFirewallPolicyOperator() *HTTPFirewallPolicyOperator {
|
func NewHTTPFirewallPolicyOperator() *HTTPFirewallPolicyOperator {
|
||||||
|
|||||||
@@ -434,6 +434,18 @@ func (this *HTTPWebDAO) ComposeWebConfig(tx *dbs.Tx, webId int64, cacheMap *util
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 请求脚本
|
||||||
|
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 {
|
if cacheMap != nil {
|
||||||
cacheMap.Put(cacheKey, config)
|
cacheMap.Put(cacheKey, config)
|
||||||
}
|
}
|
||||||
@@ -1119,6 +1131,43 @@ func (this *HTTPWebDAO) FindWebRequestLimit(tx *dbs.Tx, webId int64) (*servercon
|
|||||||
return config, nil
|
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 通知更新
|
// NotifyUpdate 通知更新
|
||||||
func (this *HTTPWebDAO) NotifyUpdate(tx *dbs.Tx, webId int64) error {
|
func (this *HTTPWebDAO) NotifyUpdate(tx *dbs.Tx, webId int64) error {
|
||||||
// server
|
// server
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ type HTTPWeb struct {
|
|||||||
RemoteAddr string `field:"remoteAddr"` // 客户端IP配置
|
RemoteAddr string `field:"remoteAddr"` // 客户端IP配置
|
||||||
MergeSlashes uint8 `field:"mergeSlashes"` // 是否合并路径中的斜杠
|
MergeSlashes uint8 `field:"mergeSlashes"` // 是否合并路径中的斜杠
|
||||||
RequestLimit string `field:"requestLimit"` // 请求限制
|
RequestLimit string `field:"requestLimit"` // 请求限制
|
||||||
|
RequestScripts string `field:"requestScripts"` // 请求脚本
|
||||||
}
|
}
|
||||||
|
|
||||||
type HTTPWebOperator struct {
|
type HTTPWebOperator struct {
|
||||||
@@ -69,6 +70,7 @@ type HTTPWebOperator struct {
|
|||||||
RemoteAddr interface{} // 客户端IP配置
|
RemoteAddr interface{} // 客户端IP配置
|
||||||
MergeSlashes interface{} // 是否合并路径中的斜杠
|
MergeSlashes interface{} // 是否合并路径中的斜杠
|
||||||
RequestLimit interface{} // 请求限制
|
RequestLimit interface{} // 请求限制
|
||||||
|
RequestScripts interface{} // 请求脚本
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHTTPWebOperator() *HTTPWebOperator {
|
func NewHTTPWebOperator() *HTTPWebOperator {
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package models
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
"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/utils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
@@ -19,6 +21,20 @@ const (
|
|||||||
IPItemStateDisabled = 0 // 已禁用
|
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
|
type IPItemType = string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -156,7 +172,7 @@ func (this *IPItemDAO) CreateIPItem(tx *dbs.Tx,
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
op := NewIPItemOperator()
|
var op = NewIPItemOperator()
|
||||||
op.ListId = listId
|
op.ListId = listId
|
||||||
op.IpFrom = ipFrom
|
op.IpFrom = ipFrom
|
||||||
op.IpTo = ipTo
|
op.IpTo = ipTo
|
||||||
@@ -179,6 +195,11 @@ func (this *IPItemDAO) CreateIPItem(tx *dbs.Tx,
|
|||||||
op.SourceHTTPFirewallRuleGroupId = sourceHTTPFirewallRuleGroupId
|
op.SourceHTTPFirewallRuleGroupId = sourceHTTPFirewallRuleGroupId
|
||||||
op.SourceHTTPFirewallRuleSetId = sourceHTTPFirewallRuleSetId
|
op.SourceHTTPFirewallRuleSetId = sourceHTTPFirewallRuleSetId
|
||||||
|
|
||||||
|
var autoAdded = listId == firewallconfigs.GlobalListId || sourceNodeId > 0 || sourceServerId > 0 || sourceHTTPFirewallPolicyId > 0
|
||||||
|
if autoAdded {
|
||||||
|
op.IsRead = 0
|
||||||
|
}
|
||||||
|
|
||||||
op.State = IPItemStateEnabled
|
op.State = IPItemStateEnabled
|
||||||
err = this.Save(tx, op)
|
err = this.Save(tx, op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -186,8 +207,8 @@ func (this *IPItemDAO) CreateIPItem(tx *dbs.Tx,
|
|||||||
}
|
}
|
||||||
itemId := types.Int64(op.Id)
|
itemId := types.Int64(op.Id)
|
||||||
|
|
||||||
// 全局名单不需要即时更新,防止数量过多而导致性能问题
|
// 自动加入名单不需要即时更新,防止数量过多而导致性能问题
|
||||||
if listId == firewallconfigs.GlobalListId {
|
if autoAdded {
|
||||||
return itemId, nil
|
return itemId, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,35 +307,6 @@ func (this *IPItemDAO) ListIPItemsWithListId(tx *dbs.Tx, listId int64, keyword s
|
|||||||
|
|
||||||
// ListIPItemsAfterVersion 根据版本号查找IP列表
|
// ListIPItemsAfterVersion 根据版本号查找IP列表
|
||||||
func (this *IPItemDAO) ListIPItemsAfterVersion(tx *dbs.Tx, version int64, size int64) (result []*IPItem, err error) {
|
func (this *IPItemDAO) ListIPItemsAfterVersion(tx *dbs.Tx, version int64, size int64) (result []*IPItem, err error) {
|
||||||
// 将过期的设置为已删除,这样是为了在 expiredAt<UNIX_TIMESTAMP()边缘节点让过期的IP有一个执行删除的机会
|
|
||||||
ones, _, err := this.Query(tx).
|
|
||||||
ResultPk().
|
|
||||||
Where("(expiredAt>0 AND expiredAt<=:timestamp)").
|
|
||||||
Param("timestamp", time.Now().Unix()).
|
|
||||||
State(IPItemStateEnabled).
|
|
||||||
Limit(100).
|
|
||||||
FindOnes()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for _, one := range ones {
|
|
||||||
var expiredId = one.GetInt64("id")
|
|
||||||
newVersion, err := SharedIPListDAO.IncreaseVersion(tx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_, err = this.Query(tx).
|
|
||||||
Pk(expiredId).
|
|
||||||
Set("state", IPItemStateDisabled).
|
|
||||||
Set("expiredAt", 0).
|
|
||||||
Set("version", newVersion).
|
|
||||||
Update()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = this.Query(tx).
|
_, err = this.Query(tx).
|
||||||
// 这里不要设置状态参数,因为我们要知道哪些是删除的
|
// 这里不要设置状态参数,因为我们要知道哪些是删除的
|
||||||
Gt("version", version).
|
Gt("version", version).
|
||||||
@@ -379,7 +371,7 @@ func (this *IPItemDAO) ExistsEnabledItem(tx *dbs.Tx, itemId int64) (bool, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CountAllEnabledIPItems 计算数量
|
// CountAllEnabledIPItems 计算数量
|
||||||
func (this *IPItemDAO) CountAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64) (int64, error) {
|
func (this *IPItemDAO) CountAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64, unread bool) (int64, error) {
|
||||||
var query = this.Query(tx)
|
var query = this.Query(tx)
|
||||||
if len(ip) > 0 {
|
if len(ip) > 0 {
|
||||||
query.Attr("ipFrom", ip)
|
query.Attr("ipFrom", ip)
|
||||||
@@ -389,6 +381,9 @@ func (this *IPItemDAO) CountAllEnabledIPItems(tx *dbs.Tx, ip string, listId int6
|
|||||||
} else {
|
} else {
|
||||||
query.Where("(listId=" + types.String(firewallconfigs.GlobalListId) + " OR listId IN (SELECT id FROM " + SharedIPListDAO.Table + " WHERE state=1))")
|
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.
|
return query.
|
||||||
State(IPItemStateEnabled).
|
State(IPItemStateEnabled).
|
||||||
Where("(expiredAt=0 OR expiredAt>:expiredAt)").
|
Where("(expiredAt=0 OR expiredAt>:expiredAt)").
|
||||||
@@ -397,7 +392,7 @@ func (this *IPItemDAO) CountAllEnabledIPItems(tx *dbs.Tx, ip string, listId int6
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListAllEnabledIPItems 搜索所有IP
|
// ListAllEnabledIPItems 搜索所有IP
|
||||||
func (this *IPItemDAO) ListAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64, offset int64, size int64) (result []*IPItem, err error) {
|
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)
|
var query = this.Query(tx)
|
||||||
if len(ip) > 0 {
|
if len(ip) > 0 {
|
||||||
query.Attr("ipFrom", ip)
|
query.Attr("ipFrom", ip)
|
||||||
@@ -407,6 +402,9 @@ func (this *IPItemDAO) ListAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64
|
|||||||
} else {
|
} else {
|
||||||
query.Where("(listId=" + types.String(firewallconfigs.GlobalListId) + " OR listId IN (SELECT id FROM " + SharedIPListDAO.Table + " WHERE state=1))")
|
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.
|
_, err = query.
|
||||||
State(IPItemStateEnabled).
|
State(IPItemStateEnabled).
|
||||||
Where("(expiredAt=0 OR expiredAt>:expiredAt)").
|
Where("(expiredAt=0 OR expiredAt>:expiredAt)").
|
||||||
@@ -419,6 +417,59 @@ func (this *IPItemDAO) ListAllEnabledIPItems(tx *dbs.Tx, ip string, listId int64
|
|||||||
return
|
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 通知更新
|
// NotifyUpdate 通知更新
|
||||||
func (this *IPItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64) error {
|
func (this *IPItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64) error {
|
||||||
// 获取ListId
|
// 获取ListId
|
||||||
@@ -445,7 +496,7 @@ func (this *IPItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, clusterId := range clusterIds {
|
for _, clusterId := range clusterIds {
|
||||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeIPItemChanged)
|
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeIPItemChanged)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -453,7 +504,7 @@ func (this *IPItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64) error {
|
|||||||
} else {
|
} else {
|
||||||
clusterIds, err := SharedNodeClusterDAO.FindAllEnabledNodeClusterIds(tx)
|
clusterIds, err := SharedNodeClusterDAO.FindAllEnabledNodeClusterIds(tx)
|
||||||
for _, clusterId := range clusterIds {
|
for _, clusterId := range clusterIds {
|
||||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeIPItemChanged)
|
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeIPItemChanged)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -505,7 +556,7 @@ func (this *IPItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64) error {
|
|||||||
|
|
||||||
if len(resultClusterIds) > 0 {
|
if len(resultClusterIds) > 0 {
|
||||||
for _, clusterId := range resultClusterIds {
|
for _, clusterId := range resultClusterIds {
|
||||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeIPItemChanged)
|
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeIPItemChanged)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
"github.com/iwind/TeaGo/dbs"
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
"github.com/iwind/TeaGo/rands"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIPItemDAO_NotifyClustersUpdate(t *testing.T) {
|
func TestIPItemDAO_NotifyClustersUpdate(t *testing.T) {
|
||||||
@@ -27,3 +31,34 @@ func TestIPItemDAO_DisableIPItemsWithListId(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Log("ok")
|
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")
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ type IPItem struct {
|
|||||||
SourceHTTPFirewallPolicyId uint32 `field:"sourceHTTPFirewallPolicyId"` // 来源策略ID
|
SourceHTTPFirewallPolicyId uint32 `field:"sourceHTTPFirewallPolicyId"` // 来源策略ID
|
||||||
SourceHTTPFirewallRuleGroupId uint32 `field:"sourceHTTPFirewallRuleGroupId"` // 来源规则集分组ID
|
SourceHTTPFirewallRuleGroupId uint32 `field:"sourceHTTPFirewallRuleGroupId"` // 来源规则集分组ID
|
||||||
SourceHTTPFirewallRuleSetId uint32 `field:"sourceHTTPFirewallRuleSetId"` // 来源规则集ID
|
SourceHTTPFirewallRuleSetId uint32 `field:"sourceHTTPFirewallRuleSetId"` // 来源规则集ID
|
||||||
|
IsRead uint8 `field:"isRead"` // 是否已读
|
||||||
}
|
}
|
||||||
|
|
||||||
type IPItemOperator struct {
|
type IPItemOperator struct {
|
||||||
@@ -47,6 +48,7 @@ type IPItemOperator struct {
|
|||||||
SourceHTTPFirewallPolicyId interface{} // 来源策略ID
|
SourceHTTPFirewallPolicyId interface{} // 来源策略ID
|
||||||
SourceHTTPFirewallRuleGroupId interface{} // 来源规则集分组ID
|
SourceHTTPFirewallRuleGroupId interface{} // 来源规则集分组ID
|
||||||
SourceHTTPFirewallRuleSetId interface{} // 来源规则集ID
|
SourceHTTPFirewallRuleSetId interface{} // 来源规则集ID
|
||||||
|
IsRead interface{} // 是否已读
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIPItemOperator() *IPItemOperator {
|
func NewIPItemOperator() *IPItemOperator {
|
||||||
|
|||||||
@@ -184,6 +184,10 @@ func (this *IPListDAO) IncreaseVersion(tx *dbs.Tx) (int64, error) {
|
|||||||
|
|
||||||
// CheckUserIPList 检查用户权限
|
// CheckUserIPList 检查用户权限
|
||||||
func (this *IPListDAO) CheckUserIPList(tx *dbs.Tx, userId int64, listId int64) error {
|
func (this *IPListDAO) CheckUserIPList(tx *dbs.Tx, userId int64, listId int64) error {
|
||||||
|
if userId == 0 || listId == 0 {
|
||||||
|
return ErrNotFound
|
||||||
|
}
|
||||||
|
|
||||||
ok, err := this.Query(tx).
|
ok, err := this.Query(tx).
|
||||||
Pk(listId).
|
Pk(listId).
|
||||||
Attr("userId", userId).
|
Attr("userId", userId).
|
||||||
@@ -194,6 +198,18 @@ func (this *IPListDAO) CheckUserIPList(tx *dbs.Tx, userId int64, listId int64) e
|
|||||||
if ok {
|
if ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查是否被用户的服务所使用
|
||||||
|
policyIds, err := SharedHTTPFirewallPolicyDAO.FindEnabledFirewallPolicyIdsWithIPListId(tx, listId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, policyId := range policyIds {
|
||||||
|
if SharedHTTPFirewallPolicyDAO.CheckUserFirewallPolicy(tx, userId, policyId) == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ErrNotFound
|
return ErrNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +300,7 @@ func (this *IPListDAO) NotifyUpdate(tx *dbs.Tx, listId int64, taskType NodeTaskT
|
|||||||
|
|
||||||
if len(resultClusterIds) > 0 {
|
if len(resultClusterIds) > 0 {
|
||||||
for _, clusterId := range resultClusterIds {
|
for _, clusterId := range resultClusterIds {
|
||||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, taskType)
|
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, taskType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ func init() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建管理员日志
|
// CreateLog 创建管理员日志
|
||||||
func (this *LogDAO) CreateLog(tx *dbs.Tx, adminType string, adminId int64, level string, description string, action string, ip string) error {
|
func (this *LogDAO) CreateLog(tx *dbs.Tx, adminType string, adminId int64, level string, description string, action string, ip string) error {
|
||||||
op := NewLogOperator()
|
op := NewLogOperator()
|
||||||
op.Level = level
|
op.Level = level
|
||||||
@@ -57,7 +57,7 @@ func (this *LogDAO) CreateLog(tx *dbs.Tx, adminType string, adminId int64, level
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算所有日志数量
|
// CountLogs 计算所有日志数量
|
||||||
func (this *LogDAO) CountLogs(tx *dbs.Tx, dayFrom string, dayTo string, keyword string, userType string) (int64, error) {
|
func (this *LogDAO) CountLogs(tx *dbs.Tx, dayFrom string, dayTo string, keyword string, userType string) (int64, error) {
|
||||||
dayFrom = this.formatDay(dayFrom)
|
dayFrom = this.formatDay(dayFrom)
|
||||||
dayTo = this.formatDay(dayTo)
|
dayTo = this.formatDay(dayTo)
|
||||||
@@ -86,7 +86,7 @@ func (this *LogDAO) CountLogs(tx *dbs.Tx, dayFrom string, dayTo string, keyword
|
|||||||
return query.Count()
|
return query.Count()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 列出单页日志
|
// ListLogs 列出单页日志
|
||||||
func (this *LogDAO) ListLogs(tx *dbs.Tx, offset int64, size int64, dayFrom string, dayTo string, keyword string, userType string) (result []*Log, err error) {
|
func (this *LogDAO) ListLogs(tx *dbs.Tx, offset int64, size int64, dayFrom string, dayTo string, keyword string, userType string) (result []*Log, err error) {
|
||||||
dayFrom = this.formatDay(dayFrom)
|
dayFrom = this.formatDay(dayFrom)
|
||||||
dayTo = this.formatDay(dayTo)
|
dayTo = this.formatDay(dayTo)
|
||||||
@@ -120,7 +120,7 @@ func (this *LogDAO) ListLogs(tx *dbs.Tx, offset int64, size int64, dayFrom strin
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 物理删除日志
|
// DeleteLogPermanently 物理删除日志
|
||||||
func (this *LogDAO) DeleteLogPermanently(tx *dbs.Tx, logId int64) error {
|
func (this *LogDAO) DeleteLogPermanently(tx *dbs.Tx, logId int64) error {
|
||||||
if logId <= 0 {
|
if logId <= 0 {
|
||||||
return errors.New("invalid logId")
|
return errors.New("invalid logId")
|
||||||
@@ -129,14 +129,14 @@ func (this *LogDAO) DeleteLogPermanently(tx *dbs.Tx, logId int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 物理删除所有日志
|
// DeleteAllLogsPermanently 物理删除所有日志
|
||||||
func (this *LogDAO) DeleteAllLogsPermanently(tx *dbs.Tx) error {
|
func (this *LogDAO) DeleteAllLogsPermanently(tx *dbs.Tx) error {
|
||||||
_, err := this.Query(tx).
|
_, err := this.Query(tx).
|
||||||
Delete()
|
Delete()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 物理删除某些天之前的日志
|
// DeleteLogsPermanentlyBeforeDays 物理删除某些天之前的日志
|
||||||
func (this *LogDAO) DeleteLogsPermanentlyBeforeDays(tx *dbs.Tx, days int) error {
|
func (this *LogDAO) DeleteLogsPermanentlyBeforeDays(tx *dbs.Tx, days int) error {
|
||||||
if days <= 0 {
|
if days <= 0 {
|
||||||
days = 0
|
days = 0
|
||||||
@@ -148,7 +148,7 @@ func (this *LogDAO) DeleteLogsPermanentlyBeforeDays(tx *dbs.Tx, days int) error
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算当前日志容量大小
|
// SumLogsSize 计算当前日志容量大小
|
||||||
func (this *LogDAO) SumLogsSize() (int64, error) {
|
func (this *LogDAO) SumLogsSize() (int64, error) {
|
||||||
col, err := this.Instance.FindCol(0, "SELECT DATA_LENGTH FROM information_schema.TABLES WHERE TABLE_SCHEMA=? AND TABLE_NAME=? LIMIT 1", this.Instance.Name(), this.Table)
|
col, err := this.Instance.FindCol(0, "SELECT DATA_LENGTH FROM information_schema.TABLES WHERE TABLE_SCHEMA=? AND TABLE_NAME=? LIMIT 1", this.Instance.Name(), this.Table)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -334,7 +334,7 @@ func (this *MetricItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64, isPublic bool)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, clusterId := range clusterIds {
|
for _, clusterId := range clusterIds {
|
||||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeConfigChanged)
|
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeConfigChanged)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -346,7 +346,7 @@ func (this *MetricItemDAO) NotifyUpdate(tx *dbs.Tx, itemId int64, isPublic bool)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, clusterId := range clusterIds {
|
for _, clusterId := range clusterIds {
|
||||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeConfigChanged)
|
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeConfigChanged)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ func (this *NSDomainDAO) NotifyUpdate(tx *dbs.Tx, domainId int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if clusterId > 0 {
|
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
|
return nil
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ func (this *NSKeyDAO) NotifyUpdate(tx *dbs.Tx, keyId int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if clusterId > 0 {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ func (this *NSRecordDAO) NotifyUpdate(tx *dbs.Tx, recordId int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if clusterId > 0 {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ func (this *NSRouteDAO) NotifyUpdate(tx *dbs.Tx) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, clusterId := range clusterIds {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ func (this *NodeClusterDAO) CreateCluster(tx *dbs.Tx, adminId int64, name string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateCluster 修改集群
|
// UpdateCluster 修改集群
|
||||||
func (this *NodeClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name string, grantId int64, installDir string, timezone string, nodeMaxThreads int32, nodeTCPMaxConnections int32) 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 {
|
if clusterId <= 0 {
|
||||||
return errors.New("invalid clusterId")
|
return errors.New("invalid clusterId")
|
||||||
}
|
}
|
||||||
@@ -198,6 +198,7 @@ func (this *NodeClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name stri
|
|||||||
nodeTCPMaxConnections = 0
|
nodeTCPMaxConnections = 0
|
||||||
}
|
}
|
||||||
op.NodeTCPMaxConnections = nodeTCPMaxConnections
|
op.NodeTCPMaxConnections = nodeTCPMaxConnections
|
||||||
|
op.AutoOpenPorts = autoOpenPorts
|
||||||
|
|
||||||
err := this.Save(tx, op)
|
err := this.Save(tx, op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -206,6 +207,14 @@ func (this *NodeClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name stri
|
|||||||
return this.NotifyUpdate(tx, clusterId)
|
return this.NotifyUpdate(tx, clusterId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateClusterIsPinned 设置集群是否置顶
|
||||||
|
func (this *NodeClusterDAO) UpdateClusterIsPinned(tx *dbs.Tx, clusterId int64, isPinned bool) error {
|
||||||
|
return this.Query(tx).
|
||||||
|
Pk(clusterId).
|
||||||
|
Set("isPinned", isPinned).
|
||||||
|
UpdateQuickly()
|
||||||
|
}
|
||||||
|
|
||||||
// CountAllEnabledClusters 计算所有集群数量
|
// CountAllEnabledClusters 计算所有集群数量
|
||||||
func (this *NodeClusterDAO) CountAllEnabledClusters(tx *dbs.Tx, keyword string) (int64, error) {
|
func (this *NodeClusterDAO) CountAllEnabledClusters(tx *dbs.Tx, keyword string) (int64, error) {
|
||||||
query := this.Query(tx).
|
query := this.Query(tx).
|
||||||
@@ -229,6 +238,7 @@ func (this *NodeClusterDAO) ListEnabledClusters(tx *dbs.Tx, keyword string, offs
|
|||||||
Offset(offset).
|
Offset(offset).
|
||||||
Limit(size).
|
Limit(size).
|
||||||
Slice(&result).
|
Slice(&result).
|
||||||
|
Desc("isPinned").
|
||||||
DescPk().
|
DescPk().
|
||||||
FindAll()
|
FindAll()
|
||||||
return
|
return
|
||||||
@@ -274,7 +284,7 @@ func (this *NodeClusterDAO) FindAllAPINodeAddrsWithCluster(tx *dbs.Tx, clusterId
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, apiNodeId := range apiNodeIds {
|
for _, apiNodeId := range apiNodeIds {
|
||||||
apiNode, err := SharedAPINodeDAO.FindEnabledAPINode(tx, apiNodeId)
|
apiNode, err := SharedAPINodeDAO.FindEnabledAPINode(tx, apiNodeId, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -887,7 +897,7 @@ func (this *NodeClusterDAO) FindClusterBasicInfo(tx *dbs.Tx, clusterId int64, ca
|
|||||||
|
|
||||||
cluster, err := this.Query(tx).
|
cluster, err := this.Query(tx).
|
||||||
Pk(clusterId).
|
Pk(clusterId).
|
||||||
Result("timeZone", "nodeMaxThreads", "nodeTCPMaxConnections", "cachePolicyId", "httpFirewallPolicyId").
|
Result("timeZone", "nodeMaxThreads", "nodeTCPMaxConnections", "cachePolicyId", "httpFirewallPolicyId", "autoOpenPorts").
|
||||||
Find()
|
Find()
|
||||||
if err != nil || cluster == nil {
|
if err != nil || cluster == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -900,7 +910,7 @@ func (this *NodeClusterDAO) FindClusterBasicInfo(tx *dbs.Tx, clusterId int64, ca
|
|||||||
|
|
||||||
// NotifyUpdate 通知更新
|
// NotifyUpdate 通知更新
|
||||||
func (this *NodeClusterDAO) NotifyUpdate(tx *dbs.Tx, clusterId int64) error {
|
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更新
|
// NotifyDNSUpdate 通知DNS更新
|
||||||
|
|||||||
@@ -177,5 +177,5 @@ func (this *NodeClusterMetricItemDAO) ExistsClusterItem(tx *dbs.Tx, clusterId in
|
|||||||
|
|
||||||
// NotifyUpdate 通知更新
|
// NotifyUpdate 通知更新
|
||||||
func (this *NodeClusterMetricItemDAO) NotifyUpdate(tx *dbs.Tx, clusterId int64) error {
|
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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ type NodeCluster struct {
|
|||||||
TimeZone string `field:"timeZone"` // 时区
|
TimeZone string `field:"timeZone"` // 时区
|
||||||
NodeMaxThreads uint32 `field:"nodeMaxThreads"` // 节点最大线程数
|
NodeMaxThreads uint32 `field:"nodeMaxThreads"` // 节点最大线程数
|
||||||
NodeTCPMaxConnections uint32 `field:"nodeTCPMaxConnections"` // TCP最大连接数
|
NodeTCPMaxConnections uint32 `field:"nodeTCPMaxConnections"` // TCP最大连接数
|
||||||
|
AutoOpenPorts uint8 `field:"autoOpenPorts"` // 是否自动尝试开放端口
|
||||||
|
IsPinned uint8 `field:"isPinned"` // 是否置顶
|
||||||
}
|
}
|
||||||
|
|
||||||
type NodeClusterOperator struct {
|
type NodeClusterOperator struct {
|
||||||
@@ -59,6 +61,8 @@ type NodeClusterOperator struct {
|
|||||||
TimeZone interface{} // 时区
|
TimeZone interface{} // 时区
|
||||||
NodeMaxThreads interface{} // 节点最大线程数
|
NodeMaxThreads interface{} // 节点最大线程数
|
||||||
NodeTCPMaxConnections interface{} // TCP最大连接数
|
NodeTCPMaxConnections interface{} // TCP最大连接数
|
||||||
|
AutoOpenPorts interface{} // 是否自动尝试开放端口
|
||||||
|
IsPinned interface{} // 是否置顶
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNodeClusterOperator() *NodeClusterOperator {
|
func NewNodeClusterOperator() *NodeClusterOperator {
|
||||||
|
|||||||
@@ -456,9 +456,26 @@ func (this *NodeDAO) FindEnabledNodeClusterIds(tx *dbs.Tx, nodeId int64) (result
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindEnabledNodeIdsWithClusterId 查找某个集群下的所有节点IDs
|
||||||
|
func (this *NodeDAO) FindEnabledNodeIdsWithClusterId(tx *dbs.Tx, clusterId int64) ([]int64, error) {
|
||||||
|
ones, err := this.Query(tx).
|
||||||
|
Attr("clusterId", clusterId).
|
||||||
|
State(NodeClusterStateEnabled).
|
||||||
|
ResultPk().
|
||||||
|
FindAll()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var result = []int64{}
|
||||||
|
for _, one := range ones {
|
||||||
|
result = append(result, int64(one.(*Node).Id))
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
// FindAllNodeIdsMatch 匹配节点并返回节点ID
|
// FindAllNodeIdsMatch 匹配节点并返回节点ID
|
||||||
func (this *NodeDAO) FindAllNodeIdsMatch(tx *dbs.Tx, clusterId int64, includeSecondaryNodes bool, isOn configutils.BoolState) (result []int64, err error) {
|
func (this *NodeDAO) FindAllNodeIdsMatch(tx *dbs.Tx, clusterId int64, includeSecondaryNodes bool, isOn configutils.BoolState) (result []int64, err error) {
|
||||||
query := this.Query(tx)
|
var query = this.Query(tx)
|
||||||
query.State(NodeStateEnabled)
|
query.State(NodeStateEnabled)
|
||||||
if clusterId > 0 {
|
if clusterId > 0 {
|
||||||
if includeSecondaryNodes {
|
if includeSecondaryNodes {
|
||||||
@@ -518,11 +535,11 @@ func (this *NodeDAO) FindAllEnabledNodeIdsWithClusterId(tx *dbs.Tx, clusterId in
|
|||||||
func (this *NodeDAO) FindAllInactiveNodesWithClusterId(tx *dbs.Tx, clusterId int64) (result []*Node, err error) {
|
func (this *NodeDAO) FindAllInactiveNodesWithClusterId(tx *dbs.Tx, clusterId int64) (result []*Node, err error) {
|
||||||
_, err = this.Query(tx).
|
_, err = this.Query(tx).
|
||||||
State(NodeStateEnabled).
|
State(NodeStateEnabled).
|
||||||
|
Result("id", "name", "status").
|
||||||
Attr("clusterId", clusterId).
|
Attr("clusterId", clusterId).
|
||||||
Attr("isOn", true). // 只监控启用的节点
|
Attr("isOn", true). // 只监控启用的节点
|
||||||
Attr("isInstalled", true). // 只监控已经安装的节点
|
Attr("isInstalled", true). // 只监控已经安装的节点
|
||||||
Attr("isActive", true). // 当前已经在线的
|
Attr("isActive", false).
|
||||||
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)").
|
|
||||||
Result("id", "name").
|
Result("id", "name").
|
||||||
Slice(&result).
|
Slice(&result).
|
||||||
FindAll()
|
FindAll()
|
||||||
@@ -827,6 +844,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
|
|||||||
if clusterIndex == 0 {
|
if clusterIndex == 0 {
|
||||||
config.MaxThreads = int(nodeCluster.NodeMaxThreads)
|
config.MaxThreads = int(nodeCluster.NodeMaxThreads)
|
||||||
config.TCPMaxConnections = int(nodeCluster.NodeTCPMaxConnections)
|
config.TCPMaxConnections = int(nodeCluster.NodeTCPMaxConnections)
|
||||||
|
config.AutoOpenPorts = nodeCluster.AutoOpenPorts == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
clusterIndex++
|
clusterIndex++
|
||||||
@@ -855,6 +873,8 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config.CacheDiskDir = node.CacheDiskDir
|
||||||
|
|
||||||
// TOA
|
// TOA
|
||||||
toaConfig, err := SharedNodeClusterDAO.FindClusterTOAConfig(tx, primaryClusterId, cacheMap)
|
toaConfig, err := SharedNodeClusterDAO.FindClusterTOAConfig(tx, primaryClusterId, cacheMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -916,6 +936,25 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
|
|||||||
|
|
||||||
config.MetricItems = metricItems
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OCSP
|
||||||
|
ocspVersion, err := SharedSSLCertDAO.FindCertOCSPLatestVersion(tx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
config.OCSPVersion = ocspVersion
|
||||||
|
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1192,7 +1231,7 @@ func (this *NodeDAO) UpdateNodeSystem(tx *dbs.Tx, nodeId int64, maxCPU int32) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateNodeCache 设置缓存相关
|
// UpdateNodeCache 设置缓存相关
|
||||||
func (this *NodeDAO) UpdateNodeCache(tx *dbs.Tx, nodeId int64, maxCacheDiskCapacityJSON []byte, maxCacheMemoryCapacityJSON []byte) error {
|
func (this *NodeDAO) UpdateNodeCache(tx *dbs.Tx, nodeId int64, maxCacheDiskCapacityJSON []byte, maxCacheMemoryCapacityJSON []byte, cacheDiskDir string) error {
|
||||||
if nodeId <= 0 {
|
if nodeId <= 0 {
|
||||||
return errors.New("invalid nodeId")
|
return errors.New("invalid nodeId")
|
||||||
}
|
}
|
||||||
@@ -1204,6 +1243,7 @@ func (this *NodeDAO) UpdateNodeCache(tx *dbs.Tx, nodeId int64, maxCacheDiskCapac
|
|||||||
if len(maxCacheMemoryCapacityJSON) > 0 {
|
if len(maxCacheMemoryCapacityJSON) > 0 {
|
||||||
op.MaxCacheMemoryCapacity = maxCacheMemoryCapacityJSON
|
op.MaxCacheMemoryCapacity = maxCacheMemoryCapacityJSON
|
||||||
}
|
}
|
||||||
|
op.CacheDiskDir = cacheDiskDir
|
||||||
err := this.Save(tx, op)
|
err := this.Save(tx, op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -1458,7 +1498,7 @@ func (this *NodeDAO) NotifyUpdate(tx *dbs.Tx, nodeId int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if clusterId > 0 {
|
if clusterId > 0 {
|
||||||
return SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, NodeTaskTypeConfigChanged, 0)
|
return SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, 0, NodeTaskTypeConfigChanged, 0)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
//go:build community
|
//go:build !plus
|
||||||
// +build community
|
// +build !plus
|
||||||
|
|
||||||
package models
|
package models
|
||||||
|
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ func (this *NodeLogDAO) DeleteExpiredLogs(tx *dbs.Tx, days int) error {
|
|||||||
// CountNodeLogs 计算节点日志数量
|
// CountNodeLogs 计算节点日志数量
|
||||||
func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx,
|
func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx,
|
||||||
role string,
|
role string,
|
||||||
|
nodeClusterId int64,
|
||||||
nodeId int64,
|
nodeId int64,
|
||||||
serverId int64,
|
serverId int64,
|
||||||
originId int64,
|
originId int64,
|
||||||
@@ -142,7 +143,8 @@ func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx,
|
|||||||
dayTo string,
|
dayTo string,
|
||||||
keyword string,
|
keyword string,
|
||||||
level string,
|
level string,
|
||||||
isUnread bool) (int64, error) {
|
isUnread bool,
|
||||||
|
tag string) (int64, error) {
|
||||||
query := this.Query(tx)
|
query := this.Query(tx)
|
||||||
if len(role) > 0 {
|
if len(role) > 0 {
|
||||||
query.Attr("role", role)
|
query.Attr("role", role)
|
||||||
@@ -150,11 +152,16 @@ func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx,
|
|||||||
if nodeId > 0 {
|
if nodeId > 0 {
|
||||||
query.Attr("nodeId", nodeId)
|
query.Attr("nodeId", nodeId)
|
||||||
} else {
|
} else {
|
||||||
switch role {
|
if nodeClusterId > 0 {
|
||||||
case nodeconfigs.NodeRoleNode:
|
query.Where("nodeId IN (SELECT id FROM " + SharedNodeDAO.Table + " WHERE clusterId=:nodeClusterId AND state=1)")
|
||||||
query.Where("nodeId IN (SELECT id FROM " + SharedNodeDAO.Table + " WHERE state=1 AND clusterId>0)")
|
query.Param("nodeClusterId", nodeClusterId)
|
||||||
case nodeconfigs.NodeRoleDNS:
|
} else {
|
||||||
query.Where("nodeId IN (SELECT id FROM edgeNSNodes WHERE state=1 AND clusterId > 0)") // 没有用 SharedNSNodeDAO() 因为有包循环引用的问题
|
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 {
|
if serverId > 0 {
|
||||||
@@ -181,6 +188,9 @@ func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx,
|
|||||||
if isUnread {
|
if isUnread {
|
||||||
query.Attr("isRead", 0)
|
query.Attr("isRead", 0)
|
||||||
}
|
}
|
||||||
|
if len(tag) > 0 {
|
||||||
|
query.Like("tag", "%"+tag+"%")
|
||||||
|
}
|
||||||
|
|
||||||
return query.Count()
|
return query.Count()
|
||||||
}
|
}
|
||||||
@@ -188,6 +198,7 @@ func (this *NodeLogDAO) CountNodeLogs(tx *dbs.Tx,
|
|||||||
// ListNodeLogs 列出单页日志
|
// ListNodeLogs 列出单页日志
|
||||||
func (this *NodeLogDAO) ListNodeLogs(tx *dbs.Tx,
|
func (this *NodeLogDAO) ListNodeLogs(tx *dbs.Tx,
|
||||||
role string,
|
role string,
|
||||||
|
nodeClusterId int64,
|
||||||
nodeId int64,
|
nodeId int64,
|
||||||
serverId int64,
|
serverId int64,
|
||||||
originId int64,
|
originId int64,
|
||||||
@@ -198,6 +209,7 @@ func (this *NodeLogDAO) ListNodeLogs(tx *dbs.Tx,
|
|||||||
level string,
|
level string,
|
||||||
fixedState configutils.BoolState,
|
fixedState configutils.BoolState,
|
||||||
isUnread bool,
|
isUnread bool,
|
||||||
|
tag string,
|
||||||
offset int64,
|
offset int64,
|
||||||
size int64) (result []*NodeLog, err error) {
|
size int64) (result []*NodeLog, err error) {
|
||||||
query := this.Query(tx)
|
query := this.Query(tx)
|
||||||
@@ -207,11 +219,16 @@ func (this *NodeLogDAO) ListNodeLogs(tx *dbs.Tx,
|
|||||||
if nodeId > 0 {
|
if nodeId > 0 {
|
||||||
query.Attr("nodeId", nodeId)
|
query.Attr("nodeId", nodeId)
|
||||||
} else {
|
} else {
|
||||||
switch role {
|
if nodeClusterId > 0 {
|
||||||
case nodeconfigs.NodeRoleNode:
|
query.Where("nodeId IN (SELECT id FROM " + SharedNodeDAO.Table + " WHERE clusterId=:nodeClusterId AND state=1)")
|
||||||
query.Where("nodeId IN (SELECT id FROM " + SharedNodeDAO.Table + " WHERE state=1 AND clusterId>0)")
|
query.Param("nodeClusterId", nodeClusterId)
|
||||||
case nodeconfigs.NodeRoleDNS:
|
} else {
|
||||||
query.Where("nodeId IN (SELECT id FROM edgeNSNodes WHERE state=1 AND clusterId>0)") // 没有用 SharedNSNodeDAO() 因为有包循环引用的问题
|
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 {
|
if serverId > 0 {
|
||||||
@@ -240,11 +257,19 @@ func (this *NodeLogDAO) ListNodeLogs(tx *dbs.Tx,
|
|||||||
Param("keyword", "%"+keyword+"%")
|
Param("keyword", "%"+keyword+"%")
|
||||||
}
|
}
|
||||||
if len(level) > 0 {
|
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 {
|
if isUnread {
|
||||||
query.Attr("isRead", 0)
|
query.Attr("isRead", 0)
|
||||||
}
|
}
|
||||||
|
if len(tag) > 0 {
|
||||||
|
query.Like("tag", "%"+tag+"%")
|
||||||
|
}
|
||||||
_, err = query.
|
_, err = query.
|
||||||
Offset(offset).
|
Offset(offset).
|
||||||
Limit(size).
|
Limit(size).
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ type Node struct {
|
|||||||
DnsRoutes string `field:"dnsRoutes"` // DNS线路设置
|
DnsRoutes string `field:"dnsRoutes"` // DNS线路设置
|
||||||
MaxCacheDiskCapacity string `field:"maxCacheDiskCapacity"` // 硬盘缓存容量
|
MaxCacheDiskCapacity string `field:"maxCacheDiskCapacity"` // 硬盘缓存容量
|
||||||
MaxCacheMemoryCapacity string `field:"maxCacheMemoryCapacity"` // 内存缓存容量
|
MaxCacheMemoryCapacity string `field:"maxCacheMemoryCapacity"` // 内存缓存容量
|
||||||
|
CacheDiskDir string `field:"cacheDiskDir"` // 缓存目录
|
||||||
}
|
}
|
||||||
|
|
||||||
type NodeOperator struct {
|
type NodeOperator struct {
|
||||||
@@ -63,6 +64,7 @@ type NodeOperator struct {
|
|||||||
DnsRoutes interface{} // DNS线路设置
|
DnsRoutes interface{} // DNS线路设置
|
||||||
MaxCacheDiskCapacity interface{} // 硬盘缓存容量
|
MaxCacheDiskCapacity interface{} // 硬盘缓存容量
|
||||||
MaxCacheMemoryCapacity interface{} // 内存缓存容量
|
MaxCacheMemoryCapacity interface{} // 内存缓存容量
|
||||||
|
CacheDiskDir interface{} // 缓存目录
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNodeOperator() *NodeOperator {
|
func NewNodeOperator() *NodeOperator {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
// 区域计费设置
|
// NodePriceItem 区域计费设置
|
||||||
type NodePriceItem struct {
|
type NodePriceItem struct {
|
||||||
Id uint32 `field:"id"` // ID
|
Id uint32 `field:"id"` // ID
|
||||||
IsOn uint8 `field:"isOn"` // 是否启用
|
IsOn uint8 `field:"isOn"` // 是否启用
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
// 节点区域
|
// NodeRegion 节点区域
|
||||||
type NodeRegion struct {
|
type NodeRegion struct {
|
||||||
Id uint32 `field:"id"` // ID
|
Id uint32 `field:"id"` // ID
|
||||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||||
|
|||||||
@@ -1 +1,18 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
func (this *NodeRegion) DecodePriceMap() map[int64]float64 {
|
||||||
|
var m = map[int64]float64{}
|
||||||
|
if len(this.Prices) == 0 {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.Unmarshal([]byte(this.Prices), &m)
|
||||||
|
if err != nil {
|
||||||
|
// 忽略错误
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|||||||
@@ -49,17 +49,18 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateNodeTask 创建单个节点任务
|
// CreateNodeTask 创建单个节点任务
|
||||||
func (this *NodeTaskDAO) CreateNodeTask(tx *dbs.Tx, role string, clusterId int64, nodeId int64, taskType NodeTaskType, version int64) error {
|
func (this *NodeTaskDAO) CreateNodeTask(tx *dbs.Tx, role string, clusterId int64, nodeId int64, serverId int64, taskType NodeTaskType, version int64) error {
|
||||||
if clusterId <= 0 || nodeId <= 0 {
|
if clusterId <= 0 || nodeId <= 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
uniqueId := role + "@" + types.String(nodeId) + "@node@" + taskType
|
var uniqueId = role + "@" + types.String(nodeId) + "@node@" + types.String(serverId) + "@" + taskType
|
||||||
updatedAt := time.Now().Unix()
|
var updatedAt = time.Now().Unix()
|
||||||
_, _, err := this.Query(tx).
|
_, _, err := this.Query(tx).
|
||||||
InsertOrUpdate(maps.Map{
|
InsertOrUpdate(maps.Map{
|
||||||
"role": role,
|
"role": role,
|
||||||
"clusterId": clusterId,
|
"clusterId": clusterId,
|
||||||
"nodeId": nodeId,
|
"nodeId": nodeId,
|
||||||
|
"serverId": serverId,
|
||||||
"type": taskType,
|
"type": taskType,
|
||||||
"uniqueId": uniqueId,
|
"uniqueId": uniqueId,
|
||||||
"updatedAt": updatedAt,
|
"updatedAt": updatedAt,
|
||||||
@@ -75,22 +76,24 @@ func (this *NodeTaskDAO) CreateNodeTask(tx *dbs.Tx, role string, clusterId int64
|
|||||||
"error": "",
|
"error": "",
|
||||||
"isNotified": 0,
|
"isNotified": 0,
|
||||||
"version": version,
|
"version": version,
|
||||||
|
"serverId": serverId,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateClusterTask 创建集群任务
|
// CreateClusterTask 创建集群任务
|
||||||
func (this *NodeTaskDAO) CreateClusterTask(tx *dbs.Tx, role string, clusterId int64, taskType NodeTaskType) error {
|
func (this *NodeTaskDAO) CreateClusterTask(tx *dbs.Tx, role string, clusterId int64, serverId int64, taskType NodeTaskType) error {
|
||||||
if clusterId <= 0 {
|
if clusterId <= 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
uniqueId := role + "@" + types.String(clusterId) + "@cluster@" + taskType
|
var uniqueId = role + "@" + types.String(clusterId) + "@" + types.String(serverId) + "@cluster@" + types.String(serverId) + "@" + taskType
|
||||||
updatedAt := time.Now().Unix()
|
var updatedAt = time.Now().Unix()
|
||||||
_, _, err := this.Query(tx).
|
_, _, err := this.Query(tx).
|
||||||
InsertOrUpdate(maps.Map{
|
InsertOrUpdate(maps.Map{
|
||||||
"role": role,
|
"role": role,
|
||||||
"clusterId": clusterId,
|
"clusterId": clusterId,
|
||||||
|
"serverId": serverId,
|
||||||
"nodeId": 0,
|
"nodeId": 0,
|
||||||
"type": taskType,
|
"type": taskType,
|
||||||
"uniqueId": uniqueId,
|
"uniqueId": uniqueId,
|
||||||
@@ -107,12 +110,13 @@ func (this *NodeTaskDAO) CreateClusterTask(tx *dbs.Tx, role string, clusterId in
|
|||||||
"isNotified": 0,
|
"isNotified": 0,
|
||||||
"error": "",
|
"error": "",
|
||||||
"version": time.Now().UnixNano(),
|
"version": time.Now().UnixNano(),
|
||||||
|
"serverId": serverId,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtractNodeClusterTask 分解边缘节点集群任务
|
// ExtractNodeClusterTask 分解边缘节点集群任务
|
||||||
func (this *NodeTaskDAO) ExtractNodeClusterTask(tx *dbs.Tx, clusterId int64, taskType NodeTaskType) error {
|
func (this *NodeTaskDAO) ExtractNodeClusterTask(tx *dbs.Tx, clusterId int64, serverId int64, taskType NodeTaskType) error {
|
||||||
nodeIds, err := SharedNodeDAO.FindAllNodeIdsMatch(tx, clusterId, true, configutils.BoolStateYes)
|
nodeIds, err := SharedNodeDAO.FindAllNodeIdsMatch(tx, clusterId, true, configutils.BoolStateYes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -131,7 +135,7 @@ func (this *NodeTaskDAO) ExtractNodeClusterTask(tx *dbs.Tx, clusterId int64, tas
|
|||||||
|
|
||||||
var version = time.Now().UnixNano()
|
var version = time.Now().UnixNano()
|
||||||
for _, nodeId := range nodeIds {
|
for _, nodeId := range nodeIds {
|
||||||
err = this.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, taskType, version)
|
err = this.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, serverId, taskType, version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -170,7 +174,7 @@ func (this *NodeTaskDAO) ExtractNSClusterTask(tx *dbs.Tx, clusterId int64, taskT
|
|||||||
|
|
||||||
var version = time.Now().UnixNano()
|
var version = time.Now().UnixNano()
|
||||||
for _, nodeId := range nodeIds {
|
for _, nodeId := range nodeIds {
|
||||||
err = this.CreateNodeTask(tx, nodeconfigs.NodeRoleDNS, clusterId, nodeId, taskType, version)
|
err = this.CreateNodeTask(tx, nodeconfigs.NodeRoleDNS, clusterId, nodeId, 0, taskType, version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -202,7 +206,8 @@ func (this *NodeTaskDAO) ExtractAllClusterTasks(tx *dbs.Tx, role string) error {
|
|||||||
clusterId := int64(one.(*NodeTask).ClusterId)
|
clusterId := int64(one.(*NodeTask).ClusterId)
|
||||||
switch role {
|
switch role {
|
||||||
case nodeconfigs.NodeRoleNode:
|
case nodeconfigs.NodeRoleNode:
|
||||||
err = this.ExtractNodeClusterTask(tx, clusterId, one.(*NodeTask).Type)
|
var nodeTask = one.(*NodeTask)
|
||||||
|
err = this.ExtractNodeClusterTask(tx, clusterId, int64(nodeTask.ServerId), nodeTask.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ func TestNodeTaskDAO_CreateNodeTask(t *testing.T) {
|
|||||||
dbs.NotifyReady()
|
dbs.NotifyReady()
|
||||||
|
|
||||||
var tx *dbs.Tx
|
var tx *dbs.Tx
|
||||||
err := SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, 1, 2, NodeTaskTypeConfigChanged, 0)
|
err := SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, 1, 2, 0, NodeTaskTypeConfigChanged, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,7 @@ func TestNodeTaskDAO_CreateClusterTask(t *testing.T) {
|
|||||||
dbs.NotifyReady()
|
dbs.NotifyReady()
|
||||||
|
|
||||||
var tx *dbs.Tx
|
var tx *dbs.Tx
|
||||||
err := SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, 1, NodeTaskTypeConfigChanged)
|
err := SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, 1, 0, NodeTaskTypeConfigChanged)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ func TestNodeTaskDAO_ExtractClusterTask(t *testing.T) {
|
|||||||
dbs.NotifyReady()
|
dbs.NotifyReady()
|
||||||
|
|
||||||
var tx *dbs.Tx
|
var tx *dbs.Tx
|
||||||
err := SharedNodeTaskDAO.ExtractNodeClusterTask(tx, 1, NodeTaskTypeConfigChanged)
|
err := SharedNodeTaskDAO.ExtractNodeClusterTask(tx, 1, 0, NodeTaskTypeConfigChanged)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ type NodeTask struct {
|
|||||||
Role string `field:"role"` // 节点角色
|
Role string `field:"role"` // 节点角色
|
||||||
NodeId uint32 `field:"nodeId"` // 节点ID
|
NodeId uint32 `field:"nodeId"` // 节点ID
|
||||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||||
|
ServerId uint32 `field:"serverId"` // 服务ID
|
||||||
Type string `field:"type"` // 任务类型
|
Type string `field:"type"` // 任务类型
|
||||||
UniqueId string `field:"uniqueId"` // 唯一ID:nodeId@type
|
UniqueId string `field:"uniqueId"` // 唯一ID:nodeId@type
|
||||||
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
|
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
|
||||||
@@ -21,6 +22,7 @@ type NodeTaskOperator struct {
|
|||||||
Role interface{} // 节点角色
|
Role interface{} // 节点角色
|
||||||
NodeId interface{} // 节点ID
|
NodeId interface{} // 节点ID
|
||||||
ClusterId interface{} // 集群ID
|
ClusterId interface{} // 集群ID
|
||||||
|
ServerId interface{} // 服务ID
|
||||||
Type interface{} // 任务类型
|
Type interface{} // 任务类型
|
||||||
UniqueId interface{} // 唯一ID:nodeId@type
|
UniqueId interface{} // 唯一ID:nodeId@type
|
||||||
UpdatedAt interface{} // 修改时间
|
UpdatedAt interface{} // 修改时间
|
||||||
|
|||||||
@@ -57,12 +57,10 @@ func (this *NodeValueDAO) CreateValue(tx *dbs.Tx, clusterId int64, role nodeconf
|
|||||||
|
|
||||||
// Clean 清除数据
|
// Clean 清除数据
|
||||||
func (this *NodeValueDAO) Clean(tx *dbs.Tx) error {
|
func (this *NodeValueDAO) Clean(tx *dbs.Tx) error {
|
||||||
// 删除N天之前的所有数据
|
var hour = timeutil.Format("YmdH", time.Now().Add(-2*time.Hour))
|
||||||
expiredDays := 2
|
|
||||||
day := timeutil.Format("Ymd", time.Now().AddDate(0, 0, -expiredDays))
|
|
||||||
_, err := this.Query(tx).
|
_, err := this.Query(tx).
|
||||||
Where("day<=:day").
|
Where("hour<=:hour").
|
||||||
Param("day", day).
|
Param("hour", hour).
|
||||||
Delete()
|
Delete()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestNodeValueDAO_CreateValue(t *testing.T) {
|
func TestNodeValueDAO_CreateValue(t *testing.T) {
|
||||||
dao := NewNodeValueDAO()
|
var dao = NewNodeValueDAO()
|
||||||
m := maps.Map{
|
m := maps.Map{
|
||||||
"hello": "world12344",
|
"hello": "world12344",
|
||||||
}
|
}
|
||||||
@@ -20,3 +20,12 @@ func TestNodeValueDAO_CreateValue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Log("ok")
|
t.Log("ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNodeValueDAO_Clean(t *testing.T) {
|
||||||
|
var dao = NewNodeValueDAO()
|
||||||
|
err := dao.Clean(nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log("ok")
|
||||||
|
}
|
||||||
|
|||||||
@@ -195,5 +195,5 @@ func (this *NSClusterDAO) FindClusterRecursion(tx *dbs.Tx, clusterId int64) ([]b
|
|||||||
|
|
||||||
// NotifyUpdate 通知更改
|
// NotifyUpdate 通知更改
|
||||||
func (this *NSClusterDAO) NotifyUpdate(tx *dbs.Tx, clusterId int64) error {
|
func (this *NSClusterDAO) NotifyUpdate(tx *dbs.Tx, clusterId int64) error {
|
||||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, NSNodeTaskTypeConfigChanged)
|
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, 0, NSNodeTaskTypeConfigChanged)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,8 +87,22 @@ func (this *OriginDAO) FindOriginName(tx *dbs.Tx, id int64) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateOrigin 创建源站
|
// CreateOrigin 创建源站
|
||||||
func (this *OriginDAO) CreateOrigin(tx *dbs.Tx, adminId int64, userId int64, name string, addrJSON string, description string, weight int32, isOn bool, connTimeout *shared.TimeDuration, readTimeout *shared.TimeDuration, idleTimeout *shared.TimeDuration, maxConns int32, maxIdleConns int32, domains []string) (originId int64, err error) {
|
func (this *OriginDAO) CreateOrigin(tx *dbs.Tx,
|
||||||
op := NewOriginOperator()
|
adminId int64,
|
||||||
|
userId int64,
|
||||||
|
name string,
|
||||||
|
addrJSON string,
|
||||||
|
description string,
|
||||||
|
weight int32, isOn bool,
|
||||||
|
connTimeout *shared.TimeDuration,
|
||||||
|
readTimeout *shared.TimeDuration,
|
||||||
|
idleTimeout *shared.TimeDuration,
|
||||||
|
maxConns int32,
|
||||||
|
maxIdleConns int32,
|
||||||
|
certRef *sslconfigs.SSLCertRef,
|
||||||
|
domains []string,
|
||||||
|
host string) (originId int64, err error) {
|
||||||
|
var op = NewOriginOperator()
|
||||||
op.AdminId = adminId
|
op.AdminId = adminId
|
||||||
op.UserId = userId
|
op.UserId = userId
|
||||||
op.IsOn = isOn
|
op.IsOn = isOn
|
||||||
@@ -133,6 +147,15 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx, adminId int64, userId int64, nam
|
|||||||
}
|
}
|
||||||
op.Weight = weight
|
op.Weight = weight
|
||||||
|
|
||||||
|
// cert
|
||||||
|
if certRef != nil {
|
||||||
|
certRefJSON, err := json.Marshal(certRef)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
op.Cert = certRefJSON
|
||||||
|
}
|
||||||
|
|
||||||
if len(domains) > 0 {
|
if len(domains) > 0 {
|
||||||
domainsJSON, err := json.Marshal(domains)
|
domainsJSON, err := json.Marshal(domains)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -143,6 +166,8 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx, adminId int64, userId int64, nam
|
|||||||
op.Domains = "[]"
|
op.Domains = "[]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
op.Host = host
|
||||||
|
|
||||||
op.State = OriginStateEnabled
|
op.State = OriginStateEnabled
|
||||||
err = this.Save(tx, op)
|
err = this.Save(tx, op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -152,11 +177,25 @@ func (this *OriginDAO) CreateOrigin(tx *dbs.Tx, adminId int64, userId int64, nam
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateOrigin 修改源站
|
// UpdateOrigin 修改源站
|
||||||
func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx, originId int64, name string, addrJSON string, description string, weight int32, isOn bool, connTimeout *shared.TimeDuration, readTimeout *shared.TimeDuration, idleTimeout *shared.TimeDuration, maxConns int32, maxIdleConns int32, domains []string) error {
|
func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx,
|
||||||
|
originId int64,
|
||||||
|
name string,
|
||||||
|
addrJSON string,
|
||||||
|
description string,
|
||||||
|
weight int32,
|
||||||
|
isOn bool,
|
||||||
|
connTimeout *shared.TimeDuration,
|
||||||
|
readTimeout *shared.TimeDuration,
|
||||||
|
idleTimeout *shared.TimeDuration,
|
||||||
|
maxConns int32,
|
||||||
|
maxIdleConns int32,
|
||||||
|
certRef *sslconfigs.SSLCertRef,
|
||||||
|
domains []string,
|
||||||
|
host string) error {
|
||||||
if originId <= 0 {
|
if originId <= 0 {
|
||||||
return errors.New("invalid originId")
|
return errors.New("invalid originId")
|
||||||
}
|
}
|
||||||
op := NewOriginOperator()
|
var op = NewOriginOperator()
|
||||||
op.Id = originId
|
op.Id = originId
|
||||||
op.Name = name
|
op.Name = name
|
||||||
op.Addr = addrJSON
|
op.Addr = addrJSON
|
||||||
@@ -201,6 +240,17 @@ func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx, originId int64, name string, add
|
|||||||
op.IsOn = isOn
|
op.IsOn = isOn
|
||||||
op.Version = dbs.SQL("version+1")
|
op.Version = dbs.SQL("version+1")
|
||||||
|
|
||||||
|
// cert
|
||||||
|
if certRef != nil {
|
||||||
|
certRefJSON, err := json.Marshal(certRef)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
op.Cert = certRefJSON
|
||||||
|
} else {
|
||||||
|
op.Cert = dbs.SQL("NULL")
|
||||||
|
}
|
||||||
|
|
||||||
if len(domains) > 0 {
|
if len(domains) > 0 {
|
||||||
domainsJSON, err := json.Marshal(domains)
|
domainsJSON, err := json.Marshal(domains)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -211,6 +261,8 @@ func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx, originId int64, name string, add
|
|||||||
op.Domains = "[]"
|
op.Domains = "[]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
op.Host = host
|
||||||
|
|
||||||
err := this.Save(tx, op)
|
err := this.Save(tx, op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -238,7 +290,7 @@ func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, cacheMap
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &serverconfigs.OriginConfig{
|
var config = &serverconfigs.OriginConfig{
|
||||||
Id: int64(origin.Id),
|
Id: int64(origin.Id),
|
||||||
IsOn: origin.IsOn == 1,
|
IsOn: origin.IsOn == 1,
|
||||||
Version: int(origin.Version),
|
Version: int(origin.Version),
|
||||||
|
|||||||
@@ -80,7 +80,17 @@ func (this *PlanDAO) FindPlanName(tx *dbs.Tx, id int64) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreatePlan 创建套餐
|
// CreatePlan 创建套餐
|
||||||
func (this *PlanDAO) CreatePlan(tx *dbs.Tx, name string, clusterId int64, trafficLimitJSON []byte, featuresJSON []byte, priceType serverconfigs.PlanPriceType, trafficPriceJSON []byte, monthlyPrice float32, seasonallyPrice float32, yearlyPrice float32) (int64, error) {
|
func (this *PlanDAO) CreatePlan(tx *dbs.Tx,
|
||||||
|
name string,
|
||||||
|
clusterId int64,
|
||||||
|
trafficLimitJSON []byte,
|
||||||
|
featuresJSON []byte,
|
||||||
|
priceType serverconfigs.PlanPriceType,
|
||||||
|
trafficPriceJSON []byte,
|
||||||
|
bandwidthPriceJSON []byte,
|
||||||
|
monthlyPrice float32,
|
||||||
|
seasonallyPrice float32,
|
||||||
|
yearlyPrice float32) (int64, error) {
|
||||||
var op = NewPlanOperator()
|
var op = NewPlanOperator()
|
||||||
op.Name = name
|
op.Name = name
|
||||||
op.ClusterId = clusterId
|
op.ClusterId = clusterId
|
||||||
@@ -94,6 +104,9 @@ func (this *PlanDAO) CreatePlan(tx *dbs.Tx, name string, clusterId int64, traffi
|
|||||||
if len(trafficPriceJSON) > 0 {
|
if len(trafficPriceJSON) > 0 {
|
||||||
op.TrafficPrice = trafficPriceJSON
|
op.TrafficPrice = trafficPriceJSON
|
||||||
}
|
}
|
||||||
|
if len(bandwidthPriceJSON) > 0 {
|
||||||
|
op.BandwidthPrice = bandwidthPriceJSON
|
||||||
|
}
|
||||||
if monthlyPrice >= 0 {
|
if monthlyPrice >= 0 {
|
||||||
op.MonthlyPrice = monthlyPrice
|
op.MonthlyPrice = monthlyPrice
|
||||||
}
|
}
|
||||||
@@ -109,7 +122,19 @@ func (this *PlanDAO) CreatePlan(tx *dbs.Tx, name string, clusterId int64, traffi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdatePlan 修改套餐
|
// UpdatePlan 修改套餐
|
||||||
func (this *PlanDAO) UpdatePlan(tx *dbs.Tx, planId int64, name string, isOn bool, clusterId int64, trafficLimitJSON []byte, featuresJSON []byte, priceType serverconfigs.PlanPriceType, trafficPriceJSON []byte, monthlyPrice float32, seasonallyPrice float32, yearlyPrice float32) error {
|
func (this *PlanDAO) UpdatePlan(tx *dbs.Tx,
|
||||||
|
planId int64,
|
||||||
|
name string,
|
||||||
|
isOn bool,
|
||||||
|
clusterId int64,
|
||||||
|
trafficLimitJSON []byte,
|
||||||
|
featuresJSON []byte,
|
||||||
|
priceType serverconfigs.PlanPriceType,
|
||||||
|
trafficPriceJSON []byte,
|
||||||
|
bandwidthPriceJSON []byte,
|
||||||
|
monthlyPrice float32,
|
||||||
|
seasonallyPrice float32,
|
||||||
|
yearlyPrice float32) error {
|
||||||
if planId <= 0 {
|
if planId <= 0 {
|
||||||
return errors.New("invalid planId")
|
return errors.New("invalid planId")
|
||||||
}
|
}
|
||||||
@@ -138,6 +163,9 @@ func (this *PlanDAO) UpdatePlan(tx *dbs.Tx, planId int64, name string, isOn bool
|
|||||||
if len(trafficPriceJSON) > 0 {
|
if len(trafficPriceJSON) > 0 {
|
||||||
op.TrafficPrice = trafficPriceJSON
|
op.TrafficPrice = trafficPriceJSON
|
||||||
}
|
}
|
||||||
|
if len(bandwidthPriceJSON) > 0 {
|
||||||
|
op.BandwidthPrice = bandwidthPriceJSON
|
||||||
|
}
|
||||||
if monthlyPrice >= 0 {
|
if monthlyPrice >= 0 {
|
||||||
op.MonthlyPrice = monthlyPrice
|
op.MonthlyPrice = monthlyPrice
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ type Plan struct {
|
|||||||
TrafficLimit string `field:"trafficLimit"` // 流量限制
|
TrafficLimit string `field:"trafficLimit"` // 流量限制
|
||||||
Features string `field:"features"` // 允许的功能
|
Features string `field:"features"` // 允许的功能
|
||||||
TrafficPrice string `field:"trafficPrice"` // 流量价格设定
|
TrafficPrice string `field:"trafficPrice"` // 流量价格设定
|
||||||
|
BandwidthPrice string `field:"bandwidthPrice"` // 带宽价格
|
||||||
MonthlyPrice float64 `field:"monthlyPrice"` // 月付
|
MonthlyPrice float64 `field:"monthlyPrice"` // 月付
|
||||||
SeasonallyPrice float64 `field:"seasonallyPrice"` // 季付
|
SeasonallyPrice float64 `field:"seasonallyPrice"` // 季付
|
||||||
YearlyPrice float64 `field:"yearlyPrice"` // 年付
|
YearlyPrice float64 `field:"yearlyPrice"` // 年付
|
||||||
@@ -25,6 +26,7 @@ type PlanOperator struct {
|
|||||||
TrafficLimit interface{} // 流量限制
|
TrafficLimit interface{} // 流量限制
|
||||||
Features interface{} // 允许的功能
|
Features interface{} // 允许的功能
|
||||||
TrafficPrice interface{} // 流量价格设定
|
TrafficPrice interface{} // 流量价格设定
|
||||||
|
BandwidthPrice interface{} // 带宽价格
|
||||||
MonthlyPrice interface{} // 月付
|
MonthlyPrice interface{} // 月付
|
||||||
SeasonallyPrice interface{} // 季付
|
SeasonallyPrice interface{} // 季付
|
||||||
YearlyPrice interface{} // 年付
|
YearlyPrice interface{} // 年付
|
||||||
|
|||||||
@@ -1 +1,38 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DecodeTrafficPrice 流量价格配置
|
||||||
|
func (this *Plan) DecodeTrafficPrice() *serverconfigs.PlanTrafficPriceConfig {
|
||||||
|
var config = &serverconfigs.PlanTrafficPriceConfig{}
|
||||||
|
|
||||||
|
if len(this.TrafficPrice) == 0 {
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.Unmarshal([]byte(this.TrafficPrice), config)
|
||||||
|
if err != nil {
|
||||||
|
// 忽略错误
|
||||||
|
}
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeBandwidthPrice 带宽价格配置
|
||||||
|
func (this *Plan) DecodeBandwidthPrice() *serverconfigs.PlanBandwidthPriceConfig {
|
||||||
|
var config = &serverconfigs.PlanBandwidthPriceConfig{}
|
||||||
|
|
||||||
|
if len(this.BandwidthPrice) == 0 {
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.Unmarshal([]byte(this.BandwidthPrice), config)
|
||||||
|
if err != nil {
|
||||||
|
// 忽略错误
|
||||||
|
}
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ func init() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 启用条目
|
// EnableRegionCity 启用条目
|
||||||
func (this *RegionCityDAO) EnableRegionCity(tx *dbs.Tx, id uint32) error {
|
func (this *RegionCityDAO) EnableRegionCity(tx *dbs.Tx, id uint32) error {
|
||||||
_, err := this.Query(tx).
|
_, err := this.Query(tx).
|
||||||
Pk(id).
|
Pk(id).
|
||||||
@@ -47,7 +47,7 @@ func (this *RegionCityDAO) EnableRegionCity(tx *dbs.Tx, id uint32) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 禁用条目
|
// DisableRegionCity 禁用条目
|
||||||
func (this *RegionCityDAO) DisableRegionCity(tx *dbs.Tx, id uint32) error {
|
func (this *RegionCityDAO) DisableRegionCity(tx *dbs.Tx, id uint32) error {
|
||||||
_, err := this.Query(tx).
|
_, err := this.Query(tx).
|
||||||
Pk(id).
|
Pk(id).
|
||||||
@@ -56,7 +56,7 @@ func (this *RegionCityDAO) DisableRegionCity(tx *dbs.Tx, id uint32) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查找启用中的条目
|
// FindEnabledRegionCity 查找启用中的条目
|
||||||
func (this *RegionCityDAO) FindEnabledRegionCity(tx *dbs.Tx, id int64) (*RegionCity, error) {
|
func (this *RegionCityDAO) FindEnabledRegionCity(tx *dbs.Tx, id int64) (*RegionCity, error) {
|
||||||
result, err := this.Query(tx).
|
result, err := this.Query(tx).
|
||||||
Pk(id).
|
Pk(id).
|
||||||
@@ -68,7 +68,7 @@ func (this *RegionCityDAO) FindEnabledRegionCity(tx *dbs.Tx, id int64) (*RegionC
|
|||||||
return result.(*RegionCity), err
|
return result.(*RegionCity), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据主键查找名称
|
// FindRegionCityName 根据主键查找名称
|
||||||
func (this *RegionCityDAO) FindRegionCityName(tx *dbs.Tx, id uint32) (string, error) {
|
func (this *RegionCityDAO) FindRegionCityName(tx *dbs.Tx, id uint32) (string, error) {
|
||||||
return this.Query(tx).
|
return this.Query(tx).
|
||||||
Pk(id).
|
Pk(id).
|
||||||
@@ -76,7 +76,7 @@ func (this *RegionCityDAO) FindRegionCityName(tx *dbs.Tx, id uint32) (string, er
|
|||||||
FindStringCol("")
|
FindStringCol("")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据数据ID查找城市
|
// FindCityWithDataId 根据数据ID查找城市
|
||||||
func (this *RegionCityDAO) FindCityWithDataId(tx *dbs.Tx, dataId string) (int64, error) {
|
func (this *RegionCityDAO) FindCityWithDataId(tx *dbs.Tx, dataId string) (int64, error) {
|
||||||
return this.Query(tx).
|
return this.Query(tx).
|
||||||
Attr("dataId", dataId).
|
Attr("dataId", dataId).
|
||||||
@@ -84,7 +84,7 @@ func (this *RegionCityDAO) FindCityWithDataId(tx *dbs.Tx, dataId string) (int64,
|
|||||||
FindInt64Col(0)
|
FindInt64Col(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建城市
|
// CreateCity 创建城市
|
||||||
func (this *RegionCityDAO) CreateCity(tx *dbs.Tx, provinceId int64, name string, dataId string) (int64, error) {
|
func (this *RegionCityDAO) CreateCity(tx *dbs.Tx, provinceId int64, name string, dataId string) (int64, error) {
|
||||||
op := NewRegionCityOperator()
|
op := NewRegionCityOperator()
|
||||||
op.ProvinceId = provinceId
|
op.ProvinceId = provinceId
|
||||||
@@ -105,7 +105,7 @@ func (this *RegionCityDAO) CreateCity(tx *dbs.Tx, provinceId int64, name string,
|
|||||||
return types.Int64(op.Id), nil
|
return types.Int64(op.Id), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据城市名查找城市ID
|
// FindCityIdWithNameCacheable 根据城市名查找城市ID
|
||||||
func (this *RegionCityDAO) FindCityIdWithNameCacheable(tx *dbs.Tx, provinceId int64, cityName string) (int64, error) {
|
func (this *RegionCityDAO) FindCityIdWithNameCacheable(tx *dbs.Tx, provinceId int64, cityName string) (int64, error) {
|
||||||
key := cityName + "@" + numberutils.FormatInt64(provinceId)
|
key := cityName + "@" + numberutils.FormatInt64(provinceId)
|
||||||
|
|
||||||
@@ -132,3 +132,12 @@ func (this *RegionCityDAO) FindCityIdWithNameCacheable(tx *dbs.Tx, provinceId in
|
|||||||
|
|
||||||
return cityId, nil
|
return cityId, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindAllEnabledCities 获取所有城市信息
|
||||||
|
func (this *RegionCityDAO) FindAllEnabledCities(tx *dbs.Tx) (result []*RegionCity, err error) {
|
||||||
|
_, err = this.Query(tx).
|
||||||
|
State(RegionCityStateEnabled).
|
||||||
|
Slice(&result).
|
||||||
|
FindAll()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@@ -1 +1,18 @@
|
|||||||
package regions
|
package regions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/iwind/TeaGo/logs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (this *RegionCity) DecodeCodes() []string {
|
||||||
|
if len(this.Codes) == 0 {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
result := []string{}
|
||||||
|
err := json.Unmarshal([]byte(this.Codes), &result)
|
||||||
|
if err != nil {
|
||||||
|
logs.Error(err)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ func init() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 启用条目
|
// EnableRegionProvider 启用条目
|
||||||
func (this *RegionProviderDAO) EnableRegionProvider(tx *dbs.Tx, id uint32) error {
|
func (this *RegionProviderDAO) EnableRegionProvider(tx *dbs.Tx, id uint32) error {
|
||||||
_, err := this.Query(tx).
|
_, err := this.Query(tx).
|
||||||
Pk(id).
|
Pk(id).
|
||||||
@@ -45,7 +45,7 @@ func (this *RegionProviderDAO) EnableRegionProvider(tx *dbs.Tx, id uint32) error
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 禁用条目
|
// DisableRegionProvider 禁用条目
|
||||||
func (this *RegionProviderDAO) DisableRegionProvider(tx *dbs.Tx, id uint32) error {
|
func (this *RegionProviderDAO) DisableRegionProvider(tx *dbs.Tx, id uint32) error {
|
||||||
_, err := this.Query(tx).
|
_, err := this.Query(tx).
|
||||||
Pk(id).
|
Pk(id).
|
||||||
@@ -54,8 +54,8 @@ func (this *RegionProviderDAO) DisableRegionProvider(tx *dbs.Tx, id uint32) erro
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查找启用中的条目
|
// FindEnabledRegionProvider 查找启用中的条目
|
||||||
func (this *RegionProviderDAO) FindEnabledRegionProvider(tx *dbs.Tx, id uint32) (*RegionProvider, error) {
|
func (this *RegionProviderDAO) FindEnabledRegionProvider(tx *dbs.Tx, id int64) (*RegionProvider, error) {
|
||||||
result, err := this.Query(tx).
|
result, err := this.Query(tx).
|
||||||
Pk(id).
|
Pk(id).
|
||||||
Attr("state", RegionProviderStateEnabled).
|
Attr("state", RegionProviderStateEnabled).
|
||||||
@@ -66,7 +66,7 @@ func (this *RegionProviderDAO) FindEnabledRegionProvider(tx *dbs.Tx, id uint32)
|
|||||||
return result.(*RegionProvider), err
|
return result.(*RegionProvider), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据主键查找名称
|
// FindRegionProviderName 根据主键查找名称
|
||||||
func (this *RegionProviderDAO) FindRegionProviderName(tx *dbs.Tx, id uint32) (string, error) {
|
func (this *RegionProviderDAO) FindRegionProviderName(tx *dbs.Tx, id uint32) (string, error) {
|
||||||
return this.Query(tx).
|
return this.Query(tx).
|
||||||
Pk(id).
|
Pk(id).
|
||||||
@@ -74,7 +74,7 @@ func (this *RegionProviderDAO) FindRegionProviderName(tx *dbs.Tx, id uint32) (st
|
|||||||
FindStringCol("")
|
FindStringCol("")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据服务商名称查找服务商ID
|
// FindProviderIdWithNameCacheable 根据服务商名称查找服务商ID
|
||||||
func (this *RegionProviderDAO) FindProviderIdWithNameCacheable(tx *dbs.Tx, providerName string) (int64, error) {
|
func (this *RegionProviderDAO) FindProviderIdWithNameCacheable(tx *dbs.Tx, providerName string) (int64, error) {
|
||||||
SharedCacheLocker.RLock()
|
SharedCacheLocker.RLock()
|
||||||
providerId, ok := regionProviderNameAndIdCacheMap[providerName]
|
providerId, ok := regionProviderNameAndIdCacheMap[providerName]
|
||||||
@@ -100,7 +100,7 @@ func (this *RegionProviderDAO) FindProviderIdWithNameCacheable(tx *dbs.Tx, provi
|
|||||||
return providerId, nil
|
return providerId, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建Provider
|
// CreateProvider 创建Provider
|
||||||
func (this *RegionProviderDAO) CreateProvider(tx *dbs.Tx, name string) (int64, error) {
|
func (this *RegionProviderDAO) CreateProvider(tx *dbs.Tx, name string) (int64, error) {
|
||||||
op := NewRegionProviderOperator()
|
op := NewRegionProviderOperator()
|
||||||
op.Name = name
|
op.Name = name
|
||||||
@@ -112,3 +112,12 @@ func (this *RegionProviderDAO) CreateProvider(tx *dbs.Tx, name string) (int64, e
|
|||||||
op.Codes = codesJSON
|
op.Codes = codesJSON
|
||||||
return this.SaveInt64(tx, op)
|
return this.SaveInt64(tx, op)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindAllEnabledProviders 查找所有服务商
|
||||||
|
func (this *RegionProviderDAO) FindAllEnabledProviders(tx *dbs.Tx) (result []*RegionProvider, err error) {
|
||||||
|
_, err = this.Query(tx).
|
||||||
|
State(RegionProviderStateEnabled).
|
||||||
|
Slice(&result).
|
||||||
|
FindAll()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@@ -1 +1,18 @@
|
|||||||
package regions
|
package regions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/iwind/TeaGo/logs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (this *RegionProvider) DecodeCodes() []string {
|
||||||
|
if len(this.Codes) == 0 {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
result := []string{}
|
||||||
|
err := json.Unmarshal([]byte(this.Codes), &result)
|
||||||
|
if err != nil {
|
||||||
|
logs.Error(err)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ func (this *ReverseProxyDAO) ComposeReverseProxyConfig(tx *dbs.Tx, reverseProxyI
|
|||||||
config.RequestURI = reverseProxy.RequestURI
|
config.RequestURI = reverseProxy.RequestURI
|
||||||
config.StripPrefix = reverseProxy.StripPrefix
|
config.StripPrefix = reverseProxy.StripPrefix
|
||||||
config.AutoFlush = reverseProxy.AutoFlush == 1
|
config.AutoFlush = reverseProxy.AutoFlush == 1
|
||||||
|
config.FollowRedirects = reverseProxy.FollowRedirects == 1
|
||||||
|
|
||||||
schedulingConfig := &serverconfigs.SchedulingConfig{}
|
schedulingConfig := &serverconfigs.SchedulingConfig{}
|
||||||
if len(reverseProxy.Scheduling) > 0 && reverseProxy.Scheduling != "null" {
|
if len(reverseProxy.Scheduling) > 0 && reverseProxy.Scheduling != "null" {
|
||||||
@@ -312,12 +313,13 @@ func (this *ReverseProxyDAO) UpdateReverseProxy(tx *dbs.Tx,
|
|||||||
idleTimeout *shared.TimeDuration,
|
idleTimeout *shared.TimeDuration,
|
||||||
maxConns int32,
|
maxConns int32,
|
||||||
maxIdleConns int32,
|
maxIdleConns int32,
|
||||||
proxyProtocolJSON []byte) error {
|
proxyProtocolJSON []byte,
|
||||||
|
followRedirects bool) error {
|
||||||
if reverseProxyId <= 0 {
|
if reverseProxyId <= 0 {
|
||||||
return errors.New("invalid reverseProxyId")
|
return errors.New("invalid reverseProxyId")
|
||||||
}
|
}
|
||||||
|
|
||||||
op := NewReverseProxyOperator()
|
var op = NewReverseProxyOperator()
|
||||||
op.Id = reverseProxyId
|
op.Id = reverseProxyId
|
||||||
|
|
||||||
if requestHostType < 0 {
|
if requestHostType < 0 {
|
||||||
@@ -329,6 +331,7 @@ func (this *ReverseProxyDAO) UpdateReverseProxy(tx *dbs.Tx,
|
|||||||
op.RequestURI = requestURI
|
op.RequestURI = requestURI
|
||||||
op.StripPrefix = stripPrefix
|
op.StripPrefix = stripPrefix
|
||||||
op.AutoFlush = autoFlush
|
op.AutoFlush = autoFlush
|
||||||
|
op.FollowRedirects = followRedirects
|
||||||
|
|
||||||
if len(addHeaders) == 0 {
|
if len(addHeaders) == 0 {
|
||||||
addHeaders = []string{}
|
addHeaders = []string{}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ type ReverseProxy struct {
|
|||||||
MaxConns uint32 `field:"maxConns"` // 最大并发连接数
|
MaxConns uint32 `field:"maxConns"` // 最大并发连接数
|
||||||
MaxIdleConns uint32 `field:"maxIdleConns"` // 最大空闲连接数
|
MaxIdleConns uint32 `field:"maxIdleConns"` // 最大空闲连接数
|
||||||
ProxyProtocol string `field:"proxyProtocol"` // Proxy Protocol配置
|
ProxyProtocol string `field:"proxyProtocol"` // Proxy Protocol配置
|
||||||
|
FollowRedirects uint8 `field:"followRedirects"` // 回源跟随
|
||||||
}
|
}
|
||||||
|
|
||||||
type ReverseProxyOperator struct {
|
type ReverseProxyOperator struct {
|
||||||
@@ -49,6 +50,7 @@ type ReverseProxyOperator struct {
|
|||||||
MaxConns interface{} // 最大并发连接数
|
MaxConns interface{} // 最大并发连接数
|
||||||
MaxIdleConns interface{} // 最大空闲连接数
|
MaxIdleConns interface{} // 最大空闲连接数
|
||||||
ProxyProtocol interface{} // Proxy Protocol配置
|
ProxyProtocol interface{} // Proxy Protocol配置
|
||||||
|
FollowRedirects interface{} // 回源跟随
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewReverseProxyOperator() *ReverseProxyOperator {
|
func NewReverseProxyOperator() *ReverseProxyOperator {
|
||||||
|
|||||||
108
internal/db/models/server_bill_dao.go
Normal file
108
internal/db/models/server_bill_dao.go
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"math"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ServerBillDAO dbs.DAO
|
||||||
|
|
||||||
|
func NewServerBillDAO() *ServerBillDAO {
|
||||||
|
return dbs.NewDAO(&ServerBillDAO{
|
||||||
|
DAOObject: dbs.DAOObject{
|
||||||
|
DB: Tea.Env,
|
||||||
|
Table: "edgeServerBills",
|
||||||
|
Model: new(ServerBill),
|
||||||
|
PkName: "id",
|
||||||
|
},
|
||||||
|
}).(*ServerBillDAO)
|
||||||
|
}
|
||||||
|
|
||||||
|
var SharedServerBillDAO *ServerBillDAO
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
dbs.OnReady(func() {
|
||||||
|
SharedServerBillDAO = NewServerBillDAO()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdateServerBill 创建账单
|
||||||
|
func (this *ServerBillDAO) CreateOrUpdateServerBill(tx *dbs.Tx,
|
||||||
|
userId int64,
|
||||||
|
serverId int64,
|
||||||
|
month string,
|
||||||
|
userPlanId int64,
|
||||||
|
planId int64,
|
||||||
|
totalTrafficBytes int64,
|
||||||
|
bandwidthPercentileBytes int64,
|
||||||
|
bandwidthPercentile int,
|
||||||
|
priceType string,
|
||||||
|
fee float64) error {
|
||||||
|
fee = math.Floor(fee*100) / 100
|
||||||
|
return this.Query(tx).
|
||||||
|
InsertOrUpdateQuickly(maps.Map{
|
||||||
|
"userId": userId,
|
||||||
|
"serverId": serverId,
|
||||||
|
"month": month,
|
||||||
|
"priceType": priceType,
|
||||||
|
"amount": fee,
|
||||||
|
"userPlanId": userPlanId,
|
||||||
|
"planId": planId,
|
||||||
|
"totalTrafficBytes": totalTrafficBytes,
|
||||||
|
"bandwidthPercentileBytes": bandwidthPercentileBytes,
|
||||||
|
"bandwidthPercentile": bandwidthPercentile,
|
||||||
|
"createdAt": time.Now().Unix(),
|
||||||
|
}, maps.Map{
|
||||||
|
"userId": userId,
|
||||||
|
"priceType": priceType,
|
||||||
|
"amount": fee,
|
||||||
|
"userPlanId": userPlanId,
|
||||||
|
"planId": planId,
|
||||||
|
"totalTrafficBytes": totalTrafficBytes,
|
||||||
|
"bandwidthPercentileBytes": bandwidthPercentileBytes,
|
||||||
|
"bandwidthPercentile": bandwidthPercentile,
|
||||||
|
"createdAt": time.Now().Unix(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SumUserMonthlyAmount 计算总费用
|
||||||
|
func (this *ServerBillDAO) SumUserMonthlyAmount(tx *dbs.Tx, userId int64, month string) (float64, error) {
|
||||||
|
return this.Query(tx).
|
||||||
|
Attr("userId", userId).
|
||||||
|
Attr("month", month).
|
||||||
|
Sum("amount", 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountServerBills 计算总账单数量
|
||||||
|
func (this *ServerBillDAO) CountServerBills(tx *dbs.Tx, userId int64, month string) (int64, error) {
|
||||||
|
var query = this.Query(tx)
|
||||||
|
if userId > 0 {
|
||||||
|
query.Attr("userId", userId)
|
||||||
|
}
|
||||||
|
if len(month) > 0 {
|
||||||
|
query.Attr("month", month)
|
||||||
|
}
|
||||||
|
return query.Count()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListServerBills 列出单页账单
|
||||||
|
func (this *ServerBillDAO) ListServerBills(tx *dbs.Tx, userId int64, month string, offset int64, size int64) (result []*ServerBill, err error) {
|
||||||
|
var query = this.Query(tx)
|
||||||
|
if userId > 0 {
|
||||||
|
query.Attr("userId", userId)
|
||||||
|
}
|
||||||
|
if len(month) > 0 {
|
||||||
|
query.Attr("month", month)
|
||||||
|
}
|
||||||
|
_, err = query.
|
||||||
|
Desc("serverId").
|
||||||
|
Offset(offset).
|
||||||
|
Limit(size).
|
||||||
|
Slice(&result).
|
||||||
|
FindAll()
|
||||||
|
return
|
||||||
|
}
|
||||||
20
internal/db/models/server_bill_dao_test.go
Normal file
20
internal/db/models/server_bill_dao_test.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestServerBillDAO_CreateOrUpdateServerBill(t *testing.T) {
|
||||||
|
var dao = NewServerBillDAO()
|
||||||
|
var tx *dbs.Tx
|
||||||
|
var month = timeutil.Format("Y02")
|
||||||
|
err := dao.CreateOrUpdateServerBill(tx, 1, 2, month, 4, 5, 6, 7, 95, "", 100)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log("ok")
|
||||||
|
}
|
||||||
36
internal/db/models/server_bill_model.go
Normal file
36
internal/db/models/server_bill_model.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
// ServerBill 服务账单
|
||||||
|
type ServerBill struct {
|
||||||
|
Id uint64 `field:"id"` // ID
|
||||||
|
UserId uint32 `field:"userId"` // 用户ID
|
||||||
|
ServerId uint32 `field:"serverId"` // 服务ID
|
||||||
|
Amount float64 `field:"amount"` // 金额
|
||||||
|
Month string `field:"month"` // 月份
|
||||||
|
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||||
|
UserPlanId uint32 `field:"userPlanId"` // 用户套餐ID
|
||||||
|
PlanId uint32 `field:"planId"` // 套餐ID
|
||||||
|
TotalTrafficBytes uint64 `field:"totalTrafficBytes"` // 总流量
|
||||||
|
BandwidthPercentileBytes uint64 `field:"bandwidthPercentileBytes"` // 带宽百分位字节
|
||||||
|
BandwidthPercentile uint8 `field:"bandwidthPercentile"` // 带宽百分位
|
||||||
|
PriceType string `field:"priceType"` // 计费类型
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerBillOperator struct {
|
||||||
|
Id interface{} // ID
|
||||||
|
UserId interface{} // 用户ID
|
||||||
|
ServerId interface{} // 服务ID
|
||||||
|
Amount interface{} // 金额
|
||||||
|
Month interface{} // 月份
|
||||||
|
CreatedAt interface{} // 创建时间
|
||||||
|
UserPlanId interface{} // 用户套餐ID
|
||||||
|
PlanId interface{} // 套餐ID
|
||||||
|
TotalTrafficBytes interface{} // 总流量
|
||||||
|
BandwidthPercentileBytes interface{} // 带宽百分位字节
|
||||||
|
BandwidthPercentile interface{} // 带宽百分位
|
||||||
|
PriceType interface{} // 计费类型
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServerBillOperator() *ServerBillOperator {
|
||||||
|
return &ServerBillOperator{}
|
||||||
|
}
|
||||||
1
internal/db/models/server_bill_model_ext.go
Normal file
1
internal/db/models/server_bill_model_ext.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package models
|
||||||
@@ -12,7 +12,9 @@ import (
|
|||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
"github.com/iwind/TeaGo/rands"
|
"github.com/iwind/TeaGo/rands"
|
||||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
"math"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -24,7 +26,7 @@ func init() {
|
|||||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||||
goman.New(func() {
|
goman.New(func() {
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
err := SharedServerDailyStatDAO.Clean(nil, 30) // 只保留N天
|
err := SharedServerDailyStatDAO.Clean(nil, 60) // 只保留 N 天,时间需要长一些,因为需要用来生成账单
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Println("ServerDailyStatDAO", "clean expired data failed: "+err.Error())
|
logs.Println("ServerDailyStatDAO", "clean expired data failed: "+err.Error())
|
||||||
}
|
}
|
||||||
@@ -130,15 +132,15 @@ func (this *ServerDailyStatDAO) SaveStats(tx *dbs.Tx, stats []*pb.ServerDailySta
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SumUserMonthly 根据用户计算某月合计
|
// SumServerMonthlyWithRegion 根据服务计算某月合计
|
||||||
// month 格式为YYYYMM
|
// month 格式为YYYYMM
|
||||||
func (this *ServerDailyStatDAO) SumUserMonthly(tx *dbs.Tx, userId int64, regionId int64, month string) (int64, error) {
|
func (this *ServerDailyStatDAO) SumServerMonthlyWithRegion(tx *dbs.Tx, serverId int64, regionId int64, month string) (int64, error) {
|
||||||
query := this.Query(tx)
|
query := this.Query(tx)
|
||||||
if regionId > 0 {
|
if regionId > 0 {
|
||||||
query.Attr("regionId", regionId)
|
query.Attr("regionId", regionId)
|
||||||
}
|
}
|
||||||
return query.Between("day", month+"01", month+"32").
|
return query.Between("day", month+"01", month+"32").
|
||||||
Attr("userId", userId).
|
Attr("serverId", serverId).
|
||||||
SumInt64("bytes", 0)
|
SumInt64("bytes", 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,16 +158,6 @@ func (this *ServerDailyStatDAO) SumUserMonthlyWithoutPlan(tx *dbs.Tx, userId int
|
|||||||
SumInt64("bytes", 0)
|
SumInt64("bytes", 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SumUserMonthlyFee 计算用户某个月费用
|
|
||||||
// month 格式为YYYYMM
|
|
||||||
func (this *ServerDailyStatDAO) SumUserMonthlyFee(tx *dbs.Tx, userId int64, month string) (float64, error) {
|
|
||||||
return this.Query(tx).
|
|
||||||
Attr("userId", userId).
|
|
||||||
Between("day", month+"01", month+"32").
|
|
||||||
Gt("fee", 0).
|
|
||||||
Sum("fee", 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SumUserMonthlyPeek 获取某月带宽峰值
|
// SumUserMonthlyPeek 获取某月带宽峰值
|
||||||
// month 格式为YYYYMM
|
// month 格式为YYYYMM
|
||||||
func (this *ServerDailyStatDAO) SumUserMonthlyPeek(tx *dbs.Tx, userId int64, regionId int64, month string) (int64, error) {
|
func (this *ServerDailyStatDAO) SumUserMonthlyPeek(tx *dbs.Tx, userId int64, regionId int64, month string) (int64, error) {
|
||||||
@@ -195,6 +187,15 @@ func (this *ServerDailyStatDAO) SumUserDaily(tx *dbs.Tx, userId int64, regionId
|
|||||||
SumInt64("bytes", 0)
|
SumInt64("bytes", 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SumUserMonthly 获取某月流量总和
|
||||||
|
// month 格式为YYYYMM
|
||||||
|
func (this *ServerDailyStatDAO) SumUserMonthly(tx *dbs.Tx, userId int64, month string) (int64, error) {
|
||||||
|
return this.Query(tx).
|
||||||
|
Between("day", month+"01", month+"31").
|
||||||
|
Attr("userId", userId).
|
||||||
|
SumInt64("bytes", 0)
|
||||||
|
}
|
||||||
|
|
||||||
// SumUserDailyPeek 获取某天带宽峰值
|
// SumUserDailyPeek 获取某天带宽峰值
|
||||||
// day 格式为YYYYMMDD
|
// day 格式为YYYYMMDD
|
||||||
func (this *ServerDailyStatDAO) SumUserDailyPeek(tx *dbs.Tx, userId int64, regionId int64, day string) (int64, error) {
|
func (this *ServerDailyStatDAO) SumUserDailyPeek(tx *dbs.Tx, userId int64, regionId int64, day string) (int64, error) {
|
||||||
@@ -339,6 +340,59 @@ func (this *ServerDailyStatDAO) SumMonthlyStat(tx *dbs.Tx, serverId int64, month
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SumMonthlyBytes 获取某月内的流量
|
||||||
|
// month 格式为YYYYMM
|
||||||
|
func (this *ServerDailyStatDAO) SumMonthlyBytes(tx *dbs.Tx, serverId int64, month string) (result int64, err error) {
|
||||||
|
if !regexp.MustCompile(`^\d{6}$`).MatchString(month) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.Query(tx).
|
||||||
|
Result("SUM(bytes) AS bytes").
|
||||||
|
Attr("serverId", serverId).
|
||||||
|
Between("day", month+"01", month+"31").
|
||||||
|
FindInt64Col(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindMonthlyPercentile 获取某月内百分位
|
||||||
|
func (this *ServerDailyStatDAO) FindMonthlyPercentile(tx *dbs.Tx, serverId int64, month string, percentile int) (result int64, err error) {
|
||||||
|
if percentile <= 0 {
|
||||||
|
percentile = 95
|
||||||
|
}
|
||||||
|
if percentile > 100 {
|
||||||
|
percentile = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
total, err := this.Query(tx).
|
||||||
|
Attr("serverId", serverId).
|
||||||
|
Between("day", month+"01", month+"31").
|
||||||
|
Count()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if total == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var offset int64
|
||||||
|
|
||||||
|
if total > 1 {
|
||||||
|
offset = int64(math.Ceil(float64(total) * float64(100-percentile) / 100))
|
||||||
|
}
|
||||||
|
result, err = this.Query(tx).
|
||||||
|
Result("bytes").
|
||||||
|
Attr("serverId", serverId).
|
||||||
|
Between("day", month+"01", month+"31").
|
||||||
|
Desc("bytes").
|
||||||
|
Offset(offset).
|
||||||
|
Limit(1).
|
||||||
|
FindInt64Col(0)
|
||||||
|
|
||||||
|
// 因为是5分钟统计,所以需要除以300
|
||||||
|
result = result / 300
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// FindDailyStats 按天统计
|
// FindDailyStats 按天统计
|
||||||
func (this *ServerDailyStatDAO) FindDailyStats(tx *dbs.Tx, serverId int64, dayFrom string, dayTo string) (result []*ServerDailyStat, err error) {
|
func (this *ServerDailyStatDAO) FindDailyStats(tx *dbs.Tx, serverId int64, dayFrom string, dayTo string) (result []*ServerDailyStat, err error) {
|
||||||
ones, err := this.Query(tx).
|
ones, err := this.Query(tx).
|
||||||
@@ -428,6 +482,25 @@ func (this *ServerDailyStatDAO) FindTopUserStats(tx *dbs.Tx, hourFrom string, ho
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindDistinctServerIds 查找所有有流量的服务ID列表
|
||||||
|
// dayFrom YYYYMMDD
|
||||||
|
// dayTo YYYYMMDD
|
||||||
|
func (this *ServerDailyStatDAO) FindDistinctServerIds(tx *dbs.Tx, dayFrom string, dayTo string) (serverIds []int64, err error) {
|
||||||
|
dayFrom = strings.ReplaceAll(dayFrom, "-", "")
|
||||||
|
dayTo = strings.ReplaceAll(dayTo, "-", "")
|
||||||
|
ones, _, err := this.Query(tx).
|
||||||
|
Result("DISTINCT(serverId) AS serverId").
|
||||||
|
Between("day", dayFrom, dayTo).
|
||||||
|
FindOnes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, one := range ones {
|
||||||
|
serverIds = append(serverIds, one.GetInt64("serverId"))
|
||||||
|
}
|
||||||
|
return serverIds, nil
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateStatFee 设置费用
|
// UpdateStatFee 设置费用
|
||||||
func (this *ServerDailyStatDAO) UpdateStatFee(tx *dbs.Tx, statId int64, fee float32) error {
|
func (this *ServerDailyStatDAO) UpdateStatFee(tx *dbs.Tx, statId int64, fee float32) error {
|
||||||
return this.Query(tx).
|
return this.Query(tx).
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ func TestServerDailyStatDAO_SaveStats2(t *testing.T) {
|
|||||||
func TestServerDailyStatDAO_SumUserMonthly(t *testing.T) {
|
func TestServerDailyStatDAO_SumUserMonthly(t *testing.T) {
|
||||||
dbs.NotifyReady()
|
dbs.NotifyReady()
|
||||||
var tx *dbs.Tx
|
var tx *dbs.Tx
|
||||||
bytes, err := NewServerDailyStatDAO().SumUserMonthly(tx, 1, 1, timeutil.Format("Ym"))
|
bytes, err := NewServerDailyStatDAO().SumUserMonthly(tx, 1, timeutil.Format("Ym"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -68,9 +68,28 @@ func TestServerDailyStatDAO_SumMinutelyRequests(t *testing.T) {
|
|||||||
dbs.NotifyReady()
|
dbs.NotifyReady()
|
||||||
var tx *dbs.Tx
|
var tx *dbs.Tx
|
||||||
|
|
||||||
stat, err := NewServerDailyStatDAO().SumMinutelyStat(tx, 23, timeutil.Format("Ymd") + "1435")
|
stat, err := NewServerDailyStatDAO().SumMinutelyStat(tx, 23, timeutil.Format("Ymd")+"1435")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
logs.PrintAsJSON(stat, t)
|
logs.PrintAsJSON(stat, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestServerDailyStatDAO_FindDistinctPlanServerIdsBetweenDay(t *testing.T) {
|
||||||
|
var tx *dbs.Tx
|
||||||
|
serverIds, err := NewServerDailyStatDAO().FindDistinctServerIds(tx, timeutil.Format("Ym01"), timeutil.Format("Ymd"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(serverIds)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServerDailyStatDAO_FindMonthlyPercentile(t *testing.T) {
|
||||||
|
var tx *dbs.Tx
|
||||||
|
var dao = NewServerDailyStatDAO()
|
||||||
|
result, err := dao.FindMonthlyPercentile(tx, 23, timeutil.Format("Ym"), 95)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log("result:", result)
|
||||||
|
}
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ func (this *ServerDAO) CreateServer(tx *dbs.Tx,
|
|||||||
op.DnsName = dnsName
|
op.DnsName = dnsName
|
||||||
|
|
||||||
op.UserPlanId = userPlanId
|
op.UserPlanId = userPlanId
|
||||||
|
op.LastUserPlanId = userPlanId
|
||||||
|
|
||||||
op.Version = 1
|
op.Version = 1
|
||||||
op.IsOn = 1
|
op.IsOn = 1
|
||||||
@@ -1226,6 +1227,16 @@ func (this *ServerDAO) FindAllEnabledServerIdsWithSSLPolicyIds(tx *dbs.Tx, sslPo
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExistEnabledUserServerWithSSLPolicyId 检查是否存在某个用户的策略
|
||||||
|
func (this *ServerDAO) ExistEnabledUserServerWithSSLPolicyId(tx *dbs.Tx, userId int64, sslPolicyId int64) (bool, error) {
|
||||||
|
return this.Query(tx).
|
||||||
|
State(ServerStateEnabled).
|
||||||
|
Attr("userId", userId).
|
||||||
|
Where("(JSON_CONTAINS(https, :jsonQuery) OR JSON_CONTAINS(tls, :jsonQuery))").
|
||||||
|
Param("jsonQuery", maps.Map{"sslPolicyRef": maps.Map{"sslPolicyId": sslPolicyId}}.AsJSON()).
|
||||||
|
Exist()
|
||||||
|
}
|
||||||
|
|
||||||
// CountEnabledServersWithWebIds 计算使用某个缓存策略的所有服务数量
|
// CountEnabledServersWithWebIds 计算使用某个缓存策略的所有服务数量
|
||||||
func (this *ServerDAO) CountEnabledServersWithWebIds(tx *dbs.Tx, webIds []int64) (count int64, err error) {
|
func (this *ServerDAO) CountEnabledServersWithWebIds(tx *dbs.Tx, webIds []int64) (count int64, err error) {
|
||||||
if len(webIds) == 0 {
|
if len(webIds) == 0 {
|
||||||
@@ -1262,9 +1273,13 @@ func (this *ServerDAO) CountAllEnabledServersWithNodeClusterId(tx *dbs.Tx, clust
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CountAllEnabledServersWithGroupId 计算使用某个分组的服务数量
|
// CountAllEnabledServersWithGroupId 计算使用某个分组的服务数量
|
||||||
func (this *ServerDAO) CountAllEnabledServersWithGroupId(tx *dbs.Tx, groupId int64) (int64, error) {
|
func (this *ServerDAO) CountAllEnabledServersWithGroupId(tx *dbs.Tx, groupId int64, userId int64) (int64, error) {
|
||||||
return this.Query(tx).
|
var query = this.Query(tx).
|
||||||
State(ServerStateEnabled).
|
State(ServerStateEnabled)
|
||||||
|
if userId > 0 {
|
||||||
|
query.Attr("userId", userId)
|
||||||
|
}
|
||||||
|
return query.
|
||||||
Where("JSON_CONTAINS(groupIds, :groupId)").
|
Where("JSON_CONTAINS(groupIds, :groupId)").
|
||||||
Param("groupId", numberutils.FormatInt64(groupId)).
|
Param("groupId", numberutils.FormatInt64(groupId)).
|
||||||
Count()
|
Count()
|
||||||
@@ -1496,11 +1511,11 @@ func (this *ServerDAO) UpdateUserServersClusterId(tx *dbs.Tx, userId int64, oldC
|
|||||||
}
|
}
|
||||||
|
|
||||||
if oldClusterId > 0 {
|
if oldClusterId > 0 {
|
||||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, oldClusterId, NodeTaskTypeConfigChanged)
|
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, oldClusterId, 0, NodeTaskTypeConfigChanged)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, oldClusterId, NodeTaskTypeIPItemChanged)
|
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, oldClusterId, 0, NodeTaskTypeIPItemChanged)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -1511,11 +1526,11 @@ func (this *ServerDAO) UpdateUserServersClusterId(tx *dbs.Tx, userId int64, oldC
|
|||||||
}
|
}
|
||||||
|
|
||||||
if newClusterId > 0 {
|
if newClusterId > 0 {
|
||||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, newClusterId, NodeTaskTypeConfigChanged)
|
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, newClusterId, 0, NodeTaskTypeConfigChanged)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, newClusterId, NodeTaskTypeIPItemChanged)
|
err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, newClusterId, 0, NodeTaskTypeIPItemChanged)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -2238,6 +2253,7 @@ func (this *ServerDAO) UpdateServerUserPlanId(tx *dbs.Tx, serverId int64, userPl
|
|||||||
err = this.Query(tx).
|
err = this.Query(tx).
|
||||||
Pk(serverId).
|
Pk(serverId).
|
||||||
Set("userPlanId", userPlanId).
|
Set("userPlanId", userPlanId).
|
||||||
|
Set("lastUserPlanId", userPlanId).
|
||||||
Set("clusterId", plan.ClusterId).
|
Set("clusterId", plan.ClusterId).
|
||||||
UpdateQuickly()
|
UpdateQuickly()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -2246,6 +2262,19 @@ func (this *ServerDAO) UpdateServerUserPlanId(tx *dbs.Tx, serverId int64, userPl
|
|||||||
return this.NotifyUpdate(tx, serverId)
|
return this.NotifyUpdate(tx, serverId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindServerLastUserPlanIdAndUserId 查找最后使用的套餐
|
||||||
|
func (this *ServerDAO) FindServerLastUserPlanIdAndUserId(tx *dbs.Tx, serverId int64) (userPlanId int64, userId int64, err error) {
|
||||||
|
one, err := this.Query(tx).
|
||||||
|
Pk(serverId).
|
||||||
|
Result("lastUserPlanId", "userId").
|
||||||
|
Find()
|
||||||
|
if err != nil || one == nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return int64(one.(*Server).LastUserPlanId), int64(one.(*Server).UserId), nil
|
||||||
|
}
|
||||||
|
|
||||||
// NotifyUpdate 同步集群
|
// NotifyUpdate 同步集群
|
||||||
func (this *ServerDAO) NotifyUpdate(tx *dbs.Tx, serverId int64) error {
|
func (this *ServerDAO) NotifyUpdate(tx *dbs.Tx, serverId int64) error {
|
||||||
// 创建任务
|
// 创建任务
|
||||||
@@ -2256,7 +2285,7 @@ func (this *ServerDAO) NotifyUpdate(tx *dbs.Tx, serverId int64) error {
|
|||||||
if clusterId == 0 {
|
if clusterId == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, NodeTaskTypeConfigChanged)
|
return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, serverId, NodeTaskTypeConfigChanged)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotifyDNSUpdate 通知DNS更新
|
// NotifyDNSUpdate 通知DNS更新
|
||||||
|
|||||||
@@ -77,10 +77,11 @@ func (this *ServerGroupDAO) FindServerGroupName(tx *dbs.Tx, id int64) (string, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateGroup 创建分组
|
// CreateGroup 创建分组
|
||||||
func (this *ServerGroupDAO) CreateGroup(tx *dbs.Tx, name string) (groupId int64, err error) {
|
func (this *ServerGroupDAO) CreateGroup(tx *dbs.Tx, name string, userId int64) (groupId int64, err error) {
|
||||||
op := NewServerGroupOperator()
|
op := NewServerGroupOperator()
|
||||||
op.State = ServerGroupStateEnabled
|
op.State = ServerGroupStateEnabled
|
||||||
op.Name = name
|
op.Name = name
|
||||||
|
op.UserId = userId
|
||||||
op.IsOn = true
|
op.IsOn = true
|
||||||
err = this.Save(tx, op)
|
err = this.Save(tx, op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -102,9 +103,15 @@ func (this *ServerGroupDAO) UpdateGroup(tx *dbs.Tx, groupId int64, name string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FindAllEnabledGroups 查找所有分组
|
// FindAllEnabledGroups 查找所有分组
|
||||||
func (this *ServerGroupDAO) FindAllEnabledGroups(tx *dbs.Tx) (result []*ServerGroup, err error) {
|
func (this *ServerGroupDAO) FindAllEnabledGroups(tx *dbs.Tx, userId int64) (result []*ServerGroup, err error) {
|
||||||
_, err = this.Query(tx).
|
var query = this.Query(tx).
|
||||||
State(ServerGroupStateEnabled).
|
State(ServerGroupStateEnabled)
|
||||||
|
if userId > 0 {
|
||||||
|
query.Attr("userId", userId)
|
||||||
|
} else {
|
||||||
|
query.Attr("userId", 0)
|
||||||
|
}
|
||||||
|
_, err = query.
|
||||||
Desc("order").
|
Desc("order").
|
||||||
AscPk().
|
AscPk().
|
||||||
Slice(&result).
|
Slice(&result).
|
||||||
@@ -113,9 +120,13 @@ func (this *ServerGroupDAO) FindAllEnabledGroups(tx *dbs.Tx) (result []*ServerGr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateGroupOrders 修改分组排序
|
// UpdateGroupOrders 修改分组排序
|
||||||
func (this *ServerGroupDAO) UpdateGroupOrders(tx *dbs.Tx, groupIds []int64) error {
|
func (this *ServerGroupDAO) UpdateGroupOrders(tx *dbs.Tx, groupIds []int64, userId int64) error {
|
||||||
for index, groupId := range groupIds {
|
for index, groupId := range groupIds {
|
||||||
_, err := this.Query(tx).
|
var query = this.Query(tx)
|
||||||
|
if userId > 0 {
|
||||||
|
query.Attr("userId", userId)
|
||||||
|
}
|
||||||
|
_, err := query.
|
||||||
Pk(groupId).
|
Pk(groupId).
|
||||||
Set("order", len(groupIds)-index).
|
Set("order", len(groupIds)-index).
|
||||||
Update()
|
Update()
|
||||||
@@ -383,6 +394,22 @@ func (this *ServerGroupDAO) FindEnabledGroupIdWithReverseProxyId(tx *dbs.Tx, rev
|
|||||||
FindInt64Col(0)
|
FindInt64Col(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckUserGroup 检查用户分组
|
||||||
|
func (this *ServerGroupDAO) CheckUserGroup(tx *dbs.Tx, userId int64, groupId int64) error {
|
||||||
|
b, err := this.Query(tx).
|
||||||
|
Pk(groupId).
|
||||||
|
Attr("userId", userId).
|
||||||
|
State(ServerGroupStateEnabled).
|
||||||
|
Exist()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !b {
|
||||||
|
return ErrNotFound
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// NotifyUpdate 通知更新
|
// NotifyUpdate 通知更新
|
||||||
func (this *ServerGroupDAO) NotifyUpdate(tx *dbs.Tx, groupId int64) error {
|
func (this *ServerGroupDAO) NotifyUpdate(tx *dbs.Tx, groupId int64) error {
|
||||||
serverIds, err := SharedServerDAO.FindAllEnabledServerIdsWithGroupId(tx, groupId)
|
serverIds, err := SharedServerDAO.FindAllEnabledServerIdsWithGroupId(tx, groupId)
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ type Server struct {
|
|||||||
TrafficLimitStatus string `field:"trafficLimitStatus"` // 流量限制状态
|
TrafficLimitStatus string `field:"trafficLimitStatus"` // 流量限制状态
|
||||||
TotalTraffic float64 `field:"totalTraffic"` // 总流量
|
TotalTraffic float64 `field:"totalTraffic"` // 总流量
|
||||||
UserPlanId uint32 `field:"userPlanId"` // 所属套餐ID
|
UserPlanId uint32 `field:"userPlanId"` // 所属套餐ID
|
||||||
|
LastUserPlanId uint32 `field:"lastUserPlanId"` // 上一次使用的套餐
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerOperator struct {
|
type ServerOperator struct {
|
||||||
@@ -87,6 +88,7 @@ type ServerOperator struct {
|
|||||||
TrafficLimitStatus interface{} // 流量限制状态
|
TrafficLimitStatus interface{} // 流量限制状态
|
||||||
TotalTraffic interface{} // 总流量
|
TotalTraffic interface{} // 总流量
|
||||||
UserPlanId interface{} // 所属套餐ID
|
UserPlanId interface{} // 所属套餐ID
|
||||||
|
LastUserPlanId interface{} // 上一次使用的套餐
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServerOperator() *ServerOperator {
|
func NewServerOperator() *ServerOperator {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||||
@@ -113,6 +114,8 @@ func (this *SSLCertDAO) CreateCert(tx *dbs.Tx, adminId int64, userId int64, isOn
|
|||||||
}
|
}
|
||||||
op.CommonNames = commonNamesJSON
|
op.CommonNames = commonNamesJSON
|
||||||
|
|
||||||
|
op.OcspIsUpdated = false
|
||||||
|
|
||||||
err = this.Save(tx, op)
|
err = this.Save(tx, op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -121,11 +124,33 @@ func (this *SSLCertDAO) CreateCert(tx *dbs.Tx, adminId int64, userId int64, isOn
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateCert 修改证书
|
// UpdateCert 修改证书
|
||||||
func (this *SSLCertDAO) UpdateCert(tx *dbs.Tx, certId int64, isOn bool, name string, description string, serverName string, isCA bool, certData []byte, keyData []byte, timeBeginAt int64, timeEndAt int64, dnsNames []string, commonNames []string) error {
|
func (this *SSLCertDAO) UpdateCert(tx *dbs.Tx,
|
||||||
|
certId int64,
|
||||||
|
isOn bool,
|
||||||
|
name string,
|
||||||
|
description string,
|
||||||
|
serverName string,
|
||||||
|
isCA bool,
|
||||||
|
certData []byte,
|
||||||
|
keyData []byte,
|
||||||
|
timeBeginAt int64,
|
||||||
|
timeEndAt int64,
|
||||||
|
dnsNames []string, commonNames []string) error {
|
||||||
if certId <= 0 {
|
if certId <= 0 {
|
||||||
return errors.New("invalid certId")
|
return errors.New("invalid certId")
|
||||||
}
|
}
|
||||||
op := NewSSLCertOperator()
|
|
||||||
|
oldOne, err := this.Query(tx).Find()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if oldOne == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var oldCert = oldOne.(*SSLCert)
|
||||||
|
var dataIsChanged = bytes.Compare(certData, []byte(oldCert.CertData)) != 0 || bytes.Compare(keyData, []byte(oldCert.KeyData)) != 0
|
||||||
|
|
||||||
|
var op = NewSSLCertOperator()
|
||||||
op.Id = certId
|
op.Id = certId
|
||||||
op.IsOn = isOn
|
op.IsOn = isOn
|
||||||
op.Name = name
|
op.Name = name
|
||||||
@@ -156,6 +181,16 @@ func (this *SSLCertDAO) UpdateCert(tx *dbs.Tx, certId int64, isOn bool, name str
|
|||||||
}
|
}
|
||||||
op.CommonNames = commonNamesJSON
|
op.CommonNames = commonNamesJSON
|
||||||
|
|
||||||
|
// OCSP
|
||||||
|
if dataIsChanged {
|
||||||
|
op.OcspIsUpdated = 0
|
||||||
|
op.Ocsp = ""
|
||||||
|
op.OcspUpdatedAt = 0
|
||||||
|
op.OcspError = ""
|
||||||
|
op.OcspTries = 0
|
||||||
|
op.OcspExpiresAt = 0
|
||||||
|
}
|
||||||
|
|
||||||
err = this.Save(tx, op)
|
err = this.Save(tx, op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -195,6 +230,13 @@ func (this *SSLCertDAO) ComposeCertConfig(tx *dbs.Tx, certId int64, cacheMap *ut
|
|||||||
config.TimeBeginAt = int64(cert.TimeBeginAt)
|
config.TimeBeginAt = int64(cert.TimeBeginAt)
|
||||||
config.TimeEndAt = int64(cert.TimeEndAt)
|
config.TimeEndAt = int64(cert.TimeEndAt)
|
||||||
|
|
||||||
|
// OCSP
|
||||||
|
if int64(cert.OcspExpiresAt) > time.Now().Unix() {
|
||||||
|
config.OCSP = []byte(cert.Ocsp)
|
||||||
|
config.OCSPExpiresAt = int64(cert.OcspExpiresAt)
|
||||||
|
}
|
||||||
|
config.OCSPError = cert.OcspError
|
||||||
|
|
||||||
if IsNotNull(cert.DnsNames) {
|
if IsNotNull(cert.DnsNames) {
|
||||||
dnsNames := []string{}
|
dnsNames := []string{}
|
||||||
err := json.Unmarshal([]byte(cert.DnsNames), &dnsNames)
|
err := json.Unmarshal([]byte(cert.DnsNames), &dnsNames)
|
||||||
@@ -356,6 +398,197 @@ func (this *SSLCertDAO) CheckUserCert(tx *dbs.Tx, certId int64, userId int64) er
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListCertsToUpdateOCSP 查找需要更新OCSP的证书
|
||||||
|
func (this *SSLCertDAO) ListCertsToUpdateOCSP(tx *dbs.Tx, maxTries int, size int64) (result []*SSLCert, err error) {
|
||||||
|
var nowTime = time.Now().Unix()
|
||||||
|
var query = this.Query(tx).
|
||||||
|
State(SSLCertStateEnabled).
|
||||||
|
Lt("ocspExpiresAt", nowTime+120). // 提前 N 秒钟准备更新
|
||||||
|
Lt("ocspTries", maxTries).
|
||||||
|
Lt("timeBeginAt", nowTime).
|
||||||
|
Gt("timeEndAt", nowTime)
|
||||||
|
|
||||||
|
// TODO 需要排除没有被server使用的policy,或许可以增加一个字段记录policy最近使用时间
|
||||||
|
|
||||||
|
// 检查函数
|
||||||
|
var JSONArrayAggIsEnabled = false
|
||||||
|
_, err = this.Object().Instance.Exec("SELECT JSON_ARRAYAGG('1')")
|
||||||
|
if err == nil {
|
||||||
|
JSONArrayAggIsEnabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if JSONArrayAggIsEnabled {
|
||||||
|
query.Where("JSON_CONTAINS((SELECT JSON_ARRAYAGG(JSON_EXTRACT(certs, '$[*].certId')) FROM edgeSSLPolicies WHERE state=1 AND ocspIsOn=1 AND certs IS NOT NULL), CAST(id AS CHAR))")
|
||||||
|
} else {
|
||||||
|
query.Where("JSON_CONTAINS((SELECT REPLACE(GROUP_CONCAT(JSON_EXTRACT(certs, '$[*].certId')), '],[', ',') FROM edgeSSLPolicies WHERE state=1 AND ocspIsOn=1 AND certs IS NOT NULL), CAST(id AS CHAR))")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = query.
|
||||||
|
Asc("ocspUpdatedAt").
|
||||||
|
Limit(size).
|
||||||
|
Slice(&result).
|
||||||
|
FindAll()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListCertOCSPAfterVersion 列出某个版本后的OCSP
|
||||||
|
func (this *SSLCertDAO) ListCertOCSPAfterVersion(tx *dbs.Tx, version int64, size int64) (result []*SSLCert, err error) {
|
||||||
|
// 不需要判断ocsp是否为空
|
||||||
|
_, err = this.Query(tx).
|
||||||
|
Result("id", "ocsp", "ocspUpdatedVersion", "ocspExpiresAt").
|
||||||
|
State(SSLCertStateEnabled).
|
||||||
|
Attr("ocspIsUpdated", 1).
|
||||||
|
Gt("ocspUpdatedVersion", version).
|
||||||
|
Asc("ocspUpdatedVersion").
|
||||||
|
Limit(size).
|
||||||
|
Slice(&result).
|
||||||
|
FindAll()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindCertOCSPLatestVersion 获取OCSP最新版本
|
||||||
|
func (this *SSLCertDAO) FindCertOCSPLatestVersion(tx *dbs.Tx) (int64, error) {
|
||||||
|
return this.Query(tx).
|
||||||
|
Result("ocspUpdatedVersion").
|
||||||
|
Desc("ocspUpdatedVersion").
|
||||||
|
Limit(1).
|
||||||
|
FindInt64Col(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrepareCertOCSPUpdating 更新OCSP更新时间,以便于准备更新,相当于锁定
|
||||||
|
func (this *SSLCertDAO) PrepareCertOCSPUpdating(tx *dbs.Tx, certId int64) error {
|
||||||
|
return this.Query(tx).
|
||||||
|
Pk(certId).
|
||||||
|
Set("ocspUpdatedAt", time.Now().Unix()).
|
||||||
|
UpdateQuickly()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateCertOCSP 修改OCSP
|
||||||
|
func (this *SSLCertDAO) UpdateCertOCSP(tx *dbs.Tx, certId int64, ocsp []byte, expiresAt int64, hasErr bool, errString string) error {
|
||||||
|
if hasErr && len(errString) == 0 {
|
||||||
|
errString = "failed"
|
||||||
|
}
|
||||||
|
|
||||||
|
version, err := SharedSysLockerDAO.Increase(tx, "SSL_CERT_OCSP_VERSION", 1)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ocsp == nil {
|
||||||
|
ocsp = []byte{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 限制长度
|
||||||
|
if len(errString) > 300 {
|
||||||
|
errString = errString[:300]
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = this.Query(tx).
|
||||||
|
Pk(certId).
|
||||||
|
Set("ocsp", ocsp).
|
||||||
|
Set("ocspError", errString).
|
||||||
|
Set("ocspIsUpdated", true).
|
||||||
|
Set("ocspUpdatedAt", time.Now().Unix()).
|
||||||
|
Set("ocspUpdatedVersion", version).
|
||||||
|
Set("ocspExpiresAt", expiresAt)
|
||||||
|
|
||||||
|
if hasErr {
|
||||||
|
query.Set("ocspTries", dbs.SQL("ocspTries+1"))
|
||||||
|
} else {
|
||||||
|
query.Set("ocspTries", 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = query.UpdateQuickly()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注意:这里不通知更新,避免频繁的更新导致服务不稳定
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountAllSSLCertsWithOCSPError 计算有OCSP错误的证书数量
|
||||||
|
func (this *SSLCertDAO) CountAllSSLCertsWithOCSPError(tx *dbs.Tx, keyword string) (int64, error) {
|
||||||
|
var query = this.Query(tx)
|
||||||
|
|
||||||
|
if len(keyword) > 0 {
|
||||||
|
query.Where("(name LIKE :keyword OR description LIKE :keyword OR dnsNames LIKE :keyword OR commonNames LIKE :keyword OR ocspError LIKE :keyword)").
|
||||||
|
Param("keyword", "%"+keyword+"%")
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.
|
||||||
|
State(SSLCertStateEnabled).
|
||||||
|
Attr("ocspIsUpdated", true).
|
||||||
|
Where("LENGTH(ocspError) > 0").
|
||||||
|
Count()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListSSLCertsWithOCSPError 列出有OCSP错误的证书
|
||||||
|
func (this *SSLCertDAO) ListSSLCertsWithOCSPError(tx *dbs.Tx, keyword string, offset int64, size int64) (result []*SSLCert, err error) {
|
||||||
|
var query = this.Query(tx)
|
||||||
|
|
||||||
|
if len(keyword) > 0 {
|
||||||
|
query.Where("(name LIKE :keyword OR description LIKE :keyword OR dnsNames LIKE :keyword OR commonNames LIKE :keyword OR ocspError LIKE :keyword)").
|
||||||
|
Param("keyword", "%"+keyword+"%")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = query.
|
||||||
|
State(SSLCertStateEnabled).
|
||||||
|
Attr("ocspIsUpdated", true).
|
||||||
|
Where("LENGTH(ocspError) > 0").
|
||||||
|
Offset(offset).
|
||||||
|
Limit(size).
|
||||||
|
DescPk().
|
||||||
|
Slice(&result).
|
||||||
|
FindAll()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// IgnoreSSLCertsWithOCSPError 忽略一组OCSP证书错误
|
||||||
|
func (this *SSLCertDAO) IgnoreSSLCertsWithOCSPError(tx *dbs.Tx, certIds []int64) error {
|
||||||
|
for _, certId := range certIds {
|
||||||
|
err := this.Query(tx).
|
||||||
|
Pk(certId).
|
||||||
|
Set("ocspError", "").
|
||||||
|
UpdateQuickly()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetSSLCertsWithOCSPError 重置一组证书OCSP错误状态
|
||||||
|
func (this *SSLCertDAO) ResetSSLCertsWithOCSPError(tx *dbs.Tx, certIds []int64) error {
|
||||||
|
for _, certId := range certIds {
|
||||||
|
err := this.Query(tx).
|
||||||
|
Pk(certId).
|
||||||
|
Set("ocspIsUpdated", 0).
|
||||||
|
Set("ocspUpdatedAt", 0).
|
||||||
|
Set("ocspError", "").
|
||||||
|
Set("ocspTries", 0).
|
||||||
|
UpdateQuickly()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetAllSSLCertsWithOCSPError 重置所有证书OCSP错误状态
|
||||||
|
func (this *SSLCertDAO) ResetAllSSLCertsWithOCSPError(tx *dbs.Tx) error {
|
||||||
|
return this.Query(tx).
|
||||||
|
State(SSLCertStateEnabled).
|
||||||
|
Attr("ocspIsUpdated", 1).
|
||||||
|
Where("LENGTH(ocspError)>0").
|
||||||
|
Set("ocspIsUpdated", 0).
|
||||||
|
Set("ocspUpdatedAt", 0).
|
||||||
|
Set("ocspError", "").
|
||||||
|
Set("ocspTries", 0).
|
||||||
|
UpdateQuickly()
|
||||||
|
}
|
||||||
|
|
||||||
// NotifyUpdate 通知更新
|
// NotifyUpdate 通知更新
|
||||||
func (this *SSLCertDAO) NotifyUpdate(tx *dbs.Tx, certId int64) error {
|
func (this *SSLCertDAO) NotifyUpdate(tx *dbs.Tx, certId int64) error {
|
||||||
policyIds, err := SharedSSLPolicyDAO.FindAllEnabledPolicyIdsWithCertId(tx, certId)
|
policyIds, err := SharedSSLPolicyDAO.FindAllEnabledPolicyIdsWithCertId(tx, certId)
|
||||||
|
|||||||
@@ -1,5 +1,19 @@
|
|||||||
package models
|
package models_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestSSLCertDAO_ListCertsToUpdateOCSP(t *testing.T) {
|
||||||
|
var dao = models.NewSSLCertDAO()
|
||||||
|
certs, err := dao.ListCertsToUpdateOCSP(nil, 3600, 10)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, cert := range certs {
|
||||||
|
t.Log(cert.Id, cert.Name, "updatedAt:", cert.OcspUpdatedAt, timeutil.FormatTime("Y-m-d H:i:s", int64(cert.OcspUpdatedAt)), cert.OcspIsUpdated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,52 +1,66 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
// SSL证书
|
// SSLCert SSL证书
|
||||||
type SSLCert struct {
|
type SSLCert struct {
|
||||||
Id uint32 `field:"id"` // ID
|
Id uint32 `field:"id"` // ID
|
||||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||||
UserId uint32 `field:"userId"` // 用户ID
|
UserId uint32 `field:"userId"` // 用户ID
|
||||||
State uint8 `field:"state"` // 状态
|
State uint8 `field:"state"` // 状态
|
||||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||||
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
|
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
|
||||||
IsOn uint8 `field:"isOn"` // 是否启用
|
IsOn uint8 `field:"isOn"` // 是否启用
|
||||||
Name string `field:"name"` // 证书名
|
Name string `field:"name"` // 证书名
|
||||||
Description string `field:"description"` // 描述
|
Description string `field:"description"` // 描述
|
||||||
CertData string `field:"certData"` // 证书内容
|
CertData string `field:"certData"` // 证书内容
|
||||||
KeyData string `field:"keyData"` // 密钥内容
|
KeyData string `field:"keyData"` // 密钥内容
|
||||||
ServerName string `field:"serverName"` // 证书使用的主机名
|
ServerName string `field:"serverName"` // 证书使用的主机名
|
||||||
IsCA uint8 `field:"isCA"` // 是否为CA证书
|
IsCA uint8 `field:"isCA"` // 是否为CA证书
|
||||||
GroupIds string `field:"groupIds"` // 证书分组
|
GroupIds string `field:"groupIds"` // 证书分组
|
||||||
TimeBeginAt uint64 `field:"timeBeginAt"` // 开始时间
|
TimeBeginAt uint64 `field:"timeBeginAt"` // 开始时间
|
||||||
TimeEndAt uint64 `field:"timeEndAt"` // 结束时间
|
TimeEndAt uint64 `field:"timeEndAt"` // 结束时间
|
||||||
DnsNames string `field:"dnsNames"` // DNS名称列表
|
DnsNames string `field:"dnsNames"` // DNS名称列表
|
||||||
CommonNames string `field:"commonNames"` // 发行单位列表
|
CommonNames string `field:"commonNames"` // 发行单位列表
|
||||||
IsACME uint8 `field:"isACME"` // 是否为ACME自动生成的
|
IsACME uint8 `field:"isACME"` // 是否为ACME自动生成的
|
||||||
AcmeTaskId uint64 `field:"acmeTaskId"` // ACME任务ID
|
AcmeTaskId uint64 `field:"acmeTaskId"` // ACME任务ID
|
||||||
NotifiedAt uint64 `field:"notifiedAt"` // 最后通知时间
|
NotifiedAt uint64 `field:"notifiedAt"` // 最后通知时间
|
||||||
|
Ocsp string `field:"ocsp"` // OCSP缓存
|
||||||
|
OcspIsUpdated uint8 `field:"ocspIsUpdated"` // OCSP是否已更新
|
||||||
|
OcspUpdatedAt uint64 `field:"ocspUpdatedAt"` // OCSP更新时间
|
||||||
|
OcspError string `field:"ocspError"` // OCSP更新错误
|
||||||
|
OcspUpdatedVersion uint64 `field:"ocspUpdatedVersion"` // OCSP更新版本
|
||||||
|
OcspExpiresAt uint64 `field:"ocspExpiresAt"` // OCSP过期时间(UTC)
|
||||||
|
OcspTries uint32 `field:"ocspTries"` // OCSP尝试次数
|
||||||
}
|
}
|
||||||
|
|
||||||
type SSLCertOperator struct {
|
type SSLCertOperator struct {
|
||||||
Id interface{} // ID
|
Id interface{} // ID
|
||||||
AdminId interface{} // 管理员ID
|
AdminId interface{} // 管理员ID
|
||||||
UserId interface{} // 用户ID
|
UserId interface{} // 用户ID
|
||||||
State interface{} // 状态
|
State interface{} // 状态
|
||||||
CreatedAt interface{} // 创建时间
|
CreatedAt interface{} // 创建时间
|
||||||
UpdatedAt interface{} // 修改时间
|
UpdatedAt interface{} // 修改时间
|
||||||
IsOn interface{} // 是否启用
|
IsOn interface{} // 是否启用
|
||||||
Name interface{} // 证书名
|
Name interface{} // 证书名
|
||||||
Description interface{} // 描述
|
Description interface{} // 描述
|
||||||
CertData interface{} // 证书内容
|
CertData interface{} // 证书内容
|
||||||
KeyData interface{} // 密钥内容
|
KeyData interface{} // 密钥内容
|
||||||
ServerName interface{} // 证书使用的主机名
|
ServerName interface{} // 证书使用的主机名
|
||||||
IsCA interface{} // 是否为CA证书
|
IsCA interface{} // 是否为CA证书
|
||||||
GroupIds interface{} // 证书分组
|
GroupIds interface{} // 证书分组
|
||||||
TimeBeginAt interface{} // 开始时间
|
TimeBeginAt interface{} // 开始时间
|
||||||
TimeEndAt interface{} // 结束时间
|
TimeEndAt interface{} // 结束时间
|
||||||
DnsNames interface{} // DNS名称列表
|
DnsNames interface{} // DNS名称列表
|
||||||
CommonNames interface{} // 发行单位列表
|
CommonNames interface{} // 发行单位列表
|
||||||
IsACME interface{} // 是否为ACME自动生成的
|
IsACME interface{} // 是否为ACME自动生成的
|
||||||
AcmeTaskId interface{} // ACME任务ID
|
AcmeTaskId interface{} // ACME任务ID
|
||||||
NotifiedAt interface{} // 最后通知时间
|
NotifiedAt interface{} // 最后通知时间
|
||||||
|
Ocsp interface{} // OCSP缓存
|
||||||
|
OcspIsUpdated interface{} // OCSP是否已更新
|
||||||
|
OcspUpdatedAt interface{} // OCSP更新时间
|
||||||
|
OcspError interface{} // OCSP更新错误
|
||||||
|
OcspUpdatedVersion interface{} // OCSP更新版本
|
||||||
|
OcspExpiresAt interface{} // OCSP过期时间(UTC)
|
||||||
|
OcspTries interface{} // OCSP尝试次数
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSSLCertOperator() *SSLCertOperator {
|
func NewSSLCertOperator() *SSLCertOperator {
|
||||||
|
|||||||
@@ -1 +1,31 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
func (this *SSLCert) DecodeDNSNames() []string {
|
||||||
|
if len(this.DnsNames) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = []string{}
|
||||||
|
var err = json.Unmarshal([]byte(this.DnsNames), &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *SSLCert) DecodeCommonNames() []string {
|
||||||
|
if len(this.CommonNames) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = []string{}
|
||||||
|
var err = json.Unmarshal([]byte(this.CommonNames), &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@@ -167,6 +167,9 @@ func (this *SSLPolicyDAO) ComposePolicyConfig(tx *dbs.Tx, policyId int64, cacheM
|
|||||||
config.HSTS = hstsConfig
|
config.HSTS = hstsConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ocsp
|
||||||
|
config.OCSPIsOn = policy.OcspIsOn == 1
|
||||||
|
|
||||||
if cacheMap != nil {
|
if cacheMap != nil {
|
||||||
cacheMap.Put(cacheKey, config)
|
cacheMap.Put(cacheKey, config)
|
||||||
}
|
}
|
||||||
@@ -196,7 +199,7 @@ func (this *SSLPolicyDAO) FindAllEnabledPolicyIdsWithCertId(tx *dbs.Tx, certId i
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreatePolicy 创建Policy
|
// CreatePolicy 创建Policy
|
||||||
func (this *SSLPolicyDAO) CreatePolicy(tx *dbs.Tx, adminId int64, userId int64, http2Enabled bool, minVersion string, certsJSON []byte, hstsJSON []byte, clientAuthType int32, clientCACertsJSON []byte, cipherSuitesIsOn bool, cipherSuites []string) (int64, error) {
|
func (this *SSLPolicyDAO) CreatePolicy(tx *dbs.Tx, adminId int64, userId int64, http2Enabled bool, minVersion string, certsJSON []byte, hstsJSON []byte, ocspIsOn bool, clientAuthType int32, clientCACertsJSON []byte, cipherSuitesIsOn bool, cipherSuites []string) (int64, error) {
|
||||||
op := NewSSLPolicyOperator()
|
op := NewSSLPolicyOperator()
|
||||||
op.State = SSLPolicyStateEnabled
|
op.State = SSLPolicyStateEnabled
|
||||||
op.IsOn = true
|
op.IsOn = true
|
||||||
@@ -213,6 +216,8 @@ func (this *SSLPolicyDAO) CreatePolicy(tx *dbs.Tx, adminId int64, userId int64,
|
|||||||
op.Hsts = hstsJSON
|
op.Hsts = hstsJSON
|
||||||
}
|
}
|
||||||
|
|
||||||
|
op.OcspIsOn = ocspIsOn
|
||||||
|
|
||||||
op.ClientAuthType = clientAuthType
|
op.ClientAuthType = clientAuthType
|
||||||
if len(clientCACertsJSON) > 0 {
|
if len(clientCACertsJSON) > 0 {
|
||||||
op.ClientCACerts = clientCACertsJSON
|
op.ClientCACerts = clientCACertsJSON
|
||||||
@@ -234,7 +239,7 @@ func (this *SSLPolicyDAO) CreatePolicy(tx *dbs.Tx, adminId int64, userId int64,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdatePolicy 修改Policy
|
// UpdatePolicy 修改Policy
|
||||||
func (this *SSLPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, http2Enabled bool, minVersion string, certsJSON []byte, hstsJSON []byte, clientAuthType int32, clientCACertsJSON []byte, cipherSuitesIsOn bool, cipherSuites []string) error {
|
func (this *SSLPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, http2Enabled bool, minVersion string, certsJSON []byte, hstsJSON []byte, ocspIsOn bool, clientAuthType int32, clientCACertsJSON []byte, cipherSuitesIsOn bool, cipherSuites []string) error {
|
||||||
if policyId <= 0 {
|
if policyId <= 0 {
|
||||||
return errors.New("invalid policyId")
|
return errors.New("invalid policyId")
|
||||||
}
|
}
|
||||||
@@ -251,6 +256,8 @@ func (this *SSLPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, http2Enabled
|
|||||||
op.Hsts = hstsJSON
|
op.Hsts = hstsJSON
|
||||||
}
|
}
|
||||||
|
|
||||||
|
op.OcspIsOn = ocspIsOn
|
||||||
|
|
||||||
op.ClientAuthType = clientAuthType
|
op.ClientAuthType = clientAuthType
|
||||||
if len(clientCACertsJSON) > 0 {
|
if len(clientCACertsJSON) > 0 {
|
||||||
op.ClientCACerts = clientCACertsJSON
|
op.ClientCACerts = clientCACertsJSON
|
||||||
@@ -274,9 +281,9 @@ func (this *SSLPolicyDAO) UpdatePolicy(tx *dbs.Tx, policyId int64, http2Enabled
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CheckUserPolicy 检查是否为用户所属策略
|
// CheckUserPolicy 检查是否为用户所属策略
|
||||||
func (this *SSLPolicyDAO) CheckUserPolicy(tx *dbs.Tx, policyId int64, userId int64) error {
|
func (this *SSLPolicyDAO) CheckUserPolicy(tx *dbs.Tx, userId int64, policyId int64) error {
|
||||||
if policyId <= 0 || userId <= 0 {
|
if policyId <= 0 || userId <= 0 {
|
||||||
return errors.New("not found")
|
return ErrNotFound
|
||||||
}
|
}
|
||||||
ok, err := this.Query(tx).
|
ok, err := this.Query(tx).
|
||||||
State(SSLPolicyStateEnabled).
|
State(SSLPolicyStateEnabled).
|
||||||
@@ -287,7 +294,14 @@ func (this *SSLPolicyDAO) CheckUserPolicy(tx *dbs.Tx, policyId int64, userId int
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("not found")
|
// 是否为当前用户的某个服务所用
|
||||||
|
exists, err := SharedServerDAO.ExistEnabledUserServerWithSSLPolicyId(tx, userId, policyId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !exists {
|
||||||
|
return ErrNotFound
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
//
|
// SSLPolicy SSL配置策略
|
||||||
type SSLPolicy struct {
|
type SSLPolicy struct {
|
||||||
Id uint32 `field:"id"` // ID
|
Id uint32 `field:"id"` // ID
|
||||||
AdminId uint32 `field:"adminId"` // 管理员ID
|
AdminId uint32 `field:"adminId"` // 管理员ID
|
||||||
@@ -14,6 +14,7 @@ type SSLPolicy struct {
|
|||||||
CipherSuites string `field:"cipherSuites"` // 加密算法套件
|
CipherSuites string `field:"cipherSuites"` // 加密算法套件
|
||||||
Hsts string `field:"hsts"` // HSTS设置
|
Hsts string `field:"hsts"` // HSTS设置
|
||||||
Http2Enabled uint8 `field:"http2Enabled"` // 是否启用HTTP/2
|
Http2Enabled uint8 `field:"http2Enabled"` // 是否启用HTTP/2
|
||||||
|
OcspIsOn uint8 `field:"ocspIsOn"` // 是否启用OCSP
|
||||||
State uint8 `field:"state"` // 状态
|
State uint8 `field:"state"` // 状态
|
||||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||||
}
|
}
|
||||||
@@ -31,6 +32,7 @@ type SSLPolicyOperator struct {
|
|||||||
CipherSuites interface{} // 加密算法套件
|
CipherSuites interface{} // 加密算法套件
|
||||||
Hsts interface{} // HSTS设置
|
Hsts interface{} // HSTS设置
|
||||||
Http2Enabled interface{} // 是否启用HTTP/2
|
Http2Enabled interface{} // 是否启用HTTP/2
|
||||||
|
OcspIsOn interface{} // 是否启用OCSP
|
||||||
State interface{} // 状态
|
State interface{} // 状态
|
||||||
CreatedAt interface{} // 创建时间
|
CreatedAt interface{} // 创建时间
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func init() {
|
|||||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||||
goman.New(func() {
|
goman.New(func() {
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
err := SharedServerDomainHourlyStatDAO.Clean(nil, 7) // 只保留7天
|
err := SharedServerDomainHourlyStatDAO.Clean(nil, 7) // 只保留 N 天
|
||||||
if err != nil {
|
if err != nil {
|
||||||
remotelogs.Error("ServerDomainHourlyStatDAO", "clean expired data failed: "+err.Error())
|
remotelogs.Error("ServerDomainHourlyStatDAO", "clean expired data failed: "+err.Error())
|
||||||
}
|
}
|
||||||
@@ -374,7 +374,9 @@ func (this *ServerDomainHourlyStatDAO) Clean(tx *dbs.Tx, days int) error {
|
|||||||
Table(table).
|
Table(table).
|
||||||
Lt("hour", hour).
|
Lt("hour", hour).
|
||||||
Delete()
|
Delete()
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,10 +109,13 @@ func (this *ServerHTTPFirewallDailyStatDAO) GroupDailyCount(tx *dbs.Tx, userId i
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FindDailyStats 查询某个日期段内的记录
|
// FindDailyStats 查询某个日期段内的记录
|
||||||
func (this *ServerHTTPFirewallDailyStatDAO) FindDailyStats(tx *dbs.Tx, userId int64, serverId int64, action string, dayFrom string, dayTo string) (result []*ServerHTTPFirewallDailyStat, err error) {
|
func (this *ServerHTTPFirewallDailyStatDAO) FindDailyStats(tx *dbs.Tx, userId int64, serverId int64, actions []string, dayFrom string, dayTo string) (result []*ServerHTTPFirewallDailyStat, err error) {
|
||||||
|
if len(actions) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
query := this.Query(tx).
|
query := this.Query(tx).
|
||||||
Between("day", dayFrom, dayTo).
|
Between("day", dayFrom, dayTo).
|
||||||
Attr("action", action)
|
Attr("action", actions)
|
||||||
if serverId > 0 {
|
if serverId > 0 {
|
||||||
query.Attr("serverId", serverId)
|
query.Attr("serverId", serverId)
|
||||||
} else if userId > 0 {
|
} else if userId > 0 {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func init() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开锁
|
// Lock 开锁
|
||||||
func (this *SysLockerDAO) Lock(tx *dbs.Tx, key string, timeout int64) (ok bool, err error) {
|
func (this *SysLockerDAO) Lock(tx *dbs.Tx, key string, timeout int64) (ok bool, err error) {
|
||||||
maxErrors := 5
|
maxErrors := 5
|
||||||
for {
|
for {
|
||||||
@@ -103,7 +103,7 @@ func (this *SysLockerDAO) Lock(tx *dbs.Tx, key string, timeout int64) (ok bool,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解锁
|
// Unlock 解锁
|
||||||
func (this *SysLockerDAO) Unlock(tx *dbs.Tx, key string) error {
|
func (this *SysLockerDAO) Unlock(tx *dbs.Tx, key string) error {
|
||||||
_, err := this.Query(tx).
|
_, err := this.Query(tx).
|
||||||
Attr("key", key).
|
Attr("key", key).
|
||||||
@@ -112,7 +112,7 @@ func (this *SysLockerDAO) Unlock(tx *dbs.Tx, key string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 增加版本号
|
// Increase 增加版本号
|
||||||
func (this *SysLockerDAO) Increase(tx *dbs.Tx, key string, defaultValue int64) (int64, error) {
|
func (this *SysLockerDAO) Increase(tx *dbs.Tx, key string, defaultValue int64) (int64, error) {
|
||||||
if tx == nil {
|
if tx == nil {
|
||||||
var result int64
|
var result int64
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/zero"
|
"github.com/TeaOSLab/EdgeAPI/internal/zero"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
"github.com/iwind/TeaGo/dbs"
|
"github.com/iwind/TeaGo/dbs"
|
||||||
@@ -138,6 +140,72 @@ func (this *SysSettingDAO) ReadGlobalConfig(tx *dbs.Tx) (*serverconfigs.GlobalCo
|
|||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadUserServerConfig 读取用户服务配置
|
||||||
|
func (this *SysSettingDAO) ReadUserServerConfig(tx *dbs.Tx) (*userconfigs.UserServerConfig, error) {
|
||||||
|
valueJSON, err := this.ReadSetting(tx, systemconfigs.SettingCodeUserServerConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(valueJSON) == 0 {
|
||||||
|
return userconfigs.DefaultUserServerConfig(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = userconfigs.DefaultUserServerConfig()
|
||||||
|
err = json.Unmarshal(valueJSON, config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadUserFinanceConfig 读取用户服务配置
|
||||||
|
func (this *SysSettingDAO) ReadUserFinanceConfig(tx *dbs.Tx) (*userconfigs.UserFinanceConfig, error) {
|
||||||
|
valueJSON, err := this.ReadSetting(tx, systemconfigs.SettingCodeUserFinanceConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(valueJSON) == 0 {
|
||||||
|
return userconfigs.DefaultUserFinanceConfig(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = userconfigs.DefaultUserFinanceConfig()
|
||||||
|
err = json.Unmarshal(valueJSON, config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadAdminUIConfig 读取管理员界面配置
|
||||||
|
func (this *SysSettingDAO) ReadAdminUIConfig(tx *dbs.Tx, cacheMap *utils.CacheMap) (*systemconfigs.AdminUIConfig, error) {
|
||||||
|
var cacheKey = this.Table + ":ReadAdminUIConfig"
|
||||||
|
if cacheMap != nil {
|
||||||
|
cache, ok := cacheMap.Get(cacheKey)
|
||||||
|
if ok && cache != nil {
|
||||||
|
return cache.(*systemconfigs.AdminUIConfig), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
valueJSON, err := this.ReadSetting(tx, systemconfigs.SettingCodeAdminUIConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(valueJSON) > 0 {
|
||||||
|
var config = &systemconfigs.AdminUIConfig{}
|
||||||
|
err = json.Unmarshal(valueJSON, config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if cacheMap != nil {
|
||||||
|
cacheMap.Put(cacheKey, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
return &systemconfigs.AdminUIConfig{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// NotifyUpdate 通知更改
|
// NotifyUpdate 通知更改
|
||||||
func (this *SysSettingDAO) NotifyUpdate(tx *dbs.Tx, code string) error {
|
func (this *SysSettingDAO) NotifyUpdate(tx *dbs.Tx, code string) error {
|
||||||
switch code {
|
switch code {
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/numberutils"
|
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
@@ -23,7 +22,7 @@ func init() {
|
|||||||
|
|
||||||
goman.New(func() {
|
goman.New(func() {
|
||||||
// 自动生成账单任务
|
// 自动生成账单任务
|
||||||
var ticker = time.NewTicker(1 * time.Minute)
|
var ticker = time.NewTicker(1 * time.Hour)
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
// 是否已经生成了,如果已经生成了就跳过
|
// 是否已经生成了,如果已经生成了就跳过
|
||||||
var lastMonth = timeutil.Format("Ym", time.Now().AddDate(0, -1, 0))
|
var lastMonth = timeutil.Format("Ym", time.Now().AddDate(0, -1, 0))
|
||||||
@@ -136,7 +135,7 @@ func (this *UserBillDAO) FindUnpaidBills(tx *dbs.Tx, size int64) (result []*User
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateBill 创建账单
|
// CreateBill 创建账单
|
||||||
func (this *UserBillDAO) CreateBill(tx *dbs.Tx, userId int64, billType BillType, description string, amount float32, month string) error {
|
func (this *UserBillDAO) CreateBill(tx *dbs.Tx, userId int64, billType BillType, description string, amount float64, month string, canPay bool) error {
|
||||||
code, err := this.GenerateBillCode(tx)
|
code, err := this.GenerateBillCode(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -149,9 +148,11 @@ func (this *UserBillDAO) CreateBill(tx *dbs.Tx, userId int64, billType BillType,
|
|||||||
"amount": amount,
|
"amount": amount,
|
||||||
"month": month,
|
"month": month,
|
||||||
"code": code,
|
"code": code,
|
||||||
"isPaid": false,
|
"isPaid": amount == 0,
|
||||||
|
"canPay": canPay,
|
||||||
}, maps.Map{
|
}, maps.Map{
|
||||||
"amount": amount,
|
"amount": amount,
|
||||||
|
"canPay": canPay,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,19 +173,22 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(regions) == 0 {
|
|
||||||
return nil
|
var priceItems []*NodePriceItem
|
||||||
|
if len(regions) > 0 {
|
||||||
|
priceItems, err = SharedNodePriceItemDAO.FindAllEnabledRegionPrices(tx, NodePriceTypeTraffic)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priceItems, err := SharedNodePriceItemDAO.FindAllEnabledRegionPrices(tx, NodePriceTypeTraffic)
|
// 默认计费方式
|
||||||
|
userFinanceConfig, err := SharedSysSettingDAO.ReadUserFinanceConfig(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(priceItems) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算套餐费用
|
// 计算服务套餐费用
|
||||||
plans, err := SharedPlanDAO.FindAllEnabledPlans(tx)
|
plans, err := SharedPlanDAO.FindAllEnabledPlans(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -194,54 +198,220 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error {
|
|||||||
planMap[int64(plan.Id)] = plan
|
planMap[int64(plan.Id)] = plan
|
||||||
}
|
}
|
||||||
|
|
||||||
stats, err := SharedServerDailyStatDAO.FindMonthlyStatsWithPlan(tx, month)
|
var dayFrom = month + "01"
|
||||||
|
var dayTo = month + "32"
|
||||||
|
serverIds, err := SharedServerDailyStatDAO.FindDistinctServerIds(tx, dayFrom, dayTo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, stat := range stats {
|
var cacheMap = utils.NewCacheMap()
|
||||||
plan, ok := planMap[int64(stat.PlanId)]
|
var userIds = []int64{}
|
||||||
if !ok {
|
for _, serverId := range serverIds {
|
||||||
continue
|
// 套餐类型
|
||||||
}
|
userPlanId, userId, err := SharedServerDAO.FindServerLastUserPlanIdAndUserId(tx, serverId)
|
||||||
if plan.PriceType != serverconfigs.PlanPriceTypeTraffic {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if len(plan.TrafficPrice) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var priceConfig = &serverconfigs.PlanTrafficPrice{}
|
|
||||||
err = json.Unmarshal([]byte(plan.TrafficPrice), priceConfig)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if priceConfig.Base > 0 {
|
if userId == 0 {
|
||||||
var fee = priceConfig.Base * (float32(stat.Bytes) / 1024 / 1024 / 1024)
|
continue
|
||||||
err = SharedServerDailyStatDAO.UpdateStatFee(tx, int64(stat.Id), fee)
|
}
|
||||||
|
|
||||||
|
userIds = append(userIds, userId)
|
||||||
|
if userPlanId == 0 {
|
||||||
|
// 总流量
|
||||||
|
totalTrafficBytes, err := SharedServerDailyStatDAO.SumMonthlyBytes(tx, serverId, month)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 默认计费方式
|
||||||
|
if userFinanceConfig != nil && userFinanceConfig.IsOn { // 默认计费方式
|
||||||
|
switch userFinanceConfig.PriceType {
|
||||||
|
case serverconfigs.PlanPriceTypeTraffic:
|
||||||
|
var config = userFinanceConfig.TrafficPriceConfig
|
||||||
|
var fee float64 = 0
|
||||||
|
if config != nil && config.Base > 0 {
|
||||||
|
fee = float64(totalTrafficBytes) / 1024 / 1024 / 1024 * float64(config.Base)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 百分位
|
||||||
|
var percentile = 95
|
||||||
|
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, userId, serverId, month, userPlanId, 0, totalTrafficBytes, percentileBytes, percentile, userFinanceConfig.PriceType, fee)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case serverconfigs.PlanPriceTypeBandwidth:
|
||||||
|
// 百分位
|
||||||
|
var percentile = 95
|
||||||
|
var config = userFinanceConfig.BandwidthPriceConfig
|
||||||
|
if config != nil {
|
||||||
|
percentile = config.Percentile
|
||||||
|
if percentile <= 0 {
|
||||||
|
percentile = 95
|
||||||
|
} else if percentile > 100 {
|
||||||
|
percentile = 100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var mb = float32(percentileBytes) / 1024 / 1024
|
||||||
|
var price float32
|
||||||
|
if config != nil {
|
||||||
|
price = config.LookupPrice(mb)
|
||||||
|
}
|
||||||
|
var fee = float64(price)
|
||||||
|
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, userId, serverId, month, userPlanId, 0, totalTrafficBytes, percentileBytes, percentile, userFinanceConfig.PriceType, fee)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // 区域流量计费
|
||||||
|
var fee float64
|
||||||
|
|
||||||
|
for _, region := range regions {
|
||||||
|
var regionId = int64(region.Id)
|
||||||
|
var pricesMap = region.DecodePriceMap()
|
||||||
|
if len(pricesMap) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
trafficBytes, err := SharedServerDailyStatDAO.SumServerMonthlyWithRegion(tx, serverId, regionId, month)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if trafficBytes == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var itemId = SharedNodePriceItemDAO.SearchItemsWithBytes(priceItems, trafficBytes)
|
||||||
|
if itemId == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
price, ok := pricesMap[itemId]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if price <= 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var regionFee = float64(trafficBytes) / 1000 / 1000 / 1000 * 8 * price
|
||||||
|
fee += regionFee
|
||||||
|
}
|
||||||
|
|
||||||
|
// 百分位
|
||||||
|
var percentile = 95
|
||||||
|
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, userId, serverId, month, userPlanId, 0, totalTrafficBytes, percentileBytes, percentile, "", fee)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
userPlan, err := SharedUserPlanDAO.FindUserPlanWithoutState(tx, userPlanId, cacheMap)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if userPlan == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
plan, ok := planMap[int64(userPlan.PlanId)]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 总流量
|
||||||
|
totalTrafficBytes, err := SharedServerDailyStatDAO.SumMonthlyBytes(tx, serverId, month)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch plan.PriceType {
|
||||||
|
case serverconfigs.PlanPriceTypePeriod:
|
||||||
|
// 已经在购买套餐的时候付过费,这里不再重复计费
|
||||||
|
var fee float64 = 0
|
||||||
|
|
||||||
|
// 百分位
|
||||||
|
var percentile = 95
|
||||||
|
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, int64(userPlan.UserId), serverId, month, userPlanId, int64(userPlan.PlanId), totalTrafficBytes, percentileBytes, percentile, plan.PriceType, fee)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case serverconfigs.PlanPriceTypeTraffic:
|
||||||
|
var config = plan.DecodeTrafficPrice()
|
||||||
|
var fee float64 = 0
|
||||||
|
if config != nil && config.Base > 0 {
|
||||||
|
fee = float64(totalTrafficBytes) / 1024 / 1024 / 1024 * float64(config.Base)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 百分位
|
||||||
|
var percentile = 95
|
||||||
|
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, int64(userPlan.UserId), serverId, month, userPlanId, int64(userPlan.PlanId), totalTrafficBytes, percentileBytes, percentile, plan.PriceType, fee)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case serverconfigs.PlanPriceTypeBandwidth:
|
||||||
|
// 百分位
|
||||||
|
var percentile = 95
|
||||||
|
var config = plan.DecodeBandwidthPrice()
|
||||||
|
if config != nil {
|
||||||
|
percentile = config.Percentile
|
||||||
|
if percentile <= 0 {
|
||||||
|
percentile = 95
|
||||||
|
} else if percentile > 100 {
|
||||||
|
percentile = 100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var mb = float32(percentileBytes) / 1024 / 1024
|
||||||
|
var price float32
|
||||||
|
if config != nil {
|
||||||
|
price = config.LookupPrice(mb)
|
||||||
|
}
|
||||||
|
var fee = float64(price)
|
||||||
|
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, int64(userPlan.UserId), serverId, month, userPlanId, int64(userPlan.PlanId), totalTrafficBytes, percentileBytes, percentile, plan.PriceType, fee)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用户
|
// 计算用户费用
|
||||||
offset := int64(0)
|
for _, userId := range userIds {
|
||||||
size := int64(100) // 每次只查询N次,防止由于执行时间过长而锁表
|
if userId == 0 {
|
||||||
for {
|
continue
|
||||||
userIds, err := SharedUserDAO.ListEnabledUserIds(tx, offset, size)
|
}
|
||||||
|
amount, err := SharedServerBillDAO.SumUserMonthlyAmount(tx, userId, month)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
offset += size
|
err = SharedUserBillDAO.CreateBill(tx, userId, BillTypeTraffic, "流量带宽费用", amount, month, month < timeutil.Format("Ym"))
|
||||||
if len(userIds) == 0 {
|
if err != nil {
|
||||||
break
|
return err
|
||||||
}
|
|
||||||
|
|
||||||
for _, userId := range userIds {
|
|
||||||
// CDN流量账单
|
|
||||||
err := this.generateTrafficBill(tx, userId, month, regions, priceItems)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,74 +426,11 @@ func (this *UserBillDAO) UpdateUserBillIsPaid(tx *dbs.Tx, billId int64, isPaid b
|
|||||||
UpdateQuickly()
|
UpdateQuickly()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成CDN流量账单
|
|
||||||
// month 格式YYYYMM
|
|
||||||
func (this *UserBillDAO) generateTrafficBill(tx *dbs.Tx, userId int64, month string, regions []*NodeRegion, priceItems []*NodePriceItem) error {
|
|
||||||
// 检查是否已经有账单了
|
|
||||||
if month < timeutil.Format("Ym") {
|
|
||||||
b, err := this.ExistBill(tx, userId, BillTypeTraffic, month)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if b {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var cost = float32(0)
|
|
||||||
for _, region := range regions {
|
|
||||||
if len(region.Prices) == 0 || region.Prices == "null" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
priceMap := map[string]float32{}
|
|
||||||
err := json.Unmarshal([]byte(region.Prices), &priceMap)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
trafficBytes, err := SharedServerDailyStatDAO.SumUserMonthlyWithoutPlan(tx, userId, int64(region.Id), month)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if trafficBytes == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
itemId := SharedNodePriceItemDAO.SearchItemsWithBytes(priceItems, trafficBytes)
|
|
||||||
if itemId == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
price, ok := priceMap[numberutils.FormatInt64(itemId)]
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算钱
|
|
||||||
// 这里采用1000进制
|
|
||||||
cost += (float32(trafficBytes*8) / 1_000_000_000) * price
|
|
||||||
}
|
|
||||||
|
|
||||||
// 套餐费用
|
|
||||||
planFee, err := SharedServerDailyStatDAO.SumUserMonthlyFee(tx, userId, month)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
cost += float32(planFee)
|
|
||||||
|
|
||||||
if cost == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建账单
|
|
||||||
return this.CreateBill(tx, userId, BillTypeTraffic, "按流量计费", cost, month)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BillTypeName 获取账单类型名称
|
// BillTypeName 获取账单类型名称
|
||||||
func (this *UserBillDAO) BillTypeName(billType BillType) string {
|
func (this *UserBillDAO) BillTypeName(billType BillType) string {
|
||||||
switch billType {
|
switch billType {
|
||||||
case BillTypeTraffic:
|
case BillTypeTraffic:
|
||||||
return "流量"
|
return "流量带宽"
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,10 @@ type UserBill struct {
|
|||||||
Type string `field:"type"` // 消费类型
|
Type string `field:"type"` // 消费类型
|
||||||
Description string `field:"description"` // 描述
|
Description string `field:"description"` // 描述
|
||||||
Amount float64 `field:"amount"` // 消费数额
|
Amount float64 `field:"amount"` // 消费数额
|
||||||
|
DayFrom string `field:"dayFrom"` // YYYYMMDD
|
||||||
|
DayTo string `field:"dayTo"` // YYYYMMDD
|
||||||
Month string `field:"month"` // 帐期YYYYMM
|
Month string `field:"month"` // 帐期YYYYMM
|
||||||
|
CanPay uint8 `field:"canPay"` // 是否可以支付
|
||||||
IsPaid uint8 `field:"isPaid"` // 是否已支付
|
IsPaid uint8 `field:"isPaid"` // 是否已支付
|
||||||
PaidAt uint64 `field:"paidAt"` // 支付时间
|
PaidAt uint64 `field:"paidAt"` // 支付时间
|
||||||
Code string `field:"code"` // 账单编号
|
Code string `field:"code"` // 账单编号
|
||||||
@@ -20,7 +23,10 @@ type UserBillOperator struct {
|
|||||||
Type interface{} // 消费类型
|
Type interface{} // 消费类型
|
||||||
Description interface{} // 描述
|
Description interface{} // 描述
|
||||||
Amount interface{} // 消费数额
|
Amount interface{} // 消费数额
|
||||||
|
DayFrom interface{} // YYYYMMDD
|
||||||
|
DayTo interface{} // YYYYMMDD
|
||||||
Month interface{} // 帐期YYYYMM
|
Month interface{} // 帐期YYYYMM
|
||||||
|
CanPay interface{} // 是否可以支付
|
||||||
IsPaid interface{} // 是否已支付
|
IsPaid interface{} // 是否已支付
|
||||||
PaidAt interface{} // 支付时间
|
PaidAt interface{} // 支付时间
|
||||||
Code interface{} // 账单编号
|
Code interface{} // 账单编号
|
||||||
|
|||||||
@@ -95,6 +95,18 @@ func (this *UserDAO) FindEnabledBasicUser(tx *dbs.Tx, id int64) (*User, error) {
|
|||||||
return result.(*User), err
|
return result.(*User), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindBasicUserWithoutState 查找用户基本信息,并忽略状态
|
||||||
|
func (this *UserDAO) FindBasicUserWithoutState(tx *dbs.Tx, id int64) (*User, error) {
|
||||||
|
result, err := this.Query(tx).
|
||||||
|
Pk(id).
|
||||||
|
Result("id", "fullname", "username").
|
||||||
|
Find()
|
||||||
|
if result == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result.(*User), err
|
||||||
|
}
|
||||||
|
|
||||||
// FindUserFullname 获取管理员名称
|
// FindUserFullname 获取管理员名称
|
||||||
func (this *UserDAO) FindUserFullname(tx *dbs.Tx, userId int64) (string, error) {
|
func (this *UserDAO) FindUserFullname(tx *dbs.Tx, userId int64) (string, error) {
|
||||||
return this.Query(tx).
|
return this.Query(tx).
|
||||||
@@ -104,7 +116,18 @@ func (this *UserDAO) FindUserFullname(tx *dbs.Tx, userId int64) (string, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateUser 创建用户
|
// CreateUser 创建用户
|
||||||
func (this *UserDAO) CreateUser(tx *dbs.Tx, username string, password string, fullname string, mobile string, tel string, email string, remark string, source string, clusterId int64) (int64, error) {
|
func (this *UserDAO) CreateUser(tx *dbs.Tx, username string,
|
||||||
|
password string,
|
||||||
|
fullname string,
|
||||||
|
mobile string,
|
||||||
|
tel string,
|
||||||
|
email string,
|
||||||
|
remark string,
|
||||||
|
source string,
|
||||||
|
clusterId int64,
|
||||||
|
features []string,
|
||||||
|
registeredIP string,
|
||||||
|
isVerified bool) (int64, error) {
|
||||||
op := NewUserOperator()
|
op := NewUserOperator()
|
||||||
op.Username = username
|
op.Username = username
|
||||||
op.Password = stringutil.Md5(password)
|
op.Password = stringutil.Md5(password)
|
||||||
@@ -112,10 +135,24 @@ func (this *UserDAO) CreateUser(tx *dbs.Tx, username string, password string, fu
|
|||||||
op.Mobile = mobile
|
op.Mobile = mobile
|
||||||
op.Tel = tel
|
op.Tel = tel
|
||||||
op.Email = email
|
op.Email = email
|
||||||
|
op.EmailIsVerified = false
|
||||||
op.Remark = remark
|
op.Remark = remark
|
||||||
op.Source = source
|
op.Source = source
|
||||||
op.ClusterId = clusterId
|
op.ClusterId = clusterId
|
||||||
op.Day = timeutil.Format("Ymd")
|
op.Day = timeutil.Format("Ymd")
|
||||||
|
op.IsVerified = isVerified
|
||||||
|
op.RegisteredIP = registeredIP
|
||||||
|
|
||||||
|
// features
|
||||||
|
if len(features) == 0 {
|
||||||
|
op.Features = "[]"
|
||||||
|
} else {
|
||||||
|
featuresJSON, err := json.Marshal(features)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
op.Features = featuresJSON
|
||||||
|
}
|
||||||
|
|
||||||
op.IsOn = true
|
op.IsOn = true
|
||||||
op.State = UserStateEnabled
|
op.State = UserStateEnabled
|
||||||
@@ -149,13 +186,15 @@ func (this *UserDAO) UpdateUser(tx *dbs.Tx, userId int64, username string, passw
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUserInfo 修改用户基本信息
|
// UpdateUserInfo 修改用户基本信息
|
||||||
func (this *UserDAO) UpdateUserInfo(tx *dbs.Tx, userId int64, fullname string) error {
|
func (this *UserDAO) UpdateUserInfo(tx *dbs.Tx, userId int64, fullname string, mobile string, email string) error {
|
||||||
if userId <= 0 {
|
if userId <= 0 {
|
||||||
return errors.New("invalid userId")
|
return errors.New("invalid userId")
|
||||||
}
|
}
|
||||||
op := NewUserOperator()
|
op := NewUserOperator()
|
||||||
op.Id = userId
|
op.Id = userId
|
||||||
op.Fullname = fullname
|
op.Fullname = fullname
|
||||||
|
op.Mobile = mobile
|
||||||
|
op.Email = email
|
||||||
return this.Save(tx, op)
|
return this.Save(tx, op)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +214,7 @@ func (this *UserDAO) UpdateUserLogin(tx *dbs.Tx, userId int64, username string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CountAllEnabledUsers 计算用户数量
|
// CountAllEnabledUsers 计算用户数量
|
||||||
func (this *UserDAO) CountAllEnabledUsers(tx *dbs.Tx, clusterId int64, keyword string) (int64, error) {
|
func (this *UserDAO) CountAllEnabledUsers(tx *dbs.Tx, clusterId int64, keyword string, isVerifying bool) (int64, error) {
|
||||||
query := this.Query(tx)
|
query := this.Query(tx)
|
||||||
query.State(UserStateEnabled)
|
query.State(UserStateEnabled)
|
||||||
if clusterId > 0 {
|
if clusterId > 0 {
|
||||||
@@ -185,11 +224,22 @@ func (this *UserDAO) CountAllEnabledUsers(tx *dbs.Tx, clusterId int64, keyword s
|
|||||||
query.Where("(username LIKE :keyword OR fullname LIKE :keyword OR mobile LIKE :keyword OR email LIKE :keyword OR tel LIKE :keyword OR remark LIKE :keyword)").
|
query.Where("(username LIKE :keyword OR fullname LIKE :keyword OR mobile LIKE :keyword OR email LIKE :keyword OR tel LIKE :keyword OR remark LIKE :keyword)").
|
||||||
Param("keyword", "%"+keyword+"%")
|
Param("keyword", "%"+keyword+"%")
|
||||||
}
|
}
|
||||||
|
if isVerifying {
|
||||||
|
query.Attr("isVerified", 0)
|
||||||
|
}
|
||||||
|
return query.Count()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountAllVerifyingUsers 获取等待审核的用户数
|
||||||
|
func (this *UserDAO) CountAllVerifyingUsers(tx *dbs.Tx) (int64, error) {
|
||||||
|
query := this.Query(tx)
|
||||||
|
query.State(UserStateEnabled)
|
||||||
|
query.Attr("isVerified", 0)
|
||||||
return query.Count()
|
return query.Count()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListEnabledUsers 列出单页用户
|
// ListEnabledUsers 列出单页用户
|
||||||
func (this *UserDAO) ListEnabledUsers(tx *dbs.Tx, clusterId int64, keyword string, offset int64, size int64) (result []*User, err error) {
|
func (this *UserDAO) ListEnabledUsers(tx *dbs.Tx, clusterId int64, keyword string, isVerifying bool, offset int64, size int64) (result []*User, err error) {
|
||||||
query := this.Query(tx)
|
query := this.Query(tx)
|
||||||
query.State(UserStateEnabled)
|
query.State(UserStateEnabled)
|
||||||
if clusterId > 0 {
|
if clusterId > 0 {
|
||||||
@@ -199,6 +249,9 @@ func (this *UserDAO) ListEnabledUsers(tx *dbs.Tx, clusterId int64, keyword strin
|
|||||||
query.Where("(username LIKE :keyword OR fullname LIKE :keyword OR mobile LIKE :keyword OR email LIKE :keyword OR tel LIKE :keyword OR remark LIKE :keyword)").
|
query.Where("(username LIKE :keyword OR fullname LIKE :keyword OR mobile LIKE :keyword OR email LIKE :keyword OR tel LIKE :keyword OR remark LIKE :keyword)").
|
||||||
Param("keyword", "%"+keyword+"%")
|
Param("keyword", "%"+keyword+"%")
|
||||||
}
|
}
|
||||||
|
if isVerifying {
|
||||||
|
query.Attr("isVerified", 0)
|
||||||
|
}
|
||||||
_, err = query.
|
_, err = query.
|
||||||
DescPk().
|
DescPk().
|
||||||
Offset(offset).
|
Offset(offset).
|
||||||
@@ -355,3 +408,16 @@ func (this *UserDAO) CountDailyUsers(tx *dbs.Tx, dayFrom string, dayTo string) (
|
|||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateUserIsVerified 审核用户
|
||||||
|
func (this *UserDAO) UpdateUserIsVerified(tx *dbs.Tx, userId int64, isRejected bool, rejectReason string) error {
|
||||||
|
if userId <= 0 {
|
||||||
|
return errors.New("invalid userId")
|
||||||
|
}
|
||||||
|
var op = NewUserOperator()
|
||||||
|
op.Id = userId
|
||||||
|
op.IsRejected = isRejected
|
||||||
|
op.RejectReason = rejectReason
|
||||||
|
op.IsVerified = true
|
||||||
|
return this.Save(tx, op)
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,43 +2,55 @@ package models
|
|||||||
|
|
||||||
// User 用户
|
// User 用户
|
||||||
type User struct {
|
type User struct {
|
||||||
Id uint32 `field:"id"` // ID
|
Id uint32 `field:"id"` // ID
|
||||||
IsOn uint8 `field:"isOn"` // 是否启用
|
IsOn uint8 `field:"isOn"` // 是否启用
|
||||||
Username string `field:"username"` // 用户名
|
Username string `field:"username"` // 用户名
|
||||||
Password string `field:"password"` // 密码
|
Password string `field:"password"` // 密码
|
||||||
Fullname string `field:"fullname"` // 真实姓名
|
Fullname string `field:"fullname"` // 真实姓名
|
||||||
Mobile string `field:"mobile"` // 手机号
|
Mobile string `field:"mobile"` // 手机号
|
||||||
Tel string `field:"tel"` // 联系电话
|
Tel string `field:"tel"` // 联系电话
|
||||||
Remark string `field:"remark"` // 备注
|
Remark string `field:"remark"` // 备注
|
||||||
Email string `field:"email"` // 邮箱地址
|
Email string `field:"email"` // 邮箱地址
|
||||||
AvatarFileId uint64 `field:"avatarFileId"` // 头像文件ID
|
EmailIsVerified uint8 `field:"emailIsVerified"` // 邮箱是否已验证
|
||||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
AvatarFileId uint64 `field:"avatarFileId"` // 头像文件ID
|
||||||
Day string `field:"day"` // YYYYMMDD
|
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||||
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
|
Day string `field:"day"` // YYYYMMDD
|
||||||
State uint8 `field:"state"` // 状态
|
UpdatedAt uint64 `field:"updatedAt"` // 修改时间
|
||||||
Source string `field:"source"` // 来源
|
State uint8 `field:"state"` // 状态
|
||||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
Source string `field:"source"` // 来源
|
||||||
Features string `field:"features"` // 允许操作的特征
|
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||||
|
Features string `field:"features"` // 允许操作的特征
|
||||||
|
RegisteredIP string `field:"registeredIP"` // 注册使用的IP
|
||||||
|
IsRejected uint8 `field:"isRejected"` // 是否已拒绝
|
||||||
|
RejectReason string `field:"rejectReason"` // 拒绝理由
|
||||||
|
IsVerified uint8 `field:"isVerified"` // 是否验证通过
|
||||||
|
RequirePlans uint8 `field:"requirePlans"` // 是否需要购买套餐
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserOperator struct {
|
type UserOperator struct {
|
||||||
Id interface{} // ID
|
Id interface{} // ID
|
||||||
IsOn interface{} // 是否启用
|
IsOn interface{} // 是否启用
|
||||||
Username interface{} // 用户名
|
Username interface{} // 用户名
|
||||||
Password interface{} // 密码
|
Password interface{} // 密码
|
||||||
Fullname interface{} // 真实姓名
|
Fullname interface{} // 真实姓名
|
||||||
Mobile interface{} // 手机号
|
Mobile interface{} // 手机号
|
||||||
Tel interface{} // 联系电话
|
Tel interface{} // 联系电话
|
||||||
Remark interface{} // 备注
|
Remark interface{} // 备注
|
||||||
Email interface{} // 邮箱地址
|
Email interface{} // 邮箱地址
|
||||||
AvatarFileId interface{} // 头像文件ID
|
EmailIsVerified interface{} // 邮箱是否已验证
|
||||||
CreatedAt interface{} // 创建时间
|
AvatarFileId interface{} // 头像文件ID
|
||||||
Day interface{} // YYYYMMDD
|
CreatedAt interface{} // 创建时间
|
||||||
UpdatedAt interface{} // 修改时间
|
Day interface{} // YYYYMMDD
|
||||||
State interface{} // 状态
|
UpdatedAt interface{} // 修改时间
|
||||||
Source interface{} // 来源
|
State interface{} // 状态
|
||||||
ClusterId interface{} // 集群ID
|
Source interface{} // 来源
|
||||||
Features interface{} // 允许操作的特征
|
ClusterId interface{} // 集群ID
|
||||||
|
Features interface{} // 允许操作的特征
|
||||||
|
RegisteredIP interface{} // 注册使用的IP
|
||||||
|
IsRejected interface{} // 是否已拒绝
|
||||||
|
RejectReason interface{} // 拒绝理由
|
||||||
|
IsVerified interface{} // 是否验证通过
|
||||||
|
RequirePlans interface{} // 是否需要购买套餐
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUserOperator() *UserOperator {
|
func NewUserOperator() *UserOperator {
|
||||||
|
|||||||
@@ -85,6 +85,31 @@ func (this *UserPlanDAO) FindEnabledUserPlan(tx *dbs.Tx, userPlanId int64, cache
|
|||||||
return result.(*UserPlan), err
|
return result.(*UserPlan), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindUserPlanWithoutState 查找套餐,并不检查状态
|
||||||
|
// 防止因为删除套餐而导致计费失败
|
||||||
|
func (this *UserPlanDAO) FindUserPlanWithoutState(tx *dbs.Tx, userPlanId int64, cacheMap *utils.CacheMap) (*UserPlan, error) {
|
||||||
|
var cacheKey = this.Table + ":FindUserPlanWithoutState:" + types.String(userPlanId)
|
||||||
|
if cacheMap != nil {
|
||||||
|
cache, ok := cacheMap.Get(cacheKey)
|
||||||
|
if ok {
|
||||||
|
return cache.(*UserPlan), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := this.Query(tx).
|
||||||
|
Pk(userPlanId).
|
||||||
|
Find()
|
||||||
|
if result == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if cacheMap != nil {
|
||||||
|
cacheMap.Put(cacheKey, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.(*UserPlan), err
|
||||||
|
}
|
||||||
|
|
||||||
// CountAllEnabledUserPlans 计算套餐数量
|
// CountAllEnabledUserPlans 计算套餐数量
|
||||||
func (this *UserPlanDAO) CountAllEnabledUserPlans(tx *dbs.Tx, userId int64, isAvailable bool, isExpired bool, expiringDays int32) (int64, error) {
|
func (this *UserPlanDAO) CountAllEnabledUserPlans(tx *dbs.Tx, userId int64, isAvailable bool, isExpired bool, expiringDays int32) (int64, error) {
|
||||||
var query = this.Query(tx).
|
var query = this.Query(tx).
|
||||||
|
|||||||
@@ -150,13 +150,13 @@ func (this *AliDNSProvider) AddRecord(domain string, newRecord *dnstypes.Record)
|
|||||||
resp := alidns.CreateAddDomainRecordResponse()
|
resp := alidns.CreateAddDomainRecordResponse()
|
||||||
err := this.doAPI(req, resp)
|
err := this.doAPI(req, resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
if resp.IsSuccess() {
|
if resp.IsSuccess() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.New(resp.GetHttpContentString())
|
return this.WrapError(errors.New(resp.GetHttpContentString()), domain, newRecord)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateRecord 修改记录
|
// UpdateRecord 修改记录
|
||||||
@@ -174,7 +174,7 @@ func (this *AliDNSProvider) UpdateRecord(domain string, record *dnstypes.Record,
|
|||||||
|
|
||||||
resp := alidns.CreateUpdateDomainRecordResponse()
|
resp := alidns.CreateUpdateDomainRecordResponse()
|
||||||
err := this.doAPI(req, resp)
|
err := this.doAPI(req, resp)
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRecord 删除记录
|
// DeleteRecord 删除记录
|
||||||
@@ -184,7 +184,7 @@ func (this *AliDNSProvider) DeleteRecord(domain string, record *dnstypes.Record)
|
|||||||
|
|
||||||
resp := alidns.CreateDeleteDomainRecordResponse()
|
resp := alidns.CreateDeleteDomainRecordResponse()
|
||||||
err := this.doAPI(req, resp)
|
err := this.doAPI(req, resp)
|
||||||
return err
|
return this.WrapError(err, domain, record)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultRoute 默认线路
|
// DefaultRoute 默认线路
|
||||||
|
|||||||
@@ -1,4 +1,29 @@
|
|||||||
package dnsclients
|
package dnsclients
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/dnsclients/dnstypes"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
)
|
||||||
|
|
||||||
type BaseProvider struct {
|
type BaseProvider struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WrapError 封装解析相关错误
|
||||||
|
func (this *BaseProvider) WrapError(err error, domain string, record *dnstypes.Record) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if record == nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var fullname = ""
|
||||||
|
if len(record.Name) == 0 {
|
||||||
|
fullname = domain
|
||||||
|
} else {
|
||||||
|
fullname = record.Name + "." + domain
|
||||||
|
}
|
||||||
|
return errors.New("record operation failed: '" + fullname + " " + record.Type + " " + record.Value + " " + types.String(record.TTL) + "': " + err.Error())
|
||||||
|
}
|
||||||
|
|||||||
38
internal/dnsclients/provider_base_test.go
Normal file
38
internal/dnsclients/provider_base_test.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package dnsclients_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/dnsclients"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/dnsclients/dnstypes"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBaseProvider_WrapError(t *testing.T) {
|
||||||
|
var provider = &dnsclients.BaseProvider{}
|
||||||
|
t.Log(provider.WrapError(nil, "example.com", &dnstypes.Record{
|
||||||
|
Id: "",
|
||||||
|
Name: "a",
|
||||||
|
Type: "A",
|
||||||
|
Value: "192.168.1.100",
|
||||||
|
Route: "",
|
||||||
|
TTL: 3600,
|
||||||
|
}))
|
||||||
|
t.Log(provider.WrapError(errors.New("fake error"), "example.com", &dnstypes.Record{
|
||||||
|
Id: "",
|
||||||
|
Name: "a",
|
||||||
|
Type: "A",
|
||||||
|
Value: "192.168.1.100",
|
||||||
|
Route: "",
|
||||||
|
TTL: 3600,
|
||||||
|
}))
|
||||||
|
t.Log(provider.WrapError(errors.New("fake error"), "example.com", &dnstypes.Record{
|
||||||
|
Id: "",
|
||||||
|
Name: "",
|
||||||
|
Type: "A",
|
||||||
|
Value: "192.168.1.100",
|
||||||
|
Route: "",
|
||||||
|
TTL: 3600,
|
||||||
|
}))
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/dnsclients/cloudflare"
|
"github.com/TeaOSLab/EdgeAPI/internal/dnsclients/cloudflare"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/dnsclients/dnstypes"
|
"github.com/TeaOSLab/EdgeAPI/internal/dnsclients/dnstypes"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||||
@@ -168,7 +169,7 @@ func (this *CloudFlareProvider) QueryRecord(domain string, name string, recordTy
|
|||||||
func (this *CloudFlareProvider) AddRecord(domain string, newRecord *dnstypes.Record) error {
|
func (this *CloudFlareProvider) AddRecord(domain string, newRecord *dnstypes.Record) error {
|
||||||
zoneId, err := this.findZoneIdWithDomain(domain)
|
zoneId, err := this.findZoneIdWithDomain(domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := new(cloudflare.CreateDNSRecordResponse)
|
resp := new(cloudflare.CreateDNSRecordResponse)
|
||||||
@@ -185,7 +186,7 @@ func (this *CloudFlareProvider) AddRecord(domain string, newRecord *dnstypes.Rec
|
|||||||
"ttl": ttl,
|
"ttl": ttl,
|
||||||
}, resp)
|
}, resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -194,7 +195,7 @@ func (this *CloudFlareProvider) AddRecord(domain string, newRecord *dnstypes.Rec
|
|||||||
func (this *CloudFlareProvider) UpdateRecord(domain string, record *dnstypes.Record, newRecord *dnstypes.Record) error {
|
func (this *CloudFlareProvider) UpdateRecord(domain string, record *dnstypes.Record, newRecord *dnstypes.Record) error {
|
||||||
zoneId, err := this.findZoneIdWithDomain(domain)
|
zoneId, err := this.findZoneIdWithDomain(domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ttl = newRecord.TTL
|
var ttl = newRecord.TTL
|
||||||
@@ -215,13 +216,13 @@ func (this *CloudFlareProvider) UpdateRecord(domain string, record *dnstypes.Rec
|
|||||||
func (this *CloudFlareProvider) DeleteRecord(domain string, record *dnstypes.Record) error {
|
func (this *CloudFlareProvider) DeleteRecord(domain string, record *dnstypes.Record) error {
|
||||||
zoneId, err := this.findZoneIdWithDomain(domain)
|
zoneId, err := this.findZoneIdWithDomain(domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, record)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := new(cloudflare.DeleteDNSRecordResponse)
|
resp := new(cloudflare.DeleteDNSRecordResponse)
|
||||||
err = this.doAPI(http.MethodDelete, "zones/"+zoneId+"/dns_records/"+record.Id, map[string]string{}, nil, resp)
|
err = this.doAPI(http.MethodDelete, "zones/"+zoneId+"/dns_records/"+record.Id, map[string]string{}, nil, resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, record)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -257,6 +258,7 @@ func (this *CloudFlareProvider) doAPI(method string, apiPath string, args map[st
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
req.Header.Set("User-Agent", teaconst.ProductName+"/"+teaconst.Version)
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
req.Header.Set("X-Auth-Key", this.apiKey)
|
req.Header.Set("X-Auth-Key", this.apiKey)
|
||||||
req.Header.Set("x-Auth-Email", this.email)
|
req.Header.Set("x-Auth-Email", this.email)
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ var customHTTPClient = &http.Client{
|
|||||||
type CustomHTTPProvider struct {
|
type CustomHTTPProvider struct {
|
||||||
url string
|
url string
|
||||||
secret string
|
secret string
|
||||||
|
|
||||||
|
BaseProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auth 认证
|
// Auth 认证
|
||||||
@@ -96,7 +98,7 @@ func (this *CustomHTTPProvider) QueryRecord(domain string, name string, recordTy
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(resp) == 0 {
|
if len(resp) == 0 || string(resp) == "null" {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
record := &dnstypes.Record{}
|
record := &dnstypes.Record{}
|
||||||
@@ -117,7 +119,7 @@ func (this *CustomHTTPProvider) AddRecord(domain string, newRecord *dnstypes.Rec
|
|||||||
"domain": domain,
|
"domain": domain,
|
||||||
"newRecord": newRecord,
|
"newRecord": newRecord,
|
||||||
})
|
})
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateRecord 修改记录
|
// UpdateRecord 修改记录
|
||||||
@@ -128,7 +130,7 @@ func (this *CustomHTTPProvider) UpdateRecord(domain string, record *dnstypes.Rec
|
|||||||
"record": record,
|
"record": record,
|
||||||
"newRecord": newRecord,
|
"newRecord": newRecord,
|
||||||
})
|
})
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRecord 删除记录
|
// DeleteRecord 删除记录
|
||||||
@@ -138,7 +140,7 @@ func (this *CustomHTTPProvider) DeleteRecord(domain string, record *dnstypes.Rec
|
|||||||
"domain": domain,
|
"domain": domain,
|
||||||
"record": record,
|
"record": record,
|
||||||
})
|
})
|
||||||
return err
|
return this.WrapError(err, domain, record)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultRoute 默认线路
|
// DefaultRoute 默认线路
|
||||||
@@ -162,10 +164,11 @@ func (this *CustomHTTPProvider) post(params maps.Map) (respData []byte, err erro
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
|
var timestamp = strconv.FormatInt(time.Now().Unix(), 10)
|
||||||
req.Header.Set("Timestamp", timestamp)
|
req.Header.Set("Timestamp", timestamp)
|
||||||
req.Header.Set("Token", fmt.Sprintf("%x", sha1.Sum([]byte(this.secret+"@"+timestamp))))
|
req.Header.Set("Token", fmt.Sprintf("%x", sha1.Sum([]byte(this.secret+"@"+timestamp))))
|
||||||
req.Header.Set("User-Agent", "GoEdge/"+teaconst.Version)
|
req.Header.Set("User-Agent", teaconst.ProductName+"/"+teaconst.Version)
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
resp, err := customHTTPClient.Do(req)
|
resp, err := customHTTPClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ func (this *DNSPodProvider) AddRecord(domain string, newRecord *dnstypes.Record)
|
|||||||
args["ttl"] = types.String(newRecord.TTL)
|
args["ttl"] = types.String(newRecord.TTL)
|
||||||
}
|
}
|
||||||
_, err := this.post("/Record.Create", args)
|
_, err := this.post("/Record.Create", args)
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateRecord 修改记录
|
// UpdateRecord 修改记录
|
||||||
@@ -211,7 +211,7 @@ func (this *DNSPodProvider) UpdateRecord(domain string, record *dnstypes.Record,
|
|||||||
args["ttl"] = types.String(newRecord.TTL)
|
args["ttl"] = types.String(newRecord.TTL)
|
||||||
}
|
}
|
||||||
_, err := this.post("/Record.Modify", args)
|
_, err := this.post("/Record.Modify", args)
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteRecord 删除记录
|
// DeleteRecord 删除记录
|
||||||
@@ -225,7 +225,7 @@ func (this *DNSPodProvider) DeleteRecord(domain string, record *dnstypes.Record)
|
|||||||
"record_id": record.Id,
|
"record_id": record.Id,
|
||||||
})
|
})
|
||||||
|
|
||||||
return err
|
return this.WrapError(err, domain, record)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送请求
|
// 发送请求
|
||||||
|
|||||||
@@ -1331,7 +1331,7 @@ func (this *HuaweiDNSProvider) QueryRecord(domain string, name string, recordTyp
|
|||||||
func (this *HuaweiDNSProvider) AddRecord(domain string, newRecord *dnstypes.Record) error {
|
func (this *HuaweiDNSProvider) AddRecord(domain string, newRecord *dnstypes.Record) error {
|
||||||
zoneId, err := this.findZoneIdWithDomain(domain)
|
zoneId, err := this.findZoneIdWithDomain(domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp = new(huaweidns.ZonesCreateRecordSetResponse)
|
var resp = new(huaweidns.ZonesCreateRecordSetResponse)
|
||||||
@@ -1354,7 +1354,7 @@ func (this *HuaweiDNSProvider) AddRecord(domain string, newRecord *dnstypes.Reco
|
|||||||
"ttl": ttl,
|
"ttl": ttl,
|
||||||
}, resp)
|
}, resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
|
|
||||||
newRecord.Id = resp.Id + "@" + newRecord.Value
|
newRecord.Id = resp.Id + "@" + newRecord.Value
|
||||||
@@ -1366,7 +1366,7 @@ func (this *HuaweiDNSProvider) AddRecord(domain string, newRecord *dnstypes.Reco
|
|||||||
func (this *HuaweiDNSProvider) UpdateRecord(domain string, record *dnstypes.Record, newRecord *dnstypes.Record) error {
|
func (this *HuaweiDNSProvider) UpdateRecord(domain string, record *dnstypes.Record, newRecord *dnstypes.Record) error {
|
||||||
zoneId, err := this.findZoneIdWithDomain(domain)
|
zoneId, err := this.findZoneIdWithDomain(domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
|
|
||||||
var recordId string
|
var recordId string
|
||||||
@@ -1397,7 +1397,7 @@ func (this *HuaweiDNSProvider) UpdateRecord(domain string, record *dnstypes.Reco
|
|||||||
"ttl": ttl,
|
"ttl": ttl,
|
||||||
}, resp)
|
}, resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -1407,7 +1407,7 @@ func (this *HuaweiDNSProvider) UpdateRecord(domain string, record *dnstypes.Reco
|
|||||||
func (this *HuaweiDNSProvider) DeleteRecord(domain string, record *dnstypes.Record) error {
|
func (this *HuaweiDNSProvider) DeleteRecord(domain string, record *dnstypes.Record) error {
|
||||||
zoneId, err := this.findZoneIdWithDomain(domain)
|
zoneId, err := this.findZoneIdWithDomain(domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, record)
|
||||||
}
|
}
|
||||||
|
|
||||||
var recordId string
|
var recordId string
|
||||||
@@ -1421,7 +1421,7 @@ func (this *HuaweiDNSProvider) DeleteRecord(domain string, record *dnstypes.Reco
|
|||||||
var resp = new(huaweidns.ZonesDeleteRecordSetResponse)
|
var resp = new(huaweidns.ZonesDeleteRecordSetResponse)
|
||||||
err = this.doAPI(http.MethodDelete, "/v2.1/zones/"+zoneId+"/recordsets/"+recordId, map[string]string{}, maps.Map{}, resp)
|
err = this.doAPI(http.MethodDelete, "/v2.1/zones/"+zoneId+"/recordsets/"+recordId, map[string]string{}, maps.Map{}, resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, record)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ import (
|
|||||||
type LocalEdgeDNSProvider struct {
|
type LocalEdgeDNSProvider struct {
|
||||||
clusterId int64 // 集群ID
|
clusterId int64 // 集群ID
|
||||||
ttl int32 // TTL
|
ttl int32 // TTL
|
||||||
|
|
||||||
|
BaseProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auth 认证
|
// Auth 认证
|
||||||
@@ -193,10 +195,10 @@ func (this *LocalEdgeDNSProvider) AddRecord(domain string, newRecord *dnstypes.R
|
|||||||
var tx *dbs.Tx
|
var tx *dbs.Tx
|
||||||
domainId, err := nameservers.SharedNSDomainDAO.FindDomainIdWithName(tx, this.clusterId, domain)
|
domainId, err := nameservers.SharedNSDomainDAO.FindDomainIdWithName(tx, this.clusterId, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
if domainId == 0 {
|
if domainId == 0 {
|
||||||
return errors.New("can not find domain '" + domain + "'")
|
return this.WrapError(errors.New("can not find domain '"+domain+"'"), domain, newRecord)
|
||||||
}
|
}
|
||||||
|
|
||||||
var routeIds = []string{}
|
var routeIds = []string{}
|
||||||
@@ -209,7 +211,7 @@ func (this *LocalEdgeDNSProvider) AddRecord(domain string, newRecord *dnstypes.R
|
|||||||
}
|
}
|
||||||
_, err = nameservers.SharedNSRecordDAO.CreateRecord(tx, domainId, "", newRecord.Name, newRecord.Type, newRecord.Value, newRecord.TTL, routeIds)
|
_, err = nameservers.SharedNSRecordDAO.CreateRecord(tx, domainId, "", newRecord.Name, newRecord.Type, newRecord.Value, newRecord.TTL, routeIds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -220,7 +222,7 @@ func (this *LocalEdgeDNSProvider) UpdateRecord(domain string, record *dnstypes.R
|
|||||||
var tx *dbs.Tx
|
var tx *dbs.Tx
|
||||||
domainId, err := nameservers.SharedNSDomainDAO.FindDomainIdWithName(tx, this.clusterId, domain)
|
domainId, err := nameservers.SharedNSDomainDAO.FindDomainIdWithName(tx, this.clusterId, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
if domainId == 0 {
|
if domainId == 0 {
|
||||||
return errors.New("can not find domain '" + domain + "'")
|
return errors.New("can not find domain '" + domain + "'")
|
||||||
@@ -238,17 +240,17 @@ func (this *LocalEdgeDNSProvider) UpdateRecord(domain string, record *dnstypes.R
|
|||||||
if len(record.Id) > 0 {
|
if len(record.Id) > 0 {
|
||||||
err = nameservers.SharedNSRecordDAO.UpdateRecord(tx, types.Int64(record.Id), "", newRecord.Name, newRecord.Type, newRecord.Value, newRecord.TTL, routeIds, true)
|
err = nameservers.SharedNSRecordDAO.UpdateRecord(tx, types.Int64(record.Id), "", newRecord.Name, newRecord.Type, newRecord.Value, newRecord.TTL, routeIds, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
realRecord, err := nameservers.SharedNSRecordDAO.FindEnabledRecordWithName(tx, domainId, record.Name, record.Type)
|
realRecord, err := nameservers.SharedNSRecordDAO.FindEnabledRecordWithName(tx, domainId, record.Name, record.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
if realRecord != nil {
|
if realRecord != nil {
|
||||||
err = nameservers.SharedNSRecordDAO.UpdateRecord(tx, types.Int64(realRecord.Id), "", newRecord.Name, newRecord.Type, newRecord.Value, newRecord.TTL, routeIds, true)
|
err = nameservers.SharedNSRecordDAO.UpdateRecord(tx, types.Int64(realRecord.Id), "", newRecord.Name, newRecord.Type, newRecord.Value, newRecord.TTL, routeIds, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, newRecord)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -261,7 +263,7 @@ func (this *LocalEdgeDNSProvider) DeleteRecord(domain string, record *dnstypes.R
|
|||||||
var tx *dbs.Tx
|
var tx *dbs.Tx
|
||||||
domainId, err := nameservers.SharedNSDomainDAO.FindDomainIdWithName(tx, this.clusterId, domain)
|
domainId, err := nameservers.SharedNSDomainDAO.FindDomainIdWithName(tx, this.clusterId, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, record)
|
||||||
}
|
}
|
||||||
if domainId == 0 {
|
if domainId == 0 {
|
||||||
return errors.New("can not find domain '" + domain + "'")
|
return errors.New("can not find domain '" + domain + "'")
|
||||||
@@ -270,17 +272,17 @@ func (this *LocalEdgeDNSProvider) DeleteRecord(domain string, record *dnstypes.R
|
|||||||
if len(record.Id) > 0 {
|
if len(record.Id) > 0 {
|
||||||
err = nameservers.SharedNSRecordDAO.DisableNSRecord(tx, types.Int64(record.Id))
|
err = nameservers.SharedNSRecordDAO.DisableNSRecord(tx, types.Int64(record.Id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, record)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
realRecord, err := nameservers.SharedNSRecordDAO.FindEnabledRecordWithName(tx, domainId, record.Name, record.Type)
|
realRecord, err := nameservers.SharedNSRecordDAO.FindEnabledRecordWithName(tx, domainId, record.Name, record.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, record)
|
||||||
}
|
}
|
||||||
if realRecord != nil {
|
if realRecord != nil {
|
||||||
err = nameservers.SharedNSRecordDAO.DisableNSRecord(tx, types.Int64(realRecord.Id))
|
err = nameservers.SharedNSRecordDAO.DisableNSRecord(tx, types.Int64(realRecord.Id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return this.WrapError(err, domain, record)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,19 +9,30 @@ import (
|
|||||||
|
|
||||||
var SharedDeployManager = NewDeployManager()
|
var SharedDeployManager = NewDeployManager()
|
||||||
|
|
||||||
|
// DeployManager 节点部署文件管理器
|
||||||
|
// 如果节点部署文件有变化,需要重启API节点以便于生效
|
||||||
type DeployManager struct {
|
type DeployManager struct {
|
||||||
dir string
|
dir string
|
||||||
|
nodeFiles []*DeployFile
|
||||||
|
nsNodeFiles []*DeployFile
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDeployManager 节点部署文件管理器
|
// NewDeployManager 获取新节点部署文件管理器
|
||||||
func NewDeployManager() *DeployManager {
|
func NewDeployManager() *DeployManager {
|
||||||
return &DeployManager{
|
var manager = &DeployManager{
|
||||||
dir: Tea.Root + "/deploy",
|
dir: Tea.Root + "/deploy",
|
||||||
}
|
}
|
||||||
|
manager.LoadNodeFiles()
|
||||||
|
manager.LoadNSNodeFiles()
|
||||||
|
return manager
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadNodeFiles 加载所有边缘节点文件
|
// LoadNodeFiles 加载所有边缘节点文件
|
||||||
func (this *DeployManager) LoadNodeFiles() []*DeployFile {
|
func (this *DeployManager) LoadNodeFiles() []*DeployFile {
|
||||||
|
if len(this.nodeFiles) > 0 {
|
||||||
|
return this.nodeFiles
|
||||||
|
}
|
||||||
|
|
||||||
keyMap := map[string]*DeployFile{} // key => File
|
keyMap := map[string]*DeployFile{} // key => File
|
||||||
|
|
||||||
reg := regexp.MustCompile(`^edge-node-(\w+)-(\w+)-v([0-9.]+)\.zip$`)
|
reg := regexp.MustCompile(`^edge-node-(\w+)-(\w+)-v([0-9.]+)\.zip$`)
|
||||||
@@ -52,6 +63,9 @@ func (this *DeployManager) LoadNodeFiles() []*DeployFile {
|
|||||||
for _, v := range keyMap {
|
for _, v := range keyMap {
|
||||||
result = append(result, v)
|
result = append(result, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.nodeFiles = result
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,6 +81,10 @@ func (this *DeployManager) FindNodeFile(os string, arch string) *DeployFile {
|
|||||||
|
|
||||||
// LoadNSNodeFiles 加载所有NS节点安装文件
|
// LoadNSNodeFiles 加载所有NS节点安装文件
|
||||||
func (this *DeployManager) LoadNSNodeFiles() []*DeployFile {
|
func (this *DeployManager) LoadNSNodeFiles() []*DeployFile {
|
||||||
|
if len(this.nsNodeFiles) > 0 {
|
||||||
|
return this.nsNodeFiles
|
||||||
|
}
|
||||||
|
|
||||||
keyMap := map[string]*DeployFile{} // key => File
|
keyMap := map[string]*DeployFile{} // key => File
|
||||||
|
|
||||||
reg := regexp.MustCompile(`^edge-dns-(\w+)-(\w+)-v([0-9.]+)\.zip$`)
|
reg := regexp.MustCompile(`^edge-dns-(\w+)-(\w+)-v([0-9.]+)\.zip$`)
|
||||||
@@ -97,6 +115,9 @@ func (this *DeployManager) LoadNSNodeFiles() []*DeployFile {
|
|||||||
for _, v := range keyMap {
|
for _, v := range keyMap {
|
||||||
result = append(result, v)
|
result = append(result, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.nsNodeFiles = result
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package nodes
|
package nodes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -11,9 +12,9 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAPI/internal/events"
|
"github.com/TeaOSLab/EdgeAPI/internal/events"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/rpc"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/setup"
|
"github.com/TeaOSLab/EdgeAPI/internal/setup"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||||
"github.com/go-yaml/yaml"
|
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
"github.com/iwind/TeaGo/dbs"
|
"github.com/iwind/TeaGo/dbs"
|
||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
@@ -24,6 +25,7 @@ import (
|
|||||||
"github.com/iwind/gosock/pkg/gosock"
|
"github.com/iwind/gosock/pkg/gosock"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
@@ -35,6 +37,9 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
// grpc decompression
|
||||||
|
_ "google.golang.org/grpc/encoding/gzip"
|
||||||
)
|
)
|
||||||
|
|
||||||
var sharedAPIConfig *configs.APIConfig = nil
|
var sharedAPIConfig *configs.APIConfig = nil
|
||||||
@@ -214,10 +219,10 @@ func (this *APINode) listenRPC(listener net.Listener, tlsConfig *tls.Config) err
|
|||||||
var rpcServer *grpc.Server
|
var rpcServer *grpc.Server
|
||||||
if tlsConfig == nil {
|
if tlsConfig == nil {
|
||||||
remotelogs.Println("API_NODE", "listening GRPC http://"+listener.Addr().String()+" ...")
|
remotelogs.Println("API_NODE", "listening GRPC http://"+listener.Addr().String()+" ...")
|
||||||
rpcServer = grpc.NewServer(grpc.MaxRecvMsgSize(128 * 1024 * 1024))
|
rpcServer = grpc.NewServer(grpc.MaxRecvMsgSize(128*1024*1024), grpc.UnaryInterceptor(this.unaryInterceptor))
|
||||||
} else {
|
} else {
|
||||||
logs.Println("[API_NODE]listening GRPC https://" + listener.Addr().String() + " ...")
|
logs.Println("[API_NODE]listening GRPC https://" + listener.Addr().String() + " ...")
|
||||||
rpcServer = grpc.NewServer(grpc.Creds(credentials.NewTLS(tlsConfig)), grpc.MaxRecvMsgSize(128*1024*1024))
|
rpcServer = grpc.NewServer(grpc.Creds(credentials.NewTLS(tlsConfig)), grpc.MaxRecvMsgSize(128*1024*1024), grpc.UnaryInterceptor(this.unaryInterceptor))
|
||||||
}
|
}
|
||||||
this.registerServices(rpcServer)
|
this.registerServices(rpcServer)
|
||||||
err := rpcServer.Serve(listener)
|
err := rpcServer.Serve(listener)
|
||||||
@@ -274,7 +279,7 @@ func (this *APINode) autoUpgrade() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("decode database config failed: " + err.Error())
|
return errors.New("decode database config failed: " + err.Error())
|
||||||
}
|
}
|
||||||
dbConfig := config.DBs[Tea.Env]
|
var dbConfig = config.DBs[Tea.Env]
|
||||||
db, err := dbs.NewInstanceFromConfig(dbConfig)
|
db, err := dbs.NewInstanceFromConfig(dbConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("load database failed: " + err.Error())
|
return errors.New("load database failed: " + err.Error())
|
||||||
@@ -285,8 +290,8 @@ func (this *APINode) autoUpgrade() error {
|
|||||||
}
|
}
|
||||||
if one != nil {
|
if one != nil {
|
||||||
// 如果是同样的版本,则直接认为是最新版本
|
// 如果是同样的版本,则直接认为是最新版本
|
||||||
version := one.GetString("version")
|
var version = one.GetString("version")
|
||||||
if stringutil.VersionCompare(version, teaconst.Version) >= 0 {
|
if stringutil.VersionCompare(version, setup.ComposeSQLVersion()) >= 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -572,6 +577,11 @@ func (this *APINode) listenSock() error {
|
|||||||
"result": result,
|
"result": result,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
case "debug":
|
||||||
|
teaconst.Debug = !teaconst.Debug
|
||||||
|
_ = cmd.Reply(&gosock.Command{
|
||||||
|
Params: map[string]interface{}{"debug": teaconst.Debug},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -588,3 +598,29 @@ func (this *APINode) listenSock() error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 服务过滤器
|
||||||
|
func (this *APINode) unaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
|
||||||
|
if teaconst.Debug {
|
||||||
|
var before = time.Now()
|
||||||
|
var traceCtx = rpc.NewContext(ctx)
|
||||||
|
resp, err = handler(traceCtx, req)
|
||||||
|
|
||||||
|
var costMs = time.Since(before).Seconds() * 1000
|
||||||
|
statErr := models.SharedAPIMethodStatDAO.CreateStat(nil, info.FullMethod, "", costMs)
|
||||||
|
if statErr != nil {
|
||||||
|
remotelogs.Error("API_NODE", "create method stat failed: "+statErr.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
var tagMap = traceCtx.TagMap()
|
||||||
|
for tag, tagCostMs := range tagMap {
|
||||||
|
statErr = models.SharedAPIMethodStatDAO.CreateStat(nil, info.FullMethod, tag, tagCostMs)
|
||||||
|
if statErr != nil {
|
||||||
|
remotelogs.Error("API_NODE", "create method stat failed: "+statErr.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return handler(ctx, req)
|
||||||
|
}
|
||||||
|
|||||||
@@ -63,6 +63,11 @@ func (this *APINode) registerServices(server *grpc.Server) {
|
|||||||
pb.RegisterAPINodeServiceServer(server, instance)
|
pb.RegisterAPINodeServiceServer(server, instance)
|
||||||
this.rest(instance)
|
this.rest(instance)
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
instance := this.serviceInstance(&services.APIMethodStatService{}).(*services.APIMethodStatService)
|
||||||
|
pb.RegisterAPIMethodStatServiceServer(server, instance)
|
||||||
|
this.rest(instance)
|
||||||
|
}
|
||||||
{
|
{
|
||||||
instance := this.serviceInstance(&services.OriginService{}).(*services.OriginService)
|
instance := this.serviceInstance(&services.OriginService{}).(*services.OriginService)
|
||||||
pb.RegisterOriginServiceServer(server, instance)
|
pb.RegisterOriginServiceServer(server, instance)
|
||||||
@@ -263,6 +268,16 @@ func (this *APINode) registerServices(server *grpc.Server) {
|
|||||||
pb.RegisterRegionProvinceServiceServer(server, instance)
|
pb.RegisterRegionProvinceServiceServer(server, instance)
|
||||||
this.rest(instance)
|
this.rest(instance)
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
instance := this.serviceInstance(&services.RegionCityService{}).(*services.RegionCityService)
|
||||||
|
pb.RegisterRegionCityServiceServer(server, instance)
|
||||||
|
this.rest(instance)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
instance := this.serviceInstance(&services.RegionProviderService{}).(*services.RegionProviderService)
|
||||||
|
pb.RegisterRegionProviderServiceServer(server, instance)
|
||||||
|
this.rest(instance)
|
||||||
|
}
|
||||||
{
|
{
|
||||||
instance := this.serviceInstance(&services.IPListService{}).(*services.IPListService)
|
instance := this.serviceInstance(&services.IPListService{}).(*services.IPListService)
|
||||||
pb.RegisterIPListServiceServer(server, instance)
|
pb.RegisterIPListServiceServer(server, instance)
|
||||||
@@ -333,6 +348,11 @@ func (this *APINode) registerServices(server *grpc.Server) {
|
|||||||
pb.RegisterUserBillServiceServer(server, instance)
|
pb.RegisterUserBillServiceServer(server, instance)
|
||||||
this.rest(instance)
|
this.rest(instance)
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
instance := this.serviceInstance(&services.ServerBillService{}).(*services.ServerBillService)
|
||||||
|
pb.RegisterServerBillServiceServer(server, instance)
|
||||||
|
this.rest(instance)
|
||||||
|
}
|
||||||
{
|
{
|
||||||
instance := this.serviceInstance(&services.UserNodeService{}).(*services.UserNodeService)
|
instance := this.serviceInstance(&services.UserNodeService{}).(*services.UserNodeService)
|
||||||
pb.RegisterUserNodeServiceServer(server, instance)
|
pb.RegisterUserNodeServiceServer(server, instance)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
// +build community
|
//go:build !plus
|
||||||
|
// +build !plus
|
||||||
|
|
||||||
package nodes
|
package nodes
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
"github.com/shirou/gopsutil/cpu"
|
"github.com/shirou/gopsutil/v3/cpu"
|
||||||
"github.com/shirou/gopsutil/disk"
|
"github.com/shirou/gopsutil/v3/disk"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user