Designate/APIv2
This is a EARLY DRAFT of the Designate Version 2 API.
Contents
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).
- This complicates simple record types, but simplifies complex record types (SRV, GEeoIP, Weigthed 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.
- 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.
- Pagination (See "List Zones")
- Filtering of result sets (See "List Zones")
TODOs
- Try Align with the Glance V2 and Keystone V3 APIs where possible, these are the latest OpenStack APIs and should be used as a reference where possible
- 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.")
- Pagination? (See "List Zones")
- All tenant access?
- Filtering/searching syntax? (See "List Zones")
- Probably LOTS more
Resources
Zone
| Property | Type | Default | Required | Immutable | Read Only |
|---|---|---|---|---|---|
| id | uuid | Generated | ✔ | ✔ | ✔ |
| pool_id | uuid | Configured | ✘ | ✔ | ✘ |
| name | string | None | ✔ | ✔ | ✘ |
| string | None | ✔ | ✘ | ✘ | |
| ttl | int | 3600 | ✔ | ✘ | ✘ |
| serial | int | Generated | ✔ | ✘ | ✔ |
| notes | string | None | ✘ | ✘ | ✘ |
| version | int | Generated | ✔ | ✘ | ✔ |
| created_at | timestamp | Generated | ✔ | ✘ | ✔ |
| updated_at | timestamp | Generated | ✔ | ✘ | ✔ |
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 | ✘ | ✘ | ✘ |
| version | int | Generated | ✔ | ✘ | ✔ |
| created_at | timestamp | Generated | ✔ | ✘ | ✔ |
| updated_at | timestamp | Generated | ✔ | ✘ | ✔ |
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
Collections
The following conventions apply to all collections, unless otherwise noted below.
Pagination
Pagination is available on all collections and is controlled using a compination 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"
}
}
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",
"name": "example.org.",
"email": "joe@example.org.",
"ttl": 7200,
"serial": 1351800588,
"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",
"name": "example.org.",
"email": "joe@example.org.",
"ttl": 7200,
"serial": 1351800588,
"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_*****
Request (With Filters):
GET /v2/zones?email=joe%40example.net HTTP/1.1 Host: dns.provider.com Accept: application/json X-Auth-Token: HPAuth_*****
Request (With Paging):
GET /v2/zones?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://endpoint/v2/zones?per_page=10&page=1>;rel=previous Link: <https://endpoint/v2/zones?per_page=10&page=3>;rel=next
{
"zones": [{
"id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
"pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
"name": "example.org.",
"email": "joe@example.org.",
"ttl": 7200,
"serial": 1351800588,
"version": 1,
"created_at": "...",
"updated_at": null
}, {
"id": "fdd7b0dc-52a3-491e-829f-41d18e1d3ada",
"pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
"name": "example.net.",
"email": "joe@example.net.",
"ttl": 7200,
"serial": 1351800588,
"version": 1,
"created_at": "...",
"updated_at": null
}]
}
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 201 Created Vary: Accept Content-Type: application/json
{
"zone": {
"id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
"pool_id": "7d62d10d-3a16-4828-85dd-7b3fdc0ba989",
"name": "example.org.",
"email": "joe@example.org.",
"ttl": 3600,
"serial": 1351800588,
"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 202 Accepted
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"
}],
"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."
}],
"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"
}],
"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
{
"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"
}],
"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."
}],
"version": 1,
"created_at": "...",
"updated_at": null
}]
}
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 201 Created 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"
}],
"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 202 Accepted