feat: 支持多IP监听

This commit is contained in:
2023-03-24 17:25:04 +08:00
parent ccb574933e
commit 6cd3b8609f
5 changed files with 228 additions and 382 deletions

93
internal/watch/record.go Normal file
View File

@ -0,0 +1,93 @@
package watch
import (
"context"
"net"
"time"
"github.com/codfrm/cago/pkg/logger"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
dnspod "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod/v20210323"
"go.uber.org/zap"
)
type record struct {
w *watch
record *dnspod.RecordListItem
isDisable bool
domain, value string
logger *logger.CtxLogger
}
func newRecord(w *watch, r *dnspod.RecordListItem, domain, value string) *record {
return &record{
w: w,
record: r,
isDisable: false,
domain: domain, value: value,
logger: logger.NewCtxLogger(logger.Default()).With(
zap.String("domain", domain), zap.String("value", value),
),
}
}
// watch 每分钟检查ip是否可以访问, 无法访问自动暂停记录
func (r *record) watch(ctx context.Context) {
t := time.NewTicker(time.Minute)
count := 0
for {
select {
case <-t.C:
// 检查ip是否可以访问
count++
if err := r.checkIP(ctx, r.value); err != nil {
// 连续3次无法访问,暂停记录
if !r.isDisable && count > 3 {
count = 0
// 暂停记录
request := dnspod.NewModifyRecordStatusRequest()
request.SetContext(ctx)
request.Domain = common.StringPtr(r.domain)
request.RecordId = common.Uint64Ptr(*r.record.RecordId)
request.Status = common.StringPtr("DISABLE")
_, err := r.w.client.ModifyRecordStatus(request)
if err != nil {
r.logger.Ctx(ctx).Error("modify record status err", zap.Error(err))
} else {
r.logger.Ctx(ctx).Info("modify record status success",
zap.String("status", "DISABLE"))
r.isDisable = true
}
}
} else if r.isDisable && count > 3 {
// 检查连续成功3次,开启记录
count = 0
request := dnspod.NewModifyRecordStatusRequest()
request.SetContext(ctx)
request.Domain = common.StringPtr(r.domain)
request.RecordId = common.Uint64Ptr(*r.record.RecordId)
request.Status = common.StringPtr("ENABLE")
_, err := r.w.client.ModifyRecordStatus(request)
if err != nil {
r.logger.Ctx(ctx).Error("modify record status err", zap.Error(err))
} else {
r.logger.Ctx(ctx).Info("modify record status success",
zap.String("status", "ENABLE"))
r.isDisable = false
}
} else {
r.logger.Ctx(ctx).Info("ip is ok")
}
case <-ctx.Done():
t.Stop()
}
}
}
func (r *record) checkIP(ctx context.Context, ip string) error {
con, err := net.DialTimeout("tcp", ip+":80", time.Second*10)
if err != nil {
return err
}
return con.Close()
}

View File

