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