Change Aurora DNS client (#683)

This commit is contained in:
Ludovic Fernandez 2018-10-22 20:42:22 +02:00 committed by GitHub
parent 5511373184
commit a68cb214d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 434 additions and 392 deletions

27
Gopkg.lock generated
View file

@ -174,21 +174,6 @@
pruneopts = "NUT"
revision = "35bcc6b47c20ec9bf3a53adcb7fa9665a75f0e7b"
[[projects]]
digest = "1:82127d77b40b617d650e64dc287cfc190f31d1030bd01cae5110780dd1e5bbb3"
name = "github.com/edeckers/auroradnsclient"
packages = [
".",
"records",
"requests",
"requests/errors",
"tokens",
"zones",
]
pruneopts = "NUT"
revision = "1563e622aaca0a8bb895a448f31d4a430ab97586"
version = "v1.0.3"
[[projects]]
digest = "1:e096f1857eedd49e2bd0885d05105d1d4af1bfcf8b1d07fa5710718e6641fd48"
name = "github.com/exoscale/egoscale"
@ -271,6 +256,14 @@
revision = "59fac5042749a5afb9af70e813da1dd5474f0167"
version = "1.0.1"
[[projects]]
digest = "1:417193ba917954c4837c6fc48c6ac241b3fefd13fc0889367b4a7e43b69d582c"
name = "github.com/ldez/go-auroradns"
packages = ["."]
pruneopts = "NUT"
revision = "b40dfcae7c417f8129579362695dc1f3cfe5928d"
version = "v2.0.0"
[[projects]]
digest = "1:111ff5a09a32895248270bfaef9b8b6ac163a8cde9cdd603fed64b3e4b59e8ab"
name = "github.com/linode/linodego"
@ -604,12 +597,10 @@
"github.com/cpu/goacmedns",
"github.com/decker502/dnspod-go",
"github.com/dnsimple/dnsimple-go/dnsimple",
"github.com/edeckers/auroradnsclient",
"github.com/edeckers/auroradnsclient/records",
"github.com/edeckers/auroradnsclient/zones",
"github.com/exoscale/egoscale",
"github.com/iij/doapi",
"github.com/iij/doapi/protocol",
"github.com/ldez/go-auroradns",
"github.com/linode/linodego",
"github.com/miekg/dns",
"github.com/namedotcom/go/namecom",

View file

@ -7,9 +7,7 @@ import (
"sync"
"time"
"github.com/edeckers/auroradnsclient"
"github.com/edeckers/auroradnsclient/records"
"github.com/edeckers/auroradnsclient/zones"
"github.com/ldez/go-auroradns"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/platform/config/env"
)
@ -40,7 +38,7 @@ type DNSProvider struct {
recordIDs map[string]string
recordIDsMu sync.Mutex
config *Config
client *auroradnsclient.AuroraDNSClient
client *auroradns.Client
}
// NewDNSProvider returns a DNSProvider instance configured for AuroraDNS.
@ -86,7 +84,12 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
config.BaseURL = defaultBaseURL
}
client, err := auroradnsclient.NewAuroraDNSClient(config.BaseURL, config.UserID, config.Key)
tr, err := auroradns.NewTokenTransport(config.UserID, config.Key)
if err != nil {
return nil, fmt.Errorf("aurora: %v", err)
}
client, err := auroradns.NewClient(tr.Client(), auroradns.WithBaseURL(config.BaseURL))
if err != nil {
return nil, fmt.Errorf("aurora: %v", err)
}
@ -118,26 +121,25 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
authZone = acme.UnFqdn(authZone)
zoneRecord, err := d.getZoneInformationByName(authZone)
zone, err := d.getZoneInformationByName(authZone)
if err != nil {
return fmt.Errorf("aurora: could not create record: %v", err)
}
reqData :=
records.CreateRecordRequest{
record := auroradns.Record{
RecordType: "TXT",
Name: subdomain,
Content: value,
TTL: d.config.TTL,
}
respData, err := d.client.CreateRecord(zoneRecord.ID, reqData)
newRecord, _, err := d.client.CreateRecord(zone.ID, record)
if err != nil {
return fmt.Errorf("aurora: could not create record: %v", err)
}
d.recordIDsMu.Lock()
d.recordIDs[fqdn] = respData.ID
d.recordIDs[fqdn] = newRecord.ID
d.recordIDsMu.Unlock()
return nil
@ -162,12 +164,12 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
authZone = acme.UnFqdn(authZone)
zoneRecord, err := d.getZoneInformationByName(authZone)
zone, err := d.getZoneInformationByName(authZone)
if err != nil {
return err
}
_, err = d.client.RemoveRecord(zoneRecord.ID, recordID)
_, _, err = d.client.DeleteRecord(zone.ID, recordID)
if err != nil {
return err
}
@ -185,10 +187,10 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
return d.config.PropagationTimeout, d.config.PollingInterval
}
func (d *DNSProvider) getZoneInformationByName(name string) (zones.ZoneRecord, error) {
zs, err := d.client.GetZones()
func (d *DNSProvider) getZoneInformationByName(name string) (auroradns.Zone, error) {
zs, _, err := d.client.ListZones()
if err != nil {
return zones.ZoneRecord{}, err
return auroradns.Zone{}, err
}
for _, element := range zs {
@ -197,5 +199,5 @@ func (d *DNSProvider) getZoneInformationByName(name string) (zones.ZoneRecord, e
}
}
return zones.ZoneRecord{}, fmt.Errorf("could not find Zone record")
return auroradns.Zone{}, fmt.Errorf("could not find Zone record")
}

View file

@ -1,22 +0,0 @@
package auroradnsclient
import (
"github.com/edeckers/auroradnsclient/requests"
)
// AuroraDNSClient is a client for accessing the Aurora DNS API
type AuroraDNSClient struct {
requestor *requests.AuroraRequestor
}
// NewAuroraDNSClient instantiates a new client
func NewAuroraDNSClient(endpoint string, userID string, key string) (*AuroraDNSClient, error) {
requestor, err := requests.NewAuroraRequestor(endpoint, userID, key)
if err != nil {
return nil, err
}
return &AuroraDNSClient{
requestor: requestor,
}, nil
}

View file

@ -1,11 +0,0 @@
package auroradnsclient
// AuroraDNSError describes the format of a generic AuroraDNS API error
type AuroraDNSError struct {
ErrorCode string `json:"error"`
Message string `json:"errormsg"`
}
func (e AuroraDNSError) Error() string {
return e.Message
}

View file

@ -1,75 +0,0 @@
package auroradnsclient
import (
"encoding/json"
"fmt"
"github.com/edeckers/auroradnsclient/records"
"github.com/sirupsen/logrus"
)
// GetRecords returns a list of all records in given zone
func (client *AuroraDNSClient) GetRecords(zoneID string) ([]records.GetRecordsResponse, error) {
logrus.Debugf("GetRecords(%s)", zoneID)
relativeURL := fmt.Sprintf("zones/%s/records", zoneID)
response, err := client.requestor.Request(relativeURL, "GET", []byte(""))
if err != nil {
logrus.Errorf("Failed to receive records: %s", err)
return nil, err
}
var respData []records.GetRecordsResponse
err = json.Unmarshal(response, &respData)
if err != nil {
logrus.Errorf("Failed to unmarshall response: %s", err)
return nil, err
}
return respData, nil
}
// CreateRecord creates a new record in given zone
func (client *AuroraDNSClient) CreateRecord(zoneID string, data records.CreateRecordRequest) (*records.CreateRecordResponse, error) {
logrus.Debugf("CreateRecord(%s, %+v)", zoneID, data)
body, err := json.Marshal(data)
if err != nil {
logrus.Errorf("Failed to marshall request body: %s", err)
return nil, err
}
relativeURL := fmt.Sprintf("zones/%s/records", zoneID)
response, err := client.requestor.Request(relativeURL, "POST", body)
if err != nil {
logrus.Errorf("Failed to create record: %s", err)
return nil, err
}
var respData *records.CreateRecordResponse
err = json.Unmarshal(response, &respData)
if err != nil {
logrus.Errorf("Failed to unmarshall response: %s", err)
return nil, err
}
return respData, nil
}
// RemoveRecord removes a record corresponding to a particular id in a given zone
func (client *AuroraDNSClient) RemoveRecord(zoneID string, recordID string) (*records.RemoveRecordResponse, error) {
logrus.Debugf("RemoveRecord(%s, %s)", zoneID, recordID)
relativeURL := fmt.Sprintf("zones/%s/records/%s", zoneID, recordID)
_, err := client.requestor.Request(relativeURL, "DELETE", nil)
if err != nil {
logrus.Errorf("Failed to remove record: %s", err)
return nil, err
}
return &records.RemoveRecordResponse{}, nil
}

View file

@ -1,31 +0,0 @@
package records
// CreateRecordRequest describes the json payload for creating a record
type CreateRecordRequest struct {
RecordType string `json:"type"`
Name string `json:"name"`
Content string `json:"content"`
TTL int `json:"ttl"`
}
// CreateRecordResponse describes the json response for creating a record
type CreateRecordResponse struct {
ID string `json:"id"`
RecordType string `json:"type"`
Name string `json:"name"`
Content string `json:"content"`
TTL int `json:"ttl"`
}
// GetRecordsResponse describes the json response of a single record
type GetRecordsResponse struct {
ID string `json:"id"`
RecordType string `json:"type"`
Name string `json:"name"`
Content string `json:"content"`
TTL int `json:"ttl"`
}
// RemoveRecordResponse describes the json response for removing a record
type RemoveRecordResponse struct {
}

View file

@ -1,19 +0,0 @@
package errors
// BadRequest HTTP error wrapper
type BadRequest error
// Unauthorized HTTP error wrapper
type Unauthorized error
// Forbidden HTTP error wrapper
type Forbidden error
// NotFound HTTP error wrapper
type NotFound error
// ServerError HTTP error wrapper
type ServerError error
// InvalidStatusCodeError is used when none of the other types applies
type InvalidStatusCodeError error

View file

@ -1,124 +0,0 @@
package requests
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/http/httputil"
"time"
request_errors "github.com/edeckers/auroradnsclient/requests/errors"
"github.com/edeckers/auroradnsclient/tokens"
"github.com/sirupsen/logrus"
)
// AuroraRequestor performs actual requests to API
type AuroraRequestor struct {
endpoint string
userID string
key string
}
// NewAuroraRequestor instantiates a new requestor
func NewAuroraRequestor(endpoint string, userID string, key string) (*AuroraRequestor, error) {
if endpoint == "" {
return nil, fmt.Errorf("Aurora endpoint missing")
}
if userID == "" || key == "" {
return nil, fmt.Errorf("Aurora credentials missing")
}
return &AuroraRequestor{endpoint: endpoint, userID: userID, key: key}, nil
}
func (requestor *AuroraRequestor) buildRequest(relativeURL string, method string, body []byte) (*http.Request, error) {
url := fmt.Sprintf("%s/%s", requestor.endpoint, relativeURL)
request, err := http.NewRequest(method, url, bytes.NewReader(body))
if err != nil {
logrus.Errorf("Failed to build request: %s", err)
return request, err
}
timestamp := time.Now().UTC()
fmtTime := timestamp.Format("20060102T150405Z")
token := tokens.NewToken(requestor.userID, requestor.key, method, fmt.Sprintf("/%s", relativeURL), timestamp)
request.Header.Set("X-AuroraDNS-Date", fmtTime)
request.Header.Set("Authorization", fmt.Sprintf("AuroraDNSv1 %s", token))
request.Header.Set("Content-Type", "application/json")
rawRequest, err := httputil.DumpRequestOut(request, true)
if err != nil {
logrus.Errorf("Failed to dump request: %s", err)
}
logrus.Debugf("Built request:\n%s", rawRequest)
return request, err
}
func (requestor *AuroraRequestor) testInvalidResponse(resp *http.Response, response []byte) ([]byte, error) {
if resp.StatusCode < 400 {
return response, nil
}
logrus.Errorf("Received invalid status code %d:\n%s", resp.StatusCode, response)
content := errors.New(string(response))
statusCodeErrorMap := map[int]error{
400: request_errors.BadRequest(content),
401: request_errors.Unauthorized(content),
403: request_errors.Forbidden(content),
404: request_errors.NotFound(content),
500: request_errors.ServerError(content),
}
mappedError := statusCodeErrorMap[resp.StatusCode]
if mappedError == nil {
return nil, request_errors.InvalidStatusCodeError(content)
}
return nil, mappedError
}
// Request builds and executues a request to the API
func (requestor *AuroraRequestor) Request(relativeURL string, method string, body []byte) ([]byte, error) {
req, err := requestor.buildRequest(relativeURL, method, body)
client := http.Client{Timeout: 30 * time.Second}
resp, err := client.Do(req)
if err != nil {
logrus.Errorf("Failed request: %s", err)
return nil, err
}
defer resp.Body.Close()
rawResponse, err := httputil.DumpResponse(resp, true)
logrus.Debugf("Received raw response:\n%s", rawResponse)
if err != nil {
logrus.Errorf("Failed to dump response: %s", err)
}
response, err := ioutil.ReadAll(resp.Body)
if err != nil {
logrus.Errorf("Failed to read response: %s", response)
return nil, err
}
response, err = requestor.testInvalidResponse(resp, response)
if err != nil {
return nil, err
}
return response, nil
}

