DNS Zones: List / Get (#271)
* Add Zone List / Get Support
* Addressing code review comments
* Adding v2 to DNS client
* List / Get unit tests plus updates to results for unit tests to work.
* DNS v2 List acceptance tests
* add failing unit test for dns v2 allpages
* Changing acceptance test for DNS v2 to use AllPages
* Adding empty zones.go file for package requirements
* Change ttl back to int
* DNS v2 Zones ListOpts
diff --git a/openstack/dns/v2/zones/results.go b/openstack/dns/v2/zones/results.go
new file mode 100644
index 0000000..4693b09
--- /dev/null
+++ b/openstack/dns/v2/zones/results.go
@@ -0,0 +1,144 @@
+package zones
+
+import (
+ "encoding/json"
+ "strconv"
+ "time"
+
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
+)
+
+type commonResult struct {
+ gophercloud.Result
+}
+
+// Extract interprets a GetResult, CreateResult or UpdateResult as a concrete Zone.
+// An error is returned if the original call or the extraction failed.
+func (r commonResult) Extract() (*Zone, error) {
+ var s *Zone
+ err := r.ExtractInto(&s)
+ return s, err
+}
+
+// GetResult is the deferred result of a Get call.
+type GetResult struct {
+ commonResult
+}
+
+// ZonePage is a single page of Zone results.
+type ZonePage struct {
+ pagination.LinkedPageBase
+}
+
+// IsEmpty returns true if the page contains no results.
+func (r ZonePage) IsEmpty() (bool, error) {
+ s, err := ExtractZones(r)
+ return len(s) == 0, err
+}
+
+// ExtractZones extracts a slice of Services from a Collection acquired from List.
+func ExtractZones(r pagination.Page) ([]Zone, error) {
+ var s struct {
+ Zones []Zone `json:"zones"`
+ }
+ err := (r.(ZonePage)).ExtractInto(&s)
+ return s.Zones, err
+}
+
+// Zone represents a DNS zone.
+type Zone struct {
+ // ID uniquely identifies this zone amongst all other zones, including those not accessible to the current tenant.
+ ID string `json:"id"`
+
+ // PoolID is the ID for the pool hosting this zone.
+ PoolID string `json:"pool_id"`
+
+ // ProjectID identifies the project/tenant owning this resource.
+ ProjectID string `json:"project_id"`
+
+ // Name is the DNS Name for the zone.
+ Name string `json:"name"`
+
+ // Email for the zone. Used in SOA records for the zone.
+ Email string `json:"email"`
+
+ // Description for this zone.
+ Description string `json:"description"`
+
+ // TTL is the Time to Live for the zone.
+ TTL int `json:"ttl"`
+
+ // Serial is the current serial number for the zone.
+ Serial int `json:"-"`
+
+ // Status is the status of the resource.
+ Status string `json:"status"`
+
+ // Action is the current action in progress on the resource.
+ Action string `json:"action"`
+
+ // Version of the resource.
+ Version int `json:"version"`
+
+ // Attributes for the zone.
+ Attributes map[string]string `json:"attributes"`
+
+ // Type of zone. Primary is controlled by Designate.
+ // Secondary zones are slaved from another DNS Server.
+ // Defaults to Primary.
+ Type string `json:"type"`
+
+ // Masters is the servers for slave servers to get DNS information from.
+ Masters []string `json:"masters"`
+
+ // CreatedAt is the date when the zone was created.
+ CreatedAt time.Time `json:"-"`
+
+ // UpdatedAt is the date when the last change was made to the zone.
+ UpdatedAt time.Time `json:"-"`
+
+ // TransferredAt is the last time an update was retrieved from the master servers.
+ TransferredAt time.Time `json:"-"`
+
+ // Links includes HTTP references to the itself, useful for passing along to other APIs that might want a server reference.
+ Links map[string]interface{} `json:"links"`
+}
+
+func (r *Zone) UnmarshalJSON(b []byte) error {
+ type tmp Zone
+ var s struct {
+ tmp
+ CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"`
+ UpdatedAt gophercloud.JSONRFC3339MilliNoZ `json:"updated_at"`
+ TransferredAt gophercloud.JSONRFC3339MilliNoZ `json:"transferred_at"`
+ Serial interface{} `json:"serial"`
+ }
+ err := json.Unmarshal(b, &s)
+ if err != nil {
+ return err
+ }
+ *r = Zone(s.tmp)
+
+ r.CreatedAt = time.Time(s.CreatedAt)
+ r.UpdatedAt = time.Time(s.UpdatedAt)
+ r.TransferredAt = time.Time(s.TransferredAt)
+
+ switch t := s.Serial.(type) {
+ case float64:
+ r.Serial = int(t)
+ case string:
+ switch t {
+ case "":
+ r.Serial = 0
+ default:
+ serial, err := strconv.ParseFloat(t, 64)
+ if err != nil {
+ return err
+ }
+ r.Serial = int(serial)
+ }
+ }
+
+ return err
+}