Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id D5E67200C60 for ; Mon, 10 Apr 2017 04:44:19 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id D4686160BA8; Mon, 10 Apr 2017 02:44:19 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 5866B160BA4 for ; Mon, 10 Apr 2017 04:44:18 +0200 (CEST) Received: (qmail 38791 invoked by uid 500); 10 Apr 2017 02:44:17 -0000 Mailing-List: contact notifications-help@libcloud.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@libcloud.apache.org Delivered-To: mailing list notifications@libcloud.apache.org Received: (qmail 38770 invoked by uid 500); 10 Apr 2017 02:44:16 -0000 Delivered-To: apmail-libcloud-commits@libcloud.apache.org Received: (qmail 38767 invoked by uid 99); 10 Apr 2017 02:44:16 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 10 Apr 2017 02:44:16 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id A9514E028C; Mon, 10 Apr 2017 02:44:16 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: anthonyshaw@apache.org To: commits@libcloud.apache.org Date: Mon, 10 Apr 2017 02:44:16 -0000 Message-Id: <27ba62292a1c44bda67f23fde9de4d61@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [1/2] libcloud git commit: Added DNS driver for OnApp archived-at: Mon, 10 Apr 2017 02:44:20 -0000 Repository: libcloud Updated Branches: refs/heads/trunk bdd0b34e8 -> 14cb428e4 Added DNS driver for OnApp Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/bc580377 Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/bc580377 Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/bc580377 Branch: refs/heads/trunk Commit: bc580377a64cb2cbfe9119ddc0bc449fb418f579 Parents: bdd0b34 Author: Tinu Cleatus Authored: Sun Mar 26 00:09:49 2017 +0530 Committer: Anthony Shaw Committed: Mon Apr 10 12:39:15 2017 +1000 ---------------------------------------------------------------------- docs/dns/drivers/onapp.rst | 23 ++ docs/examples/dns/onapp/instantiate_driver.py | 9 + libcloud/dns/drivers/onapp.py | 332 +++++++++++++++++++ libcloud/dns/providers.py | 2 + libcloud/dns/types.py | 1 + .../test/dns/fixtures/onapp/create_record.json | 9 + .../test/dns/fixtures/onapp/create_zone.json | 10 + .../dns/fixtures/onapp/dns_zone_not_found.json | 5 + .../test/dns/fixtures/onapp/get_record.json | 9 + .../fixtures/onapp/get_record_after_update.json | 9 + libcloud/test/dns/fixtures/onapp/get_zone.json | 10 + .../test/dns/fixtures/onapp/list_records.json | 65 ++++ .../test/dns/fixtures/onapp/list_zones.json | 22 ++ libcloud/test/dns/test_onapp.py | 223 +++++++++++++ libcloud/test/secrets.py-dist | 1 + 15 files changed, 730 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/bc580377/docs/dns/drivers/onapp.rst ---------------------------------------------------------------------- diff --git a/docs/dns/drivers/onapp.rst b/docs/dns/drivers/onapp.rst new file mode 100644 index 0000000..b5cde10 --- /dev/null +++ b/docs/dns/drivers/onapp.rst @@ -0,0 +1,23 @@ +OnApp DNS Driver Documentation +================================= + +`OnApp`_ Cloud integrates its fully redundant DNS network into the OnApp +Control Panel, so you can manage DNS for your own domains, and your customers’ +domains. Its Anycast DNS service is hosted at datacenters around the world, +and it’s free of charge for customers running the full version of OnApp Cloud, +with CDN enabled. Get fast, fully redundant DNS for free! + +Instantiating the driver +------------------------ + +.. literalinclude:: /examples/dns/onapp/instantiate_driver.py + :language: python + +API Docs +-------- + +.. autoclass:: libcloud.dns.drivers.onapp.OnAppDNSDriver + :members: + :inherited-members: + +.. _`OnApp`: http://onapp.com/ http://git-wip-us.apache.org/repos/asf/libcloud/blob/bc580377/docs/examples/dns/onapp/instantiate_driver.py ---------------------------------------------------------------------- diff --git a/docs/examples/dns/onapp/instantiate_driver.py b/docs/examples/dns/onapp/instantiate_driver.py new file mode 100644 index 0000000..6643764 --- /dev/null +++ b/docs/examples/dns/onapp/instantiate_driver.py @@ -0,0 +1,9 @@ +from libcloud.dns.types import Provider +from libcloud.dns.providers import get_driver + +username = 'your account username' +password = 'your account password' +host = 'onapp.test' + +cls = get_driver(Provider.ONAPP) +driver = cls(key=username, secret=password, host=host) http://git-wip-us.apache.org/repos/asf/libcloud/blob/bc580377/libcloud/dns/drivers/onapp.py ---------------------------------------------------------------------- diff --git a/libcloud/dns/drivers/onapp.py b/libcloud/dns/drivers/onapp.py new file mode 100644 index 0000000..ee704ad --- /dev/null +++ b/libcloud/dns/drivers/onapp.py @@ -0,0 +1,332 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +OnApp DNS Driver +""" + +__all__ = [ + 'OnAppDNSDriver' +] + +import json + +from libcloud.common.onapp import OnAppConnection +from libcloud.dns.types import Provider, RecordType +from libcloud.dns.base import DNSDriver, Zone, Record + + +DEFAULT_ZONE_TTL = 1200 + + +class OnAppDNSDriver(DNSDriver): + type = Provider.ONAPP + name = 'OnApp' + website = 'http://onapp.com/' + connectionCls = OnAppConnection + + RECORD_TYPE_MAP = { + RecordType.SOA: 'SOA', + RecordType.NS: 'NS', + RecordType.A: 'A', + RecordType.AAAA: 'AAAA', + RecordType.CNAME: 'CNAME', + RecordType.MX: 'MX', + RecordType.TXT: 'TXT', + RecordType.SRV: 'SRV', + } + + def list_zones(self): + """ + Return a list of zones. + + :return: ``list`` of :class:`Zone` + """ + response = self.connection.request('/dns_zones.json') + + zones = self._to_zones(response.object) + 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` + """ + response = self.connection.request('/dns_zones/%s.json' % zone_id) + zone = self._to_zone(response.object) + return zone + + 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 (All zones are master by design). + :type type: ``str`` + + :param ttl: TTL for new records. (This is not really used) + :type ttl: ``int`` + + :param extra: Extra attributes (set auto_populate: 0 if you + don't want to auto populate with existing DNS records). (optional) + :type extra: ``dict`` + + :rtype: :class:`Zone` + + For more info, please see: + https://docs.onapp.com/display/52API/Add+DNS+Zone + """ + dns_zone = {'name': domain} + if extra is not None: + dns_zone.update(extra) + dns_zone_data = json.dumps({'dns_zone': dns_zone}) + response = self.connection.request( + '/dns_zones.json', + method='POST', + headers={"Content-type": "application/json"}, + data=dns_zone_data) + zone = self._to_zone(response.object) + return zone + + def delete_zone(self, zone): + """ + Delete a zone. + + Note: This will also delete all the records belonging to this zone. + + :param zone: Zone to delete. + :type zone: :class:`Zone` + + :rtype: ``bool`` + """ + self.connection.request( + '/dns_zones/%s.json' % zone.id, + method='DELETE') + return True + + 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` + """ + response = self.connection.request( + '/dns_zones/%s/records.json' % zone.id) + dns_records = response.object['dns_zone']['records'] + records = self._to_records(dns_records, 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` + """ + response = self.connection.request('/dns_zones/%s/records/%s.json' % + (zone_id, record_id)) + record = self._to_record(response.object, zone_id=zone_id) + return record + + def create_record(self, name, zone, type, data, extra=None): + """ + Create a new 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 where the requested record is created. + :type zone: :class:`Zone` + + :param type: DNS record type (A, AAAA, ...). + :type type: :class:`RecordType` + + :param data: Data for the record (depends on the record type). + Used only for A and AAAA record types. + :type data: ``str`` + + :param extra: Extra attributes (driver specific). (optional) + :type extra: ``dict`` + + :rtype: :class:`Record` + + For more info, please see: + https://docs.onapp.com/display/52API/Add+DNS+Record + """ + dns_record = self._format_record(name, type, data, extra) + dns_record_data = json.dumps({'dns_record': dns_record}) + response = self.connection.request( + '/dns_zones/%s/records.json' % zone.id, + method='POST', + headers={"Content-type": "application/json"}, + data=dns_record_data) + record = self._to_record(response.object, zone=zone) + return record + + def update_record(self, record, name, type, data, extra=None): + """ + Update an existing record. + + :param record: Record to update. + :type record: :class:`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 type: DNS record type (A, AAAA, ...). + :type type: :class:`RecordType` + + :param data: Data for the record (depends on the record type). + Used only for A and AAAA record types. + :type data: ``str`` + + :param extra: (optional) Extra attributes (driver specific). + :type extra: ``dict`` + + :rtype: :class:`Record` + + For more info, please see: + https://docs.onapp.com/display/52API/Edit+DNS+Records + """ + zone = record.zone + dns_record = self._format_record(name, type, data, extra) + dns_record_data = json.dumps({'dns_record': dns_record}) + self.connection.request( + '/dns_zones/%s/records/%s.json' % (zone.id, record.id), + method='PUT', + headers={"Content-type": "application/json"}, + data=dns_record_data) + record = self.get_record(zone.id, record.id) + return record + + def delete_record(self, record): + """ + Delete a record. + + :param record: Record to delete. + :type record: :class:`Record` + + :rtype: ``bool`` + + For more info, please see: + https://docs.onapp.com/display/52API/Delete+DNS+Record + """ + zone_id = record.zone.id + self.connection.request('/dns_zones/%s/records/%s.json' % (zone_id, + record.id), method='DELETE') + return True + + # + # Helper methods + # + + def _format_record(self, name, type, data, extra): + if name is '': + name = '@' + if extra is None: + extra = {} + record_type = self.RECORD_TYPE_MAP[type] + new_record = { + 'name': name, + 'ttl': extra.get('ttl', DEFAULT_ZONE_TTL), + 'type': record_type + } + if type == RecordType.MX: + additions = { + 'priority': extra.get('priority', 1), + 'hostname': extra.get('hostname') + } + elif type == RecordType.SRV: + additions = { + 'port': extra.get('port'), + 'weight': extra.get('weight', 1), + 'priority': extra.get('priority', 1), + 'hostname': extra.get('hostname') + } + elif type == RecordType.A: + additions = {'ip': data} + elif type == RecordType.CNAME: + additions = {'hostname': extra.get('hostname')} + elif type == RecordType.AAAA: + additions = {'ip': data} + elif type == RecordType.TXT: + additions = {'txt': extra.get('txt')} + elif type == RecordType.NS: + additions = {'hostname': extra.get('hostname')} + + new_record.update(additions) + return new_record + + def _to_zones(self, data): + zones = [] + for zone in data: + _zone = self._to_zone(zone) + zones.append(_zone) + + return zones + + def _to_zone(self, data): + dns_zone = data.get('dns_zone') + id = dns_zone.get('id') + name = dns_zone.get('name') + extra = {'user_id': dns_zone.get('user_id'), + 'cdn_reference': dns_zone.get('cdn_reference'), + 'created_at': dns_zone.get('created_at'), + 'updated_at': dns_zone.get('updated_at')} + + type = 'master' + + return Zone(id=id, domain=name, type=type, ttl=DEFAULT_ZONE_TTL, + driver=self, extra=extra) + + def _to_records(self, data, zone): + records = [] + data = data.values() + for data_type in data: + for item in data_type: + record = self._to_record(item, zone=zone) + records.append(record) + records.sort(key=lambda x: x.id, reverse=False) + return records + + def _to_record(self, data, zone_id=None, zone=None): + if not zone: # We need zone_id or zone + zone = self.get_zone(zone_id) + record = data.get('dns_record') + id = record.get('id') + name = record.get('name') + type = record.get('type') + ttl = record.get('ttl', None) + return Record(id=id, name=name, type=type, data=record, zone=zone, + driver=self, ttl=ttl, extra={}) http://git-wip-us.apache.org/repos/asf/libcloud/blob/bc580377/libcloud/dns/providers.py ---------------------------------------------------------------------- diff --git a/libcloud/dns/providers.py b/libcloud/dns/providers.py index 38aa39f..c7c4968 100644 --- a/libcloud/dns/providers.py +++ b/libcloud/dns/providers.py @@ -75,6 +75,8 @@ DRIVERS = { ('libcloud.dns.drivers.buddyns', 'BuddyNSDNSDriver'), Provider.POWERDNS: ('libcloud.dns.drivers.powerdns', 'PowerDNSDriver'), + Provider.ONAPP: + ('libcloud.dns.drivers.onapp', 'OnAppDNSDriver'), # Deprecated Provider.RACKSPACE_US: http://git-wip-us.apache.org/repos/asf/libcloud/blob/bc580377/libcloud/dns/types.py ---------------------------------------------------------------------- diff --git a/libcloud/dns/types.py b/libcloud/dns/types.py index f05deb3..6b272e2 100644 --- a/libcloud/dns/types.py +++ b/libcloud/dns/types.py @@ -52,6 +52,7 @@ class Provider(object): LUADNS = 'luadns' NFSN = 'nfsn' NSONE = 'nsone' + ONAPP = 'onapp' POINTDNS = 'pointdns' POWERDNS = 'powerdns' RACKSPACE = 'rackspace' http://git-wip-us.apache.org/repos/asf/libcloud/blob/bc580377/libcloud/test/dns/fixtures/onapp/create_record.json ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/fixtures/onapp/create_record.json b/libcloud/test/dns/fixtures/onapp/create_record.json new file mode 100644 index 0000000..8b39878 --- /dev/null +++ b/libcloud/test/dns/fixtures/onapp/create_record.json @@ -0,0 +1,9 @@ +{ + "dns_record": { + "name": "blog", + "id": 111227, + "ttl": 3600, + "ip": "123.156.189.2", + "type": "A" + } +} http://git-wip-us.apache.org/repos/asf/libcloud/blob/bc580377/libcloud/test/dns/fixtures/onapp/create_zone.json ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/fixtures/onapp/create_zone.json b/libcloud/test/dns/fixtures/onapp/create_zone.json new file mode 100644 index 0000000..63ed2cf --- /dev/null +++ b/libcloud/test/dns/fixtures/onapp/create_zone.json @@ -0,0 +1,10 @@ +{ + "dns_zone": { + "id": 1, + "name": "example.com", + "user_id": 123, + "created_at": "2017-03-24T16:07:05.000+05:30", + "updated_at": "2017-03-24T16:07:05.000+05:30", + "cdn_reference": 12345678 + } +} http://git-wip-us.apache.org/repos/asf/libcloud/blob/bc580377/libcloud/test/dns/fixtures/onapp/dns_zone_not_found.json ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/fixtures/onapp/dns_zone_not_found.json b/libcloud/test/dns/fixtures/onapp/dns_zone_not_found.json new file mode 100644 index 0000000..9f1c2ee --- /dev/null +++ b/libcloud/test/dns/fixtures/onapp/dns_zone_not_found.json @@ -0,0 +1,5 @@ +{ + "errors": [ + "DnsZone not found" + ] +} http://git-wip-us.apache.org/repos/asf/libcloud/blob/bc580377/libcloud/test/dns/fixtures/onapp/get_record.json ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/fixtures/onapp/get_record.json b/libcloud/test/dns/fixtures/onapp/get_record.json new file mode 100644 index 0000000..b84fad6 --- /dev/null +++ b/libcloud/test/dns/fixtures/onapp/get_record.json @@ -0,0 +1,9 @@ +{ + "dns_record": { + "name": "@", + "id": 123, + "ttl": 3600, + "ip": "123.156.189.1", + "type": "A" + } +} http://git-wip-us.apache.org/repos/asf/libcloud/blob/bc580377/libcloud/test/dns/fixtures/onapp/get_record_after_update.json ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/fixtures/onapp/get_record_after_update.json b/libcloud/test/dns/fixtures/onapp/get_record_after_update.json new file mode 100644 index 0000000..13dcf09 --- /dev/null +++ b/libcloud/test/dns/fixtures/onapp/get_record_after_update.json @@ -0,0 +1,9 @@ +{ + "dns_record": { + "name": "@", + "id": 123, + "ttl": 4500, + "ip": "123.156.189.2", + "type": "A" + } +} http://git-wip-us.apache.org/repos/asf/libcloud/blob/bc580377/libcloud/test/dns/fixtures/onapp/get_zone.json ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/fixtures/onapp/get_zone.json b/libcloud/test/dns/fixtures/onapp/get_zone.json new file mode 100644 index 0000000..63ed2cf --- /dev/null +++ b/libcloud/test/dns/fixtures/onapp/get_zone.json @@ -0,0 +1,10 @@ +{ + "dns_zone": { + "id": 1, + "name": "example.com", + "user_id": 123, + "created_at": "2017-03-24T16:07:05.000+05:30", + "updated_at": "2017-03-24T16:07:05.000+05:30", + "cdn_reference": 12345678 + } +} http://git-wip-us.apache.org/repos/asf/libcloud/blob/bc580377/libcloud/test/dns/fixtures/onapp/list_records.json ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/fixtures/onapp/list_records.json b/libcloud/test/dns/fixtures/onapp/list_records.json new file mode 100644 index 0000000..b4be246 --- /dev/null +++ b/libcloud/test/dns/fixtures/onapp/list_records.json @@ -0,0 +1,65 @@ +{ + "dns_zone": { + "id": 1, + "name": "example.com", + "user_id": 123, + "created_at": "2017-03-24T16:07:05.000+05:30", + "updated_at": "2017-03-24T16:07:05.000+05:30", + "cdn_reference": 12345678, + "records": { + "A": [ + { + "dns_record": { + "name": "@", + "id": 111222, + "ttl": 3600, + "ip": "123.156.189.1", + "type": "A" + } + }, + { + "dns_record": { + "name": "www", + "id": 111223, + "ttl": 3600, + "ip": "123.156.189.1", + "type": "A" + } + } + ], + "CNAME": [ + { + "dns_record": { + "name": "mail", + "id": 111224, + "ttl": 3600, + "hostname": "examplemail.com", + "type": "CNAME" + } + } + ], + "MX": [ + { + "dns_record": { + "priority": 20, + "name": "@", + "id": 111225, + "ttl": 3600, + "hostname": "mx.examplemail.com", + "type": "MX" + } + }, + { + "dns_record": { + "priority": 10, + "name": "@", + "id": 111226, + "ttl": 3600, + "hostname": "mx2.examplemail.com", + "type": "MX" + } + } + ] + } + } +} http://git-wip-us.apache.org/repos/asf/libcloud/blob/bc580377/libcloud/test/dns/fixtures/onapp/list_zones.json ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/fixtures/onapp/list_zones.json b/libcloud/test/dns/fixtures/onapp/list_zones.json new file mode 100644 index 0000000..631a558 --- /dev/null +++ b/libcloud/test/dns/fixtures/onapp/list_zones.json @@ -0,0 +1,22 @@ +[ + { + "dns_zone": { + "id": 1, + "name": "example.com", + "user_id": 123, + "created_at": "2017-03-24T16:07:05.000+05:30", + "updated_at": "2017-03-24T16:07:05.000+05:30", + "cdn_reference": 12345678 + } + }, + { + "dns_zone": { + "id": 2, + "name": "example.net", + "user_id": 124, + "created_at": "2017-03-24T16:07:05.000+05:30", + "updated_at": "2017-03-24T16:07:05.000+05:30", + "cdn_reference": 12345679 + } + } +] http://git-wip-us.apache.org/repos/asf/libcloud/blob/bc580377/libcloud/test/dns/test_onapp.py ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/test_onapp.py b/libcloud/test/dns/test_onapp.py new file mode 100644 index 0000000..7af52ba --- /dev/null +++ b/libcloud/test/dns/test_onapp.py @@ -0,0 +1,223 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and + +import sys +import unittest + +from libcloud.dns.drivers.onapp import OnAppDNSDriver +from libcloud.dns.types import RecordType +from libcloud.test import LibcloudTestCase, MockHttpTestCase +from libcloud.test.file_fixtures import DNSFileFixtures +from libcloud.test.secrets import DNS_PARAMS_ONAPP +from libcloud.utils.py3 import httplib +from libcloud.common.exceptions import BaseHTTPError + + +class OnAppDNSTests(LibcloudTestCase): + + def setUp(self): + OnAppDNSDriver.connectionCls.conn_class = OnAppDNSMockHttp + OnAppDNSMockHttp.type = None + self.driver = OnAppDNSDriver(*DNS_PARAMS_ONAPP) + + def assertHasKeys(self, dictionary, keys): + for key in keys: + self.assertTrue(key in dictionary, 'key "%s" not in dictionary' % + (key)) + + def test_list_record_types(self): + record_types = self.driver.list_record_types() + self.assertEqual(len(record_types), 8) + self.assertTrue(RecordType.A in record_types) + self.assertTrue(RecordType.AAAA in record_types) + self.assertTrue(RecordType.CNAME in record_types) + self.assertTrue(RecordType.MX in record_types) + self.assertTrue(RecordType.NS in record_types) + self.assertTrue(RecordType.SOA in record_types) + self.assertTrue(RecordType.SRV in record_types) + self.assertTrue(RecordType.TXT in record_types) + + def test_list_zones_success(self): + zones = self.driver.list_zones() + self.assertEqual(len(zones), 2) + + zone1 = zones[0] + self.assertEqual(zone1.id, '1') + self.assertEqual(zone1.type, 'master') + self.assertEqual(zone1.domain, 'example.com') + self.assertEqual(zone1.ttl, 1200) + self.assertHasKeys(zone1.extra, ['user_id', 'cdn_reference', + 'created_at', 'updated_at']) + + zone2 = zones[1] + self.assertEqual(zone2.id, '2') + self.assertEqual(zone2.type, 'master') + self.assertEqual(zone2.domain, 'example.net') + self.assertEqual(zone2.ttl, 1200) + self.assertHasKeys(zone2.extra, ['user_id', 'cdn_reference', + 'created_at', 'updated_at']) + + def test_get_zone_success(self): + zone1 = self.driver.get_zone(zone_id='1') + self.assertEqual(zone1.id, '1') + self.assertEqual(zone1.type, 'master') + self.assertEqual(zone1.domain, 'example.com') + self.assertEqual(zone1.ttl, 1200) + self.assertHasKeys(zone1.extra, ['user_id', 'cdn_reference', + 'created_at', 'updated_at']) + + def test_get_zone_not_found(self): + OnAppDNSMockHttp.type = 'NOT_FOUND' + try: + self.driver.get_zone(zone_id='3') + except BaseHTTPError: + self.assertRaises(Exception) + + def test_create_zone_success(self): + OnAppDNSMockHttp.type = 'CREATE' + zone = self.driver.create_zone(domain='example.com') + self.assertEqual(zone.id, '1') + self.assertEqual(zone.domain, 'example.com') + self.assertEqual(zone.ttl, 1200) + self.assertEqual(zone.type, 'master') + self.assertHasKeys(zone.extra, ['user_id', 'cdn_reference', + 'created_at', 'updated_at']) + + def test_delete_zone(self): + zone = self.driver.get_zone(zone_id='1') + OnAppDNSMockHttp.type = 'DELETE' + self.assertTrue(self.driver.delete_zone(zone)) + + def test_list_records_success(self): + zone = self.driver.get_zone(zone_id='1') + records = self.driver.list_records(zone=zone) + self.assertEqual(len(records), 5) + + record1 = records[0] + self.assertEqual(record1.id, '111222') + self.assertEqual(record1.name, '@') + self.assertEqual(record1.type, RecordType.A) + self.assertEqual(record1.ttl, 3600) + self.assertEqual(record1.data['ip'], '123.156.189.1') + + record2 = records[2] + self.assertEqual(record2.id, '111224') + self.assertEqual(record2.name, 'mail') + self.assertEqual(record1.ttl, 3600) + self.assertEqual(record2.type, RecordType.CNAME) + self.assertEqual(record2.data['hostname'], 'examplemail.com') + + record3 = records[4] + self.assertEqual(record3.id, '111226') + self.assertEqual(record3.name, '@') + self.assertEqual(record3.type, RecordType.MX) + self.assertEqual(record3.data['hostname'], 'mx2.examplemail.com') + + def test_get_record_success(self): + record = self.driver.get_record(zone_id='1', + record_id='123') + self.assertEqual(record.id, '123') + self.assertEqual(record.name, '@') + self.assertEqual(record.type, RecordType.A) + self.assertEqual(record.data['ip'], '123.156.189.1') + + def test_create_record_success(self): + zone = self.driver.get_zone(zone_id='1') + OnAppDNSMockHttp.type = 'CREATE' + record = self.driver.create_record(name='blog', zone=zone, + type=RecordType.A, + data='123.156.189.2') + self.assertEqual(record.id, '111227') + self.assertEqual(record.name, 'blog') + self.assertEqual(record.type, RecordType.A) + self.assertEqual(record.data['ip'], '123.156.189.2') + self.assertEqual(record.data['ttl'], 3600) + + def test_update_record_success(self): + record = self.driver.get_record(zone_id='1', + record_id='123') + OnAppDNSMockHttp.type = 'UPDATE' + extra = {'ttl': 4500} + record1 = self.driver.update_record(record=record, name='@', + type=record.type, + data='123.156.189.2', + extra=extra) + self.assertEqual(record.data['ip'], '123.156.189.1') + self.assertEqual(record.ttl, 3600) + self.assertEqual(record1.data['ip'], '123.156.189.2') + self.assertEqual(record1.ttl, 4500) + + def test_delete_record_success(self): + record = self.driver.get_record(zone_id='1', + record_id='123') + OnAppDNSMockHttp.type = 'DELETE' + status = self.driver.delete_record(record=record) + self.assertTrue(status) + + +class OnAppDNSMockHttp(MockHttpTestCase): + fixtures = DNSFileFixtures('onapp') + + def _dns_zones_json(self, method, url, body, headers): + body = self.fixtures.load('list_zones.json') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + + def _dns_zones_1_json(self, method, url, body, headers): + body = self.fixtures.load('get_zone.json') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + + def _dns_zones_3_json_NOT_FOUND(self, method, url, body, headers): + body = self.fixtures.load('dns_zone_not_found.json') + return (httplib.NOT_FOUND, body, {}, + httplib.responses[httplib.NOT_FOUND]) + + def _dns_zones_json_CREATE(self, method, url, body, headers): + body = self.fixtures.load('create_zone.json') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + + def _dns_zones_1_json_DELETE(self, method, url, body, headers): + return (httplib.NO_CONTENT, '', {}, + httplib.responses[httplib.NO_CONTENT]) + + def _dns_zones_1_records_json(self, method, url, body, headers): + body = self.fixtures.load('list_records.json') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + + def _dns_zones_1_records_123_json(self, method, url, body, headers): + body = self.fixtures.load('get_record.json') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + + def _dns_zones_1_records_json_CREATE(self, method, url, body, headers): + body = self.fixtures.load('create_record.json') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + + def _dns_zones_1_records_123_json_UPDATE(self, method, url, body, headers): + if method == 'GET': + body = self.fixtures.load('get_record_after_update.json') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + else: + return (httplib.NO_CONTENT, '', {}, + httplib.responses[httplib.NO_CONTENT]) + + def _dns_zones_1_json_UPDATE(self, method, url, body, headers): + body = self.fixtures.load('get_zone.json') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + + def _dns_zones_1_records_123_json_DELETE(self, method, url, body, headers): + return (httplib.NO_CONTENT, '', {}, + httplib.responses[httplib.NO_CONTENT]) + + +if __name__ == '__main__': + sys.exit(unittest.main()) http://git-wip-us.apache.org/repos/asf/libcloud/blob/bc580377/libcloud/test/secrets.py-dist ---------------------------------------------------------------------- diff --git a/libcloud/test/secrets.py-dist b/libcloud/test/secrets.py-dist index 2c21f84..ce16d95 100644 --- a/libcloud/test/secrets.py-dist +++ b/libcloud/test/secrets.py-dist @@ -90,6 +90,7 @@ DNS_PARAMS_NSONE = ('key', ) DNS_PARAMS_LUADNS = ('user', 'key') DNS_PARAMS_BUDDYNS = ('key', ) DNS_PARAMS_DNSPOD = ('key', ) +DNS_PARAMS_ONAPP = ('key', 'secret', True, 'host') # Container CONTAINER_PARAMS_DOCKER = ('user', 'password')