View file

@ -1,35 +0,0 @@
package tokens
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"strings"
"time"
"github.com/sirupsen/logrus"
)
// NewToken generates a token for accessing a specific method of the API
func NewToken(userID string, key string, method string, action string, timestamp time.Time) string {
fmtTime := timestamp.Format("20060102T150405Z")
logrus.Debugf("Built timestamp: %s", fmtTime)
message := strings.Join([]string{method, action, fmtTime}, "")
logrus.Debugf("Built message: %s", message)
signatureHmac := hmac.New(sha256.New, []byte(key))
signatureHmac.Write([]byte(message))
signature := base64.StdEncoding.EncodeToString([]byte(signatureHmac.Sum(nil)))
logrus.Debugf("Built signature: %s", signature)
userIDAndSignature := fmt.Sprintf("%s:%s", userID, signature)
token := base64.StdEncoding.EncodeToString([]byte(userIDAndSignature))
logrus.Debugf("Built token: %s", token)
return token
}

View file

@ -1,29 +0,0 @@
package auroradnsclient
import (
"encoding/json"
"github.com/edeckers/auroradnsclient/zones"
"github.com/sirupsen/logrus"
)
// GetZones returns a list of all zones
func (client *AuroraDNSClient) GetZones() ([]zones.ZoneRecord, error) {
logrus.Debugf("GetZones")
response, err := client.requestor.Request("zones", "GET", []byte(""))
if err != nil {
logrus.Errorf("Failed to get zones: %s", err)
return nil, err
}
var respData []zones.ZoneRecord
err = json.Unmarshal(response, &respData)
if err != nil {
logrus.Errorf("Failed to unmarshall response: %s", err)
return nil, err
}
logrus.Debugf("Unmarshalled response: %+v", respData)
return respData, nil
}

