diff --git a/octodns/.vscode/settings.json b/octodns/.vscode/settings.json new file mode 100644 index 0000000..38e6c1e --- /dev/null +++ b/octodns/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.pythonPath": "C:\\Python27\\python.exe" +} \ No newline at end of file diff --git a/octodns/provider/.vscode/settings.json b/octodns/provider/.vscode/settings.json index 7a73a41..88322cc 100644 --- a/octodns/provider/.vscode/settings.json +++ b/octodns/provider/.vscode/settings.json @@ -1,2 +1,3 @@ { + "python.pythonPath": "C:\\Python27\\python.exe" } \ No newline at end of file diff --git a/octodns/provider/fastdns.py b/octodns/provider/fastdns.py index de8e7d6..bcb1f32 100644 --- a/octodns/provider/fastdns.py +++ b/octodns/provider/fastdns.py @@ -1,417 +1,582 @@ -# -# -# - -from __future__ import absolute_import, division, print_function, \ - unicode_literals - -## octodns specfic imports: -import requests -from akamai.edgegrid import EdgeGridAuth -from urlparse import urljoin -import json -from collections import defaultdict - -import logging -from functools import reduce -from ..record import Record -from .base import BaseProvider - -TESTING = True - -class AkamaiClientException(Exception): - - _errorMessages = { - 400: "400: Bad request", - 403: "403: Access is forbidden", - 404: "404: Resource not found", - 405: "405: Method not supported", - 406: "406: Not Acceptable", - 409: "409: Request not allowed due to conflict with current state of resource", - 415: "415: Unsupported media type", - 422: "422: Request body contains an error preventing processing", - 500: "500: Internal server error" - } - - def __init__(self, code): - message = self._errorMessages.get(code) - super(AkamaiClientException, self).__init__(message) - - -class _AkamaiRecord(object): - pass - - -class AkamaiClient(object): - - def __init__(self, _client_secret, _host, _access_token, _client_token): - - self.base = "https://" + _host + "/config-dns/v2/" - self.basev1 = "https://" + _host + "/config-dns/v1/" - - sess = requests.Session() - sess.auth = EdgeGridAuth( - client_token=_client_token, - client_secret=_client_secret, - access_token=_access_token - ) - self._sess = sess - - - def _writePrepped(self, prepped): - filename = str(prepped.method) + ".json" - f = open(filename, 'w') - - f.write("headers: \n") - f.write(str(prepped.headers)) - f.write("\nbody: \n") - f.write(str(prepped.body)) - f.write("\nhooks:\n") - f.write(str(prepped.hooks)) - f.write("\nmethod: " + str(prepped.method)) - f.write("\nurl: " + str(prepped.url) + "\n") - - f.close() - - def _request(self, method, path, params=None, data=None, v1=False): - - url = urljoin(self.base, path) - if v1: - url = urljoin(self.basev1, path) - - if (TESTING): - print("testing mode") - print(method, url) - req = requests.Request(method, url, params=params, json=data) - prepped = req.prepare() - self._writePrepped(prepped) - - resp = self._sess.request(method, url, params=params, json=data) - - - if resp.status_code > 299: - raise AkamaiClientException(resp.status_code) - - resp.raise_for_status() - - - return resp - - - def record_get(self, zone, name, record_type): - - path = 'zones/{}/names/{}/types/{}'.format(zone, name, record_type) - result = self._request('GET', path) - - return result - - def record_create(self, zone, name, record_type, params): - path = 'zones/{}/names/{}/types/{}'.format(zone, name, record_type) - result = self._request('POST', path, data=params) - - return result - - def record_delete(self, zone, name, record_type): - path = 'zones/{}/names/{}/types/{}'.format(zone, name, record_type) - result = self._request('DELETE', path) - - if result.status_code == 204: - print ("successfully deleted ", path) - - return result - - def record_replace(self, zone, name, record_type, params): - path = 'zones/{}/names/{}/types/{}'.format(zone, name, record_type) - result = self._request('PUT', path, data=params) - - return result - - def zones_get(self, contractIds=None, page=None, pageSize=None, search=None, - showAll="true", sortBy="zone", types=None): - path = 'zones' - - params = { - 'contractIds': contractIds, - 'page': page, - 'pageSize': pageSize, - 'search': search, - 'showAll': showAll, - 'sortBy': sortBy, - 'types': types - } - - result = self._request('GET', path, params=params) - - return result - - def zone_recordset_get(self, zone, page=None, pageSize=30, search=None, - showAll="true", sortBy="name", types=None): - - - params = { - 'page': page, - 'pageSize': pageSize, - 'search': search, - 'showAll': showAll, - 'sortBy': sortBy, - 'types': types - } - - path = 'zones/{}/recordsets'.format(zone) - result = self._request('GET', path, params=params) - - return result - - def records(self, zone_name): - - recordset = self.zone_recordset_get(zone_name, showAll="true").json().get("recordsets") - - return recordset - - def master_zone_file_get(self, zone): - - path = 'zones/{}/zone-file'.format(zone) - - try: - result = self._request('GET', path) - - except AkamaiClientException as e: - # not working with API v2, API v1 fallback - path = 'zones/{}'.format(zone) - result = self._request('GET', path, v1=True) - print("Using API v1 fallback") - print("(Probably Ignore)", e.message) - - return result - - -class AkamaiProvider(BaseProvider): - - SUPPORTS_GEO = False - SUPPORTS_DYNAMIC = False - SUPPORTS = set(('A', 'AAAA', 'CNAME', 'MX', 'NAPTR', 'NS', 'PTR', 'SPF', - 'SRV', 'SSHFP', 'TXT')) - - - def __init__(self, id, client_secret, host, access_token, client_token, - *args, **kwargs): - - self.log = logging.getLogger('AkamaiProvider[{}]'.format(id)) - self.log.debug('__init__: id=%s, ') - super(AkamaiProvider, self).__init__(id, *args, **kwargs) - - - self._dns_client = AkamaiClient(client_secret, host, access_token, client_token) - - - self._zone_records = {} - - - def zone_records(self, zone): - if zone.name not in self._zone_records: - try: - self._zone_records[zone.name] = self._dns_client.records(zone.name[:-1]) - - except AkamaiClientException: - return [] - - return self._zone_records[zone.name] - - - def populate(self, zone, target=False, lenient=False): - self.log.debug('populate: name=%s, target=%s, lenient=%s', zone.name, target, lenient) - - # self._test(zone) - - values = defaultdict(lambda: defaultdict(list)) - - for record in self.zone_records(zone): - _type=record['type'] - if _type not in self.SUPPORTS: - continue - elif _type == 'TXT' and record['content'].startswith('ALIAS for'): - # ALIAS has a "ride along" TXT record with 'ALIAS for XXXX', - # we're ignoring it - continue - values[record['name']][record['type']].append(record) - - - - def _test(self, zone) : - - zone_name = zone.name[:len(zone.name)-1] - - record_name = "octo.basir-test.com" - record_type = "A" - params = { - "name": "octo.basir-test.com", - "type": "A", - "ttl": 300, - "rdata": [ - "10.0.0.2", - "10.0.0.3" - ] - } - repl_params = { - "name": "octo.basir-test.com", - "type": "A", - "ttl": 300, - "rdata": [ - "99.99.99.99", - "10.0.0.3", - "1.2.3.4" - ] - } - - - # print("\n\nRunning test: record get..........\n") - # self._test_record_get(zone_name, "test.basir-test.com", record_type) - # print("\n\nRunning test: record create..........\n") - # self._test_record_create(zone_name, record_name, record_type, params) - # print("\n\nRunning test: record replace..........\n") - # self._test_record_replace(zone_name, record_name, record_type, repl_params) - # print("\n\nRunning test: record delete..........\n") - # self._test_record_delete(zone_name, record_name, record_type) - - # print("\n\nRunning test: zones get..........\n") - # self._test_zones_get() - - print("\n\nRunning test: zone recordset get..........\n") - self._test_zones_recordset_get(zone_name) - - # print("\n\nRunning test: Master Zone File get..........\n") - # self._test_master_zone_file_get(zone_name) - - return - - def _test_record_get(self, zone_name, record_name, record_type): - try: - get = self._dns_client.record_get(zone_name, record_name, record_type) - except AkamaiClientException as e: - print ("record get test failed") - print (e.message) - - else: - print("record get test result: ") - print(json.dumps(get.json(), indent=4, separators=(',', ': '))) - - return - - def _test_record_delete(self, zone_name, record_name, record_type): - - try: - delete = self._dns_client.record_delete(zone_name, record_name, record_type) - except AkamaiClientException as e: - print("delete failed") - print(e.message) - return - - - try: - self._dns_client.record_get(zone_name, record_name, record_type) - except AkamaiClientException as e: - print("get on record failed as expected, since record was succesfully deleted") - print ("(Probably Ignore):", e.message) - print ("delete status:", delete.status_code) - else: - print("unexpected condition in test delete") - - return - - def _test_record_create(self, zone_name, record_name, record_type, params): - - try: - create = self._dns_client.record_create(zone_name, record_name, record_type, params) - except AkamaiClientException as e: - print ("create unsuccessful, presumably because it already exists") - print ("(Probably Ignore)", e.message) - else: - print("initial create of", create.json().get("name"), "succesful: ", create.status_code) - - return - - def _test_record_replace(self, zone_name, record_name, record_type, params): - - ## create record to be replaced, if it doesn't already exist - try: - old_params = { - "name": record_name, - "type": record_type, - "ttl": 300, - "rdata": [ - "10.0.0.2", - "10.0.0.3" - ] - } - create = self._dns_client.record_create(zone_name, record_name, record_type, old_params) - except AkamaiClientException as e: - print ("initial create unsuccessful, presumably because it already exists") - print ("(Probably Ignore)", e.message) - else: - print("initial create of record to be replaced", create.json().get("name"), "succesful: ", create.status_code) - - - ## test replace - try: - replace = self._dns_client.record_replace(zone_name, record_name, record_type, params) - except AkamaiClientException as e: - print("replace failed") - print(e.message) - return - else: - try: - record = self._dns_client.record_get(zone_name, record_name, record_type) - except AkamaiClientException as e: - print("retrieval in replacement failed") - print(e.message) - else: - new_data = record.json() - - if (new_data != params): - print("replace failed, records don't match") - print("current data:") - print(new_data) - print("expected data:") - print(params) - - else: - print("replace succesful") - print("replace status:", replace.status_code) - - def _test_zones_get(self): - try: - zonesList = self._dns_client.zones_get() - except AkamaiClientException as e: - print ("zones get test failed") - print (e.message) - - else: - print("zones list: ") - print(json.dumps(zonesList.json(), indent=4, separators=(',', ': '))) - - return - - def _test_zones_recordset_get(self, zone_name): - try: - zoneRecordset = self._dns_client.zone_recordset_get(zone_name) - except AkamaiClientException as e: - print("zone recordset retrieval test failed") - print (e.message) - else: - print("zone recordset: ") - print(json.dumps(zoneRecordset.json(), indent=4, separators=(',', ': '))) - return - - def _test_master_zone_file_get(self, zone_name): - try: - mzf = self._dns_client.master_zone_file_get(zone_name) - - except AkamaiClientException as e: - print("MZF retrieval test failed") - print (e.message) - - else: - print("Master Zone File:") - print(json.dumps(mzf.json(), indent=4, separators=(',', ': '))) - - return +# +# +# + +from __future__ import absolute_import, division, print_function, \ + unicode_literals + +## octodns specfic imports: +import requests +from akamai.edgegrid import EdgeGridAuth +from urlparse import urljoin +import json +from collections import defaultdict + +import logging +from ..record import Record +from .base import BaseProvider + +TESTING = True + +class AkamaiClientException(Exception): + + _errorMessages = { + 400: "400: Bad request", + 403: "403: Access is forbidden", + 404: "404: Resource not found", + 405: "405: Method not supported", + 406: "406: Not Acceptable", + 409: "409: Request not allowed due to conflict with current state of resource", + 415: "415: Unsupported media type", + 422: "422: Request body contains an error preventing processing", + 500: "500: Internal server error" + } + + def __init__(self, code): + message = self._errorMessages.get(code) + super(AkamaiClientException, self).__init__(message) + + +class _AkamaiRecord(object): + pass + + +class AkamaiClient(object): + + def __init__(self, _client_secret, _host, _access_token, _client_token): + + self.base = "https://" + _host + "/config-dns/v2/" + self.basev1 = "https://" + _host + "/config-dns/v1/" + + sess = requests.Session() + sess.auth = EdgeGridAuth( + client_token=_client_token, + client_secret=_client_secret, + access_token=_access_token + ) + self._sess = sess + + + def _writePrepped(self, prepped): + filename = str(prepped.method) + ".json" + f = open(filename, 'w') + + f.write("headers: \n") + f.write(str(prepped.headers)) + f.write("\nbody: \n") + f.write(str(prepped.body)) + f.write("\nhooks:\n") + f.write(str(prepped.hooks)) + f.write("\nmethod: " + str(prepped.method)) + f.write("\nurl: " + str(prepped.url) + "\n") + + f.close() + + def _request(self, method, path, params=None, data=None, v1=False): + + url = urljoin(self.base, path) + if v1: + url = urljoin(self.basev1, path) + + if (TESTING): + print("testing mode") + print(method, url) + req = requests.Request(method, url, params=params, json=data) + prepped = req.prepare() + self._writePrepped(prepped) + + resp = self._sess.request(method, url, params=params, json=data) + + + if resp.status_code > 299: + raise AkamaiClientException(resp.status_code) + + resp.raise_for_status() + + + return resp + + + def record_get(self, zone, name, record_type): + + path = 'zones/{}/names/{}/types/{}'.format(zone, name, record_type) + result = self._request('GET', path) + + return result + + def record_create(self, zone, name, record_type, params): + path = 'zones/{}/names/{}/types/{}'.format(zone, name, record_type) + result = self._request('POST', path, data=params) + + return result + + def record_delete(self, zone, name, record_type): + path = 'zones/{}/names/{}/types/{}'.format(zone, name, record_type) + result = self._request('DELETE', path) + + if result.status_code == 204: + print ("successfully deleted ", path) + + return result + + def record_replace(self, zone, name, record_type, params): + path = 'zones/{}/names/{}/types/{}'.format(zone, name, record_type) + result = self._request('PUT', path, data=params) + + return result + + def zones_get(self, contractIds=None, page=None, pageSize=None, search=None, + showAll="true", sortBy="zone", types=None): + path = 'zones' + + params = { + 'contractIds': contractIds, + 'page': page, + 'pageSize': pageSize, + 'search': search, + 'showAll': showAll, + 'sortBy': sortBy, + 'types': types + } + + result = self._request('GET', path, params=params) + + return result + + def zone_recordset_get(self, zone, page=None, pageSize=30, search=None, + showAll="true", sortBy="name", types=None): + + + params = { + 'page': page, + 'pageSize': pageSize, + 'search': search, + 'showAll': showAll, + 'sortBy': sortBy, + 'types': types + } + + path = 'zones/{}/recordsets'.format(zone) + result = self._request('GET', path, params=params) + + + return result + + def records(self, zone_name): + + resp = self.zone_recordset_get(zone_name, showAll="true") + recordset = resp.json().get("recordsets") + + return recordset + + def master_zone_file_get(self, zone): + + path = 'zones/{}/zone-file'.format(zone) + + try: + result = self._request('GET', path) + + except AkamaiClientException as e: + # not working with API v2, API v1 fallback + path = 'zones/{}'.format(zone) + result = self._request('GET', path, v1=True) + print("Using API v1 fallback") + print("(Probably Ignore)", e.message) + + return result + + +class AkamaiProvider(BaseProvider): + + SUPPORTS_GEO = False + SUPPORTS_DYNAMIC = False + + SUPPORTS = set(('A', 'AAAA', 'CNAME', 'MX', 'NAPTR', 'NS', 'PTR', 'SPF', + 'SRV', 'SSHFP', 'TXT')) + # SUPPORTS = set(('NAPTR', 'MX')) + + def __init__(self, id, client_secret, host, access_token, client_token, + *args, **kwargs): + + self.log = logging.getLogger('AkamaiProvider[{}]'.format(id)) + self.log.debug('__init__: id=%s, ') + super(AkamaiProvider, self).__init__(id, *args, **kwargs) + + self._dns_client = AkamaiClient(client_secret, host, access_token, + client_token) + + self._zone_records = {} + + + def zone_records(self, zone): + """ returns records for a zone, finds it if not present, or + returns empty if doesnt exist + """ + if zone.name not in self._zone_records: + try: + name = zone.name[:-1] + self._zone_records[zone.name] = self._dns_client.records(name) + + except AkamaiClientException: + return [] + + + # fileName = "zone_records_for_" + zone.name +".json" + # path = "/mnt/c/Users/bajamil/Desktop/" + fileName + # f = open(path, 'w') + # f.write(json.dumps(self._zone_records[zone.name], indent=4, separators=(',', ': '))) + # f.close() + + return self._zone_records[zone.name] + + + def populate(self, zone, target=False, lenient=False): + self.log.debug('populate: name=%s', zone.name) + # self._test(zone) + + values = defaultdict(lambda: defaultdict(list)) + for record in self.zone_records(zone): + + _type =record.get('type') + _name = record.get('name') + + if _type not in self.SUPPORTS: + continue + + values[_name][_type].append(record) + + + + fileName = "values_for_" + zone.name +".json" + path = "/mnt/c/Users/bajamil/Desktop/" + fileName + f = open(path, 'w') + f.write(json.dumps(values, indent=4, separators=(',', ': '))) + f.close() + + return ### + before = len(zone.records) + for name, types in values.items(): + for _type, records in types.items(): + data_for = getattr(self, '_data_for_{}'.format(_type)) + + data = data_for(_type, records) + + print() + print ("data processed for", name, ":") + print (json.dumps(data, indent=4, separators=(',', ': '))) + print() + + record = Record.new(zone, name, data_for(_type, records), source=self, lenient=lenient) + + + exists = zone.name in self._zone_records + self.log.info('populate: found %s records, exists=%s', + len(zone.records) - before, exists) + + return exists + + + def _data_for_multiple(self, _type, records): + + return { + 'ttl': records[0]['ttl'], + 'type': _type, + 'values': [r['rdata'][0] for r in records] + } + + _data_for_A = _data_for_multiple + _data_for_AAAA = _data_for_multiple + _data_for_SPF = _data_for_multiple + + def _data_for_CNAME(self, _type, records): + record = records[0] + value = record['rdata'][0] + if (value[-1] != "."): + value = '{}.'.format(value) + + return { + 'ttl': records[0]['ttl'], + 'type': _type, + 'value': value + } + + def _data_for_MX(self, _type, records): + values = [] + for record in records: + print ("MX record: ", record) + values.append({ + 'preference': record['priority'], + 'exchange': '{}.'.format(record['rdata'][0]) + }) + return { + 'ttl': records[0]['ttl'], + 'type': _type, + 'values': values + } + + def _data_for_NAPTR(self, _type, records): + print ("NAPTR Record") + print(json.dumps(records, indent=4, separators=(',', ': '))) + values = [] + for record in records: + order, preference, flags, service, regexp, replacement = \ + record['rdata'][0].split(' ', 5) + + values.append({ + 'flags': flags[1:-1], + 'order': order, + 'preference': preference, + 'regexp': regexp[1:-1], + 'replacement': replacement, + 'service': service[1:-1] + }) + return { + 'type': _type, + 'ttl': records[0]['ttl'], + 'values': values + } + + def _data_for_NS(self, _type, records): + values = [] + for record in records: + rdata = record['rdata'] + for content in rdata: + if content[-1] != '.': + content = '{}.'.format(content) + values.append(content) + return { + 'ttl': records[0]['ttl'], + 'type': _type, + 'value': values + } + + def _data_for_PTR(self, _type, records): + return self._data_for_multiple(_type, records[0]) + + # rdata[0]? + def _data_for_SRV(self, _type, records): + values = [] + for record in records: + weight, port, target = record['rdata'].split(', ', 2) + values.append({ + 'port': port, + 'priority': record['priority'], + 'target': '{}.'.format(target), + 'weight': weight + }) + return { + 'type': _type, + 'ttl': records[0]['ttl'], + 'values': values + } + + # rdata[0]? + def _data_for_SSHFP(self, _type, records): + values = [] + algorithm, fp_type, fingerprint = record['rdata'].split(' ', 2) + values.append({ + 'algorithm': algorithm, + 'fingerprint': fingerprint, + 'fingerprint_type': fp_type + }) + + return { + 'type': _type, + 'ttl': records[0]['ttl'], + 'values': values + } + + def _data_for_TXT(self, _type, records): + values = [] + for r in records: + for content in r['rdata']: + values.append(content.replace(';', '\\;')) + + return { + 'ttl': records[0]['ttl'], + 'type': _type, + 'values': values + # 'values': [r['rdata'][0].replace(';', '\\;') for r in records] + } + + + + + def _test(self, zone) : + + zone_name = zone.name[:len(zone.name)-1] + + record_name = "octo.basir-test.com" + record_type = "A" + params = { + "name": "octo.basir-test.com", + "type": "A", + "ttl": 300, + "rdata": [ + "10.0.0.2", + "10.0.0.3" + ] + } + repl_params = { + "name": "octo.basir-test.com", + "type": "A", + "ttl": 300, + "rdata": [ + "99.99.99.99", + "10.0.0.3", + "1.2.3.4" + ] + } + + + # print("\n\nRunning test: record get..........\n") + # self._test_record_get(zone_name, "test.basir-test.com", record_type) + # print("\n\nRunning test: record create..........\n") + # self._test_record_create(zone_name, record_name, record_type, params) + # print("\n\nRunning test: record replace..........\n") + # self._test_record_replace(zone_name, record_name, record_type, repl_params) + # print("\n\nRunning test: record delete..........\n") + # self._test_record_delete(zone_name, record_name, record_type) + + # print("\n\nRunning test: zones get..........\n") + # self._test_zones_get() + + print("\n\nRunning test: zone recordset get..........\n") + self._test_zones_recordset_get(zone_name) + + # print("\n\nRunning test: Master Zone File get..........\n") + # self._test_master_zone_file_get(zone_name) + + return + + def _test_record_get(self, zone_name, record_name, record_type): + try: + get = self._dns_client.record_get(zone_name, record_name, record_type) + except AkamaiClientException as e: + print ("record get test failed") + print (e.message) + + else: + print("record get test result: ") + print(json.dumps(get.json(), indent=4, separators=(',', ': '))) + + return + + def _test_record_delete(self, zone_name, record_name, record_type): + + try: + delete = self._dns_client.record_delete(zone_name, record_name, record_type) + except AkamaiClientException as e: + print("delete failed") + print(e.message) + return + + + try: + self._dns_client.record_get(zone_name, record_name, record_type) + except AkamaiClientException as e: + print("get on record failed as expected, since record was succesfully deleted") + print ("(Probably Ignore):", e.message) + print ("delete status:", delete.status_code) + else: + print("unexpected condition in test delete") + + return + + def _test_record_create(self, zone_name, record_name, record_type, params): + + try: + create = self._dns_client.record_create(zone_name, record_name, record_type, params) + except AkamaiClientException as e: + print ("create unsuccessful, presumably because it already exists") + print ("(Probably Ignore)", e.message) + else: + print("initial create of", create.json().get("name"), "succesful: ", create.status_code) + + return + + def _test_record_replace(self, zone_name, record_name, record_type, params): + + ## create record to be replaced, if it doesn't already exist + try: + old_params = { + "name": record_name, + "type": record_type, + "ttl": 300, + "rdata": [ + "10.0.0.2", + "10.0.0.3" + ] + } + create = self._dns_client.record_create(zone_name, record_name, record_type, old_params) + except AkamaiClientException as e: + print ("initial create unsuccessful, presumably because it already exists") + print ("(Probably Ignore)", e.message) + else: + print("initial create of record to be replaced", create.json().get("name"), "succesful: ", create.status_code) + + + ## test replace + try: + replace = self._dns_client.record_replace(zone_name, record_name, record_type, params) + except AkamaiClientException as e: + print("replace failed") + print(e.message) + return + else: + try: + record = self._dns_client.record_get(zone_name, record_name, record_type) + except AkamaiClientException as e: + print("retrieval in replacement failed") + print(e.message) + else: + new_data = record.json() + + if (new_data != params): + print("replace failed, records don't match") + print("current data:") + print(new_data) + print("expected data:") + print(params) + + else: + print("replace succesful") + print("replace status:", replace.status_code) + + def _test_zones_get(self): + try: + zonesList = self._dns_client.zones_get() + except AkamaiClientException as e: + print ("zones get test failed") + print (e.message) + + else: + print("zones list: ") + print(json.dumps(zonesList.json(), indent=4, separators=(',', ': '))) + + return + + def _test_zones_recordset_get(self, zone_name): + try: + zoneRecordset = self._dns_client.zone_recordset_get(zone_name) + except AkamaiClientException as e: + print("zone recordset retrieval test failed") + print (e.message) + else: + print("zone recordset: ") + print(json.dumps(zoneRecordset.json(), indent=4, separators=(',', ': '))) + return + + def _test_master_zone_file_get(self, zone_name): + try: + mzf = self._dns_client.master_zone_file_get(zone_name) + + except AkamaiClientException as e: + print("MZF retrieval test failed") + print (e.message) + + else: + print("Master Zone File:") + print(json.dumps(mzf.json(), indent=4, separators=(',', ': '))) + + return