Jump to: navigation, search

Difference between revisions of "Designate/APIv2"

(Basic APIv2 Requirements)
m (Mark page as obsolete, to prevent future confusion)
 
(38 intermediate revisions by 3 users not shown)
Line 1: Line 1:
<blockquote>This is a EARLY DRAFT of the Designate Version 2 API.</blockquote>
+
<blockquote>This page should be considered obsolete.  Modern API documentation can be found [https://developer.openstack.org/api-ref/dns/ here].</blockquote>
 +
 
 +
<blockquote>This is a DRAFT of the Designate Version 2 API. The draft shall not be considered final until a implementation is complete.</blockquote>
 +
 
 +
= Introduction =
 +
 
 +
This specification document is intended to describe the concepts and conventions the Designate v2 API will conform to. Several common, or new, resources have been explicitly detailed, others have not. Any resources not explicitly detailed shall follow the conventions set in this document.
 +
 
 +
The Designate v2 API will eventually replace the v1 API, but there will be a period of time where both APIs exist alongside each other. The v1 API will not be affected by this spec. The length of time the v1 API is kept for is not addressed by this specification.
 +
 
 +
When in doubt - We follow the conventions set forth in the [https://github.com/openstack/identity-api/blob/master/openstack-identity-api/v3/src/markdown/identity-api-v3.md Keystone V3 API].
  
 
= Basic APIv2 Requirements =
 
= Basic APIv2 Requirements =
  
# Switch from string based rdata to dict based rdata. This allows for a sane API for the more complex record types (SRV, GEOIP, WRR etc).
+
# Switch from string based rdata to dict based rdata. This allows for a sane API for the more complex record types (SRV, GeoIP, WRR etc).
# # This complicates simple record types, but  simplifies complex record types (SRV, GEeoIP, Weigthed RR, Failover etc)
+
## This complicates simple record types, but  simplifies complex record types (SRV, GeoIP, Weighted RR, Failover etc)
 
# Introduce the concept of RecordSets. This helps our API more accurately reflect the DNS specs, and provides saner grouping of related rdatas.
 
# Introduce the concept of RecordSets. This helps our API more accurately reflect the DNS specs, and provides saner grouping of related rdatas.
 +
## See RFC2181 Section 5
 
# Document the concept of "server pools". This allows the API to remain the same if/when we introduce private DNS instances.
 
# Document the concept of "server pools". This allows the API to remain the same if/when we introduce private DNS instances.
 
# Provided a mechanism to prevent concurrent modifications.
 
# Provided a mechanism to prevent concurrent modifications.
 +
## This is intended to allow end users to prevent their API calls from updating a resource, if the resource has already been updated by another API client.
 
# Pagination
 
# Pagination
 
# Filtering of result sets
 
# Filtering of result sets
  
= TODOs =
+
= TODO =
  
# Ideally, we can support both dict and string based rdata's ({"weight": 0, "priority": 10, "target": "xmpp1.example.org."} AND "0 10 xmpp1.example.org.")
+
* All Tenants Access
# Pagination?
+
* How do we include "total items" in paginated response?
# All tenant access?
+
* How do we optionally include a nested collection?
# Should we include a top level container on responses?
+
* Document Error Response Format
# Filtering/searching syntax?
 
# Probably '''LOTS''' more
 
  
 
= Resources =
 
= Resources =
 +
 +
== Pool ==
 +
 +
A "pool" is a set of DNS servers to which a Zone may be scheduled. Each pool has a distinct Zone namespace, allowing "example.com" to exist in multiple pools.
 +
 +
Pools may be defined by the provider, and marked "public". Public pools will have zones from multiple customers while private pools will be restricted to a single project_id.
 +
 +
Additionally, private pools may be created by a customer. Available pool flavors are defined by the provider, and may include attributes such as "Number of Nameservers", "AnyCast" etc.
 +
 +
The intention of this API is twofold:
 +
 +
# In order for the provider to offer multiple tiers of service. For example, a "standard" service operated out of two datacenters, and a "premium" service operated via many datacenters using AnyCast.
 +
# In order to allow customers to create "private" nameservers, intended for use only be their instances. This allows customers to create "dev.local" style domains, without conflicting with other users or exposing these names to the global internet.
 +
 +
{| class="wikitable sortable"
 +
! Property    !! Type        !! Default        !! Required    !! Immutable !! Read Only
 +
|-
 +
| id          || uuid        || Generated      || ✔            || ✔        || ✔ 
 +
|-
 +
| project_id  || uuid        || None          || ✘            || ✔        || ✔ 
 +
|-
 +
| name        || string      || None          || ✔            || ✘        || ✘ 
 +
|-
 +
| flavor_id  || string      || None          || ✔            || ✔        || ✘ 
 +
|-
 +
| public      || boolean      || False          || ✘            || ✔        || ✘
 +
|-
 +
| nameservers || list<string> || Empty List    || ✔            || ✘        || ✔
 +
|-
 +
| notes      || string      || None          || ✘            || ✘        || ✘
 +
|-
 +
| status      || string      || None          || ✔            || ✔        || ✔
 +
|-
 +
| version    || int          || Generated      || ✔            || ✘        || ✔
 +
|-
 +
| created_at  || timestamp    || Generated      || ✔            || ✔        || ✔ 
 +
|-
 +
| updated_at  || timestamp    || Generated      || ✔            || ✘        || ✔ 
 +
|}
 +
 +
The "status" property may have value of "ACTIVE", "PENDING", "DELETING",  "ERROR", "ERROR_DELETING" or "SUSPENDED".
  
 
== Zone ==
 
== Zone ==
Line 30: Line 81:
 
|-
 
|-
 
| pool_id    || uuid        || Configured    || ✘            || ✔        || ✘   
 
| pool_id    || uuid        || Configured    || ✘            || ✔        || ✘   
 +
|-
 +
| project_id || uuid        || None          || ✔            || ✔        || ✔ 
 
|-
 
|-
 
| name      || string      || None          || ✔            || ✔        || ✘   
 
| name      || string      || None          || ✔            || ✔        || ✘   
Line 38: Line 91:
 
|-
 
|-
 
| serial    || int          || Generated      || ✔            || ✘        || ✔   
 
| serial    || int          || Generated      || ✔            || ✘        || ✔   
 +
|-
 +
| notes      || string      || None          || ✘            || ✘        || ✘ 
 +
|-
 +
| status    || string      || None          || ✔            || ✔        || ✔ 
 
|-
 
|-
 
| version    || int          || Generated      || ✔            || ✘        || ✔   
 
| version    || int          || Generated      || ✔            || ✘        || ✔   
 
|-
 
|-
| created_at || timestamp    || Generated      || ✔            ||         || ✔   
+
| created_at || timestamp    || Generated      || ✔            ||         || ✔   
 
|-
 
|-
 
| updated_at || timestamp    || Generated      || ✔            || ✘        || ✔   
 
| updated_at || timestamp    || Generated      || ✔            || ✘        || ✔   
 
|}
 
|}
 +
 +
The "status" property may have value of "ACTIVE", "PENDING", "DELETING",  "ERROR", "ERROR_DELETING" or "SUSPENDED".
  
 
== Record Set ==
 
