Browse Source

Merge pull request #1050 from octodns/yaml-includes

Add support for !include YAML directive
processor-id
Ross McFarland 2 years ago
committed by GitHub
parent
commit
2f4e3e2d8e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 63 additions and 0 deletions
  1. +4
    -0
      CHANGELOG.md
  2. +12
    -0
      octodns/yaml.py
  3. +5
    -0
      tests/config/include/array.yaml
  4. +3
    -0
      tests/config/include/dict.yaml
  5. +1
    -0
      tests/config/include/empty.yaml
  6. +2
    -0
      tests/config/include/include-doesnt-exist.yaml
  7. +8
    -0
      tests/config/include/main.yaml
  8. +2
    -0
      tests/config/include/nested.yaml
  9. +2
    -0
      tests/config/include/subdir/value.yaml
  10. +24
    -0
      tests/test_octodns_yaml.py

+ 4
- 0
CHANGELOG.md View File

@ -15,6 +15,10 @@
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.
* YamlProvider now supports an `!include` directive which enables shared
snippets of config to be reused across many records, e.g. common dynamic rules
across a set of services with service-specific pool values or a unified SFP
value included in TXT records at the root of all zones.
#### Stuff


+ 12
- 0
octodns/yaml.py View File

@ -2,6 +2,8 @@
#
#
from os.path import dirname, join
from natsort import natsort_keygen
from yaml import SafeDumper, SafeLoader, dump, load
from yaml.constructor import ConstructorError
@ -23,7 +25,17 @@ class ContextLoader(SafeLoader):
def _construct(self, node):
return self._pairs(node)[0]
def include(self, node):
mark = self.get_mark()
directory = dirname(mark.name)
filename = join(directory, self.construct_scalar(node))
with open(filename, 'r') as fh:
return safe_load(fh, self.__class__)
ContextLoader.add_constructor('!include', ContextLoader.include)
ContextLoader.add_constructor(
ContextLoader.DEFAULT_MAPPING_TAG, ContextLoader._construct
)


+ 5
- 0
tests/config/include/array.yaml View File

@ -0,0 +1,5 @@
---
- 14
- 15
- 16
- 72

+ 3
- 0
tests/config/include/dict.yaml View File

@ -0,0 +1,3 @@
---
k: v
z: 42

+ 1
- 0
tests/config/include/empty.yaml View File

@ -0,0 +1 @@
---

+ 2
- 0
tests/config/include/include-doesnt-exist.yaml View File

@ -0,0 +1,2 @@
---
key: !include does-not-exist.yaml

+ 8
- 0
tests/config/include/main.yaml View File

@ -0,0 +1,8 @@
---
included-array: !include array.yaml
included-dict: !include dict.yaml
included-empty: !include empty.yaml
included-nested: !include nested.yaml
included-subdir: !include subdir/value.yaml
key: value
name: main

+ 2
- 0
tests/config/include/nested.yaml View File

@ -0,0 +1,2 @@
---
!include subdir/value.yaml

+ 2
- 0
tests/config/include/subdir/value.yaml View File

@ -0,0 +1,2 @@
---
Hello World!

+ 24
- 0
tests/test_octodns_yaml.py View File

@ -62,3 +62,27 @@ class TestYaml(TestCase):
buf = StringIO()
safe_dump({'45a03129': 42, '45a0392a': 43}, buf)
self.assertEqual("---\n45a0392a: 43\n45a03129: 42\n", buf.getvalue())
def test_include(self):
with open('tests/config/include/main.yaml') as fh:
data = safe_load(fh)
self.assertEqual(
{
'included-array': [14, 15, 16, 72],
'included-dict': {'k': 'v', 'z': 42},
'included-empty': None,
'included-nested': 'Hello World!',
'included-subdir': 'Hello World!',
'key': 'value',
'name': 'main',
},
data,
)
with open('tests/config/include/include-doesnt-exist.yaml') as fh:
with self.assertRaises(FileNotFoundError) as ctx:
data = safe_load(fh)
self.assertEqual(
"[Errno 2] No such file or directory: 'tests/config/include/does-not-exist.yaml'",
str(ctx.exception),
)

Loading…
Cancel
Save