View file

@ -1,7 +0,0 @@
package zones
// ZoneRecord describes the json format for a zone
type ZoneRecord struct {
ID string `json:"id"`
Name string `json:"name"`
}

98
vendor/github.com/ldez/go-auroradns/auth.go generated vendored Normal file
View file

@ -0,0 +1,98 @@
package auroradns
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"net/http"
"strings"
"time"
)
// TokenTransport HTTP transport for API authentication
type TokenTransport struct {
userID string
key string
// Transport is the underlying HTTP transport to use when making requests.
// It will default to http.DefaultTransport if nil.
Transport http.RoundTripper
}
// NewTokenTransport Creates a new TokenTransport
func NewTokenTransport(userID, key string) (*TokenTransport, error) {
if userID == "" || key == "" {
return nil, fmt.Errorf("credentials missing")
}
return &TokenTransport{userID: userID, key: key}, nil
}
// RoundTrip executes a single HTTP transaction
func (t *TokenTransport) RoundTrip(req *http.Request) (*http.Response, error) {
enrichedReq := &http.Request{}
*enrichedReq = *req
enrichedReq.Header = make(http.Header, len(req.Header))
for k, s := range req.Header {
enrichedReq.Header[k] = append([]string(nil), s...)
}
if t.userID != "" && t.key != "" {
timestamp := time.Now().UTC()
fmtTime := timestamp.Format("20060102T150405Z")
req.Header.Set("X-AuroraDNS-Date", fmtTime)
token, err := newToken(t.userID, t.key, req.Method, req.URL.Path, timestamp)
if err == nil {
req.Header.Set("Authorization", fmt.Sprintf("AuroraDNSv1 %s", token))
}
}
return t.transport().RoundTrip(enrichedReq)
}
// Wrap Wrap a HTTP client Transport with the TokenTransport
func (t *TokenTransport) Wrap(client *http.Client) *http.Client {
backup := client.Transport
t.Transport = backup
client.Transport = t
return client
}
// Client Creates a new HTTP client
func (t *TokenTransport) Client() *http.Client {
return &http.Client{
Transport: t,
Timeout: 30 * time.Second,
}
}
func (t *TokenTransport) transport() http.RoundTripper {
if t.Transport != nil {
return t.Transport
}
return http.DefaultTransport
}
// newToken generates a token for accessing a specific method of the API
func newToken(userID string, key string, method string, action string, timestamp time.Time) (string, error) {
fmtTime := timestamp.Format("20060102T150405Z")
message := strings.Join([]string{method, action, fmtTime}, "")
signatureHmac := hmac.New(sha256.New, []byte(key))
_, err := signatureHmac.Write([]byte(message))
if err != nil {
return "", err
}
signature := base64.StdEncoding.EncodeToString(signatureHmac.Sum(nil))
userIDAndSignature := fmt.Sprintf("%s:%s", userID, signature)
token := base64.StdEncoding.EncodeToString([]byte(userIDAndSignature))
return token, nil
}