== Record Set ==
  
 
{| class="wikitable sortable"
 
{| class="wikitable sortable"
! Property  !! Type        !! Default        !! Required             !! Immutable !! Read Only
+
! Property  !! Type        !! Default        !! Required     !! Immutable !! Read Only
 +
|-
 +
| id        || uuid        || Generated      || ✔            || ✔        || ✔
 +
|-
 +
| zone_id  || uuid        || Configured    || ✔            || ✔        || ✔
 
|-
 
|-
| id        || uuid        || Generated      || ✔                     || ✔        ||
+
| name      || domainname  || None          || ✔           || ✔        ||
 
|-
 
|-
| zone_id  || uuid        || Configured    || ✔                     || ✔        ||
+
| type      || string      || None          || ✔           || ✔        ||
 
|-
 
|-
| name      || domainname  || None          || ✔                     ||         || ✘
+
| ttl      || int          || nil            || ✔           ||         || ✘
 
|-
 
|-
| type      || string      || None          || ✔                     ||         || ✘
+
| records  || list<rdata>  || Empty List    || ✔           ||         || ✘
 
|-
 
|-
| ttl       || int          || nil           || ✔                    || ✘        || ✘
+
| notes    || string       || None          ||           || ✘        || ✘
 
|-
 
|-
| records  || list<rdata>  || Empty List    || ✔                     ||         ||
+
| status    || string      || None          || ✔           ||         || ✔ 
 
|-
 
|-
| version  || int          || Generated      || ✔                     || ✘        || ✔
+
| version  || int          || Generated      || ✔           || ✘        || ✔
 
|-
 
|-
| created_at|| timestamp    || Generated      || ✔                     ||         || ✔
+
| created_at|| timestamp    || Generated      || ✔           ||         || ✔
 
|-
 
|-
| updated_at|| timestamp    || Generated      || ✔                     || ✘        || ✔
+
| updated_at|| timestamp    || Generated      || ✔           || ✘        || ✔
 
|}
 
|}
 +
 +
The "status" property may have value of "ACTIVE", "PENDING", "DELETING",  "ERROR" or "ERROR_DELETING".
  
 
== RData ==
 
== RData ==
 +
 +
<blockquote><strong>Note:</strong> This list of RData is NOT the entire list. Additional RData types, including psuedo RData's for things likle GeoIP/WRR/Failover, may be added without violating the spec.</blockquote>
  
 
=== A ===
 
=== A ===
Line 124: Line 191:
 
=== SOA ===
 
=== SOA ===
  
{note:title=Additional Restrictions}Only 1 SOA record may be present in a zone, and it must be at the root of the zone{note}
+
<blockquote><strong>Additional Restrictions:</strong> Only 1 SOA record may be present in a zone, and it must be at the root of the zone</blockquote>
  
 
{| class="wikitable sortable"
 
{| class="wikitable sortable"
Line 185: Line 252:
 
| text      || string      || None          || ✔                    || ✘        || ✘
 
| text      || string      || None          || ✔                    || ✘        || ✘
 
|}
 
|}
 +
 +
= Conventions =
 +
 +
== General ==
 +
 +
=== Synchronous vs Asynchronous ===
 +
 +
All Create, Update, and Delete operations can be either asynchronous or synchronous. Asynchronous operations are restricted to resources containing a "status" attribute. API Consumers MUST NOT make the assumption that any API call is always asynchronous or synchronous. This document defines the method which API consumers may use to determine if a completed API call was asynchronous or synchronous.
 +
 +
''' Synchronous '''
 +
 +
Synchronous Create/Update/Delete API calls will return a HTTP status of either "201 Created", "200 OK" or "204 No Content" respectivly. Additionally, resources which contain a "status" property MUST have the value "ACTIVE".
 +
 +
''' Asynchronous '''
 +
 +
Asynchronous Create/Update/Delete API calls will return a HTTP status of "202 Accepted". The "status" property MUST NOT have the value "ACTIVE".
 +
 +
Clients can determine if an asynchronous job is complete by querying the resource URL (or, for creates, the URL returned in the "Location" header) and checking the value of the "status" property. Once the job is complete, the status field will be "ACTIVE".
 +
 +
== Collections ==
 +
 +
The following conventions apply to all collections, unless otherwise noted below.
 +
 +
==== Links ====
 +
 +
A links object will exist at the root of all Collection responses. At the minimun, it will contain a "self" link. If the collection resultset is not complete, a "next" and/or "previous" link will be included for pagination.
 +
 +
''' Response: '''
 +
 +
  HTTP/1.1 200 OK
 +
  Vary: Accept
 +
  Content-Type: application/json
 +
 +
  {
 +
    "examples": [{
 +
      "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
 +
      "....": "...."
 +
    }, {
 +
      "id": "fdd7b0dc-52a3-491e-829f-41d18e1d3ada",
 +
      "....": "...."
 +
    }],
 +
    "links": {
 +
      "self": "<URL for This Page>",
 +
      "next": "<URL for Next Page>",
 +
      "previous": "<URL for Previous Page>"
 +
    }
 +
  }
 +
 +
==== Pagination ====
 +
 +
Pagination is available on all collections and is controlled using a combination of two query paramaters - `marker=<UUID>&limit=<INTEGER>`. Collection responses will include a `links` object containing absolute URLs for the `next` and `previous` pages. These links may be omitted, or null, at the edges of a paginated collection.
 +
 +
To navigate the collection, the parameters limit and marker can be set in the URI (e.g.?limit=100&marker=<UUID>). The marker parameter is the ID of the last item in the previous list. Items are sorted by create time in descending order. When a create time is not available they are sorted by ID. The limit parameter sets the page size. Both parameters are optional.
 +
 +
''' Request: '''
 +
 +
  GET /v2/examples?marker=c74af170-0673-11e3-8ffd-0800200c9a66&limit=2 HTTP/1.1
 +
  Host: dns.provider.com
 +
  Accept: application/json
 +
  X-Auth-Token: HPAuth_*****
 +
 +
''' Response: '''
 +
 +
  HTTP/1.1 200 OK
 +
  Vary: Accept
 +
  Content-Type: application/json
 +
 +
  {
 +
    "examples": [{
 +
      "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
 +
      "....": "...."
 +
    }, {
 +
      "id": "fdd7b0dc-52a3-491e-829f-41d18e1d3ada",
 +
      "....": "...."
 +
    }],
 +
    "links": {
 +
      "self": "https://dns.provider.com/v2/examples?marker=e728bfe0-0673-11e3-8ffd-0800200c9a66&limit=2",
 +
      "next": "https://dns.provider.com/v2/examples?marker=fdd7b0dc-52a3-491e-829f-41d18e1d3ada&limit=2",
 +
      "previous": "https://dns.provider.com/v2/examples?marker=d9890c50-0673-11e3-8ffd-0800200c9a66&limit=2"
 +
    }
 +
  }
 +
 +
==== Filtering ====
 +
 +
Filtering is available on all collections and is controlled using query parameters which match the name of the attribute being filtered. It is *not* required that all attributes are available as filter targets, but the majority will be. Filters are an exact match - use of wildcard or substring matching is not supported.
 +
 +
Wildcard and substring matching may be introduced in a later revision of the v2 API, so long as the implementation is backward compatible.
 +
 +
''' Request: '''
 +
 +
  GET /v2/examples?title=MyExample HTTP/1.1
 +
  Host: dns.provider.com
 +
  Accept: application/json
 +
  X-Auth-Token: HPAuth_*****
 +
 +
''' Response: '''
 +
 +
  HTTP/1.1 200 OK
 +
  Vary: Accept
 +
  Content-Type: application/json
 +
 
 +
  {
 +
    "examples": [{
 +
      "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
 +
      "title": "MyExample",
 +
      "....": "...."
 +
    }, {
 +
      "id": "fdd7b0dc-52a3-491e-829f-41d18e1d3ada",
 +
      "title": "MyExample",
 +
      "....": "...."
 +
    }],
 +
    "links": {
 +
      "...": "..."
 +
    }
 +
  }
 +
 +
