Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14315923d8 | ||
|
|
3d3228fe96 | ||
|
|
173ac5a8aa | ||
|
|
e9c5d7e7cf | ||
|
|
194127dce9 | ||
|
|
86cb7e9d41 | ||
|
|
b2774de6a2 | ||
|
|
3a4722b701 | ||
|
|
028aea4e3d | ||
|
|
c3dd97a7c1 | ||
|
|
d527fcdd78 | ||
|
|
d6f311e057 | ||
|
|
991e08fa71 | ||
|
|
06b44dc101 | ||
|
|
2d94b994fa | ||
|
|
c036186dde | ||
|
|
bc2ad13037 | ||
|
|
bfa04856aa | ||
|
|
feb1068441 | ||
|
|
181a4d05b0 | ||
|
|
c449265e05 | ||
|
|
e778616b5c | ||
|
|
dad5be2670 | ||
|
|
414afd17b8 | ||
|
|
86a806bca2 | ||
|
|
faed7420a7 | ||
|
|
ae14ff4f9f | ||
|
|
99e1658fdf | ||
|
|
e79264eefc | ||
|
|
dd0e26e7bc | ||
|
|
342c4bfbc2 | ||
|
|
7d2b8fd4c8 | ||
|
|
6426622992 | ||
|
|
3d154411de | ||
|
|
241f41e900 | ||
|
|
6c3d24d895 | ||
|
|
b2a0204f6b | ||
|
|
a9d71652b7 | ||
|
|
1b6bfb33d6 | ||
|
|
aec0d8d681 | ||
|
|
e38871b52d | ||
|
|
c1b4551dd1 | ||
|
|
d479140f87 |
@@ -27,10 +27,11 @@ func main() {
|
|||||||
app.Version(teaconst.Version)
|
app.Version(teaconst.Version)
|
||||||
app.Product(teaconst.ProductName)
|
app.Product(teaconst.ProductName)
|
||||||
app.Usage(teaconst.ProcessName + " [start|stop|restart|setup|upgrade|service|daemon|issues]")
|
app.Usage(teaconst.ProcessName + " [start|stop|restart|setup|upgrade|service|daemon|issues]")
|
||||||
|
|
||||||
app.On("setup", func() {
|
app.On("setup", func() {
|
||||||
var setupCmd = setup.NewSetupFromCmd()
|
var setupCmd = setup.NewSetupFromCmd()
|
||||||
err := setupCmd.Run()
|
err := setupCmd.Run()
|
||||||
result := maps.Map{}
|
var result = maps.Map{}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result["isOk"] = false
|
result["isOk"] = false
|
||||||
result["error"] = err.Error()
|
result["error"] = err.Error()
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func main() {
|
|||||||
fmt.Println("[ERROR]" + err.Error())
|
fmt.Println("[ERROR]" + err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
results, err := setup.NewSQLDump().Dump(db)
|
results, err := setup.NewSQLDump().Dump(db, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("[ERROR]" + err.Error())
|
fmt.Println("[ERROR]" + err.Error())
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -5,12 +5,18 @@ import (
|
|||||||
"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"
|
||||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||||
|
"github.com/iwind/TeaGo/lists"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DNSProvider struct {
|
type DNSProvider struct {
|
||||||
raw dnsclients.ProviderInterface
|
raw dnsclients.ProviderInterface
|
||||||
dnsDomain string
|
dnsDomain string
|
||||||
|
|
||||||
|
locker sync.Mutex
|
||||||
|
deletedRecordNames []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDNSProvider(raw dnsclients.ProviderInterface, dnsDomain string) *DNSProvider {
|
func NewDNSProvider(raw dnsclients.ProviderInterface, dnsDomain string) *DNSProvider {
|
||||||
@@ -21,6 +27,7 @@ func NewDNSProvider(raw dnsclients.ProviderInterface, dnsDomain string) *DNSProv
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (this *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
|
_ = os.Setenv("LEGO_DISABLE_CNAME_SUPPORT", "true")
|
||||||
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
||||||
|
|
||||||
// 设置记录
|
// 设置记录
|
||||||
@@ -29,31 +36,38 @@ func (this *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||||||
return errors.New("invalid fqdn value")
|
return errors.New("invalid fqdn value")
|
||||||
}
|
}
|
||||||
var recordName = fqdn[:index]
|
var recordName = fqdn[:index]
|
||||||
record, err := this.raw.QueryRecord(this.dnsDomain, recordName, dnstypes.RecordTypeTXT)
|
|
||||||
if err != nil {
|
// 先删除老的
|
||||||
return errors.New("query DNS record failed: " + err.Error())
|
this.locker.Lock()
|
||||||
|
var wasDeleted = lists.ContainsString(this.deletedRecordNames, recordName)
|
||||||
|
this.locker.Unlock()
|
||||||
|
|
||||||
|
if !wasDeleted {
|
||||||
|
records, err := this.raw.QueryRecords(this.dnsDomain, recordName, dnstypes.RecordTypeTXT)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("query DNS record failed: " + err.Error())
|
||||||
|
}
|
||||||
|
for _, record := range records {
|
||||||
|
err = this.raw.DeleteRecord(this.dnsDomain, record)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.locker.Lock()
|
||||||
|
this.deletedRecordNames = append(this.deletedRecordNames, recordName)
|
||||||
|
this.locker.Unlock()
|
||||||
}
|
}
|
||||||
if record == nil {
|
|
||||||
err = this.raw.AddRecord(this.dnsDomain, &dnstypes.Record{
|
// 添加新的
|
||||||
Id: "",
|
err := this.raw.AddRecord(this.dnsDomain, &dnstypes.Record{
|
||||||
Name: recordName,
|
Id: "",
|
||||||
Type: dnstypes.RecordTypeTXT,
|
Name: recordName,
|
||||||
Value: value,
|
Type: dnstypes.RecordTypeTXT,
|
||||||
Route: this.raw.DefaultRoute(),
|
Value: value,
|
||||||
})
|
Route: this.raw.DefaultRoute(),
|
||||||
if err != nil {
|
})
|
||||||
return errors.New("create DNS record failed: " + err.Error())
|
if err != nil {
|
||||||
}
|
return errors.New("create DNS record failed: " + err.Error())
|
||||||
} else {
|
|
||||||
err = this.raw.UpdateRecord(this.dnsDomain, record, &dnstypes.Record{
|
|
||||||
Name: recordName,
|
|
||||||
Type: dnstypes.RecordTypeTXT,
|
|
||||||
Value: value,
|
|
||||||
Route: this.raw.DefaultRoute(),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return errors.New("update DNS record failed: " + err.Error())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package teaconst
|
package teaconst
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version = "0.5.7"
|
Version = "0.5.8"
|
||||||
|
|
||||||
ProductName = "Edge API"
|
ProductName = "Edge API"
|
||||||
ProcessName = "edge-api"
|
ProcessName = "edge-api"
|
||||||
@@ -18,13 +18,8 @@ const (
|
|||||||
|
|
||||||
// 其他节点版本号,用来检测是否有需要升级的节点
|
// 其他节点版本号,用来检测是否有需要升级的节点
|
||||||
|
|
||||||
NodeVersion = "0.5.6"
|
NodeVersion = "0.5.8"
|
||||||
UserNodeVersion = "0.5.6"
|
|
||||||
DNSNodeVersion = "0.2.8"
|
|
||||||
AuthorityNodeVersion = "0.0.2"
|
|
||||||
MonitorNodeVersion = "0.0.4"
|
|
||||||
ReportNodeVersion = "0.1.1"
|
|
||||||
|
|
||||||
// SQLVersion SQL版本号
|
// SQLVersion SQL版本号
|
||||||
SQLVersion = "2"
|
SQLVersion = "4"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ func init() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成日志
|
// CreateACMETaskLog 生成日志
|
||||||
func (this *ACMETaskLogDAO) CreateACMETaskLog(tx *dbs.Tx, taskId int64, isOk bool, errMsg string) error {
|
func (this *ACMETaskLogDAO) CreateACMETaskLog(tx *dbs.Tx, taskId int64, isOk bool, errMsg string) error {
|
||||||
var op = NewACMETaskLogOperator()
|
var op = NewACMETaskLogOperator()
|
||||||
op.TaskId = taskId
|
op.TaskId = taskId
|
||||||
@@ -37,7 +37,7 @@ func (this *ACMETaskLogDAO) CreateACMETaskLog(tx *dbs.Tx, taskId int64, isOk boo
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 取得任务的最后一条执行日志
|
// FindLatestACMETasKLog 取得任务的最后一条执行日志
|
||||||
func (this *ACMETaskLogDAO) FindLatestACMETasKLog(tx *dbs.Tx, taskId int64) (*ACMETaskLog, error) {
|
func (this *ACMETaskLogDAO) FindLatestACMETasKLog(tx *dbs.Tx, taskId int64) (*ACMETaskLog, error) {
|
||||||
one, err := this.Query(tx).
|
one, err := this.Query(tx).
|
||||||
Attr("taskId", taskId).
|
Attr("taskId", taskId).
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/utils/ttlcache"
|
||||||
_ "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"
|
||||||
"strconv"
|
"github.com/iwind/TeaGo/rands"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -13,7 +17,20 @@ const (
|
|||||||
ClientBrowserStateDisabled = 0 // 已禁用
|
ClientBrowserStateDisabled = 0 // 已禁用
|
||||||
)
|
)
|
||||||
|
|
||||||
var clientBrowserNameAndIdCacheMap = map[string]int64{}
|
func init() {
|
||||||
|
dbs.OnReadyDone(func() {
|
||||||
|
// 清理数据任务
|
||||||
|
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||||
|
goman.New(func() {
|
||||||
|
for range ticker.C {
|
||||||
|
err := SharedClientBrowserDAO.Clean(nil, 7) // 只保留N天
|
||||||
|
if err != nil {
|
||||||
|
remotelogs.Error("SharedClientBrowserDAO", "clean expired data failed: "+err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type ClientBrowserDAO dbs.DAO
|
type ClientBrowserDAO dbs.DAO
|
||||||
|
|
||||||
@@ -74,65 +91,64 @@ func (this *ClientBrowserDAO) FindClientBrowserName(tx *dbs.Tx, id uint32) (stri
|
|||||||
FindStringCol("")
|
FindStringCol("")
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindBrowserIdWithNameCacheable 根据浏览器名称查找浏览器ID
|
// CreateBrowserIfNotExists 创建浏览器信息
|
||||||
func (this *ClientBrowserDAO) FindBrowserIdWithNameCacheable(tx *dbs.Tx, browserName string) (int64, error) {
|
func (this *ClientBrowserDAO) CreateBrowserIfNotExists(tx *dbs.Tx, browserName string) error {
|
||||||
SharedCacheLocker.RLock()
|
const maxlength = 50
|
||||||
browserId, ok := clientBrowserNameAndIdCacheMap[browserName]
|
|
||||||
if ok {
|
|
||||||
SharedCacheLocker.RUnlock()
|
|
||||||
return browserId, nil
|
|
||||||
}
|
|
||||||
SharedCacheLocker.RUnlock()
|
|
||||||
|
|
||||||
browserId, err := this.Query(tx).
|
|
||||||
Where("JSON_CONTAINS(codes, :browserName)").
|
|
||||||
Param("browserName", strconv.Quote(browserName)). // 查询的需要是个JSON字符串,所以这里加双引号
|
|
||||||
ResultPk().
|
|
||||||
FindInt64Col(0)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if browserId > 0 {
|
|
||||||
// 只有找到的时候才放入缓存,以便于我们可以在不存在的时候创建一条新的记录
|
|
||||||
SharedCacheLocker.Lock()
|
|
||||||
clientBrowserNameAndIdCacheMap[browserName] = browserId
|
|
||||||
SharedCacheLocker.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
return browserId, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateBrowser 创建浏览器
|
|
||||||
func (this *ClientBrowserDAO) CreateBrowser(tx *dbs.Tx, browserName string) (int64, error) {
|
|
||||||
var maxlength = 50
|
|
||||||
if len(browserName) > maxlength {
|
if len(browserName) > maxlength {
|
||||||
browserName = browserName[:50]
|
browserName = browserName[:50]
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedCacheLocker.Lock()
|
// 检查缓存
|
||||||
defer SharedCacheLocker.Unlock()
|
var cacheKey = "clientBrowser:" + browserName
|
||||||
|
var cacheItem = ttlcache.SharedCache.Read(cacheKey)
|
||||||
|
if cacheItem != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// 检查是否已经创建
|
// 检查是否已经存在
|
||||||
|
// 不需要加状态条件
|
||||||
browserId, err := this.Query(tx).
|
browserId, err := this.Query(tx).
|
||||||
Attr("name", browserName).
|
Attr("name", browserName).
|
||||||
ResultPk().
|
ResultPk().
|
||||||
FindInt64Col(0)
|
FindInt64Col(0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return err
|
||||||
}
|
}
|
||||||
if browserId > 0 {
|
if browserId > 0 {
|
||||||
return browserId, nil
|
// 加入缓存,但缓存时间不要过长,因为有别的操作在更新数据
|
||||||
|
ttlcache.SharedCache.Write(cacheKey, browserId, time.Now().Unix()+3600)
|
||||||
|
|
||||||
|
return this.Query(tx).
|
||||||
|
Pk(browserId).
|
||||||
|
Set("createdDay", timeutil.Format("Ymd")).
|
||||||
|
UpdateQuickly()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果不存在,则创建之
|
||||||
var op = NewClientBrowserOperator()
|
var op = NewClientBrowserOperator()
|
||||||
op.Name = browserName
|
op.Name = browserName
|
||||||
codes := []string{browserName}
|
op.CreatedDay = timeutil.Format("Ymd")
|
||||||
codesJSON, err := json.Marshal(codes)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
op.Codes = codesJSON
|
|
||||||
op.State = ClientBrowserStateEnabled
|
op.State = ClientBrowserStateEnabled
|
||||||
return this.SaveInt64(tx, op)
|
browserId, err = this.SaveInt64(tx, op)
|
||||||
|
if err != nil && CheckSQLErrCode(err, 1062 /** duplicate entry **/) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加入缓存,但缓存时间不要过长,因为有别的操作在更新数据
|
||||||
|
if browserId > 0 {
|
||||||
|
ttlcache.SharedCache.Write(cacheKey, browserId, time.Now().Unix()+3600)
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean 清理
|
||||||
|
func (this *ClientBrowserDAO) Clean(tx *dbs.Tx, days int) error {
|
||||||
|
if days <= 0 {
|
||||||
|
days = 30
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.Query(tx).
|
||||||
|
Lt("createdDay", timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days))).
|
||||||
|
DeleteQuickly()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,33 @@
|
|||||||
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"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestClientBrowserDAO_CreateBrowser(t *testing.T) {
|
||||||
|
var dao = models.NewClientBrowserDAO()
|
||||||
|
err := dao.CreateBrowserIfNotExists(nil, "Hello")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = dao.CreateBrowserIfNotExists(nil, "Hello")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = dao.CreateBrowserIfNotExists(nil, "Hello")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClientBrowserDAO_Clean(t *testing.T) {
|
||||||
|
var dao = models.NewClientBrowserDAO()
|
||||||
|
err := dao.Clean(nil, 30)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,17 +4,19 @@ import "github.com/iwind/TeaGo/dbs"
|
|||||||
|
|
||||||
// ClientBrowser 终端浏览器信息
|
// ClientBrowser 终端浏览器信息
|
||||||
type ClientBrowser struct {
|
type ClientBrowser struct {
|
||||||
Id uint32 `field:"id"` // ID
|
Id uint32 `field:"id"` // ID
|
||||||
Name string `field:"name"` // 浏览器名称
|
Name string `field:"name"` // 浏览器名称
|
||||||
Codes dbs.JSON `field:"codes"` // 代号
|
Codes dbs.JSON `field:"codes"` // 代号
|
||||||
State uint8 `field:"state"` // 状态
|
CreatedDay string `field:"createdDay"` // 创建日期YYYYMMDD
|
||||||
|
State uint8 `field:"state"` // 状态
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClientBrowserOperator struct {
|
type ClientBrowserOperator struct {
|
||||||
Id interface{} // ID
|
Id any // ID
|
||||||
Name interface{} // 浏览器名称
|
Name any // 浏览器名称
|
||||||
Codes interface{} // 代号
|
Codes any // 代号
|
||||||
State interface{} // 状态
|
CreatedDay any // 创建日期YYYYMMDD
|
||||||
|
State any // 状态
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClientBrowserOperator() *ClientBrowserOperator {
|
func NewClientBrowserOperator() *ClientBrowserOperator {
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/utils/ttlcache"
|
||||||
_ "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"
|
||||||
"strconv"
|
"github.com/iwind/TeaGo/rands"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -13,7 +17,20 @@ const (
|
|||||||
ClientSystemStateDisabled = 0 // 已禁用
|
ClientSystemStateDisabled = 0 // 已禁用
|
||||||
)
|
)
|
||||||
|
|
||||||
var clientSystemNameAndIdCacheMap = map[string]int64{} // system name => id
|
func init() {
|
||||||
|
dbs.OnReadyDone(func() {
|
||||||
|
// 清理数据任务
|
||||||
|
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||||
|
goman.New(func() {
|
||||||
|
for range ticker.C {
|
||||||
|
err := SharedClientSystemDAO.Clean(nil, 7) // 只保留N天
|
||||||
|
if err != nil {
|
||||||
|
remotelogs.Error("SharedClientSystemDAO", "clean expired data failed: "+err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type ClientSystemDAO dbs.DAO
|
type ClientSystemDAO dbs.DAO
|
||||||
|
|
||||||
@@ -74,67 +91,63 @@ func (this *ClientSystemDAO) FindClientSystemName(tx *dbs.Tx, id uint32) (string
|
|||||||
FindStringCol("")
|
FindStringCol("")
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindSystemIdWithNameCacheable 根据操作系统名称查找系统ID
|
// CreateSystemIfNotExists 创建系统信息
|
||||||
func (this *ClientSystemDAO) FindSystemIdWithNameCacheable(tx *dbs.Tx, systemName string) (int64, error) {
|
func (this *ClientSystemDAO) CreateSystemIfNotExists(tx *dbs.Tx, systemName string) error {
|
||||||
SharedCacheLocker.RLock()
|
const maxlength = 50
|
||||||
systemId, ok := clientSystemNameAndIdCacheMap[systemName]
|
|
||||||
if ok {
|
|
||||||
SharedCacheLocker.RUnlock()
|
|
||||||
return systemId, nil
|
|
||||||
}
|
|
||||||
SharedCacheLocker.RUnlock()
|
|
||||||
|
|
||||||
systemId, err := this.Query(tx).
|
|
||||||
Where("JSON_CONTAINS(codes, :systemName)").
|
|
||||||
Param("systemName", strconv.Quote(systemName)). // 查询的需要是个JSON字符串,所以这里加双引号
|
|
||||||
ResultPk().
|
|
||||||
FindInt64Col(0)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if systemId > 0 {
|
|
||||||
// 只有找到的时候才放入缓存,以便于我们可以在不存在的时候创建一条新的记录
|
|
||||||
SharedCacheLocker.Lock()
|
|
||||||
clientSystemNameAndIdCacheMap[systemName] = systemId
|
|
||||||
SharedCacheLocker.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
return systemId, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateSystem 创建浏览器
|
|
||||||
func (this *ClientSystemDAO) CreateSystem(tx *dbs.Tx, systemName string) (int64, error) {
|
|
||||||
var maxlength = 50
|
|
||||||
if len(systemName) > maxlength {
|
if len(systemName) > maxlength {
|
||||||
systemName = systemName[:50]
|
systemName = systemName[:50]
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedCacheLocker.Lock()
|
// 检查缓存
|
||||||
defer SharedCacheLocker.Unlock()
|
var cacheKey = "clientSystem:" + systemName
|
||||||
|
var cacheItem = ttlcache.SharedCache.Read(cacheKey)
|
||||||
|
if cacheItem != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// 检查是否已经创建
|
// 检查是否已经存在
|
||||||
|
// 不需要加状态条件
|
||||||
systemId, err := this.Query(tx).
|
systemId, err := this.Query(tx).
|
||||||
Attr("name", systemName).
|
Attr("name", systemName).
|
||||||
ResultPk().
|
ResultPk().
|
||||||
FindInt64Col(0)
|
FindInt64Col(0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return err
|
||||||
}
|
}
|
||||||
if systemId > 0 {
|
if systemId > 0 {
|
||||||
return systemId, nil
|
// 加入缓存,但缓存时间不要过长,因为有别的操作在更新数据
|
||||||
|
ttlcache.SharedCache.Write(cacheKey, systemId, time.Now().Unix()+3600)
|
||||||
|
|
||||||
|
return this.Query(tx).
|
||||||
|
Pk(systemId).
|
||||||
|
Set("createdDay", timeutil.Format("Ymd")).
|
||||||
|
UpdateQuickly()
|
||||||
}
|
}
|
||||||
|
|
||||||
var op = NewClientSystemOperator()
|
var op = NewClientSystemOperator()
|
||||||
op.Name = systemName
|
op.Name = systemName
|
||||||
|
op.CreatedDay = timeutil.Format("Ymd")
|
||||||
codes := []string{systemName}
|
|
||||||
codesJSON, err := json.Marshal(codes)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
op.Codes = codesJSON
|
|
||||||
|
|
||||||
op.State = ClientSystemStateEnabled
|
op.State = ClientSystemStateEnabled
|
||||||
return this.SaveInt64(tx, op)
|
systemId, err = this.SaveInt64(tx, op)
|
||||||
|
if err != nil && CheckSQLErrCode(err, 1062 /** duplicate entry **/) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加入缓存,但缓存时间不要过长,因为有别的操作在更新数据
|
||||||
|
if systemId > 0 {
|
||||||
|
ttlcache.SharedCache.Write(cacheKey, systemId, time.Now().Unix()+3600)
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean 清理
|
||||||
|
func (this *ClientSystemDAO) Clean(tx *dbs.Tx, days int) error {
|
||||||
|
if days <= 0 {
|
||||||
|
days = 30
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.Query(tx).
|
||||||
|
Lt("createdDay", timeutil.Format("Ymd", time.Now().AddDate(0, 0, -days))).
|
||||||
|
DeleteQuickly()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,31 @@
|
|||||||
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"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestClientSystemDAO_CreateSystemIfNotExists(t *testing.T) {
|
||||||
|
var dao = models.NewClientSystemDAO()
|
||||||
|
{
|
||||||
|
err := dao.CreateSystemIfNotExists(nil, "Mac OS X")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
err := dao.CreateSystemIfNotExists(nil, "Mac OS X 2")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClientSystemDAO_Clean(t *testing.T) {
|
||||||
|
var dao = models.NewClientSystemDAO()
|
||||||
|
err := dao.Clean(nil, 30)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,17 +4,19 @@ import "github.com/iwind/TeaGo/dbs"
|
|||||||
|
|
||||||
// ClientSystem 终端操作系统信息
|
// ClientSystem 终端操作系统信息
|
||||||
type ClientSystem struct {
|
type ClientSystem struct {
|
||||||
Id uint32 `field:"id"` // ID
|
Id uint32 `field:"id"` // ID
|
||||||
Name string `field:"name"` // 系统名称
|
Name string `field:"name"` // 系统名称
|
||||||
Codes dbs.JSON `field:"codes"` // 代号
|
Codes dbs.JSON `field:"codes"` // 代号
|
||||||
State uint8 `field:"state"` //
|
CreatedDay string `field:"createdDay"` // 创建日期YYYYMMDD
|
||||||
|
State uint8 `field:"state"` // 状态
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClientSystemOperator struct {
|
type ClientSystemOperator struct {
|
||||||
Id interface{} // ID
|
Id any // ID
|
||||||
Name interface{} // 系统名称
|
Name any // 系统名称
|
||||||
Codes interface{} // 代号
|
Codes any // 代号
|
||||||
State interface{} //
|
CreatedDay any // 创建日期YYYYMMDD
|
||||||
|
State any // 状态
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClientSystemOperator() *ClientSystemOperator {
|
func NewClientSystemOperator() *ClientSystemOperator {
|
||||||
|
|||||||
@@ -78,8 +78,8 @@ func (this *DNSTaskDAO) CreateClusterRemoveTask(tx *dbs.Tx, clusterId int64, dom
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateNodeTask 生成节点任务
|
// CreateNodeTask 生成节点任务
|
||||||
func (this *DNSTaskDAO) CreateNodeTask(tx *dbs.Tx, nodeId int64, taskType DNSTaskType) error {
|
func (this *DNSTaskDAO) CreateNodeTask(tx *dbs.Tx, clusterId int64, nodeId int64, taskType DNSTaskType) error {
|
||||||
return this.CreateDNSTask(tx, 0, 0, nodeId, 0, "", taskType)
|
return this.CreateDNSTask(tx, clusterId, 0, nodeId, 0, "", taskType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateServerTask 生成服务任务
|
// CreateServerTask 生成服务任务
|
||||||
|
|||||||
207
internal/db/models/formal_client_browser_dao.go
Normal file
207
internal/db/models/formal_client_browser_dao.go
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/utils/ttlcache"
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
FormalClientBrowserStateEnabled = 1 // 已启用
|
||||||
|
FormalClientBrowserStateDisabled = 0 // 已禁用
|
||||||
|
)
|
||||||
|
|
||||||
|
type FormalClientBrowserDAO dbs.DAO
|
||||||
|
|
||||||
|
func NewFormalClientBrowserDAO() *FormalClientBrowserDAO {
|
||||||
|
return dbs.NewDAO(&FormalClientBrowserDAO{
|
||||||
|
DAOObject: dbs.DAOObject{
|
||||||
|
DB: Tea.Env,
|
||||||
|
Table: "edgeFormalClientBrowsers",
|
||||||
|
Model: new(FormalClientBrowser),
|
||||||
|
PkName: "id",
|
||||||
|
},
|
||||||
|
}).(*FormalClientBrowserDAO)
|
||||||
|
}
|
||||||
|
|
||||||
|
var SharedFormalClientBrowserDAO *FormalClientBrowserDAO
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
dbs.OnReady(func() {
|
||||||
|
SharedFormalClientBrowserDAO = NewFormalClientBrowserDAO()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnableFormalClientBrowser 启用条目
|
||||||
|
func (this *FormalClientBrowserDAO) EnableFormalClientBrowser(tx *dbs.Tx, id uint32) error {
|
||||||
|
_, err := this.Query(tx).
|
||||||
|
Pk(id).
|
||||||
|
Set("state", FormalClientBrowserStateEnabled).
|
||||||
|
Update()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisableFormalClientBrowser 禁用条目
|
||||||
|
func (this *FormalClientBrowserDAO) DisableFormalClientBrowser(tx *dbs.Tx, id uint32) error {
|
||||||
|
_, err := this.Query(tx).
|
||||||
|
Pk(id).
|
||||||
|
Set("state", FormalClientBrowserStateDisabled).
|
||||||
|
Update()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindEnabledFormalClientBrowser 查找启用中的条目
|
||||||
|
func (this *FormalClientBrowserDAO) FindEnabledFormalClientBrowser(tx *dbs.Tx, id int64) (*FormalClientBrowser, error) {
|
||||||
|
result, err := this.Query(tx).
|
||||||
|
Pk(id).
|
||||||
|
State(FormalClientBrowserStateEnabled).
|
||||||
|
Find()
|
||||||
|
if result == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result.(*FormalClientBrowser), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindFormalClientBrowserName 根据主键查找名称
|
||||||
|
func (this *FormalClientBrowserDAO) FindFormalClientBrowserName(tx *dbs.Tx, id uint32) (string, error) {
|
||||||
|
return this.Query(tx).
|
||||||
|
Pk(id).
|
||||||
|
Result("name").
|
||||||
|
FindStringCol("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindBrowserIdWithNameCacheable 根据浏览器名称查找系统ID
|
||||||
|
func (this *FormalClientBrowserDAO) FindBrowserIdWithNameCacheable(tx *dbs.Tx, browserName string) (int64, error) {
|
||||||
|
var cacheKey = "formalClientBrowser:" + browserName
|
||||||
|
var cacheItem = ttlcache.SharedCache.Read(cacheKey)
|
||||||
|
if cacheItem != nil {
|
||||||
|
return types.Int64(cacheItem.Value), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先使用 name 查找,因为有索引,所以会快一些
|
||||||
|
browserId, err := this.Query(tx).
|
||||||
|
Attr("name", browserName).
|
||||||
|
ResultPk().
|
||||||
|
FindInt64Col(0)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if browserId == 0 {
|
||||||
|
browserId, err = this.Query(tx).
|
||||||
|
Where("JSON_CONTAINS(codes, :browserName)").
|
||||||
|
Param("browserName", strconv.Quote(browserName)). // 查询的需要是个JSON字符串,所以这里加双引号
|
||||||
|
ResultPk().
|
||||||
|
FindInt64Col(0)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 即使找不到也要放入到缓存中
|
||||||
|
ttlcache.SharedCache.Write(cacheKey, browserId, time.Now().Unix()+3600)
|
||||||
|
|
||||||
|
return browserId, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountBrowsers 计算浏览器数量
|
||||||
|
func (this *FormalClientBrowserDAO) CountBrowsers(tx *dbs.Tx, keyword string) (int64, error) {
|
||||||
|
var query = this.Query(tx)
|
||||||
|
if len(keyword) > 0 {
|
||||||
|
query.Like("LOWER(codes)", dbutils.QuoteLikeKeyword(strings.ToLower(keyword)))
|
||||||
|
}
|
||||||
|
return query.Count()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListBrowsers 列出单页浏览器信息
|
||||||
|
func (this *FormalClientBrowserDAO) ListBrowsers(tx *dbs.Tx, keyword string, offset int64, size int64) (result []*FormalClientBrowser, err error) {
|
||||||
|
var query = this.Query(tx)
|
||||||
|
if len(keyword) > 0 {
|
||||||
|
query.Like("LOWER(codes)", dbutils.QuoteLikeKeyword(strings.ToLower(keyword)))
|
||||||
|
}
|
||||||
|
_, err = query.
|
||||||
|
Offset(offset).
|
||||||
|
Limit(size).
|
||||||
|
DescPk().
|
||||||
|
Slice(&result).
|
||||||
|
FindAll()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindBrowserWithDataId 根据dataId查找浏览器信息
|
||||||
|
func (this *FormalClientBrowserDAO) FindBrowserWithDataId(tx *dbs.Tx, dataId string) (*FormalClientBrowser, error) {
|
||||||
|
one, err := this.Query(tx).
|
||||||
|
Attr("dataId", dataId).
|
||||||
|
Find()
|
||||||
|
if err != nil || one == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return one.(*FormalClientBrowser), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateBrowser 创建浏览器信息
|
||||||
|
func (this *FormalClientBrowserDAO) CreateBrowser(tx *dbs.Tx, name string, codes []string, dataId string) (int64, error) {
|
||||||
|
if len(dataId) == 0 {
|
||||||
|
return 0, errors.New("invalid dataId")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查 dataId 是否已经存在
|
||||||
|
exists, err := this.Query(tx).
|
||||||
|
Attr("dataId", dataId).
|
||||||
|
Exist()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if exists {
|
||||||
|
return 0, errors.New("dataId '" + dataId + "' already exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
var op = NewFormalClientBrowserOperator()
|
||||||
|
op.Name = name
|
||||||
|
if len(codes) == 0 {
|
||||||
|
op.Codes = "[]"
|
||||||
|
} else {
|
||||||
|
codesJSON, err := json.Marshal(codes)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
op.Codes = codesJSON
|
||||||
|
}
|
||||||
|
op.DataId = dataId
|
||||||
|
op.State = FormalClientBrowserStateEnabled
|
||||||
|
return this.SaveInt64(tx, op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateBrowser 修改浏览器信息
|
||||||
|
func (this *FormalClientBrowserDAO) UpdateBrowser(tx *dbs.Tx, browserId int64, name string, codes []string, dataId string) error {
|
||||||
|
if browserId <= 0 {
|
||||||
|
return errors.New("invalid browserId '" + types.String(browserId) + "'")
|
||||||
|
}
|
||||||
|
if len(dataId) == 0 {
|
||||||
|
return errors.New("invalid dataId")
|
||||||
|
}
|
||||||
|
|
||||||
|
var op = NewFormalClientBrowserOperator()
|
||||||
|
op.Id = browserId
|
||||||
|
op.Name = name
|
||||||
|
if len(codes) == 0 {
|
||||||
|
op.Codes = "[]"
|
||||||
|
} else {
|
||||||
|
codesJSON, err := json.Marshal(codes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
op.Codes = codesJSON
|
||||||
|
}
|
||||||
|
op.DataId = dataId
|
||||||
|
return this.Save(tx, op)
|
||||||
|
}
|
||||||
6
internal/db/models/formal_client_browser_dao_test.go
Normal file
6
internal/db/models/formal_client_browser_dao_test.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package models_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
|
)
|
||||||
24
internal/db/models/formal_client_browser_model.go
Normal file
24
internal/db/models/formal_client_browser_model.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "github.com/iwind/TeaGo/dbs"
|
||||||
|
|
||||||
|
// FormalClientBrowser 终端浏览器信息
|
||||||
|
type FormalClientBrowser struct {
|
||||||
|
Id uint32 `field:"id"` // ID
|
||||||
|
Name string `field:"name"` // 浏览器名称
|
||||||
|
Codes dbs.JSON `field:"codes"` // 代号
|
||||||
|
DataId string `field:"dataId"` // 数据ID
|
||||||
|
State uint8 `field:"state"` // 状态
|
||||||
|
}
|
||||||
|
|
||||||
|
type FormalClientBrowserOperator struct {
|
||||||
|
Id any // ID
|
||||||
|
Name any // 浏览器名称
|
||||||
|
Codes any // 代号
|
||||||
|
DataId any // 数据ID
|
||||||
|
State any // 状态
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFormalClientBrowserOperator() *FormalClientBrowserOperator {
|
||||||
|
return &FormalClientBrowserOperator{}
|
||||||
|
}
|
||||||
21
internal/db/models/formal_client_browser_model_ext.go
Normal file
21
internal/db/models/formal_client_browser_model_ext.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DecodeCodes 解析代号
|
||||||
|
func (this *FormalClientBrowser) DecodeCodes() []string {
|
||||||
|
if IsNull(this.Codes) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = []string{}
|
||||||
|
err := json.Unmarshal(this.Codes, &result)
|
||||||
|
if err != nil {
|
||||||
|
remotelogs.Error("FormalClientBrowser.DecodeCodes", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
207
internal/db/models/formal_client_system_dao.go
Normal file
207
internal/db/models/formal_client_system_dao.go
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/utils/ttlcache"
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
FormalClientSystemStateEnabled = 1 // 已启用
|
||||||
|
FormalClientSystemStateDisabled = 0 // 已禁用
|
||||||
|
)
|
||||||
|
|
||||||
|
type FormalClientSystemDAO dbs.DAO
|
||||||
|
|
||||||
|
func NewFormalClientSystemDAO() *FormalClientSystemDAO {
|
||||||
|
return dbs.NewDAO(&FormalClientSystemDAO{
|
||||||
|
DAOObject: dbs.DAOObject{
|
||||||
|
DB: Tea.Env,
|
||||||
|
Table: "edgeFormalClientSystems",
|
||||||
|
Model: new(FormalClientSystem),
|
||||||
|
PkName: "id",
|
||||||
|
},
|
||||||
|
}).(*FormalClientSystemDAO)
|
||||||
|
}
|
||||||
|
|
||||||
|
var SharedFormalClientSystemDAO *FormalClientSystemDAO
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
dbs.OnReady(func() {
|
||||||
|
SharedFormalClientSystemDAO = NewFormalClientSystemDAO()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnableFormalClientSystem 启用条目
|
||||||
|
func (this *FormalClientSystemDAO) EnableFormalClientSystem(tx *dbs.Tx, id uint32) error {
|
||||||
|
_, err := this.Query(tx).
|
||||||
|
Pk(id).
|
||||||
|
Set("state", FormalClientSystemStateEnabled).
|
||||||
|
Update()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisableFormalClientSystem 禁用条目
|
||||||
|
func (this *FormalClientSystemDAO) DisableFormalClientSystem(tx *dbs.Tx, id uint32) error {
|
||||||
|
_, err := this.Query(tx).
|
||||||
|
Pk(id).
|
||||||
|
Set("state", FormalClientSystemStateDisabled).
|
||||||
|
Update()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindEnabledFormalClientSystem 查找启用中的条目
|
||||||
|
func (this *FormalClientSystemDAO) FindEnabledFormalClientSystem(tx *dbs.Tx, id int64) (*FormalClientSystem, error) {
|
||||||
|
result, err := this.Query(tx).
|
||||||
|
Pk(id).
|
||||||
|
State(FormalClientSystemStateEnabled).
|
||||||
|
Find()
|
||||||
|
if result == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result.(*FormalClientSystem), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindFormalClientSystemName 根据主键查找名称
|
||||||
|
func (this *FormalClientSystemDAO) FindFormalClientSystemName(tx *dbs.Tx, id uint32) (string, error) {
|
||||||
|
return this.Query(tx).
|
||||||
|
Pk(id).
|
||||||
|
Result("name").
|
||||||
|
FindStringCol("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindSystemIdWithNameCacheable 根据操作系统名称查找系统ID
|
||||||
|
func (this *FormalClientSystemDAO) FindSystemIdWithNameCacheable(tx *dbs.Tx, systemName string) (int64, error) {
|
||||||
|
var cacheKey = "formalClientSystem:" + systemName
|
||||||
|
var cacheItem = ttlcache.SharedCache.Read(cacheKey)
|
||||||
|
if cacheItem != nil {
|
||||||
|
return types.Int64(cacheItem.Value), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先使用 name 查找,因为有索引,所以会快一些
|
||||||
|
systemId, err := this.Query(tx).
|
||||||
|
Attr("name", systemName).
|
||||||
|
ResultPk().
|
||||||
|
FindInt64Col(0)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if systemId == 0 {
|
||||||
|
systemId, err = this.Query(tx).
|
||||||
|
Where("JSON_CONTAINS(codes, :systemName)").
|
||||||
|
Param("systemName", strconv.Quote(systemName)). // 查询的需要是个JSON字符串,所以这里加双引号
|
||||||
|
ResultPk().
|
||||||
|
FindInt64Col(0)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 即使找不到也要放入到缓存中
|
||||||
|
ttlcache.SharedCache.Write(cacheKey, systemId, time.Now().Unix()+3600)
|
||||||
|
|
||||||
|
return systemId, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateSystem 创建操作系统信息
|
||||||
|
func (this *FormalClientSystemDAO) CreateSystem(tx *dbs.Tx, name string, codes []string, dataId string) (int64, error) {
|
||||||
|
if len(dataId) == 0 {
|
||||||
|
return 0, errors.New("invalid dataId")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查 dataId 是否已经存在
|
||||||
|
exists, err := this.Query(tx).
|
||||||
|
Attr("dataId", dataId).
|
||||||
|
Exist()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if exists {
|
||||||
|
return 0, errors.New("dataId '" + dataId + "' already exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
var op = NewFormalClientSystemOperator()
|
||||||
|
op.Name = name
|
||||||
|
if len(codes) == 0 {
|
||||||
|
op.Codes = "[]"
|
||||||
|
} else {
|
||||||
|
codesJSON, err := json.Marshal(codes)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
op.Codes = codesJSON
|
||||||
|
}
|
||||||
|
op.DataId = dataId
|
||||||
|
op.State = FormalClientSystemStateEnabled
|
||||||
|
return this.SaveInt64(tx, op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateSystem 修改操作系统信息
|
||||||
|
func (this *FormalClientSystemDAO) UpdateSystem(tx *dbs.Tx, systemId int64, name string, codes []string, dataId string) error {
|
||||||
|
if systemId <= 0 {
|
||||||
|
return errors.New("invalid systemId '" + types.String(systemId) + "'")
|
||||||
|
}
|
||||||
|
if len(dataId) == 0 {
|
||||||
|
return errors.New("invalid dataId")
|
||||||
|
}
|
||||||
|
|
||||||
|
var op = NewFormalClientSystemOperator()
|
||||||
|
op.Id = systemId
|
||||||
|
op.Name = name
|
||||||
|
if len(codes) == 0 {
|
||||||
|
op.Codes = "[]"
|
||||||
|
} else {
|
||||||
|
codesJSON, err := json.Marshal(codes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
op.Codes = codesJSON
|
||||||
|
}
|
||||||
|
op.DataId = dataId
|
||||||
|
return this.Save(tx, op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountSystems 计算操作系统数量
|
||||||
|
func (this *FormalClientSystemDAO) CountSystems(tx *dbs.Tx, keyword string) (int64, error) {
|
||||||
|
var query = this.Query(tx)
|
||||||
|
if len(keyword) > 0 {
|
||||||
|
query.Like("LOWER(codes)", dbutils.QuoteLikeKeyword(strings.ToLower(keyword)))
|
||||||
|
}
|
||||||
|
return query.Count()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListSystems 列出单页操作系统信息
|
||||||
|
func (this *FormalClientSystemDAO) ListSystems(tx *dbs.Tx, keyword string, offset int64, size int64) (result []*FormalClientSystem, err error) {
|
||||||
|
var query = this.Query(tx)
|
||||||
|
if len(keyword) > 0 {
|
||||||
|
query.Like("LOWER(codes)", dbutils.QuoteLikeKeyword(strings.ToLower(keyword)))
|
||||||
|
}
|
||||||
|
_, err = query.
|
||||||
|
Offset(offset).
|
||||||
|
Limit(size).
|
||||||
|
DescPk().
|
||||||
|
Slice(&result).
|
||||||
|
FindAll()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindSystemWithDataId 根据dataId查找操作系统信息
|
||||||
|
func (this *FormalClientSystemDAO) FindSystemWithDataId(tx *dbs.Tx, dataId string) (*FormalClientSystem, error) {
|
||||||
|
one, err := this.Query(tx).
|
||||||
|
Attr("dataId", dataId).
|
||||||
|
Find()
|
||||||
|
if err != nil || one == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return one.(*FormalClientSystem), nil
|
||||||
|
}
|
||||||
6
internal/db/models/formal_client_system_dao_test.go
Normal file
6
internal/db/models/formal_client_system_dao_test.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package models_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
|
)
|
||||||
24
internal/db/models/formal_client_system_model.go
Normal file
24
internal/db/models/formal_client_system_model.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "github.com/iwind/TeaGo/dbs"
|
||||||
|
|
||||||
|
// FormalClientSystem 终端操作系统信息
|
||||||
|
type FormalClientSystem struct {
|
||||||
|
Id uint32 `field:"id"` // ID
|
||||||
|
Name string `field:"name"` // 系统名称
|
||||||
|
Codes dbs.JSON `field:"codes"` // 代号
|
||||||
|
State uint8 `field:"state"` // 状态
|
||||||
|
DataId string `field:"dataId"` // 数据ID
|
||||||
|
}
|
||||||
|
|
||||||
|
type FormalClientSystemOperator struct {
|
||||||
|
Id any // ID
|
||||||
|
Name any // 系统名称
|
||||||
|
Codes any // 代号
|
||||||
|
State any // 状态
|
||||||
|
DataId any // 数据ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFormalClientSystemOperator() *FormalClientSystemOperator {
|
||||||
|
return &FormalClientSystemOperator{}
|
||||||
|
}
|
||||||
21
internal/db/models/formal_client_system_model_ext.go
Normal file
21
internal/db/models/formal_client_system_model_ext.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DecodeCodes 解析代号
|
||||||
|
func (this *FormalClientSystem) DecodeCodes() []string {
|
||||||
|
if IsNull(this.Codes) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = []string{}
|
||||||
|
err := json.Unmarshal(this.Codes, &result)
|
||||||
|
if err != nil {
|
||||||
|
remotelogs.Error("FormalClientSystem.DecodeCodes", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -460,6 +460,7 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx,
|
|||||||
var requestPathReg = regexp.MustCompile(`requestPath:(\S+)`)
|
var requestPathReg = regexp.MustCompile(`requestPath:(\S+)`)
|
||||||
var protoReg = regexp.MustCompile(`proto:(\S+)`)
|
var protoReg = regexp.MustCompile(`proto:(\S+)`)
|
||||||
var schemeReg = regexp.MustCompile(`scheme:(\S+)`)
|
var schemeReg = regexp.MustCompile(`scheme:(\S+)`)
|
||||||
|
var methodReg = regexp.MustCompile(`(?:method|requestMethod):(\S+)`)
|
||||||
|
|
||||||
var count = len(tableQueries)
|
var count = len(tableQueries)
|
||||||
var wg = &sync.WaitGroup{}
|
var wg = &sync.WaitGroup{}
|
||||||
@@ -607,6 +608,11 @@ func (this *HTTPAccessLogDAO) listAccessLogs(tx *dbs.Tx,
|
|||||||
query.Where("JSON_EXTRACT(content, '$.requestURI') LIKE :keyword").
|
query.Where("JSON_EXTRACT(content, '$.requestURI') LIKE :keyword").
|
||||||
Param("keyword", dbutils.QuoteLikePrefix("\""+u.RequestURI()))
|
Param("keyword", dbutils.QuoteLikePrefix("\""+u.RequestURI()))
|
||||||
}
|
}
|
||||||
|
} else if methodReg.MatchString(keyword) { // method|requestMethod:xxx
|
||||||
|
isSpecialKeyword = true
|
||||||
|
var matches = methodReg.FindStringSubmatch(keyword)
|
||||||
|
query.Where("JSON_EXTRACT(content, '$.requestMethod')=:keyword").
|
||||||
|
Param("keyword", strings.ToUpper(matches[1]))
|
||||||
}
|
}
|
||||||
if !isSpecialKeyword {
|
if !isSpecialKeyword {
|
||||||
if regexp.MustCompile(`^ip:.+`).MatchString(keyword) {
|
if regexp.MustCompile(`^ip:.+`).MatchString(keyword) {
|
||||||
|
|||||||
73
internal/db/models/nameservers/ns_record_dao.go
Normal file
73
internal/db/models/nameservers/ns_record_dao.go
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
//go:build !plus
|
||||||
|
|
||||||
|
package nameservers
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
NSRecordStateEnabled = 1 // 已启用
|
||||||
|
NSRecordStateDisabled = 0 // 已禁用
|
||||||
|
)
|
||||||
|
|
||||||
|
type NSRecordDAO dbs.DAO
|
||||||
|
|
||||||
|
func NewNSRecordDAO() *NSRecordDAO {
|
||||||
|
return dbs.NewDAO(&NSRecordDAO{
|
||||||
|
DAOObject: dbs.DAOObject{
|
||||||
|
DB: Tea.Env,
|
||||||
|
Table: "edgeNSRecords",
|
||||||
|
Model: new(NSRecord),
|
||||||
|
PkName: "id",
|
||||||
|
},
|
||||||
|
}).(*NSRecordDAO)
|
||||||
|
}
|
||||||
|
|
||||||
|
var SharedNSRecordDAO *NSRecordDAO
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
dbs.OnReady(func() {
|
||||||
|
SharedNSRecordDAO = NewNSRecordDAO()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnableNSRecord 启用条目
|
||||||
|
func (this *NSRecordDAO) EnableNSRecord(tx *dbs.Tx, id uint64) error {
|
||||||
|
_, err := this.Query(tx).
|
||||||
|
Pk(id).
|
||||||
|
Set("state", NSRecordStateEnabled).
|
||||||
|
Update()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisableNSRecord 禁用条目
|
||||||
|
func (this *NSRecordDAO) DisableNSRecord(tx *dbs.Tx, id uint64) error {
|
||||||
|
_, err := this.Query(tx).
|
||||||
|
Pk(id).
|
||||||
|
Set("state", NSRecordStateDisabled).
|
||||||
|
Update()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindEnabledNSRecord 查找启用中的条目
|
||||||
|
func (this *NSRecordDAO) FindEnabledNSRecord(tx *dbs.Tx, id uint64) (*NSRecord, error) {
|
||||||
|
result, err := this.Query(tx).
|
||||||
|
Pk(id).
|
||||||
|
State(NSRecordStateEnabled).
|
||||||
|
Find()
|
||||||
|
if result == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result.(*NSRecord), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindNSRecordName 根据主键查找名称
|
||||||
|
func (this *NSRecordDAO) FindNSRecordName(tx *dbs.Tx, id uint64) (string, error) {
|
||||||
|
return this.Query(tx).
|
||||||
|
Pk(id).
|
||||||
|
Result("name").
|
||||||
|
FindStringCol("")
|
||||||
|
}
|
||||||
6
internal/db/models/nameservers/ns_record_dao_test.go
Normal file
6
internal/db/models/nameservers/ns_record_dao_test.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package nameservers_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
|
)
|
||||||
@@ -11,28 +11,30 @@ type NSRecord struct {
|
|||||||
Name string `field:"name"` // 记录名
|
Name string `field:"name"` // 记录名
|
||||||
Type string `field:"type"` // 类型
|
Type string `field:"type"` // 类型
|
||||||
Value string `field:"value"` // 值
|
Value string `field:"value"` // 值
|
||||||
|
MxPriority uint32 `field:"mxPriority"` // MX优先级
|
||||||
Ttl uint32 `field:"ttl"` // TTL(秒)
|
Ttl uint32 `field:"ttl"` // TTL(秒)
|
||||||
Weight uint32 `field:"weight"` // 权重
|
Weight uint32 `field:"weight"` // 权重
|
||||||
RouteIds dbs.JSON `field:"routeIds"` // 线路
|
RouteIds dbs.JSON `field:"routeIds"` // 线路
|
||||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||||
Version uint64 `field:"version"` //
|
Version uint64 `field:"version"` // 版本号
|
||||||
State uint8 `field:"state"` // 状态
|
State uint8 `field:"state"` // 状态
|
||||||
}
|
}
|
||||||
|
|
||||||
type NSRecordOperator struct {
|
type NSRecordOperator struct {
|
||||||
Id interface{} // ID
|
Id any // ID
|
||||||
DomainId interface{} // 域名ID
|
DomainId any // 域名ID
|
||||||
IsOn interface{} // 是否启用
|
IsOn any // 是否启用
|
||||||
Description interface{} // 备注
|
Description any // 备注
|
||||||
Name interface{} // 记录名
|
Name any // 记录名
|
||||||
Type interface{} // 类型
|
Type any // 类型
|
||||||
Value interface{} // 值
|
Value any // 值
|
||||||
Ttl interface{} // TTL(秒)
|
MxPriority any // MX优先级
|
||||||
Weight interface{} // 权重
|
Ttl any // TTL(秒)
|
||||||
RouteIds interface{} // 线路
|
Weight any // 权重
|
||||||
CreatedAt interface{} // 创建时间
|
RouteIds any // 线路
|
||||||
Version interface{} //
|
CreatedAt any // 创建时间
|
||||||
State interface{} // 状态
|
Version any // 版本号
|
||||||
|
State any // 状态
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNSRecordOperator() *NSRecordOperator {
|
func NewNSRecordOperator() *NSRecordOperator {
|
||||||
|
|||||||
33
internal/db/models/nameservers/ns_route_category_dao.go
Normal file
33
internal/db/models/nameservers/ns_route_category_dao.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package nameservers
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
NSRouteCategoryStateEnabled = 1 // 已启用
|
||||||
|
NSRouteCategoryStateDisabled = 0 // 已禁用
|
||||||
|
)
|
||||||
|
|
||||||
|
type NSRouteCategoryDAO dbs.DAO
|
||||||
|
|
||||||
|
func NewNSRouteCategoryDAO() *NSRouteCategoryDAO {
|
||||||
|
return dbs.NewDAO(&NSRouteCategoryDAO{
|
||||||
|
DAOObject: dbs.DAOObject{
|
||||||
|
DB: Tea.Env,
|
||||||
|
Table: "edgeNSRouteCategories",
|
||||||
|
Model: new(NSRouteCategory),
|
||||||
|
PkName: "id",
|
||||||
|
},
|
||||||
|
}).(*NSRouteCategoryDAO)
|
||||||
|
}
|
||||||
|
|
||||||
|
var SharedNSRouteCategoryDAO *NSRouteCategoryDAO
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
dbs.OnReady(func() {
|
||||||
|
SharedNSRouteCategoryDAO = NewNSRouteCategoryDAO()
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package nameservers_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
|
)
|
||||||
26
internal/db/models/nameservers/ns_route_category_model.go
Normal file
26
internal/db/models/nameservers/ns_route_category_model.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package nameservers
|
||||||
|
|
||||||
|
// NSRouteCategory 线路分类
|
||||||
|
type NSRouteCategory struct {
|
||||||
|
Id uint64 `field:"id"` // ID
|
||||||
|
IsOn bool `field:"isOn"` // 是否启用
|
||||||
|
Name string `field:"name"` // 分类名
|
||||||
|
AdminId uint64 `field:"adminId"` // 管理员ID
|
||||||
|
UserId uint64 `field:"userId"` // 用户ID
|
||||||
|
Order uint32 `field:"order"` // 排序
|
||||||
|
State uint8 `field:"state"` // 状态
|
||||||
|
}
|
||||||
|
|
||||||
|
type NSRouteCategoryOperator struct {
|
||||||
|
Id any // ID
|
||||||
|
IsOn any // 是否启用
|
||||||
|
Name any // 分类名
|
||||||
|
AdminId any // 管理员ID
|
||||||
|
UserId any // 用户ID
|
||||||
|
Order any // 排序
|
||||||
|
State any // 状态
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNSRouteCategoryOperator() *NSRouteCategoryOperator {
|
||||||
|
return &NSRouteCategoryOperator{}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
package nameservers
|
||||||
73
internal/db/models/nameservers/ns_route_dao.go
Normal file
73
internal/db/models/nameservers/ns_route_dao.go
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
//go:build !plus
|
||||||
|
|
||||||
|
package nameservers
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
NSRouteStateEnabled = 1 // 已启用
|
||||||
|
NSRouteStateDisabled = 0 // 已禁用
|
||||||
|
)
|
||||||
|
|
||||||
|
type NSRouteDAO dbs.DAO
|
||||||
|
|
||||||
|
func NewNSRouteDAO() *NSRouteDAO {
|
||||||
|
return dbs.NewDAO(&NSRouteDAO{
|
||||||
|
DAOObject: dbs.DAOObject{
|
||||||
|
DB: Tea.Env,
|
||||||
|
Table: "edgeNSRoutes",
|
||||||
|
Model: new(NSRoute),
|
||||||
|
PkName: "id",
|
||||||
|
},
|
||||||
|
}).(*NSRouteDAO)
|
||||||
|
}
|
||||||
|
|
||||||
|
var SharedNSRouteDAO *NSRouteDAO
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
dbs.OnReady(func() {
|
||||||
|
SharedNSRouteDAO = NewNSRouteDAO()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnableNSRoute 启用条目
|
||||||
|
func (this *NSRouteDAO) EnableNSRoute(tx *dbs.Tx, id uint32) error {
|
||||||
|
_, err := this.Query(tx).
|
||||||
|
Pk(id).
|
||||||
|
Set("state", NSRouteStateEnabled).
|
||||||
|
Update()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisableNSRoute 禁用条目
|
||||||
|
func (this *NSRouteDAO) DisableNSRoute(tx *dbs.Tx, id uint32) error {
|
||||||
|
_, err := this.Query(tx).
|
||||||
|
Pk(id).
|
||||||
|
Set("state", NSRouteStateDisabled).
|
||||||
|
Update()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindEnabledNSRoute 查找启用中的条目
|
||||||
|
func (this *NSRouteDAO) FindEnabledNSRoute(tx *dbs.Tx, id uint32) (*NSRoute, error) {
|
||||||
|
result, err := this.Query(tx).
|
||||||
|
Pk(id).
|
||||||
|
State(NSRouteStateEnabled).
|
||||||
|
Find()
|
||||||
|
if result == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result.(*NSRoute), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindNSRouteName 根据主键查找名称
|
||||||
|
func (this *NSRouteDAO) FindNSRouteName(tx *dbs.Tx, id uint32) (string, error) {
|
||||||
|
return this.Query(tx).
|
||||||
|
Pk(id).
|
||||||
|
Result("name").
|
||||||
|
FindStringCol("")
|
||||||
|
}
|
||||||
6
internal/db/models/nameservers/ns_route_dao_test.go
Normal file
6
internal/db/models/nameservers/ns_route_dao_test.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package nameservers_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
|
)
|
||||||
@@ -4,31 +4,37 @@ import "github.com/iwind/TeaGo/dbs"
|
|||||||
|
|
||||||
// NSRoute DNS线路
|
// NSRoute DNS线路
|
||||||
type NSRoute struct {
|
type NSRoute struct {
|
||||||
Id uint32 `field:"id"` // ID
|
Id uint32 `field:"id"` // ID
|
||||||
IsOn bool `field:"isOn"` // 是否启用
|
IsOn bool `field:"isOn"` // 是否启用
|
||||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||||
DomainId uint32 `field:"domainId"` // 域名ID
|
CategoryId uint32 `field:"categoryId"` // 分类ID
|
||||||
UserId uint32 `field:"userId"` // 用户ID
|
DomainId uint64 `field:"domainId"` // 域名ID
|
||||||
Name string `field:"name"` // 名称
|
AdminId uint64 `field:"adminId"` // 管理员ID
|
||||||
Ranges dbs.JSON `field:"ranges"` // 范围
|
UserId uint64 `field:"userId"` // 用户ID
|
||||||
Order uint32 `field:"order"` // 排序
|
IsPublic bool `field:"isPublic"` // 是否公用(管理员创建的线路)
|
||||||
Version uint64 `field:"version"` // 版本号
|
Name string `field:"name"` // 名称
|
||||||
Code string `field:"code"` // 代号
|
Ranges dbs.JSON `field:"ranges"` // 范围
|
||||||
State uint8 `field:"state"` // 状态
|
Order uint32 `field:"order"` // 排序
|
||||||
|
Version uint64 `field:"version"` // 版本号
|
||||||
|
Code string `field:"code"` // 代号
|
||||||
|
State uint8 `field:"state"` // 状态
|
||||||
}
|
}
|
||||||
|
|
||||||
type NSRouteOperator struct {
|
type NSRouteOperator struct {
|
||||||
Id interface{} // ID
|
Id any // ID
|
||||||
IsOn interface{} // 是否启用
|
IsOn any // 是否启用
|
||||||
ClusterId interface{} // 集群ID
|
ClusterId any // 集群ID
|
||||||
DomainId interface{} // 域名ID
|
CategoryId any // 分类ID
|
||||||
UserId interface{} // 用户ID
|
DomainId any // 域名ID
|
||||||
Name interface{} // 名称
|
AdminId any // 管理员ID
|
||||||
Ranges interface{} // 范围
|
UserId any // 用户ID
|
||||||
Order interface{} // 排序
|
IsPublic any // 是否公用(管理员创建的线路)
|
||||||
Version interface{} // 版本号
|
Name any // 名称
|
||||||
Code interface{} // 代号
|
Ranges any // 范围
|
||||||
State interface{} // 状态
|
Order any // 排序
|
||||||
|
Version any // 版本号
|
||||||
|
Code any // 代号
|
||||||
|
State any // 状态
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNSRouteOperator() *NSRouteOperator {
|
func NewNSRouteOperator() *NSRouteOperator {
|
||||||
|
|||||||
@@ -437,7 +437,7 @@ func (this *NodeClusterDAO) FindAllEnabledClustersWithDNSDomainId(tx *dbs.Tx, dn
|
|||||||
_, err = this.Query(tx).
|
_, err = this.Query(tx).
|
||||||
State(NodeClusterStateEnabled).
|
State(NodeClusterStateEnabled).
|
||||||
Attr("dnsDomainId", dnsDomainId).
|
Attr("dnsDomainId", dnsDomainId).
|
||||||
Result("id", "name", "dnsName", "dnsDomainId", "isOn").
|
Result("id", "name", "dnsName", "dnsDomainId", "isOn", "dns").
|
||||||
Slice(&result).
|
Slice(&result).
|
||||||
FindAll()
|
FindAll()
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -961,6 +961,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
|
|||||||
Level: types.Int32(node.Level),
|
Level: types.Int32(node.Level),
|
||||||
GroupId: int64(node.GroupId),
|
GroupId: int64(node.GroupId),
|
||||||
EnableIPLists: node.EnableIPLists,
|
EnableIPLists: node.EnableIPLists,
|
||||||
|
APINodeAddrs: node.DecodeAPINodeAddrs(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// API节点IP
|
// API节点IP
|
||||||
@@ -1146,6 +1147,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
|
|||||||
}
|
}
|
||||||
|
|
||||||
config.CacheDiskDir = node.CacheDiskDir
|
config.CacheDiskDir = node.CacheDiskDir
|
||||||
|
config.CacheDiskSubDirs = node.DecodeCacheDiskSubDirs()
|
||||||
|
|
||||||
// TOA
|
// TOA
|
||||||
toaConfig, err := SharedNodeClusterDAO.FindClusterTOAConfig(tx, primaryClusterId, cacheMap)
|
toaConfig, err := SharedNodeClusterDAO.FindClusterTOAConfig(tx, primaryClusterId, cacheMap)
|
||||||
@@ -1621,7 +1623,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, cacheDiskDir string) error {
|
func (this *NodeDAO) UpdateNodeCache(tx *dbs.Tx, nodeId int64, maxCacheDiskCapacityJSON []byte, maxCacheMemoryCapacityJSON []byte, cacheDiskDir string, cacheDiskSubDirs []*serverconfigs.CacheDir) error {
|
||||||
if nodeId <= 0 {
|
if nodeId <= 0 {
|
||||||
return errors.New("invalid nodeId")
|
return errors.New("invalid nodeId")
|
||||||
}
|
}
|
||||||
@@ -1634,7 +1636,17 @@ func (this *NodeDAO) UpdateNodeCache(tx *dbs.Tx, nodeId int64, maxCacheDiskCapac
|
|||||||
op.MaxCacheMemoryCapacity = maxCacheMemoryCapacityJSON
|
op.MaxCacheMemoryCapacity = maxCacheMemoryCapacityJSON
|
||||||
}
|
}
|
||||||
op.CacheDiskDir = cacheDiskDir
|
op.CacheDiskDir = cacheDiskDir
|
||||||
err := this.Save(tx, op)
|
|
||||||
|
if cacheDiskSubDirs == nil {
|
||||||
|
cacheDiskSubDirs = []*serverconfigs.CacheDir{}
|
||||||
|
}
|
||||||
|
cacheDiskSubDirsJSON, err := json.Marshal(cacheDiskSubDirs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
op.CacheDiskSubDirs = cacheDiskSubDirsJSON
|
||||||
|
|
||||||
|
err = this.Save(tx, op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -1827,6 +1839,12 @@ func (this *NodeDAO) DeleteNodeFromCluster(tx *dbs.Tx, nodeId int64, clusterId i
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 提前通知DNS更新,因为后面集群会有变化
|
||||||
|
err = this.NotifyDNSUpdate(tx, nodeId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
var node = one.(*Node)
|
var node = one.(*Node)
|
||||||
|
|
||||||
var secondaryClusterIds = []int64{}
|
var secondaryClusterIds = []int64{}
|
||||||
@@ -2022,11 +2040,51 @@ func (this *NodeDAO) UpdateNodeDDoSProtection(tx *dbs.Tx, nodeId int64, ddosProt
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if clusterId > 0 {
|
if clusterId > 0 {
|
||||||
return SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, 0, 0, NodeTaskTypeDDosProtectionChanged, 0)
|
return SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, 0, 0, NodeTaskTypeDDosProtectionChanged)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindNodeAPIConfig 查找API相关配置信息
|
||||||
|
func (this *NodeDAO) FindNodeAPIConfig(tx *dbs.Tx, nodeId int64) (*Node, error) {
|
||||||
|
if nodeId <= 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
one, err := this.Query(tx).
|
||||||
|
Pk(nodeId).
|
||||||
|
Result("apiNodeAddrs").
|
||||||
|
Find()
|
||||||
|
if err != nil || one == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return one.(*Node), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateNodeAPIConfig 修改API相关配置信息
|
||||||
|
func (this *NodeDAO) UpdateNodeAPIConfig(tx *dbs.Tx, nodeId int64, apiNodeAddrs []*serverconfigs.NetworkAddressConfig) error {
|
||||||
|
if nodeId <= 0 {
|
||||||
|
return errors.New("invalid nodeId")
|
||||||
|
}
|
||||||
|
|
||||||
|
if apiNodeAddrs == nil {
|
||||||
|
apiNodeAddrs = []*serverconfigs.NetworkAddressConfig{}
|
||||||
|
}
|
||||||
|
apiNodeAddrsJSON, err := json.Marshal(apiNodeAddrs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var op = NewNodeOperator()
|
||||||
|
op.Id = nodeId
|
||||||
|
op.ApiNodeAddrs = apiNodeAddrsJSON
|
||||||
|
err = this.Save(tx, op)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.NotifyUpdate(tx, nodeId)
|
||||||
|
}
|
||||||
|
|
||||||
// NotifyUpdate 通知节点相关更新
|
// NotifyUpdate 通知节点相关更新
|
||||||
func (this *NodeDAO) NotifyUpdate(tx *dbs.Tx, nodeId int64) error {
|
func (this *NodeDAO) NotifyUpdate(tx *dbs.Tx, nodeId int64) error {
|
||||||
// 这里只需要通知单个集群即可,因为节点是公用的,更新一个就相当于更新了所有
|
// 这里只需要通知单个集群即可,因为节点是公用的,更新一个就相当于更新了所有
|
||||||
@@ -2034,7 +2092,7 @@ func (this *NodeDAO) NotifyUpdate(tx *dbs.Tx, nodeId int64) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, 0, 0, NodeTaskTypeConfigChanged, 0)
|
err = SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, 0, 0, NodeTaskTypeConfigChanged)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -2075,7 +2133,7 @@ func (this *NodeDAO) NotifyDNSUpdate(tx *dbs.Tx, nodeId int64) error {
|
|||||||
if len(dnsInfo.DnsName) == 0 || dnsInfo.DnsDomainId <= 0 {
|
if len(dnsInfo.DnsName) == 0 || dnsInfo.DnsDomainId <= 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
err = dns.SharedDNSTaskDAO.CreateNodeTask(tx, nodeId, dns.DNSTaskTypeNodeChange)
|
err = dns.SharedDNSTaskDAO.CreateNodeTask(tx, clusterId, nodeId, dns.DNSTaskTypeNodeChange)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -604,7 +604,7 @@ func (this *NodeIPAddressDAO) NotifyUpdate(tx *dbs.Tx, addressId int64) error {
|
|||||||
var role = address.(*NodeIPAddress).Role
|
var role = address.(*NodeIPAddress).Role
|
||||||
switch role {
|
switch role {
|
||||||
case nodeconfigs.NodeRoleNode:
|
case nodeconfigs.NodeRoleNode:
|
||||||
err = dns.SharedDNSTaskDAO.CreateNodeTask(tx, nodeId, dns.DNSTaskTypeNodeChange)
|
err = dns.SharedDNSTaskDAO.CreateNodeTask(tx, 0, nodeId, dns.DNSTaskTypeNodeChange)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,9 +38,11 @@ type Node struct {
|
|||||||
DnsRoutes dbs.JSON `field:"dnsRoutes"` // DNS线路设置
|
DnsRoutes dbs.JSON `field:"dnsRoutes"` // DNS线路设置
|
||||||
MaxCacheDiskCapacity dbs.JSON `field:"maxCacheDiskCapacity"` // 硬盘缓存容量
|
MaxCacheDiskCapacity dbs.JSON `field:"maxCacheDiskCapacity"` // 硬盘缓存容量
|
||||||
MaxCacheMemoryCapacity dbs.JSON `field:"maxCacheMemoryCapacity"` // 内存缓存容量
|
MaxCacheMemoryCapacity dbs.JSON `field:"maxCacheMemoryCapacity"` // 内存缓存容量
|
||||||
CacheDiskDir string `field:"cacheDiskDir"` // 缓存目录
|
CacheDiskDir string `field:"cacheDiskDir"` // 主缓存目录
|
||||||
|
CacheDiskSubDirs dbs.JSON `field:"cacheDiskSubDirs"` // 其他缓存目录
|
||||||
DnsResolver dbs.JSON `field:"dnsResolver"` // DNS解析器
|
DnsResolver dbs.JSON `field:"dnsResolver"` // DNS解析器
|
||||||
EnableIPLists bool `field:"enableIPLists"` // 启用IP名单
|
EnableIPLists bool `field:"enableIPLists"` // 启用IP名单
|
||||||
|
ApiNodeAddrs dbs.JSON `field:"apiNodeAddrs"` // API节点地址
|
||||||
}
|
}
|
||||||
|
|
||||||
type NodeOperator struct {
|
type NodeOperator struct {
|
||||||
@@ -78,9 +80,11 @@ type NodeOperator struct {
|
|||||||
DnsRoutes any // DNS线路设置
|
DnsRoutes any // DNS线路设置
|
||||||
MaxCacheDiskCapacity any // 硬盘缓存容量
|
MaxCacheDiskCapacity any // 硬盘缓存容量
|
||||||
MaxCacheMemoryCapacity any // 内存缓存容量
|
MaxCacheMemoryCapacity any // 内存缓存容量
|
||||||
CacheDiskDir any // 缓存目录
|
CacheDiskDir any // 主缓存目录
|
||||||
|
CacheDiskSubDirs any // 其他缓存目录
|
||||||
DnsResolver any // DNS解析器
|
DnsResolver any // DNS解析器
|
||||||
EnableIPLists any // 启用IP名单
|
EnableIPLists any // 启用IP名单
|
||||||
|
ApiNodeAddrs any // API节点地址
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNodeOperator() *NodeOperator {
|
func NewNodeOperator() *NodeOperator {
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package models
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -135,6 +137,7 @@ func (this *Node) HasDDoSProtection() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeMaxCacheDiskCapacity 解析硬盘容量
|
||||||
func (this *Node) DecodeMaxCacheDiskCapacity() *shared.SizeCapacity {
|
func (this *Node) DecodeMaxCacheDiskCapacity() *shared.SizeCapacity {
|
||||||
if this.MaxCacheDiskCapacity.IsNull() {
|
if this.MaxCacheDiskCapacity.IsNull() {
|
||||||
return nil
|
return nil
|
||||||
@@ -145,6 +148,7 @@ func (this *Node) DecodeMaxCacheDiskCapacity() *shared.SizeCapacity {
|
|||||||
return capacity
|
return capacity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeMaxCacheMemoryCapacity 解析内存容量
|
||||||
func (this *Node) DecodeMaxCacheMemoryCapacity() *shared.SizeCapacity {
|
func (this *Node) DecodeMaxCacheMemoryCapacity() *shared.SizeCapacity {
|
||||||
if this.MaxCacheMemoryCapacity.IsNull() {
|
if this.MaxCacheMemoryCapacity.IsNull() {
|
||||||
return nil
|
return nil
|
||||||
@@ -169,6 +173,7 @@ func (this *Node) DecodeDNSResolver() *nodeconfigs.DNSResolverConfig {
|
|||||||
return resolverConfig
|
return resolverConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeLnAddrs 解析Ln地址
|
||||||
func (this *Node) DecodeLnAddrs() []string {
|
func (this *Node) DecodeLnAddrs() []string {
|
||||||
if IsNull(this.LnAddrs) {
|
if IsNull(this.LnAddrs) {
|
||||||
return nil
|
return nil
|
||||||
@@ -181,3 +186,31 @@ func (this *Node) DecodeLnAddrs() []string {
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeCacheDiskSubDirs 解析缓存目录
|
||||||
|
func (this *Node) DecodeCacheDiskSubDirs() []*serverconfigs.CacheDir {
|
||||||
|
if IsNull(this.CacheDiskSubDirs) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = []*serverconfigs.CacheDir{}
|
||||||
|
err := json.Unmarshal(this.CacheDiskSubDirs, &result)
|
||||||
|
if err != nil {
|
||||||
|
remotelogs.Error("Node.DecodeCacheDiskSubDirs", err.Error())
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeAPINodeAddrs 解析API节点地址
|
||||||
|
func (this *Node) DecodeAPINodeAddrs() []*serverconfigs.NetworkAddressConfig {
|
||||||
|
var result = []*serverconfigs.NetworkAddressConfig{}
|
||||||
|
if IsNull(this.ApiNodeAddrs) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.Unmarshal(this.ApiNodeAddrs, &result)
|
||||||
|
if err != nil {
|
||||||
|
remotelogs.Error("Node.DecodeAPINodeAddrs", err.Error())
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateNodeTask 创建单个节点任务
|
// CreateNodeTask 创建单个节点任务
|
||||||
func (this *NodeTaskDAO) CreateNodeTask(tx *dbs.Tx, role string, clusterId int64, nodeId int64, userId int64, serverId int64, taskType NodeTaskType, version int64) error {
|
func (this *NodeTaskDAO) CreateNodeTask(tx *dbs.Tx, role string, clusterId int64, nodeId int64, userId int64, serverId int64, taskType NodeTaskType) error {
|
||||||
if clusterId <= 0 || nodeId <= 0 {
|
if clusterId <= 0 || nodeId <= 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -69,8 +69,13 @@ func (this *NodeTaskDAO) CreateNodeTask(tx *dbs.Tx, role string, clusterId int64
|
|||||||
uniqueId += "@" + types.String(userId)
|
uniqueId += "@" + types.String(userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version, err := this.increaseVersion(tx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
var 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,
|
||||||
@@ -157,9 +162,8 @@ func (this *NodeTaskDAO) ExtractNodeClusterTask(tx *dbs.Tx, clusterId int64, use
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var version = time.Now().UnixNano()
|
|
||||||
for _, nodeId := range nodeIds {
|
for _, nodeId := range nodeIds {
|
||||||
err = this.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, userId, serverId, taskType, version)
|
err = this.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, userId, serverId, taskType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -225,14 +229,22 @@ func (this *NodeTaskDAO) DeleteNodeTasks(tx *dbs.Tx, role string, nodeId int64)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FindDoingNodeTasks 查询一个节点的所有任务
|
// FindDoingNodeTasks 查询一个节点的所有任务
|
||||||
func (this *NodeTaskDAO) FindDoingNodeTasks(tx *dbs.Tx, role string, nodeId int64) (result []*NodeTask, err error) {
|
func (this *NodeTaskDAO) FindDoingNodeTasks(tx *dbs.Tx, role string, nodeId int64, version int64) (result []*NodeTask, err error) {
|
||||||
if nodeId <= 0 {
|
if nodeId <= 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err = this.Query(tx).
|
var query = this.Query(tx).
|
||||||
Attr("role", role).
|
Attr("role", role).
|
||||||
Attr("nodeId", nodeId).
|
Attr("nodeId", nodeId).
|
||||||
Where("(isDone=0 OR (isDone=1 AND isOk=0))").
|
Asc("version")
|
||||||
|
if version > 0 {
|
||||||
|
query.Lt("LENGTH(version)", 19) // 兼容以往版本
|
||||||
|
query.Gt("version", version)
|
||||||
|
} else {
|
||||||
|
// 第一次访问时只取当前正在执行的或者执行失败的
|
||||||
|
query.Where("(isDone=0 OR (isDone=1 AND isOk=0))")
|
||||||
|
}
|
||||||
|
_, err = query.
|
||||||
Slice(&result).
|
Slice(&result).
|
||||||
FindAll()
|
FindAll()
|
||||||
return
|
return
|
||||||
@@ -240,8 +252,16 @@ func (this *NodeTaskDAO) FindDoingNodeTasks(tx *dbs.Tx, role string, nodeId int6
|
|||||||
|
|
||||||
// UpdateNodeTaskDone 修改节点任务的完成状态
|
// UpdateNodeTaskDone 修改节点任务的完成状态
|
||||||
func (this *NodeTaskDAO) UpdateNodeTaskDone(tx *dbs.Tx, taskId int64, isOk bool, errorMessage string) error {
|
func (this *NodeTaskDAO) UpdateNodeTaskDone(tx *dbs.Tx, taskId int64, isOk bool, errorMessage string) error {
|
||||||
_, err := this.Query(tx).
|
var query = this.Query(tx).
|
||||||
Pk(taskId).
|
Pk(taskId)
|
||||||
|
if !isOk {
|
||||||
|
version, err := this.increaseVersion(tx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
query.Set("version", version)
|
||||||
|
}
|
||||||
|
_, err := query.
|
||||||
Set("isDone", 1).
|
Set("isDone", 1).
|
||||||
Set("isOk", isOk).
|
Set("isOk", isOk).
|
||||||
Set("error", errorMessage).
|
Set("error", errorMessage).
|
||||||
@@ -373,3 +393,8 @@ func (this *NodeTaskDAO) UpdateTasksNotified(tx *dbs.Tx, taskIds []int64) error
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 生成一个版本号
|
||||||
|
func (this *NodeTaskDAO) increaseVersion(tx *dbs.Tx) (version int64, err error) {
|
||||||
|
return SharedSysLockerDAO.Increase(tx, "NODE_TASK_VERSION", 0)
|
||||||
|
}
|
||||||
|
|||||||
@@ -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, 0, 0, NodeTaskTypeConfigChanged, 0)
|
err := SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, 1, 2, 0, 0, NodeTaskTypeConfigChanged)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
6
internal/db/models/ns_node_dao_test.go
Normal file
6
internal/db/models/ns_node_dao_test.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package models_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
|
)
|
||||||
@@ -22,6 +22,7 @@ type NSNode struct {
|
|||||||
InactiveNotifiedAt uint64 `field:"inactiveNotifiedAt"` // 离线通知时间
|
InactiveNotifiedAt uint64 `field:"inactiveNotifiedAt"` // 离线通知时间
|
||||||
ConnectedAPINodes dbs.JSON `field:"connectedAPINodes"` // 当前连接的API节点
|
ConnectedAPINodes dbs.JSON `field:"connectedAPINodes"` // 当前连接的API节点
|
||||||
DdosProtection dbs.JSON `field:"ddosProtection"` // DDoS防护设置
|
DdosProtection dbs.JSON `field:"ddosProtection"` // DDoS防护设置
|
||||||
|
ApiNodeAddrs dbs.JSON `field:"apiNodeAddrs"` // API节点地址
|
||||||
}
|
}
|
||||||
|
|
||||||
type NSNodeOperator struct {
|
type NSNodeOperator struct {
|
||||||
@@ -43,6 +44,7 @@ type NSNodeOperator struct {
|
|||||||
InactiveNotifiedAt any // 离线通知时间
|
InactiveNotifiedAt any // 离线通知时间
|
||||||
ConnectedAPINodes any // 当前连接的API节点
|
ConnectedAPINodes any // 当前连接的API节点
|
||||||
DdosProtection any // DDoS防护设置
|
DdosProtection any // DDoS防护设置
|
||||||
|
ApiNodeAddrs any // API节点地址
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNSNodeOperator() *NSNodeOperator {
|
func NewNSNodeOperator() *NSNodeOperator {
|
||||||
|
|||||||
@@ -1,79 +1 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DecodeInstallStatus 安装状态
|
|
||||||
func (this *NSNode) DecodeInstallStatus() (*NodeInstallStatus, error) {
|
|
||||||
if len(this.InstallStatus) == 0 {
|
|
||||||
return NewNodeInstallStatus(), nil
|
|
||||||
}
|
|
||||||
status := &NodeInstallStatus{}
|
|
||||||
err := json.Unmarshal(this.InstallStatus, status)
|
|
||||||
if err != nil {
|
|
||||||
return NewNodeInstallStatus(), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果N秒钟没有更新状态,则认为不在运行
|
|
||||||
if status.IsRunning && status.UpdatedAt < time.Now().Unix()-10 {
|
|
||||||
status.IsRunning = false
|
|
||||||
status.IsFinished = true
|
|
||||||
status.Error = "timeout"
|
|
||||||
}
|
|
||||||
|
|
||||||
return status, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeStatus 节点状态
|
|
||||||
func (this *NSNode) DecodeStatus() (*nodeconfigs.NodeStatus, error) {
|
|
||||||
if len(this.Status) == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
status := &nodeconfigs.NodeStatus{}
|
|
||||||
err := json.Unmarshal(this.Status, status)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return status, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeDDoSProtection 解析DDoS Protection设置
|
|
||||||
func (this *NSNode) DecodeDDoSProtection() *ddosconfigs.ProtectionConfig {
|
|
||||||
if IsNull(this.DdosProtection) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = &ddosconfigs.ProtectionConfig{}
|
|
||||||
err := json.Unmarshal(this.DdosProtection, &result)
|
|
||||||
if err != nil {
|
|
||||||
// ignore err
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasDDoSProtection 检查是否有DDOS设置
|
|
||||||
func (this *NSNode) HasDDoSProtection() bool {
|
|
||||||
var config = this.DecodeDDoSProtection()
|
|
||||||
if config != nil {
|
|
||||||
return !config.IsPriorEmpty()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeConnectedAPINodes 解析连接的API节点列表
|
|
||||||
func (this *NSNode) DecodeConnectedAPINodes() []int64 {
|
|
||||||
if IsNull(this.ConnectedAPINodes) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = []int64{}
|
|
||||||
err := json.Unmarshal(this.ConnectedAPINodes, &result)
|
|
||||||
if err != nil {
|
|
||||||
// ignore err
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/iwind/TeaGo/types"
|
"github.com/iwind/TeaGo/types"
|
||||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
"math"
|
"math"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -452,6 +453,75 @@ func (this *ServerBandwidthStatDAO) FindPercentileBetweenDays(tx *dbs.Tx, server
|
|||||||
return one.(*ServerBandwidthStat), nil
|
return one.(*ServerBandwidthStat), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindPercentileBetweenTimes 获取时间段内内百分位
|
||||||
|
// timeFrom 开始时间,格式 YYYYMMDDHHII
|
||||||
|
// timeTo 结束时间,格式 YYYYMMDDHHII
|
||||||
|
func (this *ServerBandwidthStatDAO) FindPercentileBetweenTimes(tx *dbs.Tx, serverId int64, timeFrom string, timeTo string, percentile int32) (result *ServerBandwidthStat, err error) {
|
||||||
|
var reg = regexp.MustCompile(`^\d{12}$`)
|
||||||
|
if !reg.MatchString(timeFrom) {
|
||||||
|
return nil, errors.New("invalid timeFrom '" + timeFrom + "'")
|
||||||
|
}
|
||||||
|
if !reg.MatchString(timeTo) {
|
||||||
|
return nil, errors.New("invalid timeTo '" + timeTo + "'")
|
||||||
|
}
|
||||||
|
|
||||||
|
if timeFrom > timeTo {
|
||||||
|
timeFrom, timeTo = timeTo, timeFrom
|
||||||
|
}
|
||||||
|
|
||||||
|
if percentile <= 0 {
|
||||||
|
percentile = 95
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是100%以上,则快速返回
|
||||||
|
if percentile >= 100 {
|
||||||
|
one, err := this.Query(tx).
|
||||||
|
Table(this.partialTable(serverId)).
|
||||||
|
Attr("serverId", serverId).
|
||||||
|
Between("CONCAT(day, timeAt)", timeFrom, timeTo).
|
||||||
|
Desc("bytes").
|
||||||
|
Find()
|
||||||
|
if err != nil || one == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return one.(*ServerBandwidthStat), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 总数量
|
||||||
|
total, err := this.Query(tx).
|
||||||
|
Table(this.partialTable(serverId)).
|
||||||
|
Attr("serverId", serverId).
|
||||||
|
Between("CONCAT(day, timeAt)", timeFrom, timeTo).
|
||||||
|
Count()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if total == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var offset int64
|
||||||
|
|
||||||
|
if total > 1 {
|
||||||
|
offset = int64(math.Ceil(float64(total) * float64(100-percentile) / 100))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询 nth 位置
|
||||||
|
one, err := this.Query(tx).
|
||||||
|
Table(this.partialTable(serverId)).
|
||||||
|
Attr("serverId", serverId).
|
||||||
|
Between("CONCAT(day, timeAt)", timeFrom, timeTo).
|
||||||
|
Desc("bytes").
|
||||||
|
Offset(offset).
|
||||||
|
Find()
|
||||||
|
if err != nil || one == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return one.(*ServerBandwidthStat), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Clean 清理过期数据
|
// Clean 清理过期数据
|
||||||
func (this *ServerBandwidthStatDAO) Clean(tx *dbs.Tx) error {
|
func (this *ServerBandwidthStatDAO) Clean(tx *dbs.Tx) error {
|
||||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -100)) // 保留大约3个月的数据
|
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -100)) // 保留大约3个月的数据
|
||||||
|
|||||||
@@ -710,7 +710,10 @@ func (this *ServerDailyStatDAO) FindDistinctUserIds(tx *dbs.Tx, dayFrom string,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, one := range ones {
|
for _, one := range ones {
|
||||||
userIds = append(userIds, one.GetInt64("userId"))
|
var userId = one.GetInt64("userId")
|
||||||
|
if userId > 0 {
|
||||||
|
userIds = append(userIds, userId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return userIds, nil
|
return userIds, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ func (this *SSLCertDAO) ComposeCertConfig(tx *dbs.Tx, certId int64, cacheMap *ut
|
|||||||
if cacheMap == nil {
|
if cacheMap == nil {
|
||||||
cacheMap = utils.NewCacheMap()
|
cacheMap = utils.NewCacheMap()
|
||||||
}
|
}
|
||||||
var cacheKey = this.Table + ":config:" + types.String(certId)
|
var cacheKey = this.Table + ":ComposeCertConfig:" + types.String(certId)
|
||||||
var cache, _ = cacheMap.Get(cacheKey)
|
var cache, _ = cacheMap.Get(cacheKey)
|
||||||
if cache != nil {
|
if cache != nil {
|
||||||
return cache.(*sslconfigs.SSLCertConfig), nil
|
return cache.(*sslconfigs.SSLCertConfig), nil
|
||||||
@@ -600,6 +600,7 @@ func (this *SSLCertDAO) NotifyUpdate(tx *dbs.Tx, certId int64) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 通知服务更新
|
||||||
serverIds, err := SharedServerDAO.FindAllEnabledServerIdsWithSSLPolicyIds(tx, policyIds)
|
serverIds, err := SharedServerDAO.FindAllEnabledServerIdsWithSSLPolicyIds(tx, policyIds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -613,5 +614,8 @@ func (this *SSLCertDAO) NotifyUpdate(tx *dbs.Tx, certId int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO 通知用户节点、API节点、管理系统(将来实现选择)更新
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,6 +172,24 @@ func (this *SysSettingDAO) ReadAdminUIConfig(tx *dbs.Tx, cacheMap *utils.CacheMa
|
|||||||
return &systemconfigs.AdminUIConfig{}, nil
|
return &systemconfigs.AdminUIConfig{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadUserUIConfig 读取用户UI配置
|
||||||
|
func (this *SysSettingDAO) ReadUserUIConfig(tx *dbs.Tx) (*systemconfigs.UserUIConfig, error) {
|
||||||
|
valueJSON, err := this.ReadSetting(tx, systemconfigs.SettingCodeUserUIConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(valueJSON) == 0 {
|
||||||
|
return systemconfigs.DefaultUserUIConfig(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = systemconfigs.DefaultUserUIConfig()
|
||||||
|
err = json.Unmarshal(valueJSON, config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return config, 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 {
|
||||||
|
|||||||
@@ -304,7 +304,10 @@ func (this *UserBandwidthStatDAO) FindDistinctUserIds(tx *dbs.Tx, dayFrom string
|
|||||||
|
|
||||||
for _, one := range ones {
|
for _, one := range ones {
|
||||||
locker.Lock()
|
locker.Lock()
|
||||||
userIds = append(userIds, int64(one.(*UserBandwidthStat).UserId))
|
var userId = int64(one.(*UserBandwidthStat).UserId)
|
||||||
|
if userId > 0 {
|
||||||
|
userIds = append(userIds, userId)
|
||||||
|
}
|
||||||
locker.Unlock()
|
locker.Unlock()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ func (this *DomainRecordsCache) WriteDomainRecords(providerId int64, domain stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryDomainRecord 从缓存中读取域名记录
|
// QueryDomainRecord 从缓存中读取单条域名记录
|
||||||
func (this *DomainRecordsCache) QueryDomainRecord(providerId int64, domain string, recordName string, recordType string) (record *dnstypes.Record, hasRecords bool, ok bool) {
|
func (this *DomainRecordsCache) QueryDomainRecord(providerId int64, domain string, recordName string, recordType string) (record *dnstypes.Record, hasRecords bool, ok bool) {
|
||||||
if providerId <= 0 || len(domain) == 0 {
|
if providerId <= 0 || len(domain) == 0 {
|
||||||
return
|
return
|
||||||
@@ -117,6 +117,52 @@ func (this *DomainRecordsCache) QueryDomainRecord(providerId int64, domain strin
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryDomainRecords 从缓存中读取多条域名记录
|
||||||
|
func (this *DomainRecordsCache) QueryDomainRecords(providerId int64, domain string, recordName string, recordType string) (records []*dnstypes.Record, hasRecords bool, ok bool) {
|
||||||
|
if providerId <= 0 || len(domain) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
domain = types.String(providerId) + "@" + domain
|
||||||
|
|
||||||
|
this.locker.Lock()
|
||||||
|
defer this.locker.Unlock()
|
||||||
|
|
||||||
|
// check version
|
||||||
|
var key = "DomainRecordsCache" + "@" + types.String(providerId) + "@" + domain
|
||||||
|
version, err := models.SharedSysLockerDAO.Read(nil, key)
|
||||||
|
if err != nil {
|
||||||
|
remotelogs.Error("dnsclients.BaseProvider", "ReadDomainRecordsCache: "+err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// find list
|
||||||
|
list, recordsOk := this.domainRecordsMap[domain]
|
||||||
|
if !recordsOk {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if version != list.version {
|
||||||
|
delete(this.domainRecordsMap, domain)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// check timestamp
|
||||||
|
if list.updatedAt < time.Now().Unix()-86400 /** 缓存有效期为一天 **/ {
|
||||||
|
delete(this.domainRecordsMap, domain)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
hasRecords = true
|
||||||
|
for _, r := range list.records {
|
||||||
|
if r.Name == recordName && r.Type == recordType {
|
||||||
|
records = append(records, r)
|
||||||
|
ok = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteDomainRecord 删除域名记录缓存
|
// DeleteDomainRecord 删除域名记录缓存
|
||||||
func (this *DomainRecordsCache) DeleteDomainRecord(providerId int64, domain string, recordId string) {
|
func (this *DomainRecordsCache) DeleteDomainRecord(providerId int64, domain string, recordId string) {
|
||||||
if providerId <= 0 || len(domain) == 0 || len(recordId) == 0 {
|
if providerId <= 0 || len(domain) == 0 || len(recordId) == 0 {
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package edgeapi
|
||||||
|
|
||||||
|
type FindNSRecordsWithNameAndTypeResponse struct {
|
||||||
|
BaseResponse
|
||||||
|
|
||||||
|
Data struct {
|
||||||
|
NSRecords []struct {
|
||||||
|
Id int64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
TTL int32 `json:"ttl"`
|
||||||
|
NSRoutes []struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Code string `json:"code"`
|
||||||
|
} `json:"nsRoutes"`
|
||||||
|
} `json:"nsRecords"`
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -154,7 +154,30 @@ func (this *AliDNSProvider) QueryRecord(domain string, name string, recordType d
|
|||||||
return record, nil
|
return record, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryRecords 查询多个记录
|
||||||
|
func (this *AliDNSProvider) QueryRecords(domain string, name string, recordType dnstypes.RecordType) ([]*dnstypes.Record, error) {
|
||||||
|
// 从缓存中读取
|
||||||
|
if this.ProviderId > 0 {
|
||||||
|
records, hasRecords, _ := sharedDomainRecordsCache.QueryDomainRecords(this.ProviderId, domain, name, recordType)
|
||||||
|
if hasRecords { // 有效的搜索
|
||||||
|
return records, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
records, err := this.GetRecords(domain)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var result = []*dnstypes.Record{}
|
||||||
|
for _, record := range records {
|
||||||
|
if record.Name == name && record.Type == recordType {
|
||||||
|
result = append(result, record)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddRecord 设置记录
|
// AddRecord 设置记录
|
||||||
|
|||||||
@@ -53,6 +53,20 @@ func TestAliDNSProvider_QueryRecord(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAliDNSProvider_QueryRecords(t *testing.T) {
|
||||||
|
provider, err := testAliDNSProvider()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
records, err := provider.QueryRecords("meloy.cn", "www", "A")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Logf("%+v", records)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestAliDNSProvider_DeleteRecord(t *testing.T) {
|
func TestAliDNSProvider_DeleteRecord(t *testing.T) {
|
||||||
provider, err := testAliDNSProvider()
|
provider, err := testAliDNSProvider()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ var cloudFlareHTTPClient = &http.Client{
|
|||||||
TLSClientConfig: &tls.Config{
|
TLSClientConfig: &tls.Config{
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
},
|
},
|
||||||
|
/**Proxy: func(req *http.Request) (*url.URL, error) {
|
||||||
|
return url.Parse("socks5://127.0.0.1:7890")
|
||||||
|
},**/
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,14 +67,22 @@ func (this *CloudFlareProvider) Auth(params maps.Map) error {
|
|||||||
|
|
||||||
// GetDomains 获取所有域名列表
|
// GetDomains 获取所有域名列表
|
||||||
func (this *CloudFlareProvider) GetDomains() (domains []string, err error) {
|
func (this *CloudFlareProvider) GetDomains() (domains []string, err error) {
|
||||||
resp := new(cloudflare.ZonesResponse)
|
for page := 1; page <= 500; page++ {
|
||||||
err = this.doAPI(http.MethodGet, "zones", map[string]string{}, nil, resp)
|
var resp = new(cloudflare.ZonesResponse)
|
||||||
if err != nil {
|
err = this.doAPI(http.MethodGet, "zones", map[string]string{
|
||||||
return nil, err
|
"per_page": "50",
|
||||||
}
|
"page": types.String(page),
|
||||||
|
}, nil, resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(resp.Result) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
for _, zone := range resp.Result {
|
for _, zone := range resp.Result {
|
||||||
domains = append(domains, zone.Name)
|
domains = append(domains, zone.Name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -134,7 +145,7 @@ func (this *CloudFlareProvider) QueryRecord(domain string, name string, recordTy
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := new(cloudflare.GetDNSRecordsResponse)
|
var resp = new(cloudflare.GetDNSRecordsResponse)
|
||||||
err = this.doAPI(http.MethodGet, "zones/"+zoneId+"/dns_records", map[string]string{
|
err = this.doAPI(http.MethodGet, "zones/"+zoneId+"/dns_records", map[string]string{
|
||||||
"per_page": "100",
|
"per_page": "100",
|
||||||
"name": name + "." + domain,
|
"name": name + "." + domain,
|
||||||
@@ -147,7 +158,7 @@ func (this *CloudFlareProvider) QueryRecord(domain string, name string, recordTy
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
record := resp.Result[0]
|
var record = resp.Result[0]
|
||||||
|
|
||||||
// 修正Record
|
// 修正Record
|
||||||
if record.Type == dnstypes.RecordTypeCNAME && !strings.HasSuffix(record.Content, ".") {
|
if record.Type == dnstypes.RecordTypeCNAME && !strings.HasSuffix(record.Content, ".") {
|
||||||
@@ -166,6 +177,46 @@ func (this *CloudFlareProvider) QueryRecord(domain string, name string, recordTy
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryRecords 查询多个记录
|
||||||
|
func (this *CloudFlareProvider) QueryRecords(domain string, name string, recordType dnstypes.RecordType) (records []*dnstypes.Record, err error) {
|
||||||
|
zoneId, err := this.findZoneIdWithDomain(domain)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp = new(cloudflare.GetDNSRecordsResponse)
|
||||||
|
err = this.doAPI(http.MethodGet, "zones/"+zoneId+"/dns_records", map[string]string{
|
||||||
|
"per_page": "100",
|
||||||
|
"name": name + "." + domain,
|
||||||
|
"type": recordType,
|
||||||
|
}, nil, resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(resp.Result) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, record := range resp.Result {
|
||||||
|
// 修正Record
|
||||||
|
if record.Type == dnstypes.RecordTypeCNAME && !strings.HasSuffix(record.Content, ".") {
|
||||||
|
record.Content += "."
|
||||||
|
}
|
||||||
|
|
||||||
|
record.Name = strings.TrimSuffix(record.Name, "."+domain)
|
||||||
|
|
||||||
|
records = append(records, &dnstypes.Record{
|
||||||
|
Id: record.Id,
|
||||||
|
Name: record.Name,
|
||||||
|
Type: record.Type,
|
||||||
|
Value: record.Content,
|
||||||
|
TTL: types.Int32(record.Ttl),
|
||||||
|
Route: CloudFlareDefaultRoute,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return records, nil
|
||||||
|
}
|
||||||
|
|
||||||
// AddRecord 设置记录
|
// AddRecord 设置记录
|
||||||
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)
|
||||||
|
|||||||
@@ -86,6 +86,21 @@ func TestCloudFlareProvider_QueryRecord(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCloudFlareProvider_QueryRecords(t *testing.T) {
|
||||||
|
provider, err := testCloudFlareProvider()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
t.Log("== www.meloy.cn/A ==")
|
||||||
|
records, err := provider.QueryRecords("meloy.cn", "www", dnstypes.RecordTypeA)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
logs.PrintAsJSON(records, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCloudFlareProvider_AddRecord(t *testing.T) {
|
func TestCloudFlareProvider_AddRecord(t *testing.T) {
|
||||||
provider, err := testCloudFlareProvider()
|
provider, err := testCloudFlareProvider()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -156,19 +171,19 @@ func testCloudFlareProvider() (ProviderInterface, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
one, err := db.FindOne("SELECT * FROM edgeDNSProviders WHERE type='cloudFlare' ORDER BY id DESC")
|
one, err := db.FindOne("SELECT * FROM edgeDNSProviders WHERE type='cloudFlare' AND state=1 ORDER BY id DESC")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if one == nil {
|
if one == nil {
|
||||||
return nil, errors.New("can not find providers with type 'cloudFlare'")
|
return nil, errors.New("can not find providers with type 'cloudFlare'")
|
||||||
}
|
}
|
||||||
apiParams := maps.Map{}
|
var apiParams = maps.Map{}
|
||||||
err = json.Unmarshal([]byte(one.GetString("apiParams")), &apiParams)
|
err = json.Unmarshal([]byte(one.GetString("apiParams")), &apiParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
provider := &CloudFlareProvider{}
|
var provider = &CloudFlareProvider{}
|
||||||
err = provider.Auth(apiParams)
|
err = provider.Auth(apiParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ func (this *CustomHTTPProvider) QueryRecord(domain string, name string, recordTy
|
|||||||
if len(resp) == 0 || string(resp) == "null" {
|
if len(resp) == 0 || string(resp) == "null" {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
record := &dnstypes.Record{}
|
var record = &dnstypes.Record{}
|
||||||
err = json.Unmarshal(resp, record)
|
err = json.Unmarshal(resp, record)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -114,6 +114,28 @@ func (this *CustomHTTPProvider) QueryRecord(domain string, name string, recordTy
|
|||||||
return record, nil
|
return record, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryRecords 查询多个记录
|
||||||
|
func (this *CustomHTTPProvider) QueryRecords(domain string, name string, recordType dnstypes.RecordType) (result []*dnstypes.Record, err error) {
|
||||||
|
resp, err := this.post(maps.Map{
|
||||||
|
"action": "QueryRecords",
|
||||||
|
"domain": domain,
|
||||||
|
"name": name,
|
||||||
|
"recordType": recordType,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(resp) == 0 || string(resp) == "null" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
result = []*dnstypes.Record{}
|
||||||
|
err = json.Unmarshal(resp, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
// AddRecord 设置记录
|
// AddRecord 设置记录
|
||||||
func (this *CustomHTTPProvider) AddRecord(domain string, newRecord *dnstypes.Record) error {
|
func (this *CustomHTTPProvider) AddRecord(domain string, newRecord *dnstypes.Record) error {
|
||||||
_, err := this.post(maps.Map{
|
_, err := this.post(maps.Map{
|
||||||
|
|||||||
@@ -186,7 +186,30 @@ func (this *DNSPodProvider) QueryRecord(domain string, name string, recordType d
|
|||||||
return record, nil
|
return record, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryRecords 查询多个记录
|
||||||
|
func (this *DNSPodProvider) QueryRecords(domain string, name string, recordType dnstypes.RecordType) ([]*dnstypes.Record, error) {
|
||||||
|
// 从缓存中读取
|
||||||
|
if this.ProviderId > 0 {
|
||||||
|
records, hasRecords, _ := sharedDomainRecordsCache.QueryDomainRecords(this.ProviderId, domain, name, recordType)
|
||||||
|
if hasRecords { // 有效的搜索
|
||||||
|
return records, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
records, err := this.GetRecords(domain)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var result = []*dnstypes.Record{}
|
||||||
|
for _, record := range records {
|
||||||
|
if record.Name == name && record.Type == recordType {
|
||||||
|
result = append(result, record)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddRecord 设置记录
|
// AddRecord 设置记录
|
||||||
|
|||||||
@@ -98,6 +98,21 @@ func TestDNSPodProvider_QueryRecord(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDNSPodProvider_QueryRecords(t *testing.T) {
|
||||||
|
provider, _, err := testDNSPodProvider()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
records, err := provider.QueryRecords(DNSPodTestDomain, "hello-forward", dnstypes.RecordTypeCNAME)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
logs.PrintAsJSON(records, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestDNSPodProvider_UpdateRecord(t *testing.T) {
|
func TestDNSPodProvider_UpdateRecord(t *testing.T) {
|
||||||
provider, isInternational, err := testDNSPodProvider()
|
provider, isInternational, err := testDNSPodProvider()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -269,6 +269,54 @@ func (this *EdgeDNSAPIProvider) QueryRecord(domain string, name string, recordTy
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryRecords 查询多个记录
|
||||||
|
func (this *EdgeDNSAPIProvider) QueryRecords(domain string, name string, recordType dnstypes.RecordType) ([]*dnstypes.Record, error) {
|
||||||
|
var domainResp = &edgeapi.FindDomainWithNameResponse{}
|
||||||
|
err := this.doAPI("/NSDomainService/FindNSDomainWithName", map[string]any{
|
||||||
|
"name": domain,
|
||||||
|
}, domainResp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var domainId = domainResp.Data.NSDomain.Id
|
||||||
|
if domainId == 0 {
|
||||||
|
return nil, errors.New("can not find domain '" + domain + "'")
|
||||||
|
}
|
||||||
|
|
||||||
|
var recordResp = &edgeapi.FindNSRecordsWithNameAndTypeResponse{}
|
||||||
|
err = this.doAPI("/NSRecordService/FindNSRecordsWithNameAndType", map[string]any{
|
||||||
|
"nsDomainId": domainId,
|
||||||
|
"name": name,
|
||||||
|
"type": recordType,
|
||||||
|
}, recordResp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = []*dnstypes.Record{}
|
||||||
|
for _, record := range recordResp.Data.NSRecords {
|
||||||
|
if record.Id <= 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var routeCode = this.DefaultRoute()
|
||||||
|
if len(record.NSRoutes) > 0 {
|
||||||
|
routeCode = record.NSRoutes[0].Code
|
||||||
|
}
|
||||||
|
|
||||||
|
result = append(result, &dnstypes.Record{
|
||||||
|
Id: types.String(record.Id),
|
||||||
|
Name: record.Name,
|
||||||
|
Type: record.Type,
|
||||||
|
Value: record.Value,
|
||||||
|
Route: routeCode,
|
||||||
|
TTL: record.TTL,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
// AddRecord 设置记录
|
// AddRecord 设置记录
|
||||||
func (this *EdgeDNSAPIProvider) AddRecord(domain string, newRecord *dnstypes.Record) error {
|
func (this *EdgeDNSAPIProvider) AddRecord(domain string, newRecord *dnstypes.Record) error {
|
||||||
var domainResp = &edgeapi.FindDomainWithNameResponse{}
|
var domainResp = &edgeapi.FindDomainWithNameResponse{}
|
||||||
|
|||||||
@@ -63,6 +63,18 @@ func TestEdgeDNSAPIProvider_QueryRecord(t *testing.T) {
|
|||||||
logs.PrintAsJSON(record)
|
logs.PrintAsJSON(record)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEdgeDNSAPIProvider_QueryRecords(t *testing.T) {
|
||||||
|
provider, err := testEdgeDNSAPIProvider()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
record, err := provider.QueryRecords(edgeDNSAPIDomainName, "cdn", dnstypes.RecordTypeA)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
logs.PrintAsJSON(record)
|
||||||
|
}
|
||||||
|
|
||||||
func TestEdgeDNSAPIProvider_AddRecord(t *testing.T) {
|
func TestEdgeDNSAPIProvider_AddRecord(t *testing.T) {
|
||||||
provider, err := testEdgeDNSAPIProvider()
|
provider, err := testEdgeDNSAPIProvider()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -153,8 +165,8 @@ func testEdgeDNSAPIProvider() (dnsclients.ProviderInterface, error) {
|
|||||||
err := provider.Auth(maps.Map{
|
err := provider.Auth(maps.Map{
|
||||||
"role": "user",
|
"role": "user",
|
||||||
"host": "http://127.0.0.1:8004",
|
"host": "http://127.0.0.1:8004",
|
||||||
"accessKeyId": "JOvsyXIFqkQbh5kl",
|
"accessKeyId": "zr9cmR42AEZxRyIV",
|
||||||
"accessKeySecret": "t0RY8YO3R58VbJJNp0RqKw9KWNpObwtE",
|
"accessKeySecret": "2w5p5NSZZuplUPsfPMzM7dFmTrI7xyja",
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -1328,6 +1328,41 @@ func (this *HuaweiDNSProvider) QueryRecord(domain string, name string, recordTyp
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryRecords 查询多个记录
|
||||||
|
func (this *HuaweiDNSProvider) QueryRecords(domain string, name string, recordType dnstypes.RecordType) ([]*dnstypes.Record, error) {
|
||||||
|
var resp = new(huaweidns.RecordSetsResponse)
|
||||||
|
err := this.doAPI(http.MethodGet, "/v2.1/recordsets", map[string]string{
|
||||||
|
"name": name + "." + domain + ".",
|
||||||
|
"type": recordType,
|
||||||
|
}, maps.Map{}, resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(resp.RecordSets) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = []*dnstypes.Record{}
|
||||||
|
for _, recordSet := range resp.RecordSets {
|
||||||
|
if len(recordSet.Records) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, record := range recordSet.Records {
|
||||||
|
result = append(result, &dnstypes.Record{
|
||||||
|
Id: recordSet.Id + "@" + record,
|
||||||
|
Name: name,
|
||||||
|
Type: recordType,
|
||||||
|
Value: record,
|
||||||
|
Route: recordSet.Line,
|
||||||
|
TTL: types.Int32(recordSet.Ttl),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
// AddRecord 设置记录
|
// AddRecord 设置记录
|
||||||
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)
|
||||||
|
|||||||
@@ -57,7 +57,19 @@ func TestHuaweiDNSProvider_QueryRecord(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
logs.PrintAsJSON(record)
|
logs.PrintAsJSON(record, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHuaweiDNSProvider_QueryRecords(t *testing.T) {
|
||||||
|
provider, err := testHuaweiDNSProvider()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
records, err := provider.QueryRecords("yun4s.cn", "abc", dnstypes.RecordTypeA)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
logs.PrintAsJSON(records, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHuaweiDNSProvider_AddRecord(t *testing.T) {
|
func TestHuaweiDNSProvider_AddRecord(t *testing.T) {
|
||||||
@@ -71,7 +83,7 @@ func TestHuaweiDNSProvider_AddRecord(t *testing.T) {
|
|||||||
Type: "A",
|
Type: "A",
|
||||||
Value: "192.168.2.40",
|
Value: "192.168.2.40",
|
||||||
Route: "Beijing",
|
Route: "Beijing",
|
||||||
TTL: 120,
|
TTL: 120,
|
||||||
}
|
}
|
||||||
err = provider.AddRecord("yun4s.cn", record)
|
err = provider.AddRecord("yun4s.cn", record)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ type ProviderInterface interface {
|
|||||||
// QueryRecord 查询单个记录
|
// QueryRecord 查询单个记录
|
||||||
QueryRecord(domain string, name string, recordType dnstypes.RecordType) (*dnstypes.Record, error)
|
QueryRecord(domain string, name string, recordType dnstypes.RecordType) (*dnstypes.Record, error)
|
||||||
|
|
||||||
|
// QueryRecords 查询多个记录
|
||||||
|
QueryRecords(domain string, name string, recordType dnstypes.RecordType) ([]*dnstypes.Record, error)
|
||||||
|
|
||||||
// AddRecord 设置记录
|
// AddRecord 设置记录
|
||||||
AddRecord(domain string, newRecord *dnstypes.Record) error
|
AddRecord(domain string, newRecord *dnstypes.Record) error
|
||||||
|
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ package installers
|
|||||||
type Env struct {
|
type Env struct {
|
||||||
OS string
|
OS string
|
||||||
Arch string
|
Arch string
|
||||||
HelperName string
|
HelperPath string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,9 +147,19 @@ func (this *BaseInstaller) LookupLatestInstaller(filePrefix string) (string, err
|
|||||||
|
|
||||||
// InstallHelper 上传安装助手
|
// InstallHelper 上传安装助手
|
||||||
func (this *BaseInstaller) InstallHelper(targetDir string, role nodeconfigs.NodeRole) (env *Env, err error) {
|
func (this *BaseInstaller) InstallHelper(targetDir string, role nodeconfigs.NodeRole) (env *Env, err error) {
|
||||||
uname, _, err := this.client.Exec("/usr/bin/uname -a")
|
var unameRetries = 3
|
||||||
|
var uname string
|
||||||
|
for i := 0; i < unameRetries; i++ {
|
||||||
|
uname, _, err = this.client.Exec("/usr/bin/uname -a")
|
||||||
|
if len(uname) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return env, err
|
return env, errors.New("unable to execute 'uname -a' on this system: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(uname) == 0 {
|
if len(uname) == 0 {
|
||||||
@@ -181,22 +191,41 @@ func (this *BaseInstaller) InstallHelper(targetDir string, role nodeconfigs.Node
|
|||||||
archName = "386"
|
archName = "386"
|
||||||
}
|
}
|
||||||
|
|
||||||
exeName := "edge-installer-helper-" + osName + "-" + archName
|
var exeName = "edge-installer-helper-" + osName + "-" + archName
|
||||||
switch role {
|
switch role {
|
||||||
case nodeconfigs.NodeRoleDNS:
|
case nodeconfigs.NodeRoleDNS:
|
||||||
exeName = "edge-installer-dns-helper-" + osName + "-" + archName
|
exeName = "edge-installer-dns-helper-" + osName + "-" + archName
|
||||||
}
|
}
|
||||||
exePath := Tea.Root + "/installers/" + exeName
|
var exePath = Tea.Root + "/installers/" + exeName
|
||||||
|
|
||||||
err = this.client.Copy(exePath, targetDir+"/"+exeName, 0777)
|
var realHelperPath = ""
|
||||||
if err != nil {
|
|
||||||
return env, errors.New("copy '" + exeName + "' to '" + targetDir + "' failed: " + err.Error())
|
var firstCopyErr error
|
||||||
|
for _, path := range []string{
|
||||||
|
targetDir + "/" + exeName,
|
||||||
|
this.client.UserHome() + "/" + exeName,
|
||||||
|
"/tmp/" + exeName,
|
||||||
|
} {
|
||||||
|
err = this.client.Copy(exePath, path, 0777)
|
||||||
|
if err != nil {
|
||||||
|
if firstCopyErr == nil {
|
||||||
|
firstCopyErr = err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = nil
|
||||||
|
firstCopyErr = nil
|
||||||
|
realHelperPath = path
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if firstCopyErr != nil {
|
||||||
|
return env, errors.New("copy '" + exeName + "' to '" + targetDir + "' failed: " + firstCopyErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
env = &Env{
|
env = &Env{
|
||||||
OS: osName,
|
OS: osName,
|
||||||
Arch: archName,
|
Arch: archName,
|
||||||
HelperName: exeName,
|
HelperPath: realHelperPath,
|
||||||
}
|
}
|
||||||
return env, nil
|
return env, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func (this *NodeInstaller) Install(dir string, params interface{}, installStatus
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 上传安装文件
|
// 上传安装文件
|
||||||
filePrefix := "edge-node-" + env.OS + "-" + env.Arch
|
var filePrefix = "edge-node-" + env.OS + "-" + env.Arch
|
||||||
zipFile, err := this.LookupLatestInstaller(filePrefix)
|
zipFile, err := this.LookupLatestInstaller(filePrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -53,16 +53,34 @@ func (this *NodeInstaller) Install(dir string, params interface{}, installStatus
|
|||||||
if len(zipFile) == 0 {
|
if len(zipFile) == 0 {
|
||||||
return errors.New("can not find installer file for " + env.OS + "/" + env.Arch)
|
return errors.New("can not find installer file for " + env.OS + "/" + env.Arch)
|
||||||
}
|
}
|
||||||
targetZip := dir + "/" + filepath.Base(zipFile)
|
var targetZip = ""
|
||||||
err = this.client.Copy(zipFile, targetZip, 0777)
|
var firstCopyErr error
|
||||||
if err != nil {
|
var zipName = filepath.Base(zipFile)
|
||||||
return err
|
for _, candidateTargetZip := range []string{
|
||||||
|
dir + "/" + zipName,
|
||||||
|
this.client.UserHome() + "/" + zipName,
|
||||||
|
"/tmp/" + zipName,
|
||||||
|
} {
|
||||||
|
err = this.client.Copy(zipFile, candidateTargetZip, 0777)
|
||||||
|
if err != nil {
|
||||||
|
if firstCopyErr == nil {
|
||||||
|
firstCopyErr = err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = nil
|
||||||
|
firstCopyErr = nil
|
||||||
|
targetZip = candidateTargetZip
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if firstCopyErr != nil {
|
||||||
|
return errors.New("upload node file failed: " + firstCopyErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// 测试运行环境
|
// 测试运行环境
|
||||||
// 升级的节点暂时不列入测试
|
// 升级的节点暂时不列入测试
|
||||||
if !nodeParams.IsUpgrading {
|
if !nodeParams.IsUpgrading {
|
||||||
_, stderr, err := this.client.Exec(dir + "/" + env.HelperName + " -cmd=test")
|
_, stderr, err := this.client.Exec(env.HelperPath + " -cmd=test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("test failed: " + err.Error())
|
return errors.New("test failed: " + err.Error())
|
||||||
}
|
}
|
||||||
@@ -72,7 +90,7 @@ func (this *NodeInstaller) Install(dir string, params interface{}, installStatus
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 如果是升级则优雅停止先前的进程
|
// 如果是升级则优雅停止先前的进程
|
||||||
exePath := dir + "/edge-node/bin/edge-node"
|
var exePath = dir + "/edge-node/bin/edge-node"
|
||||||
if nodeParams.IsUpgrading {
|
if nodeParams.IsUpgrading {
|
||||||
_, err = this.client.Stat(exePath)
|
_, err = this.client.Stat(exePath)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -87,7 +105,7 @@ func (this *NodeInstaller) Install(dir string, params interface{}, installStatus
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 解压
|
// 解压
|
||||||
_, stderr, err := this.client.Exec(dir + "/" + env.HelperName + " -cmd=unzip -zip=\"" + targetZip + "\" -target=\"" + dir + "\"")
|
_, stderr, err := this.client.Exec(env.HelperPath + " -cmd=unzip -zip=\"" + targetZip + "\" -target=\"" + dir + "\"")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,13 +94,15 @@ func (this *NodeQueue) InstallNode(nodeId int64, installStatus *models.NodeInsta
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if login == nil {
|
var loginParams = &models.NodeLoginSSHParams{}
|
||||||
installStatus.ErrorCode = "EMPTY_LOGIN"
|
if login != nil {
|
||||||
return errors.New("can not find node login information")
|
sshLoginParams, err := login.DecodeSSHParams()
|
||||||
}
|
if err != nil {
|
||||||
loginParams, err := login.DecodeSSHParams()
|
return err
|
||||||
if err != nil {
|
}
|
||||||
return err
|
if sshLoginParams != nil {
|
||||||
|
loginParams = sshLoginParams
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(loginParams.Host) == 0 {
|
if len(loginParams.Host) == 0 {
|
||||||
|
|||||||
@@ -165,7 +165,14 @@ func (this *SSHClient) Mkdir(path string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *SSHClient) MkdirAll(path string) error {
|
func (this *SSHClient) MkdirAll(path string) error {
|
||||||
return this.sftp.MkdirAll(path)
|
err := this.sftp.MkdirAll(path)
|
||||||
|
if err != nil && this.sudo {
|
||||||
|
_, _, err2 := this.execSudo("mkdir -p "+path, this.sudoPassword)
|
||||||
|
if err2 == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *SSHClient) Chmod(path string, mode os.FileMode) error {
|
func (this *SSHClient) Chmod(path string, mode os.FileMode) error {
|
||||||
|
|||||||
@@ -12,6 +12,11 @@ import (
|
|||||||
|
|
||||||
// 注册服务
|
// 注册服务
|
||||||
func (this *APINode) registerServices(server *grpc.Server) {
|
func (this *APINode) registerServices(server *grpc.Server) {
|
||||||
|
{
|
||||||
|
var instance = this.serviceInstance(&services.PingService{}).(*services.PingService)
|
||||||
|
pb.RegisterPingServiceServer(server, instance)
|
||||||
|
this.rest(instance)
|
||||||
|
}
|
||||||
{
|
{
|
||||||
var instance = this.serviceInstance(&services.APITokenService{}).(*services.APITokenService)
|
var instance = this.serviceInstance(&services.APITokenService{}).(*services.APITokenService)
|
||||||
pb.RegisterAPITokenServiceServer(server, instance)
|
pb.RegisterAPITokenServiceServer(server, instance)
|
||||||
@@ -402,6 +407,16 @@ func (this *APINode) registerServices(server *grpc.Server) {
|
|||||||
pb.RegisterServerRegionProviderMonthlyStatServiceServer(server, instance)
|
pb.RegisterServerRegionProviderMonthlyStatServiceServer(server, instance)
|
||||||
this.rest(instance)
|
this.rest(instance)
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
var instance = this.serviceInstance(&services.FormalClientSystemService{}).(*services.FormalClientSystemService)
|
||||||
|
pb.RegisterFormalClientSystemServiceServer(server, instance)
|
||||||
|
this.rest(instance)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var instance = this.serviceInstance(&services.FormalClientBrowserService{}).(*services.FormalClientBrowserService)
|
||||||
|
pb.RegisterFormalClientBrowserServiceServer(server, instance)
|
||||||
|
this.rest(instance)
|
||||||
|
}
|
||||||
{
|
{
|
||||||
var instance = this.serviceInstance(&services.ServerClientSystemMonthlyStatService{}).(*services.ServerClientSystemMonthlyStatService)
|
var instance = this.serviceInstance(&services.ServerClientSystemMonthlyStatService{}).(*services.ServerClientSystemMonthlyStatService)
|
||||||
pb.RegisterServerClientSystemMonthlyStatServiceServer(server, instance)
|
pb.RegisterServerClientSystemMonthlyStatServiceServer(server, instance)
|
||||||
|
|||||||
@@ -6,11 +6,13 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/cespare/xxhash"
|
||||||
"github.com/iwind/TeaGo/logs"
|
"github.com/iwind/TeaGo/logs"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var logChan = make(chan *pb.NodeLog, 1024)
|
var logChan = make(chan *pb.NodeLog, 64) // 队列数量不需要太长,因为日志通常仅仅为调试用
|
||||||
var sharedDAO DAOInterface
|
var sharedDAO DAOInterface
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -106,13 +108,33 @@ func uploadLogs() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hashSize = 10
|
||||||
|
var hashList = []uint64{}
|
||||||
|
|
||||||
Loop:
|
Loop:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case log := <-logChan:
|
case log := <-logChan:
|
||||||
err := sharedDAO.CreateLog(nil, nodeconfigs.NodeRoleAPI, log.NodeId, log.ServerId, log.OriginId, log.Level, log.Tag, log.Description, log.CreatedAt, "", nil)
|
// 是否已存在
|
||||||
if err != nil {
|
var hash = xxhash.Sum64String(types.String(log.NodeId) + "_" + log.Description)
|
||||||
return err
|
var found = false
|
||||||
|
for _, h := range hashList {
|
||||||
|
if h == hash {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加入
|
||||||
|
if !found {
|
||||||
|
hashList = append(hashList, hash)
|
||||||
|
if len(hashList) > hashSize {
|
||||||
|
hashList = hashList[1:]
|
||||||
|
}
|
||||||
|
err := sharedDAO.CreateLog(nil, nodeconfigs.NodeRoleAPI, log.NodeId, log.ServerId, log.OriginId, log.Level, log.Tag, log.Description, log.CreatedAt, "", nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break Loop
|
break Loop
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
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/authority"
|
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/regions"
|
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/stats"
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models/stats"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/rpc/tasks"
|
"github.com/TeaOSLab/EdgeAPI/internal/rpc/tasks"
|
||||||
@@ -604,8 +602,8 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 小时流量统计
|
// 小时流量统计
|
||||||
hourFrom := timeutil.Format("YmdH", time.Now().Add(-23*time.Hour))
|
var hourFrom = timeutil.Format("YmdH", time.Now().Add(-23*time.Hour))
|
||||||
hourTo := timeutil.Format("YmdH")
|
var hourTo = timeutil.Format("YmdH")
|
||||||
this.BeginTag(ctx, "SharedTrafficHourlyStatDAO.FindHourlyStats")
|
this.BeginTag(ctx, "SharedTrafficHourlyStatDAO.FindHourlyStats")
|
||||||
hourlyTrafficStats, err := stats.SharedTrafficHourlyStatDAO.FindHourlyStats(tx, hourFrom, hourTo)
|
hourlyTrafficStats, err := stats.SharedTrafficHourlyStatDAO.FindHourlyStats(tx, hourFrom, hourTo)
|
||||||
this.EndTag(ctx, "SharedTrafficHourlyStatDAO.FindHourlyStats")
|
this.EndTag(ctx, "SharedTrafficHourlyStatDAO.FindHourlyStats")
|
||||||
@@ -624,12 +622,6 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 是否是商业版
|
|
||||||
isPlus, err := authority.SharedAuthorityKeyDAO.IsPlus(tx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 边缘节点升级信息
|
// 边缘节点升级信息
|
||||||
{
|
{
|
||||||
upgradeInfo := &pb.ComposeAdminDashboardResponse_UpgradeInfo{
|
upgradeInfo := &pb.ComposeAdminDashboardResponse_UpgradeInfo{
|
||||||
@@ -645,51 +637,6 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
|||||||
result.NodeUpgradeInfo = upgradeInfo
|
result.NodeUpgradeInfo = upgradeInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监控节点升级信息
|
|
||||||
if isPlus {
|
|
||||||
upgradeInfo := &pb.ComposeAdminDashboardResponse_UpgradeInfo{
|
|
||||||
NewVersion: teaconst.MonitorNodeVersion,
|
|
||||||
}
|
|
||||||
this.BeginTag(ctx, "SharedMonitorNodeDAO.CountAllLowerVersionNodes")
|
|
||||||
countNodes, err := models.SharedMonitorNodeDAO.CountAllLowerVersionNodes(tx, upgradeInfo.NewVersion)
|
|
||||||
this.EndTag(ctx, "SharedMonitorNodeDAO.CountAllLowerVersionNodes")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
upgradeInfo.CountNodes = countNodes
|
|
||||||
result.MonitorNodeUpgradeInfo = upgradeInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
// 认证节点升级信息
|
|
||||||
if isPlus {
|
|
||||||
upgradeInfo := &pb.ComposeAdminDashboardResponse_UpgradeInfo{
|
|
||||||
NewVersion: teaconst.AuthorityNodeVersion,
|
|
||||||
}
|
|
||||||
this.BeginTag(ctx, "SharedAuthorityNodeDAO.CountAllLowerVersionNodes")
|
|
||||||
countNodes, err := authority.SharedAuthorityNodeDAO.CountAllLowerVersionNodes(tx, upgradeInfo.NewVersion)
|
|
||||||
this.EndTag(ctx, "SharedAuthorityNodeDAO.CountAllLowerVersionNodes")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
upgradeInfo.CountNodes = countNodes
|
|
||||||
result.AuthorityNodeUpgradeInfo = upgradeInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户节点升级信息
|
|
||||||
if isPlus {
|
|
||||||
upgradeInfo := &pb.ComposeAdminDashboardResponse_UpgradeInfo{
|
|
||||||
NewVersion: teaconst.UserNodeVersion,
|
|
||||||
}
|
|
||||||
this.BeginTag(ctx, "SharedUserNodeDAO.CountAllLowerVersionNodes")
|
|
||||||
countNodes, err := models.SharedUserNodeDAO.CountAllLowerVersionNodes(tx, upgradeInfo.NewVersion)
|
|
||||||
this.EndTag(ctx, "SharedUserNodeDAO.CountAllLowerVersionNodes")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
upgradeInfo.CountNodes = countNodes
|
|
||||||
result.UserNodeUpgradeInfo = upgradeInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
// API节点升级信息
|
// API节点升级信息
|
||||||
{
|
{
|
||||||
var apiVersion = req.ApiVersion
|
var apiVersion = req.ApiVersion
|
||||||
@@ -709,34 +656,10 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
|||||||
result.ApiNodeUpgradeInfo = upgradeInfo
|
result.ApiNodeUpgradeInfo = upgradeInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
// DNS节点升级信息
|
// 额外的检查节点版本
|
||||||
if isPlus {
|
err = this.composeAdminDashboardExt(tx, ctx, result)
|
||||||
upgradeInfo := &pb.ComposeAdminDashboardResponse_UpgradeInfo{
|
if err != nil {
|
||||||
NewVersion: teaconst.DNSNodeVersion,
|
return nil, err
|
||||||
}
|
|
||||||
this.BeginTag(ctx, "SharedNSNodeDAO.CountAllLowerVersionNodes")
|
|
||||||
countNodes, err := models.SharedNSNodeDAO.CountAllLowerVersionNodes(tx, upgradeInfo.NewVersion)
|
|
||||||
this.EndTag(ctx, "SharedNSNodeDAO.CountAllLowerVersionNodes")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
upgradeInfo.CountNodes = countNodes
|
|
||||||
result.NsNodeUpgradeInfo = upgradeInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
// Report节点升级信息
|
|
||||||
if isPlus {
|
|
||||||
upgradeInfo := &pb.ComposeAdminDashboardResponse_UpgradeInfo{
|
|
||||||
NewVersion: teaconst.ReportNodeVersion,
|
|
||||||
}
|
|
||||||
this.BeginTag(ctx, "SharedReportNodeDAO.CountAllLowerVersionNodes")
|
|
||||||
countNodes, err := models.SharedReportNodeDAO.CountAllLowerVersionNodes(tx, upgradeInfo.NewVersion)
|
|
||||||
this.EndTag(ctx, "SharedReportNodeDAO.CountAllLowerVersionNodes")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
upgradeInfo.CountNodes = countNodes
|
|
||||||
result.ReportNodeUpgradeInfo = upgradeInfo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 域名排行
|
// 域名排行
|
||||||
@@ -759,63 +682,6 @@ func (this *AdminService) ComposeAdminDashboard(ctx context.Context, req *pb.Com
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 节点排行
|
|
||||||
if isPlus {
|
|
||||||
this.BeginTag(ctx, "SharedNodeTrafficHourlyStatDAO.FindTopNodeStats")
|
|
||||||
topNodeStats, err := stats.SharedNodeTrafficHourlyStatDAO.FindTopNodeStats(tx, "node", hourFrom, hourTo, 10)
|
|
||||||
this.EndTag(ctx, "SharedNodeTrafficHourlyStatDAO.FindTopNodeStats")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for _, stat := range topNodeStats {
|
|
||||||
nodeName, err := models.SharedNodeDAO.FindNodeName(tx, int64(stat.NodeId))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(nodeName) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
result.TopNodeStats = append(result.TopNodeStats, &pb.ComposeAdminDashboardResponse_NodeStat{
|
|
||||||
NodeId: int64(stat.NodeId),
|
|
||||||
NodeName: nodeName,
|
|
||||||
CountRequests: int64(stat.CountRequests),
|
|
||||||
Bytes: int64(stat.Bytes),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 地区流量排行
|
|
||||||
if isPlus {
|
|
||||||
this.BeginTag(ctx, "SharedServerRegionCountryDailyStatDAO.SumDailyTotalBytes")
|
|
||||||
totalCountryBytes, err := stats.SharedServerRegionCountryDailyStatDAO.SumDailyTotalBytes(tx, timeutil.Format("Ymd"))
|
|
||||||
this.EndTag(ctx, "SharedServerRegionCountryDailyStatDAO.SumDailyTotalBytes")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if totalCountryBytes > 0 {
|
|
||||||
topCountryStats, err := stats.SharedServerRegionCountryDailyStatDAO.ListSumStats(tx, timeutil.Format("Ymd"), "bytes", 0, 100)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, stat := range topCountryStats {
|
|
||||||
countryName, err := regions.SharedRegionCountryDAO.FindRegionCountryName(tx, int64(stat.CountryId))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
result.TopCountryStats = append(result.TopCountryStats, &pb.ComposeAdminDashboardResponse_CountryStat{
|
|
||||||
CountryName: countryName,
|
|
||||||
Bytes: int64(stat.Bytes),
|
|
||||||
CountRequests: int64(stat.CountRequests),
|
|
||||||
AttackBytes: int64(stat.AttackBytes),
|
|
||||||
CountAttackRequests: int64(stat.CountAttackRequests),
|
|
||||||
Percent: float32(stat.Bytes*100) / float32(totalCountryBytes),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 指标数据
|
// 指标数据
|
||||||
this.BeginTag(ctx, "findMetricDataCharts")
|
this.BeginTag(ctx, "findMetricDataCharts")
|
||||||
var pbCharts []*pb.MetricDataChart
|
var pbCharts []*pb.MetricDataChart
|
||||||
|
|||||||
15
internal/rpc/services/service_admin_ext.go
Normal file
15
internal/rpc/services/service_admin_ext.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
//go:build !plus
|
||||||
|
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ComposeAdminDashboard方法扩展
|
||||||
|
func (this *AdminService) composeAdminDashboardExt(tx *dbs.Tx, ctx context.Context, result *pb.ComposeAdminDashboardResponse) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -351,7 +351,7 @@ func (this *DNSDomainService) ExistAvailableDomains(ctx context.Context, req *pb
|
|||||||
|
|
||||||
// 转换域名信息
|
// 转换域名信息
|
||||||
func (this *DNSDomainService) convertDomainToPB(tx *dbs.Tx, domain *dns.DNSDomain) (*pb.DNSDomain, error) {
|
func (this *DNSDomainService) convertDomainToPB(tx *dbs.Tx, domain *dns.DNSDomain) (*pb.DNSDomain, error) {
|
||||||
domainId := int64(domain.Id)
|
var domainId = int64(domain.Id)
|
||||||
|
|
||||||
defaultRoute, err := dnsutils.FindDefaultDomainRoute(tx, domain)
|
defaultRoute, err := dnsutils.FindDefaultDomainRoute(tx, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -383,7 +383,6 @@ func (this *DNSDomainService) convertDomainToPB(tx *dbs.Tx, domain *dns.DNSDomai
|
|||||||
countAllNodes1 := int64(0)
|
countAllNodes1 := int64(0)
|
||||||
countAllServers1 := int64(0)
|
countAllServers1 := int64(0)
|
||||||
for _, cluster := range clusters {
|
for _, cluster := range clusters {
|
||||||
|
|
||||||
_, nodeRecords, serverRecords, countAllNodes, countAllServers, nodesChanged2, serversChanged2, err := this.findClusterDNSChanges(cluster, records, domain.Name, defaultRoute)
|
_, nodeRecords, serverRecords, countAllNodes, countAllServers, nodesChanged2, serversChanged2, err := this.findClusterDNSChanges(cluster, records, domain.Name, defaultRoute)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -471,6 +470,7 @@ func (this *DNSDomainService) findClusterDNSChanges(cluster *models.NodeCluster,
|
|||||||
|
|
||||||
// 新增的节点域名
|
// 新增的节点域名
|
||||||
var nodeKeys = []string{}
|
var nodeKeys = []string{}
|
||||||
|
var addingNodeRecordKeysMap = map[string]bool{} // clusterDnsName_type_ip_route
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
ipAddresses, err := models.SharedNodeIPAddressDAO.FindNodeAccessAndUpIPAddresses(tx, int64(node.Id), nodeconfigs.NodeRoleNode)
|
ipAddresses, err := models.SharedNodeIPAddressDAO.FindNodeAccessAndUpIPAddresses(tx, int64(node.Id), nodeconfigs.NodeRoleNode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -500,7 +500,7 @@ func (this *DNSDomainService) findClusterDNSChanges(cluster *models.NodeCluster,
|
|||||||
if net.ParseIP(ip) == nil {
|
if net.ParseIP(ip) == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
key := ip + "_" + route
|
var key = ip + "_" + route
|
||||||
nodeKeys = append(nodeKeys, key)
|
nodeKeys = append(nodeKeys, key)
|
||||||
record, ok := nodeRecordMapping[key]
|
record, ok := nodeRecordMapping[key]
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -508,6 +508,14 @@ func (this *DNSDomainService) findClusterDNSChanges(cluster *models.NodeCluster,
|
|||||||
if utils.IsIPv6(ip) {
|
if utils.IsIPv6(ip) {
|
||||||
recordType = dnstypes.RecordTypeAAAA
|
recordType = dnstypes.RecordTypeAAAA
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 避免添加重复的记录
|
||||||
|
var fullKey = clusterDnsName + "_" + recordType + "_" + ip + "_" + route
|
||||||
|
if addingNodeRecordKeysMap[fullKey] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
addingNodeRecordKeysMap[fullKey] = true
|
||||||
|
|
||||||
result = append(result, maps.Map{
|
result = append(result, maps.Map{
|
||||||
"action": "create",
|
"action": "create",
|
||||||
"record": &dnstypes.Record{
|
"record": &dnstypes.Record{
|
||||||
|
|||||||
143
internal/rpc/services/service_formal_client_browser.go
Normal file
143
internal/rpc/services/service_formal_client_browser.go
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FormalClientBrowserService 浏览器信息库服务
|
||||||
|
type FormalClientBrowserService struct {
|
||||||
|
BaseService
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateFormalClientBrowser 创建浏览器信息
|
||||||
|
func (this *FormalClientBrowserService) CreateFormalClientBrowser(ctx context.Context, req *pb.CreateFormalClientBrowserRequest) (*pb.CreateFormalClientBrowserResponse, error) {
|
||||||
|
_, err := this.ValidateAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查dataId是否存在
|
||||||
|
var tx = this.NullTx()
|
||||||
|
browser, err := models.SharedFormalClientBrowserDAO.FindBrowserWithDataId(tx, req.DataId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if browser != nil {
|
||||||
|
return nil, errors.New("dataId '" + req.DataId + "' already exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
browserId, err := models.SharedFormalClientBrowserDAO.CreateBrowser(tx, req.Name, req.Codes, req.DataId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &pb.CreateFormalClientBrowserResponse{
|
||||||
|
FormalClientBrowserId: browserId,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountFormalClientBrowsers 计算浏览器信息数量
|
||||||
|
func (this *FormalClientBrowserService) CountFormalClientBrowsers(ctx context.Context, req *pb.CountFormalClientBrowsersRequest) (*pb.RPCCountResponse, error) {
|
||||||
|
_, err := this.ValidateAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tx = this.NullTx()
|
||||||
|
count, err := models.SharedFormalClientBrowserDAO.CountBrowsers(tx, req.Keyword)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.SuccessCount(count)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListFormalClientBrowsers 列出单页浏览器信息
|
||||||
|
func (this *FormalClientBrowserService) ListFormalClientBrowsers(ctx context.Context, req *pb.ListFormalClientBrowsersRequest) (*pb.ListFormalClientBrowsersResponse, error) {
|
||||||
|
_, err := this.ValidateAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tx = this.NullTx()
|
||||||
|
browsers, err := models.SharedFormalClientBrowserDAO.ListBrowsers(tx, req.Keyword, req.Offset, req.Size)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var pbBrowsers = []*pb.FormalClientBrowser{}
|
||||||
|
for _, browser := range browsers {
|
||||||
|
pbBrowsers = append(pbBrowsers, &pb.FormalClientBrowser{
|
||||||
|
Id: int64(browser.Id),
|
||||||
|
Name: browser.Name,
|
||||||
|
Codes: browser.DecodeCodes(),
|
||||||
|
DataId: browser.DataId,
|
||||||
|
State: types.Int32(browser.State),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return &pb.ListFormalClientBrowsersResponse{
|
||||||
|
FormalClientBrowsers: pbBrowsers,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateFormalClientBrowser 修改浏览器信息
|
||||||
|
func (this *FormalClientBrowserService) UpdateFormalClientBrowser(ctx context.Context, req *pb.UpdateFormalClientBrowserRequest) (*pb.RPCSuccess, error) {
|
||||||
|
_, err := this.ValidateAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(req.DataId) == 0 {
|
||||||
|
return nil, errors.New("invalid dataId")
|
||||||
|
}
|
||||||
|
|
||||||
|
var tx = this.NullTx()
|
||||||
|
|
||||||
|
// 检查dataId是否已经被使用
|
||||||
|
oldBrowser, err := models.SharedFormalClientBrowserDAO.FindBrowserWithDataId(tx, req.DataId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if oldBrowser != nil && int64(oldBrowser.Id) != req.FormalClientBrowserId {
|
||||||
|
return nil, errors.New("the dataId '" + req.DataId + "' already has been used")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = models.SharedFormalClientBrowserDAO.UpdateBrowser(tx, req.FormalClientBrowserId, req.Name, req.Codes, req.DataId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.Success()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindFormalClientBrowserWithDataId 通过dataId查询浏览器信息
|
||||||
|
func (this *FormalClientBrowserService) FindFormalClientBrowserWithDataId(ctx context.Context, req *pb.FindFormalClientBrowserWithDataIdRequest) (*pb.FindFormalClientBrowserWithDataIdResponse, error) {
|
||||||
|
_, err := this.ValidateAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tx = this.NullTx()
|
||||||
|
browser, err := models.SharedFormalClientBrowserDAO.FindBrowserWithDataId(tx, req.DataId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if browser == nil {
|
||||||
|
return &pb.FindFormalClientBrowserWithDataIdResponse{
|
||||||
|
FormalClientBrowser: nil,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.FindFormalClientBrowserWithDataIdResponse{
|
||||||
|
FormalClientBrowser: &pb.FormalClientBrowser{
|
||||||
|
Id: int64(browser.Id),
|
||||||
|
Name: browser.Name,
|
||||||
|
Codes: browser.DecodeCodes(),
|
||||||
|
DataId: browser.DataId,
|
||||||
|
State: types.Int32(browser.State),
|
||||||
|
}}, nil
|
||||||
|
}
|
||||||
143
internal/rpc/services/service_formal_client_system.go
Normal file
143
internal/rpc/services/service_formal_client_system.go
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FormalClientSystemService 操作系统信息库服务
|
||||||
|
type FormalClientSystemService struct {
|
||||||
|
BaseService
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateFormalClientSystem 创建操作系统信息
|
||||||
|
func (this *FormalClientSystemService) CreateFormalClientSystem(ctx context.Context, req *pb.CreateFormalClientSystemRequest) (*pb.CreateFormalClientSystemResponse, error) {
|
||||||
|
_, err := this.ValidateAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查dataId是否存在
|
||||||
|
var tx = this.NullTx()
|
||||||
|
system, err := models.SharedFormalClientSystemDAO.FindSystemWithDataId(tx, req.DataId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if system != nil {
|
||||||
|
return nil, errors.New("dataId '" + req.DataId + "' already exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
systemId, err := models.SharedFormalClientSystemDAO.CreateSystem(tx, req.Name, req.Codes, req.DataId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &pb.CreateFormalClientSystemResponse{
|
||||||
|
FormalClientSystemId: systemId,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountFormalClientSystems 计算操作系统信息数量
|
||||||
|
func (this *FormalClientSystemService) CountFormalClientSystems(ctx context.Context, req *pb.CountFormalClientSystemsRequest) (*pb.RPCCountResponse, error) {
|
||||||
|
_, err := this.ValidateAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tx = this.NullTx()
|
||||||
|
count, err := models.SharedFormalClientSystemDAO.CountSystems(tx, req.Keyword)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.SuccessCount(count)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListFormalClientSystems 列出单页操作系统信息
|
||||||
|
func (this *FormalClientSystemService) ListFormalClientSystems(ctx context.Context, req *pb.ListFormalClientSystemsRequest) (*pb.ListFormalClientSystemsResponse, error) {
|
||||||
|
_, err := this.ValidateAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tx = this.NullTx()
|
||||||
|
systems, err := models.SharedFormalClientSystemDAO.ListSystems(tx, req.Keyword, req.Offset, req.Size)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var pbSystems = []*pb.FormalClientSystem{}
|
||||||
|
for _, system := range systems {
|
||||||
|
pbSystems = append(pbSystems, &pb.FormalClientSystem{
|
||||||
|
Id: int64(system.Id),
|
||||||
|
Name: system.Name,
|
||||||
|
Codes: system.DecodeCodes(),
|
||||||
|
DataId: system.DataId,
|
||||||
|
State: types.Int32(system.State),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return &pb.ListFormalClientSystemsResponse{
|
||||||
|
FormalClientSystems: pbSystems,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateFormalClientSystem 修改操作系统信息
|
||||||
|
func (this *FormalClientSystemService) UpdateFormalClientSystem(ctx context.Context, req *pb.UpdateFormalClientSystemRequest) (*pb.RPCSuccess, error) {
|
||||||
|
_, err := this.ValidateAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(req.DataId) == 0 {
|
||||||
|
return nil, errors.New("invalid dataId")
|
||||||
|
}
|
||||||
|
|
||||||
|
var tx = this.NullTx()
|
||||||
|
|
||||||
|
// 检查dataId是否已经被使用
|
||||||
|
oldSystem, err := models.SharedFormalClientSystemDAO.FindSystemWithDataId(tx, req.DataId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if oldSystem != nil && int64(oldSystem.Id) != req.FormalClientSystemId {
|
||||||
|
return nil, errors.New("the dataId '" + req.DataId + "' already has been used")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = models.SharedFormalClientSystemDAO.UpdateSystem(tx, req.FormalClientSystemId, req.Name, req.Codes, req.DataId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.Success()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindFormalClientSystemWithDataId 通过dataId查询操作系统信息
|
||||||
|
func (this *FormalClientSystemService) FindFormalClientSystemWithDataId(ctx context.Context, req *pb.FindFormalClientSystemWithDataIdRequest) (*pb.FindFormalClientSystemWithDataIdResponse, error) {
|
||||||
|
_, err := this.ValidateAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tx = this.NullTx()
|
||||||
|
system, err := models.SharedFormalClientSystemDAO.FindSystemWithDataId(tx, req.DataId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if system == nil {
|
||||||
|
return &pb.FindFormalClientSystemWithDataIdResponse{
|
||||||
|
FormalClientSystem: nil,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.FindFormalClientSystemWithDataIdResponse{
|
||||||
|
FormalClientSystem: &pb.FormalClientSystem{
|
||||||
|
Id: int64(system.Id),
|
||||||
|
Name: system.Name,
|
||||||
|
Codes: system.DecodeCodes(),
|
||||||
|
DataId: system.DataId,
|
||||||
|
State: types.Int32(system.State),
|
||||||
|
}}, nil
|
||||||
|
}
|
||||||
@@ -92,7 +92,9 @@ func init() {
|
|||||||
return nil
|
return nil
|
||||||
}(key)
|
}(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
remotelogs.Error("METRIC_STAT", "upload metric stats failed: "+err.Error())
|
if !models.CheckSQLErrCode(err, 1213 /** transaction deadlock **/) {
|
||||||
|
remotelogs.Error("METRIC_STAT", "upload metric stats failed: "+err.Error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 人为限速
|
// 人为限速
|
||||||
|
|||||||
@@ -546,7 +546,7 @@ func (this *NodeService) FindEnabledNode(ctx context.Context, req *pb.FindEnable
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
installStatusResult := &pb.NodeInstallStatus{}
|
var installStatusResult = &pb.NodeInstallStatus{}
|
||||||
if installStatus != nil {
|
if installStatus != nil {
|
||||||
installStatusResult = &pb.NodeInstallStatus{
|
installStatusResult = &pb.NodeInstallStatus{
|
||||||
IsRunning: installStatus.IsRunning,
|
IsRunning: installStatus.IsRunning,
|
||||||
@@ -673,10 +673,12 @@ func (this *NodeService) FindEnabledNode(ctx context.Context, req *pb.FindEnable
|
|||||||
MaxCacheDiskCapacity: pbMaxCacheDiskCapacity,
|
MaxCacheDiskCapacity: pbMaxCacheDiskCapacity,
|
||||||
MaxCacheMemoryCapacity: pbMaxCacheMemoryCapacity,
|
MaxCacheMemoryCapacity: pbMaxCacheMemoryCapacity,
|
||||||
CacheDiskDir: node.CacheDiskDir,
|
CacheDiskDir: node.CacheDiskDir,
|
||||||
|
CacheDiskSubDirsJSON: node.CacheDiskSubDirs,
|
||||||
Level: int32(node.Level),
|
Level: int32(node.Level),
|
||||||
LnAddrs: node.DecodeLnAddrs(),
|
LnAddrs: node.DecodeLnAddrs(),
|
||||||
DnsRoutes: pbRoutes,
|
DnsRoutes: pbRoutes,
|
||||||
EnableIPLists: node.EnableIPLists,
|
EnableIPLists: node.EnableIPLists,
|
||||||
|
ApiNodeAddrsJSON: node.ApiNodeAddrs,
|
||||||
}}, nil
|
}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1708,7 +1710,16 @@ func (this *NodeService) UpdateNodeCache(ctx context.Context, req *pb.UpdateNode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = models.SharedNodeDAO.UpdateNodeCache(tx, req.NodeId, maxCacheDiskCapacityJSON, maxCacheMemoryCapacityJSON, req.CacheDiskDir)
|
// cache sub dirs
|
||||||
|
var cacheSubDirs = []*serverconfigs.CacheDir{}
|
||||||
|
if len(req.CacheDiskSubDirsJSON) > 0 {
|
||||||
|
err = json.Unmarshal(req.CacheDiskSubDirsJSON, &cacheSubDirs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("decode 'cacheDiskSubDirsJSON' failed: " + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = models.SharedNodeDAO.UpdateNodeCache(tx, req.NodeId, maxCacheDiskCapacityJSON, maxCacheMemoryCapacityJSON, req.CacheDiskDir, cacheSubDirs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -2031,6 +2042,14 @@ func (this *NodeService) FindEnabledNodeConfigInfo(ctx context.Context, req *pb.
|
|||||||
if dnsResolverConfig != nil {
|
if dnsResolverConfig != nil {
|
||||||
result.HasSystemSettings = dnsResolverConfig.Type != nodeconfigs.DNSResolverTypeDefault
|
result.HasSystemSettings = dnsResolverConfig.Type != nodeconfigs.DNSResolverTypeDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !result.HasSystemSettings {
|
||||||
|
// api node addresses
|
||||||
|
var apiNodeAddrs = node.DecodeAPINodeAddrs()
|
||||||
|
if len(apiNodeAddrs) > 0 {
|
||||||
|
result.HasSystemSettings = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ddos protection
|
// ddos protection
|
||||||
@@ -2132,3 +2151,50 @@ func (this *NodeService) UpdateNodeRegionInfo(ctx context.Context, req *pb.Updat
|
|||||||
|
|
||||||
return this.Success()
|
return this.Success()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindNodeAPIConfig 查找单个节点的API相关配置
|
||||||
|
func (this *NodeService) FindNodeAPIConfig(ctx context.Context, req *pb.FindNodeAPIConfigRequest) (*pb.FindNodeAPIConfigResponse, error) {
|
||||||
|
_, err := this.ValidateAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tx = this.NullTx()
|
||||||
|
node, err := models.SharedNodeDAO.FindNodeAPIConfig(tx, req.NodeId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if node == nil {
|
||||||
|
return &pb.FindNodeAPIConfigResponse{
|
||||||
|
ApiNodeAddrsJSON: nil,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.FindNodeAPIConfigResponse{
|
||||||
|
ApiNodeAddrsJSON: node.ApiNodeAddrs,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateNodeAPIConfig 修改某个节点的API相关配置
|
||||||
|
func (this *NodeService) UpdateNodeAPIConfig(ctx context.Context, req *pb.UpdateNodeAPIConfigRequest) (*pb.RPCSuccess, error) {
|
||||||
|
_, err := this.ValidateAdmin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tx = this.NullTx()
|
||||||
|
var apiNodeAddrs = []*serverconfigs.NetworkAddressConfig{}
|
||||||
|
if len(req.ApiNodeAddrsJSON) > 0 {
|
||||||
|
err = json.Unmarshal(req.ApiNodeAddrsJSON, &apiNodeAddrs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = models.SharedNodeDAO.UpdateNodeAPIConfig(tx, req.NodeId, apiNodeAddrs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.Success()
|
||||||
|
}
|
||||||
|
|||||||
@@ -112,24 +112,24 @@ func (this *NodeService) NodeStream(server pb.NodeService_NodeStreamServer) erro
|
|||||||
|
|
||||||
var tx = this.NullTx()
|
var tx = this.NullTx()
|
||||||
|
|
||||||
// 标记为活跃状态
|
// 是否发送恢复通知
|
||||||
oldIsActive, err := models.SharedNodeDAO.FindNodeActive(tx, nodeId)
|
oldIsActive, err := models.SharedNodeDAO.FindNodeActive(tx, nodeId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !oldIsActive {
|
if !oldIsActive {
|
||||||
inactiveNotifiedAt, err := models.SharedNodeDAO.FindNodeInactiveNotifiedAt(tx, nodeId)
|
inactiveNotifiedAt, err := models.SharedNodeDAO.FindNodeInactiveNotifiedAt(tx, nodeId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if inactiveNotifiedAt > 0 {
|
|
||||||
// 设置为活跃
|
|
||||||
err = models.SharedNodeDAO.UpdateNodeActive(tx, nodeId, true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// 设置为活跃
|
||||||
|
err = models.SharedNodeDAO.UpdateNodeActive(tx, nodeId, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if inactiveNotifiedAt > 0 {
|
||||||
// 发送恢复消息
|
// 发送恢复消息
|
||||||
clusterId, err := models.SharedNodeDAO.FindNodeClusterId(tx, nodeId)
|
clusterId, err := models.SharedNodeDAO.FindNodeClusterId(tx, nodeId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -145,12 +145,6 @@ func (this *NodeService) NodeStream(server pb.NodeService_NodeStreamServer) erro
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// 设置为活跃
|
|
||||||
err = models.SharedNodeDAO.UpdateNodeActive(tx, nodeId, true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,10 +24,8 @@ func (this *NodeTaskService) FindNodeTasks(ctx context.Context, req *pb.FindNode
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = req
|
|
||||||
|
|
||||||
var tx = this.NullTx()
|
var tx = this.NullTx()
|
||||||
tasks, err := models.SharedNodeTaskDAO.FindDoingNodeTasks(tx, nodeType, nodeId)
|
tasks, err := models.SharedNodeTaskDAO.FindDoingNodeTasks(tx, nodeType, nodeId, req.Version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
23
internal/rpc/services/service_ping.go
Normal file
23
internal/rpc/services/service_ping.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PingService Ping服务
|
||||||
|
// 用来测试连接是否可用
|
||||||
|
type PingService struct {
|
||||||
|
BaseService
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ping 发起Ping
|
||||||
|
func (this *PingService) Ping(ctx context.Context, req *pb.PingRequest) (*pb.PingResponse, error) {
|
||||||
|
_, _, err := this.ValidateNodeId(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &pb.PingResponse{}, nil
|
||||||
|
}
|
||||||
@@ -1709,17 +1709,20 @@ func (this *ServerService) UploadServerHTTPRequestStat(ctx context.Context, req
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
systemId, err := models.SharedClientSystemDAO.FindSystemIdWithNameCacheable(tx, result.Name)
|
systemId, err := models.SharedFormalClientSystemDAO.FindSystemIdWithNameCacheable(tx, result.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if systemId == 0 {
|
if systemId == 0 {
|
||||||
systemId, err = models.SharedClientSystemDAO.CreateSystem(tx, result.Name)
|
err = models.SharedClientSystemDAO.CreateSystemIfNotExists(tx, result.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 直接返回不再进行操作
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
key := fmt.Sprintf("%d@%d@%s@%s", result.ServerId, systemId, result.Version, month)
|
var key = fmt.Sprintf("%d@%d@%s@%s", result.ServerId, systemId, result.Version, month)
|
||||||
serverStatLocker.Lock()
|
serverStatLocker.Lock()
|
||||||
serverHTTPSystemStatMap[key] += result.Count
|
serverHTTPSystemStatMap[key] += result.Count
|
||||||
serverStatLocker.Unlock()
|
serverStatLocker.Unlock()
|
||||||
@@ -1737,15 +1740,18 @@ func (this *ServerService) UploadServerHTTPRequestStat(ctx context.Context, req
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
browserId, err := models.SharedClientBrowserDAO.FindBrowserIdWithNameCacheable(tx, result.Name)
|
browserId, err := models.SharedFormalClientBrowserDAO.FindBrowserIdWithNameCacheable(tx, result.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if browserId == 0 {
|
if browserId == 0 {
|
||||||
browserId, err = models.SharedClientBrowserDAO.CreateBrowser(tx, result.Name)
|
err = models.SharedClientBrowserDAO.CreateBrowserIfNotExists(tx, result.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 直接返回不再进行操作
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
key := fmt.Sprintf("%d@%d@%s@%s", result.ServerId, browserId, result.Version, month)
|
key := fmt.Sprintf("%d@%d@%s@%s", result.ServerId, browserId, result.Version, month)
|
||||||
serverStatLocker.Lock()
|
serverStatLocker.Lock()
|
||||||
|
|||||||
@@ -10,8 +10,10 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/regexputils"
|
"github.com/TeaOSLab/EdgeAPI/internal/utils/regexputils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||||
"github.com/iwind/TeaGo/dbs"
|
"github.com/iwind/TeaGo/dbs"
|
||||||
"github.com/iwind/TeaGo/types"
|
"github.com/iwind/TeaGo/types"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -186,14 +188,45 @@ func (this *ServerBandwidthStatService) FindHourlyServerBandwidthStats(ctx conte
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if req.Hours <= 0 {
|
||||||
|
req.Hours = 12
|
||||||
|
}
|
||||||
|
|
||||||
var tx = this.NullTx()
|
var tx = this.NullTx()
|
||||||
stats, err := models.SharedServerBandwidthStatDAO.FindHourlyBandwidthStats(tx, req.ServerId, req.Hours)
|
stats, err := models.SharedServerBandwidthStatDAO.FindHourlyBandwidthStats(tx, req.ServerId, req.Hours)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// percentile
|
||||||
|
var percentile = systemconfigs.DefaultBandwidthPercentile
|
||||||
|
userUIConfig, _ := models.SharedSysSettingDAO.ReadUserUIConfig(tx)
|
||||||
|
if userUIConfig != nil && userUIConfig.TrafficStats.BandwidthPercentile > 0 {
|
||||||
|
percentile = userUIConfig.TrafficStats.BandwidthPercentile
|
||||||
|
}
|
||||||
|
|
||||||
|
var timestamp = time.Now().Unix() - int64(req.Hours)*3600
|
||||||
|
var timeFrom = timeutil.FormatTime("YmdH00", timestamp)
|
||||||
|
var timeTo = timeutil.Format("YmdHi")
|
||||||
|
|
||||||
|
var pbNthStat *pb.FindHourlyServerBandwidthStatsResponse_Stat
|
||||||
|
percentileStat, err := models.SharedServerBandwidthStatDAO.FindPercentileBetweenTimes(tx, req.ServerId, timeFrom, timeTo, percentile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if percentileStat != nil {
|
||||||
|
pbNthStat = &pb.FindHourlyServerBandwidthStatsResponse_Stat{
|
||||||
|
Day: percentileStat.Day,
|
||||||
|
Hour: types.Int32(percentileStat.TimeAt[:2]),
|
||||||
|
Bytes: int64(percentileStat.Bytes),
|
||||||
|
Bits: int64(percentileStat.Bytes * 8),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &pb.FindHourlyServerBandwidthStatsResponse{
|
return &pb.FindHourlyServerBandwidthStatsResponse{
|
||||||
Stats: stats,
|
Stats: stats,
|
||||||
|
Percentile: percentile,
|
||||||
|
NthStat: pbNthStat,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,13 +238,52 @@ func (this *ServerBandwidthStatService) FindDailyServerBandwidthStats(ctx contex
|
|||||||
}
|
}
|
||||||
|
|
||||||
var tx = this.NullTx()
|
var tx = this.NullTx()
|
||||||
stats, err := models.SharedServerBandwidthStatDAO.FindDailyBandwidthStats(tx, req.ServerId, req.Days)
|
|
||||||
|
if req.Days <= 0 {
|
||||||
|
req.Days = 30
|
||||||
|
}
|
||||||
|
|
||||||
|
var timestamp = time.Now().Unix() - int64(req.Days)*86400
|
||||||
|
var dayFrom = timeutil.FormatTime("Ymd", timestamp)
|
||||||
|
var dayTo = timeutil.Format("Ymd")
|
||||||
|
|
||||||
|
stats, err := models.SharedServerBandwidthStatDAO.FindBandwidthStatsBetweenDays(tx, req.ServerId, dayFrom, dayTo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
var pbStats = []*pb.FindDailyServerBandwidthStatsResponse_Stat{}
|
||||||
|
for _, stat := range stats {
|
||||||
|
pbStats = append(pbStats, &pb.FindDailyServerBandwidthStatsResponse_Stat{
|
||||||
|
Day: stat.Day,
|
||||||
|
Bytes: stat.Bytes,
|
||||||
|
Bits: stat.Bytes * 8,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// percentile
|
||||||
|
var percentile = systemconfigs.DefaultBandwidthPercentile
|
||||||
|
userUIConfig, _ := models.SharedSysSettingDAO.ReadUserUIConfig(tx)
|
||||||
|
if userUIConfig != nil && userUIConfig.TrafficStats.BandwidthPercentile > 0 {
|
||||||
|
percentile = userUIConfig.TrafficStats.BandwidthPercentile
|
||||||
|
}
|
||||||
|
|
||||||
|
var pbNthStat = &pb.FindDailyServerBandwidthStatsResponse_Stat{}
|
||||||
|
percentileStat, err := models.SharedServerBandwidthStatDAO.FindPercentileBetweenDays(tx, req.ServerId, dayFrom, dayTo, percentile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if percentileStat != nil {
|
||||||
|
pbNthStat = &pb.FindDailyServerBandwidthStatsResponse_Stat{
|
||||||
|
Day: percentileStat.Day,
|
||||||
|
Bytes: int64(percentileStat.Bytes),
|
||||||
|
Bits: int64(percentileStat.Bytes * 8),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &pb.FindDailyServerBandwidthStatsResponse{
|
return &pb.FindDailyServerBandwidthStatsResponse{
|
||||||
Stats: stats,
|
Stats: pbStats,
|
||||||
|
Percentile: percentile,
|
||||||
|
NthStat: pbNthStat,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,13 +31,13 @@ func (this *ServerClientBrowserMonthlyStatService) FindTopServerClientBrowserMon
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
pbStats := []*pb.FindTopServerClientBrowserMonthlyStatsResponse_Stat{}
|
var pbStats = []*pb.FindTopServerClientBrowserMonthlyStatsResponse_Stat{}
|
||||||
for _, stat := range statList {
|
for _, stat := range statList {
|
||||||
pbStat := &pb.FindTopServerClientBrowserMonthlyStatsResponse_Stat{
|
pbStat := &pb.FindTopServerClientBrowserMonthlyStatsResponse_Stat{
|
||||||
Count: int64(stat.Count),
|
Count: int64(stat.Count),
|
||||||
Version: stat.Version,
|
Version: stat.Version,
|
||||||
}
|
}
|
||||||
browser, err := models.SharedClientBrowserDAO.FindEnabledClientBrowser(tx, int64(stat.BrowserId))
|
browser, err := models.SharedFormalClientBrowserDAO.FindEnabledFormalClientBrowser(tx, int64(stat.BrowserId))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,6 @@ func (this *ServerClientBrowserMonthlyStatService) FindTopServerClientBrowserMon
|
|||||||
Id: int64(browser.Id),
|
Id: int64(browser.Id),
|
||||||
Name: browser.Name,
|
Name: browser.Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
pbStats = append(pbStats, pbStat)
|
pbStats = append(pbStats, pbStat)
|
||||||
}
|
}
|
||||||
return &pb.FindTopServerClientBrowserMonthlyStatsResponse{Stats: pbStats}, nil
|
return &pb.FindTopServerClientBrowserMonthlyStatsResponse{Stats: pbStats}, nil
|
||||||
|
|||||||
@@ -31,13 +31,13 @@ func (this *ServerClientSystemMonthlyStatService) FindTopServerClientSystemMonth
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
pbStats := []*pb.FindTopServerClientSystemMonthlyStatsResponse_Stat{}
|
var pbStats = []*pb.FindTopServerClientSystemMonthlyStatsResponse_Stat{}
|
||||||
for _, stat := range statList {
|
for _, stat := range statList {
|
||||||
pbStat := &pb.FindTopServerClientSystemMonthlyStatsResponse_Stat{
|
pbStat := &pb.FindTopServerClientSystemMonthlyStatsResponse_Stat{
|
||||||
Count: int64(stat.Count),
|
Count: int64(stat.Count),
|
||||||
Version: stat.Version,
|
Version: stat.Version,
|
||||||
}
|
}
|
||||||
system, err := models.SharedClientSystemDAO.FindEnabledClientSystem(tx, int64(stat.SystemId))
|
system, err := models.SharedFormalClientSystemDAO.FindEnabledFormalClientSystem(tx, int64(stat.SystemId))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -465,7 +466,16 @@ func (this *ServerStatBoardService) ComposeServerStatBoard(ctx context.Context,
|
|||||||
{
|
{
|
||||||
var bandwidthMinutes = utils.RangeMinutes(time.Now(), 12, 5)
|
var bandwidthMinutes = utils.RangeMinutes(time.Now(), 12, 5)
|
||||||
var bandwidthStatMap = map[string]*pb.ServerBandwidthStat{}
|
var bandwidthStatMap = map[string]*pb.ServerBandwidthStat{}
|
||||||
|
var timeFrom = ""
|
||||||
|
var timeTo = ""
|
||||||
for _, r := range utils.GroupMinuteRanges(bandwidthMinutes) {
|
for _, r := range utils.GroupMinuteRanges(bandwidthMinutes) {
|
||||||
|
if len(timeFrom) == 0 || timeFrom > r.Day+r.MinuteFrom {
|
||||||
|
timeFrom = r.Day + r.MinuteFrom
|
||||||
|
}
|
||||||
|
if len(timeTo) == 0 || timeTo < r.Day+r.MinuteTo {
|
||||||
|
timeTo = r.Day + r.MinuteTo
|
||||||
|
}
|
||||||
|
|
||||||
bandwidthStats, err := models.SharedServerBandwidthStatDAO.FindServerStats(tx, req.ServerId, r.Day, r.MinuteFrom, r.MinuteTo)
|
bandwidthStats, err := models.SharedServerBandwidthStatDAO.FindServerStats(tx, req.ServerId, r.Day, r.MinuteFrom, r.MinuteTo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -499,6 +509,29 @@ func (this *ServerStatBoardService) ComposeServerStatBoard(ctx context.Context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.MinutelyBandwidthStats = pbBandwidthStats
|
result.MinutelyBandwidthStats = pbBandwidthStats
|
||||||
|
|
||||||
|
// percentile
|
||||||
|
if len(timeFrom) > 0 && len(timeTo) > 0 {
|
||||||
|
var percentile = systemconfigs.DefaultBandwidthPercentile
|
||||||
|
userUIConfig, _ := models.SharedSysSettingDAO.ReadUserUIConfig(tx)
|
||||||
|
if userUIConfig != nil && userUIConfig.TrafficStats.BandwidthPercentile > 0 {
|
||||||
|
percentile = userUIConfig.TrafficStats.BandwidthPercentile
|
||||||
|
}
|
||||||
|
result.BandwidthPercentile = percentile
|
||||||
|
|
||||||
|
percentileStat, err := models.SharedServerBandwidthStatDAO.FindPercentileBetweenTimes(tx, req.ServerId, timeFrom, timeTo, percentile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if percentileStat != nil {
|
||||||
|
result.MinutelyNthBandwidthStat = &pb.ServerBandwidthStat{
|
||||||
|
Day: percentileStat.Day,
|
||||||
|
TimeAt: percentileStat.TimeAt,
|
||||||
|
Bytes: int64(percentileStat.Bytes),
|
||||||
|
Bits: int64(percentileStat.Bytes * 8),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 按日流量统计
|
// 按日流量统计
|
||||||
|
|||||||
@@ -483,8 +483,16 @@ func (this *UserService) ComposeUserDashboard(ctx context.Context, req *pb.Compo
|
|||||||
var dailyTrafficStats = []*pb.ComposeUserDashboardResponse_DailyTrafficStat{}
|
var dailyTrafficStats = []*pb.ComposeUserDashboardResponse_DailyTrafficStat{}
|
||||||
var dailyPeekBandwidthStats = []*pb.ComposeUserDashboardResponse_DailyPeekBandwidthStat{}
|
var dailyPeekBandwidthStats = []*pb.ComposeUserDashboardResponse_DailyPeekBandwidthStat{}
|
||||||
|
|
||||||
|
var dayFrom = ""
|
||||||
|
var dayTo = ""
|
||||||
for i := 30; i >= 0; i-- {
|
for i := 30; i >= 0; i-- {
|
||||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -i))
|
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -i))
|
||||||
|
if len(dayFrom) == 0 {
|
||||||
|
dayFrom = day
|
||||||
|
}
|
||||||
|
if len(dayTo) == 0 || day > dayTo {
|
||||||
|
dayTo = day
|
||||||
|
}
|
||||||
|
|
||||||
// 流量
|
// 流量
|
||||||
trafficBytes, err := models.SharedServerDailyStatDAO.SumUserDaily(tx, req.UserId, 0, day)
|
trafficBytes, err := models.SharedServerDailyStatDAO.SumUserDaily(tx, req.UserId, 0, day)
|
||||||
@@ -505,8 +513,7 @@ func (this *UserService) ComposeUserDashboard(ctx context.Context, req *pb.Compo
|
|||||||
dailyTrafficStats = append(dailyTrafficStats, &pb.ComposeUserDashboardResponse_DailyTrafficStat{Day: day, Bytes: trafficBytes})
|
dailyTrafficStats = append(dailyTrafficStats, &pb.ComposeUserDashboardResponse_DailyTrafficStat{Day: day, Bytes: trafficBytes})
|
||||||
dailyPeekBandwidthStats = append(dailyPeekBandwidthStats, &pb.ComposeUserDashboardResponse_DailyPeekBandwidthStat{Day: day, Bytes: peekBandwidthBytes})
|
dailyPeekBandwidthStats = append(dailyPeekBandwidthStats, &pb.ComposeUserDashboardResponse_DailyPeekBandwidthStat{Day: day, Bytes: peekBandwidthBytes})
|
||||||
}
|
}
|
||||||
|
var result = &pb.ComposeUserDashboardResponse{
|
||||||
return &pb.ComposeUserDashboardResponse{
|
|
||||||
CountServers: countServers,
|
CountServers: countServers,
|
||||||
MonthlyTrafficBytes: monthlyTrafficBytes,
|
MonthlyTrafficBytes: monthlyTrafficBytes,
|
||||||
MonthlyPeekBandwidthBytes: monthlyPeekBandwidthBytes,
|
MonthlyPeekBandwidthBytes: monthlyPeekBandwidthBytes,
|
||||||
@@ -514,7 +521,24 @@ func (this *UserService) ComposeUserDashboard(ctx context.Context, req *pb.Compo
|
|||||||
DailyPeekBandwidthBytes: dailyPeekBandwidthBytes,
|
DailyPeekBandwidthBytes: dailyPeekBandwidthBytes,
|
||||||
DailyTrafficStats: dailyTrafficStats,
|
DailyTrafficStats: dailyTrafficStats,
|
||||||
DailyPeekBandwidthStats: dailyPeekBandwidthStats,
|
DailyPeekBandwidthStats: dailyPeekBandwidthStats,
|
||||||
}, nil
|
}
|
||||||
|
|
||||||
|
// 带宽百分位
|
||||||
|
var bandwidthPercentile = systemconfigs.DefaultBandwidthPercentile
|
||||||
|
userConfig, _ := models.SharedSysSettingDAO.ReadUserUIConfig(tx)
|
||||||
|
if userConfig != nil && userConfig.TrafficStats.BandwidthPercentile > 0 {
|
||||||
|
bandwidthPercentile = userConfig.TrafficStats.BandwidthPercentile
|
||||||
|
}
|
||||||
|
result.BandwidthPercentile = bandwidthPercentile
|
||||||
|
stat, err := models.SharedUserBandwidthStatDAO.FindPercentileBetweenDays(tx, req.UserId, 0, dayFrom, dayTo, bandwidthPercentile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if stat != nil {
|
||||||
|
result.BandwidthPercentileBits = int64(stat.Bytes) * 8
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindUserNodeClusterId 获取用户所在的集群ID
|
// FindUserNodeClusterId 获取用户所在的集群ID
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ type Setup struct {
|
|||||||
// 要返回的数据
|
// 要返回的数据
|
||||||
AdminNodeId string
|
AdminNodeId string
|
||||||
AdminNodeSecret string
|
AdminNodeSecret string
|
||||||
|
|
||||||
|
logFp *os.File
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSetup(config *Config) *Setup {
|
func NewSetup(config *Config) *Setup {
|
||||||
@@ -31,15 +33,15 @@ func NewSetup(config *Config) *Setup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewSetupFromCmd() *Setup {
|
func NewSetupFromCmd() *Setup {
|
||||||
args := cmd.ParseArgs(strings.Join(os.Args[1:], " "))
|
var args = cmd.ParseArgs(strings.Join(os.Args[1:], " "))
|
||||||
|
|
||||||
config := &Config{}
|
var config = &Config{}
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
index := strings.Index(arg, "=")
|
var index = strings.Index(arg, "=")
|
||||||
if index <= 0 {
|
if index <= 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
value := arg[index+1:]
|
var value = arg[index+1:]
|
||||||
value = strings.Trim(value, "\"'")
|
value = strings.Trim(value, "\"'")
|
||||||
switch arg[:index] {
|
switch arg[:index] {
|
||||||
case "-api-node-protocol":
|
case "-api-node-protocol":
|
||||||
@@ -51,7 +53,18 @@ func NewSetupFromCmd() *Setup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewSetup(config)
|
var setup = NewSetup(config)
|
||||||
|
|
||||||
|
// log writer
|
||||||
|
var tmpDir = os.TempDir()
|
||||||
|
if len(tmpDir) > 0 {
|
||||||
|
fp, err := os.OpenFile(tmpDir+"/edge-install.log", os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0666)
|
||||||
|
if err == nil {
|
||||||
|
setup.logFp = fp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return setup
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Setup) Run() error {
|
func (this *Setup) Run() error {
|
||||||
@@ -73,7 +86,7 @@ func (this *Setup) Run() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 执行SQL
|
// 执行SQL
|
||||||
config := &dbs.Config{}
|
var config = &dbs.Config{}
|
||||||
configData, err := os.ReadFile(Tea.ConfigFile("db.yaml"))
|
configData, err := os.ReadFile(Tea.ConfigFile("db.yaml"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -91,14 +104,22 @@ func (this *Setup) Run() error {
|
|||||||
return errors.New("can not find database config for env '" + Tea.Env + "'")
|
return errors.New("can not find database config for env '" + Tea.Env + "'")
|
||||||
}
|
}
|
||||||
|
|
||||||
executor := NewSQLExecutor(dbConfig)
|
var executor = NewSQLExecutor(dbConfig)
|
||||||
|
if this.logFp != nil {
|
||||||
|
executor.SetLogWriter(this.logFp)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = this.logFp.Close()
|
||||||
|
_ = os.Remove(this.logFp.Name())
|
||||||
|
}()
|
||||||
|
}
|
||||||
err = executor.Run(false)
|
err = executor.Run(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Admin节点信息
|
// Admin节点信息
|
||||||
apiTokenDAO := models.NewApiTokenDAO()
|
var apiTokenDAO = models.NewApiTokenDAO()
|
||||||
token, err := apiTokenDAO.FindEnabledTokenWithRole(nil, "admin")
|
token, err := apiTokenDAO.FindEnabledTokenWithRole(nil, "admin")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -110,7 +131,7 @@ func (this *Setup) Run() error {
|
|||||||
this.AdminNodeSecret = token.Secret
|
this.AdminNodeSecret = token.Secret
|
||||||
|
|
||||||
// 检查API节点
|
// 检查API节点
|
||||||
dao := models.NewAPINodeDAO()
|
var dao = models.NewAPINodeDAO()
|
||||||
apiNodeId, err := dao.FindEnabledAPINodeIdWithAddr(nil, this.config.APINodeProtocol, this.config.APINodeHost, this.config.APINodePort)
|
apiNodeId, err := dao.FindEnabledAPINodeIdWithAddr(nil, this.config.APINodeProtocol, this.config.APINodeHost, this.config.APINodePort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -175,7 +196,7 @@ func (this *Setup) Run() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 保存配置
|
// 保存配置
|
||||||
apiConfig := &configs.APIConfig{
|
var apiConfig = &configs.APIConfig{
|
||||||
NodeId: apiNode.UniqueId,
|
NodeId: apiNode.UniqueId,
|
||||||
Secret: apiNode.Secret,
|
Secret: apiNode.Secret,
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -7,7 +7,10 @@ import (
|
|||||||
"github.com/iwind/TeaGo/dbs"
|
"github.com/iwind/TeaGo/dbs"
|
||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
"github.com/iwind/TeaGo/types"
|
"github.com/iwind/TeaGo/types"
|
||||||
|
"io"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"runtime"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
@@ -38,6 +41,14 @@ var recordsTables = []*SQLRecordsTable{
|
|||||||
UniqueFields: []string{"name"},
|
UniqueFields: []string{"name"},
|
||||||
ExceptFields: []string{"customName", "customCodes"},
|
ExceptFields: []string{"customName", "customCodes"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
TableName: "edgeFormalClientSystems",
|
||||||
|
UniqueFields: []string{"dataId"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
TableName: "edgeFormalClientBrowsers",
|
||||||
|
UniqueFields: []string{"dataId"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
type sqlItem struct {
|
type sqlItem struct {
|
||||||
@@ -46,21 +57,36 @@ type sqlItem struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SQLDump struct {
|
type SQLDump struct {
|
||||||
|
logWriter io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSQLDump() *SQLDump {
|
func NewSQLDump() *SQLDump {
|
||||||
return &SQLDump{}
|
return &SQLDump{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *SQLDump) SetLogWriter(logWriter io.Writer) {
|
||||||
|
this.logWriter = logWriter
|
||||||
|
}
|
||||||
|
|
||||||
// Dump 导出数据
|
// Dump 导出数据
|
||||||
func (this *SQLDump) Dump(db *dbs.DB) (result *SQLDumpResult, err error) {
|
func (this *SQLDump) Dump(db *dbs.DB, includingRecords bool) (result *SQLDumpResult, err error) {
|
||||||
result = &SQLDumpResult{}
|
result = &SQLDumpResult{}
|
||||||
|
|
||||||
tableNames, err := db.TableNames()
|
tableNames, err := db.TableNames()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
for _, tableName := range tableNames {
|
|
||||||
|
fullTableMap, err := this.findFullTables(db, tableNames)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var autoIncrementReg = regexp.MustCompile(` AUTO_INCREMENT=\d+`)
|
||||||
|
|
||||||
|
for _, table := range fullTableMap {
|
||||||
|
var tableName = table.Name
|
||||||
|
|
||||||
// 忽略一些分表
|
// 忽略一些分表
|
||||||
if strings.HasPrefix(strings.ToLower(tableName), strings.ToLower("edgeHTTPAccessLogs_")) {
|
if strings.HasPrefix(strings.ToLower(tableName), strings.ToLower("edgeHTTPAccessLogs_")) {
|
||||||
continue
|
continue
|
||||||
@@ -69,15 +95,11 @@ func (this *SQLDump) Dump(db *dbs.DB) (result *SQLDumpResult, err error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
table, err := db.FindFullTable(tableName)
|
var sqlTable = &SQLTable{
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
sqlTable := &SQLTable{
|
|
||||||
Name: table.Name,
|
Name: table.Name,
|
||||||
Engine: table.Engine,
|
Engine: table.Engine,
|
||||||
Charset: table.Collation,
|
Charset: table.Collation,
|
||||||
Definition: regexp.MustCompile(` AUTO_INCREMENT=\d+`).ReplaceAllString(table.Code, ""),
|
Definition: autoIncrementReg.ReplaceAllString(table.Code, ""),
|
||||||
}
|
}
|
||||||
|
|
||||||
// 字段
|
// 字段
|
||||||
@@ -102,28 +124,30 @@ func (this *SQLDump) Dump(db *dbs.DB) (result *SQLDumpResult, err error) {
|
|||||||
|
|
||||||
// Records
|
// Records
|
||||||
var records = []*SQLRecord{}
|
var records = []*SQLRecord{}
|
||||||
recordsTable := this.findRecordsTable(tableName)
|
if includingRecords {
|
||||||
if recordsTable != nil {
|
recordsTable := this.findRecordsTable(tableName)
|
||||||
ones, _, err := db.FindOnes("SELECT * FROM " + tableName + " ORDER BY id ASC")
|
if recordsTable != nil {
|
||||||
if err != nil {
|
ones, _, err := db.FindOnes("SELECT * FROM " + tableName + " ORDER BY id ASC")
|
||||||
return result, err
|
if err != nil {
|
||||||
}
|
return result, err
|
||||||
for _, one := range ones {
|
|
||||||
record := &SQLRecord{
|
|
||||||
Id: one.GetInt64("id"),
|
|
||||||
Values: map[string]string{},
|
|
||||||
UniqueFields: recordsTable.UniqueFields,
|
|
||||||
ExceptFields: recordsTable.ExceptFields,
|
|
||||||
}
|
}
|
||||||
for k, v := range one {
|
for _, one := range ones {
|
||||||
// 需要排除的字段
|
record := &SQLRecord{
|
||||||
if lists.ContainsString(record.ExceptFields, k) {
|
Id: one.GetInt64("id"),
|
||||||
continue
|
Values: map[string]string{},
|
||||||
|
UniqueFields: recordsTable.UniqueFields,
|
||||||
|
ExceptFields: recordsTable.ExceptFields,
|
||||||
}
|
}
|
||||||
|
for k, v := range one {
|
||||||
|
// 需要排除的字段
|
||||||
|
if lists.ContainsString(record.ExceptFields, k) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
record.Values[k] = types.String(v)
|
record.Values[k] = types.String(v)
|
||||||
|
}
|
||||||
|
records = append(records, record)
|
||||||
}
|
}
|
||||||
records = append(records, record)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlTable.Records = records
|
sqlTable.Records = records
|
||||||
@@ -218,7 +242,7 @@ func (this *SQLDump) applyQueue(db *dbs.DB, newResult *SQLDumpResult, showLog bo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
currentResult, err := this.Dump(db)
|
currentResult, err := this.Dump(db, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -230,7 +254,7 @@ func (this *SQLDump) applyQueue(db *dbs.DB, newResult *SQLDumpResult, showLog bo
|
|||||||
var op = "+ table " + newTable.Name
|
var op = "+ table " + newTable.Name
|
||||||
ops = append(ops, op)
|
ops = append(ops, op)
|
||||||
if showLog {
|
if showLog {
|
||||||
fmt.Println(op)
|
this.log(op)
|
||||||
}
|
}
|
||||||
if len(newTable.Records) == 0 {
|
if len(newTable.Records) == 0 {
|
||||||
execSQL(newTable.Definition)
|
execSQL(newTable.Definition)
|
||||||
@@ -249,7 +273,7 @@ func (this *SQLDump) applyQueue(db *dbs.DB, newResult *SQLDumpResult, showLog bo
|
|||||||
var op = "+ " + newTable.Name + " " + newField.Name
|
var op = "+ " + newTable.Name + " " + newField.Name
|
||||||
ops = append(ops, op)
|
ops = append(ops, op)
|
||||||
if showLog {
|
if showLog {
|
||||||
fmt.Println(op)
|
this.log(op)
|
||||||
}
|
}
|
||||||
_, err = db.Exec("ALTER TABLE " + newTable.Name + " ADD `" + newField.Name + "` " + newField.Definition)
|
_, err = db.Exec("ALTER TABLE " + newTable.Name + " ADD `" + newField.Name + "` " + newField.Definition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -259,7 +283,7 @@ func (this *SQLDump) applyQueue(db *dbs.DB, newResult *SQLDumpResult, showLog bo
|
|||||||
var op = "* " + newTable.Name + " " + newField.Name
|
var op = "* " + newTable.Name + " " + newField.Name
|
||||||
ops = append(ops, op)
|
ops = append(ops, op)
|
||||||
if showLog {
|
if showLog {
|
||||||
fmt.Println(op)
|
this.log(op)
|
||||||
}
|
}
|
||||||
_, err = db.Exec("ALTER TABLE " + newTable.Name + " MODIFY `" + newField.Name + "` " + newField.Definition)
|
_, err = db.Exec("ALTER TABLE " + newTable.Name + " MODIFY `" + newField.Name + "` " + newField.Definition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -276,7 +300,7 @@ func (this *SQLDump) applyQueue(db *dbs.DB, newResult *SQLDumpResult, showLog bo
|
|||||||
var op = "+ index " + newTable.Name + " " + newIndex.Name
|
var op = "+ index " + newTable.Name + " " + newIndex.Name
|
||||||
ops = append(ops, op)
|
ops = append(ops, op)
|
||||||
if showLog {
|
if showLog {
|
||||||
fmt.Println(op)
|
this.log(op)
|
||||||
}
|
}
|
||||||
_, err = db.Exec("ALTER TABLE " + newTable.Name + " ADD " + newIndex.Definition)
|
_, err = db.Exec("ALTER TABLE " + newTable.Name + " ADD " + newIndex.Definition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -289,7 +313,7 @@ func (this *SQLDump) applyQueue(db *dbs.DB, newResult *SQLDumpResult, showLog bo
|
|||||||
var op = "* index " + newTable.Name + " " + newIndex.Name
|
var op = "* index " + newTable.Name + " " + newIndex.Name
|
||||||
ops = append(ops, op)
|
ops = append(ops, op)
|
||||||
if showLog {
|
if showLog {
|
||||||
fmt.Println(op)
|
this.log(op)
|
||||||
}
|
}
|
||||||
_, err = db.Exec("ALTER TABLE " + newTable.Name + " DROP KEY " + newIndex.Name)
|
_, err = db.Exec("ALTER TABLE " + newTable.Name + " DROP KEY " + newIndex.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -312,7 +336,7 @@ func (this *SQLDump) applyQueue(db *dbs.DB, newResult *SQLDumpResult, showLog bo
|
|||||||
var op = "- index " + oldTable.Name + " " + oldIndex.Name
|
var op = "- index " + oldTable.Name + " " + oldIndex.Name
|
||||||
ops = append(ops, op)
|
ops = append(ops, op)
|
||||||
if showLog {
|
if showLog {
|
||||||
fmt.Println(op)
|
this.log(op)
|
||||||
}
|
}
|
||||||
_, err = db.Exec("ALTER TABLE " + oldTable.Name + " DROP KEY " + oldIndex.Name)
|
_, err = db.Exec("ALTER TABLE " + oldTable.Name + " DROP KEY " + oldIndex.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -329,7 +353,7 @@ func (this *SQLDump) applyQueue(db *dbs.DB, newResult *SQLDumpResult, showLog bo
|
|||||||
var op = "- field " + oldTable.Name + " " + oldField.Name
|
var op = "- field " + oldTable.Name + " " + oldField.Name
|
||||||
ops = append(ops, op)
|
ops = append(ops, op)
|
||||||
if showLog {
|
if showLog {
|
||||||
fmt.Println(op)
|
this.log(op)
|
||||||
}
|
}
|
||||||
_, err = db.Exec("ALTER TABLE " + oldTable.Name + " DROP COLUMN `" + oldField.Name + "`")
|
_, err = db.Exec("ALTER TABLE " + oldTable.Name + " DROP COLUMN `" + oldField.Name + "`")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -343,7 +367,7 @@ func (this *SQLDump) applyQueue(db *dbs.DB, newResult *SQLDumpResult, showLog bo
|
|||||||
// +
|
// +
|
||||||
for _, record := range newTable.Records {
|
for _, record := range newTable.Records {
|
||||||
var queryArgs = []string{}
|
var queryArgs = []string{}
|
||||||
var queryValues = []interface{}{}
|
var queryValues = []any{}
|
||||||
var valueStrings = []string{}
|
var valueStrings = []string{}
|
||||||
for _, field := range record.UniqueFields {
|
for _, field := range record.UniqueFields {
|
||||||
queryArgs = append(queryArgs, field+"=?")
|
queryArgs = append(queryArgs, field+"=?")
|
||||||
@@ -367,7 +391,7 @@ func (this *SQLDump) applyQueue(db *dbs.DB, newResult *SQLDumpResult, showLog bo
|
|||||||
if one == nil {
|
if one == nil {
|
||||||
ops = append(ops, "+ record "+newTable.Name+" "+strings.Join(valueStrings, ", "))
|
ops = append(ops, "+ record "+newTable.Name+" "+strings.Join(valueStrings, ", "))
|
||||||
if showLog {
|
if showLog {
|
||||||
fmt.Println("+ record " + newTable.Name + " " + strings.Join(valueStrings, ", "))
|
this.log("+ record " + newTable.Name + " " + strings.Join(valueStrings, ", "))
|
||||||
}
|
}
|
||||||
var params = []string{}
|
var params = []string{}
|
||||||
var args = []string{}
|
var args = []string{}
|
||||||
@@ -388,10 +412,10 @@ func (this *SQLDump) applyQueue(db *dbs.DB, newResult *SQLDumpResult, showLog bo
|
|||||||
} else if !record.ValuesEquals(one) {
|
} else if !record.ValuesEquals(one) {
|
||||||
ops = append(ops, "* record "+newTable.Name+" "+strings.Join(valueStrings, ", "))
|
ops = append(ops, "* record "+newTable.Name+" "+strings.Join(valueStrings, ", "))
|
||||||
if showLog {
|
if showLog {
|
||||||
fmt.Println("* record " + newTable.Name + " " + strings.Join(valueStrings, ", "))
|
this.log("* record " + newTable.Name + " " + strings.Join(valueStrings, ", "))
|
||||||
}
|
}
|
||||||
args := []string{}
|
var args = []string{}
|
||||||
values := []interface{}{}
|
var values = []any{}
|
||||||
for k, v := range record.Values {
|
for k, v := range record.Values {
|
||||||
if k == "id" {
|
if k == "id" {
|
||||||
continue
|
continue
|
||||||
@@ -418,6 +442,65 @@ func (this *SQLDump) applyQueue(db *dbs.DB, newResult *SQLDumpResult, showLog bo
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查找所有表的完整信息
|
||||||
|
func (this *SQLDump) findFullTables(db *dbs.DB, tableNames []string) ([]*dbs.Table, error) {
|
||||||
|
var fullTables = []*dbs.Table{}
|
||||||
|
if len(tableNames) == 0 {
|
||||||
|
return fullTables, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var locker = &sync.Mutex{}
|
||||||
|
var queue = make(chan string, len(tableNames))
|
||||||
|
for _, tableName := range tableNames {
|
||||||
|
queue <- tableName
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg = &sync.WaitGroup{}
|
||||||
|
var concurrent = 8
|
||||||
|
|
||||||
|
if runtime.NumCPU() > 4 {
|
||||||
|
concurrent = 32
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Add(concurrent)
|
||||||
|
var lastErr error
|
||||||
|
for i := 0; i < concurrent; i++ {
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case tableName := <-queue:
|
||||||
|
table, err := db.FindFullTable(tableName)
|
||||||
|
if err != nil {
|
||||||
|
locker.Lock()
|
||||||
|
lastErr = err
|
||||||
|
locker.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
locker.Lock()
|
||||||
|
table.Name = tableName
|
||||||
|
fullTables = append(fullTables, table)
|
||||||
|
locker.Unlock()
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
if lastErr != nil {
|
||||||
|
return nil, lastErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// 排序
|
||||||
|
sort.Slice(fullTables, func(i, j int) bool {
|
||||||
|
return fullTables[i].Name < fullTables[j].Name
|
||||||
|
})
|
||||||
|
|
||||||
|
return fullTables, nil
|
||||||
|
}
|
||||||
|
|
||||||
// 查找有记录的表
|
// 查找有记录的表
|
||||||
func (this *SQLDump) findRecordsTable(tableName string) *SQLRecordsTable {
|
func (this *SQLDump) findRecordsTable(tableName string) *SQLRecordsTable {
|
||||||
for _, table := range recordsTables {
|
for _, table := range recordsTables {
|
||||||
@@ -458,3 +541,12 @@ func (this *SQLDump) tryCreateIndex(err error, db *dbs.DB, tableName string, ind
|
|||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 打印操作日志
|
||||||
|
func (this *SQLDump) log(message string) {
|
||||||
|
if this.logWriter != nil {
|
||||||
|
_, _ = this.logWriter.Write([]byte(message + "\n"))
|
||||||
|
} else {
|
||||||
|
fmt.Println(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func TestSQLDump_Dump(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
dump := NewSQLDump()
|
dump := NewSQLDump()
|
||||||
result, err := dump.Dump(db)
|
result, err := dump.Dump(db, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ func TestSQLDump_Apply(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
var dump = NewSQLDump()
|
var dump = NewSQLDump()
|
||||||
result, err := dump.Dump(db)
|
result, err := dump.Dump(db, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/iwind/TeaGo/types"
|
"github.com/iwind/TeaGo/types"
|
||||||
stringutil "github.com/iwind/TeaGo/utils/string"
|
stringutil "github.com/iwind/TeaGo/utils/string"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -22,7 +23,8 @@ var LatestSQLResult = &SQLDumpResult{}
|
|||||||
|
|
||||||
// SQLExecutor 安装或升级SQL执行器
|
// SQLExecutor 安装或升级SQL执行器
|
||||||
type SQLExecutor struct {
|
type SQLExecutor struct {
|
||||||
dbConfig *dbs.DBConfig
|
dbConfig *dbs.DBConfig
|
||||||
|
logWriter io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSQLExecutor(dbConfig *dbs.DBConfig) *SQLExecutor {
|
func NewSQLExecutor(dbConfig *dbs.DBConfig) *SQLExecutor {
|
||||||
@@ -33,7 +35,7 @@ func NewSQLExecutor(dbConfig *dbs.DBConfig) *SQLExecutor {
|
|||||||
|
|
||||||
func NewSQLExecutorFromCmd() (*SQLExecutor, error) {
|
func NewSQLExecutorFromCmd() (*SQLExecutor, error) {
|
||||||
// 执行SQL
|
// 执行SQL
|
||||||
config := &dbs.Config{}
|
var config = &dbs.Config{}
|
||||||
configData, err := os.ReadFile(Tea.ConfigFile("db.yaml"))
|
configData, err := os.ReadFile(Tea.ConfigFile("db.yaml"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -45,6 +47,10 @@ func NewSQLExecutorFromCmd() (*SQLExecutor, error) {
|
|||||||
return NewSQLExecutor(config.DBs[Tea.Env]), nil
|
return NewSQLExecutor(config.DBs[Tea.Env]), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *SQLExecutor) SetLogWriter(logWriter io.Writer) {
|
||||||
|
this.logWriter = logWriter
|
||||||
|
}
|
||||||
|
|
||||||
func (this *SQLExecutor) Run(showLog bool) error {
|
func (this *SQLExecutor) Run(showLog bool) error {
|
||||||
db, err := dbs.NewInstanceFromConfig(this.dbConfig)
|
db, err := dbs.NewInstanceFromConfig(this.dbConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -55,7 +61,11 @@ func (this *SQLExecutor) Run(showLog bool) error {
|
|||||||
_ = db.Close()
|
_ = db.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
sqlDump := NewSQLDump()
|
var sqlDump = NewSQLDump()
|
||||||
|
sqlDump.SetLogWriter(this.logWriter)
|
||||||
|
if this.logWriter != nil {
|
||||||
|
showLog = true
|
||||||
|
}
|
||||||
_, err = sqlDump.Apply(db, LatestSQLResult, showLog)
|
_, err = sqlDump.Apply(db, LatestSQLResult, showLog)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -307,12 +317,12 @@ func (this *SQLExecutor) checkIPList(db *dbs.DB) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 创建名单
|
// 创建名单
|
||||||
_, err = db.Exec("INSERT INTO edgeIPLists(name, type, code, isPublic, createdAt) VALUES (?, ?, ?, ?, ?)", "公共黑名单", "black", "black", 1, time.Now().Unix())
|
_, err = db.Exec("INSERT INTO edgeIPLists(name, type, code, isPublic, isGlobal, createdAt) VALUES (?, ?, ?, ?, ?, ?)", "公共黑名单", "black", "black", 1, 1, time.Now().Unix())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = db.Exec("INSERT INTO edgeIPLists(name, type, code, isPublic, createdAt) VALUES (?, ?, ?, ?, ?)", "公共白名单", "white", "white", 1, time.Now().Unix())
|
_, err = db.Exec("INSERT INTO edgeIPLists(name, type, code, isPublic, isGlobal, createdAt) VALUES (?, ?, ?, ?, ?, ?)", "公共白名单", "white", "white", 1, 1, time.Now().Unix())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,10 +83,13 @@ var upgradeFuncs = []*upgradeVersion{
|
|||||||
"0.4.11", upgradeV0_4_11,
|
"0.4.11", upgradeV0_4_11,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"v0.5.3", upgradeV0_5_3,
|
"0.5.3", upgradeV0_5_3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"v0.5.6", upgradeV0_5_6,
|
"0.5.6", upgradeV0_5_6,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0.5.8", upgradeV0_5_8,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||||
"github.com/iwind/TeaGo/dbs"
|
"github.com/iwind/TeaGo/dbs"
|
||||||
"github.com/iwind/TeaGo/types"
|
"github.com/iwind/TeaGo/types"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -176,3 +177,39 @@ func upgradeV0_5_6(db *dbs.DB) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// v0.5.7
|
||||||
|
func upgradeV0_5_8(db *dbs.DB) error {
|
||||||
|
// node task versions
|
||||||
|
{
|
||||||
|
_, err := db.Exec("UPDATE edgeNodeTasks SET version=0 WHERE LENGTH(version)=19")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除操作系统和浏览器相关统计
|
||||||
|
// 只删除当前月,避免因为数据过多阻塞
|
||||||
|
{
|
||||||
|
_, err := db.Exec("DELETE FROM edgeServerClientSystemMonthlyStats WHERE month=?", timeutil.Format("Ym"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
_, err := db.Exec("DELETE FROM edgeServerClientBrowserMonthlyStats WHERE month=?", timeutil.Format("Ym"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修复默认黑白名单不是全局的问题
|
||||||
|
{
|
||||||
|
_, err := db.Exec("UPDATE edgeIPLists SET isGlobal=1 WHERE id IN (1, 2)")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -251,3 +251,4 @@ func TestUpgradeSQLData_v0_5_3(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Log("ok")
|
t.Log("ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ func (this *DNSTaskExecutor) loop() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case dnsmodels.DNSTaskTypeNodeChange:
|
case dnsmodels.DNSTaskTypeNodeChange:
|
||||||
err = this.doNode(taskId, int64(task.NodeId))
|
err = this.doNode(taskId, int64(task.ClusterId), int64(task.NodeId))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = dnsmodels.SharedDNSTaskDAO.UpdateDNSTaskError(nil, taskId, err.Error())
|
err = dnsmodels.SharedDNSTaskDAO.UpdateDNSTaskError(nil, taskId, err.Error())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -269,8 +269,8 @@ func (this *DNSTaskExecutor) doServer(taskId int64, oldClusterId int64, serverId
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 修改节点相关记录
|
// 修改节点相关记录
|
||||||
func (this *DNSTaskExecutor) doNode(taskId int64, nodeId int64) error {
|
func (this *DNSTaskExecutor) doNode(taskId int64, nodeClusterId int64, nodeId int64) error {
|
||||||
isOk := false
|
var isOk = false
|
||||||
defer func() {
|
defer func() {
|
||||||
if isOk {
|
if isOk {
|
||||||
err := dnsmodels.SharedDNSTaskDAO.UpdateDNSTaskDone(nil, taskId)
|
err := dnsmodels.SharedDNSTaskDAO.UpdateDNSTaskDone(nil, taskId)
|
||||||
@@ -291,15 +291,22 @@ func (this *DNSTaskExecutor) doNode(taskId int64, nodeId int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 转交给cluster统一处理
|
// 转交给cluster统一处理
|
||||||
clusterIds, err := models.SharedNodeDAO.FindEnabledAndOnNodeClusterIds(tx, nodeId)
|
if nodeClusterId > 0 {
|
||||||
if err != nil {
|
err = dnsmodels.SharedDNSTaskDAO.CreateClusterTask(tx, nodeClusterId, dnsmodels.DNSTaskTypeClusterChange)
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, clusterId := range clusterIds {
|
|
||||||
err = dnsmodels.SharedDNSTaskDAO.CreateClusterTask(tx, clusterId, dnsmodels.DNSTaskTypeClusterChange)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
clusterIds, err := models.SharedNodeDAO.FindEnabledAndOnNodeClusterIds(tx, nodeId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, clusterId := range clusterIds {
|
||||||
|
err = dnsmodels.SharedDNSTaskDAO.CreateClusterTask(tx, clusterId, dnsmodels.DNSTaskTypeClusterChange)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isOk = true
|
isOk = true
|
||||||
@@ -361,6 +368,7 @@ func (this *DNSTaskExecutor) doCluster(taskId int64, clusterId int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var isChanged = false
|
var isChanged = false
|
||||||
|
var addingNodeRecordKeysMap = map[string]bool{} // clusterDnsName_type_ip_route
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
routes, err := node.DNSRouteCodesForDomainId(domainId)
|
routes, err := node.DNSRouteCodesForDomainId(domainId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -398,6 +406,14 @@ func (this *DNSTaskExecutor) doCluster(taskId int64, clusterId int64) error {
|
|||||||
if utils.IsIPv6(ip) {
|
if utils.IsIPv6(ip) {
|
||||||
recordType = dnstypes.RecordTypeAAAA
|
recordType = dnstypes.RecordTypeAAAA
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 避免添加重复的记录
|
||||||
|
var fullKey = clusterDNSName + "_" + recordType + "_" + ip + "_" + route
|
||||||
|
if addingNodeRecordKeysMap[fullKey] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
addingNodeRecordKeysMap[fullKey] = true
|
||||||
|
|
||||||
err = manager.AddRecord(domain, &dnstypes.Record{
|
err = manager.AddRecord(domain, &dnstypes.Record{
|
||||||
Id: "",
|
Id: "",
|
||||||
Name: clusterDNSName,
|
Name: clusterDNSName,
|
||||||
|
|||||||
@@ -64,11 +64,11 @@ func (this *HealthCheckClusterTask) Run() {
|
|||||||
if this.config.Interval == nil {
|
if this.config.Interval == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
duration := this.config.Interval.Duration()
|
var duration = this.config.Interval.Duration()
|
||||||
if duration <= 0 {
|
if duration <= 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ticker := utils.NewTicker(duration)
|
var ticker = utils.NewTicker(duration)
|
||||||
goman.New(func() {
|
goman.New(func() {
|
||||||
for ticker.Wait() {
|
for ticker.Wait() {
|
||||||
err := this.Loop()
|
err := this.Loop()
|
||||||
|
|||||||
@@ -38,8 +38,9 @@ func (this *HealthCheckExecutor) Run() ([]*HealthCheckResult, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if cluster == nil {
|
if cluster == nil || !cluster.IsOn {
|
||||||
return nil, errors.New("can not find cluster with id '" + strconv.FormatInt(this.clusterId, 10) + "'")
|
// 如果节点已经被删除,则不提示错误
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
if !cluster.HealthCheck.IsNotNull() {
|
if !cluster.HealthCheck.IsNotNull() {
|
||||||
return nil, errors.New("health check config is not found")
|
return nil, errors.New("health check config is not found")
|
||||||
@@ -52,10 +53,16 @@ func (this *HealthCheckExecutor) Run() ([]*HealthCheckResult, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var results = []*HealthCheckResult{}
|
var results = []*HealthCheckResult{}
|
||||||
|
|
||||||
|
// 查询集群下的节点
|
||||||
nodes, err := models.NewNodeDAO().FindAllEnabledNodesWithClusterId(nil, this.clusterId, false)
|
nodes, err := models.NewNodeDAO().FindAllEnabledNodesWithClusterId(nil, this.clusterId, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if len(nodes) == 0 {
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
if !node.IsOn {
|
if !node.IsOn {
|
||||||
continue
|
continue
|
||||||
@@ -115,7 +122,7 @@ func (this *HealthCheckExecutor) Run() ([]*HealthCheckResult, error) {
|
|||||||
|
|
||||||
var concurrent = 128
|
var concurrent = 128
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
var wg = sync.WaitGroup{}
|
||||||
wg.Add(countResults)
|
wg.Add(countResults)
|
||||||
for i := 0; i < concurrent; i++ {
|
for i := 0; i < concurrent; i++ {
|
||||||
go func() {
|
go func() {
|
||||||
@@ -160,24 +167,27 @@ func (this *HealthCheckExecutor) runNode(healthCheckConfig *serverconfigs.Health
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isChanged {
|
if isChanged {
|
||||||
// 发送消息
|
// 在线状态发生变化
|
||||||
var message = ""
|
if healthCheckConfig.AutoDown {
|
||||||
var messageType string
|
// 发送消息
|
||||||
var messageLevel string
|
var message = ""
|
||||||
if result.IsOk {
|
var messageType string
|
||||||
message = "健康检查成功,节点\"" + result.Node.Name + "\",IP\"" + result.NodeAddr + "\"已恢复上线"
|
var messageLevel string
|
||||||
messageType = models.MessageTypeHealthCheckNodeUp
|
if result.IsOk {
|
||||||
messageLevel = models.MessageLevelSuccess
|
message = "健康检查成功,节点\"" + result.Node.Name + "\",IP\"" + result.NodeAddr + "\"已恢复上线"
|
||||||
} else {
|
messageType = models.MessageTypeHealthCheckNodeUp
|
||||||
message = "健康检查失败,节点\"" + result.Node.Name + "\",IP\"" + result.NodeAddr + "\"已自动下线"
|
messageLevel = models.MessageLevelSuccess
|
||||||
messageType = models.MessageTypeHealthCheckNodeDown
|
} else {
|
||||||
messageLevel = models.MessageLevelError
|
message = "健康检查失败,节点\"" + result.Node.Name + "\",IP\"" + result.NodeAddr + "\"已自动下线"
|
||||||
}
|
messageType = models.MessageTypeHealthCheckNodeDown
|
||||||
|
messageLevel = models.MessageLevelError
|
||||||
|
}
|
||||||
|
|
||||||
err = models.NewMessageDAO().CreateNodeMessage(nil, nodeconfigs.NodeRoleNode, this.clusterId, int64(result.Node.Id), messageType, messageLevel, message, message, nil, false)
|
err = models.NewMessageDAO().CreateNodeMessage(nil, nodeconfigs.NodeRoleNode, this.clusterId, int64(result.Node.Id), messageType, messageLevel, message, message, nil, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.logErr("HealthCheckExecutor", err.Error())
|
this.logErr("HealthCheckExecutor", err.Error())
|
||||||
return
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 触发阈值
|
// 触发阈值
|
||||||
@@ -188,8 +198,10 @@ func (this *HealthCheckExecutor) runNode(healthCheckConfig *serverconfigs.Health
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 我们只处理IP的上下线,不修改节点的状态
|
// 结束处理 ,因为我们只处理IP的上下线,不修改节点的状态
|
||||||
return
|
if healthCheckConfig.AutoDown {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改节点状态
|
// 修改节点状态
|
||||||
@@ -206,6 +218,24 @@ func (this *HealthCheckExecutor) runNode(healthCheckConfig *serverconfigs.Health
|
|||||||
message := "健康检查失败,节点\"" + result.Node.Name + "\"已自动下线"
|
message := "健康检查失败,节点\"" + result.Node.Name + "\"已自动下线"
|
||||||
err = models.NewMessageDAO().CreateNodeMessage(nil, nodeconfigs.NodeRoleNode, this.clusterId, int64(result.Node.Id), models.MessageTypeHealthCheckNodeDown, models.MessageLevelError, message, message, nil, false)
|
err = models.NewMessageDAO().CreateNodeMessage(nil, nodeconfigs.NodeRoleNode, this.clusterId, int64(result.Node.Id), models.MessageTypeHealthCheckNodeDown, models.MessageLevelError, message, message, nil, false)
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
this.logErr("HealthCheckExecutor", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 通知健康检查结果
|
||||||
|
var err error
|
||||||
|
if result.IsOk {
|
||||||
|
message := "节点\"" + result.Node.Name + "\"健康检查成功"
|
||||||
|
err = models.NewMessageDAO().CreateNodeMessage(nil, nodeconfigs.NodeRoleNode, this.clusterId, int64(result.Node.Id), models.MessageTypeHealthCheckNodeUp, models.MessageLevelSuccess, message, message, nil, false)
|
||||||
|
} else {
|
||||||
|
message := "节点\"" + result.Node.Name + "\"健康检查失败"
|
||||||
|
err = models.NewMessageDAO().CreateNodeMessage(nil, nodeconfigs.NodeRoleNode, this.clusterId, int64(result.Node.Id), models.MessageTypeHealthCheckNodeDown, models.MessageLevelError, message, message, nil, false)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
this.logErr("HealthCheckExecutor", err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -259,7 +289,7 @@ func (this *HealthCheckExecutor) runNodeOnce(healthCheckConfig *serverconfigs.He
|
|||||||
MaxIdleConns: 1,
|
MaxIdleConns: 1,
|
||||||
MaxIdleConnsPerHost: 1,
|
MaxIdleConnsPerHost: 1,
|
||||||
MaxConnsPerHost: 1,
|
MaxConnsPerHost: 1,
|
||||||
IdleConnTimeout: 2 * time.Minute,
|
IdleConnTimeout: 10 * time.Second,
|
||||||
ExpectContinueTimeout: 1 * time.Second,
|
ExpectContinueTimeout: 1 * time.Second,
|
||||||
TLSHandshakeTimeout: 0,
|
TLSHandshakeTimeout: 0,
|
||||||
TLSClientConfig: &tls.Config{
|
TLSClientConfig: &tls.Config{
|
||||||
|
|||||||
@@ -70,7 +70,16 @@ func (this *HealthCheckTask) Loop() error {
|
|||||||
|
|
||||||
// 启动新的或更新老的
|
// 启动新的或更新老的
|
||||||
for _, cluster := range clusters {
|
for _, cluster := range clusters {
|
||||||
clusterId := int64(cluster.Id)
|
var clusterId = int64(cluster.Id)
|
||||||
|
|
||||||
|
// 检查当前集群上是否有服务,如果尚没有部署服务,则直接跳过
|
||||||
|
countServers, err := models.SharedServerDAO.CountAllEnabledServersWithNodeClusterId(nil, clusterId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if countServers == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
var config = &serverconfigs.HealthCheckConfig{}
|
var config = &serverconfigs.HealthCheckConfig{}
|
||||||
if len(cluster.HealthCheck) > 0 {
|
if len(cluster.HealthCheck) > 0 {
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ func (this *SSLCertExpireCheckExecutor) Loop() error {
|
|||||||
}
|
}
|
||||||
for _, cert := range certs {
|
for _, cert := range certs {
|
||||||
// 发送消息
|
// 发送消息
|
||||||
subject := "SSL证书\"" + cert.Name + "\"在" + strconv.Itoa(days) + "天后将到期,"
|
var subject = "SSL证书\"" + cert.Name + "\"在" + strconv.Itoa(days) + "天后将到期,"
|
||||||
msg := "SSL证书\"" + cert.Name + "\"(" + string(cert.DnsNames) + ")在" + strconv.Itoa(days) + "天后将到期,"
|
var msg = "SSL证书\"" + cert.Name + "\"(" + string(cert.DnsNames) + ")在" + strconv.Itoa(days) + "天后将到期,"
|
||||||
|
|
||||||
// 是否有自动更新任务
|
// 是否有自动更新任务
|
||||||
if cert.AcmeTaskId > 0 {
|
if cert.AcmeTaskId > 0 {
|
||||||
@@ -185,9 +185,9 @@ func (this *SSLCertExpireCheckExecutor) Loop() error {
|
|||||||
}
|
}
|
||||||
for _, cert := range certs {
|
for _, cert := range certs {
|
||||||
// 发送消息
|
// 发送消息
|
||||||
today := timeutil.Format("Y-m-d")
|
var today = timeutil.Format("Y-m-d")
|
||||||
subject := "SSL证书\"" + cert.Name + "\"在今天(" + today + ")过期"
|
var subject = "SSL证书\"" + cert.Name + "\"在今天(" + today + ")过期"
|
||||||
msg := "SSL证书\"" + cert.Name + "\"(" + string(cert.DnsNames) + ")在今天(" + today + ")过期,请及时更新证书,之后将不再重复提醒。"
|
var msg = "SSL证书\"" + cert.Name + "\"(" + string(cert.DnsNames) + ")在今天(" + today + ")过期,请及时更新证书,之后将不再重复提醒。"
|
||||||
err = models.SharedMessageDAO.CreateMessage(nil, int64(cert.AdminId), int64(cert.UserId), models.MessageTypeSSLCertExpiring, models.MessageLevelWarning, subject, msg, maps.Map{
|
err = models.SharedMessageDAO.CreateMessage(nil, int64(cert.AdminId), int64(cert.UserId), models.MessageTypeSSLCertExpiring, models.MessageLevelWarning, subject, msg, maps.Map{
|
||||||
"certId": cert.Id,
|
"certId": cert.Id,
|
||||||
"acmeTaskId": cert.AcmeTaskId,
|
"acmeTaskId": cert.AcmeTaskId,
|
||||||
|
|||||||
@@ -1,153 +0,0 @@
|
|||||||
package tests
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
|
|
||||||
pb "github.com/TeaOSLab/EdgeAPI/internal/tests/helloworld"
|
|
||||||
pb2 "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/grpc/credentials"
|
|
||||||
"google.golang.org/grpc/credentials/insecure"
|
|
||||||
"google.golang.org/grpc/metadata"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type server struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *server) SayHello(ctx context.Context, request *pb.HelloRequest) (*pb.HelloReply, error) {
|
|
||||||
md, ok := metadata.FromIncomingContext(ctx)
|
|
||||||
if ok {
|
|
||||||
jsonData, _ := json.MarshalIndent(md, "", " ")
|
|
||||||
log.Print(string(jsonData))
|
|
||||||
|
|
||||||
_ = md
|
|
||||||
}
|
|
||||||
|
|
||||||
return &pb.HelloReply{
|
|
||||||
Message: "Hello, " + request.Name,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTCPServer(t *testing.T) {
|
|
||||||
listener, err := net.Listen("tcp", ":8001")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s := grpc.NewServer()
|
|
||||||
pb.RegisterGreeterServer(s, &server{})
|
|
||||||
pb2.RegisterNodeServiceServer(s, &services.NodeService{})
|
|
||||||
|
|
||||||
err = s.Serve(listener)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTCPClient(t *testing.T) {
|
|
||||||
conn, err := grpc.Dial("127.0.0.1:8001", grpc.WithTransportCredentials(insecure.NewCredentials()))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
_ = conn.Close()
|
|
||||||
}()
|
|
||||||
|
|
||||||
c := pb.NewGreeterClient(conn)
|
|
||||||
|
|
||||||
before := time.Now()
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
ctx = metadata.AppendToOutgoingContext(ctx, "name", "liu", "age", "20")
|
|
||||||
reply, err := c.SayHello(ctx, &pb.HelloRequest{
|
|
||||||
Name: strings.Repeat("golang", 1),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
t.Log(reply.Message)
|
|
||||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTLSServer(t *testing.T) {
|
|
||||||
listener, err := net.Listen("tcp", ":8001")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsCred, err := credentials.NewServerTLSFromFile("test.pem", "test.key")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s := grpc.NewServer(grpc.Creds(tlsCred))
|
|
||||||
pb.RegisterGreeterServer(s, &server{})
|
|
||||||
err = s.Serve(listener)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTLSClient(t *testing.T) {
|
|
||||||
tlsCred, err := credentials.NewClientTLSFromFile("test.pem", "www.hisock.cn")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := grpc.Dial("127.0.0.1:8001", grpc.WithTransportCredentials(tlsCred))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
_ = conn.Close()
|
|
||||||
}()
|
|
||||||
|
|
||||||
c := pb.NewGreeterClient(conn)
|
|
||||||
|
|
||||||
before := time.Now()
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
ctx = metadata.AppendToOutgoingContext(ctx, "name", "liu")
|
|
||||||
reply, err := c.SayHello(ctx, &pb.HelloRequest{
|
|
||||||
Name: strings.Repeat("golang", 1),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
t.Log(reply.Message)
|
|
||||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkClient(b *testing.B) {
|
|
||||||
runtime.GOMAXPROCS(1)
|
|
||||||
|
|
||||||
tlsCred, err := credentials.NewClientTLSFromFile("test.pem", "www.hisock.cn")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
conn, err := grpc.Dial("127.0.0.1:8001", grpc.WithTransportCredentials(tlsCred))
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
_ = conn.Close()
|
|
||||||
}()
|
|
||||||
|
|
||||||
c := pb.NewGreeterClient(conn)
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
ctx := context.Background()
|
|
||||||
ctx = metadata.AppendToOutgoingContext(ctx, "name", "liu")
|
|
||||||
reply, err := c.SayHello(ctx, &pb.HelloRequest{
|
|
||||||
Name: "golang",
|
|
||||||
})
|
|
||||||
_, _ = reply, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
option go_package = "./helloworld";
|
|
||||||
|
|
||||||
service Greeter {
|
|
||||||
rpc SayHello (HelloRequest) returns (HelloReply) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
message HelloRequest {
|
|
||||||
string name = 100;
|
|
||||||
int32 page_number = 101;
|
|
||||||
repeated int32 ages = 102;
|
|
||||||
}
|
|
||||||
|
|
||||||
message HelloReply {
|
|
||||||
string message = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message SearchResult {
|
|
||||||
string query = 1;
|
|
||||||
int32 page_number = 2;
|
|
||||||
int32 result_per_page = 3;
|
|
||||||
|
|
||||||
enum Corpus {
|
|
||||||
option allow_alias = true;
|
|
||||||
|
|
||||||
UNIVERSAL = 0;
|
|
||||||
WEB = 1;
|
|
||||||
IMAGES = 2;
|
|
||||||
RUNNING = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
Corpus corpus = 4;
|
|
||||||
SearchResponse result = 5;
|
|
||||||
map<string, SearchResponse> resultMap = 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
message SearchResponse {
|
|
||||||
reserved 1 to 15;
|
|
||||||
|
|
||||||
int32 count = 16;
|
|
||||||
bool isOk = 17;
|
|
||||||
bytes padding = 18;
|
|
||||||
}
|
|
||||||
@@ -1,584 +0,0 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
|
||||||
// versions:
|
|
||||||
// protoc-gen-go v1.25.0
|
|
||||||
// protoc v3.12.3
|
|
||||||
// source: hello_service.proto
|
|
||||||
|
|
||||||
package helloworld
|
|
||||||
|
|
||||||
import (
|
|
||||||
context "context"
|
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
grpc "google.golang.org/grpc"
|
|
||||||
codes "google.golang.org/grpc/codes"
|
|
||||||
status "google.golang.org/grpc/status"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
|
||||||
reflect "reflect"
|
|
||||||
sync "sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Verify that this generated code is sufficiently up-to-date.
|
|
||||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
|
||||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
|
||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
|
||||||
)
|
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
type SearchResult_Corpus int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
SearchResult_UNIVERSAL SearchResult_Corpus = 0
|
|
||||||
SearchResult_WEB SearchResult_Corpus = 1
|
|
||||||
SearchResult_IMAGES SearchResult_Corpus = 2
|
|
||||||
SearchResult_RUNNING SearchResult_Corpus = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
// Enum value maps for SearchResult_Corpus.
|
|
||||||
var (
|
|
||||||
SearchResult_Corpus_name = map[int32]string{
|
|
||||||
0: "UNIVERSAL",
|
|
||||||
1: "WEB",
|
|
||||||
2: "IMAGES",
|
|
||||||
// Duplicate value: 2: "RUNNING",
|
|
||||||
}
|
|
||||||
SearchResult_Corpus_value = map[string]int32{
|
|
||||||
"UNIVERSAL": 0,
|
|
||||||
"WEB": 1,
|
|
||||||
"IMAGES": 2,
|
|
||||||
"RUNNING": 2,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (x SearchResult_Corpus) Enum() *SearchResult_Corpus {
|
|
||||||
p := new(SearchResult_Corpus)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x SearchResult_Corpus) String() string {
|
|
||||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (SearchResult_Corpus) Descriptor() protoreflect.EnumDescriptor {
|
|
||||||
return file_hello_service_proto_enumTypes[0].Descriptor()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (SearchResult_Corpus) Type() protoreflect.EnumType {
|
|
||||||
return &file_hello_service_proto_enumTypes[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x SearchResult_Corpus) Number() protoreflect.EnumNumber {
|
|
||||||
return protoreflect.EnumNumber(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use SearchResult_Corpus.Descriptor instead.
|
|
||||||
func (SearchResult_Corpus) EnumDescriptor() ([]byte, []int) {
|
|
||||||
return file_hello_service_proto_rawDescGZIP(), []int{2, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
type HelloRequest struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Name string `protobuf:"bytes,100,opt,name=name,proto3" json:"name,omitempty"`
|
|
||||||
PageNumber int32 `protobuf:"varint,101,opt,name=page_number,json=pageNumber,proto3" json:"page_number,omitempty"`
|
|
||||||
Ages []int32 `protobuf:"varint,102,rep,packed,name=ages,proto3" json:"ages,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *HelloRequest) Reset() {
|
|
||||||
*x = HelloRequest{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_hello_service_proto_msgTypes[0]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *HelloRequest) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*HelloRequest) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *HelloRequest) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_hello_service_proto_msgTypes[0]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use HelloRequest.ProtoReflect.Descriptor instead.
|
|
||||||
func (*HelloRequest) Descriptor() ([]byte, []int) {
|
|
||||||
return file_hello_service_proto_rawDescGZIP(), []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *HelloRequest) GetName() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Name
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *HelloRequest) GetPageNumber() int32 {
|
|
||||||
if x != nil {
|
|
||||||
return x.PageNumber
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *HelloRequest) GetAges() []int32 {
|
|
||||||
if x != nil {
|
|
||||||
return x.Ages
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type HelloReply struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *HelloReply) Reset() {
|
|
||||||
*x = HelloReply{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_hello_service_proto_msgTypes[1]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *HelloReply) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*HelloReply) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *HelloReply) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_hello_service_proto_msgTypes[1]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use HelloReply.ProtoReflect.Descriptor instead.
|
|
||||||
func (*HelloReply) Descriptor() ([]byte, []int) {
|
|
||||||
return file_hello_service_proto_rawDescGZIP(), []int{1}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *HelloReply) GetMessage() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Message
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type SearchResult struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Query string `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"`
|
|
||||||
PageNumber int32 `protobuf:"varint,2,opt,name=page_number,json=pageNumber,proto3" json:"page_number,omitempty"`
|
|
||||||
ResultPerPage int32 `protobuf:"varint,3,opt,name=result_per_page,json=resultPerPage,proto3" json:"result_per_page,omitempty"`
|
|
||||||
Corpus SearchResult_Corpus `protobuf:"varint,4,opt,name=corpus,proto3,enum=SearchResult_Corpus" json:"corpus,omitempty"`
|
|
||||||
Result *SearchResponse `protobuf:"bytes,5,opt,name=result,proto3" json:"result,omitempty"`
|
|
||||||
ResultMap map[string]*SearchResponse `protobuf:"bytes,6,rep,name=resultMap,proto3" json:"resultMap,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SearchResult) Reset() {
|
|
||||||
*x = SearchResult{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_hello_service_proto_msgTypes[2]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SearchResult) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*SearchResult) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *SearchResult) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_hello_service_proto_msgTypes[2]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use SearchResult.ProtoReflect.Descriptor instead.
|
|
||||||
func (*SearchResult) Descriptor() ([]byte, []int) {
|
|
||||||
return file_hello_service_proto_rawDescGZIP(), []int{2}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SearchResult) GetQuery() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Query
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SearchResult) GetPageNumber() int32 {
|
|
||||||
if x != nil {
|
|
||||||
return x.PageNumber
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SearchResult) GetResultPerPage() int32 {
|
|
||||||
if x != nil {
|
|
||||||
return x.ResultPerPage
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SearchResult) GetCorpus() SearchResult_Corpus {
|
|
||||||
if x != nil {
|
|
||||||
return x.Corpus
|
|
||||||
}
|
|
||||||
return SearchResult_UNIVERSAL
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SearchResult) GetResult() *SearchResponse {
|
|
||||||
if x != nil {
|
|
||||||
return x.Result
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SearchResult) GetResultMap() map[string]*SearchResponse {
|
|
||||||
if x != nil {
|
|
||||||
return x.ResultMap
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type SearchResponse struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Count int32 `protobuf:"varint,16,opt,name=count,proto3" json:"count,omitempty"`
|
|
||||||
IsOk bool `protobuf:"varint,17,opt,name=isOk,proto3" json:"isOk,omitempty"`
|
|
||||||
Padding []byte `protobuf:"bytes,18,opt,name=padding,proto3" json:"padding,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SearchResponse) Reset() {
|
|
||||||
*x = SearchResponse{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_hello_service_proto_msgTypes[3]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SearchResponse) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*SearchResponse) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *SearchResponse) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_hello_service_proto_msgTypes[3]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use SearchResponse.ProtoReflect.Descriptor instead.
|
|
||||||
func (*SearchResponse) Descriptor() ([]byte, []int) {
|
|
||||||
return file_hello_service_proto_rawDescGZIP(), []int{3}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SearchResponse) GetCount() int32 {
|
|
||||||
if x != nil {
|
|
||||||
return x.Count
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SearchResponse) GetIsOk() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.IsOk
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SearchResponse) GetPadding() []byte {
|
|
||||||
if x != nil {
|
|
||||||
return x.Padding
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_hello_service_proto protoreflect.FileDescriptor
|
|
||||||
|
|
||||||
var file_hello_service_proto_rawDesc = []byte{
|
|
||||||
0x0a, 0x13, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e,
|
|
||||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x57, 0x0a, 0x0c, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65,
|
|
||||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x64, 0x20,
|
|
||||||
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x67,
|
|
||||||
0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x65, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a,
|
|
||||||
0x70, 0x61, 0x67, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x67,
|
|
||||||
0x65, 0x73, 0x18, 0x66, 0x20, 0x03, 0x28, 0x05, 0x52, 0x04, 0x61, 0x67, 0x65, 0x73, 0x22, 0x26,
|
|
||||||
0x0a, 0x0a, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07,
|
|
||||||
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d,
|
|
||||||
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x8e, 0x03, 0x0a, 0x0c, 0x53, 0x65, 0x61, 0x72, 0x63,
|
|
||||||
0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79,
|
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1f, 0x0a,
|
|
||||||
0x0b, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01,
|
|
||||||
0x28, 0x05, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x26,
|
|
||||||
0x0a, 0x0f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x70, 0x61, 0x67,
|
|
||||||
0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x50,
|
|
||||||
0x65, 0x72, 0x50, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x63, 0x6f, 0x72, 0x70, 0x75, 0x73,
|
|
||||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52,
|
|
||||||
0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x43, 0x6f, 0x72, 0x70, 0x75, 0x73, 0x52, 0x06, 0x63, 0x6f,
|
|
||||||
0x72, 0x70, 0x75, 0x73, 0x12, 0x27, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x05,
|
|
||||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73,
|
|
||||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x3a, 0x0a,
|
|
||||||
0x09, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x4d, 0x61, 0x70, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b,
|
|
||||||
0x32, 0x1c, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e,
|
|
||||||
0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09,
|
|
||||||
0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x4d, 0x61, 0x70, 0x1a, 0x4d, 0x0a, 0x0e, 0x52, 0x65, 0x73,
|
|
||||||
0x75, 0x6c, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
|
|
||||||
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x25, 0x0a,
|
|
||||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x53,
|
|
||||||
0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, 0x76,
|
|
||||||
0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x3d, 0x0a, 0x06, 0x43, 0x6f, 0x72, 0x70,
|
|
||||||
0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x49, 0x56, 0x45, 0x52, 0x53, 0x41, 0x4c, 0x10,
|
|
||||||
0x00, 0x12, 0x07, 0x0a, 0x03, 0x57, 0x45, 0x42, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x49, 0x4d,
|
|
||||||
0x41, 0x47, 0x45, 0x53, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e,
|
|
||||||
0x47, 0x10, 0x02, 0x1a, 0x02, 0x10, 0x01, 0x22, 0x5a, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63,
|
|
||||||
0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75,
|
|
||||||
0x6e, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12,
|
|
||||||
0x12, 0x0a, 0x04, 0x69, 0x73, 0x4f, 0x6b, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69,
|
|
||||||
0x73, 0x4f, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x12,
|
|
||||||
0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x4a, 0x04, 0x08,
|
|
||||||
0x01, 0x10, 0x10, 0x32, 0x33, 0x0a, 0x07, 0x47, 0x72, 0x65, 0x65, 0x74, 0x65, 0x72, 0x12, 0x28,
|
|
||||||
0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x0d, 0x2e, 0x48, 0x65, 0x6c,
|
|
||||||
0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x48, 0x65, 0x6c, 0x6c,
|
|
||||||
0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x0e, 0x5a, 0x0c, 0x2e, 0x2f, 0x68, 0x65,
|
|
||||||
0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
file_hello_service_proto_rawDescOnce sync.Once
|
|
||||||
file_hello_service_proto_rawDescData = file_hello_service_proto_rawDesc
|
|
||||||
)
|
|
||||||
|
|
||||||
func file_hello_service_proto_rawDescGZIP() []byte {
|
|
||||||
file_hello_service_proto_rawDescOnce.Do(func() {
|
|
||||||
file_hello_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_hello_service_proto_rawDescData)
|
|
||||||
})
|
|
||||||
return file_hello_service_proto_rawDescData
|
|
||||||
}
|
|
||||||
|
|
||||||
var file_hello_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
|
||||||
var file_hello_service_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
|
||||||
var file_hello_service_proto_goTypes = []interface{}{
|
|
||||||
(SearchResult_Corpus)(0), // 0: SearchResult.Corpus
|
|
||||||
(*HelloRequest)(nil), // 1: HelloRequest
|
|
||||||
(*HelloReply)(nil), // 2: HelloReply
|
|
||||||
(*SearchResult)(nil), // 3: SearchResult
|
|
||||||
(*SearchResponse)(nil), // 4: SearchResponse
|
|
||||||
nil, // 5: SearchResult.ResultMapEntry
|
|
||||||
}
|
|
||||||
var file_hello_service_proto_depIdxs = []int32{
|
|
||||||
0, // 0: SearchResult.corpus:type_name -> SearchResult.Corpus
|
|
||||||
4, // 1: SearchResult.result:type_name -> SearchResponse
|
|
||||||
5, // 2: SearchResult.resultMap:type_name -> SearchResult.ResultMapEntry
|
|
||||||
4, // 3: SearchResult.ResultMapEntry.value:type_name -> SearchResponse
|
|
||||||
1, // 4: Greeter.SayHello:input_type -> HelloRequest
|
|
||||||
2, // 5: Greeter.SayHello:output_type -> HelloReply
|
|
||||||
5, // [5:6] is the sub-list for method output_type
|
|
||||||
4, // [4:5] is the sub-list for method input_type
|
|
||||||
4, // [4:4] is the sub-list for extension type_name
|
|
||||||
4, // [4:4] is the sub-list for extension extendee
|
|
||||||
0, // [0:4] is the sub-list for field type_name
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { file_hello_service_proto_init() }
|
|
||||||
func file_hello_service_proto_init() {
|
|
||||||
if File_hello_service_proto != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !protoimpl.UnsafeEnabled {
|
|
||||||
file_hello_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*HelloRequest); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_hello_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*HelloReply); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_hello_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*SearchResult); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_hello_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*SearchResponse); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
type x struct{}
|
|
||||||
out := protoimpl.TypeBuilder{
|
|
||||||
File: protoimpl.DescBuilder{
|
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
|
||||||
RawDescriptor: file_hello_service_proto_rawDesc,
|
|
||||||
NumEnums: 1,
|
|
||||||
NumMessages: 5,
|
|
||||||
NumExtensions: 0,
|
|
||||||
NumServices: 1,
|
|
||||||
},
|
|
||||||
GoTypes: file_hello_service_proto_goTypes,
|
|
||||||
DependencyIndexes: file_hello_service_proto_depIdxs,
|
|
||||||
EnumInfos: file_hello_service_proto_enumTypes,
|
|
||||||
MessageInfos: file_hello_service_proto_msgTypes,
|
|
||||||
}.Build()
|
|
||||||
File_hello_service_proto = out.File
|
|
||||||
file_hello_service_proto_rawDesc = nil
|
|
||||||
file_hello_service_proto_goTypes = nil
|
|
||||||
file_hello_service_proto_depIdxs = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
|
||||||
var _ context.Context
|
|
||||||
var _ grpc.ClientConnInterface
|
|
||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
|
||||||
// is compatible with the grpc package it is being compiled against.
|
|
||||||
const _ = grpc.SupportPackageIsVersion6
|
|
||||||
|
|
||||||
// GreeterClient is the client API for Greeter service.
|
|
||||||
//
|
|
||||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
|
||||||
type GreeterClient interface {
|
|
||||||
SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type greeterClient struct {
|
|
||||||
cc grpc.ClientConnInterface
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewGreeterClient(cc grpc.ClientConnInterface) GreeterClient {
|
|
||||||
return &greeterClient{cc}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) {
|
|
||||||
out := new(HelloReply)
|
|
||||||
err := c.cc.Invoke(ctx, "/Greeter/SayHello", in, out, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GreeterServer is the server API for Greeter service.
|
|
||||||
type GreeterServer interface {
|
|
||||||
SayHello(context.Context, *HelloRequest) (*HelloReply, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnimplementedGreeterServer can be embedded to have forward compatible implementations.
|
|
||||||
type UnimplementedGreeterServer struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*UnimplementedGreeterServer) SayHello(context.Context, *HelloRequest) (*HelloReply, error) {
|
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) {
|
|
||||||
s.RegisterService(&_Greeter_serviceDesc, srv)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
|
||||||
in := new(HelloRequest)
|
|
||||||
if err := dec(in); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if interceptor == nil {
|
|
||||||
return srv.(GreeterServer).SayHello(ctx, in)
|
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
|
||||||
Server: srv,
|
|
||||||
FullMethod: "/Greeter/SayHello",
|
|
||||||
}
|
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest))
|
|
||||||
}
|
|
||||||
return interceptor(ctx, in, info, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
var _Greeter_serviceDesc = grpc.ServiceDesc{
|
|
||||||
ServiceName: "Greeter",
|
|
||||||
HandlerType: (*GreeterServer)(nil),
|
|
||||||
Methods: []grpc.MethodDesc{
|
|
||||||
{
|
|
||||||
MethodName: "SayHello",
|
|
||||||
Handler: _Greeter_SayHello_Handler,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Streams: []grpc.StreamDesc{},
|
|
||||||
Metadata: "hello_service.proto",
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package tests
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/iwind/TeaGo/rands"
|
|
||||||
"math"
|
|
||||||
"net/url"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRandString(t *testing.T) {
|
|
||||||
t.Log(rands.HexString(32))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCharset(t *testing.T) {
|
|
||||||
t.Log(url.QueryEscape("中文"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInt(t *testing.T) {
|
|
||||||
t.Log(math.MaxInt64)
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user