王一之 ac04817346
All checks were successful
Release / deploy (push) Successful in 1m44s
ci: 测试ci
2023-10-24 14:27:24 +08:00

154 lines
4.9 KiB
Go

package watch
import (
"context"
"fmt"
"net"
"time"
"github.com/codfrm/cago/pkg/logger"
"github.com/codfrm/dnspod-watch/pkg/pushcat"
dnspod "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod/v20210323"
"go.uber.org/zap"
)
type record struct {
w *watch
record *dnspod.RecordListItem
loadBalance *dnspod.RecordListItem
isDisable bool
domain *CheckDomain
logger *logger.CtxLogger
}
func newRecord(w *watch, r *dnspod.RecordListItem, domain *CheckDomain) (*record, error) {
ret := &record{
w: w,
record: r,
isDisable: false,
domain: domain,
logger: logger.NewCtxLogger(logger.Default()).With(
zap.String("domain", domain.Domain), zap.String("value", domain.Value),
),
}
if domain.LoadBalance != nil {
var err error
ret.loadBalance, err = w.queryRecord(domain.Domain, domain.Name,
domain.LoadBalance.Value, domain.LoadBalance.Line)
if err != nil {
return nil, err
}
}
return ret, nil
}
// watch 每分钟检查ip是否可以访问, 无法访问自动暂停记录
func (r *record) watch(ctx context.Context) {
t := time.NewTicker(time.Minute)
s := newRetry()
loadBalance := newRetry()
for {
select {
case <-t.C:
duration, err := r.checkIP(ctx, r.domain.Value)
if err != nil {
r.logger.Ctx(ctx).Error("check ip err", zap.Error(err))
} else {
r.logger.Ctx(ctx).Info("check ip ok",
zap.String("duration", fmt.Sprintf("%dms", duration.Milliseconds())))
}
_ = s.check(err == nil, func() error {
// 增加负载均衡
if r.domain.LoadBalance != nil {
// 判断延迟是否超过200毫秒
_ = loadBalance.check(duration > time.Millisecond*100, func() error {
// 开启记录
msg := fmt.Sprintf("开启负载均衡 域名: %s, 记录: %s",
r.domain.Domain, r.domain.LoadBalance.Value)
enableErr := r.w.enable(ctx, r.domain.Domain, *r.loadBalance.RecordId)
if enableErr != nil {
r.logger.Ctx(ctx).Error("modify record status err", zap.Error(enableErr))
msg += "\n记录修改失败: " + enableErr.Error()
} else {
r.logger.Ctx(ctx).Info("modify record status success",
zap.String("status", "ENABLE"))
r.isDisable = false
}
if pushErr := pushcat.Send(ctx, "开启负载均衡", msg); pushErr != nil {
r.logger.Ctx(ctx).Error("发送通知错误",
zap.Error(pushErr),
zap.String("msg", msg))
}
return enableErr
}, func() error {
// 开启记录
msg := fmt.Sprintf("关闭负载均衡 域名: %s, 记录: %s",
r.domain.Domain, r.domain.LoadBalance.Value)
disableErr := r.w.disable(ctx, r.domain.Domain, *r.loadBalance.RecordId)
if disableErr != nil {
r.logger.Ctx(ctx).Error("modify record status err", zap.Error(disableErr))
msg += "\n记录修改失败: " + disableErr.Error()
} else {
r.logger.Ctx(ctx).Info("modify record status success",
zap.String("status", "DISABLE"))
r.isDisable = false
}
if pushErr := pushcat.Send(ctx, "关闭负载均衡", msg); pushErr != nil {
r.logger.Ctx(ctx).Error("发送通知错误",
zap.Error(pushErr),
zap.String("msg", msg))
}
return disableErr
})
}
// 开启记录
msg := fmt.Sprintf("域名: %s, 记录: %s, ip可以访问,开启记录", r.domain.Domain, r.domain.Value)
enableErr := r.w.enable(ctx, r.domain.Domain, *r.record.RecordId)
if enableErr != nil {
r.logger.Ctx(ctx).Error("modify record status err", zap.Error(enableErr))
msg += "\n记录修改失败: " + enableErr.Error()
} else {
r.logger.Ctx(ctx).Info("modify record status success",
zap.String("status", "ENABLE"))
r.isDisable = false
}
if pushErr := pushcat.Send(ctx, "ip可以访问,开启记录", msg); pushErr != nil {
r.logger.Ctx(ctx).Error("发送通知错误",
zap.Error(pushErr),
zap.String("msg", msg))
}
return enableErr
}, func() error {
// 暂停记录
msg := fmt.Sprintf("域名: %s, 记录: %s, ip无法访问,暂停记录", r.domain.Domain, r.domain.Value)
disableErr := r.w.disable(ctx, r.domain.Domain, *r.record.RecordId)
if disableErr != nil {
r.logger.Ctx(ctx).Error("modify record status err", zap.Error(disableErr))
msg += "\n记录修改失败: " + disableErr.Error()
} else {
r.logger.Ctx(ctx).Info("modify record status success",
zap.String("status", "DISABLE"))
r.isDisable = true
}
if pushErr := pushcat.Send(ctx, "ip无法访问,暂停记录", msg); pushErr != nil {
r.logger.Ctx(ctx).Error("发送通知错误",
zap.Error(pushErr),
zap.String("msg", msg))
}
return disableErr
})
case <-ctx.Done():
t.Stop()
}
}
}
func (r *record) checkIP(ctx context.Context, ip string) (time.Duration, error) {
ts := time.Now()
con, err := net.DialTimeout("tcp", ip+":80", time.Second*10)
if err != nil {
return 0, err
}
return time.Since(ts), con.Close()
}