==== Nested Collections ====
 +
 +
A nested collection is a collection without a URI of it's own. The only current example we have of this is the "records" array under the RecordSet resource.
 +
 +
By default, Nested Collections shall not be included in the listing of it's parent resource. For example, List RecordSets shall not include the "records" collection for each of the RecordSets returned.
 +
 +
== Resources ==
 +
 +
The following conventions apply to all resources, unless otherwise noted below.
 +
 +
 +
==== Links ====
 +
 +
A links object will exist inside of resource object. At the minimun, it will contain a "self" link.
 +
 +
''' Response: '''
 +
 +
  HTTP/1.1 200 OK
 +
  Vary: Accept
 +
  Content-Type: application/json
 +
 +
  {
 +
    "example": {
 +
      "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
 +
      "....": "....",
 +
      "links": {
 +
        "self": "https://dns.provider.com/v2/examples/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
 +
      }
 +
    }
 +
  }
  
 
= Usage =
 
= Usage =
Line 195: Line 408:
  
 
   POST /v2/zones HTTP/1.1
 
   POST /v2/zones HTTP/1.1
   Host: region-a.geo-1.dns.hpcloudsvc.com
+
   Host: dns.provider.com
 
   Accept: application/json
 
   Accept: application/json
 
   Content-Type: application/json
 
   Content-Type: application/json
Line 201: Line 414:
  
 
   {
 
   {
     "name": "example.org.",
+
     "zone": {
    "email": "joe@example.org.",
+
      "name": "example.org.",
    "ttl": 7200
+
      "email": "joe@example.org",
 +
      "ttl": 7200
 +
    }
 
   }
 
   }
  
 
''' Response: '''
 
''' Response: '''
  
    HTTP/1.1 201 Created
+
  HTTP/1.1 201 Created
 
   Vary: Accept
 
   Vary: Accept
 
   Content-Type: application/json
 
   Content-Type: application/json
   Location: https://region-a.geo-1.dns.hpcloudsvc.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3
+
   Location: https://dns.provider.com/v2/zones/{zone-id}
  
 
   {
 
   {
     "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
+
     "zone": {
    "pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
+
      "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
    "name": "example.org.",
+
      "pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
    "email": "joe@example.org.",
+
      "project_id": "4335d1f0-f793-11e2-b778-0800200c9a66",
    "ttl": 7200,
+
      "name": "example.org.",
    "serial": 1351800588,
+
      "email": "joe@example.org",
    "version": 1,
+
      "ttl": 7200,
    "created_at": "...",
+
      "serial": 1351800588,
    "updated_at": null
+
      "status": "ACTIVE",
 +
      "version": 1,
 +
      "created_at": "...",
 +
      "updated_at": null,
 +
      "links": {
 +
        "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3"
 +
      }
 +
    }
 
   }
 
   }
  
Line 229: Line 451:
 
''' Request: '''
 
''' Request: '''
  
   GET /v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3 HTTP/1.1
+
   GET /v2/zones/{zone-id} HTTP/1.1
   Host: region-a.geo-1.dns.hpcloudsvc.com
+
   Host: dns.provider.com
 
   Accept: application/json
 
   Accept: application/json
 
   X-Auth-Token: HPAuth_*****
 
   X-Auth-Token: HPAuth_*****
Line 241: Line 463:
  
 
   {
 
   {
     "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
+
     "zone": {
    "pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
+
      "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
    "name": "example.org.",
+
      "pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
    "email": "joe@example.org.",
+
      "project_id": "4335d1f0-f793-11e2-b778-0800200c9a66",
    "ttl": 7200,
+
      "name": "example.org.",
    "serial": 1351800588,
+
      "email": "joe@example.org.",
    "version": 1,
+
      "ttl": 7200,
    "created_at": "...",
+
      "serial": 1351800588,
    "updated_at": null
+
      "status": "ACTIVE",
 +
      "version": 1,
 +
      "created_at": "...",
 +
      "updated_at": null,
 +
      "links": {
 +
        "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3"
 +
      }
 +
    }
 
   }
 
   }
  
Line 257: Line 486:
  
 
   GET /v2/zones HTTP/1.1
 
   GET /v2/zones HTTP/1.1
   Host: region-a.geo-1.dns.hpcloudsvc.com
+
   Host: dns.provider.com
 
   Accept: application/json
 
   Accept: application/json
 
   X-Auth-Token: HPAuth_*****
 
   X-Auth-Token: HPAuth_*****
Line 271: Line 500:
 
       "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
 
       "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
 
       "pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
 
       "pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
 +
      "project_id": "4335d1f0-f793-11e2-b778-0800200c9a66",
 
       "name": "example.org.",
 
       "name": "example.org.",
 
       "email": "joe@example.org.",
 
       "email": "joe@example.org.",
 
       "ttl": 7200,
 
       "ttl": 7200,
 
       "serial": 1351800588,
 
       "serial": 1351800588,
 +
      "status": "ACTIVE",
 
       "version": 1,
 
       "version": 1,
 
       "created_at": "...",
 
       "created_at": "...",
       "updated_at": null
+
       "updated_at": null,
 +
      "links": {
 +
        "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3"
 +
      }
 
     }, {
 
     }, {
 
       "id": "fdd7b0dc-52a3-491e-829f-41d18e1d3ada",
 
       "id": "fdd7b0dc-52a3-491e-829f-41d18e1d3ada",
 
       "pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
 
       "pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
 +
      "project_id": "4335d1f0-f793-11e2-b778-0800200c9a66",
 
       "name": "example.net.",
 
       "name": "example.net.",
 
       "email": "joe@example.net.",
 
       "email": "joe@example.net.",
 
       "ttl": 7200,
 
       "ttl": 7200,
 
       "serial": 1351800588,
 
       "serial": 1351800588,
 +
      "status": "ACTIVE",
 
       "version": 1,
 
       "version": 1,
 
       "created_at": "...",
 
       "created_at": "...",
       "updated_at": null
+
       "updated_at": null,
     }]
+
      "links": {
 +
        "self": "https://dns.provider.com/v2/zones/fdd7b0dc-52a3-491e-829f-41d18e1d3ada"
 +
      }
 +
     }],
 +
    "links": {
 +
      "self": "https://dns.provider.com/v2/zones",
 +
      "next": "https://dns.provider.com/v2/zones?marker=fdd7b0dc-52a3-491e-829f-41d18e1d3ada"
 +
    }
 
   }
 
   }
  
Line 295: Line 538:
 
In both examples below, we update the TTL to 3600.
 
In both examples below, we update the TTL to 3600.
  
''' Request Option 1 - PUT Request: '''
+
''' Request Option 1 - Normal Request: '''
  
   PUT https://region-a.geo-1.dns.hpcloudsvc.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3 HTTP/1.1
+
   PATCH https://dns.provider.com/v2/zones/{zone-id} HTTP/1.1
   Host: region-a.geo-1.dns.hpcloudsvc.com
+
   Host: dns.provider.com
 
   Accept: application/json
 
   Accept: application/json
 
   Content-Type: application/json
 
   Content-Type: application/json
Line 304: Line 547:
  
 
   {
 
   {
     "ttl": 3600
+
     "zone": {
 +
      "ttl": 3600
 +
    }
 
   }
 
   }
  
  
