diff --git a/octodns/manager.py b/octodns/manager.py index e640a8d..27b384d 100644 --- a/octodns/manager.py +++ b/octodns/manager.py @@ -162,23 +162,18 @@ class Manager(object): 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]): - # ignore trailing dots, and reverse - pieces = name[:-1].split('.')[::-1] - # where starts out at the top - where = zone_tree - # for all the pieces - for piece in pieces: - try: - where = where[piece] - # our current piece already exists, just point where at - # it's value - except KeyError: - # our current piece doesn't exist, create it - where[piece] = {} - # and then point where at it's newly created value - where = where[piece] + # Sort so we iterate on the deepest nodes first, ensuring if a parent + # zone exists it will be seen after the subzone, thus we can easily + # reparent children to their parent zone from the tree root. + for name in sorted(self.config['zones'].keys(), + key=lambda s: 0 - s.count('.')): + name = name[:-1] + this = {} + for sz in filter( + lambda k: k.endswith(name), set(zone_tree.keys()) + ): + this[sz[:-(len(name) + 1)]] = zone_tree.pop(sz) + zone_tree[name] = this self.zone_tree = zone_tree self.plan_outputs = {} @@ -274,21 +269,14 @@ class Manager(object): return kwargs def configured_sub_zones(self, zone_name): - # Reversed pieces of the zone name - pieces = zone_name[:-1].split('.')[::-1] - # Point where at the root of the tree + name = zone_name[:-1] where = self.zone_tree - # Until we've hit the bottom of this zone - try: - while pieces: - # Point where at the value of our current piece - where = where[pieces.pop(0)] - except KeyError: - self.log.debug('configured_sub_zones: unknown zone, %s, no subs', - zone_name) - return set() - # We're not pointed at the dict for our name, the keys of which will be - # any subzones + while True: + parent = next(filter(lambda k: name.endswith(k), where), None) + if not parent: + break + where = where[parent] + name = name[:-(len(parent) + 1)] sub_zone_names = where.keys() self.log.debug('configured_sub_zones: subs=%s', sub_zone_names) return set(sub_zone_names) diff --git a/octodns/zone.py b/octodns/zone.py index 4cd5e91..41cd6ec 100644 --- a/octodns/zone.py +++ b/octodns/zone.py @@ -68,10 +68,10 @@ class Zone(object): self.hydrate() name = record.name - last = name.split('.')[-1] - if not lenient and last in self.sub_zones: - if name != last: + if not lenient and any(map(lambda sz: name.endswith(sz), + self.sub_zones)): + if name not in self.sub_zones: # it's a record for something under a sub-zone raise SubzoneRecordException(f'Record {record.fqdn} is under ' 'a managed subzone')