zone.go raw
1 package rest
2
3 import (
4 "errors"
5 "fmt"
6 "net/http"
7
8 "gopkg.in/ns1/ns1-go.v2/rest/model/dns"
9 )
10
11 // ZonesService handles 'zones' endpoint.
12 type ZonesService service
13
14 // List returns all active zones and basic zone configuration details for each.
15 //
16 // NS1 API docs: https://ns1.com/api/#zones-get
17 func (s *ZonesService) List() ([]*dns.Zone, *http.Response, error) {
18 req, err := s.client.NewRequest("GET", "zones", nil)
19 if err != nil {
20 return nil, nil, err
21 }
22
23 zl := []*dns.Zone{}
24 var resp *http.Response
25 if s.client.FollowPagination {
26 resp, err = s.client.DoWithPagination(req, &zl, s.nextZones)
27 } else {
28 resp, err = s.client.Do(req, &zl)
29 }
30 if err != nil {
31 return nil, resp, err
32 }
33
34 return zl, resp, nil
35 }
36
37 // Get takes a zone name and returns a single active zone and its basic configuration details.
38 //
39 // records Optional Query Parameter, if false records array in payload returns empty
40 //
41 // NS1 API docs: https://ns1.com/api/#zones-zone-get
42 func (s *ZonesService) Get(zone string, records bool) (*dns.Zone, *http.Response, error) {
43 path := fmt.Sprintf("zones/%s", zone)
44 if !records {
45 path = fmt.Sprintf("%s%s", path, "?records=false")
46 }
47
48 req, err := s.client.NewRequest("GET", path, nil)
49 if err != nil {
50 return nil, nil, err
51 }
52
53 var z dns.Zone
54 var resp *http.Response
55 if s.client.FollowPagination {
56 resp, err = s.client.DoWithPagination(req, &z, s.nextRecords)
57 } else {
58 resp, err = s.client.Do(req, &z)
59 }
60 if err != nil {
61 switch err.(type) {
62 case *Error:
63 if err.(*Error).Message == "zone not found" {
64 return nil, resp, ErrZoneMissing
65 }
66 }
67 return nil, resp, err
68 }
69
70 return &z, resp, nil
71 }
72
73 // Create takes a *Zone and creates a new DNS zone.
74 //
75 // NS1 API docs: https://ns1.com/api/#zones-put
76 func (s *ZonesService) Create(z *dns.Zone) (*http.Response, error) {
77 path := fmt.Sprintf("zones/%s", z.Zone)
78
79 req, err := s.client.NewRequest("PUT", path, &z)
80 if err != nil {
81 return nil, err
82 }
83
84 // Update zones fields with data from api(ensure consistent)
85 resp, err := s.client.Do(req, &z)
86 if err != nil {
87 switch err.(type) {
88 case *Error:
89 if err.(*Error).Message == "zone already exists" ||
90 err.(*Error).Message == "invalid: FQDN already exists" ||
91 err.(*Error).Message == "invalid: FQDN already exists in the view" {
92 return resp, ErrZoneExists
93 }
94 }
95 return resp, err
96 }
97
98 return resp, nil
99 }
100
101 // Update takes a *Zone and modifies basic details of a DNS zone.
102 //
103 // NS1 API docs: https://ns1.com/api/#zones-post
104 func (s *ZonesService) Update(z *dns.Zone) (*http.Response, error) {
105 path := fmt.Sprintf("zones/%s", z.Zone)
106
107 req, err := s.client.NewRequest("POST", path, &z)
108 if err != nil {
109 return nil, err
110 }
111
112 // Update zones fields with data from api(ensure consistent)
113 resp, err := s.client.Do(req, &z)
114 if err != nil {
115 switch err.(type) {
116 case *Error:
117 if err.(*Error).Message == "zone not found" {
118 return resp, ErrZoneMissing
119 }
120 }
121 return resp, err
122 }
123
124 return resp, nil
125 }
126
127 // Delete takes a zone and destroys an existing DNS zone and all records in the zone.
128 //
129 // NS1 API docs: https://ns1.com/api/#zones-delete
130 func (s *ZonesService) Delete(zone string) (*http.Response, error) {
131 path := fmt.Sprintf("zones/%s", zone)
132
133 req, err := s.client.NewRequest("DELETE", path, nil)
134 if err != nil {
135 return nil, err
136 }
137
138 resp, err := s.client.Do(req, nil)
139 if err != nil {
140 switch err.(type) {
141 case *Error:
142 if err.(*Error).Message == "zone not found" {
143 return resp, ErrZoneMissing
144 }
145 }
146 return resp, err
147 }
148
149 return resp, nil
150 }
151
152 // nextZones is a pagination helper than gets and appends another list of zones
153 // to the passed list.
154 func (s *ZonesService) nextZones(v *interface{}, uri string) (*http.Response, error) {
155 tmpZl := []*dns.Zone{}
156 resp, err := s.client.getURI(&tmpZl, uri)
157 if err != nil {
158 return resp, err
159 }
160 zoneList, ok := (*v).(*[]*dns.Zone)
161 if !ok {
162 return nil, fmt.Errorf(
163 "incorrect value for v, expected value of type *[]*dns.Zone, got: %T", v,
164 )
165 }
166 *zoneList = append(*zoneList, tmpZl...)
167 return resp, nil
168 }
169
170 // nextRecords is a pagination helper tha gets and appends another set of
171 // records to the passed zone.
172 func (s *ZonesService) nextRecords(v *interface{}, uri string) (*http.Response, error) {
173 var tmpZone dns.Zone
174 resp, err := s.client.getURI(&tmpZone, uri)
175 if err != nil {
176 return resp, err
177 }
178 zone, ok := (*v).(*dns.Zone)
179 if !ok {
180 return nil, fmt.Errorf(
181 "incorrect value for v, expected value of type *dns.Zone, got: %T", v,
182 )
183 }
184 // Aside from Records, the rest of the zone data is identical in the
185 // paginated response.
186 zone.Records = append(zone.Records, tmpZone.Records...)
187 return resp, nil
188 }
189
190 var (
191 // ErrZoneExists bundles PUT create error.
192 ErrZoneExists = errors.New("zone already exists")
193 // ErrZoneMissing bundles GET/POST/DELETE error.
194 ErrZoneMissing = errors.New("zone does not exist")
195 )
196