From 932774f9d607178f4a900673e94cf538217dfe29 Mon Sep 17 00:00:00 2001 From: Jonathan Leroy Date: Wed, 30 Jul 2025 20:04:38 +0200 Subject: [PATCH] Add new provider parameter "root_ns_warnings" to disable root NS related warnings --- .../fb7aa3d7570d4ee1ae8afb93408bfff4.md | 4 + octodns/provider/base.py | 24 +++-- tests/test_octodns_provider_base.py | 97 +++++++++++++++++++ 3 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 .changelog/fb7aa3d7570d4ee1ae8afb93408bfff4.md diff --git a/.changelog/fb7aa3d7570d4ee1ae8afb93408bfff4.md b/.changelog/fb7aa3d7570d4ee1ae8afb93408bfff4.md new file mode 100644 index 0000000..d332590 --- /dev/null +++ b/.changelog/fb7aa3d7570d4ee1ae8afb93408bfff4.md @@ -0,0 +1,4 @@ +--- +type: minor +--- +Add new provider parameter root_ns_warnings to disable root NS related warnings diff --git a/octodns/provider/base.py b/octodns/provider/base.py index 56091fa..b089ffd 100644 --- a/octodns/provider/base.py +++ b/octodns/provider/base.py @@ -16,21 +16,27 @@ class BaseProvider(BaseSource): update_pcent_threshold=Plan.MAX_SAFE_UPDATE_PCENT, delete_pcent_threshold=Plan.MAX_SAFE_DELETE_PCENT, strict_supports=True, + root_ns_warnings=True, ): super().__init__(id) self.log.debug( '__init__: id=%s, apply_disabled=%s, ' 'update_pcent_threshold=%.2f, ' - 'delete_pcent_threshold=%.2f', + 'delete_pcent_threshold=%.2f, ' + 'strict_supports=%s, ' + 'root_ns_warnings=%s', id, apply_disabled, update_pcent_threshold, delete_pcent_threshold, + strict_supports, + root_ns_warnings, ) self.apply_disabled = apply_disabled self.update_pcent_threshold = update_pcent_threshold self.delete_pcent_threshold = delete_pcent_threshold self.strict_supports = strict_supports + self.root_ns_warnings = root_ns_warnings def _process_desired_zone(self, desired): ''' @@ -151,7 +157,7 @@ class BaseProvider(BaseSource): record = desired.root_ns if self.SUPPORTS_ROOT_NS: - if not record: + if not record and self.root_ns_warnings: self.log.warning( 'root NS record supported, but no record ' 'is configured for %s', @@ -162,7 +168,10 @@ class BaseProvider(BaseSource): # we can't manage root NS records, get rid of it msg = f'root NS record not supported for {record.fqdn}' fallback = 'ignoring it' - self.supports_warn_or_except(msg, fallback) + if self.strict_supports: + raise SupportsException(f'{self.id}: {msg}') + if self.root_ns_warnings: + self.log.warning('%s; %s', msg, fallback) desired.remove_record(record) return desired @@ -191,10 +200,11 @@ class BaseProvider(BaseSource): if existing_root_ns and ( not self.SUPPORTS_ROOT_NS or not desired.root_ns ): - self.log.info( - 'root NS record in existing, but not supported or ' - 'not configured; ignoring it' - ) + if self.root_ns_warnings: + self.log.info( + 'root NS record in existing, but not supported or ' + 'not configured; ignoring it' + ) existing.remove_record(existing_root_ns) return existing diff --git a/tests/test_octodns_provider_base.py b/tests/test_octodns_provider_base.py index 8d9cce6..9ff8179 100644 --- a/tests/test_octodns_provider_base.py +++ b/tests/test_octodns_provider_base.py @@ -29,12 +29,14 @@ class HelperProvider(BaseProvider): extra_changes=[], apply_disabled=False, include_change_callback=None, + root_ns_warnings=True, ): self.__extra_changes = extra_changes self.apply_disabled = apply_disabled self.include_change_callback = include_change_callback self.update_pcent_threshold = Plan.MAX_SAFE_UPDATE_PCENT self.delete_pcent_threshold = Plan.MAX_SAFE_DELETE_PCENT + self.root_ns_warnings = root_ns_warnings def populate(self, zone, target=False, lenient=False): return True @@ -697,6 +699,101 @@ class TestBaseProvider(TestCase): self.assertTrue('Too many deletes' in str(ctx.exception)) + def test_root_ns_warnings(self): + class PopulateProvider(HelperProvider): + SUPPORTS_ROOT_NS = False + + def populate(self, zone, target=False, lenient=False): + zone.add_record( + Record.new( + zone, + '', + {'ttl': 60, 'type': 'NS', 'value': 'dns1.octo.dns.'}, + ), + lenient=lenient, + ) + + provider = HelperProvider([]) + zone = Zone('unit.tests.', []) + + # Provider supports root NS, but no root NS records configured in zone. + provider.SUPPORTS_ROOT_NS = True + with self.assertLogs('HelperProvider', level='DEBUG') as lc: + provider.plan(zone) + self.assertIn( + 'WARNING:HelperProvider:root NS record supported, but no record is ' + 'configured for unit.tests.', + lc.output, + ) + + # No warning logged if "root_ns_warnings" is disabled. + provider.root_ns_warnings = False + with self.assertLogs('HelperProvider', level='DEBUG') as lc: + provider.plan(zone) + self.assertNotIn( + 'WARNING:HelperProvider:root NS record supported, but no record is ' + 'configured for unit.tests.', + lc.output, + ) + + # Provider doesn't supports root NS, but root NS records are configured + # in zone. + provider.SUPPORTS_ROOT_NS = False + provider.root_ns_warnings = True + zone.add_record( + Record.new( + zone, '', {'ttl': 60, 'type': 'NS', 'value': 'ns1.octo.dns.'} + ) + ) + with self.assertLogs('HelperProvider', level='DEBUG') as lc: + provider.plan(zone) + self.assertIn( + 'WARNING:HelperProvider:root NS record not supported for ' + 'unit.tests.; ignoring it', + lc.output, + ) + + # No warning logged if "root_ns_warnings" is disabled. + provider.root_ns_warnings = False + with self.assertLogs('HelperProvider', level='DEBUG') as lc: + provider.plan(zone) + self.assertNotIn( + 'WARNING:HelperProvider:root NS record not supported for ' + 'unit.tests.; ignoring it', + lc.output, + ) + + # When "strict_supports" is enabled, a SupportsException is raised + # instead. + provider.strict_supports = True + with self.assertRaises(SupportsException) as ctx: + provider.plan(zone) + self.assertEqual( + 'test: root NS record not supported for unit.tests.', + str(ctx.exception), + ) + + # Root NS records are present in existing zone, but provider doesn't + # supports root NS. + provider = PopulateProvider([]) + with self.assertLogs('HelperProvider', level='DEBUG') as lc: + provider.plan(zone) + self.assertIn( + 'INFO:HelperProvider:root NS record in existing, but not supported ' + 'or not configured; ignoring it', + lc.output, + ) + + # No warning logged if "root_ns_warnings" is disabled. + provider.root_ns_warnings = False + with self.assertLogs('HelperProvider', level='DEBUG') as lc: + provider.plan(zone) + self.assertNotIn( + 'INFO:HelperProvider:root NS record in existing, but not supported ' + 'or not configured; ignoring it', + lc.output, + ) + def test_supports_warn_or_except(self): class MinimalProvider(BaseProvider): SUPPORTS = set()