mirror of
https://github.com/github/octodns.git
synced 2024-05-11 05:55:00 +00:00
Make each alias zone reference its target zone instead of listing all
aliases zones in the target zone configuration
This commit is contained in:
@@ -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']
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
tests/config/simple-alias-zone.yaml
Normal file
19
tests/config/simple-alias-zone.yaml
Normal 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
tests/config/unknown-source-zone.yaml
Normal file
13
tests/config/unknown-source-zone.yaml
Normal 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.
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user