diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cdef09..ce2ebed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ possible. This includes the ability to split some zones and not others and even to have partially split zones with some records in the primary zone YAML and others in a split directory. See YamlProvider documentation for more info. +* YamlProvider now supports a `shared_filename` that can be used to add a set of + common records across all zones using the provider. It can be used stand-alone + or in combination with zone files and/or split configs to aid in DRYing up DNS + configs. #### Stuff diff --git a/octodns/provider/yaml.py b/octodns/provider/yaml.py index da6fdf1..3ca7842 100644 --- a/octodns/provider/yaml.py +++ b/octodns/provider/yaml.py @@ -58,6 +58,11 @@ class YamlProvider(BaseProvider): # (optional, default True) split_catchall: true + # Optional filename with record data to be included in all zones + # populated by this provider. Has no effect when used as a target. + # (optional, default null) + shared_filename: null + # Disable loading of the zone .yaml files. # (optional, default False) disable_zonefile: false @@ -172,6 +177,7 @@ class YamlProvider(BaseProvider): supports_root_ns=True, split_extension=False, split_catchall=True, + shared_filename=False, disable_zonefile=False, *args, **kwargs, @@ -179,7 +185,7 @@ class YamlProvider(BaseProvider): klass = self.__class__.__name__ self.log = logging.getLogger(f'{klass}[{id}]') self.log.debug( - '__init__: id=%s, directory=%s, default_ttl=%d, enforce_order=%d, populate_should_replace=%s, supports_root_ns=%s, split_extension=%s, split_catchall=%s, disable_zonefile=%s', + '__init__: id=%s, directory=%s, default_ttl=%d, enforce_order=%d, populate_should_replace=%s, supports_root_ns=%s, split_extension=%s, split_catchall=%s, shared_filename=%s, disable_zonefile=%s', id, directory, default_ttl, @@ -188,6 +194,7 @@ class YamlProvider(BaseProvider): supports_root_ns, split_extension, split_catchall, + shared_filename, disable_zonefile, ) super().__init__(id, *args, **kwargs) @@ -198,6 +205,7 @@ class YamlProvider(BaseProvider): self.supports_root_ns = supports_root_ns self.split_extension = split_extension self.split_catchall = split_catchall + self.shared_filename = shared_filename self.disable_zonefile = disable_zonefile def copy(self): @@ -335,6 +343,9 @@ class YamlProvider(BaseProvider): if not self.disable_zonefile: sources.append(self._zone_sources(zone)) + if self.shared_filename: + sources.append(join(self.directory, self.shared_filename)) + # determinstically order our sources sources.sort() diff --git a/tests/config/split/shared.yaml b/tests/config/split/shared.yaml new file mode 100644 index 0000000..d4c3058 --- /dev/null +++ b/tests/config/split/shared.yaml @@ -0,0 +1,4 @@ +--- +only-shared: + type: TXT + value: Only included when shared file processing is enabled diff --git a/tests/config/split/unit.tests.yaml b/tests/config/split/unit.tests.yaml index e249c43..1a25149 100644 --- a/tests/config/split/unit.tests.yaml +++ b/tests/config/split/unit.tests.yaml @@ -2,4 +2,3 @@ only-zone-file: type: TXT value: Only included when zone file processing is enabled - diff --git a/tests/test_octodns_provider_yaml.py b/tests/test_octodns_provider_yaml.py index a41a417..c289e6a 100644 --- a/tests/test_octodns_provider_yaml.py +++ b/tests/test_octodns_provider_yaml.py @@ -514,6 +514,23 @@ class TestSplitYamlProvider(TestCase): self.assertEqual(1, n) source.disable_zonefile = True + # temporarily enable shared file processing, we should see one extra + # record in the zone + source.shared_filename = 'shared.yaml' + zone_shared = Zone('unit.tests.', []) + source.populate(zone_shared) + self.assertEqual(21, len(zone_shared.records)) + n = len([r for r in zone_shared.records if r.name == 'only-shared']) + self.assertEqual(1, n) + dynamic_zone_shared = Zone('dynamic.tests.', []) + source.populate(dynamic_zone_shared) + self.assertEqual(6, len(dynamic_zone_shared.records)) + n = len( + [r for r in dynamic_zone_shared.records if r.name == 'only-shared'] + ) + self.assertEqual(1, n) + source.shared_filename = None + source.populate(dynamic_zone) self.assertEqual(5, len(dynamic_zone.records)) self.assertFalse(