|
|
|
@ -121,6 +121,25 @@ class Manager(object): |
|
|
|
raise ManagerException('Incorrect provider config for {}' |
|
|
|
.format(provider_name)) |
|
|
|
|
|
|
|
self.processors = {} |
|
|
|
for processor_name, processor_config in \ |
|
|
|
self.config.get('processors', {}).items(): |
|
|
|
try: |
|
|
|
_class = processor_config.pop('class') |
|
|
|
except KeyError: |
|
|
|
self.log.exception('Invalid processor class') |
|
|
|
raise ManagerException('Processor {} is missing class' |
|
|
|
.format(processor_name)) |
|
|
|
_class = self._get_named_class('processor', _class) |
|
|
|
kwargs = self._build_kwargs(processor_config) |
|
|
|
try: |
|
|
|
self.processors[processor_name] = _class(processor_name, |
|
|
|
**kwargs) |
|
|
|
except TypeError: |
|
|
|
self.log.exception('Invalid processor config') |
|
|
|
raise ManagerException('Incorrect processor config for {}' |
|
|
|
.format(processor_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,8 +241,8 @@ 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, desired=None, |
|
|
|
lenient=False): |
|
|
|
def _populate_and_plan(self, zone_name, processors, sources, targets, |
|
|
|
desired=None, lenient=False): |
|
|
|
|
|
|
|
self.log.debug('sync: populating, zone=%s, lenient=%s', |
|
|
|
zone_name, lenient) |
|
|
|
@ -248,6 +267,10 @@ class Manager(object): |
|
|
|
'param', source.__class__.__name__) |
|
|
|
source.populate(zone) |
|
|
|
|
|
|
|
self.log.debug('sync: processing, zone=%s', zone_name) |
|
|
|
for processor in processors: |
|
|
|
zone = processor.process(zone) |
|
|
|
|
|
|
|
self.log.debug('sync: planning, zone=%s', zone_name) |
|
|
|
plans = [] |
|
|
|
|
|
|
|
@ -259,7 +282,9 @@ class Manager(object): |
|
|
|
'value': 'provider={}'.format(target.id) |
|
|
|
}) |
|
|
|
zone.add_record(meta, replace=True) |
|
|
|
plan = target.plan(zone) |
|
|
|
# TODO: if someone has overrriden plan already this will be a |
|
|
|
# breaking change so we probably need to try both ways |
|
|
|
plan = target.plan(zone, processors=processors) |
|
|
|
if plan: |
|
|
|
plans.append((target, plan)) |
|
|
|
|
|
|
|
@ -315,6 +340,8 @@ class Manager(object): |
|
|
|
raise ManagerException('Zone {} is missing targets' |
|
|
|
.format(zone_name)) |
|
|
|
|
|
|
|
processors = config.get('processors', []) |
|
|
|
|
|
|
|
if (eligible_sources and not |
|
|
|
[s for s in sources if s in eligible_sources]): |
|
|
|
self.log.info('sync: no eligible sources, skipping') |
|
|
|
@ -332,6 +359,15 @@ class Manager(object): |
|
|
|
|
|
|
|
self.log.info('sync: sources=%s -> targets=%s', sources, targets) |
|
|
|
|
|
|
|
try: |
|
|
|
collected = [] |
|
|
|
for processor in processors: |
|
|
|
collected.append(self.processors[processor]) |
|
|
|
processors = collected |
|
|
|
except KeyError: |
|
|
|
raise ManagerException('Zone {}, unknown processor: {}' |
|
|
|
.format(zone_name, processor)) |
|
|
|
|
|
|
|
try: |
|
|
|
# rather than using a list comprehension, we break this loop |
|
|
|
# out so that the `except` block below can reference the |
|
|
|
@ -358,8 +394,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, processors, |
|
|
|
sources, targets, |
|
|
|
lenient=lenient)) |
|
|
|
|
|
|
|
# Wait on all results and unpack/flatten the plans and store the |
|
|
|
# desired states in case we need them below |
|
|
|
@ -378,6 +415,7 @@ class Manager(object): |
|
|
|
futures.append(self._executor.submit( |
|
|
|
self._populate_and_plan, |
|
|
|
zone_name, |
|
|
|
processors, |
|
|
|
[], |
|
|
|
[self.providers[t] for t in source_config['targets']], |
|
|
|
desired=desired[zone_source], |
|
|
|
@ -518,6 +556,9 @@ class Manager(object): |
|
|
|
if isinstance(source, YamlProvider): |
|
|
|
source.populate(zone) |
|
|
|
|
|
|
|
# TODO: validate |
|
|
|
# processors = config.get('processors', []) |
|
|
|
|
|
|
|
def get_zone(self, zone_name): |
|
|
|
if not zone_name[-1] == '.': |
|
|
|
raise ManagerException('Invalid zone name {}, missing ending dot' |
|
|
|
|