144
vendor/github.com/ldez/go-auroradns/client.go generated vendored Normal file
View file

@ -0,0 +1,144 @@
package auroradns
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
)
const defaultBaseURL = "https://api.auroradns.eu"
const (
contentTypeHeader = "Content-Type"
contentTypeJSON = "application/json"
)
// ErrorResponse A representation of an API error message.
type ErrorResponse struct {
ErrorCode string `json:"error"`
Message string `json:"errormsg"`
}
func (e *ErrorResponse) Error() string {
return fmt.Sprintf("%s - %s", e.ErrorCode, e.Message)
}
// Option Type of a client option
type Option func(*Client) error
// Client The API client
type Client struct {
baseURL *url.URL
UserAgent string
httpClient *http.Client
}
// NewClient Creates a new client
func NewClient(httpClient *http.Client, opts ...Option) (*Client, error) {
if httpClient == nil {
httpClient = http.DefaultClient
}
baseURL, _ := url.Parse(defaultBaseURL)
client := &Client{
baseURL: baseURL,
httpClient: httpClient,
}
for _, opt := range opts {
err := opt(client)
if err != nil {
return nil, err
}
}
return client, nil
}
func (c *Client) newRequest(method, resource string, body io.Reader) (*http.Request, error) {
u, err := c.baseURL.Parse(resource)
if err != nil {
return nil, err
}
req, err := http.NewRequest(method, u.String(), body)
if err != nil {
return nil, err
}
req.Header.Set(contentTypeHeader, contentTypeJSON)
if c.UserAgent != "" {
req.Header.Set("User-Agent", c.UserAgent)
}
return req, nil
}
func (c *Client) do(req *http.Request, v interface{}) (*http.Response, error) {
resp, err := c.httpClient.Do(req)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()
if err = checkResponse(resp); err != nil {
return resp, err
}
if v == nil {
return resp, nil
}
raw, err := ioutil.ReadAll(resp.Body)
if err != nil {
return resp, fmt.Errorf("failed to read body: %v", err)
}
if err = json.Unmarshal(raw, v); err != nil {
return resp, fmt.Errorf("unmarshaling %T error: %v: %s", err, v, string(raw))
}
return resp, nil
}
func checkResponse(resp *http.Response) error {
if c := resp.StatusCode; 200 <= c && c <= 299 {
return nil
}
data, err := ioutil.ReadAll(resp.Body)
if err == nil && data != nil {
errorResponse := new(ErrorResponse)
err = json.Unmarshal(data, errorResponse)
if err != nil {
return fmt.Errorf("unmarshaling ErrorResponse error: %v: %s", err.Error(), string(data))
}
return errorResponse
}
defer func() { _ = resp.Body.Close() }()
return nil
}
// WithBaseURL Allows to define a custom base URL
func WithBaseURL(rawBaseURL string) func(*Client) error {
return func(client *Client) error {
if len(rawBaseURL) == 0 {
return nil
}
baseURL, err := url.Parse(rawBaseURL)
if err != nil {
return err
}
client.baseURL = baseURL
return nil
}
}

