-
Notifications
You must be signed in to change notification settings - Fork 29
/
zones.go
241 lines (206 loc) · 7.57 KB
/
zones.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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
package powerdns
import (
"context"
"fmt"
"io"
)
// ZonesService handles communication with the zones related methods of the Client API
type ZonesService service
// Zone structure with JSON API metadata
type Zone struct {
ID *string `json:"id,omitempty"`
Name *string `json:"name,omitempty"`
Type *ZoneType `json:"type,omitempty"`
URL *string `json:"url,omitempty"`
Kind *ZoneKind `json:"kind,omitempty"`
RRsets []RRset `json:"rrsets,omitempty"`
Serial *uint32 `json:"serial,omitempty"`
NotifiedSerial *uint32 `json:"notified_serial,omitempty"`
EditedSerial *uint32 `json:"edited_serial,omitempty"`
Masters []string `json:"masters,omitempty"`
DNSsec *bool `json:"dnssec,omitempty"`
Nsec3Param *string `json:"nsec3param,omitempty"`
Nsec3Narrow *bool `json:"nsec3narrow,omitempty"`
Presigned *bool `json:"presigned,omitempty"`
SOAEdit *string `json:"soa_edit,omitempty"`
SOAEditAPI *string `json:"soa_edit_api,omitempty"`
APIRectify *bool `json:"api_rectify,omitempty"`
Zone *string `json:"zone,omitempty"`
Catalog *string `json:"catalog,omitempty"`
Account *string `json:"account,omitempty"`
Nameservers []string `json:"nameservers,omitempty"`
MasterTSIGKeyIDs []string `json:"master_tsig_key_ids,omitempty"`
SlaveTSIGKeyIDs []string `json:"slave_tsig_key_ids,omitempty"`
}
// NotifyResult structure with JSON API metadata
type NotifyResult struct {
Result *string `json:"result,omitempty"`
}
// AxfrRetrieveResult structure with JSON API metadata
type AxfrRetrieveResult struct {
Result *string `json:"result,omitempty"`
}
// Export string type
type Export string
// ZoneType string type
type ZoneType string
// ZoneZoneType sets the zone's type to zone
const ZoneZoneType ZoneType = "Zone"
// ZoneTypePtr is a helper function that allocates a new ZoneType value to store v and returns a pointer to it.
func ZoneTypePtr(v ZoneType) *ZoneType {
return &v
}
// ZoneKind string type
type ZoneKind string
// ZoneKindPtr is a helper function that allocates a new ZoneKind value to store v and returns a pointer to it.
func ZoneKindPtr(v ZoneKind) *ZoneKind {
return &v
}
const (
// NativeZoneKind sets the zone's kind to native
NativeZoneKind ZoneKind = "Native"
// MasterZoneKind sets the zone's kind to master
MasterZoneKind ZoneKind = "Master"
// SlaveZoneKind sets the zone's kind to slave
SlaveZoneKind ZoneKind = "Slave"
// ProducerZoneKind sets the zone's kind to producer
ProducerZoneKind ZoneKind = "Producer"
// ConsumerZoneKind sets the zone's kind to consumer
ConsumerZoneKind ZoneKind = "Consumer"
)
// List retrieves a list of Zones
func (z *ZonesService) List(ctx context.Context) ([]Zone, error) {
req, err := z.client.newRequest(ctx, "GET", fmt.Sprintf("servers/%s/zones", z.client.VHost), nil, nil)
if err != nil {
return nil, err
}
zones := make([]Zone, 0)
_, err = z.client.do(req, &zones)
return zones, err
}
// Get returns a certain Zone for a given domain
func (z *ZonesService) Get(ctx context.Context, domain string) (*Zone, error) {
req, err := z.client.newRequest(ctx, "GET", fmt.Sprintf("servers/%s/zones/%s", z.client.VHost, makeDomainCanonical(domain)), nil, nil)
if err != nil {
return nil, err
}
zone := &Zone{}
_, err = z.client.do(req, &zone)
return zone, err
}
// AddNative creates a new native zone
func (z *ZonesService) AddNative(ctx context.Context, domain string, dnssec bool, nsec3Param string, nsec3Narrow bool, soaEdit, soaEditApi string, apiRectify bool, nameservers []string) (*Zone, error) {
zone := Zone{
Name: String(domain),
Kind: ZoneKindPtr(NativeZoneKind),
DNSsec: Bool(dnssec),
SOAEdit: String(soaEdit),
SOAEditAPI: String(soaEditApi),
APIRectify: Bool(apiRectify),
Nameservers: nameservers,
}
if dnssec {
zone.Nsec3Param = String(nsec3Param)
zone.Nsec3Narrow = Bool(nsec3Narrow)
}
return z.postZone(ctx, &zone)
}
// AddMaster creates a new master zone
func (z *ZonesService) AddMaster(ctx context.Context, domain string, dnssec bool, nsec3Param string, nsec3Narrow bool, soaEdit, soaEditApi string, apiRectify bool, nameservers []string) (*Zone, error) {
zone := Zone{
Name: String(domain),
Kind: ZoneKindPtr(MasterZoneKind),
DNSsec: Bool(dnssec),
SOAEdit: String(soaEdit),
SOAEditAPI: String(soaEditApi),
APIRectify: Bool(apiRectify),
Nameservers: nameservers,
}
if dnssec {
zone.Nsec3Param = String(nsec3Param)
zone.Nsec3Narrow = Bool(nsec3Narrow)
}
return z.postZone(ctx, &zone)
}
// AddSlave creates a new slave zone
func (z *ZonesService) AddSlave(ctx context.Context, domain string, masters []string) (*Zone, error) {
zone := Zone{
Name: String(domain),
Kind: ZoneKindPtr(SlaveZoneKind),
Masters: masters,
}
return z.postZone(ctx, &zone)
}
// Add pre-created zone
func (z *ZonesService) Add(ctx context.Context, zone *Zone) (*Zone, error) {
return z.postZone(ctx, zone)
}
func (z *ZonesService) postZone(ctx context.Context, zone *Zone) (*Zone, error) {
zone.Name = String(makeDomainCanonical(*zone.Name))
zone.Type = ZoneTypePtr(ZoneZoneType)
req, err := z.client.newRequest(ctx, "POST", fmt.Sprintf("servers/%s/zones", z.client.VHost), nil, zone)
if err != nil {
return nil, err
}
createdZone := new(Zone)
_, err = z.client.do(req, &createdZone)
return createdZone, err
}
// Change modifies an existing zone
func (z *ZonesService) Change(ctx context.Context, domain string, zone *Zone) error {
zone.ID = nil
zone.Name = nil
zone.Type = nil
zone.URL = nil
if zone.DNSsec != nil && !*zone.DNSsec {
zone.Nsec3Param = nil
}
req, err := z.client.newRequest(ctx, "PUT", fmt.Sprintf("servers/%s/zones/%s", z.client.VHost, makeDomainCanonical(domain)), nil, zone)
if err != nil {
return err
}
_, err = z.client.do(req, nil)
return err
}
// Delete removes a certain Zone for a given domain
func (z *ZonesService) Delete(ctx context.Context, domain string) error {
req, err := z.client.newRequest(ctx, "DELETE", fmt.Sprintf("servers/%s/zones/%s", z.client.VHost, makeDomainCanonical(domain)), nil, nil)
if err != nil {
return err
}
_, err = z.client.do(req, nil)
return err
}
// Notify sends a DNS notify packet to all slaves
func (z *ZonesService) Notify(ctx context.Context, domain string) (*NotifyResult, error) {
req, err := z.client.newRequest(ctx, "PUT", fmt.Sprintf("servers/%s/zones/%s/notify", z.client.VHost, makeDomainCanonical(domain)), nil, nil)
if err != nil {
return nil, err
}
notifyResult := &NotifyResult{}
_, err = z.client.do(req, notifyResult)
return notifyResult, err
}
// AxfrRetrieve requests a axfr transfer from the master to requesting slave
func (z *ZonesService) AxfrRetrieve(ctx context.Context, domain string) (*AxfrRetrieveResult, error) {
req, err := z.client.newRequest(ctx, "PUT", fmt.Sprintf("servers/%s/zones/%s/axfr-retrieve", z.client.VHost, makeDomainCanonical(domain)), nil, nil)
if err != nil {
return nil, err
}
axfrRetrieveResult := &AxfrRetrieveResult{}
_, err = z.client.do(req, axfrRetrieveResult)
return axfrRetrieveResult, err
}
// Export returns a BIND-like Zone file
func (z *ZonesService) Export(ctx context.Context, domain string) (Export, error) {
req, err := z.client.newRequest(ctx, "GET", fmt.Sprintf("servers/%s/zones/%s/export", z.client.VHost, makeDomainCanonical(domain)), nil, nil)
if err != nil {
return "", err
}
resp, err := z.client.do(req, nil)
if err != nil {
return "", err
}
bodyBytes, _ := io.ReadAll(resp.Body)
return Export(bodyBytes), nil
}