-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprovider.go
136 lines (117 loc) · 3.06 KB
/
provider.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package hexonet
import (
"context"
"io"
"os"
"strings"
"sync"
"github.com/libdns/libdns"
)
// Provider facilitates DNS record manipulation with Hexonet.
type Provider struct {
Username string `json:"username"`
Password string `json:"password,omitempty"`
// Debug - can set this to stdout or stderr to dump
// debugging information about the API interaction with
// hexonet. This will dump your auth token in plain text
// so be careful.
Debug string `json:"debug,omitempty"`
mu sync.Mutex
c *client
}
// GetRecords lists all the records in the zone.
func (p *Provider) GetRecords(ctx context.Context, zone string) ([]libdns.Record, error) {
c, err := p.client()
if err != nil {
return nil, err
}
recs, err := c.getDNSEntries(ctx, zone)
return recs, nil
}
// AppendRecords adds records to the zone. It returns the records that were added.
func (p *Provider) AppendRecords(ctx context.Context, zone string, records []libdns.Record) ([]libdns.Record, error) {
c, err := p.client()
if err != nil {
return nil, err
}
err = c.addDNSEntry(ctx, zone, records)
if err != nil {
return nil, err
}
return records, nil
}
// SetRecords sets the records in the zone, either by updating existing records or creating new ones.
// It returns the updated records.
func (p *Provider) SetRecords(ctx context.Context, zone string, records []libdns.Record) ([]libdns.Record, error) {
c, err := p.client()
if err != nil {
return nil, err
}
alls, err := c.getDNSEntries(ctx, zone)
if err != nil {
return nil, err
}
// key+value is uniq in dns record
visited := map[string]libdns.Record{}
for i := range alls {
key := alls[i].Type + ":" + alls[i].Value
visited[key] = alls[i]
}
var adds, dels []libdns.Record
for i := range records {
key := records[i].Type + ":" + records[i].Value
if old, ok := visited[key]; !ok {
adds = append(adds, records[i])
} else {
dels = append(dels, old)
adds = append(adds, records[i])
}
}
err = c.removeDNSEntry(ctx, zone, dels)
if err != nil {
return nil, err
}
err = c.addDNSEntry(ctx, zone, adds)
if err != nil {
return nil, err
}
return records, nil
}
// DeleteRecords deletes the records from the zone. It returns the records that were deleted.
func (p *Provider) DeleteRecords(ctx context.Context, zone string, records []libdns.Record) ([]libdns.Record, error) {
c, err := p.client()
if err != nil {
return nil, err
}
err = c.removeDNSEntry(ctx, zone, records)
if err != nil {
return nil, err
}
return records, nil
}
func (p *Provider) client() (*client, error) {
p.mu.Lock()
defer p.mu.Unlock()
if p.c == nil {
var err error
var debug io.Writer
switch strings.ToLower(p.Debug) {
case "stdout", "yes", "true", "1":
debug = os.Stdout
case "stderr":
debug = os.Stderr
}
p.c, err = newClient(p.Username, p.Password, debug)
if err != nil {
return nil, err
}
}
return p.c, nil
}
// Interface guards
var (
_ libdns.RecordGetter = (*Provider)(nil)
_ libdns.RecordAppender = (*Provider)(nil)
_ libdns.RecordSetter = (*Provider)(nil)
_ libdns.RecordDeleter = (*Provider)(nil)
)