diff --git a/octodns/manager.py b/octodns/manager.py index 40a9c4f..c03398f 100644 --- a/octodns/manager.py +++ b/octodns/manager.py @@ -17,6 +17,7 @@ from sys import stdout import logging from . import __VERSION__ +from .idna import IdnaDict, idna_decode from .provider.base import BaseProvider from .provider.plan import Plan from .provider.yaml import SplitYamlProvider, YamlProvider @@ -114,6 +115,8 @@ class Manager(object): # Read our config file with open(config_file, 'r') as fh: self.config = safe_load(fh, enforce_order=False) + # convert the zones portion of things into an IdnaDict + self.config['zones'] = IdnaDict(self.config['zones']) manager_config = self.config.get('manager', {}) max_workers = ( @@ -341,10 +344,12 @@ class Manager(object): lenient=False, ): + zone = Zone(zone_name, sub_zones=self.configured_sub_zones(zone_name)) self.log.debug( - 'sync: populating, zone=%s, lenient=%s', zone_name, lenient + 'sync: populating, zone=%s, lenient=%s', + zone.decoded_name, + lenient, ) - zone = Zone(zone_name, sub_zones=self.configured_sub_zones(zone_name)) if desired: # This is an alias zone, rather than populate it we'll copy the @@ -368,7 +373,7 @@ class Manager(object): for processor in processors: zone = processor.process_source_zone(zone, sources=sources) - self.log.debug('sync: planning, zone=%s', zone_name) + self.log.debug('sync: planning, zone=%s', zone.decoded_name) plans = [] for target in targets: @@ -431,7 +436,7 @@ class Manager(object): aliased_zones = {} futures = [] for zone_name, config in zones: - self.log.info('sync: zone=%s', zone_name) + self.log.info('sync: zone=%s', idna_decode(zone_name)) if 'alias' in config: source_zone = config['alias'] @@ -602,7 +607,7 @@ class Manager(object): self.log.debug('sync: applying') zones = self.config['zones'] for target, plan in plans: - zone_name = plan.existing.name + zone_name = plan.existing.decoded_name if zones[zone_name].get('always-dry-run', False): self.log.info( 'sync: zone=%s skipping always-dry-run', zone_name diff --git a/octodns/provider/base.py b/octodns/provider/base.py index 78001fa..2a5366c 100644 --- a/octodns/provider/base.py +++ b/octodns/provider/base.py @@ -114,7 +114,7 @@ class BaseProvider(BaseSource): self.log.warning( 'root NS record supported, but no record ' 'is configured for %s', - desired.name, + desired.decoded_name, ) else: if record: @@ -179,7 +179,7 @@ class BaseProvider(BaseSource): self.log.warning('%s; %s', msg, fallback) def plan(self, desired, processors=[]): - self.log.info('plan: desired=%s', desired.name) + self.log.info('plan: desired=%s', desired.decoded_name) existing = Zone(desired.name, desired.sub_zones) exists = self.populate(existing, target=True, lenient=True) @@ -247,7 +247,7 @@ class BaseProvider(BaseSource): self.log.info('apply: disabled') return 0 - zone_name = plan.desired.name + zone_name = plan.desired.decoded_name num_changes = len(plan.changes) self.log.info('apply: making %d changes to %s', num_changes, zone_name) self._apply(plan) diff --git a/octodns/provider/plan.py b/octodns/provider/plan.py index a436483..d9abd92 100644 --- a/octodns/provider/plan.py +++ b/octodns/provider/plan.py @@ -165,8 +165,8 @@ class PlanLogger(_PlanOutput): if plans: current_zone = None for target, plan in plans: - if plan.desired.name != current_zone: - current_zone = plan.desired.name + if plan.desired.decoded_name != current_zone: + current_zone = plan.desired.decoded_name buf.write(hr) buf.write('* ') buf.write(current_zone) @@ -215,8 +215,8 @@ class PlanMarkdown(_PlanOutput): if plans: current_zone = None for target, plan in plans: - if plan.desired.name != current_zone: - current_zone = plan.desired.name + if plan.desired.decoded_name != current_zone: + current_zone = plan.desired.decoded_name fh.write('## ') fh.write(current_zone) fh.write('\n\n') @@ -276,8 +276,8 @@ class PlanHtml(_PlanOutput): if plans: current_zone = None for target, plan in plans: - if plan.desired.name != current_zone: - current_zone = plan.desired.name + if plan.desired.decoded_name != current_zone: + current_zone = plan.desired.decoded_name fh.write('

