summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Halley <halley@dnspython.org>2022-01-23 15:38:05 -0800
committerBob Halley <halley@dnspython.org>2022-01-23 15:38:05 -0800
commitc07d11ea060bc4bb02ee8deadba8365bd5b8b99d (patch)
tree07b0a7447376d25f4016a9f14242ff0e058f2bff
parentecdc63b866856d7a38f73484722226f29b95224f (diff)
downloaddnspython-absolute_origin_zone_txn_fix.tar.gz
Use the version's origin if the zone doesn't have one yet. [#766]absolute_origin_zone_txn_fix
-rw-r--r--dns/transaction.py11
-rw-r--r--dns/zone.py20
-rw-r--r--tests/test_zone.py7
3 files changed, 35 insertions, 3 deletions
diff --git a/dns/transaction.py b/dns/transaction.py
index ae7417e..846db4e 100644
--- a/dns/transaction.py
+++ b/dns/transaction.py
@@ -389,7 +389,7 @@ class Transaction:
if rdataset.rdclass != self.manager.get_class():
raise ValueError(f'{method} has objects of wrong RdataClass')
if rdataset.rdtype == dns.rdatatype.SOA:
- (_, _, origin) = self.manager.origin_information()
+ (_, _, origin) = self._origin_information()
if name != origin:
raise ValueError(f'{method} has non-origin SOA')
self._raise_if_not_empty(method, args)
@@ -585,3 +585,12 @@ class Transaction:
Returns a node or ``None``.
"""
raise NotImplementedError # pragma: no cover
+
+ #
+ # Low-level API with a default implementation, in case a subclass needs
+ # to override.
+ #
+
+ def _origin_information(self):
+ # This is only used by _add()
+ return self.manager.origin_information()
diff --git a/dns/zone.py b/dns/zone.py
index 2e73144..69c3a73 100644
--- a/dns/zone.py
+++ b/dns/zone.py
@@ -870,10 +870,14 @@ class Version:
def _validate_name(self, name):
if name.is_absolute():
- if not name.is_subdomain(self.zone.origin):
+ if self.origin is None:
+ # This should probably never happen as other code (e.g.
+ # _rr_line) will notice the lack of an origin before us, but
+ # we check just in case!
+ raise KeyError('no zone origin is defined')
+ if not name.is_subdomain(self.origin):
raise KeyError("name is not a subdomain of the zone origin")
if self.zone.relativize:
- # XXXRTH should it be an error if self.origin is still None?
name = name.relativize(self.origin)
return name
@@ -1030,6 +1034,18 @@ class Transaction(dns.transaction.Transaction):
def _get_node(self, name):
return self.version.get_node(name)
+ def _origin_information(self):
+ (absolute, relativize, effective) = self.manager.origin_information()
+ if absolute is None and self.version.origin is not None:
+ # No origin has been committed yet, but we've learned one as part of
+ # this txn. Use it.
+ absolute = self.version.origin
+ if relativize:
+ effective = dns.name.empty
+ else:
+ effective = absolute
+ return (absolute, relativize, effective)
+
def from_text(text, origin=None, rdclass=dns.rdataclass.IN,
relativize=True, zone_factory=Zone, filename=None,
diff --git a/tests/test_zone.py b/tests/test_zone.py
index bdc99a3..d0765df 100644
--- a/tests/test_zone.py
+++ b/tests/test_zone.py
@@ -1012,6 +1012,13 @@ class VersionedZoneTestCase(unittest.TestCase):
rds = txn.get('example.', 'soa')
self.assertEqual(rds[0].serial, 1)
+ def testNoRelativizeReaderOriginInText(self):
+ z = dns.zone.from_text(example_text, relativize=False,
+ zone_factory=dns.versioned.Zone)
+ with z.reader(serial=1) as txn:
+ rds = txn.get('example.', 'soa')
+ self.assertEqual(rds[0].serial, 1)
+
def testCnameAndOtherDataAddOther(self):
z = dns.zone.from_text(example_cname, 'example.', relativize=True,
zone_factory=dns.versioned.Zone)