91
vendor/github.com/ldez/go-auroradns/records.go generated vendored Normal file
View file

@ -0,0 +1,91 @@
package auroradns
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
// Record types
const (
RecordTypeA = "A"
RecordTypeAAAA = "AAAA"
RecordTypeCNAME = "CNAME"
RecordTypeMX = "MX"
RecordTypeNS = "NS"
RecordTypeSOA = "SOA"
RecordTypeSRV = "SRV"
RecordTypeTXT = "TXT"
RecordTypeDS = "DS"
RecordTypePTR = "PTR"
RecordTypeSSHFP = "SSHFP"
RecordTypeTLSA = "TLS"
)
// Record a DNS record
type Record struct {
ID string `json:"id,omitempty"`
RecordType string `json:"type"`
Name string `json:"name"`
Content string `json:"content"`
TTL int `json:"ttl,omitempty"`
}
// CreateRecord Creates a new record.
func (c *Client) CreateRecord(zoneID string, record Record) (*Record, *http.Response, error) {
body, err := json.Marshal(record)
if err != nil {
return nil, nil, fmt.Errorf("failed to marshall request body: %v", err)
}
resource := fmt.Sprintf("/zones/%s/records", zoneID)
req, err := c.newRequest(http.MethodPost, resource, bytes.NewReader(body))
if err != nil {
return nil, nil, err
}
newRecord := new(Record)
resp, err := c.do(req, newRecord)
if err != nil {
return nil, resp, err
}
return newRecord, resp, nil
}
// DeleteRecord Delete a record.
func (c *Client) DeleteRecord(zoneID string, recordID string) (bool, *http.Response, error) {
resource := fmt.Sprintf("/zones/%s/records/%s", zoneID, recordID)
req, err := c.newRequest(http.MethodDelete, resource, nil)
if err != nil {
return false, nil, err
}
resp, err := c.do(req, nil)
if err != nil {
return false, resp, err
}
return true, resp, nil
}
// ListRecords returns a list of all records in given zone
func (c *Client) ListRecords(zoneID string) ([]Record, *http.Response, error) {
resource := fmt.Sprintf("/zones/%s/records", zoneID)
req, err := c.newRequest(http.MethodGet, resource, nil)
if err != nil {
return nil, nil, err
}
var records []Record
resp, err := c.do(req, &records)
if err != nil {
return nil, resp, err
}
return records, resp, nil
}

