Browse Source

Naptr to/from rr text

pull/930/head
Ross McFarland 3 years ago
parent
commit
0eb4e66634
No known key found for this signature in database GPG Key ID: 943B179E15D3B22A
2 changed files with 112 additions and 2 deletions
  1. +41
    -0
      octodns/record/__init__.py
  2. +71
    -2
      tests/test_octodns_record.py

+ 41
- 0
octodns/record/__init__.py View File

@ -1376,12 +1376,47 @@ Record.register_type(MxRecord)
class NaptrValue(EqualityTupleMixin, dict): class NaptrValue(EqualityTupleMixin, dict):
VALID_FLAGS = ('S', 'A', 'U', 'P') VALID_FLAGS = ('S', 'A', 'U', 'P')
@classmethod
def parse_rr_text(self, value):
try:
(
order,
preference,
flags,
service,
regexp,
replacement,
) = value.split(' ')
except ValueError:
raise RrParseError('failed to parse string value as RR text')
try:
order = int(order)
preference = int(preference)
except ValueError:
pass
return {
'order': order,
'preference': preference,
'flags': flags,
'service': service,
'regexp': regexp,
'replacement': replacement,
}
@classmethod @classmethod
def validate(cls, data, _type): def validate(cls, data, _type):
if not isinstance(data, (list, tuple)): if not isinstance(data, (list, tuple)):
data = (data,) data = (data,)
reasons = [] reasons = []
for value in data: for value in data:
if isinstance(value, str):
# it's hopefully RR formatted, give parsing a try
try:
value = cls.parse_rr_text(value)
except RrParseError as e:
reasons.append(str(e))
# not a dict so no point in continuing
continue
try: try:
int(value['order']) int(value['order'])
except KeyError: except KeyError:
@ -1413,6 +1448,8 @@ class NaptrValue(EqualityTupleMixin, dict):
return [cls(v) for v in values] return [cls(v) for v in values]
def __init__(self, value): def __init__(self, value):
if isinstance(value, str):
value = self.parse_rr_text(value)
super().__init__( super().__init__(
{ {
'order': int(value['order']), 'order': int(value['order']),
@ -1476,6 +1513,10 @@ class NaptrValue(EqualityTupleMixin, dict):
def data(self): def data(self):
return self return self
@property
def rr_text(self):
return f'{self.order} {self.preference} {self.flags} {self.service} {self.regexp} {self.replacement}'
def __hash__(self): def __hash__(self):
return hash(self.__repr__()) return hash(self.__repr__())


+ 71
- 2
tests/test_octodns_record.py View File

@ -620,7 +620,7 @@ class TestRecord(TestCase):
) )
# make sure that validate is using parse_rr_text when passed string # make sure that validate is using parse_rr_text when passed string
# values
# value(s)
reasons = MxRecord.validate( reasons = MxRecord.validate(
'mx', 'mx.unit.tests.', {'ttl': 32, 'value': ''} 'mx', 'mx.unit.tests.', {'ttl': 32, 'value': ''}
) )
@ -638,8 +638,8 @@ class TestRecord(TestCase):
zone = Zone('unit.tests.', []) zone = Zone('unit.tests.', [])
a = MxRecord(zone, 'mx', {'ttl': 32, 'value': '10 mail.unit.tests.'}) a = MxRecord(zone, 'mx', {'ttl': 32, 'value': '10 mail.unit.tests.'})
self.assertEqual(10, a.values[0].preference) self.assertEqual(10, a.values[0].preference)
self.assertEqual('10 mail.unit.tests.', a.values[0].rr_text)
self.assertEqual('mail.unit.tests.', a.values[0].exchange) self.assertEqual('mail.unit.tests.', a.values[0].exchange)
self.assertEqual('10 mail.unit.tests.', a.values[0].rr_text)
a = MxRecord( a = MxRecord(
zone, zone,
'mx', 'mx',
@ -945,6 +945,75 @@ class TestRecord(TestCase):
o.replacement = '1' o.replacement = '1'
self.assertEqual('1', o.replacement) self.assertEqual('1', o.replacement)
def test_naptr_rr_text(self):
# things with the wrong number of words won't parse
for v in (
'',
'one',
'one two',
'one two three',
'one two three four',
'one two three four five',
'one two three four five six seven',
):
with self.assertRaises(RrParseError):
NaptrValue.parse_rr_text(v)
# we don't care if the types of things are correct when parsing rr text
self.assertEqual(
{
'order': 'one',
'preference': 'two',
'flags': 'three',
'service': 'four',
'regexp': 'five',
'replacement': 'six',
},
NaptrValue.parse_rr_text('one two three four five six'),
)
# order and preference will be converted to int's when possible
self.assertEqual(
{
'order': 1,
'preference': 2,
'flags': 'three',
'service': 'four',
'regexp': 'five',
'replacement': 'six',
},
NaptrValue.parse_rr_text('1 2 three four five six'),
)
# make sure that validate is using parse_rr_text when passed string
# value(s)
reasons = NaptrRecord.validate(
'naptr', 'naptr.unit.tests.', {'ttl': 32, 'value': ''}
)
self.assertEqual(['failed to parse string value as RR text'], reasons)
reasons = NaptrRecord.validate(
'naptr', 'naptr.unit.tests.', {'ttl': 32, 'value': ['']}
)
self.assertEqual(['failed to parse string value as RR text'], reasons)
reasons = NaptrRecord.validate(
'naptr',
'naptr.unit.tests.',
{'ttl': 32, 'value': ['1 2 S service regexp replacement']},
)
self.assertFalse(reasons)
# make sure that the cstor is using parse_rr_text
zone = Zone('unit.tests.', [])
s = '1 2 S service regexp replacement'
a = NaptrRecord(zone, 'naptr', {'ttl': 32, 'value': s})
self.assertEqual(1, a.values[0].order)
self.assertEqual(2, a.values[0].preference)
self.assertEqual('S', a.values[0].flags)
self.assertEqual('service', a.values[0].service)
self.assertEqual('regexp', a.values[0].regexp)
self.assertEqual('replacement', a.values[0].replacement)
self.assertEqual(s, a.values[0].rr_text)
def test_ns(self): def test_ns(self):
a_values = ['5.6.7.8.', '6.7.8.9.', '7.8.9.0.'] a_values = ['5.6.7.8.', '6.7.8.9.', '7.8.9.0.']
a_data = {'ttl': 30, 'values': a_values} a_data = {'ttl': 30, 'values': a_values}


Loading…
Cancel
Save