mirror of
https://github.com/github/octodns.git
synced 2024-05-11 05:55:00 +00:00
Record.parse_rdata_texts, TinyDns support for arbitrary record types
This commit is contained in:
@@ -123,6 +123,10 @@ class Record(EqualityTupleMixin):
|
|||||||
|
|
||||||
return records
|
return records
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def parse_rdata_texts(cls, rdatas):
|
||||||
|
return [cls._value_type.parse_rdata_text(r) for r in rdatas]
|
||||||
|
|
||||||
def __init__(self, zone, name, data, source=None):
|
def __init__(self, zone, name, data, source=None):
|
||||||
self.zone = zone
|
self.zone = zone
|
||||||
if name:
|
if name:
|
||||||
|
|||||||
@@ -357,6 +357,44 @@ class TinyDnsBaseSource(BaseSource):
|
|||||||
|
|
||||||
yield 'SRV', name, ttl, values
|
yield 'SRV', name, ttl, values
|
||||||
|
|
||||||
|
def _records_for_colon(self, zone, name, lines, arpa=False):
|
||||||
|
# :fqdn:n:rdata:ttl:timestamp:lo
|
||||||
|
# ANY
|
||||||
|
|
||||||
|
if arpa:
|
||||||
|
# no arpa
|
||||||
|
return []
|
||||||
|
|
||||||
|
if not zone.owns('SRV', name):
|
||||||
|
# if name doesn't live under our zone there's nothing for us to do
|
||||||
|
return
|
||||||
|
|
||||||
|
# group by lines by the record type
|
||||||
|
types = defaultdict(list)
|
||||||
|
for line in lines:
|
||||||
|
types[line[1].upper()].append(line)
|
||||||
|
|
||||||
|
classes = Record.registered_types()
|
||||||
|
for _type, lines in types.items():
|
||||||
|
_class = classes.get(_type, None)
|
||||||
|
if not _class:
|
||||||
|
self.log.info(
|
||||||
|
'_records_for_colon: unrecognized type %s, %s', _type, line
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# see if we can find a ttl on any of the lines, first one wins
|
||||||
|
ttl = self.default_ttl
|
||||||
|
for line in lines:
|
||||||
|
try:
|
||||||
|
ttl = int(line[3])
|
||||||
|
break
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
rdatas = [l[2] for l in lines]
|
||||||
|
yield _type, name, ttl, _class.parse_rdata_texts(rdatas)
|
||||||
|
|
||||||
def _records_for_six(self, zone, name, lines, arpa=False):
|
def _records_for_six(self, zone, name, lines, arpa=False):
|
||||||
# 6fqdn:ip:ttl:timestamp:lo
|
# 6fqdn:ip:ttl:timestamp:lo
|
||||||
# AAAA (arpa False) & PTR (arpa True)
|
# AAAA (arpa False) & PTR (arpa True)
|
||||||
@@ -376,11 +414,8 @@ class TinyDnsBaseSource(BaseSource):
|
|||||||
'\'': _records_for_quote, # TXT
|
'\'': _records_for_quote, # TXT
|
||||||
'3': _records_for_three, # AAAA
|
'3': _records_for_three, # AAAA
|
||||||
'S': _records_for_S, # SRV
|
'S': _records_for_S, # SRV
|
||||||
|
':': _records_for_colon, # arbitrary
|
||||||
'6': _records_for_six, # AAAA
|
'6': _records_for_six, # AAAA
|
||||||
# TODO:
|
|
||||||
# Sfqdn:ip:x:port:priority:weight:ttl:timestamp:lo
|
|
||||||
#':': _record_for_semicolon # arbitrary
|
|
||||||
# :fqdn:n:rdata:ttl:timestamp:lo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def _process_lines(self, zone, lines):
|
def _process_lines(self, zone, lines):
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from octodns.idna import idna_encode
|
|||||||
from octodns.record import (
|
from octodns.record import (
|
||||||
AliasRecord,
|
AliasRecord,
|
||||||
ARecord,
|
ARecord,
|
||||||
|
CnameRecord,
|
||||||
Create,
|
Create,
|
||||||
Delete,
|
Delete,
|
||||||
MxValue,
|
MxValue,
|
||||||
@@ -176,6 +177,20 @@ class TestRecord(TestCase):
|
|||||||
# make sure there's nothing extra
|
# make sure there's nothing extra
|
||||||
self.assertEqual(5, len(records))
|
self.assertEqual(5, len(records))
|
||||||
|
|
||||||
|
def test_parse_rdata_texts(self):
|
||||||
|
self.assertEqual(['2.3.4.5'], ARecord.parse_rdata_texts(['2.3.4.5']))
|
||||||
|
self.assertEqual(
|
||||||
|
['2.3.4.6', '3.4.5.7'],
|
||||||
|
ARecord.parse_rdata_texts(['2.3.4.6', '3.4.5.7']),
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
['some.target.'], CnameRecord.parse_rdata_texts(['some.target.'])
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
['some.target.', 'other.target.'],
|
||||||
|
CnameRecord.parse_rdata_texts(['some.target.', 'other.target.']),
|
||||||
|
)
|
||||||
|
|
||||||
def test_values_mixin_data(self):
|
def test_values_mixin_data(self):
|
||||||
# no values, no value or values in data
|
# no values, no value or values in data
|
||||||
a = ARecord(self.zone, '', {'type': 'A', 'ttl': 600, 'values': []})
|
a = ARecord(self.zone, '', {'type': 'A', 'ttl': 600, 'values': []})
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class TestTinyDnsFileSource(TestCase):
|
|||||||
def test_populate_normal(self):
|
def test_populate_normal(self):
|
||||||
got = Zone('example.com.', [])
|
got = Zone('example.com.', [])
|
||||||
self.source.populate(got)
|
self.source.populate(got)
|
||||||
self.assertEqual(28, len(got.records))
|
self.assertEqual(30, len(got.records))
|
||||||
|
|
||||||
expected = Zone('example.com.', [])
|
expected = Zone('example.com.', [])
|
||||||
for name, data in (
|
for name, data in (
|
||||||
@@ -177,6 +177,26 @@ class TestTinyDnsFileSource(TestCase):
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
'arbitrary-sshfp',
|
||||||
|
{
|
||||||
|
'type': 'SSHFP',
|
||||||
|
'ttl': 45,
|
||||||
|
'values': [
|
||||||
|
{
|
||||||
|
'algorithm': 1,
|
||||||
|
'fingerprint_type': 2,
|
||||||
|
'fingerprint': '00479b27',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'algorithm': 2,
|
||||||
|
'fingerprint_type': 2,
|
||||||
|
'fingerprint': '00479a28',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
('arbitrary-a', {'type': 'A', 'ttl': 3600, 'value': '80.81.82.83'}),
|
||||||
):
|
):
|
||||||
record = Record.new(expected, name, data)
|
record = Record.new(expected, name, data)
|
||||||
expected.add_record(record)
|
expected.add_record(record)
|
||||||
@@ -253,4 +273,4 @@ class TestTinyDnsFileSource(TestCase):
|
|||||||
got = Zone('example.com.', ['sub'])
|
got = Zone('example.com.', ['sub'])
|
||||||
self.source.populate(got)
|
self.source.populate(got)
|
||||||
# we don't see one www.sub.example.com. record b/c it's in a sub
|
# we don't see one www.sub.example.com. record b/c it's in a sub
|
||||||
self.assertEqual(27, len(got.records))
|
self.assertEqual(29, len(got.records))
|
||||||
|
|||||||
@@ -72,3 +72,11 @@ S_a._tcp.example.com::target.somewhere.else:8080:10:50:43
|
|||||||
S_b._tcp.example.com:56.57.58.59:target.srv.example.com.:9999
|
S_b._tcp.example.com:56.57.58.59:target.srv.example.com.:9999
|
||||||
# complete duplicate should be ignored
|
# complete duplicate should be ignored
|
||||||
S_b._tcp.example.com:56.57.58.59:target.srv.example.com.:9999
|
S_b._tcp.example.com:56.57.58.59:target.srv.example.com.:9999
|
||||||
|
|
||||||
|
# arbitrary multi-value non-spec record
|
||||||
|
:arbitrary-sshfp.example.com:SSHFP:2 2 00479a28
|
||||||
|
:arbitrary-sshfp.example.com:SSHFP:1 2 00479b27:45
|
||||||
|
# does not make sense to do an A this way, but it'll work
|
||||||
|
:arbitrary-a.example.com:a:80.81.82.83
|
||||||
|
# this should just be inored b/c the type is unknown
|
||||||
|
:arbitrary-invalid.example.com:invalid:does not matter:99
|
||||||
|
|||||||
Reference in New Issue
Block a user