''' Request Option 2 - PATCH Request: '''
+
''' Request Option 2 - JSON-Patch Request: '''
  
   PATCH https://region-a.geo-1.dns.hpcloudsvc.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3 HTTP/1.1
+
   PATCH https://dns.provider.com/v2/zones/{zone-id} HTTP/1.1
   Host: region-a.geo-1.dns.hpcloudsvc.com
+
   Host: dns.provider.com
 
   Accept: application/json
 
   Accept: application/json
 
   Content-Type: application/json-patch+json
 
   Content-Type: application/json-patch+json
Line 317: Line 562:
  
 
   [
 
   [
     {"op": "test", "path": "/version", "value": 1},
+
     {"op": "test", "path": "/zone/version", "value": 1},
     {"op": "replace", "path": "/ttl", "value": 3600}
+
     {"op": "replace", "path": "/zone/ttl", "value": 3600}
 
   ]
 
   ]
  
 
''' Response: '''
 
''' Response: '''
  
   HTTP/1.1 202 Accepted
+
   HTTP/1.1 200 OK
 
   Vary: Accept
 
   Vary: Accept
 
   Content-Type: application/json
 
   Content-Type: application/json
  
 
   {
 
   {
     "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
+
     "zone": {
    "pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
+
      "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
    "name": "example.org.",
+
      "pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
    "email": "joe@example.org.",
+
      "project_id": "4335d1f0-f793-11e2-b778-0800200c9a66",
    "ttl": 3600,
+
      "name": "example.org.",
    "serial": 1351800588,
+
      "email": "joe@example.org.",
    "version": 2,
+
      "ttl": 3600,
    "created_at": "...",
+
      "serial": 1351800588,
    "updated_at": "..."
+
      "status": "ACTIVE",
 +
      "version": 2,
 +
      "created_at": "...",
 +
      "updated_at": "...",
 +
      "links": {
 +
        "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3"
 +
      }
 +
    }
 
   }
 
   }
  
Line 343: Line 595:
 
''' Request: '''
 
''' Request: '''
  
   DELETE https://region-a.geo-1.dns.hpcloudsvc.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3 HTTP/1.1
+
   DELETE https://dns.provider.com/v2/zones/{zone-id} HTTP/1.1
   Host: region-a.geo-1.dns.hpcloudsvc.com
+
   Host: dns.provider.com
 
   X-Auth-Token: HPAuth_*****
 
   X-Auth-Token: HPAuth_*****
  
 
''' Response: '''
 
''' Response: '''
  
   HTTP/1.1 202 Accepted
+
   HTTP/1.1 204 No Content
  
 
== RecordSet Operations ==
 
== RecordSet Operations ==
Line 359: Line 611:
 
''' Request: '''
 
''' Request: '''
  
   POST https://region-a.geo-1.dns.hpcloudsvc.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets HTTP/1.1
+
   POST https://dns.provider.com/v2/zones/{zone-id}/recordsets HTTP/1.1
   Host: region-a.geo-1.dns.hpcloudsvc.com
+
   Host: dns.provider.com
 
   Accept: application/json
 
   Accept: application/json
 
   Content-Type: application/json
 
   Content-Type: application/json
Line 366: Line 618:
  
 
   {
 
   {
     "name": "www.example.org.",
+
     "recordset": {
    "type": "A",
+
      "name": "www.example.org.",
    "ttl": 3600,
+
      "type": "A",
    "records": [{
+
      "ttl": 3600,
      "address": "10.1.2.3"
+
      "records": [{
    },{
+
        "address": "10.1.2.3"
      "address": "10.3.2.1"
+
      },{
     }]
+
        "address": "10.3.2.1"
 +
      }]
 +
     }
 
   }
 
   }
  
Line 381: Line 635:
 
   Vary: Accept
 
   Vary: Accept
 
   Content-Type: application/json
 
   Content-Type: application/json
   Location: https://region-a.geo-1.dns.hpcloudsvc.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/9e27811d-0320-4179-abb7-0e00e371e25b
+
   Location: https://dns.provider.com/v2/zones/{zone-id}/recordsets/{recordset-id}
  
 
   {
 
   {
     "id": "9e27811d-0320-4179-abb7-0e00e371e25b",
+
     "recordset": {
    "zone_id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
+
      "id": "9e27811d-0320-4179-abb7-0e00e371e25b",
    "name": "www.example.org.",
+
      "zone_id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
    "type": "A",
+
      "name": "www.example.org.",
    "ttl": 3600,
+
      "type": "A",
    "records": [{
+
      "ttl": 3600,
      "address": "10.1.2.3"
+
      "records": [{
    },{
+
        "address": "10.1.2.3"
      "address": "10.3.2.1"
+
      },{
    }],
+
        "address": "10.3.2.1"
    "version": 1,
+
      }],
    "created_at": "...",
+
      "status": "ACTIVE",
    "updated_at": null
+
      "version": 1,
 +
      "created_at": "...",
 +
      "updated_at": null,
 +
      "links": {
 +
        "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/9e27811d-0320-4179-abb7-0e00e371e25b"
 +
      }
 +
    }
 
   }
 
   }
  
Line 403: Line 663:
 
''' Request: '''
 
''' Request: '''
  
   POST https://region-a.geo-1.dns.hpcloudsvc.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets HTTP/1.1
+
   POST https://dns.provider.com/v2/zones/{zone-id}/recordsets HTTP/1.1
   Host: region-a.geo-1.dns.hpcloudsvc.com
+
   Host: dns.provider.com
 
   Accept: application/json
 
   Accept: application/json
 
   Content-Type: application/json
 
   Content-Type: application/json
Line 410: Line 670:
  
 
   {
 
   {
     "name": "_xmpp-server._tcp.example.org.",
+
     "recordset": {
    "type": "SRV",
+
      "name": "_xmpp-server._tcp.example.org.",
    "ttl": 3600,
+
      "type": "SRV",
    "records": [{
+
      "ttl": 3600,
      "weight": 0,
+
      "records": [{
      "priority": 10,
+
        "weight": 0,
      "target": "xmpp1.example.org."
+
        "priority": 10,
    }, {
+
        "target": "xmpp1.example.org."
      "weight": 0,
+
      }, {
      "priority": 20,
+
        "weight": 0,
      "target": "xmpp2.example.org."
+
        "priority": 20,
     }]
+
        "target": "xmpp2.example.org."
 +
      }]
 +
     }
 
   }
 
   }
  
Line 429: Line 691:
 
   Vary: Accept
 
   Vary: Accept
 
   Content-Type: application/json
 
   Content-Type: application/json
   Location: https://region-a.geo-1.dns.hpcloudsvc.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/9e27811d-0320-4179-abb7-0e00e371e25b
+
   Location: https://dns.provider.com/v2/zones/{zone-id}/recordsets/{recordset-id}
  
 
   {
 
   {
     "id": "9e27811d-0320-4179-abb7-0e00e371e25b",
+
     "recordset": {
    "zone_id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
+
      "id": "9e27811d-0320-4179-abb7-0e00e371e25b",
    "name": "_xmpp-server._tcp.example.org.",
+
      "zone_id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
    "type": "SRV",
+
      "name": "_xmpp-server._tcp.example.org.",
    "ttl": 3600,
+
      "type": "SRV",
    "records": [{
+
      "ttl": 3600,
      "weight": 0,
+
      "records": [{
      "priority": 10,
+
        "weight": 0,
      "target": "xmpp1.example.org."
+
        "priority": 10,
    }, {
+
        "target": "xmpp1.example.org."
      "weight": 0,
+
      }, {
      "priority": 20,
+
        "weight": 0,
      "target": "xmpp2.example.org."
+
        "priority": 20,
    }],
+
        "target": "xmpp2.example.org."
    "version": 1,
+
      }],
    "created_at": "...",
+
      "status": "ACTIVE",
    "updated_at": null
+
      "version": 1,
 +
      "created_at": "...",
 +
      "updated_at": null,
 +
      "links": {
 +
        "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/9e27811d-0320-4179-abb7-0e00e371e25b"
 +
      }
 +
    }
 
   }
 
   }
  
