You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by an...@apache.org on 2016/03/31 00:46:56 UTC
[3/6] libcloud git commit: adds dns support for luadns
adds dns support for luadns
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/683f2b4c
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/683f2b4c
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/683f2b4c
Branch: refs/heads/trunk
Commit: 683f2b4c35992e1d0b120a059f8ee5dc1bcb860c
Parents: 28a16e2
Author: lostbird <lostbird@lostbird.(none)>
Authored: Wed Mar 30 01:51:53 2016 +0200
Committer: anthony-shaw <an...@gmail.com>
Committed: Thu Mar 31 09:46:24 2016 +1100
----------------------------------------------------------------------
libcloud/common/luadns.py | 69 +++++
libcloud/dns/drivers/luadns.py | 293 ++++++++++++++++++
.../fixtures/luadns/create_record_success.json | 10 +
.../fixtures/luadns/create_zone_success.json | 10 +
.../fixtures/luadns/delete_record_success.json | 0
.../fixtures/luadns/delete_zone_success.json | 0
.../dns/fixtures/luadns/empty_records_list.json | 1 +
.../dns/fixtures/luadns/empty_zones_list.json | 1 +
.../test/dns/fixtures/luadns/get_record.json | 10 +
libcloud/test/dns/fixtures/luadns/get_zone.json | 42 +++
.../fixtures/luadns/record_does_not_exist.json | 1 +
.../test/dns/fixtures/luadns/records_list.json | 22 ++
.../fixtures/luadns/zone_already_exists.json | 4 +
.../fixtures/luadns/zone_does_not_exist.json | 1 +
.../test/dns/fixtures/luadns/zones_list.json | 22 ++
libcloud/test/dns/test_luadns.py | 306 +++++++++++++++++++
libcloud/test/secrets.py-dist | 1 +
17 files changed, 793 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/683f2b4c/libcloud/common/luadns.py
----------------------------------------------------------------------
diff --git a/libcloud/common/luadns.py b/libcloud/common/luadns.py
new file mode 100644
index 0000000..373b36a
--- /dev/null
+++ b/libcloud/common/luadns.py
@@ -0,0 +1,69 @@
+import base64
+
+
+from libcloud.common.base import ConnectionUserAndKey, JsonResponse
+from libcloud.utils.py3 import b
+
+__all__ = [
+ 'API_HOST',
+ 'LuadnsException',
+ 'LuadnsResponse',
+ 'LuadnsConnection'
+]
+
+# Endpoint for luadns api
+API_HOST = 'api.luadns.com'
+
+
+class LuadnsResponse(JsonResponse):
+ errors = []
+ objects = []
+
+ def __init__(self, response, connection):
+ super(LuadnsResponse, self).__init__(response=response,
+ connection=connection)
+ self.errors, self.objects = self.parse_body_and_errors()
+ if not self.success():
+ raise LuadnsException(code=self.status,
+ message=self.errors.pop()['message'])
+
+ def parse_body_and_errors(self):
+ js = super(LuadnsResponse, self).parse_body()
+ if 'message' in js:
+ self.errors.append(js)
+ else:
+ self.objects.append(js)
+
+ return self.errors, self.objects
+
+ def success(self):
+ return len(self.errors) == 0
+
+
+class LuadnsConnection(ConnectionUserAndKey):
+ host = API_HOST
+ responseCls = LuadnsResponse
+
+ def add_default_headers(self, headers):
+ b64string = b('%s:%s' % (self.user_id, self.key))
+ encoded = base64.b64encode(b64string).decode('utf-8')
+ authorization = 'Basic ' + encoded
+
+ headers['Accept'] = 'application/json'
+ headers['Authorization'] = authorization
+
+ return headers
+
+
+class LuadnsException(Exception):
+
+ def __init__(self, code, message):
+ self.code = code
+ self.message = message
+ self.args = (code, message)
+
+ def __str__(self):
+ return "%s %s" % (self.code, self.message)
+
+ def __repr__(self):
+ return "Luadns %s %s" % (self.code, self.message)
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/683f2b4c/libcloud/dns/drivers/luadns.py
----------------------------------------------------------------------
diff --git a/libcloud/dns/drivers/luadns.py b/libcloud/dns/drivers/luadns.py
new file mode 100644
index 0000000..b0adecb
--- /dev/null
+++ b/libcloud/dns/drivers/luadns.py
@@ -0,0 +1,293 @@
+import sys
+
+try:
+ import simplejson as json
+except ImportError:
+ import json
+
+from libcloud.common.luadns import LuadnsResponse, LuadnsConnection,\
+ LuadnsException
+from libcloud.dns.base import DNSDriver, Zone, Record
+from libcloud.dns.types import Provider, RecordType
+from libcloud.dns.types import ZoneDoesNotExistError, ZoneAlreadyExistsError
+from libcloud.dns.types import RecordDoesNotExistError
+
+
+__all__ = [
+ 'LuadnsDNSDriver'
+]
+
+
+class LuadnsDNSResponse(LuadnsResponse):
+ pass
+
+
+class LuadnsDNSConnection(LuadnsConnection):
+ responseCls = LuadnsDNSResponse
+
+
+class LuadnsDNSDriver(DNSDriver):
+ type = Provider.LUADNS
+ name = 'Luadns'
+ website = 'https://www.luadns.com'
+ connectionCls = LuadnsDNSConnection
+
+ RECORD_TYPE_MAP = {
+ RecordType.A: 'A',
+ RecordType.AAAA: 'AAAA',
+ RecordType.CNAME: 'CNAME',
+ RecordType.MX: 'MX',
+ RecordType.NS: 'NS',
+ RecordType.PTR: 'PTR',
+ RecordType.SOA: 'SOA',
+ RecordType.SRV: 'SRV',
+ RecordType.TXT: 'TXT'
+ }
+
+ def list_zones(self):
+ """
+ Return a list of zones.
+
+ :return: ``list`` of :class:`Zone`
+ """
+ action = '/v1/zones'
+ response = self.connection.request(action=action,
+ method='GET')
+ zones = self._to_zones(response.parse_body())
+
+ return zones
+
+ def get_zone(self, zone_id):
+ """
+ Return a Zone instance.
+
+ :param zone_id: ID of the required zone
+ :type zone_id: ``str``
+
+ :rtype: :class:`Zone`
+ """
+ action = '/v1/zones/%s' % zone_id
+ try:
+ response = self.connection.request(action=action)
+ except LuadnsException:
+ e = sys.exc_info()[1]
+ if e.message in ['Zone not found.', 'Resource not found.']:
+ raise ZoneDoesNotExistError(zone_id=zone_id,
+ value='', driver=self)
+ else:
+ raise e
+
+ zone = self._to_zone(response.parse_body())
+
+ return zone
+
+ def delete_zone(self, zone):
+ """
+ Delete a zone.
+
+ Note: This will delete all the records belonging to this zone.
+
+ :param zone: Zone to delete.
+ :type zone: :class:`Zone`
+
+ :rtype: ``bool``
+ """
+ action = '/v1/zones/%s' % zone.id
+ try:
+ response = self.connection.request(action=action,
+ method='DELETE')
+ except LuadnsException:
+ e = sys.exc_info()[1]
+ if e.message in ['Resource not found.', 'Zone not found.']:
+ raise ZoneDoesNotExistError(zone_id=zone.id,
+ value='', driver=self)
+ else:
+ raise e
+
+ return response.status == 200
+
+ def create_zone(self, domain, type='master', ttl=None, extra=None):
+ """
+ Create a new zone.
+
+ :param domain: Zone domain name (e.g. example.com)
+ :type domain: ``str``
+
+ :param type: Zone type (This is not really used. See API docs for extra
+ parameters).
+ :type type: ``str``
+
+ :param ttl: TTL for new records. (This is not really used)
+ :type ttl: ``int``
+
+ :param extra: Extra attributes (driver specific). ('region_support',
+ 'zone_data')
+ :type extra: ``dict``
+
+ :rtype: :class:`Zone`
+ """
+ action = '/v1/zones'
+ data = json.dumps({'name': domain})
+ try:
+ response = self.connection.request(action=action,
+ method='POST',
+ data=data)
+ except LuadnsException:
+ e = sys.exc_info()[1]
+ if e.message == "Zone '%s' is taken already." % domain:
+ raise ZoneAlreadyExistsError(zone_id=domain,
+ value='',
+ driver=self)
+ else:
+ raise e
+ zone = self._to_zone(response.parse_body())
+
+ return zone
+
+ def list_records(self, zone):
+ """
+ Return a list of records for the provided zone.
+
+ :param zone: Zone to list records for.
+ :type zone: :class:`Zone`
+
+ :return: ``list`` of :class:`Record`
+ """
+ action = '/v1/zones/%s/records' % zone.id
+ response = self.connection.request(action=action)
+ records = self._to_records(response.parse_body(), zone=zone)
+
+ return records
+
+ def get_record(self, zone_id, record_id):
+ """
+ Return a Record instance.
+
+ :param zone_id: ID of the required zone
+ :type zone_id: ``str``
+
+ :param record_id: ID of the required record
+ :type record_id: ``str``
+
+ :rtype: :class:`Record`
+ """
+ zone = self.get_zone(zone_id=zone_id)
+ action = '/v1/zones/%s/records/%s' % (zone_id, record_id)
+ try:
+ response = self.connection.request(action=action)
+ except LuadnsException:
+ e = sys.exc_info()[1]
+ if e.message == 'Record not found.':
+ raise RecordDoesNotExistError(record_id=record_id, driver=self,
+ value='')
+ else:
+ raise e
+
+ record = self._to_record(response.parse_body(), zone=zone)
+
+ return record
+
+ def delete_record(self, record):
+ """
+ Delete a record.
+
+ :param record: Record to delete.
+ :type record: :class:`Record`
+
+ :rtype: ``bool``
+ """
+ action = '/v1/zones/%s/records/%s' % (record.zone.id, record.id)
+ try:
+ response = self.connection.request(action=action,
+ method='DELETE')
+ except LuadnsException:
+ e = sys.exc_info()[1]
+ if e.message == 'Record not found.':
+ raise RecordDoesNotExistError(record_id=record.id, driver=self,
+ value='')
+ else:
+ raise e
+
+ return response.status == 200
+
+ def create_record(self, name, zone, type, data, extra=None):
+ """
+ Create a record.
+
+ :param name: Record name without the domain name (e.g. www).
+ Note: If you want to create a record for a base domain
+ name, you should specify empty string ('') for this
+ argument.
+ :type name: ``str``
+
+ :param zone: Zone which the records will be created for.
+ :type zone: :class:`Zone`
+
+ :param type: DNS record type ( 'A', 'AAAA', 'CNAME', 'MX', 'NS',
+ 'PTR', 'SOA', 'SRV', 'TXT').
+ :type type: :class:`RecordType`
+
+ :param data: Data for the record (depends on the record type).
+ :type data: ``str``
+
+ :param extra: (optional) Extra attributes ('prio', 'ttl').
+ :type extra: ``dict``
+
+ :rtype: :class:`Record`
+ """
+ action = '/v1/zones/%s/records' % zone.id
+ to_post = {'name': name, 'content': data, 'type': type,
+ 'zone_id': int(zone.id)}
+ # ttl is required to create a record for luadns
+ # pass it through extra like this: extra={'ttl':ttl}
+ if extra is not None:
+ to_post.update(extra)
+ data = json.dumps(to_post)
+ try:
+ response = self.connection.request(action=action,
+ method='POST',
+ data=data)
+ except LuadnsException:
+ e = sys.exc_info()[1]
+ raise e
+
+ record = self._to_record(response.parse_body(), zone=zone)
+
+ return record
+
+ def _to_zone(self, item):
+ common_attr = ['id', 'name']
+ extra = {}
+ for key in item:
+ if key not in common_attr:
+ extra[key] = item.get(key)
+ zone = Zone(domain=item['name'], id=item['id'], type=None,
+ ttl=None, driver=self, extra=extra)
+
+ return zone
+
+ def _to_zones(self, items):
+ zones = []
+ for item in items:
+ zones.append(self._to_zone(item))
+
+ return zones
+
+ def _to_record(self, item, zone):
+ common_attr = ['id', 'content', 'name', 'type']
+ extra = {}
+ for key in item:
+ if key not in common_attr:
+ extra[key] = item.get(key)
+ record = Record(id=item['id'], name=item['name'], type=item['type'],
+ data=item['content'], zone=zone, driver=self,
+ extra=extra)
+
+ return record
+
+ def _to_records(self, items, zone):
+ records = []
+ for item in items:
+ records.append(self._to_record(item, zone))
+
+ return records
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/683f2b4c/libcloud/test/dns/fixtures/luadns/create_record_success.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/luadns/create_record_success.json b/libcloud/test/dns/fixtures/luadns/create_record_success.json
new file mode 100644
index 0000000..c72c2b9
--- /dev/null
+++ b/libcloud/test/dns/fixtures/luadns/create_record_success.json
@@ -0,0 +1,10 @@
+{
+ "id": 31,
+ "name": "test.com.",
+ "type": "A",
+ "content": "127.0.0.1",
+ "ttl": 13,
+ "zone_id": 1,
+ "created_at": "2015-01-17T14:04:35.251785849Z",
+ "updated_at": "2015-01-17T14:04:35.251785972Z"
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/683f2b4c/libcloud/test/dns/fixtures/luadns/create_zone_success.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/luadns/create_zone_success.json b/libcloud/test/dns/fixtures/luadns/create_zone_success.json
new file mode 100644
index 0000000..2df7075
--- /dev/null
+++ b/libcloud/test/dns/fixtures/luadns/create_zone_success.json
@@ -0,0 +1,10 @@
+{
+ "id": 3,
+ "name": "example.org",
+ "synced": false,
+ "queries_count": 0,
+ "records_count": 0,
+ "aliases_count": 0,
+ "redirects_count": 0,
+ "forwards_count": 0
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/683f2b4c/libcloud/test/dns/fixtures/luadns/delete_record_success.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/luadns/delete_record_success.json b/libcloud/test/dns/fixtures/luadns/delete_record_success.json
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/libcloud/blob/683f2b4c/libcloud/test/dns/fixtures/luadns/delete_zone_success.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/luadns/delete_zone_success.json b/libcloud/test/dns/fixtures/luadns/delete_zone_success.json
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/libcloud/blob/683f2b4c/libcloud/test/dns/fixtures/luadns/empty_records_list.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/luadns/empty_records_list.json b/libcloud/test/dns/fixtures/luadns/empty_records_list.json
new file mode 100644
index 0000000..0637a08
--- /dev/null
+++ b/libcloud/test/dns/fixtures/luadns/empty_records_list.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/683f2b4c/libcloud/test/dns/fixtures/luadns/empty_zones_list.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/luadns/empty_zones_list.json b/libcloud/test/dns/fixtures/luadns/empty_zones_list.json
new file mode 100644
index 0000000..0637a08
--- /dev/null
+++ b/libcloud/test/dns/fixtures/luadns/empty_zones_list.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/683f2b4c/libcloud/test/dns/fixtures/luadns/get_record.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/luadns/get_record.json b/libcloud/test/dns/fixtures/luadns/get_record.json
new file mode 100644
index 0000000..29dc374
--- /dev/null
+++ b/libcloud/test/dns/fixtures/luadns/get_record.json
@@ -0,0 +1,10 @@
+{
+ "id": 31,
+ "name": "example.com.",
+ "type": "MX",
+ "content": "10 mail.example.com.",
+ "ttl": 300,
+ "zone_id": 1,
+ "created_at": "2015-01-17T14:04:35.251785849Z",
+ "updated_at": "2015-01-17T14:04:35.251785972Z"
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/683f2b4c/libcloud/test/dns/fixtures/luadns/get_zone.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/luadns/get_zone.json b/libcloud/test/dns/fixtures/luadns/get_zone.json
new file mode 100644
index 0000000..2f8ccf7
--- /dev/null
+++ b/libcloud/test/dns/fixtures/luadns/get_zone.json
@@ -0,0 +1,42 @@
+{
+ "id": 31,
+ "name": "example.org",
+ "synced": false,
+ "queries_count": 0,
+ "records_count": 3,
+ "aliases_count": 0,
+ "redirects_count": 0,
+ "forwards_count": 0,
+ "records": [
+ {
+ "id": 6683,
+ "name": "example.org.",
+ "type": "SOA",
+ "content": "a.ns.luadns.net. hostmaster.luadns.com. 1421501178 1200 120 604800 3600",
+ "ttl": 3600,
+ "zone_id": 3,
+ "created_at": "2015-01-17T13:26:17.52747Z",
+ "updated_at": "2015-01-17T13:26:17.527471Z"
+ },
+ {
+ "id": 6684,
+ "name": "example.org.",
+ "type": "NS",
+ "content": "a.ns.luadns.net.",
+ "ttl": 86400,
+ "zone_id": 3,
+ "created_at": "2015-01-17T13:26:17.529741Z",
+ "updated_at": "2015-01-17T13:26:17.529741Z"
+ },
+ {
+ "id": 6685,
+ "name": "example.org.",
+ "type": "NS",
+ "content": "b.ns.luadns.net.",
+ "ttl": 86400,
+ "zone_id": 3,
+ "created_at": "2015-01-17T13:26:17.531911Z",
+ "updated_at": "2015-01-17T13:26:17.531911Z"
+ }
+ ]
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/683f2b4c/libcloud/test/dns/fixtures/luadns/record_does_not_exist.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/luadns/record_does_not_exist.json b/libcloud/test/dns/fixtures/luadns/record_does_not_exist.json
new file mode 100644
index 0000000..96f3d9f
--- /dev/null
+++ b/libcloud/test/dns/fixtures/luadns/record_does_not_exist.json
@@ -0,0 +1 @@
+{"status":"Not Found","request_id":"be9cd5fd857254a4059357b2354edb92","message":"Record not found."}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/683f2b4c/libcloud/test/dns/fixtures/luadns/records_list.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/luadns/records_list.json b/libcloud/test/dns/fixtures/luadns/records_list.json
new file mode 100644
index 0000000..d4cd30a
--- /dev/null
+++ b/libcloud/test/dns/fixtures/luadns/records_list.json
@@ -0,0 +1,22 @@
+[
+ {
+ "id": 6683,
+ "name": "example.org.",
+ "type": "NS",
+ "content": "b.ns.luadns.net.",
+ "ttl": 86400,
+ "zone_id": 3,
+ "created_at": "2015-01-17T13:08:37.522452Z",
+ "updated_at": "2015-01-17T13:08:37.522452Z"
+ },
+ {
+ "id": 6684,
+ "name": "example.org.",
+ "type": "NS",
+ "content": "a.ns.luadns.net.",
+ "ttl": 86400,
+ "zone_id": 3,
+ "created_at": "2015-01-17T13:08:37.520623Z",
+ "updated_at": "2015-01-17T13:08:37.520623Z"
+ }
+]
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/683f2b4c/libcloud/test/dns/fixtures/luadns/zone_already_exists.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/luadns/zone_already_exists.json b/libcloud/test/dns/fixtures/luadns/zone_already_exists.json
new file mode 100644
index 0000000..18e82d7
--- /dev/null
+++ b/libcloud/test/dns/fixtures/luadns/zone_already_exists.json
@@ -0,0 +1,4 @@
+{ "status":"Forbidden",
+ "request_id":"a75744f55cabe0411e02fa97e1a5d91b",
+ "message":"Zone 'test.com' is taken already."
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/683f2b4c/libcloud/test/dns/fixtures/luadns/zone_does_not_exist.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/luadns/zone_does_not_exist.json b/libcloud/test/dns/fixtures/luadns/zone_does_not_exist.json
new file mode 100644
index 0000000..2de2301
--- /dev/null
+++ b/libcloud/test/dns/fixtures/luadns/zone_does_not_exist.json
@@ -0,0 +1 @@
+{"status":"Not Found","request_id":"be9cd5fd857254a4059357b2354edb92","message":"Zone not found."}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/683f2b4c/libcloud/test/dns/fixtures/luadns/zones_list.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/luadns/zones_list.json b/libcloud/test/dns/fixtures/luadns/zones_list.json
new file mode 100644
index 0000000..e06e64e
--- /dev/null
+++ b/libcloud/test/dns/fixtures/luadns/zones_list.json
@@ -0,0 +1,22 @@
+[
+ {
+ "id": 1,
+ "name": "example.com",
+ "synced": false,
+ "queries_count": 0,
+ "records_count": 3,
+ "aliases_count": 0,
+ "redirects_count": 0,
+ "forwards_count": 0
+ },
+ {
+ "id": 2,
+ "name": "example.net",
+ "synced": false,
+ "queries_count": 0,
+ "records_count": 3,
+ "aliases_count": 0,
+ "redirects_count": 0,
+ "forwards_count": 0
+ }
+]
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/683f2b4c/libcloud/test/dns/test_luadns.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_luadns.py b/libcloud/test/dns/test_luadns.py
new file mode 100644
index 0000000..4d174e8
--- /dev/null
+++ b/libcloud/test/dns/test_luadns.py
@@ -0,0 +1,306 @@
+import sys
+import unittest
+
+from libcloud.utils.py3 import httplib
+from libcloud.dns.drivers.luadns import LuadnsDNSDriver
+from libcloud.test import MockHttp
+from libcloud.test.file_fixtures import DNSFileFixtures
+from libcloud.test.secrets import DNS_PARAMS_LUADNS
+from libcloud.dns.types import ZoneDoesNotExistError, ZoneAlreadyExistsError
+from libcloud.dns.types import RecordDoesNotExistError
+from libcloud.dns.types import RecordType
+from libcloud.dns.base import Zone, Record
+
+
+class LuadnsTests(unittest.TestCase):
+
+ def setUp(self):
+ LuadnsMockHttp.type = None
+ LuadnsDNSDriver.connectionCls.conn_classes = (
+ None, LuadnsMockHttp)
+ self.driver = LuadnsDNSDriver(*DNS_PARAMS_LUADNS)
+ self.test_zone = Zone(id='11', type='master', ttl=None,
+ domain='example.com', extra={},
+ driver=self.driver)
+ self.test_record = Record(id='13', type=RecordType.A,
+ name='example.com', zone=self.test_zone,
+ data='127.0.0.1', driver=self, extra={})
+
+ def assertHasKeys(self, dictionary, keys):
+ for key in keys:
+ self.assertTrue(key in dictionary,
+ 'key "%s" not in dictionary' % key)
+
+ def test_list_zones_empty(self):
+ LuadnsMockHttp.type = 'EMPTY_ZONES_LIST'
+ zones = self.driver.list_zones()
+
+ self.assertEqual(zones, [])
+
+ def test_list_zones_success(self):
+ zones = self.driver.list_zones()
+
+ self.assertEqual(len(zones), 2)
+
+ zone = zones[0]
+ self.assertEqual(zone.id, '1')
+ self.assertEqual(zone.domain, 'example.com')
+ self.assertEqual(zone.type, None)
+ self.assertEqual(zone.driver, self.driver)
+ self.assertEqual(zone.ttl, None)
+
+ second_zone = zones[1]
+ self.assertEqual(second_zone.id, '2')
+ self.assertEqual(second_zone.domain, 'example.net')
+ self.assertEqual(second_zone.type, None)
+ self.assertEqual(second_zone.driver, self.driver)
+ self.assertEqual(second_zone.ttl, None)
+
+ def test_get_zone_zone_does_not_exist(self):
+ LuadnsMockHttp.type = 'ZONE_DOES_NOT_EXIST'
+ try:
+ self.driver.get_zone(zone_id='13')
+ except ZoneDoesNotExistError:
+ e = sys.exc_info()[1]
+ self.assertEqual(e.zone_id, '13')
+ else:
+ self.fail('Exception was not thrown')
+
+ def test_get_zone_success(self):
+ LuadnsMockHttp.type = 'GET_ZONE_SUCCESS'
+ zone = self.driver.get_zone(zone_id='31')
+
+ self.assertEqual(zone.id, '31')
+ self.assertEqual(zone.domain, 'example.org')
+ self.assertEqual(zone.type, None)
+ self.assertEqual(zone.ttl, None)
+ self.assertEqual(zone.driver, self.driver)
+
+ def test_delete_zone_success(self):
+ LuadnsMockHttp.type = 'DELETE_ZONE_SUCCESS'
+ zone = self.test_zone
+ status = self.driver.delete_zone(zone=zone)
+
+ self.assertEqual(status, True)
+
+ def test_delete_zone_zone_does_not_exist(self):
+ LuadnsMockHttp.type = 'DELETE_ZONE_ZONE_DOES_NOT_EXIST'
+ zone = self.test_zone
+ try:
+ self.driver.delete_zone(zone=zone)
+ except ZoneDoesNotExistError:
+ e = sys.exc_info()[1]
+ self.assertEqual(e.zone_id, '11')
+ else:
+ self.fail('Exception was not thrown')
+
+ def test_create_zone_success(self):
+ LuadnsMockHttp.type = 'CREATE_ZONE_SUCCESS'
+ zone = self.driver.create_zone(domain='example.org')
+
+ self.assertEqual(zone.id, '3')
+ self.assertEqual(zone.domain, 'example.org')
+ self.assertEqual(zone.type, None)
+ self.assertEqual(zone.ttl, None)
+ self.assertEqual(zone.driver, self.driver)
+
+ def test_create_zone_zone_zone_already_exists(self):
+ LuadnsMockHttp.type = 'CREATE_ZONE_ZONE_ALREADY_EXISTS'
+ try:
+ self.driver.create_zone(domain='test.com')
+ except ZoneAlreadyExistsError:
+ e = sys.exc_info()[1]
+ self.assertEqual(e.zone_id, 'test.com')
+ else:
+ self.fail('Exception was not thrown')
+
+ def test_list_records_empty(self):
+ LuadnsMockHttp.type = 'EMPTY_RECORDS_LIST'
+ zone = self.test_zone
+ records = self.driver.list_records(zone=zone)
+
+ self.assertEqual(records, [])
+
+ def test_list_records_success(self):
+ LuadnsMockHttp.type = 'LIST_RECORDS_SUCCESS'
+ zone = self.test_zone
+ records = self.driver.list_records(zone=zone)
+
+ self.assertEqual(len(records), 2)
+
+ record = records[0]
+ self.assertEqual(record.id, '6683')
+ self.assertEqual(record.type, 'NS')
+ self.assertEqual(record.name, 'example.org.')
+ self.assertEqual(record.data, 'b.ns.luadns.net.')
+ self.assertEqual(record.zone, self.test_zone)
+ self.assertEqual(record.zone.id, '11')
+
+ second_record = records[1]
+ self.assertEqual(second_record.id, '6684')
+ self.assertEqual(second_record.type, 'NS')
+ self.assertEqual(second_record.name, 'example.org.')
+ self.assertEqual(second_record.data, 'a.ns.luadns.net.')
+ self.assertEqual(second_record.zone, self.test_zone)
+
+ def test_get_record_record_does_not_exist(self):
+ LuadnsMockHttp.type = 'GET_RECORD_RECORD_DOES_NOT_EXIST'
+ try:
+ self.driver.get_record(zone_id='31', record_id='31')
+ except RecordDoesNotExistError:
+ e = sys.exc_info()[1]
+ self.assertEqual(e.record_id, '31')
+ else:
+ self.fail('Exception was not thrown')
+
+ def test_get_record_success(self):
+ LuadnsMockHttp.type = 'GET_RECORD_SUCCESS'
+ record = self.driver.get_record(zone_id='31', record_id='31')
+
+ self.assertEqual(record.id, '31')
+ self.assertEqual(record.type, 'MX')
+ self.assertEqual(record.name, 'example.com.')
+ self.assertEqual(record.data, '10 mail.example.com.')
+
+ def test_delete_record_success(self):
+ LuadnsMockHttp.type = 'DELETE_RECORD_SUCCESS'
+ record = self.test_record
+ status = self.driver.delete_record(record=record)
+
+ self.assertEqual(status, True)
+
+ def test_delete_record_RECORD_DOES_NOT_EXIST_ERROR(self):
+ LuadnsMockHttp.type = 'DELETE_RECORD_RECORD_DOES_NOT_EXIST'
+ record = self.test_record
+ try:
+ self.driver.delete_record(record=record)
+ except RecordDoesNotExistError:
+ e = sys.exc_info()[1]
+ self.assertEqual(e.record_id, '13')
+ else:
+ self.fail('Exception was not thrown')
+
+ def test_create_record_success(self):
+ LuadnsMockHttp.type = 'CREATE_RECORD_SUCCESS'
+ record = self.driver.create_record(name='test.com.',
+ zone=self.test_zone,
+ type='A',
+ data='127.0.0.1',
+ extra={'ttl': 13})
+ self.assertEqual(record.id, '31')
+ self.assertEqual(record.name, 'test.com.')
+ self.assertEqual(record.data, '127.0.0.1')
+ self.assertEqual(record.ttl, None)
+
+ def test_record_already_exists_error(self):
+ pass
+
+
+class LuadnsMockHttp(MockHttp):
+ fixtures = DNSFileFixtures('luadns')
+
+ def _v1_zones(self, method, url, body, headers):
+ body = self.fixtures.load('zones_list.json')
+
+ return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
+ def _v1_zones_EMPTY_ZONES_LIST(self, method, url, body,
+ headers):
+ body = self.fixtures.load('empty_zones_list.json')
+
+ return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
+ def _v1_zones_13_ZONE_DOES_NOT_EXIST(self, method, url,
+ body, headers):
+ body = self.fixtures.load('zone_does_not_exist.json')
+
+ return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
+ def _v1_zones_31_GET_ZONE_SUCCESS(self, method, url,
+ body, headers):
+ body = self.fixtures.load('get_zone.json')
+
+ return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
+ def _v1_zones_11_DELETE_ZONE_SUCCESS(self, method, url,
+ body, headers):
+ body = self.fixtures.load('delete_zone_success.json')
+
+ return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
+ def _v1_zones_11_DELETE_ZONE_ZONE_DOES_NOT_EXIST(
+ self, method, url, body, headers):
+ body = self.fixtures.load('zone_does_not_exist.json')
+
+ return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
+ def _v1_zones_CREATE_ZONE_SUCCESS(self, method, url,
+ body, headers):
+ body = self.fixtures.load('create_zone_success.json')
+
+ return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
+ def _v1_zones_CREATE_ZONE_ZONE_ALREADY_EXISTS(
+ self, method, url, body, headers):
+ body = self.fixtures.load('zone_already_exists.json')
+
+ return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
+ def _v1_zones_11_records_EMPTY_RECORDS_LIST(self, method, url, body,
+ headers):
+ body = self.fixtures.load('empty_records_list.json')
+
+ return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
+ def _v1_zones_11_records_LIST_RECORDS_SUCCESS(self, method, url,
+ body, headers):
+ body = self.fixtures.load('records_list.json')
+
+ return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
+ def _v1_zones_31_records_31_GET_RECORD_RECORD_DOES_NOT_EXIST(
+ self, method, url, body, headers):
+ body = self.fixtures.load('record_does_not_exist.json')
+
+ return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
+ def _v1_zones_31_GET_RECORD_RECORD_DOES_NOT_EXIST(
+ self, method, url, body, headers):
+
+ body = self.fixtures.load('get_zone.json')
+
+ return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
+ def _v1_zones_31_GET_RECORD_SUCCESS(self, method, url,
+ body, headers):
+ body = self.fixtures.load('get_zone.json')
+
+ return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
+ def _v1_zones_31_records_31_GET_RECORD_SUCCESS(self, method, url,
+ body, headers):
+ body = self.fixtures.load('get_record.json')
+
+ return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
+ def _v1_zones_11_records_13_DELETE_RECORD_SUCCESS(self, method, url,
+ body, headers):
+ body = self.fixtures.load('delete_record_success.json')
+
+ return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
+ def _v1_zones_11_records_13_DELETE_RECORD_RECORD_DOES_NOT_EXIST(
+ self, method, url, body, headers):
+ body = self.fixtures.load('record_does_not_exist.json')
+
+ return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
+ def _v1_zones_11_records_CREATE_RECORD_SUCCESS(self, method, url,
+ body, headers):
+ body = self.fixtures.load('create_record_success.json')
+
+ return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
+
+if __name__ == '__main__':
+ sys.exit(unittest.main())
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/683f2b4c/libcloud/test/secrets.py-dist
----------------------------------------------------------------------
diff --git a/libcloud/test/secrets.py-dist b/libcloud/test/secrets.py-dist
index 480ac3f..2f7e202 100644
--- a/libcloud/test/secrets.py-dist
+++ b/libcloud/test/secrets.py-dist
@@ -85,6 +85,7 @@ DNS_PARAMS_GODADDY = ('customer-id', 'api_user', 'api_key')
DNS_PARAMS_CLOUDFLARE = ('user@example.com', 'key')
DNS_PARAMS_AURORADNS = ('apikey', 'secretkey')
DNS_PARAMS_NSONE = ('key', )
+DNS_PARAMS_LUADNS = ('user', 'key')
# Container
CONTAINER_PARAMS_DOCKER = ('user', 'password')