') fh.write(current_zone) fh.write('

\n') diff --git a/octodns/provider/yaml.py b/octodns/provider/yaml.py index 9ad0934..93b9b12 100644 --- a/octodns/provider/yaml.py +++ b/octodns/provider/yaml.py @@ -147,7 +147,7 @@ class YamlProvider(BaseProvider): self.log = logging.getLogger(f'{klass}[{id}]') self.log.debug( '__init__: id=%s, directory=%s, default_ttl=%d, ' - 'enforce_order=%d, populate_should_replace=%d', + 'nforce_order=%d, populate_should_replace=%d', id, directory, default_ttl, @@ -196,7 +196,7 @@ class YamlProvider(BaseProvider): def populate(self, zone, target=False, lenient=False): self.log.debug( 'populate: name=%s, target=%s, lenient=%s', - zone.name, + zone.decoded_name, target, lenient, ) @@ -207,7 +207,15 @@ class YamlProvider(BaseProvider): return False before = len(zone.records) - filename = join(self.directory, f'{zone.name}yaml') + filename = join(self.directory, f'{zone.decoded_name}yaml') + if not isfile(filename): + idna_filename = join(self.directory, f'{zone.name}yaml') + self.log.warning( + 'populate: "%s" does not exist, falling back to idna version "%s"', + filename, + idna_filename, + ) + filename = idna_filename self._populate_from_file(filename, zone, lenient) self.log.info( @@ -220,7 +228,9 @@ class YamlProvider(BaseProvider): desired = plan.desired changes = plan.changes self.log.debug( - '_apply: zone=%s, len(changes)=%d', desired.name, len(changes) + '_apply: zone=%s, len(changes)=%d', + desired.decoded_name, + len(changes), ) # Since we don't have existing we'll only see creates records = [c.new for c in changes] @@ -248,7 +258,7 @@ class YamlProvider(BaseProvider): self._do_apply(desired, data) def _do_apply(self, desired, data): - filename = join(self.directory, f'{desired.name}yaml') + filename = join(self.directory, f'{desired.decoded_name}yaml') self.log.debug('_apply: writing filename=%s', filename) with open(filename, 'w') as fh: safe_dump(dict(data), fh) diff --git a/octodns/record/__init__.py b/octodns/record/__init__.py index d7c6be4..a7db144 100644 --- a/octodns/record/__init__.py +++ b/octodns/record/__init__.py @@ -164,7 +164,7 @@ class Record(EqualityTupleMixin): def __init__(self, zone, name, data, source=None): self.log.debug( '__init__: zone.name=%s, type=%11s, name=%s', - zone.name, + zone.decoded_name, self.__class__.__name__, name, ) diff --git a/octodns/zone.py b/octodns/zone.py index 1bc3724..999a656 100644 --- a/octodns/zone.py +++ b/octodns/zone.py @@ -13,6 +13,7 @@ from collections import defaultdict from logging import getLogger import re +from .idna import idna_decode from .record import Create, Delete @@ -36,6 +37,7 @@ class Zone(object): raise Exception(f'Invalid zone name {name}, missing ending dot') # Force everything to lowercase just to be safe self.name = str(name).lower() if name else name + self.decoded_name = idna_decode(self.name) self.sub_zones = sub_zones # We're grouping by node, it allows us to efficiently search for # duplicates and detect when CNAMEs co-exist with other records @@ -283,4 +285,4 @@ class Zone(object): return copy def __repr__(self): - return f'Zone<{self.name}>' + return f'Zone<{self.decoded_name}>'