Line 455: Line 723:
 
''' Request: '''
 
''' Request: '''
  
   GET https://region-a.geo-1.dns.hpcloudsvc.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/9e27811d-0320-4179-abb7-0e00e371e25b HTTP/1.1
+
   GET https://dns.provider.com/v2/zones/{zone-id}/recordsets/{recordset-id} HTTP/1.1
   Host: region-a.geo-1.dns.hpcloudsvc.com
+
   Host: dns.provider.com
 
   Accept: application/json
 
   Accept: application/json
 
   X-Auth-Token: HPAuth_*****
 
   X-Auth-Token: HPAuth_*****
Line 467: Line 735:
  
 
   {
 
   {
     "id": "9e27811d-0320-4179-abb7-0e00e371e25b",
+
     "recordset": {
    "zone_id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
+
      "id": "9e27811d-0320-4179-abb7-0e00e371e25b",
    "name": "www.example.org.",
+
      "zone_id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
    "type": "A",
+
      "name": "www.example.org.",
    "ttl": 3600,
+
      "type": "A",
    "records": [{
+
      "ttl": 3600,
      "address": "10.1.2.3"
+
      "records": [{
    },{
+
        "address": "10.1.2.3"
      "address": "10.3.2.1"
+
      },{
    }],
+
        "address": "10.3.2.1"
    "version": 1,
+
      }],
    "created_at": "...",
+
      "status": "ACTIVE",
    "updated_at": null
+
      "version": 1,
 +
      "created_at": "...",
 +
      "updated_at": null,
 +
      "links": {
 +
        "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/9e27811d-0320-4179-abb7-0e00e371e25b"
 +
      }
 +
    }
 
   }
 
   }
  
Line 486: Line 760:
 
''' Request: '''
 
''' Request: '''
  
   GET /v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets HTTP/1.1
+
   GET /v2/zones/{zone-id}/recordsets HTTP/1.1
   Host: region-a.geo-1.dns.hpcloudsvc.com
+
   Host: dns.provider.com
 
   Accept: application/json
 
   Accept: application/json
 
   X-Auth-Token: HPAuth_*****
 
   X-Auth-Token: HPAuth_*****
Line 504: Line 778:
 
       "type": "A",
 
       "type": "A",
 
       "ttl": 3600,
 
       "ttl": 3600,
       "records": [{
+
       "status": "ACTIVE",
        "address": "10.1.2.3"
 
      },{
 
        "address": "10.3.2.1"
 
      }],
 
 
       "version": 1,
 
       "version": 1,
 
       "created_at": "...",
 
       "created_at": "...",
       "updated_at": null
+
       "updated_at": null,
 +
      "links": {
 +
        "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/9e27811d-0320-4179-abb7-0e00e371e25b"
 +
      }
 
     }, {
 
     }, {
       "id": "9e27811d-0320-4179-abb7-0e00e371e25b",
+
       "id": "dedf6879-fd9a-41d6-a7c2-eeac316fa7b3",
 
       "zone_id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
 
       "zone_id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
 
       "name": "_xmpp-server._tcp.example.org.",
 
       "name": "_xmpp-server._tcp.example.org.",
 
       "type": "SRV",
 
       "type": "SRV",
 
       "ttl": 3600,
 
       "ttl": 3600,
       "records": [{
+
       "status": "ACTIVE",
        "weight": 0,
 
        "priority": 10,
 
        "target": "xmpp1.example.org."
 
      }, {
 
        "weight": 0,
 
        "priority": 20,
 
        "target": "xmpp2.example.org."
 
      }],
 
 
       "version": 1,
 
       "version": 1,
 
       "created_at": "...",
 
       "created_at": "...",
       "updated_at": null
+
       "updated_at": null,
     }]
+
      "links": {
 +
        "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/dedf6879-fd9a-41d6-a7c2-eeac316fa7b3"
 +
      }
 +
     }],
 +
    "links": {
 +
      "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets",
 +
      "next": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets?marker=dedf6879-fd9a-41d6-a7c2-eeac316fa7b3"
 +
    }
 
   }
 
   }
  
Line 537: Line 809:
 
In both examples below, we add "127.0.0.1" to the RRSet records list.
 
In both examples below, we add "127.0.0.1" to the RRSet records list.
  
''' Request Option 1 - PUT Request: '''
+
''' Request Option 1 - Normal Request: '''
  
   PUT https://region-a.geo-1.dns.hpcloudsvc.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/9e27811d-0320-4179-abb7-0e00e371e25b HTTP/1.1
+
   PATCH https://dns.provider.com/v2/zones/{zone-id}/recordsets/{recordset-id} HTTP/1.1
   Host: region-a.geo-1.dns.hpcloudsvc.com
+
   Host: dns.provider.com
 
   Accept: application/json
 
   Accept: application/json
 
   Content-Type: application/json
 
   Content-Type: application/json
Line 546: Line 818:
  
 
   {
 
   {
     "records": [{
+
     "recordset": {
      "address": "10.1.2.3"
+
      "records": [{
    }, {
+
        "address": "10.1.2.3"
      "address": "10.3.2.1"
+
      }, {
    }, {
+
        "address": "10.3.2.1"
      "address": "127.0.0.1"
+
      }, {
     }]
+
        "address": "127.0.0.1"
 +
      }]
 +
     }
 
   }
 
   }
  
  
''' Request Option 2 - PATCH Request: '''
+
''' Request Option 2 - JSON-Patch Request: '''
  
   PATCH https://region-a.geo-1.dns.hpcloudsvc.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/9e27811d-0320-4179-abb7-0e00e371e25b HTTP/1.1
+
   PATCH https://dns.provider.com/v2/zones/{zone-id}/recordsets/{recordset-id} HTTP/1.1
   Host: region-a.geo-1.dns.hpcloudsvc.com
+
   Host: dns.provider.com
 
   Accept: application/json
 
   Accept: application/json
 
   Content-Type: application/json-patch+json
 
   Content-Type: application/json-patch+json
Line 565: Line 839:
  
 
   [
 
   [
     {"op": "test", "path": "/version", "value": 1},
+
     {"op": "test", "path": "/recordset/version", "value": 1},
     {"op": "add", "path": "/records/-", "value": {"address": "127.0.0.1"}}
+
     {"op": "add", "path": "/recordset/records/-", "value": {"address": "127.0.0.1"}}
 
   ]
 
   ]
  
Line 572: Line 846:
 
''' Response: '''
 
''' Response: '''
  
   HTTP/1.1 202 Accepted
