From c89664a9f10864007d4f376abb0af342d6232828 Mon Sep 17 00:00:00 2001 From: Piotr Pieprzycki Date: Wed, 15 Jul 2020 15:59:55 +0300 Subject: [PATCH] Add support for long txt records. Skip Alias records --- octodns/provider/azuredns.py | 53 ++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/octodns/provider/azuredns.py b/octodns/provider/azuredns.py index 3d8122a..eb822cb 100644 --- a/octodns/provider/azuredns.py +++ b/octodns/provider/azuredns.py @@ -28,6 +28,25 @@ def unescape_semicolon(s): return s.replace('\\;', ';') + +def azure_chunked_value(val): + CHUNK_SIZE = 255 + val_replace = val.replace('"', '\\"') + value = unescape_semicolon(val_replace) + if len(val) > CHUNK_SIZE: + vs = [value[i:i + CHUNK_SIZE] + for i in range(0, len(value), CHUNK_SIZE)] + else: + vs = value + return vs + + +def azure_chunked_values(s): + values = [] + for v in s: + values.append(azure_chunked_value(v)) + return values + class _AzureRecord(object): '''Wrapper for OctoDNS record for AzureProvider to make dns_client calls. @@ -72,6 +91,8 @@ class _AzureRecord(object): :type return: _AzureRecord ''' + self.log = logging.getLogger('AzureRecord') + self.resource_group = resource_group self.zone_name = record.zone.name[:len(record.zone.name) - 1] self.relative_record_set_name = record.name or '@' @@ -91,6 +112,9 @@ class _AzureRecord(object): self.params = self.params(record.data, key_name, azure_class) self.params['ttl'] = record.ttl + + + def _params_for_A(self, data, key_name, azure_class): try: values = data['values'] @@ -161,12 +185,22 @@ class _AzureRecord(object): values = [data['value']] return {key_name: [azure_class(ptrdname=v) for v in values]} + def _params_for_TXT(self, data, key_name, azure_class): + + params = [] try: # API for TxtRecord has list of str, even for singleton - values = [unescape_semicolon(v) for v in data['values']] + values = [v for v in azure_chunked_values(data['values'])] except KeyError: - values = [unescape_semicolon(data['value'])] - return {key_name: [azure_class(value=[v]) for v in values]} + values = [azure_chunked_value(data['value'])] + + for v in values: + if isinstance(v, list): + params.append(azure_class(value=v)) + else: + params.append(azure_class(value=[v])) + return {key_name: params} + def _equals(self, b): '''Checks whether two records are equal by comparing all fields. @@ -387,17 +421,30 @@ class AzureProvider(BaseProvider): for azrecord in _records: record_name = azrecord.name if azrecord.name != '@' else '' typ = _parse_azure_type(azrecord.type) + + if typ in ['A', 'CNAME']: + if self._check_for_alias(azrecord, typ): + self.log.info( + 'This entry is an Azure alias. Skipping. zone=%s record=%s, type=%s', zone_name, record_name, typ) + continue + data = getattr(self, '_data_for_{}'.format(typ)) data = data(azrecord) data['type'] = typ data['ttl'] = azrecord.ttl record = Record.new(zone, record_name, data, source=self) + zone.add_record(record, lenient=lenient) self.log.info('populate: found %s records, exists=%s', len(zone.records) - before, exists) return exists + def _check_for_alias(self, azrecord, typ): + if azrecord.target_resource.id and not azrecord.arecords and not azrecord.arecords and not azrecord.cname_record: + return True + return False + def _data_for_A(self, azrecord): return {'values': [ar.ipv4_address for ar in azrecord.arecords]}