Jump to: navigation, search

Difference between revisions of "Designate/APIv2"

(Add "links" to sample List API calls)
(Add section on "pools")
Line 17: Line 17:
  
 
= 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.
 +
 +
The pool "type" defines the pool implementation, an example implementation might be
 +
 +
{| 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" or "ERROR".
 +
  
 
== Zone ==
 
== Zone ==
Line 26: Line 70:
 
|-
 
|-
 
| pool_id    || uuid        || Configured    || ✘            || ✔        || ✘   
 
| pool_id    || uuid        || Configured    || ✘            || ✔        || ✘   
 +
|-
 +
| project_id || uuid        || None          || ✔            || ✔        || ✔ 
 
|-
 
|-
 
| name      || string      || None          || ✔            || ✔        || ✘   
 
| name      || string      || None          || ✔            || ✔        || ✘   
Line 315: Line 361:
 
       "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.",
Line 345: Line 392:
 
       "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.",
Line 376: Line 424:
 
       "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.",
Line 387: Line 436:
 
       "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.",
Line 443: Line 493:
 
       "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.",

Revision as of 14:38, 28 July 2013

This is a DRAFT of the Designate Version 2 API. The draft shall not be considered final until a implementation is complete.

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, GEeoIP, Weigthed 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.
  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.
  5. Pagination (See "List Zones")
  6. Filtering of result sets (See "List Zones")

TODOs

  1. 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.")
  2. All tenant access?

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.

The pool "type" defines the pool implementation, an example implementation might be

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" or "ERROR".


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" or "ERROR".

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" or "ERROR".

RData

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

{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}

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.

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".

Collections

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

Pagination

Pagination is available on all collections and is controlled using a combination of two query paramaters - `page=2&per_page=10`. 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.

Request:

 GET /v2/examples?per_page=10&page=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
 Link: <https://dns.provider.com/v2/zones?per_page=10&page=1>;rel=previous
 Link: <https://dns.provider.com/v2/zones?per_page=10&page=3>;rel=next
 {
   "examples": [{
     "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
     "....": "...."
   }, {
     "id": "fdd7b0dc-52a3-491e-829f-41d18e1d3ada",
     "....": "...."
   }],
   "links": {
     "next": "https://dns.provider.com/v2/examples?per_page=10&page=3",
     "previous": "https://dns.provider.com/v2/examples?per_page=10&page=1"    
   }
 }

Filtering

Filtering is available on all collections and is controlled using query paramaters 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.

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",
     "....": "...."
   }]
 }

Resources

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

TODO

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
   }
 }

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
   }
 }

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
 Link: <https://dns.provider.com/v2/zones?page=2>;rel=next
 {
   "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
   }, {
     "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": {
     "next": "https://dns.provider.com/v2/zones?page=2"
   }
 }

Update Zone

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

Request Option 1 - POST Request:

 POST 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 - 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": "..."
   }
 }

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
   }
 }

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
   }
 }

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
   }
 }

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
 Link: <https://dns.provider.com/v2/zones/{zone-id}/recordsets?page=2>;rel=next
 {
   "recordsets": [{
     "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
   }, {
     "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": {
     "next": "https://dns.provider.com/v2/zones/{zone-id}/recordsets?page=2"
   }
 }

Update RecordSet

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

Request Option 1 - POST Request:

 POST 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 - 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": "..."
   }
 }

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