+
   HTTP/1.1 200 OK
 
   Vary: Accept
 
   Vary: Accept
 
   Content-Type: application/json
 
   Content-Type: application/json
  
 
   {
 
   {
     "id": "9e27811d-0320-4179-abb7-0e00e371e25b",
+
     "recordset": {
    "zone_id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
+
      "id": "9e27811d-0320-4179-abb7-0e00e371e25b",
    "name": "www.example.org.",
+
      "zone_id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
    "type": "A",
+
      "name": "www.example.org.",
    "ttl": 3600,
+
      "type": "A",
    "records": [{
+
      "ttl": 3600,
      "address": "10.1.2.3"
+
      "records": [{
    }, {
+
        "address": "10.1.2.3"
      "address": "10.3.2.1"
+
      }, {
    }, {
+
        "address": "10.3.2.1"
      "address": "127.0.0.1"
+
      }, {
    }],
+
        "address": "127.0.0.1"
    "version": 2,
+
      }],
    "created_at": "...",
+
      "status": "ACTIVE",
    "updated_at": "..."
+
      "version": 2,
 +
      "created_at": "...",
 +
      "updated_at": "...",
 +
      "links": {
 +
        "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/9e27811d-0320-4179-abb7-0e00e371e25b"
 +
      }
 +
    }
 
   }
 
   }
  
Line 598: Line 878:
 
''' Request: '''
 
''' Request: '''
  
   DELETE https://region-a.geo-1.dns.hpcloudsvc.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/9e27811d-0320-4179-abb7-0e00e371e25b HTTP/1.1
+
   DELETE https://dns.provider.com/v2/zones/{zone-id}/recordsets/{recordset-id} HTTP/1.1
   Host: region-a.geo-1.dns.hpcloudsvc.com
+
   Host: dns.provider.com
 
   X-Auth-Token: HPAuth_*****
 
   X-Auth-Token: HPAuth_*****
  
 
''' Response: '''
 
''' Response: '''
  
   HTTP/1.1 202 Accepted
+
   HTTP/1.1 204 No Content

Latest revision as of 20:20, 9 June 2017

This page should be considered obsolete. Modern API documentation can be found here.
This is a DRAFT of the Designate Version 2 API. The draft shall not be considered final until a implementation is complete.

Introduction

This specification document is intended to describe the concepts and conventions the Designate v2 API will conform to. Several common, or new, resources have been explicitly detailed, others have not. Any resources not explicitly detailed shall follow the conventions set in this document.

The Designate v2 API will eventually replace the v1 API, but there will be a period of time where both APIs exist alongside each other. The v1 API will not be affected by this spec. The length of time the v1 API is kept for is not addressed by this specification.

When in doubt - We follow the conventions set forth in the Keystone V3 API.

Basic APIv2 Requirements

  1. Switch from string based rdata to dict based rdata. This allows for a sane API for the more complex record types (SRV, GeoIP, WRR etc).
    1. This complicates simple record types, but simplifies complex record types (SRV, GeoIP, Weighted RR, Failover etc)
  2. Introduce the concept of RecordSets. This helps our API more accurately reflect the DNS specs, and provides saner grouping of related rdatas.
    1. See RFC2181 Section 5
  3. Document the concept of "server pools". This allows the API to remain the same if/when we introduce private DNS instances.
  4. Provided a mechanism to prevent concurrent modifications.
    1. This is intended to allow end users to prevent their API calls from updating a resource, if the resource has already been updated by another API client.
  5. Pagination
  6. Filtering of result sets

TODO

  • All Tenants Access
  • How do we include "total items" in paginated response?
  • How do we optionally include a nested collection?
  • Document Error Response Format

Resources

Pool

A "pool" is a set of DNS servers to which a Zone may be scheduled. Each pool has a distinct Zone namespace, allowing "example.com" to exist in multiple pools.

Pools may be defined by the provider, and marked "public". Public pools will have zones from multiple customers while private pools will be restricted to a single project_id.

Additionally, private pools may be created by a customer. Available pool flavors are defined by the provider, and may include attributes such as "Number of Nameservers", "AnyCast" etc.

The intention of this API is twofold:

  1. In order for the provider to offer multiple tiers of service. For example, a "standard" service operated out of two datacenters, and a "premium" service operated via many datacenters using AnyCast.
  2. In order to allow customers to create "private" nameservers, intended for use only be their instances. This allows customers to create "dev.local" style domains, without conflicting with other users or exposing these names to the global internet.
Property Type Default Required Immutable Read Only
id uuid Generated
project_id uuid None
name string None
flavor_id string None
public boolean False
nameservers list<string> Empty List
notes string None
status string None
version int Generated
created_at timestamp Generated
updated_at timestamp Generated

The "status" property may have value of "ACTIVE", "PENDING", "DELETING", "ERROR", "ERROR_DELETING" or "SUSPENDED".

Zone

Property Type Default Required Immutable Read Only
id uuid Generated
pool_id uuid Configured
project_id uuid None
name string None
email string None
ttl int 3600
serial int Generated
notes string None
status string None
version int Generated
created_at timestamp Generated
updated_at timestamp Generated

The "status" property may have value of "ACTIVE", "PENDING", "DELETING", "ERROR", "ERROR_DELETING" or "SUSPENDED".

Record Set

Property Type Default Required Immutable Read Only
id uuid Generated
zone_id uuid Configured
name domainname None
type string None
ttl int nil
records list<rdata> Empty List
notes string None
status string None
version int Generated
created_at timestamp Generated
updated_at timestamp Generated

The "status" property may have value of "ACTIVE", "PENDING", "DELETING", "ERROR" or "ERROR_DELETING".

RData

Note: This list of RData is NOT the entire list. Additional RData types, including psuedo RData's for things likle GeoIP/WRR/Failover, may be added without violating the spec.

A

Property Type Default Required Immutable Read Only
address ipv4 None

AAAA

Property Type Default Required Immutable Read Only
address ipv6 None

CNAME

Property Type Default Required Immutable Read Only
cname hostname None

MX

Property Type Default Required Immutable Read Only
preference int None
exchange hostname None

NS

Property Type Default Required Immutable Read Only
nsdname hostname None

PTR

Property Type Default Required Immutable Read Only
ptrdname hostname None

SOA

Additional Restrictions: Only 1 SOA record may be present in a zone, and it must be at the root of the zone
Property Type Default Required Immutable Read Only
mname domainname Generated
rname domainname Generated
serial int Generated
refresh int Generated
retry int Generated
expire int Generated
minimun int Generated

SPF

Property Type Default Required Immutable Read Only
text string None

SRV

Property Type Default Required Immutable Read Only
priority int None
weight int None
port int None
target hostname None

SSHFP

Property Type Default Required Immutable Read Only
algorithm int None
type int 1
fingerprint string None

TXT

Property Type Default Required Immutable Read Only
text string None

Conventions

General

Synchronous vs Asynchronous

All Create, Update, and Delete operations can be either asynchronous or synchronous. Asynchronous operations are restricted to resources containing a "status" attribute. API Consumers MUST NOT make the assumption that any API call is always asynchronous or synchronous. This document defines the method which API consumers may use to determine if a completed API call was asynchronous or synchronous.

Synchronous

Synchronous Create/Update/Delete API calls will return a HTTP status of either "201 Created", "200 OK" or "204 No Content" respectivly. Additionally, resources which contain a "status" property MUST have the value "ACTIVE".

Asynchronous

Asynchronous Create/Update/Delete API calls will return a HTTP status of "202 Accepted". The "status" property MUST NOT have the value "ACTIVE".

Clients can determine if an asynchronous job is complete by querying the resource URL (or, for creates, the URL returned in the "Location" header) and checking the value of the "status" property. Once the job is complete, the status field will be "ACTIVE".

Collections

The following conventions apply to all collections, unless otherwise noted below.

Links

A links object will exist at the root of all Collection responses. At the minimun, it will contain a "self" link. If the collection resultset is not complete, a "next" and/or "previous" link will be included for pagination.

