]> mj.ucw.cz Git - pynsc.git/commitdiff
Enter NscZoneConfig
authorMartin Mares <mj@ucw.cz>
Sat, 20 Apr 2024 19:23:53 +0000 (21:23 +0200)
committerMartin Mares <mj@ucw.cz>
Sat, 20 Apr 2024 19:23:53 +0000 (21:23 +0200)
nsc.py

diff --git a/nsc.py b/nsc.py
index ca4c33ce16844ff9345d2a21e4a0b9b9e847ef0d..b734250a64308a5e90af83f76b6ba55c81d2c38e 100755 (executable)
--- a/nsc.py
+++ b/nsc.py
@@ -35,11 +35,11 @@ class NscNode:
         self.nsc_zone = nsc_zone
         self.name = name
         self.node = nsc_zone.zone.find_node(name, create=True)
-        self._ttl = int(nsc_zone.min_ttl.total_seconds())
+        self._ttl = nsc_zone._min_ttl
 
     def ttl(self, *args, **kwargs) -> Self:
         if not args and not kwargs:
-            self._ttl = int(self.nsc_zone.min_ttl.total_seconds())
+            self._ttl = self.nsc_zone._min_ttl
         else:
             self._ttl = int(timedelta(*args, **kwargs).total_seconds())
         return self
@@ -101,51 +101,75 @@ class NscNode:
         return self
 
 
-class NscZone:
-    name: str
-    admin_email: Optional[str] = None
-    refresh: timedelta = timedelta(hours=8)
-    retry: timedelta = timedelta(hours=2)
-    expire: timedelta = timedelta(days=14)
-    min_ttl: timedelta = timedelta(days=1)
-    origin_server: Optional[str] = None
-    zone: Zone
+class NscZoneConfig:
+    admin_email: str
+    refresh: timedelta
+    retry: timedelta
+    expire: timedelta
+    min_ttl: timedelta
+    origin_server: str
+
+    default_config: Optional['NscZoneConfig'] = None
 
     def __init__(self,
-                 name: str,
                  admin_email: Optional[str] = None,
                  refresh: Optional[timedelta] = None,
                  retry: Optional[timedelta] = None,
                  expire: Optional[timedelta] = None,
                  min_ttl: Optional[timedelta] = None,
                  origin_server: Optional[str] = None,
+                 inherit_config: Optional['NscZoneConfig'] = None,
                  ) -> None:
-        self.name = name
-        self.admin_email = admin_email if admin_email is not None else self.admin_email
-        self.refresh = refresh if refresh is not None else self.refresh
-        self.retry = retry if retry is not None else self.retry
-        self.expire = expire if expire is not None else self.expire
-        self.min_ttl = min_ttl if min_ttl is not None else self.min_ttl
-        self.origin_server = origin_server if origin_server is not None else self.origin_server
-        self.zone = dns.zone.Zone(origin=name, rdclass=RdataClass.IN)
-
-        if self.origin_server is None:
+        if inherit_config is None:
+            inherit_config = NscZoneConfig.default_config or self   # to satisfy the type checker
+        self.admin_email = admin_email if admin_email is not None else inherit_config.admin_email
+        self.refresh = refresh if refresh is not None else inherit_config.refresh
+        self.retry = retry if retry is not None else inherit_config.retry
+        self.expire = expire if expire is not None else inherit_config.expire
+        self.min_ttl = min_ttl if min_ttl is not None else inherit_config.min_ttl
+        self.origin_server = origin_server if origin_server is not None else inherit_config.origin_server
+
+    def finalize(self) -> Self:
+        if not self.origin_server:
             self.origin_server = socket.getfqdn()
+        if not self.admin_email:
+            self.admin_email = f'hostmaster@{self.origin_server}'
+        return self
+
 
-        if self.admin_email is None:
-            self.admin_email = f'root@{self.origin_server}'
+NscZoneConfig.default_config = NscZoneConfig(
+    admin_email="",
+    refresh=timedelta(hours=8),
+    retry=timedelta(hours=2),
+    expire=timedelta(days=14),
+    min_ttl=timedelta(days=1),
+    origin_server="",
+)
+
+
+class NscZone:
+    name: str
+    zone: Zone
+    _min_ttl: int
+
+    def __init__(self, name: str, **kwargs) -> None:
+        self.name = name
+        self.config = NscZoneConfig(**kwargs).finalize()
+        self.zone = dns.zone.Zone(origin=name, rdclass=RdataClass.IN)
+        self._min_ttl = int(self.config.min_ttl.total_seconds())
 
+        conf = self.config
         root = self[""]
         root._add(
             dns.rdtypes.ANY.SOA.SOA(
                 RdataClass.IN, RdataType.SOA,
-                mname=self.origin_server,
-                rname=self.admin_email.replace('@', '.'),   # FIXME: names with dots
+                mname=conf.origin_server,
+                rname=conf.admin_email.replace('@', '.'),   # FIXME: names with dots
                 serial=12345,
-                refresh=int(self.refresh.total_seconds()),
-                retry=int(self.retry.total_seconds()),
-                expire=int(self.expire.total_seconds()),
-                minimum=int(self.min_ttl.total_seconds()),
+                refresh=int(conf.refresh.total_seconds()),
+                retry=int(conf.retry.total_seconds()),
+                expire=int(conf.expire.total_seconds()),
+                minimum=int(conf.min_ttl.total_seconds()),
             )
         )
 
@@ -163,24 +187,27 @@ class NscZone:
     def dump(self) -> None:
         # Could use self.zone.to_file(sys.stdout), but we want better formatting
         last_name = None
-        min_ttl = int(self.min_ttl.total_seconds())
         for name, ttl, rec in self.zone.iterate_rdatas():
             if name == last_name:
                 print_name = ""
             else:
                 print_name = name
-            print(f'{print_name}\t{ttl if ttl != min_ttl else ""}\t{rec.rdtype.name}\t{rec.to_text()}')
+            print(f'{print_name}\t{ttl if ttl != self._min_ttl else ""}\t{rec.rdtype.name}\t{rec.to_text()}')
             last_name = name
 
 
-class Config:
+class Nsc:
     zones: Dict[str, Zone]
+    default_zone_config: NscZoneConfig
 
-    def __init__(self) -> None:
+    def __init__(self, **kwargs) -> None:
         self.zones = {}
+        self.default_zone_config = NscZoneConfig(**kwargs)
 
-    def add_zone(self, *args, **kwargs) -> Zone:
-        dom = NscZone(*args, **kwargs)
+    def add_zone(self, *args, inherit_config: Optional[NscZoneConfig] = None, **kwargs) -> Zone:
+        if inherit_config is None:
+            inherit_config = self.default_zone_config
+        dom = NscZone(*args, inherit_config=inherit_config, **kwargs)
         assert dom.name not in self.zones
         self.zones[dom.name] = dom
         return dom
@@ -191,7 +218,7 @@ class MyZone(Zone):
     origin_server = 'ns.ucw.cz'
 
 
-c = Config()
+c = Nsc()
 z = c.add_zone('ucw.cz')  # origin_server='jabberwock.ucw.cz')
 
 z[""].NS(['jabberwock', 'chirigo.gebbeth.cz', 'drak.ucw.cz'])