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
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()),
)
)
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
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'])