diff --git a/octodns/processor/filter.py b/octodns/processor/filter.py index 848cb6f..638823d 100644 --- a/octodns/processor/filter.py +++ b/octodns/processor/filter.py @@ -233,8 +233,12 @@ class _ValueBaseFilter(_FilterProcessor): values = [] if hasattr(record, 'values'): values = [value.rdata_text for value in record.values] - else: + elif record.value is not None: values = [record.value.rdata_text] + else: + self.log.warning( + 'value for %s is NoneType, ignoring', record.fqdn + ) if any(value in self.exact for value in values): self.matches(zone, record) @@ -281,6 +285,7 @@ class ValueAllowlistFilter(_ValueBaseFilter, AllowsMixin): ''' def __init__(self, name, allowlist): + self.log = getLogger(f'ValueAllowlistFilter[{name}]') super().__init__(name, allowlist) @@ -317,6 +322,7 @@ class ValueRejectlistFilter(_ValueBaseFilter, RejectsMixin): ''' def __init__(self, name, rejectlist): + self.log = getLogger(f'ValueRejectlistFilter[{name}]') super().__init__(name, rejectlist) diff --git a/tests/test_octodns_processor_filter.py b/tests/test_octodns_processor_filter.py index 29e1ece..84414cf 100644 --- a/tests/test_octodns_processor_filter.py +++ b/tests/test_octodns_processor_filter.py @@ -227,11 +227,18 @@ class TestValueAllowListFilter(TestCase): {'type': 'CNAME', 'ttl': 42, 'value': 'start.a3b444c.end.'}, ) zone.add_record(matchable2) + empty_val = Record.new( + zone, + 'no.values', + {'type': 'CNAME', 'ttl': 42, 'value': None}, + lenient=True, + ) + zone.add_record(empty_val) def test_exact(self): allows = ValueAllowlistFilter('exact', ('matches.example.com.',)) - self.assertEqual(6, len(self.zone.records)) + self.assertEqual(7, len(self.zone.records)) filtered = allows.process_source_zone(self.zone.copy()) self.assertEqual(2, len(filtered.records)) self.assertEqual( @@ -242,7 +249,7 @@ class TestValueAllowListFilter(TestCase): def test_regex(self): allows = ValueAllowlistFilter('exact', ('/^start\\..+\\.end\\.$/',)) - self.assertEqual(6, len(self.zone.records)) + self.assertEqual(7, len(self.zone.records)) filtered = allows.process_source_zone(self.zone.copy()) self.assertEqual(2, len(filtered.records)) self.assertEqual( @@ -297,26 +304,45 @@ class TestValueRejectListFilter(TestCase): {'type': 'CNAME', 'ttl': 42, 'value': 'start.a3b444c.end.'}, ) zone.add_record(matchable2) + empty_val = Record.new( + zone, + 'no.values', + {'type': 'CNAME', 'ttl': 42, 'value': None}, + lenient=True, + ) + zone.add_record(empty_val) def test_exact(self): rejects = ValueRejectlistFilter('exact', ('matches.example.com.',)) - self.assertEqual(6, len(self.zone.records)) + self.assertEqual(7, len(self.zone.records)) filtered = rejects.process_source_zone(self.zone.copy()) - self.assertEqual(4, len(filtered.records)) + self.assertEqual(5, len(filtered.records)) self.assertEqual( - ['bad.compare', 'bad.values', 'first.regex', 'second.regex'], + [ + 'bad.compare', + 'bad.values', + 'first.regex', + 'no.values', + 'second.regex', + ], sorted([r.name for r in filtered.records]), ) def test_regex(self): rejects = ValueRejectlistFilter('exact', ('/^start\\..+\\.end\\.$/',)) - self.assertEqual(6, len(self.zone.records)) + self.assertEqual(7, len(self.zone.records)) filtered = rejects.process_source_zone(self.zone.copy()) - self.assertEqual(4, len(filtered.records)) + self.assertEqual(5, len(filtered.records)) self.assertEqual( - ['bad.compare', 'bad.values', 'good.compare', 'good.values'], + [ + 'bad.compare', + 'bad.values', + 'good.compare', + 'good.values', + 'no.values', + ], sorted([r.name for r in filtered.records]), )