69
vendor/github.com/ldez/go-auroradns/zones.go generated vendored Normal file
View file

@ -0,0 +1,69 @@
package auroradns
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
// Zone a DNS zone
type Zone struct {
ID string `json:"id,omitempty"`
Name string `json:"name"`
}
// CreateZone Creates a zone.
func (c *Client) CreateZone(domain string) (*Zone, *http.Response, error) {
body, err := json.Marshal(Zone{Name: domain})
if err != nil {
return nil, nil, fmt.Errorf("failed to marshall request body: %v", err)
}
req, err := c.newRequest(http.MethodPost, "/zones", bytes.NewReader(body))
if err != nil {
return nil, nil, err
}
zone := new(Zone)
resp, err := c.do(req, zone)
if err != nil {
return nil, resp, err
}
return zone, resp, nil
}
// DeleteZone Delete a zone.
func (c *Client) DeleteZone(zoneID string) (bool, *http.Response, error) {
resource := fmt.Sprintf("/zones/%s", zoneID)
req, err := c.newRequest(http.MethodDelete, resource, nil)
if err != nil {
return false, nil, err
}
resp, err := c.do(req, nil)
if err != nil {
return false, resp, err
}
return true, resp, nil
}
// ListZones returns a list of all zones.
func (c *Client) ListZones() ([]Zone, *http.Response, error) {
req, err := c.newRequest(http.MethodGet, "/zones", nil)
if err != nil {
return nil, nil, err
}
var zones []Zone
resp, err := c.do(req, &zones)
if err != nil {
return nil, resp, err
}
return zones, resp, nil
}