Jump to: navigation, search

Difference between revisions of "Designate/Blueprints/Recordset Record API Redesign"

(Overview)
(Create a Recordset (POST): add comma to json)
 
(103 intermediate revisions by one other user not shown)
Line 1: Line 1:
Contents
 
  
    1 Overview
+
== Overview ==
  
 +
{| class="wikitable"
 +
|-
 +
! Gerrit Patch || []
 +
|-
 +
! Launchpad Blueprint || [https://blueprints.launchpad.net/designate/+spec/recordset-record-api-change]
 +
|}
  
 +
This blueprint proposes to eliminate the Records resource and only keep the RecordSets resource.
  
 +
The API for recordsets and records is too complicated. Currently, a user is forced to create a recordset before creating a record. This leads to a confusing user experience. Users will create, get, update and delete recordsets. When the user creates a recordset the code will determine if it should be a new recordset. If all data is the same except for the record, a Duplicate error will be returned and the user will then add the Record by modifying the Recordset. The record will no longer be accessible as a separate resource; only as part of the recordset.
  
== Overview ==
+
Currently, CNAME and DNAME record types cannot technically be a Recordset, because they cannot contain more than one record; however, in order to maintain consistency, we will be treating them as a Recordset.
 +
 
 +
Initially, there will only be a PUT and not a PATCH call available. The PUT will replace all the data in the Recordset, so if the user wants to add a record to a Recordset, the entire list of records will need to be submitted in the PUT request. There are plans to add json patch [http://www.rfc-base.org/txt/rfc-6902.txt RFC6902] through a different blueprint. This will make it easier to add, delete and modify records within a Recordset.
 +
 
 +
The concept of a Resource Record Set is defined in [http://www.ietf.org/rfc/rfc2181.txt RFC 2181, Section 5]. To summarize, it says, each DNS Resource Record (RR) has four parts: label, class, type and data. Any records that have all four equal, should be rejected as duplicates. However, it is possible for most record types to exist with the same label, class and type, but with different data. Such a group of records is defined to be a Resource Record Set (RRSet). A query for a specific label, class and type, should always return all records in the associated RRSet. It further states that all RRs in a RRSet should have the same ttl.
 +
 
 +
== API Resource ==
 +
 
 +
=== Current API ===
 +
/zones/{zone id}/recordsets/{recordset id}/records/{record id}
 +
 
 +
=== New API ===
 +
/zones/{zone id}/recordsets/{recordset id}
  
 +
=== API Details: Create / List / Patch / Delete Recordset ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! Gerrit Patch || []
+
! Verb !! Resource !! Description
 +
|-
 +
| GET || /zones/{zone id}/recordsets || Returns all recordsets for a zone
 +
|-
 +
| GET || /zones/{zone id}/recordsets/{recordset id} || Returns a specific recordset for a zone
 +
|-
 +
| POST || /zones/{zone id}/recordsets|| Creates a new recordset or adds a new record to an existing recordset
 +
|-
 +
| PUT || /zones/{zone id}/recordsets/{recordset id} || Replaces the current Recordset with data in the request
 
|-
 
|-
! Launchpad Blueprint || [https://blueprints.launchpad.net/designate/+spec/recordset-record-api-change]
+
| DELETE || /zones/{zone id}/recordsets/{recordset id} || Delete the recordset and all records associated with it.
 
|}
 
|}
 +
==== List Recordset(s) (GET) ====
 +
When no id is specified all recordsets for the specified zone are returned. No body is provided in the request.
 +
When a recordset id is provided, only that recordset is returned. No body is provided in the request
 +
 +
'''Response'''
 +
  {
 +
    "recordset" : [
 +
      {
 +
        "created_at" : "2014-04-29T19:34:21.819615",
 +
        "version" : 1,
 +
        "zone_id" : "766d7605-4c48-41fa-a9de-76692ed8051c",
 +
        "links" : {
 +
            "self" : "http://192.168.33.8:9001/v2/zones/766d7605-4c48-41fa-a9de-76692ed8051c/recordsets/06c3a2de-4e23-4143-98ab-6bf6d41ded26"
 +
        },
 +
        "ttl" : 3600,
 +
        "updated_at" : null,
 +
        "description" : null,
 +
        "type" : "A",
 +
        "id" : "06c3a2de-4e23-4143-98ab-6bf6d41ded26",
 +
        "name" : "example.com.",
 +
        "records" : [
 +
            "192.0.1.2",
 +
            "192.0.1.3"
 +
          ],
 +
        {
 +
          "created_at" : "2014-04-29T22:04:41.000000",
 +
          "version" : 1,
 +
          "zone_id":"766d7605-4c48-41fa-a9de-76692ed8051c",
 +
          "links":{
 +
            "self":"http://192.168.33.8:9001/v2/zones/766d7605-4c48-41fa-a9de-76692ed8051c/recordsets/e862ddb2-58ee-431a-a3b5-6881a5e26465"
 +
          },
 +
            "ttl":null,
 +
            "updated_at":null,
 +
            "description":null,
 +
            "type":"CNAME",
 +
            "id":"e862ddb2-58ee-431a-a3b5-6881a5e26465",
 +
            "name":"www.example.com.",
 +
            "records": [
 +
              "example.com."
 +
              ]
 +
            }
 +
        ],
 +
        "links" : {
 +
            "self" : "http://192.168.33.8:9001/v2/zones/766d7605-4c48-41fa-a9de-76692ed8051c/recordsets/"
 +
        }
 +
  }
 +
 +
==== Create a Recordset (POST) ====
 +
When a new Recordset is created, the caller must supply the name, type and data, which varies depending on the type. If the name and type are the same as an existing RecordSet, the return code will be 204 Duplicate, even if the data (record) being sent is different. The user must use PUT to change the record information. It cannot be changed implicitly through a CREATE.
 +
 +
'''Request'''
 +
  {
 +
    "recordset" : {
 +
      "name" : "foo.example.com.",
 +
      "type" : "A",
 +
      "ttl" : 3600,
 +
      "records" : [
 +
          "10.1.0.1"
 +
      ]
 +
    }
 +
  }
 +
 +
'''Response'''
 +
  {
 +
  "recordset" : [
 +
    {
 +
      "created_at" : "2014-05-01T19:34:21.819615",
 +
      "version" : 1,
 +
      "zone_id" : "766d7605-4c48-41fa-a9de-76692ed8051c",
 +
      "links" : {
 +
          "self" : "http://192.168.33.8:9001/v2/zones/766d7605-4c48-41fa-a9de-76692ed8051c/recordsets/06c3a2de-4e23-4143-98ab-6bf6d41ded12"
 +
      },
 +
      "ttl" : 3600,
 +
      "updated_at" : null,
 +
      "description" : null,
 +
      "type" : "A",
 +
      "id" : "06c3a2de-4e23-4143-98ab-6bf6d41ded12",
 +
      "name" : "foo.example.com.",
 +
      "records" : [
 +
          "10.1.0.1"
 +
        ]
 +
  }
 +
 +
==== Modify a RecordSet / Modify Records(PUT) ====
 +
 +
The PUT request will replace all the records in the Recordset.
 +
 +
'''Request'''
 +
 +
  {
 +
  "recordset" : {
 +
    "ttl" : 3000
 +
    "records" : [
 +
        "10.1.0.5"
 +
      ]
 +
    }
 +
  }
  
This blueprint proposes to provide an admin-only API call to dynamically manage blacklisted domains.
 
  
Blacklisted domains are domains that Designate will prevent from being used at the TLD level. It does not prevent them from being used as lower level domains.  For instance, if google.com is blacklisted, then that would effectively stop someone trying to add the domain www.google.com. However, it would not prohibit google.com.au, so that domain would need to be blacklisted separately, if desired.
+
'''Response'''
  
Currently, the list of blacklisted domains resides in the .config file. Designate must be restarted before any changes to the .config file take place. One possible solution to this could be to make the .config file reloadable without restarting the Designate service. However, there are only limited Operations personnel who have access to the .config file, and while blacklisted domains are not normally added or changed often, when it is needed, it needs to be done quickly. Providing an API call would allow support personnel to be given admin rights to this API call so that they can effectively make the change in a timely manner, without trying to find the one or two people who can change the .config file.  
+
  {
 +
  "recordset" : [
 +
    {
 +
      "created_at" : "2014-05-01T19:34:21.819615",
 +
      "version" : 1,
 +
      "zone_id" : "766d7605-4c48-41fa-a9de-76692ed8051c",
 +
      "links" : {
 +
          "self" : "http://192.168.33.8:9001/v2/zones/766d7605-4c48-41fa-a9de-76692ed8051c/recordsets/06c3a2de-4e23-4143-98ab-6bf6d41ded12"
 +
      },
 +
      "ttl" : 3000,
 +
      "updated_at" : 2014-05-04T19:34:21.819615,
 +
      "description" : null,
 +
      "type" : "A",
 +
      "id" : "06c3a2de-4e23-4143-98ab-6bf6d41ded12",
 +
      "name" : "foo.example.com.",
 +
      "records" : [
 +
          "10.1.0.5"
 +
      ]
 +
  }
  
To implement this management capability, a new API call will be created, along with a new database table to store the blacklisted domains, and they will no longer be in the .config file.
+
==== Delete a RecordSet (DELETE) ====
 +
When deleting a RecordSet, the user must supply the id in the url. All records associated with a RecordSet are, also, deleted. The request body and return body are empty. A 204 is returned.

Latest revision as of 22:01, 20 October 2014

Overview

Gerrit Patch []
Launchpad Blueprint [1]

This blueprint proposes to eliminate the Records resource and only keep the RecordSets resource.

The API for recordsets and records is too complicated. Currently, a user is forced to create a recordset before creating a record. This leads to a confusing user experience. Users will create, get, update and delete recordsets. When the user creates a recordset the code will determine if it should be a new recordset. If all data is the same except for the record, a Duplicate error will be returned and the user will then add the Record by modifying the Recordset. The record will no longer be accessible as a separate resource; only as part of the recordset.

Currently, CNAME and DNAME record types cannot technically be a Recordset, because they cannot contain more than one record; however, in order to maintain consistency, we will be treating them as a Recordset.

Initially, there will only be a PUT and not a PATCH call available. The PUT will replace all the data in the Recordset, so if the user wants to add a record to a Recordset, the entire list of records will need to be submitted in the PUT request. There are plans to add json patch RFC6902 through a different blueprint. This will make it easier to add, delete and modify records within a Recordset.

The concept of a Resource Record Set is defined in RFC 2181, Section 5. To summarize, it says, each DNS Resource Record (RR) has four parts: label, class, type and data. Any records that have all four equal, should be rejected as duplicates. However, it is possible for most record types to exist with the same label, class and type, but with different data. Such a group of records is defined to be a Resource Record Set (RRSet). A query for a specific label, class and type, should always return all records in the associated RRSet. It further states that all RRs in a RRSet should have the same ttl.

API Resource

Current API

/zones/{zone id}/recordsets/{recordset id}/records/{record id}

New API

/zones/{zone id}/recordsets/{recordset id}

API Details: Create / List / Patch / Delete Recordset

Verb Resource Description
GET /zones/{zone id}/recordsets Returns all recordsets for a zone
GET /zones/{zone id}/recordsets/{recordset id} Returns a specific recordset for a zone
POST /zones/{zone id}/recordsets Creates a new recordset or adds a new record to an existing recordset
PUT /zones/{zone id}/recordsets/{recordset id} Replaces the current Recordset with data in the request
DELETE /zones/{zone id}/recordsets/{recordset id} Delete the recordset and all records associated with it.

List Recordset(s) (GET)

When no id is specified all recordsets for the specified zone are returned. No body is provided in the request. When a recordset id is provided, only that recordset is returned. No body is provided in the request

Response

 {
   "recordset" : [
     {
       "created_at" : "2014-04-29T19:34:21.819615",
       "version" : 1,
       "zone_id" : "766d7605-4c48-41fa-a9de-76692ed8051c",
       "links" : {
           "self" : "http://192.168.33.8:9001/v2/zones/766d7605-4c48-41fa-a9de-76692ed8051c/recordsets/06c3a2de-4e23-4143-98ab-6bf6d41ded26"
       },
       "ttl" : 3600,
       "updated_at" : null,
       "description" : null,
       "type" : "A",
       "id" : "06c3a2de-4e23-4143-98ab-6bf6d41ded26",
       "name" : "example.com.",
       "records" : [
           "192.0.1.2",
           "192.0.1.3"
         ],
       {
         "created_at" : "2014-04-29T22:04:41.000000",
         "version" : 1,
         "zone_id":"766d7605-4c48-41fa-a9de-76692ed8051c",
         "links":{
           "self":"http://192.168.33.8:9001/v2/zones/766d7605-4c48-41fa-a9de-76692ed8051c/recordsets/e862ddb2-58ee-431a-a3b5-6881a5e26465"
          },
           "ttl":null,
           "updated_at":null,
           "description":null,
           "type":"CNAME",
           "id":"e862ddb2-58ee-431a-a3b5-6881a5e26465",
           "name":"www.example.com.",
           "records": [
              "example.com."
             ]
           }
       ],
       "links" : {
           "self" : "http://192.168.33.8:9001/v2/zones/766d7605-4c48-41fa-a9de-76692ed8051c/recordsets/"
       }
 }

Create a Recordset (POST)

When a new Recordset is created, the caller must supply the name, type and data, which varies depending on the type. If the name and type are the same as an existing RecordSet, the return code will be 204 Duplicate, even if the data (record) being sent is different. The user must use PUT to change the record information. It cannot be changed implicitly through a CREATE.

Request

 {
   "recordset" : {
     "name" : "foo.example.com.",
     "type" : "A",
     "ttl" : 3600,
     "records" : [
         "10.1.0.1"
      ]
   }
 }

Response

  {
  "recordset" : [
    {
      "created_at" : "2014-05-01T19:34:21.819615",
      "version" : 1,
      "zone_id" : "766d7605-4c48-41fa-a9de-76692ed8051c",
      "links" : {
          "self" : "http://192.168.33.8:9001/v2/zones/766d7605-4c48-41fa-a9de-76692ed8051c/recordsets/06c3a2de-4e23-4143-98ab-6bf6d41ded12"
      },
      "ttl" : 3600,
      "updated_at" : null,
      "description" : null,
      "type" : "A",
      "id" : "06c3a2de-4e23-4143-98ab-6bf6d41ded12",
      "name" : "foo.example.com.",
      "records" : [
          "10.1.0.1"
       ]
  }

Modify a RecordSet / Modify Records(PUT)

The PUT request will replace all the records in the Recordset.

Request

  {
  "recordset" : {
    "ttl" : 3000
    "records" : [
        "10.1.0.5"
      ]
    }
  }


Response

  {
 "recordset" : [
   {
     "created_at" : "2014-05-01T19:34:21.819615",
     "version" : 1,
     "zone_id" : "766d7605-4c48-41fa-a9de-76692ed8051c",
     "links" : {
         "self" : "http://192.168.33.8:9001/v2/zones/766d7605-4c48-41fa-a9de-76692ed8051c/recordsets/06c3a2de-4e23-4143-98ab-6bf6d41ded12"
     },
     "ttl" : 3000,
     "updated_at" : 2014-05-04T19:34:21.819615,
     "description" : null,
     "type" : "A",
     "id" : "06c3a2de-4e23-4143-98ab-6bf6d41ded12",
     "name" : "foo.example.com.",
     "records" : [
         "10.1.0.5"
      ]
 }

Delete a RecordSet (DELETE)

When deleting a RecordSet, the user must supply the id in the url. All records associated with a RecordSet are, also, deleted. The request body and return body are empty. A 204 is returned.