Response:

 HTTP/1.1 200 OK
 Vary: Accept
 Content-Type: application/json
 {
   "examples": [{
     "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
     "....": "...."
   }, {
     "id": "fdd7b0dc-52a3-491e-829f-41d18e1d3ada",
     "....": "...."
   }],
   "links": {
     "self": "<URL for This Page>",
     "next": "<URL for Next Page>",
     "previous": "<URL for Previous Page>"
   }
 }

Pagination

Pagination is available on all collections and is controlled using a combination of two query paramaters - `marker=<UUID>&limit=<INTEGER>`. Collection responses will include a `links` object containing absolute URLs for the `next` and `previous` pages. These links may be omitted, or null, at the edges of a paginated collection.

To navigate the collection, the parameters limit and marker can be set in the URI (e.g.?limit=100&marker=<UUID>). The marker parameter is the ID of the last item in the previous list. Items are sorted by create time in descending order. When a create time is not available they are sorted by ID. The limit parameter sets the page size. Both parameters are optional.

Request:

 GET /v2/examples?marker=c74af170-0673-11e3-8ffd-0800200c9a66&limit=2 HTTP/1.1
 Host: dns.provider.com
 Accept: application/json
 X-Auth-Token: HPAuth_*****

Response:

 HTTP/1.1 200 OK
 Vary: Accept
 Content-Type: application/json
 {
   "examples": [{
     "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
     "....": "...."
   }, {
     "id": "fdd7b0dc-52a3-491e-829f-41d18e1d3ada",
     "....": "...."
   }],
   "links": {
     "self": "https://dns.provider.com/v2/examples?marker=e728bfe0-0673-11e3-8ffd-0800200c9a66&limit=2",
     "next": "https://dns.provider.com/v2/examples?marker=fdd7b0dc-52a3-491e-829f-41d18e1d3ada&limit=2",
     "previous": "https://dns.provider.com/v2/examples?marker=d9890c50-0673-11e3-8ffd-0800200c9a66&limit=2" 
   }
 }

Filtering

Filtering is available on all collections and is controlled using query parameters which match the name of the attribute being filtered. It is *not* required that all attributes are available as filter targets, but the majority will be. Filters are an exact match - use of wildcard or substring matching is not supported.

Wildcard and substring matching may be introduced in a later revision of the v2 API, so long as the implementation is backward compatible.

Request:

 GET /v2/examples?title=MyExample HTTP/1.1
 Host: dns.provider.com
 Accept: application/json
 X-Auth-Token: HPAuth_*****

Response:

 HTTP/1.1 200 OK
 Vary: Accept
 Content-Type: application/json
 
 {
   "examples": [{
     "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
     "title": "MyExample",
     "....": "...."
   }, {
     "id": "fdd7b0dc-52a3-491e-829f-41d18e1d3ada",
     "title": "MyExample",
     "....": "...."
   }],
   "links": {
     "...": "..."
   }
 }

Nested Collections

A nested collection is a collection without a URI of it's own. The only current example we have of this is the "records" array under the RecordSet resource.

By default, Nested Collections shall not be included in the listing of it's parent resource. For example, List RecordSets shall not include the "records" collection for each of the RecordSets returned.

Resources

The following conventions apply to all resources, unless otherwise noted below.


Links

A links object will exist inside of resource object. At the minimun, it will contain a "self" link.

Response:

 HTTP/1.1 200 OK
 Vary: Accept
 Content-Type: application/json
 {
   "example": {
     "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
     "....": "....",
     "links": {
       "self": "https://dns.provider.com/v2/examples/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
     }
   }
 }

Usage

Zone Operations

Create Zone

Request:

 POST /v2/zones HTTP/1.1
 Host: dns.provider.com
 Accept: application/json
 Content-Type: application/json
 X-Auth-Token: HPAuth_*****
 {
   "zone": {
     "name": "example.org.",
     "email": "joe@example.org",
     "ttl": 7200
   }
 }

Response:

 HTTP/1.1 201 Created
 Vary: Accept
 Content-Type: application/json
 Location: https://dns.provider.com/v2/zones/{zone-id}
 {
   "zone": {
     "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
     "pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
     "project_id": "4335d1f0-f793-11e2-b778-0800200c9a66",
     "name": "example.org.",
     "email": "joe@example.org",
     "ttl": 7200,
     "serial": 1351800588,
     "status": "ACTIVE",
     "version": 1,
     "created_at": "...",
     "updated_at": null,
     "links": {
       "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3"
     }
   }
 }

Get Zone

Request:

 GET /v2/zones/{zone-id} HTTP/1.1
 Host: dns.provider.com
 Accept: application/json
 X-Auth-Token: HPAuth_*****

Response:

 HTTP/1.1 200 OK
 Vary: Accept
 Content-Type: application/json
 {
   "zone": {
     "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
     "pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
     "project_id": "4335d1f0-f793-11e2-b778-0800200c9a66",
     "name": "example.org.",
     "email": "joe@example.org.",
     "ttl": 7200,
     "serial": 1351800588,
     "status": "ACTIVE",
     "version": 1,
     "created_at": "...",
     "updated_at": null,
     "links": {
       "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3"
     }
   }
 }

List Zones

Request:

 GET /v2/zones HTTP/1.1
 Host: dns.provider.com
 Accept: application/json
 X-Auth-Token: HPAuth_*****

Response:

 HTTP/1.1 200 OK
 Vary: Accept
 Content-Type: application/json
 {
   "zones": [{
     "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
     "pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
     "project_id": "4335d1f0-f793-11e2-b778-0800200c9a66",
     "name": "example.org.",
     "email": "joe@example.org.",
     "ttl": 7200,
     "serial": 1351800588,
     "status": "ACTIVE",
     "version": 1,
     "created_at": "...",
     "updated_at": null,
     "links": {
       "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3"
     }
   }, {
     "id": "fdd7b0dc-52a3-491e-829f-41d18e1d3ada",
     "pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
     "project_id": "4335d1f0-f793-11e2-b778-0800200c9a66",
     "name": "example.net.",
     "email": "joe@example.net.",
     "ttl": 7200,
     "serial": 1351800588,
     "status": "ACTIVE",
     "version": 1,
     "created_at": "...",
     "updated_at": null,
     "links": {
       "self": "https://dns.provider.com/v2/zones/fdd7b0dc-52a3-491e-829f-41d18e1d3ada"
     }
   }],
   "links": {
     "self": "https://dns.provider.com/v2/zones",
     "next": "https://dns.provider.com/v2/zones?marker=fdd7b0dc-52a3-491e-829f-41d18e1d3ada"
   }
 }

Update Zone

In both examples below, we update the TTL to 3600.

Request Option 1 - Normal Request:

 PATCH https://dns.provider.com/v2/zones/{zone-id} HTTP/1.1
 Host: dns.provider.com
 Accept: application/json
 Content-Type: application/json
 X-Auth-Token: HPAuth_*****
 {
   "zone": {
     "ttl": 3600
   }
 }


Request Option 2 - JSON-Patch Request:

 PATCH https://dns.provider.com/v2/zones/{zone-id} HTTP/1.1
 Host: dns.provider.com
 Accept: application/json
 Content-Type: application/json-patch+json
 X-Auth-Token: HPAuth_*****
 [
   {"op": "test", "path": "/zone/version", "value": 1},
   {"op": "replace", "path": "/zone/ttl", "value": 3600}
 ]