@ -5,25 +5,11 @@ import (
"github.com/codfrm/cago/pkg/logger"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
dnspod "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod/v20210323"
"go.uber.org/zap"
)
func (w *watch) init() (*dnspod.RecordListItem, error) {
w.credential = common.NewCredential(
w.config.SecretID,
w.config.SecretKey,
)
cpf := profile.NewClientProfile()
cpf.HttpProfile.Endpoint = "dnspod.tencentcloudapi.com"
var err error
w.client, err = dnspod.NewClient(w.credential, "", cpf)
if err != nil {
logger.Default().Error("NewClient error", zap.Error(err))
return nil, err
}
func (w *watch) queryRecord(value string) (*dnspod.RecordListItem, error) {
// 实例化一个请求对象,每个接口都会对应一个request对象
request := dnspod.NewDescribeRecordListRequest()
@ -35,7 +21,7 @@ func (w *watch) init() (*dnspod.RecordListItem, error) {
return nil, err
}
for _, v := range response.Response.RecordList {
if *v.Name == w.config.Name && *v.Value == w.config.Value {
if *v.Name == w.config.Name && *v.Value == value {
logger.Default().Info("record found", zap.Any("record", v))
return v, nil
}

View File

@ -2,23 +2,22 @@ package watch
import (
"context"
"net"
"time"
"github.com/codfrm/cago"
"github.com/codfrm/cago/configs"
"github.com/codfrm/cago/pkg/logger"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
dnspod "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod/v20210323"
"go.uber.org/zap"
)
type Config struct {
SecretID string `yaml:"secretID"` // 账号 secret id
SecretKey string `yaml:"secretKey"` // 账号 secret key
Domain string // 域名
Name string // 记录名
Value string // 记录值
SecretID string `yaml:"secretID"` // 账号 secret id
SecretKey string `yaml:"secretKey"` // 账号 secret key
Domain string // 域名
Name string // 记录名
Value []string // 记录值
}
type watch struct {
@ -36,80 +35,34 @@ func Watch() cago.Component {
func (w *watch) Start(ctx context.Context, cfg *configs.Config) error {
config := &Config{}
if err := cfg.Scan("watch", config); err != nil {
if err := cfg.Scan("w", config); err != nil {
return err
}
// 获取记录列表
w.config = config
record, err := w.init()
w.credential = common.NewCredential(
w.config.SecretID,
w.config.SecretKey,
)
cpf := profile.NewClientProfile()
cpf.HttpProfile.Endpoint = "dnspod.tencentcloudapi.com"
var err error
w.client, err = dnspod.NewClient(w.credential, "", cpf)
if err != nil {
logger.Default().Error("NewClient error", zap.Error(err))
return err
}
go w.watch(ctx, record)
for _, v := range w.config.Value {
r, err := w.queryRecord(v)
if err != nil {
return err
}
record := newRecord(w, r, config.Domain, v)
go record.watch(ctx)
}
return nil
}
func (w *watch) CloseHandle() {
}
// watch 每分钟检查ip是否可以访问, 无法访问自动暂停记录
func (w *watch) watch(ctx context.Context, record *dnspod.RecordListItem) {
t := time.NewTicker(time.Minute)
count := 0
for {
select {
case <-t.C:
// 检查ip是否可以访问
count++
if err := w.checkIP(ctx, w.config.Value); err != nil {
// 连续3次无法访问,暂停记录
if !w.isDisable && count > 3 {
count = 0
// 暂停记录
request := dnspod.NewModifyRecordStatusRequest()
request.SetContext(ctx)
request.Domain = common.StringPtr(w.config.Domain)
request.RecordId = common.Uint64Ptr(*record.RecordId)
request.Status = common.StringPtr("DISABLE")
_, err := w.client.ModifyRecordStatus(request)
if err != nil {
logger.Ctx(ctx).Error("modify record status err", zap.Error(err))
} else {
logger.Ctx(ctx).Info("modify record status success",
zap.String("status", "DISABLE"))
w.isDisable = true
}
}
} else if w.isDisable && count > 3 {
// 检查连续成功3次,开启记录
count = 0
request := dnspod.NewModifyRecordStatusRequest()
request.SetContext(ctx)
request.Domain = common.StringPtr(w.config.Domain)
request.RecordId = common.Uint64Ptr(*record.RecordId)
request.Status = common.StringPtr("ENABLE")
_, err := w.client.ModifyRecordStatus(request)
if err != nil {
logger.Ctx(ctx).Error("modify record status err", zap.Error(err))
} else {
logger.Ctx(ctx).Info("modify record status success",
zap.String("status", "ENABLE"))
w.isDisable = false
}
} else {
logger.Ctx(ctx).Info("ip is ok")
}
case <-ctx.Done():
t.Stop()
}
}
}
func (w *watch) checkIP(ctx context.Context, ip string) error {
con, err := net.DialTimeout("tcp", ip+":80", time.Second*10)
if err != nil {
return err
}
return con.Close()
}