allow adding subgroups of dicts
authorRalf Jung <post@ralfj.de>
Wed, 14 Oct 2015 20:02:30 +0000 (22:02 +0200)
committerRalf Jung <post@ralfj.de>
Wed, 14 Oct 2015 20:02:30 +0000 (22:02 +0200)
db.example.com.py
zone.py

index daf53276ffcd1775122960df0c0f4bbde32fd1f5..ca620ef4e628c54b22a853caf0fe3873fda31bbe 100644 (file)
@@ -42,4 +42,9 @@ __zone__ = Zone('example.com.', serialfile = 'db.example.com.srl',
         #
         'sub1':         Delegation('ns.example.org.'), # this adds an NS record
         'sub2':         SecureDelegation('ns.example.com.', 12345, Algorithm.RSA_SHA256, Digest.SHA256, '0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF'), # this adds an NS and a DS record
+        #
+        'local': {
+            'one':      Name(one4),
+            'stuff':    CName('one'),
+        },
     })
diff --git a/zone.py b/zone.py
index 1e1251a5fcd2759a982713b68f908401001a962b..5cd0d72cac2b744fd4b807cf49e79b4ffd0434e9 100644 (file)
--- a/zone.py
+++ b/zone.py
@@ -101,6 +101,15 @@ def column_widths(datas: 'Sequence', widths: 'Sequence[int]'):
     # last data point
     return result+str(datas[-1])
 
+def concatenate(root, path):
+    if path == '' or root == '':
+        raise Exception("Empty domain name is not valid")
+    if path == '@':
+        return root
+    if root == '@' or path.endswith('.'):
+        return path
+    return path+"."+root
+
 
 ## Enums
 class Protocol:
@@ -131,15 +140,7 @@ class RR:
         return self
     
     def relativize(self, root):
-        def _relativize(path):
-            if path == '' or root == '':
-                raise Exception("Empty domain name is not valid")
-            if path == '@':
-                return root
-            if root == '@' or path.endswith('.'):
-                return path
-            return path+"."+root
-        return self.mapPath(_relativize)
+        return self.mapPath(lambda path: concatenate(root, path))
     
     def mapTTL(self, f):
         '''Run the current TTL and the recordType through f.'''
@@ -346,6 +347,20 @@ class Zone:
         # be done
         return cur_serial
     
+    @staticmethod
+    def generate_rrs_from_dict(root, domains):
+        for name in sorted(domains.keys(), key=lambda s: s.split('.')):
+            if name.endswith('.'):
+                raise Exception("You are trying to add a record outside of your zone. This is not supported. Use '@' for the zone root.")
+            domain = domains[name]
+            name = concatenate(root, name)
+            if isinstance(domain, dict):
+                for rr in Zone.generate_rrs_from_dict(name, domain):
+                    yield rr
+            else:
+                for rr in domain.generate_rrs():
+                    yield rr.relativize(name)
+    
     def generate_rrs(self) -> 'Iterator':
         # SOA record
         serial = self.inc_serial()
@@ -360,11 +375,8 @@ class Zone:
         for name in self._NS:
             yield NS(name).generate_rr()
         # all the rest
-        for name in sorted(self._domains.keys(), key=lambda s: list(reversed(s.split('.')))):
-            if name.endswith('.'):
-                raise Exception("You are trying to add a record outside of your zone. This is not supported. Use '@' for the zone root.")
-            for rr in self._domains[name].generate_rrs():
-                yield rr.relativize(name)
+        for rr in Zone.generate_rrs_from_dict('@', self._domains):
+            yield rr
     
     def write(self) -> None:
         print(";; {} zone file, generated by zonemaker <https://www.ralfj.de/projects/zonemaker> on {}".format(self._name, datetime.datetime.now()))