Response:

 HTTP/1.1 200 OK
 Vary: Accept
 Content-Type: application/json
 {
   "zone": {
     "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
     "pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
     "project_id": "4335d1f0-f793-11e2-b778-0800200c9a66",
     "name": "example.org.",
     "email": "joe@example.org.",
     "ttl": 3600,
     "serial": 1351800588,
     "status": "ACTIVE",
     "version": 2,
     "created_at": "...",
     "updated_at": "...",
     "links": {
       "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3"
     }
   }
 }

Delete Zone

Request:

 DELETE https://dns.provider.com/v2/zones/{zone-id} HTTP/1.1
 Host: dns.provider.com
 X-Auth-Token: HPAuth_*****

Response:

 HTTP/1.1 204 No Content

RecordSet Operations

Create RecordSet

Create RecordSet (A)

Request:

 POST https://dns.provider.com/v2/zones/{zone-id}/recordsets HTTP/1.1
 Host: dns.provider.com
 Accept: application/json
 Content-Type: application/json
 X-Auth-Token: HPAuth_*****
 {
   "recordset": {
     "name": "www.example.org.",
     "type": "A",
     "ttl": 3600,
     "records": [{
       "address": "10.1.2.3"
     },{
       "address": "10.3.2.1"
     }]
   }
 }

Response:

 HTTP/1.1 201 Created
 Vary: Accept
 Content-Type: application/json
 Location: https://dns.provider.com/v2/zones/{zone-id}/recordsets/{recordset-id}
 {
   "recordset": {
     "id": "9e27811d-0320-4179-abb7-0e00e371e25b",
     "zone_id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
     "name": "www.example.org.",
     "type": "A",
     "ttl": 3600,
     "records": [{
       "address": "10.1.2.3"
     },{
       "address": "10.3.2.1"
     }],
     "status": "ACTIVE",
     "version": 1,
     "created_at": "...",
     "updated_at": null,
     "links": {
       "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/9e27811d-0320-4179-abb7-0e00e371e25b"
     }
   }
 }

Create RecordSet (SRV)

Request:

 POST https://dns.provider.com/v2/zones/{zone-id}/recordsets HTTP/1.1
 Host: dns.provider.com
 Accept: application/json
 Content-Type: application/json
 X-Auth-Token: HPAuth_*****
 {
   "recordset": {
     "name": "_xmpp-server._tcp.example.org.",
     "type": "SRV",
     "ttl": 3600,
     "records": [{
       "weight": 0,
       "priority": 10,
       "target": "xmpp1.example.org."
     }, {
       "weight": 0,
       "priority": 20,
       "target": "xmpp2.example.org."
     }]
   }
 }

Response:

 HTTP/1.1 201 Created
 Vary: Accept
 Content-Type: application/json
 Location: https://dns.provider.com/v2/zones/{zone-id}/recordsets/{recordset-id}
 {
   "recordset": {
     "id": "9e27811d-0320-4179-abb7-0e00e371e25b",
     "zone_id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
     "name": "_xmpp-server._tcp.example.org.",
     "type": "SRV",
     "ttl": 3600,
     "records": [{
       "weight": 0,
       "priority": 10,
       "target": "xmpp1.example.org."
     }, {
       "weight": 0,
       "priority": 20,
       "target": "xmpp2.example.org."
     }],
     "status": "ACTIVE",
     "version": 1,
     "created_at": "...",
     "updated_at": null,
     "links": {
       "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/9e27811d-0320-4179-abb7-0e00e371e25b"
     }
   }
 }

Get RecordSet

Request:

 GET https://dns.provider.com/v2/zones/{zone-id}/recordsets/{recordset-id} HTTP/1.1
 Host: dns.provider.com
 Accept: application/json
 X-Auth-Token: HPAuth_*****

Response:

 HTTP/1.1 200 OK
 Vary: Accept
 Content-Type: application/json
 {
   "recordset": {
     "id": "9e27811d-0320-4179-abb7-0e00e371e25b",
     "zone_id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
     "name": "www.example.org.",
     "type": "A",
     "ttl": 3600,
     "records": [{
       "address": "10.1.2.3"
     },{
       "address": "10.3.2.1"
     }],
     "status": "ACTIVE",
     "version": 1,
     "created_at": "...",
     "updated_at": null,
     "links": {
       "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/9e27811d-0320-4179-abb7-0e00e371e25b"
     }
   }
 }

List RecordSets

Request:

 GET /v2/zones/{zone-id}/recordsets HTTP/1.1
 Host: dns.provider.com
 Accept: application/json
 X-Auth-Token: HPAuth_*****

Response:

 HTTP/1.1 200 OK
 Vary: Accept
 Content-Type: application/json
 {
   "recordsets": [{
     "id": "9e27811d-0320-4179-abb7-0e00e371e25b",
     "zone_id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
     "name": "www.example.org.",
     "type": "A",
     "ttl": 3600,
     "status": "ACTIVE",
     "version": 1,
     "created_at": "...",
     "updated_at": null,
     "links": {
       "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/9e27811d-0320-4179-abb7-0e00e371e25b"
     }
   }, {
     "id": "dedf6879-fd9a-41d6-a7c2-eeac316fa7b3",
     "zone_id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
     "name": "_xmpp-server._tcp.example.org.",
     "type": "SRV",
     "ttl": 3600,
     "status": "ACTIVE",
     "version": 1,
     "created_at": "...",
     "updated_at": null,
     "links": {
       "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/dedf6879-fd9a-41d6-a7c2-eeac316fa7b3"
     }
   }],
   "links": {
     "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets",
     "next": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets?marker=dedf6879-fd9a-41d6-a7c2-eeac316fa7b3"
   }
 }

Update RecordSet

In both examples below, we add "127.0.0.1" to the RRSet records list.

Request Option 1 - Normal Request:

 PATCH https://dns.provider.com/v2/zones/{zone-id}/recordsets/{recordset-id} HTTP/1.1
 Host: dns.provider.com
 Accept: application/json
 Content-Type: application/json
 X-Auth-Token: HPAuth_*****
 {
   "recordset": {
     "records": [{
       "address": "10.1.2.3"
     }, {
       "address": "10.3.2.1"
     }, {
       "address": "127.0.0.1"
     }]
   }
 }


Request Option 2 - JSON-Patch Request:

 PATCH https://dns.provider.com/v2/zones/{zone-id}/recordsets/{recordset-id} HTTP/1.1
 Host: dns.provider.com
 Accept: application/json
 Content-Type: application/json-patch+json
 X-Auth-Token: HPAuth_*****
 [
   {"op": "test", "path": "/recordset/version", "value": 1},
   {"op": "add", "path": "/recordset/records/-", "value": {"address": "127.0.0.1"}}
 ]


Response:

 HTTP/1.1 200 OK
 Vary: Accept
 Content-Type: application/json
 {
   "recordset": {
     "id": "9e27811d-0320-4179-abb7-0e00e371e25b",
     "zone_id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
     "name": "www.example.org.",
     "type": "A",
     "ttl": 3600,
     "records": [{
       "address": "10.1.2.3"
     }, {
       "address": "10.3.2.1"
     }, {
       "address": "127.0.0.1"
     }],
     "status": "ACTIVE",
     "version": 2,
     "created_at": "...",
     "updated_at": "...",
     "links": {
       "self": "https://dns.provider.com/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3/recordsets/9e27811d-0320-4179-abb7-0e00e371e25b"
     }
   }
 }

Delete RecordSet

Request:

 DELETE https://dns.provider.com/v2/zones/{zone-id}/recordsets/{recordset-id} HTTP/1.1
 Host: dns.provider.com
 X-Auth-Token: HPAuth_*****

Response:

 HTTP/1.1 204 No Content