diff --git a/octodns/manager.py b/octodns/manager.py index 104e445..a991b4b 100644 --- a/octodns/manager.py +++ b/octodns/manager.py @@ -294,8 +294,30 @@ class Manager(object): for processor in processors: plan = processor.process_plan(plan, sources=sources, target=target) - if plan: - plans.append((target, plan)) + if not plan: + continue + + # Multi value PTR check + for change in plan.changes: + record = change.new + if not record: + # Delete - doesn't need to be checked + continue + + if record._type == 'PTR' and len(record.values) > 1 and not \ + target.SUPPORTS_MUTLIVALUE_PTR: + self.log.warn('target=%s does not support multi-value PTR ' + 'record %s; using %s as its only answer', + target, record.fqdn, record.value) + # Make a new copy of the record so as to not change a + # potentially shared object + change.new = Record.new(record.zone, record.name, { + 'type': record._type, + 'ttl': record.ttl, + 'value': record.value, + }, source=record.source, lenient=lenient) + + plans.append((target, plan)) # Return the zone as it's the desired state return plans, zone diff --git a/octodns/provider/azuredns.py b/octodns/provider/azuredns.py index c75ef4b..20a9d7b 100644 --- a/octodns/provider/azuredns.py +++ b/octodns/provider/azuredns.py @@ -456,6 +456,7 @@ class AzureProvider(BaseProvider): ''' SUPPORTS_GEO = False SUPPORTS_DYNAMIC = True + SUPPORTS_MUTLIVALUE_PTR = True SUPPORTS = set(('A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'PTR', 'SRV', 'TXT')) diff --git a/octodns/provider/ns1.py b/octodns/provider/ns1.py index 9209ede..3bd0b54 100644 --- a/octodns/provider/ns1.py +++ b/octodns/provider/ns1.py @@ -261,6 +261,7 @@ class Ns1Provider(BaseProvider): ''' SUPPORTS_GEO = True SUPPORTS_DYNAMIC = True + SUPPORTS_MUTLIVALUE_PTR = True SUPPORTS = set(('A', 'AAAA', 'ALIAS', 'CAA', 'CNAME', 'MX', 'NAPTR', 'NS', 'PTR', 'SPF', 'SRV', 'TXT', 'URLFWD')) diff --git a/octodns/record/__init__.py b/octodns/record/__init__.py index 2e17948..77663a5 100644 --- a/octodns/record/__init__.py +++ b/octodns/record/__init__.py @@ -1285,10 +1285,7 @@ class PtrRecord(_ValuesMixin, Record): # multi-value PTR records. @property def value(self): - if len(self.values) == 1: - return self.data['value'] - - raise AttributeError("Multi-value PTR record has no attribute 'value'") + return self.values[0] class SshfpValue(EqualityTupleMixin): diff --git a/octodns/source/base.py b/octodns/source/base.py index 79b5a2a..6094726 100644 --- a/octodns/source/base.py +++ b/octodns/source/base.py @@ -8,6 +8,8 @@ from __future__ import absolute_import, division, print_function, \ class BaseSource(object): + SUPPORTS_MUTLIVALUE_PTR = False + def __init__(self, id): self.id = id if not getattr(self, 'log', False): diff --git a/tests/test_octodns_record.py b/tests/test_octodns_record.py index 2d8e000..886dbfb 100644 --- a/tests/test_octodns_record.py +++ b/tests/test_octodns_record.py @@ -2755,16 +2755,6 @@ class TestRecordValidation(TestCase): self.assertEquals(['PTR value "foo.bar" missing trailing .'], ctx.exception.reasons) - # multi-value requesting single-value - with self.assertRaises(AttributeError) as ctx: - Record.new(self.zone, '', { - 'type': 'PTR', - 'ttl': 600, - 'values': ['foo.com.', 'bar.net.'], - }).value - self.assertEquals("Multi-value PTR record has no attribute 'value'", - text_type(ctx.exception)) - def test_SSHFP(self): # doesn't blow up Record.new(self.zone, '', {