Browse Source

Make each alias zone reference its target zone instead of listing all

aliases zones in the target zone configuration
pull/592/head
Jonathan Leroy 5 years ago
parent
commit
f2a6f870b4
No known key found for this signature in database GPG Key ID: 7A0BCBE3934842EA
6 changed files with 87 additions and 12 deletions
  1. +32
    -7
      octodns/manager.py
  2. +3
    -2
      octodns/provider/yaml.py
  3. +3
    -1
      octodns/zone.py
  4. +19
    -0
      tests/config/simple-alias-zone.yaml
  5. +13
    -0
      tests/config/unknown-source-zone.yaml
  6. +17
    -2
      tests/test_octodns_manager.py

+ 32
- 7
octodns/manager.py View File

@ -121,6 +121,23 @@ class Manager(object):
raise ManagerException('Incorrect provider config for {}'
.format(provider_name))
for zone_name, zone_config in self.config['zones'].copy().items():
if 'alias' in zone_config:
source_zone = zone_config['alias']
# Check that the source zone is defined.
if source_zone not in self.config['zones']:
self.log.exception('Invalid alias zone')
raise ManagerException('Invalid alias zone {}: '
'source zone {} does not exist'
.format(zone_name, source_zone))
self.config['zones'][zone_name] = \
self.config['zones'][source_zone]
self.config['zones'][zone_name]['is_alias'] = True
self.config['zones'][zone_name]['file'] = source_zone
else:
self.config['zones'][zone_name]['is_alias'] = False
self.config['zones'][zone_name]['file'] = zone_name
zone_tree = {}
# sort by reversed strings so that parent zones always come first
for name in sorted(self.config['zones'].keys(), key=lambda s: s[::-1]):
@ -222,12 +239,14 @@ class Manager(object):
self.log.debug('configured_sub_zones: subs=%s', sub_zone_names)
return set(sub_zone_names)
def _populate_and_plan(self, zone_name, sources, targets, lenient=False):
def _populate_and_plan(self, zone_name, file, is_alias, sources, targets,
lenient=False):
self.log.debug('sync: populating, zone=%s, lenient=%s',
zone_name, lenient)
self.log.debug('sync: populating, zone=%s, file=%s, is_alias=%s, '
'lenient=%s', zone_name, file, is_alias, lenient)
zone = Zone(zone_name,
sub_zones=self.configured_sub_zones(zone_name))
sub_zones=self.configured_sub_zones(zone_name), file=file,
is_alias=is_alias)
for source in sources:
try:
source.populate(zone, lenient=lenient)
@ -268,6 +287,8 @@ class Manager(object):
futures = []
for zone_name, config in zones:
self.log.info('sync: zone=%s', zone_name)
file = config.get('file')
is_alias = config.get('is_alias')
lenient = config.get('lenient', False)
try:
sources = config['sources']
@ -324,8 +345,9 @@ class Manager(object):
.format(zone_name, target))
futures.append(self._executor.submit(self._populate_and_plan,
zone_name, sources,
targets, lenient=lenient))
zone_name, file, is_alias,
sources, targets,
lenient=lenient))
# Wait on all results and unpack/flatten them in to a list of target &
# plan pairs.
@ -419,7 +441,10 @@ class Manager(object):
def validate_configs(self):
for zone_name, config in self.config['zones'].items():
zone = Zone(zone_name, self.configured_sub_zones(zone_name))
file = config.get('file', False)
is_alias = config.get('is_alias', False)
zone = Zone(zone_name, self.configured_sub_zones(zone_name),
file, is_alias)
try:
sources = config['sources']


+ 3
- 2
octodns/provider/yaml.py View File

@ -139,7 +139,8 @@ class YamlProvider(BaseProvider):
filename)
def populate(self, zone, target=False, lenient=False):
self.log.debug('populate: name=%s, target=%s, lenient=%s', zone.name,
self.log.debug('populate: name=%s, file=%s, is_alias:%s, target=%s, '
'lenient=%s', zone.name, zone.file, zone.is_alias,
target, lenient)
if target:
@ -148,7 +149,7 @@ class YamlProvider(BaseProvider):
return False
before = len(zone.records)
filename = join(self.directory, '{}yaml'.format(zone.name))
filename = join(self.directory, '{}yaml'.format(zone.file))
self._populate_from_file(filename, zone, lenient)
self.log.info('populate: found %s records, exists=False',


+ 3
- 1
octodns/zone.py View File

@ -35,13 +35,15 @@ def _is_eligible(record):
class Zone(object):
log = getLogger('Zone')
def __init__(self, name, sub_zones):
def __init__(self, name, sub_zones, file=None, is_alias=False):
if not name[-1] == '.':
raise Exception('Invalid zone name {}, missing ending dot'
.format(name))
# Force everything to lowercase just to be safe
self.name = text_type(name).lower() if name else name
self.sub_zones = sub_zones
self.file = text_type(file if file else name).lower()
self.is_alias = is_alias
# We're grouping by node, it allows us to efficiently search for
# duplicates and detect when CNAMEs co-exist with other records
self._records = defaultdict(set)


+ 19
- 0
tests/config/simple-alias-zone.yaml View File

@ -0,0 +1,19 @@
manager:
max_workers: 2
providers:
in:
class: octodns.provider.yaml.YamlProvider
directory: tests/config
dump:
class: octodns.provider.yaml.YamlProvider
directory: env/YAML_TMP_DIR
zones:
unit.tests.:
sources:
- in
targets:
- dump
alias.tests.:
alias: unit.tests.

+ 13
- 0
tests/config/unknown-source-zone.yaml View File

@ -0,0 +1,13 @@
manager:
max_workers: 2
providers:
in:
class: octodns.provider.yaml.YamlProvider
directory: tests/config
dump:
class: octodns.provider.yaml.YamlProvider
directory: env/YAML_TMP_DIR
zones:
unit.tests.:
alias: unit-source.tests.

+ 17
- 2
tests/test_octodns_manager.py View File

@ -298,7 +298,8 @@ class TestManager(TestCase):
pass
# This should be ok, we'll fall back to not passing it
manager._populate_and_plan('unit.tests.', [NoLenient()], [])
manager._populate_and_plan('unit.tests.', None, False,
[NoLenient()], [])
class NoZone(SimpleProvider):
@ -307,7 +308,21 @@ class TestManager(TestCase):
# This will blow up, we don't fallback for source
with self.assertRaises(TypeError):
manager._populate_and_plan('unit.tests.', [NoZone()], [])
manager._populate_and_plan('unit.tests.', None, False,
[NoZone()], [])
def test_alias_zones(self):
with TemporaryDirectory() as tmpdir:
environ['YAML_TMP_DIR'] = tmpdir.dirname
Manager(get_config_filename('simple-alias-zone.yaml')) \
.validate_configs()
with self.assertRaises(ManagerException) as ctx:
Manager(get_config_filename('unknown-source-zone.yaml')) \
.validate_configs()
self.assertTrue('Invalid alias zone' in
text_type(ctx.exception))
class TestMainThreadExecutor(TestCase):


Loading…
Cancel
Save