Repository: libcloud Updated Branches: refs/heads/trunk 08d7d95db -> 865431320
Add support for Google DNS API. Google recently added a new API for DNS management. This new driver implement simple operations to create and view zones and records. Closes #269 Signed-off-by: Tomaz Muraus <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/86543132 Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/86543132 Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/86543132 Branch: refs/heads/trunk Commit: 865431320488b4a425171bf618ede7937df6549e Parents: 08d7d95 Author: Franck Cuny <[email protected]> Authored: Wed Mar 26 09:29:34 2014 -0700 Committer: Tomaz Muraus <[email protected]> Committed: Mon Apr 28 15:54:12 2014 +0200 ---------------------------------------------------------------------- CHANGES.rst | 4 + libcloud/dns/drivers/google.py | 343 +++++++++++++++++++ libcloud/dns/providers.py | 2 +- libcloud/dns/types.py | 1 + .../google/get_zone_does_not_exists.json | 13 + .../dns/fixtures/google/managed_zones_1.json | 1 + .../test/dns/fixtures/google/no_record.json | 5 + libcloud/test/dns/fixtures/google/record.json | 17 + .../test/dns/fixtures/google/records_list.json | 1 + .../test/dns/fixtures/google/zone_create.json | 1 + .../test/dns/fixtures/google/zone_list.json | 1 + libcloud/test/dns/test_google.py | 179 ++++++++++ libcloud/test/secrets.py-dist | 2 + 13 files changed, 569 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/86543132/CHANGES.rst ---------------------------------------------------------------------- diff --git a/CHANGES.rst b/CHANGES.rst index 89bf70e..382c987 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -119,6 +119,10 @@ DNS user to create a record with multiple values with a single call. [Tomaz Muraus] +- Add new driver for Google DNS. + (GITHUB-269) + [Franck Cuny] + Changes with Apache Libcloud 0.14.1 ----------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/86543132/libcloud/dns/drivers/google.py ---------------------------------------------------------------------- diff --git a/libcloud/dns/drivers/google.py b/libcloud/dns/drivers/google.py new file mode 100644 index 0000000..aabc783 --- /dev/null +++ b/libcloud/dns/drivers/google.py @@ -0,0 +1,343 @@ +# 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. + +__all__ = [ + 'GoogleDNSDriver' +] + +API_VERSION = 'v1beta1' + +import re +from libcloud.common.google import GoogleResponse, GoogleBaseConnection +from libcloud.common.google import ResourceNotFoundError +from libcloud.dns.types import Provider, RecordType +from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError +from libcloud.dns.base import DNSDriver, Zone, Record + + +class GoogleDNSResponse(GoogleResponse): + pass + + +class GoogleDNSConnection(GoogleBaseConnection): + host = "www.googleapis.com" + responseCls = GoogleDNSResponse + + def __init__(self, user_id, key, secure, auth_type=None, + credential_file=None, project=None): + self.scope = [ + 'https://www.googleapis.com/auth/ndev.clouddns.readwrite' + ] + super(GoogleDNSConnection, self).\ + __init__(user_id, key, secure=secure, auth_type=auth_type, + credential_file=credential_file) + self.request_path = '/dns/%s/projects/%s' % (API_VERSION, project) + + +class GoogleDNSDriver(DNSDriver): + type = Provider.GOOGLE + name = 'Google DNS' + connectionCls = GoogleDNSConnection + website = 'https://cloud.google.com/' + + 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.SPF: 'SPF', + RecordType.SRV: 'SRV', + RecordType.TXT: 'TXT', + } + + def __init__(self, user_id, key, project=None, auth_type=None): + self.auth_type = auth_type + self.project = project + if not self.project: + raise ValueError('Project name must be specified using ' + '"project" keyword.') + super(GoogleDNSDriver, self).__init__(user_id, key) + + def iterate_zones(self): + """ + Return a generator to iterate over available zones. + + :rtype: ``generator`` of :class:`Zone` + """ + return self._get_more('zones') + + def iterate_records(self, zone): + """ + Return a generator to iterate over records for the provided zone. + + :param zone: Zone to list records for. + :type zone: :class:`Zone` + + :rtype: ``generator`` of :class:`Record` + """ + return self._get_more('records', zone=zone) + + 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` + """ + request = '/managedZones/%s' % (zone_id) + + try: + response = self.connection.request(request, method='GET').object + except ResourceNotFoundError: + raise ZoneDoesNotExistError(value='', + driver=self.connection.driver, + zone_id=zone_id) + + return self._to_zone(response) + + 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` + """ + (record_name, record_type) = record_id.split('-') + + params = { + 'name': record_name, + 'type': record_type, + } + + request = '/managedZones/%s/rrsets' % (zone_id) + + try: + response = self.connection.request(request, method='GET', + params=params).object + except ResourceNotFoundError: + raise ZoneDoesNotExistError(value='', + driver=self.connection.driver, + zone_id=zone_id) + + if len(response['rrsets']) > 0: + return self._to_record(response['rrsets'][0], zone_id) + + raise RecordDoesNotExistError(value='', driver=self.connection.driver, + record_id=record_id) + + def create_zone(self, domain, type='master', ttl=None, extra=None): + """ + Create a new zone. + + :param domain: Zone domain name (e.g. example.com.) with a \'.\' + at the end. + :type domain: ``str`` + + :param type: Zone type (master is the only one supported). + :type type: ``str`` + + :param ttl: TTL for new records. (unused) + :type ttl: ``int`` + + :param extra: Extra attributes (driver specific). (optional) + :type extra: ``dict`` + + :rtype: :class:`Zone` + """ + name = None + description = '' + + if extra: + description = extra.get('description') + name = extra.get('name') + + if name is None: + name = self._cleanup_domain(domain) + + data = { + 'dnsName': domain, + 'name': name, + 'description': description, + } + + request = '/managedZones' + response = self.connection.request(request, method='POST', + data=data).object + return self._to_zone(response) + + def create_record(self, name, zone, type, data, extra=None): + """ + Create a new record. + + :param name: Record name fully qualified, with a \'.\' at the end. + :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). + :type data: ``str`` + + :param extra: Extra attributes. (optional) + :type extra: ``dict`` + + :rtype: :class:`Record` + """ + ttl = data.get('ttl', None) + rrdatas = data.get('rrdatas', []) + + data = { + 'additions': [ + { + 'name': name, + 'type': type, + 'ttl': int(ttl), + 'rrdatas': rrdatas, + } + ] + } + request = '/managedZones/%s/changes' % (zone.id) + response = self.connection.request(request, method='POST', + data=data).object + return self._to_record(response['additions'][0], 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`` + """ + request = '/managedZones/%s' % (zone.id) + response = self.connection.request(request, method='DELETE') + return response.success() + + def delete_record(self, record): + """ + Delete a record. + + :param record: Record to delete. + :type record: :class:`Record` + + :rtype: ``bool`` + """ + data = { + 'deletions': [ + { + 'name': record.name, + 'type': record.type, + 'rrdatas': record.data['rrdatas'], + 'ttl': record.data['ttl'] + } + ] + } + request = '/managedZones/%s/changes' % (record.zone.id) + response = self.connection.request(request, method='POST', + data=data) + return response.success() + + def _get_more(self, rtype, **kwargs): + last_key = None + exhausted = False + while not exhausted: + items, last_key, exhausted = self._get_data(rtype, last_key, + **kwargs) + for item in items: + yield item + + def _get_data(self, rtype, last_key, **kwargs): + params = {} + + if last_key: + params['pageToken'] = last_key + + if rtype == 'zones': + request = '/managedZones' + transform_func = self._to_zones + r_key = 'managedZones' + elif rtype == 'records': + zone = kwargs['zone'] + request = '/managedZones/%s/rrsets' % (zone.id) + transform_func = self._to_records + r_key = 'rrsets' + + response = self.connection.request(request, method='GET', + params=params,) + + if response.success(): + nextpage = response.object.get('nextPageToken', None) + items = transform_func(response.object.get(r_key), **kwargs) + exhausted = False if nextpage is not None else True + return items, nextpage, exhausted + else: + return [], None, True + + def _ex_connection_class_kwargs(self): + return {'auth_type': self.auth_type, + 'project': self.project} + + def _to_zones(self, response): + zones = [] + for r in response: + zones.append(self._to_zone(r)) + return zones + + def _to_zone(self, r): + extra = {} + + if 'description' in r: + extra['description'] = r.get('description') + + extra['creationTime'] = r.get('creationTime') + extra['nameServers'] = r.get('nameServers') + + return Zone(id=r['id'], domain=r['dnsName'], + type='master', ttl=0, driver=self, extra=extra) + + def _to_records(self, response, zone): + records = [] + for r in response: + records.append(self._to_record(r, zone)) + return records + + def _to_record(self, r, zone): + record_id = '%s-%s' % (r['name'], r['type']) + return Record(id=record_id, name=r['name'], + type=r['type'], data=r, zone=zone, + driver=self, extra={}) + + def _cleanup_domain(self, domain): + # name can only contain lower case alphanumeric characters and hyphens + domain = re.sub(r'[^a-zA-Z0-9-]', '-', domain) + if domain[-1] == '-': + domain = domain[:-1] + return domain http://git-wip-us.apache.org/repos/asf/libcloud/blob/86543132/libcloud/dns/providers.py ---------------------------------------------------------------------- diff --git a/libcloud/dns/providers.py b/libcloud/dns/providers.py index 53aa724..64483a4 100644 --- a/libcloud/dns/providers.py +++ b/libcloud/dns/providers.py @@ -32,7 +32,7 @@ DRIVERS = { ('libcloud.dns.drivers.route53', 'Route53DNSDriver'), Provider.GANDI: ('libcloud.dns.drivers.gandi', 'GandiDNSDriver'), - + Provider.GOOGLE: ('libcloud.dns.drivers.google', 'GoogleDNSDriver'), # Deprecated Provider.RACKSPACE_US: ('libcloud.dns.drivers.rackspace', 'RackspaceUSDNSDriver'), http://git-wip-us.apache.org/repos/asf/libcloud/blob/86543132/libcloud/dns/types.py ---------------------------------------------------------------------- diff --git a/libcloud/dns/types.py b/libcloud/dns/types.py index a08f1b0..3b3a79e 100644 --- a/libcloud/dns/types.py +++ b/libcloud/dns/types.py @@ -35,6 +35,7 @@ class Provider(object): ROUTE53 = 'route53' HOSTVIRTUAL = 'hostvirtual' GANDI = 'gandi' + GOOGLE = 'google' # Deprecated RACKSPACE_US = 'rackspace_us' http://git-wip-us.apache.org/repos/asf/libcloud/blob/86543132/libcloud/test/dns/fixtures/google/get_zone_does_not_exists.json ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/fixtures/google/get_zone_does_not_exists.json b/libcloud/test/dns/fixtures/google/get_zone_does_not_exists.json new file mode 100644 index 0000000..ddd959d --- /dev/null +++ b/libcloud/test/dns/fixtures/google/get_zone_does_not_exists.json @@ -0,0 +1,13 @@ +{ + "error": { + "errors": [ + { + "domain": "global", + "reason": "notFound", + "message": "The 'parameters.managedZone' resource named '2' does not exist." + } + ], + "code": 404, + "message": "The 'parameters.managedZone' resource named '2' does not exist." + } +} http://git-wip-us.apache.org/repos/asf/libcloud/blob/86543132/libcloud/test/dns/fixtures/google/managed_zones_1.json ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/fixtures/google/managed_zones_1.json b/libcloud/test/dns/fixtures/google/managed_zones_1.json new file mode 100644 index 0000000..240eb10 --- /dev/null +++ b/libcloud/test/dns/fixtures/google/managed_zones_1.json @@ -0,0 +1 @@ +{"kind": "dns#managedZone", "name": "example-com", "nameServers": ["ns-cloud1.googledomains.com.", "ns-cloud2.googledomains.com.", "ns-cloud3.googledomains.com.", "ns-cloud4.googledomains.com."], "creationTime": "2014-03-29T23:06:00.921Z", "dnsName": "example.com.", "id": "1", "description": ""} http://git-wip-us.apache.org/repos/asf/libcloud/blob/86543132/libcloud/test/dns/fixtures/google/no_record.json ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/fixtures/google/no_record.json b/libcloud/test/dns/fixtures/google/no_record.json new file mode 100644 index 0000000..f23c443 --- /dev/null +++ b/libcloud/test/dns/fixtures/google/no_record.json @@ -0,0 +1,5 @@ +{ + "kind": "dns#resourceRecordSetsListResponse", + "rrsets": [ + ] +} http://git-wip-us.apache.org/repos/asf/libcloud/blob/86543132/libcloud/test/dns/fixtures/google/record.json ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/fixtures/google/record.json b/libcloud/test/dns/fixtures/google/record.json new file mode 100644 index 0000000..c1bb807 --- /dev/null +++ b/libcloud/test/dns/fixtures/google/record.json @@ -0,0 +1,17 @@ +{ + "kind": "dns#resourceRecordSetsListResponse", + "rrsets": [ + { + "kind": "dns#resourceRecordSet", + "name": "foo.example.com.", + "type": "A", + "ttl": 21600, + "rrdatas": [ + "ns-cloud-c1.googledomains.com.", + "ns-cloud-c2.googledomains.com.", + "ns-cloud-c3.googledomains.com.", + "ns-cloud-c4.googledomains.com." + ] + } + ] +} http://git-wip-us.apache.org/repos/asf/libcloud/blob/86543132/libcloud/test/dns/fixtures/google/records_list.json ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/fixtures/google/records_list.json b/libcloud/test/dns/fixtures/google/records_list.json new file mode 100644 index 0000000..3c3f2b1 --- /dev/null +++ b/libcloud/test/dns/fixtures/google/records_list.json @@ -0,0 +1 @@ +{"rrsets": [{"rrdatas": ["ns-cloud-d1.googledomains.com.", "ns-cloud-d2.googledomains.com.", "ns-cloud-d3.googledomains.com.", "ns-cloud-d4.googledomains.com."], "kind": "dns#resourceRecordSet", "type": "NS", "name": "example.com.", "ttl": 21600}, {"rrdatas": ["ns-cloud-d1.googledomains.com. dns-admin.google.com. 0 21600 3600 1209600 300"], "kind": "dns#resourceRecordSet", "type": "SOA", "name": "example.com.", "ttl": 21600}, {"rrdatas": ["1.2.3.4"], "kind": "dns#resourceRecordSet", "type": "A", "name": "foo.example.com.", "ttl": 3600}], "kind": "dns#resourceRecordSetsListResponse"} http://git-wip-us.apache.org/repos/asf/libcloud/blob/86543132/libcloud/test/dns/fixtures/google/zone_create.json ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/fixtures/google/zone_create.json b/libcloud/test/dns/fixtures/google/zone_create.json new file mode 100644 index 0000000..bdaafdd --- /dev/null +++ b/libcloud/test/dns/fixtures/google/zone_create.json @@ -0,0 +1 @@ +{"kind": "dns#managedZone", "name": "example-org", "nameServers": ["ns-cloud-b1.googledomains.com.", "ns-cloud-b2.googledomains.com.", "ns-cloud-b3.googledomains.com.", "ns-cloud-b4.googledomains.com."], "creationTime": "2014-03-30T04:44:20.834Z", "dnsName": "example.org.", "id": "3", "description": "new domain for example.org"} http://git-wip-us.apache.org/repos/asf/libcloud/blob/86543132/libcloud/test/dns/fixtures/google/zone_list.json ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/fixtures/google/zone_list.json b/libcloud/test/dns/fixtures/google/zone_list.json new file mode 100644 index 0000000..b3f0fd7 --- /dev/null +++ b/libcloud/test/dns/fixtures/google/zone_list.json @@ -0,0 +1 @@ +{"kind": "dns#managedZonesListResponse", "managedZones": [{"kind": "dns#managedZone", "name": "example-com", "nameServers": ["ns-cloud-e1.googledomains.com.", "ns-cloud-e2.googledomains.com.", "ns-cloud-e3.googledomains.com.", "ns-cloud-e4.googledomains.com."], "creationTime": "2014-03-29T22:45:47.618Z", "dnsName": "example.com.", "id": "1", "description": ""}, {"kind": "dns#managedZone", "name": "example-net", "nameServers": ["ns-cloud-d1.googledomains.com.", "ns-cloud-d2.googledomains.com.", "ns-cloud-d3.googledomains.com.", "ns-cloud-d4.googledomains.com."], "creationTime": "2014-03-29T22:45:46.990Z", "dnsName": "example.net.", "id": "2", "description": ""}]} http://git-wip-us.apache.org/repos/asf/libcloud/blob/86543132/libcloud/test/dns/test_google.py ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/test_google.py b/libcloud/test/dns/test_google.py new file mode 100644 index 0000000..2a4b8c7 --- /dev/null +++ b/libcloud/test/dns/test_google.py @@ -0,0 +1,179 @@ +# 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.utils.py3 import httplib + +from libcloud.dns.types import ZoneDoesNotExistError +from libcloud.dns.types import RecordDoesNotExistError +from libcloud.dns.drivers.google import GoogleDNSDriver +from libcloud.common.google import (GoogleBaseAuthConnection, + GoogleInstalledAppAuthConnection, + GoogleBaseConnection) + +from libcloud.test.common.test_google import GoogleAuthMockHttp +from libcloud.test import MockHttpTestCase, LibcloudTestCase +from libcloud.test.file_fixtures import DNSFileFixtures +from libcloud.test.secrets import DNS_PARAMS_GOOGLE, DNS_KEYWORD_PARAMS_GOOGLE + + +class GoogleTests(LibcloudTestCase): + GoogleBaseConnection._get_token_info_from_file = lambda x: None + GoogleBaseConnection._write_token_info_to_file = lambda x: None + GoogleInstalledAppAuthConnection.get_code = lambda x: '1234' + + def setUp(self): + GoogleDNSMockHttp.test = self + GoogleDNSDriver.connectionCls.conn_classes = (GoogleDNSMockHttp, + GoogleDNSMockHttp) + GoogleBaseAuthConnection.conn_classes = (GoogleAuthMockHttp, + GoogleAuthMockHttp) + GoogleDNSMockHttp.type = None + kwargs = DNS_KEYWORD_PARAMS_GOOGLE.copy() + kwargs['auth_type'] = 'IA' + self.driver = GoogleDNSDriver(*DNS_PARAMS_GOOGLE, **kwargs) + + def test_list_zones(self): + zones = self.driver.list_zones() + self.assertEqual(len(zones), 2) + + def test_list_records(self): + zone = self.driver.list_zones()[0] + records = self.driver.list_records(zone=zone) + self.assertEqual(len(records), 3) + + def test_get_zone(self): + zone = self.driver.get_zone(1) + self.assertEqual(zone.id, '1') + self.assertEqual(zone.domain, 'example.com.') + + def test_get_zone_does_not_exist(self): + GoogleDNSMockHttp.type = 'ZONE_DOES_NOT_EXIST' + + try: + self.driver.get_zone(2) + except ZoneDoesNotExistError: + e = sys.exc_info()[1] + self.assertEqual(e.zone_id, 2) + else: + self.fail('Exception not thrown') + + def test_get_record(self): + GoogleDNSMockHttp.type = 'FILTER_ZONES' + zone = self.driver.list_zones()[0] + record = self.driver.get_record(zone.id, "foo.example.com.-A") + self.assertEqual(record.name, 'foo.example.com.') + self.assertEqual(record.type, 'A') + + def test_get_record_zone_does_not_exist(self): + GoogleDNSMockHttp.type = 'ZONE_DOES_NOT_EXIST' + + try: + self.driver.get_record(2, 'a-a') + except ZoneDoesNotExistError: + e = sys.exc_info()[1] + self.assertEqual(e.zone_id, 2) + else: + self.fail('Exception not thrown') + + def test_get_record_record_does_not_exist(self): + GoogleDNSMockHttp.type = 'RECORD_DOES_NOT_EXIST' + try: + self.driver.get_record(1, "foo-A") + except RecordDoesNotExistError: + e = sys.exc_info()[1] + self.assertEqual(e.record_id, 'foo-A') + else: + self.fail('Exception not thrown') + + def test_create_zone(self): + extra = {'description': 'new domain for example.org'} + zone = self.driver.create_zone('example.org.', extra) + self.assertEqual(zone.domain, 'example.org.') + self.assertEqual(zone.extra['description'], extra['description']) + self.assertEqual(len(zone.extra['nameServers']), 4) + + def test_delete_zone(self): + zone = self.driver.get_zone(1) + res = self.driver.delete_zone(zone) + self.assertTrue(res) + + +class GoogleDNSMockHttp(MockHttpTestCase): + fixtures = DNSFileFixtures('google') + + def _dns_v1beta1_projects_project_name_managedZones(self, method, url, + body, headers): + if method == 'POST': + body = self.fixtures.load('zone_create.json') + else: + body = self.fixtures.load('zone_list.json') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + + def _dns_v1beta1_projects_project_name_managedZones_FILTER_ZONES( + self, method, url, body, headers): + body = self.fixtures.load('zone_list.json') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + + def _dns_v1beta1_projects_project_name_managedZones_1_rrsets_FILTER_ZONES( + self, method, url, body, headers): + body = self.fixtures.load('record.json') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + + def _dns_v1beta1_projects_project_name_managedZones_1_rrsets( + self, method, url, body, headers): + body = self.fixtures.load('records_list.json') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + + def _dns_v1beta1_projects_project_name_managedZones_1(self, method, + url, body, + headers): + if method == 'GET': + body = self.fixtures.load('managed_zones_1.json') + elif method == 'DELETE': + body = None + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + + def _dns_v1beta1_projects_project_name_managedZones_2_ZONE_DOES_NOT_EXIST( + self, method, url, body, headers): + body = self.fixtures.load('get_zone_does_not_exists.json') + return (httplib.NOT_FOUND, body, {}, + httplib.responses[httplib.NOT_FOUND]) + + def _dns_v1beta1_projects_project_name_managedZones_3_ZONE_DOES_NOT_EXIST( + self, method, url, body, headers): + body = self.fixtures.load('get_zone_does_not_exists.json') + return (httplib.NOT_FOUND, body, {}, + httplib.responses[httplib.NOT_FOUND]) + + def _dns_v1beta1_projects_project_name_managedZones_1_RECORD_DOES_NOT_EXIST( + self, method, url, body, headers): + body = self.fixtures.load('managed_zones_1.json') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + + def _dns_v1beta1_projects_project_name_managedZones_1_rrsets_RECORD_DOES_NOT_EXIST( + self, method, url, body, headers): + body = self.fixtures.load('no_record.json') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + + def _dns_v1beta1_projects_project_name_managedZones_2_rrsets_ZONE_DOES_NOT_EXIST( + self, method, url, body, headers): + body = self.fixtures.load('get_zone_does_not_exists.json') + return (httplib.NOT_FOUND, body, {}, + httplib.responses[httplib.NOT_FOUND]) + +if __name__ == '__main__': + sys.exit(unittest.main()) http://git-wip-us.apache.org/repos/asf/libcloud/blob/86543132/libcloud/test/secrets.py-dist ---------------------------------------------------------------------- diff --git a/libcloud/test/secrets.py-dist b/libcloud/test/secrets.py-dist index 773a2c2..030176e 100644 --- a/libcloud/test/secrets.py-dist +++ b/libcloud/test/secrets.py-dist @@ -63,3 +63,5 @@ DNS_PARAMS_RACKSPACE = ('user', 'key') DNS_PARAMS_HOSTVIRTUAL = ('key',) DNS_PARAMS_ROUTE53 = ('access_id', 'secret') DNS_GANDI = ('user', ) +DNS_PARAMS_GOOGLE = ('email_address', 'key') +DNS_KEYWORD_PARAMS_GOOGLE = {'project': 'project_name'}
