Skip to content

Commit 7668b54

Browse files
committed
refactor with libdns
1 parent a9e2921 commit 7668b54

File tree

7 files changed

+96
-194
lines changed

7 files changed

+96
-194
lines changed

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM golang:1.22 as builder
1+
FROM golang:1.23 as builder
22

33
ARG ARG_GOPROXY
44
ENV GOPROXY $ARG_GOPROXY

cmd/ddns/main.go

+57-20
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,22 @@ import (
55
"fmt"
66
"log/slog"
77
"os"
8+
"strings"
89
"time"
910

1011
"github.com/catpie/musdk-go"
12+
"github.com/libdns/libdns"
13+
"github.com/weeon/log"
1114
"github.com/weeon/utils/task"
1215

1316
"github.com/orvice/ddns/dns"
1417
"github.com/orvice/ddns/internal/config"
1518
"github.com/orvice/ddns/internal/ip"
1619
"github.com/orvice/ddns/notify"
17-
"github.com/weeon/log"
1820
)
1921

2022
var (
21-
dnsProvider dns.DNS
23+
dnsProvider dns.LibDNS
2224
ipGetter ip.IPGetter
2325
muCli *musdk.Client
2426
)
@@ -40,16 +42,8 @@ func Init() error {
4042
}
4143

4244
switch config.DNS_MODE {
43-
case config.DNS_MODE_MU:
44-
dnsProvider, err = dns.NewMu(config.API_URI, config.NODE_ID)
45-
if err != nil {
46-
return err
47-
}
4845
default:
49-
dnsProvider, err = dns.NewCloudFlare()
50-
if err != nil {
51-
return err
52-
}
46+
dnsProvider = dns.NewCloudFlare()
5347
}
5448

5549
return nil
@@ -78,24 +72,67 @@ func main() {
7872
}
7973

