mirror of
https://github.com/github/octodns.git
synced 2024-05-11 05:55:00 +00:00
TinyDNS SRV support and test coverage
This commit is contained in:
+77
-10
@@ -16,12 +16,16 @@ from .base import BaseSource
|
||||
class TinyDnsBaseSource(BaseSource):
|
||||
SUPPORTS_GEO = False
|
||||
SUPPORTS_DYNAMIC = False
|
||||
SUPPORTS = set(('A', 'CNAME', 'MX', 'NS', 'TXT', 'AAAA'))
|
||||
|
||||
def __init__(self, id, default_ttl=3600):
|
||||
super().__init__(id)
|
||||
self.default_ttl = default_ttl
|
||||
|
||||
@property
|
||||
def SUPPORTS(self):
|
||||
# All record types, including those registered by 3rd party modules
|
||||
return set(Record.registered_types().keys())
|
||||
|
||||
def _records_for_at(self, zone, name, lines, arpa=False):
|
||||
# @fqdn:ip:x:dist:ttl:timestamp:lo
|
||||
# MX (and optional A)
|
||||
@@ -38,7 +42,7 @@ class TinyDnsBaseSource(BaseSource):
|
||||
ttl = self.default_ttl
|
||||
for line in lines:
|
||||
try:
|
||||
ttl = int(lines[0][4])
|
||||
ttl = int(line[4])
|
||||
break
|
||||
except IndexError:
|
||||
pass
|
||||
@@ -61,7 +65,7 @@ class TinyDnsBaseSource(BaseSource):
|
||||
|
||||
# if we have an IP then we need to create an A for the MX
|
||||
ip = line[1]
|
||||
if ip:
|
||||
if ip and zone.owns('A', mx):
|
||||
yield 'A', mx, ttl, [ip]
|
||||
|
||||
values.append({'preference': dist, 'exchange': mx})
|
||||
@@ -88,7 +92,7 @@ class TinyDnsBaseSource(BaseSource):
|
||||
ttl = self.default_ttl
|
||||
for line in lines:
|
||||
try:
|
||||
ttl = int(lines[0][2])
|
||||
ttl = int(line[2])
|
||||
break
|
||||
except IndexError:
|
||||
pass
|
||||
@@ -163,7 +167,7 @@ class TinyDnsBaseSource(BaseSource):
|
||||
ttl = self.default_ttl
|
||||
for line in lines:
|
||||
try:
|
||||
ttl = int(lines[0][3])
|
||||
ttl = int(line[3])
|
||||
break
|
||||
except IndexError:
|
||||
pass
|
||||
@@ -180,7 +184,7 @@ class TinyDnsBaseSource(BaseSource):
|
||||
|
||||
# if we have an IP then we need to create an A for the MX
|
||||
ip = line[1]
|
||||
if ip:
|
||||
if ip and zone.owns('A', ns):
|
||||
yield 'A', ns, ttl, [ip]
|
||||
|
||||
values.append(ns)
|
||||
@@ -212,7 +216,7 @@ class TinyDnsBaseSource(BaseSource):
|
||||
ttl = self.default_ttl
|
||||
for line in lines:
|
||||
try:
|
||||
ttl = int(lines[0][2])
|
||||
ttl = int(line[2])
|
||||
break
|
||||
except IndexError:
|
||||
pass
|
||||
@@ -241,7 +245,7 @@ class TinyDnsBaseSource(BaseSource):
|
||||
ttl = self.default_ttl
|
||||
for line in lines:
|
||||
try:
|
||||
ttl = int(lines[0][2])
|
||||
ttl = int(line[2])
|
||||
break
|
||||
except IndexError:
|
||||
pass
|
||||
@@ -272,13 +276,76 @@ class TinyDnsBaseSource(BaseSource):
|
||||
ttl = self.default_ttl
|
||||
for line in lines:
|
||||
try:
|
||||
ttl = int(lines[0][2])
|
||||
ttl = int(line[2])
|
||||
break
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
yield 'AAAA', name, ttl, ips
|
||||
|
||||
def _records_for_S(self, zone, name, lines, arpa=False):
|
||||
# Sfqdn:ip:x:port:priority:weight:ttl:timestamp:lo
|
||||
# SRV
|
||||
|
||||
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
|
||||
|
||||
# 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[6])
|
||||
break
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
values = []
|
||||
for line in lines:
|
||||
target = line[2]
|
||||
# if there's a . in the mx we hit a special case and use it as-is
|
||||
if '.' not in target:
|
||||
# otherwise we treat it as the MX hostnam and construct the rest
|
||||
target = f'{target}.srv.{zone.name}'
|
||||
elif target[-1] != '.':
|
||||
target = f'{target}.'
|
||||
|
||||
# if we have an IP then we need to create an A for the SRV
|
||||
# has to be present, but can be empty
|
||||
ip = line[1]
|
||||
if ip and zone.owns('A', target):
|
||||
yield 'A', target, ttl, [ip]
|
||||
|
||||
# required
|
||||
port = int(line[3])
|
||||
|
||||
# optional, default 0
|
||||
try:
|
||||
priority = int(line[4] or 0)
|
||||
except IndexError:
|
||||
priority = 0
|
||||
|
||||
# optional, default 0
|
||||
try:
|
||||
weight = int(line[5] or 0)
|
||||
except IndexError:
|
||||
weight = 0
|
||||
|
||||
values.append(
|
||||
{
|
||||
'priority': priority,
|
||||
'weight': weight,
|
||||
'port': port,
|
||||
'target': target,
|
||||
}
|
||||
)
|
||||
|
||||
yield 'SRV', name, ttl, values
|
||||
|
||||
def _records_for_six(self, zone, name, lines, arpa=False):
|
||||
# 6fqdn:ip:ttl:timestamp:lo
|
||||
# AAAA (arpa False) & PTR (arpa True)
|
||||
@@ -297,9 +364,9 @@ class TinyDnsBaseSource(BaseSource):
|
||||
'&': _records_for_amp, # NS
|
||||
'\'': _records_for_quote, # TXT
|
||||
'3': _records_for_three, # AAAA
|
||||
'S': _records_for_S, # SRV
|
||||
'6': _records_for_six, # AAAA
|
||||
# TODO:
|
||||
#'S': _records_for_S, # SRV
|
||||
# Sfqdn:ip:x:port:priority:weight:ttl:timestamp:lo
|
||||
#':': _record_for_semicolon # arbitrary
|
||||
# :fqdn:n:rdata:ttl:timestamp:lo
|
||||
|
||||
@@ -17,7 +17,7 @@ class TestTinyDnsFileSource(TestCase):
|
||||
def test_populate_normal(self):
|
||||
got = Zone('example.com.', [])
|
||||
self.source.populate(got)
|
||||
self.assertEqual(25, len(got.records))
|
||||
self.assertEqual(28, len(got.records))
|
||||
|
||||
expected = Zone('example.com.', [])
|
||||
for name, data in (
|
||||
@@ -140,6 +140,43 @@ class TestTinyDnsFileSource(TestCase):
|
||||
'values': ['ns5.ns.example.com.', 'ns6.ns.example.com.'],
|
||||
},
|
||||
),
|
||||
(
|
||||
'_a._tcp',
|
||||
{
|
||||
'type': 'SRV',
|
||||
'ttl': 43,
|
||||
'values': [
|
||||
{
|
||||
'priority': 0,
|
||||
'weight': 0,
|
||||
'port': 8888,
|
||||
'target': 'target.srv.example.com.',
|
||||
},
|
||||
{
|
||||
'priority': 10,
|
||||
'weight': 50,
|
||||
'port': 8080,
|
||||
'target': 'target.somewhere.else.',
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
('target.srv', {'type': 'A', 'ttl': 43, 'value': '56.57.58.59'}),
|
||||
(
|
||||
'_b._tcp',
|
||||
{
|
||||
'type': 'SRV',
|
||||
'ttl': 3600,
|
||||
'values': [
|
||||
{
|
||||
'priority': 0,
|
||||
'weight': 0,
|
||||
'port': 9999,
|
||||
'target': 'target.srv.example.com.',
|
||||
}
|
||||
],
|
||||
},
|
||||
),
|
||||
):
|
||||
record = Record.new(expected, name, data)
|
||||
expected.add_record(record)
|
||||
@@ -216,4 +253,4 @@ class TestTinyDnsFileSource(TestCase):
|
||||
got = Zone('example.com.', ['sub'])
|
||||
self.source.populate(got)
|
||||
# we don't see one www.sub.example.com. record b/c it's in a sub
|
||||
self.assertEqual(24, len(got.records))
|
||||
self.assertEqual(27, len(got.records))
|
||||
|
||||
@@ -61,3 +61,9 @@ Ccname.other.foo:www.other.foo
|
||||
6ipv6-6.example.com:2a021348017cd5d0002419fffef35743
|
||||
|
||||
'semicolon.example.com:v=DKIM1; k=rsa; p=blah:300
|
||||
|
||||
# SRV
|
||||
S_a._tcp.example.com:56.57.58.59:target:8888
|
||||
S_a._tcp.example.com::target.somewhere.else:8080:10:50:43
|
||||
# TODO: add an IP so it tries to create a record that already exists
|
||||
S_b._tcp.example.com::target.srv.example.com.:9999
|
||||
|
||||
Reference in New Issue
Block a user