mirror of
https://github.com/github/octodns.git
synced 2024-05-11 05:55:00 +00:00
Merge pull request #668 from ucc/srv_null_records
Fix handling of NULL SRV records in Cloudflare and Digital Ocean providers, add warnings to DNS Made Easy and DNSimple providers
This commit is contained in:
@@ -269,11 +269,13 @@ class CloudflareProvider(BaseProvider):
|
||||
def _data_for_SRV(self, _type, records):
|
||||
values = []
|
||||
for r in records:
|
||||
target = ('{}.'.format(r['data']['target'])
|
||||
if r['data']['target'] != "." else ".")
|
||||
values.append({
|
||||
'priority': r['data']['priority'],
|
||||
'weight': r['data']['weight'],
|
||||
'port': r['data']['port'],
|
||||
'target': '{}.'.format(r['data']['target']),
|
||||
'target': target,
|
||||
})
|
||||
return {
|
||||
'type': _type,
|
||||
@@ -454,6 +456,8 @@ class CloudflareProvider(BaseProvider):
|
||||
name = subdomain
|
||||
|
||||
for value in record.values:
|
||||
target = value.target[:-1] if value.target != "." else "."
|
||||
|
||||
yield {
|
||||
'data': {
|
||||
'service': service,
|
||||
@@ -462,7 +466,7 @@ class CloudflareProvider(BaseProvider):
|
||||
'priority': value.priority,
|
||||
'weight': value.weight,
|
||||
'port': value.port,
|
||||
'target': value.target[:-1],
|
||||
'target': target,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -186,10 +186,14 @@ class DigitalOceanProvider(BaseProvider):
|
||||
def _data_for_SRV(self, _type, records):
|
||||
values = []
|
||||
for record in records:
|
||||
target = (
|
||||
'{}.'.format(record['data'])
|
||||
if record['data'] != "." else "."
|
||||
)
|
||||
values.append({
|
||||
'port': record['port'],
|
||||
'priority': record['priority'],
|
||||
'target': '{}.'.format(record['data']),
|
||||
'target': target,
|
||||
'weight': record['weight']
|
||||
})
|
||||
return {
|
||||
|
||||
@@ -218,12 +218,23 @@ class DnsimpleProvider(BaseProvider):
|
||||
try:
|
||||
weight, port, target = record['content'].split(' ', 2)
|
||||
except ValueError:
|
||||
# see _data_for_NAPTR's continue
|
||||
# their api/website will let you create invalid records, this
|
||||
# essentially handles that by ignoring them for values
|
||||
# purposes. That will cause updates to happen to delete them if
|
||||
# they shouldn't exist or update them if they're wrong
|
||||
self.log.warning(
|
||||
'_data_for_SRV: unsupported %s record (%s)',
|
||||
_type,
|
||||
record['content']
|
||||
)
|
||||
continue
|
||||
|
||||
target = '{}.'.format(target) if target != "." else "."
|
||||
|
||||
values.append({
|
||||
'port': port,
|
||||
'priority': record['priority'],
|
||||
'target': '{}.'.format(target),
|
||||
'target': target,
|
||||
'weight': weight
|
||||
})
|
||||
return {
|
||||
@@ -270,6 +281,10 @@ class DnsimpleProvider(BaseProvider):
|
||||
for record in self.zone_records(zone):
|
||||
_type = record['type']
|
||||
if _type not in self.SUPPORTS:
|
||||
self.log.warning(
|
||||
'populate: skipping unsupported %s record',
|
||||
_type
|
||||
)
|
||||
continue
|
||||
elif _type == 'TXT' and record['content'].startswith('ALIAS for'):
|
||||
# ALIAS has a "ride along" TXT record with 'ALIAS for XXXX',
|
||||
@@ -290,6 +305,27 @@ class DnsimpleProvider(BaseProvider):
|
||||
len(zone.records) - before, exists)
|
||||
return exists
|
||||
|
||||
def supports(self, record):
|
||||
# DNSimple does not support empty/NULL SRV records
|
||||
#
|
||||
# Fails silently and leaves a corrupt record
|
||||
#
|
||||
# Skip the record and continue
|
||||
if record._type == "SRV":
|
||||
if 'value' in record.data:
|
||||
targets = (record.data['value']['target'],)
|
||||
else:
|
||||
targets = [value['target'] for value in record.data['values']]
|
||||
|
||||
if "." in targets:
|
||||
self.log.warning(
|
||||
'supports: unsupported %s record with target (%s)',
|
||||
record._type, targets
|
||||
)
|
||||
return False
|
||||
|
||||
return super(DnsimpleProvider, self).supports(record)
|
||||
|
||||
def _params_for_multiple(self, record):
|
||||
for value in record.values:
|
||||
yield {
|
||||
|
||||
@@ -284,6 +284,30 @@ class DnsMadeEasyProvider(BaseProvider):
|
||||
len(zone.records) - before, exists)
|
||||
return exists
|
||||
|
||||
def supports(self, record):
|
||||
# DNS Made Easy does not support empty/NULL SRV records
|
||||
#
|
||||
# Attempting to sync such a record would generate the following error
|
||||
#
|
||||
# octodns.provider.dnsmadeeasy.DnsMadeEasyClientBadRequest:
|
||||
# - Record value may not be a standalone dot.
|
||||
#
|
||||
# Skip the record and continue
|
||||
if record._type == "SRV":
|
||||
if 'value' in record.data:
|
||||
targets = (record.data['value']['target'],)
|
||||
else:
|
||||
targets = [value['target'] for value in record.data['values']]
|
||||
|
||||
if "." in targets:
|
||||
self.log.warning(
|
||||
'supports: unsupported %s record with target (%s)',
|
||||
record._type, targets
|
||||
)
|
||||
return False
|
||||
|
||||
return super(DnsMadeEasyProvider, self).supports(record)
|
||||
|
||||
def _params_for_multiple(self, record):
|
||||
for value in record.values:
|
||||
yield {
|
||||
|
||||
@@ -36,6 +36,22 @@
|
||||
- flags: 0
|
||||
tag: issue
|
||||
value: ca.unit.tests
|
||||
_imap._tcp:
|
||||
ttl: 600
|
||||
type: SRV
|
||||
values:
|
||||
- port: 0
|
||||
priority: 0
|
||||
target: .
|
||||
weight: 0
|
||||
_pop3._tcp:
|
||||
ttl: 600
|
||||
type: SRV
|
||||
values:
|
||||
- port: 0
|
||||
priority: 0
|
||||
target: .
|
||||
weight: 0
|
||||
_srv._tcp:
|
||||
ttl: 600
|
||||
type: SRV
|
||||
|
||||
@@ -173,6 +173,56 @@
|
||||
"meta": {
|
||||
"auto_added": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "fc12ab34cd5611334422ab3322997656",
|
||||
"type": "SRV",
|
||||
"name": "_imap._tcp.unit.tests",
|
||||
"data": {
|
||||
"service": "_imap",
|
||||
"proto": "_tcp",
|
||||
"name": "unit.tests",
|
||||
"priority": 0,
|
||||
"weight": 0,
|
||||
"port": 0,
|
||||
"target": "."
|
||||
},
|
||||
"proxiable": true,
|
||||
"proxied": false,
|
||||
"ttl": 600,
|
||||
"locked": false,
|
||||
"zone_id": "ff12ab34cd5611334422ab3322997650",
|
||||
"zone_name": "unit.tests",
|
||||
"modified_on": "2017-03-11T18:01:43.940682Z",
|
||||
"created_on": "2017-03-11T18:01:43.940682Z",
|
||||
"meta": {
|
||||
"auto_added": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "fc12ab34cd5611334422ab3322997656",
|
||||
"type": "SRV",
|
||||
"name": "_pop3._tcp.unit.tests",
|
||||
"data": {
|
||||
"service": "_imap",
|
||||
"proto": "_pop3",
|
||||
"name": "unit.tests",
|
||||
"priority": 0,
|
||||
"weight": 0,
|
||||
"port": 0,
|
||||
"target": "."
|
||||
},
|
||||
"proxiable": true,
|
||||
"proxied": false,
|
||||
"ttl": 600,
|
||||
"locked": false,
|
||||
"zone_id": "ff12ab34cd5611334422ab3322997650",
|
||||
"zone_name": "unit.tests",
|
||||
"modified_on": "2017-03-11T18:01:43.940682Z",
|
||||
"created_on": "2017-03-11T18:01:43.940682Z",
|
||||
"meta": {
|
||||
"auto_added": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"result_info": {
|
||||
|
||||
+56
@@ -64,6 +64,62 @@
|
||||
"roundRobinFailover": [],
|
||||
"pools": [],
|
||||
"poolsDetail": []
|
||||
}, {
|
||||
"id": 1898527,
|
||||
"type": "SRV",
|
||||
"recordType": "srv",
|
||||
"name": "_imap._tcp",
|
||||
"recordOption": "roundRobin",
|
||||
"noAnswer": false,
|
||||
"note": "",
|
||||
"ttl": 600,
|
||||
"gtdRegion": 1,
|
||||
"parentId": 123123,
|
||||
"parent": "domain",
|
||||
"source": "Domain",
|
||||
"modifiedTs": 1565149714387,
|
||||
"value": [{
|
||||
"value": ".",
|
||||
"priority": 0,
|
||||
"weight": 0,
|
||||
"port": 0,
|
||||
"disableFlag": false
|
||||
}],
|
||||
"roundRobin": [{
|
||||
"value": ".",
|
||||
"priority": 0,
|
||||
"weight": 0,
|
||||
"port": 0,
|
||||
"disableFlag": false
|
||||
}]
|
||||
}, {
|
||||
"id": 1898528,
|
||||
"type": "SRV",
|
||||
"recordType": "srv",
|
||||
"name": "_pop3._tcp",
|
||||
"recordOption": "roundRobin",
|
||||
"noAnswer": false,
|
||||
"note": "",
|
||||
"ttl": 600,
|
||||
"gtdRegion": 1,
|
||||
"parentId": 123123,
|
||||
"parent": "domain",
|
||||
"source": "Domain",
|
||||
"modifiedTs": 1565149714387,
|
||||
"value": [{
|
||||
"value": ".",
|
||||
"priority": 0,
|
||||
"weight": 0,
|
||||
"port": 0,
|
||||
"disableFlag": false
|
||||
}],
|
||||
"roundRobin": [{
|
||||
"value": ".",
|
||||
"priority": 0,
|
||||
"weight": 0,
|
||||
"port": 0,
|
||||
"disableFlag": false
|
||||
}]
|
||||
}, {
|
||||
"id": 1808527,
|
||||
"type": "SRV",
|
||||
|
||||
+22
@@ -76,6 +76,28 @@
|
||||
"weight": null,
|
||||
"flags": null,
|
||||
"tag": null
|
||||
}, {
|
||||
"id": 11189896,
|
||||
"type": "SRV",
|
||||
"name": "_imap._tcp",
|
||||
"data": ".",
|
||||
"priority": 0,
|
||||
"port": 0,
|
||||
"ttl": 600,
|
||||
"weight": 0,
|
||||
"flags": null,
|
||||
"tag": null
|
||||
}, {
|
||||
"id": 11189897,
|
||||
"type": "SRV",
|
||||
"name": "_pop3._tcp",
|
||||
"data": ".",
|
||||
"priority": 0,
|
||||
"port": 0,
|
||||
"ttl": 600,
|
||||
"weight": 0,
|
||||
"flags": null,
|
||||
"tag": null
|
||||
}],
|
||||
"links": {
|
||||
"pages": {
|
||||
|
||||
Vendored
+24
-2
@@ -264,10 +264,32 @@
|
||||
"rdata": "v=DKIM1;k=rsa;s=email;h=sha256;p=A\/kinda+of\/long\/string+with+numb3rs",
|
||||
"geozone_id": "0",
|
||||
"last_mod": "2020-01-01 01:01:01"
|
||||
},
|
||||
{
|
||||
"id": "12340025",
|
||||
"domain": "unit.tests",
|
||||
"host": "_imap._tcp",
|
||||
"ttl": "600",
|
||||
"prio": "0",
|
||||
"type": "SRV",
|
||||
"rdata": "0 0 0 .",
|
||||
"geozone_id": "0",
|
||||
"last_mod": "2020-01-01 01:01:01"
|
||||
},
|
||||
{
|
||||
"id": "12340026",
|
||||
"domain": "unit.tests",
|
||||
"host": "_pop3._tcp",
|
||||
"ttl": "600",
|
||||
"prio": "0",
|
||||
"type": "SRV",
|
||||
"rdata": "0 0 0 .",
|
||||
"geozone_id": "0",
|
||||
"last_mod": "2020-01-01 01:01:01"
|
||||
}
|
||||
],
|
||||
"count": 24,
|
||||
"total": 24,
|
||||
"count": 26,
|
||||
"total": 26,
|
||||
"start": 0,
|
||||
"max": 1000,
|
||||
"status": 200
|
||||
|
||||
Vendored
+18
-2
@@ -9,6 +9,22 @@
|
||||
"name": "_srv._tcp.unit.tests",
|
||||
"ttl": 600
|
||||
},
|
||||
{
|
||||
"rdata": [
|
||||
"0 0 0 ."
|
||||
],
|
||||
"type": "SRV",
|
||||
"name": "_imap._tcp.unit.tests",
|
||||
"ttl": 600
|
||||
},
|
||||
{
|
||||
"rdata": [
|
||||
"0 0 0 ."
|
||||
],
|
||||
"type": "SRV",
|
||||
"name": "_pop3._tcp.unit.tests",
|
||||
"ttl": 600
|
||||
},
|
||||
{
|
||||
"rdata": [
|
||||
"2601:644:500:e210:62f8:1dff:feb8:947a"
|
||||
@@ -151,7 +167,7 @@
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"totalElements": 16,
|
||||
"totalElements": 18,
|
||||
"showAll": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+18
@@ -123,6 +123,24 @@
|
||||
"2.2.3.6"
|
||||
]
|
||||
},
|
||||
{
|
||||
"rrset_type": "SRV",
|
||||
"rrset_ttl": 600,
|
||||
"rrset_name": "_imap._tcp",
|
||||
"rrset_href": "https://api.gandi.net/v5/livedns/domains/unit.tests/records/_imap._tcp/SRV",
|
||||
"rrset_values": [
|
||||
"0 0 0 ."
|
||||
]
|
||||
},
|
||||
{
|
||||
"rrset_type": "SRV",
|
||||
"rrset_ttl": 600,
|
||||
"rrset_name": "_pop3._tcp",
|
||||
"rrset_href": "https://api.gandi.net/v5/livedns/domains/unit.tests/records/_pop3._tcp/SRV",
|
||||
"rrset_values": [
|
||||
"0 0 0 ."
|
||||
]
|
||||
},
|
||||
{
|
||||
"rrset_type": "SRV",
|
||||
"rrset_ttl": 600,
|
||||
|
||||
Vendored
+2
@@ -5,6 +5,8 @@
|
||||
@ 3600 SSHFP 1 1 bf6b6825d2977c511a475bbefb88aad54a92ac73
|
||||
@ 3600 SSHFP 1 1 7491973e5f8b39d5327cd4e08bc81b05f7710b49
|
||||
@ 3600 CAA 0 issue ca.unit.tests
|
||||
_imap._tcp 600 SRV 0 0 0 .
|
||||
_pop3._tcp 600 SRV 0 0 0 .
|
||||
_srv._tcp 600 SRV 10 20 30 foo-1.unit.tests.
|
||||
_srv._tcp 600 SRV 12 20 30 foo-2.unit.tests.
|
||||
aaaa 600 AAAA 2601:644:500:e210:62f8:1dff:feb8:947a
|
||||
|
||||
+24
@@ -75,6 +75,30 @@
|
||||
"ttl": 300,
|
||||
"type": "A"
|
||||
},
|
||||
{
|
||||
"comments": [],
|
||||
"name": "_imap._tcp.unit.tests.",
|
||||
"records": [
|
||||
{
|
||||
"content": "0 0 0 .",
|
||||
"disabled": false
|
||||
}
|
||||
],
|
||||
"ttl": 600,
|
||||
"type": "SRV"
|
||||
},
|
||||
{
|
||||
"comments": [],
|
||||
"name": "_pop3._tcp.unit.tests.",
|
||||
"records": [
|
||||
{
|
||||
"content": "0 0 0 .",
|
||||
"disabled": false
|
||||
}
|
||||
],
|
||||
"ttl": 600,
|
||||
"type": "SRV"
|
||||
},
|
||||
{
|
||||
"comments": [],
|
||||
"name": "_srv._tcp.unit.tests.",
|
||||
|
||||
@@ -118,12 +118,12 @@ class TestManager(TestCase):
|
||||
environ['YAML_TMP_DIR'] = tmpdir.dirname
|
||||
tc = Manager(get_config_filename('simple.yaml')) \
|
||||
.sync(dry_run=False)
|
||||
self.assertEquals(23, tc)
|
||||
self.assertEquals(25, tc)
|
||||
|
||||
# try with just one of the zones
|
||||
tc = Manager(get_config_filename('simple.yaml')) \
|
||||
.sync(dry_run=False, eligible_zones=['unit.tests.'])
|
||||
self.assertEquals(17, tc)
|
||||
self.assertEquals(19, tc)
|
||||
|
||||
# the subzone, with 2 targets
|
||||
tc = Manager(get_config_filename('simple.yaml')) \
|
||||
@@ -138,18 +138,18 @@ class TestManager(TestCase):
|
||||
# Again with force
|
||||
tc = Manager(get_config_filename('simple.yaml')) \
|
||||
.sync(dry_run=False, force=True)
|
||||
self.assertEquals(23, tc)
|
||||
self.assertEquals(25, tc)
|
||||
|
||||
# Again with max_workers = 1
|
||||
tc = Manager(get_config_filename('simple.yaml'), max_workers=1) \
|
||||
.sync(dry_run=False, force=True)
|
||||
self.assertEquals(23, tc)
|
||||
self.assertEquals(25, tc)
|
||||
|
||||
# Include meta
|
||||
tc = Manager(get_config_filename('simple.yaml'), max_workers=1,
|
||||
include_meta=True) \
|
||||
.sync(dry_run=False, force=True)
|
||||
self.assertEquals(27, tc)
|
||||
self.assertEquals(29, tc)
|
||||
|
||||
def test_eligible_sources(self):
|
||||
with TemporaryDirectory() as tmpdir:
|
||||
@@ -215,13 +215,13 @@ class TestManager(TestCase):
|
||||
fh.write('---\n{}')
|
||||
|
||||
changes = manager.compare(['in'], ['dump'], 'unit.tests.')
|
||||
self.assertEquals(17, len(changes))
|
||||
self.assertEquals(19, len(changes))
|
||||
|
||||
# Compound sources with varying support
|
||||
changes = manager.compare(['in', 'nosshfp'],
|
||||
['dump'],
|
||||
'unit.tests.')
|
||||
self.assertEquals(16, len(changes))
|
||||
self.assertEquals(18, len(changes))
|
||||
|
||||
with self.assertRaises(ManagerException) as ctx:
|
||||
manager.compare(['nope'], ['dump'], 'unit.tests.')
|
||||
|
||||
@@ -184,7 +184,7 @@ class TestCloudflareProvider(TestCase):
|
||||
|
||||
zone = Zone('unit.tests.', [])
|
||||
provider.populate(zone)
|
||||
self.assertEquals(14, len(zone.records))
|
||||
self.assertEquals(16, len(zone.records))
|
||||
|
||||
changes = self.expected.changes(zone, provider)
|
||||
|
||||
@@ -193,7 +193,7 @@ class TestCloudflareProvider(TestCase):
|
||||
# re-populating the same zone/records comes out of cache, no calls
|
||||
again = Zone('unit.tests.', [])
|
||||
provider.populate(again)
|
||||
self.assertEquals(14, len(again.records))
|
||||
self.assertEquals(16, len(again.records))
|
||||
|
||||
def test_apply(self):
|
||||
provider = CloudflareProvider('test', 'email', 'token', retry_period=0)
|
||||
@@ -207,12 +207,12 @@ class TestCloudflareProvider(TestCase):
|
||||
'id': 42,
|
||||
}
|
||||
}, # zone create
|
||||
] + [None] * 24 # individual record creates
|
||||
] + [None] * 25 # individual record creates
|
||||
|
||||
# non-existent zone, create everything
|
||||
plan = provider.plan(self.expected)
|
||||
self.assertEquals(14, len(plan.changes))
|
||||
self.assertEquals(14, provider.apply(plan))
|
||||
self.assertEquals(16, len(plan.changes))
|
||||
self.assertEquals(16, provider.apply(plan))
|
||||
self.assertFalse(plan.exists)
|
||||
|
||||
provider._request.assert_has_calls([
|
||||
@@ -238,7 +238,7 @@ class TestCloudflareProvider(TestCase):
|
||||
}),
|
||||
], True)
|
||||
# expected number of total calls
|
||||
self.assertEquals(25, provider._request.call_count)
|
||||
self.assertEquals(27, provider._request.call_count)
|
||||
|
||||
provider._request.reset_mock()
|
||||
|
||||
|
||||
@@ -101,14 +101,14 @@ class TestConstellixProvider(TestCase):
|
||||
|
||||
zone = Zone('unit.tests.', [])
|
||||
provider.populate(zone)
|
||||
self.assertEquals(14, len(zone.records))
|
||||
self.assertEquals(16, len(zone.records))
|
||||
changes = self.expected.changes(zone, provider)
|
||||
self.assertEquals(0, len(changes))
|
||||
|
||||
# 2nd populate makes no network calls/all from cache
|
||||
again = Zone('unit.tests.', [])
|
||||
provider.populate(again)
|
||||
self.assertEquals(14, len(again.records))
|
||||
self.assertEquals(16, len(again.records))
|
||||
|
||||
# bust the cache
|
||||
del provider._zone_records[zone.name]
|
||||
@@ -163,7 +163,7 @@ class TestConstellixProvider(TestCase):
|
||||
}),
|
||||
])
|
||||
|
||||
self.assertEquals(17, provider._client._request.call_count)
|
||||
self.assertEquals(19, provider._client._request.call_count)
|
||||
|
||||
provider._client._request.reset_mock()
|
||||
|
||||
|
||||
@@ -83,14 +83,14 @@ class TestDigitalOceanProvider(TestCase):
|
||||
|
||||
zone = Zone('unit.tests.', [])
|
||||
provider.populate(zone)
|
||||
self.assertEquals(12, len(zone.records))
|
||||
self.assertEquals(14, len(zone.records))
|
||||
changes = self.expected.changes(zone, provider)
|
||||
self.assertEquals(0, len(changes))
|
||||
|
||||
# 2nd populate makes no network calls/all from cache
|
||||
again = Zone('unit.tests.', [])
|
||||
provider.populate(again)
|
||||
self.assertEquals(12, len(again.records))
|
||||
self.assertEquals(14, len(again.records))
|
||||
|
||||
# bust the cache
|
||||
del provider._zone_records[zone.name]
|
||||
@@ -190,6 +190,24 @@ class TestDigitalOceanProvider(TestCase):
|
||||
'flags': 0, 'name': '@',
|
||||
'tag': 'issue',
|
||||
'ttl': 3600, 'type': 'CAA'}),
|
||||
call('POST', '/domains/unit.tests/records', data={
|
||||
'name': '_imap._tcp',
|
||||
'weight': 0,
|
||||
'data': '.',
|
||||
'priority': 0,
|
||||
'ttl': 600,
|
||||
'type': 'SRV',
|
||||
'port': 0
|
||||
}),
|
||||
call('POST', '/domains/unit.tests/records', data={
|
||||
'name': '_pop3._tcp',
|
||||
'weight': 0,
|
||||
'data': '.',
|
||||
'priority': 0,
|
||||
'ttl': 600,
|
||||
'type': 'SRV',
|
||||
'port': 0
|
||||
}),
|
||||
call('POST', '/domains/unit.tests/records', data={
|
||||
'name': '_srv._tcp',
|
||||
'weight': 20,
|
||||
@@ -200,7 +218,7 @@ class TestDigitalOceanProvider(TestCase):
|
||||
'port': 30
|
||||
}),
|
||||
])
|
||||
self.assertEquals(24, provider._client._request.call_count)
|
||||
self.assertEquals(26, provider._client._request.call_count)
|
||||
|
||||
provider._client._request.reset_mock()
|
||||
|
||||
|
||||
@@ -136,8 +136,8 @@ class TestDnsimpleProvider(TestCase):
|
||||
]
|
||||
plan = provider.plan(self.expected)
|
||||
|
||||
# No root NS, no ignored, no excluded, no unsupported
|
||||
n = len(self.expected.records) - 5
|
||||
# No root NS, no ignored, no excluded
|
||||
n = len(self.expected.records) - 7
|
||||
self.assertEquals(n, len(plan.changes))
|
||||
self.assertEquals(n, provider.apply(plan))
|
||||
self.assertFalse(plan.exists)
|
||||
|
||||
@@ -134,7 +134,7 @@ class TestDnsMadeEasyProvider(TestCase):
|
||||
plan = provider.plan(self.expected)
|
||||
|
||||
# No root NS, no ignored, no excluded, no unsupported
|
||||
n = len(self.expected.records) - 7
|
||||
n = len(self.expected.records) - 9
|
||||
self.assertEquals(n, len(plan.changes))
|
||||
self.assertEquals(n, provider.apply(plan))
|
||||
|
||||
|
||||
@@ -80,14 +80,14 @@ class TestEasyDNSProvider(TestCase):
|
||||
text=fh.read())
|
||||
|
||||
provider.populate(zone)
|
||||
self.assertEquals(13, len(zone.records))
|
||||
self.assertEquals(15, len(zone.records))
|
||||
changes = self.expected.changes(zone, provider)
|
||||
self.assertEquals(0, len(changes))
|
||||
|
||||
# 2nd populate makes no network calls/all from cache
|
||||
again = Zone('unit.tests.', [])
|
||||
provider.populate(again)
|
||||
self.assertEquals(13, len(again.records))
|
||||
self.assertEquals(15, len(again.records))
|
||||
|
||||
# bust the cache
|
||||
del provider._zone_records[zone.name]
|
||||
@@ -379,7 +379,7 @@ class TestEasyDNSProvider(TestCase):
|
||||
self.assertEquals(n, provider.apply(plan))
|
||||
self.assertFalse(plan.exists)
|
||||
|
||||
self.assertEquals(23, provider._client._request.call_count)
|
||||
self.assertEquals(25, provider._client._request.call_count)
|
||||
|
||||
provider._client._request.reset_mock()
|
||||
|
||||
|
||||
@@ -77,14 +77,14 @@ class TestEdgeDnsProvider(TestCase):
|
||||
|
||||
zone = Zone('unit.tests.', [])
|
||||
provider.populate(zone)
|
||||
self.assertEquals(16, len(zone.records))
|
||||
self.assertEquals(18, len(zone.records))
|
||||
changes = self.expected.changes(zone, provider)
|
||||
self.assertEquals(0, len(changes))
|
||||
|
||||
# 2nd populate makes no network calls/all from cache
|
||||
again = Zone('unit.tests.', [])
|
||||
provider.populate(again)
|
||||
self.assertEquals(16, len(again.records))
|
||||
self.assertEquals(18, len(again.records))
|
||||
|
||||
# bust the cache
|
||||
del provider._zone_records[zone.name]
|
||||
@@ -105,7 +105,7 @@ class TestEdgeDnsProvider(TestCase):
|
||||
mock.delete(ANY, status_code=204)
|
||||
|
||||
changes = provider.apply(plan)
|
||||
self.assertEquals(29, changes)
|
||||
self.assertEquals(31, changes)
|
||||
|
||||
# Test against a zone that doesn't exist yet
|
||||
with requests_mock() as mock:
|
||||
@@ -118,7 +118,7 @@ class TestEdgeDnsProvider(TestCase):
|
||||
mock.delete(ANY, status_code=204)
|
||||
|
||||
changes = provider.apply(plan)
|
||||
self.assertEquals(14, changes)
|
||||
self.assertEquals(16, changes)
|
||||
|
||||
# Test against a zone that doesn't exist yet, but gid not provided
|
||||
with requests_mock() as mock:
|
||||
@@ -132,7 +132,7 @@ class TestEdgeDnsProvider(TestCase):
|
||||
mock.delete(ANY, status_code=204)
|
||||
|
||||
changes = provider.apply(plan)
|
||||
self.assertEquals(14, changes)
|
||||
self.assertEquals(16, changes)
|
||||
|
||||
# Test against a zone that doesn't exist, but cid not provided
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ class TestGandiProvider(TestCase):
|
||||
|
||||
zone = Zone('unit.tests.', [])
|
||||
provider.populate(zone)
|
||||
self.assertEquals(14, len(zone.records))
|
||||
self.assertEquals(16, len(zone.records))
|
||||
changes = self.expected.changes(zone, provider)
|
||||
self.assertEquals(0, len(changes))
|
||||
|
||||
@@ -284,6 +284,22 @@ class TestGandiProvider(TestCase):
|
||||
'12 20 30 foo-2.unit.tests.'
|
||||
]
|
||||
}),
|
||||
call('POST', '/livedns/domains/unit.tests/records', data={
|
||||
'rrset_name': '_pop3._tcp',
|
||||
'rrset_ttl': 600,
|
||||
'rrset_type': 'SRV',
|
||||
'rrset_values': [
|
||||
'0 0 0 .',
|
||||
]
|
||||
}),
|
||||
call('POST', '/livedns/domains/unit.tests/records', data={
|
||||
'rrset_name': '_imap._tcp',
|
||||
'rrset_ttl': 600,
|
||||
'rrset_type': 'SRV',
|
||||
'rrset_values': [
|
||||
'0 0 0 .',
|
||||
]
|
||||
}),
|
||||
call('POST', '/livedns/domains/unit.tests/records', data={
|
||||
'rrset_name': '@',
|
||||
'rrset_ttl': 3600,
|
||||
@@ -307,7 +323,7 @@ class TestGandiProvider(TestCase):
|
||||
})
|
||||
])
|
||||
# expected number of total calls
|
||||
self.assertEquals(17, provider._client._request.call_count)
|
||||
self.assertEquals(19, provider._client._request.call_count)
|
||||
|
||||
provider._client._request.reset_mock()
|
||||
|
||||
|
||||
@@ -378,8 +378,8 @@ class TestMythicBeastsProvider(TestCase):
|
||||
zone = Zone('unit.tests.', [])
|
||||
provider.populate(zone)
|
||||
|
||||
self.assertEquals(15, len(zone.records))
|
||||
self.assertEquals(15, len(self.expected.records))
|
||||
self.assertEquals(17, len(zone.records))
|
||||
self.assertEquals(17, len(self.expected.records))
|
||||
changes = self.expected.changes(zone, provider)
|
||||
self.assertEquals(0, len(changes))
|
||||
|
||||
@@ -445,7 +445,7 @@ class TestMythicBeastsProvider(TestCase):
|
||||
if isinstance(c, Update)]))
|
||||
self.assertEquals(1, len([c for c in plan.changes
|
||||
if isinstance(c, Delete)]))
|
||||
self.assertEquals(14, len([c for c in plan.changes
|
||||
self.assertEquals(16, len([c for c in plan.changes
|
||||
if isinstance(c, Create)]))
|
||||
self.assertEquals(16, provider.apply(plan))
|
||||
self.assertEquals(18, provider.apply(plan))
|
||||
self.assertTrue(plan.exists)
|
||||
|
||||
@@ -186,7 +186,7 @@ class TestPowerDnsProvider(TestCase):
|
||||
source = YamlProvider('test', join(dirname(__file__), 'config'))
|
||||
source.populate(expected)
|
||||
expected_n = len(expected.records) - 3
|
||||
self.assertEquals(17, expected_n)
|
||||
self.assertEquals(19, expected_n)
|
||||
|
||||
# No diffs == no changes
|
||||
with requests_mock() as mock:
|
||||
@@ -194,7 +194,7 @@ class TestPowerDnsProvider(TestCase):
|
||||
|
||||
zone = Zone('unit.tests.', [])
|
||||
provider.populate(zone)
|
||||
self.assertEquals(17, len(zone.records))
|
||||
self.assertEquals(19, len(zone.records))
|
||||
changes = expected.changes(zone, provider)
|
||||
self.assertEquals(0, len(changes))
|
||||
|
||||
@@ -291,7 +291,7 @@ class TestPowerDnsProvider(TestCase):
|
||||
expected = Zone('unit.tests.', [])
|
||||
source = YamlProvider('test', join(dirname(__file__), 'config'))
|
||||
source.populate(expected)
|
||||
self.assertEquals(20, len(expected.records))
|
||||
self.assertEquals(22, len(expected.records))
|
||||
|
||||
# A small change to a single record
|
||||
with requests_mock() as mock:
|
||||
|
||||
@@ -222,7 +222,7 @@ N4OiVz1I3rbZGYa396lpxO6ku8yCglisL1yrSP6DdEUp66ntpKVd
|
||||
provider._client = MockDomainService('unittest', self.bogus_key)
|
||||
plan = provider.plan(_expected)
|
||||
|
||||
self.assertEqual(12, plan.change_counts['Create'])
|
||||
self.assertEqual(14, plan.change_counts['Create'])
|
||||
self.assertEqual(0, plan.change_counts['Update'])
|
||||
self.assertEqual(0, plan.change_counts['Delete'])
|
||||
|
||||
@@ -235,7 +235,7 @@ N4OiVz1I3rbZGYa396lpxO6ku8yCglisL1yrSP6DdEUp66ntpKVd
|
||||
provider = TransipProvider('test', 'unittest', self.bogus_key)
|
||||
provider._client = MockDomainService('unittest', self.bogus_key)
|
||||
plan = provider.plan(_expected)
|
||||
self.assertEqual(12, len(plan.changes))
|
||||
self.assertEqual(14, len(plan.changes))
|
||||
changes = provider.apply(plan)
|
||||
self.assertEqual(changes, len(plan.changes))
|
||||
|
||||
|
||||
@@ -285,12 +285,12 @@ class TestUltraProvider(TestCase):
|
||||
provider._request.side_effect = [
|
||||
UltraNoZonesExistException('No Zones'),
|
||||
None, # zone create
|
||||
] + [None] * 13 # individual record creates
|
||||
] + [None] * 15 # individual record creates
|
||||
|
||||
# non-existent zone, create everything
|
||||
plan = provider.plan(self.expected)
|
||||
self.assertEquals(13, len(plan.changes))
|
||||
self.assertEquals(13, provider.apply(plan))
|
||||
self.assertEquals(15, len(plan.changes))
|
||||
self.assertEquals(15, provider.apply(plan))
|
||||
self.assertFalse(plan.exists)
|
||||
|
||||
provider._request.assert_has_calls([
|
||||
@@ -320,7 +320,7 @@ class TestUltraProvider(TestCase):
|
||||
'p=A/kinda+of/long/string+with+numb3rs']}),
|
||||
], True)
|
||||
# expected number of total calls
|
||||
self.assertEquals(15, provider._request.call_count)
|
||||
self.assertEquals(17, provider._request.call_count)
|
||||
|
||||
# Create sample rrset payload to attempt to alter
|
||||
page1 = json_load(open('tests/fixtures/ultra-records-page-1.json'))
|
||||
|
||||
@@ -35,7 +35,7 @@ class TestYamlProvider(TestCase):
|
||||
|
||||
# without it we see everything
|
||||
source.populate(zone)
|
||||
self.assertEquals(20, len(zone.records))
|
||||
self.assertEquals(22, len(zone.records))
|
||||
|
||||
source.populate(dynamic_zone)
|
||||
self.assertEquals(5, len(dynamic_zone.records))
|
||||
@@ -58,12 +58,12 @@ class TestYamlProvider(TestCase):
|
||||
|
||||
# We add everything
|
||||
plan = target.plan(zone)
|
||||
self.assertEquals(17, len([c for c in plan.changes
|
||||
self.assertEquals(19, len([c for c in plan.changes
|
||||
if isinstance(c, Create)]))
|
||||
self.assertFalse(isfile(yaml_file))
|
||||
|
||||
# Now actually do it
|
||||
self.assertEquals(17, target.apply(plan))
|
||||
self.assertEquals(19, target.apply(plan))
|
||||
self.assertTrue(isfile(yaml_file))
|
||||
|
||||
# Dynamic plan
|
||||
@@ -87,7 +87,7 @@ class TestYamlProvider(TestCase):
|
||||
|
||||
# A 2nd sync should still create everything
|
||||
plan = target.plan(zone)
|
||||
self.assertEquals(17, len([c for c in plan.changes
|
||||
self.assertEquals(19, len([c for c in plan.changes
|
||||
if isinstance(c, Create)]))
|
||||
|
||||
with open(yaml_file) as fh:
|
||||
@@ -108,6 +108,8 @@ class TestYamlProvider(TestCase):
|
||||
self.assertTrue('values' in data.pop('txt'))
|
||||
self.assertTrue('values' in data.pop('loc'))
|
||||
# these are stored as singular 'value'
|
||||
self.assertTrue('value' in data.pop('_imap._tcp'))
|
||||
self.assertTrue('value' in data.pop('_pop3._tcp'))
|
||||
self.assertTrue('value' in data.pop('aaaa'))
|
||||
self.assertTrue('value' in data.pop('cname'))
|
||||
self.assertTrue('value' in data.pop('dname'))
|
||||
|
||||
@@ -36,7 +36,7 @@ class TestAxfrSource(TestCase):
|
||||
]
|
||||
|
||||
self.source.populate(got)
|
||||
self.assertEquals(13, len(got.records))
|
||||
self.assertEquals(15, len(got.records))
|
||||
|
||||
with self.assertRaises(AxfrSourceZoneTransferFailed) as ctx:
|
||||
zone = Zone('unit.tests.', [])
|
||||
@@ -73,18 +73,18 @@ class TestZoneFileSource(TestCase):
|
||||
# Load zonefiles without a specified file extension
|
||||
valid = Zone('unit.tests.', [])
|
||||
source.populate(valid)
|
||||
self.assertEquals(13, len(valid.records))
|
||||
self.assertEquals(15, len(valid.records))
|
||||
|
||||
def test_populate(self):
|
||||
# Valid zone file in directory
|
||||
valid = Zone('unit.tests.', [])
|
||||
self.source.populate(valid)
|
||||
self.assertEquals(13, len(valid.records))
|
||||
self.assertEquals(15, len(valid.records))
|
||||
|
||||
# 2nd populate does not read file again
|
||||
again = Zone('unit.tests.', [])
|
||||
self.source.populate(again)
|
||||
self.assertEquals(13, len(again.records))
|
||||
self.assertEquals(15, len(again.records))
|
||||
|
||||
# bust the cache
|
||||
del self.source._zone_records[valid.name]
|
||||
|
||||
@@ -20,6 +20,9 @@ caa 1800 IN CAA 0 iodef "mailto:[email protected]"
|
||||
; SRV Records
|
||||
_srv._tcp 600 IN SRV 10 20 30 foo-1.unit.tests.
|
||||
_srv._tcp 600 IN SRV 10 20 30 foo-2.unit.tests.
|
||||
; NULL SRV Records
|
||||
_pop3._tcp 600 IN SRV 0 0 0 .
|
||||
_imap._tcp 600 IN SRV 0 0 0 .
|
||||
|
||||
; TXT Records
|
||||
txt 600 IN TXT "Bah bah black sheep"
|
||||
|
||||
Reference in New Issue
Block a user