8074
func updateIP(ctx context.Context) error {
75+
logger := slog.Default()
8176
ip, err := ipGetter.GetIP()
8277
if err != nil {
83-
log.Errorf("Get ip error %v", err)
78+
logger.Error("Get ip error", "error", err)
8479
return err
8580
}
8681

87-
currentIP, err := dnsProvider.GetIP(ctx, config.DOMAIN)
82+
name, zone := zoneFromDomain(config.DOMAIN)
83+
logger.Info("zone from domain",
84+
"name", name,
85+
"zone", zone)
86+
87+
currentIP, err := dnsProvider.GetRecords(ctx, zone)
8888
if err != nil {
89+
logger.Error("Get records error", "error", err)
8990
return err
9091
}
9192

92-
log.Infow("get ip",
93-
"from_getter", ip,
94-
"from_provider", currentIP)
95-
err = dnsProvider.UpdateIP(ctx, config.DOMAIN, ip)
96-
if err != nil {
97-
log.Errorf("Update ip error %v", err)
98-
return err
93+
var found bool
94+
var record *libdns.Record
95+
for _, r := range currentIP {
96+
if r.Name == name {
97+
found = true
98+
record = &r
99+
break
100+
}
99101
}
102+
if found {
103+
if record.Value == ip {
104+
logger.Info("ip is same, skip update", "ip", ip)
105+
return nil
106+
}
107+
record.Value = ip
108+
_, err = dnsProvider.SetRecords(ctx, zone, []libdns.Record{
109+
*record,
110+
})
111+
if err != nil {
112+
logger.Error("Set records error", "error", err)
113+
return err
114+
}
115+
} else {
116+
_, err = dnsProvider.AppendRecords(ctx, zone, []libdns.Record{
117+
{
118+
Name: name,
119+
Value: ip,
120+
},
121+
})
122+
if err != nil {
123+
logger.Error("Append records error", "error", err)
124+
return err
125+
}
126+
}
127+
100128
return nil
101129
}
130+
131+
// zoneFromDomain return zone and domain
132+
func zoneFromDomain(domain string) (string, string) {
133+
arr := strings.SplitN(domain, ".", 2)
134+
if len(arr) == 1 {
135+
return "", ""
136+
}
137+
return arr[0], arr[1]
138+
}

dns/cloudflare.go

+4-141
Original file line numberDiff line numberDiff line change
@@ -1,149 +1,12 @@
11
package dns
22

33
import (
4-
"context"
5-
"fmt"
6-
"log/slog"
74
"os"
8-
"strings"
95

10-
"github.com/cloudflare/cloudflare-go"
11-
"github.com/orvice/ddns/config"
12-
"github.com/orvice/ddns/notify"
6+
"github.com/libdns/cloudflare"
137
)
148

15-
type CloudFlare struct {
16-
client *cloudflare.API
17-
}
18-
19-
func NewCloudFlare() (*CloudFlare, error) {
20-
key := os.Getenv("CF_KEY")
21-
email := os.Getenv("CF_EMAIL")
22-
token := os.Getenv("CF_TOKEN")
23-
24-
var client *cloudflare.API
25-
var err error
26-
27-
if token != "" {
28-
slog.Info("cf use token")
29-
client, err = cloudflare.NewWithAPIToken(token)
30-
} else {
31-
client, err = cloudflare.New(key, email)
32-
}
33-
if err != nil {
34-
return nil, err
35-
}
36-
37-
return &CloudFlare{
38-
client: client,
39-
}, nil
40-
}
41-
42-
func (c *CloudFlare) getZone(ctx context.Context, domain string) (*cloudflare.Zone, error) {
43-
zones, err := c.client.ListZones(ctx)
44-
if err != nil {
45-
slog.Error("list zones error", "err", err)
46-
return nil, err
47-
}
48-
49-
for _, z := range zones {
50-
if strings.Contains(domain, z.Name) {
51-
slog.Info("get zone success", "zone", z.Name, "id", z.ID)
52-
return &z, nil
53-
}
54-
}
55-
return nil, fmt.Errorf("not found zone")
56-
}
57-
58-
func (c *CloudFlare) GetDomainZoneID(domain string) (string, error) {
59-
var zoneID = os.Getenv("CF_ZONE_ID")
60-
if zoneID != "" {
61-
return zoneID, nil
62-
}
63-
zone, err := c.getZone(context.Background(), domain)
64-
if err != nil {
65-
slog.Error("get zone error", "err", err)
66-
}
67-
return zone.ID, nil
68-
}
69-
70-
func (c *CloudFlare) GetIP(ctx context.Context, domain string) (string, error) {
71-
zid, err := c.GetDomainZoneID(domain)
72-
if err != nil {
73-
return "", err
74-
}
75-
rs, ret, err := c.client.ListDNSRecords(ctx, &cloudflare.ResourceContainer{
76-
// Name: domain,
77-
Identifier: zid,
78-
}, cloudflare.ListDNSRecordsParams{})
79-
if err != nil {
80-
return "", err
81-
}
82-
slog.Info("get dns records ", "count", ret.Count)
83-
84-
for _, v := range rs {
85-
return v.Content, nil
86-
}
87-
88-
return "", nil
89-
}
90-
91-
func (c *CloudFlare) UpdateIP(ctx context.Context, domain, ip string) error {
92-
zid, err := c.GetDomainZoneID(domain)
93-
if err != nil {
94-
return err
95-
}
96-
rs, ret, err := c.client.ListDNSRecords(ctx, &cloudflare.ResourceContainer{
97-
// Name: domain,
98-
Identifier: zid,
99-
}, cloudflare.ListDNSRecordsParams{})
100-
if err != nil {
101-
return err
102-
}
103-
slog.Info("get dns records ", "count", ret.Count)
104-
for _, r := range rs {
105-
if r.Type == "A" {
106-
107-
if r.Name != domain {
108-
slog.Info("record name not match",
109-
"id", r.ID,
110-
"record_name", r.Name,
111-
"domain", domain,
112-
)
113-
continue
114-
}
115-
116-
if r.Content == ip {
117-
slog.Info("ip not change...")
118-
continue
119-
}
120-
121-
oldIP := r.Content
122-
r.Content = ip
123-
r, err = c.client.UpdateDNSRecord(ctx, cloudflare.ResourceIdentifier(zid), cloudflare.UpdateDNSRecordParams{
124-
ID: r.ID,
125-
Type: r.Type,
126-
Name: r.Name,
127-
Content: ip,
128-
})
129-
130-
slog.Info("update dns record",
131-
"zone_id", zid,
132-
"type", r.Type,
133-
"record_id", r.ID,
134-
"domain", domain,
135-
"name", r.Name,
136-
"old_ip", oldIP,
137-
"new_ip", ip,
138-
)
139-
140-
if err != nil {
141-
slog.Error("update dns record error",
142-
"err", err)
143-
return err
144-
}
145-
notify.Notify(ctx, fmt.Sprintf(config.IpNotifyFormat, domain, oldIP, ip))
146-
}
147-
}
148-
return nil
9+
func NewCloudFlare() LibDNS {
10+
provider := cloudflare.Provider{APIToken: os.Getenv("CF_TOKEN")}
11+
return &provider
14912
}

dns/cloudflate_test.go

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package dns
2+
3+
import (
4+
"context"
5+
"os"
6+
"testing"
7+
8+
"github.com/libdns/cloudflare"
9+
)
10+
11+
func TestCloudFlare(t *testing.T) {
12+
provider := cloudflare.Provider{APIToken: os.Getenv("CF_TOKEN")}
13+
records, err := provider.GetRecords(context.Background(), os.Getenv("CF_ZONE"))
14+
if err != nil {
15+
t.Log(err)
16+
return
17+
}
18+
t.Log(records)
19+
}

dns/dns.go

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package dns
22

3-
import "context"
3+
import (
4+
"github.com/libdns/libdns"
5+
)
46

5-
type DNS interface {
6-
GetIP(ctx context.Context, domain string) (string, error)
7-
UpdateIP(ctx context.Context, domain, ip string) error
7+
type LibDNS interface {
8+
libdns.RecordGetter
9+
libdns.RecordAppender
10+
libdns.RecordSetter
811
}

go.mod

+4-6
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ module github.com/orvice/ddns
22

33
require (
44
github.com/catpie/musdk-go v0.0.0-20230815021801-7d27a00f9c60
5-
github.com/cloudflare/cloudflare-go v0.75.0
65
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
6+
github.com/libdns/cloudflare v0.1.1
7+
github.com/libdns/libdns v0.2.2
78
github.com/orvice/utils v0.0.0-20180715141935-5b71615d9c36
89
github.com/weeon/log v0.0.0-20210217051817-63fe9a730962
910
github.com/weeon/utils v0.0.0-20190524044050-159b91233ff4
@@ -14,18 +15,15 @@ require (
1415
github.com/cespare/xxhash/v2 v2.1.1 // indirect
1516
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
1617
github.com/go-redis/redis/v8 v8.5.0 // indirect
17-
github.com/goccy/go-json v0.10.2 // indirect
18-
github.com/google/go-querystring v1.1.0 // indirect
19-
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
20-
github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
18+
github.com/google/go-cmp v0.5.8 // indirect
19+
github.com/stretchr/testify v1.8.4 // indirect
2120
github.com/weeon/contract v0.0.0-20190520152601-a4ee53bdb563 // indirect
2221
go.opentelemetry.io/otel v0.16.0 // indirect
2322
go.uber.org/atomic v1.6.0 // indirect
2423
go.uber.org/multierr v1.5.0 // indirect
2524
go.uber.org/zap v1.15.0 // indirect
2625
golang.org/x/net v0.17.0 // indirect
2726
golang.org/x/text v0.13.0 // indirect
28-
golang.org/x/time v0.3.0 // indirect
2927
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
3028
gopkg.in/yaml.v2 v2.4.0 // indirect
3129
)

0 commit comments

Comments
 (0)