mirror of
https://github.com/github/octodns.git
synced 2024-05-11 05:55:00 +00:00
Add CAA for CF, DNSimple, and README
This commit is contained in:
@@ -150,12 +150,12 @@ The above command pulled the existing data out of Route53 and placed the results
|
|||||||
| Provider | Record Support | GeoDNS Support | Notes |
|
| Provider | Record Support | GeoDNS Support | Notes |
|
||||||
|--|--|--|--|
|
|--|--|--|--|
|
||||||
| [AzureProvider](/octodns/provider/azuredns.py) | A, AAAA, CNAME, MX, NS, PTR, SRV, TXT | No | |
|
| [AzureProvider](/octodns/provider/azuredns.py) | A, AAAA, CNAME, MX, NS, PTR, SRV, TXT | No | |
|
||||||
| [CloudflareProvider](/octodns/provider/cloudflare.py) | A, AAAA, CNAME, MX, NS, SPF, TXT | No | |
|
| [CloudflareProvider](/octodns/provider/cloudflare.py) | A, AAAA, CAA, CNAME, MX, NS, SPF, TXT | No | CAA tags restricted |
|
||||||
| [DnsimpleProvider](/octodns/provider/dnsimple.py) | All | No | |
|
| [DnsimpleProvider](/octodns/provider/dnsimple.py) | All | No | CAA tags restricted |
|
||||||
| [DynProvider](/octodns/provider/dyn.py) | All | Yes | |
|
| [DynProvider](/octodns/provider/dyn.py) | All | Yes | |
|
||||||
| [Ns1Provider](/octodns/provider/ns1.py) | All | No | |
|
| [Ns1Provider](/octodns/provider/ns1.py) | All | No | |
|
||||||
| [PowerDnsProvider](/octodns/provider/powerdns.py) | All | No | |
|
| [PowerDnsProvider](/octodns/provider/powerdns.py) | All | No | |
|
||||||
| [Route53](/octodns/provider/route53.py) | A, AAAA, CNAME, MX, NAPTR, NS, PTR, SPF, SRV, TXT | Yes | |
|
| [Route53](/octodns/provider/route53.py) | A, AAAA, CAA, CNAME, MX, NAPTR, NS, PTR, SPF, SRV, TXT | Yes | |
|
||||||
| [TinyDNSSource](/octodns/source/tinydns.py) | A, CNAME, MX, NS, PTR | No | read-only |
|
| [TinyDNSSource](/octodns/source/tinydns.py) | A, CNAME, MX, NS, PTR | No | read-only |
|
||||||
| [YamlProvider](/octodns/provider/yaml.py) | All | Yes | config |
|
| [YamlProvider](/octodns/provider/yaml.py) | All | Yes | config |
|
||||||
|
|
||||||
|
@@ -36,7 +36,7 @@ class CloudflareProvider(BaseProvider):
|
|||||||
'''
|
'''
|
||||||
SUPPORTS_GEO = False
|
SUPPORTS_GEO = False
|
||||||
# TODO: support SRV
|
# TODO: support SRV
|
||||||
SUPPORTS = set(('A', 'AAAA', 'CNAME', 'MX', 'NS', 'SPF', 'TXT'))
|
SUPPORTS = set(('A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'SPF', 'TXT'))
|
||||||
|
|
||||||
MIN_TTL = 120
|
MIN_TTL = 120
|
||||||
TIMEOUT = 15
|
TIMEOUT = 15
|
||||||
@@ -104,6 +104,20 @@ class CloudflareProvider(BaseProvider):
|
|||||||
'values': [r['content'].replace(';', '\;') for r in records],
|
'values': [r['content'].replace(';', '\;') for r in records],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _data_for_CAA(self, _type, records):
|
||||||
|
values = []
|
||||||
|
for r in records:
|
||||||
|
values.append({
|
||||||
|
'flags': r['flags'],
|
||||||
|
'tag': r['tag'],
|
||||||
|
'value': r['content'],
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
'ttl': records[0]['ttl'],
|
||||||
|
'type': _type,
|
||||||
|
'values': values,
|
||||||
|
}
|
||||||
|
|
||||||
def _data_for_CNAME(self, _type, records):
|
def _data_for_CNAME(self, _type, records):
|
||||||
only = records[0]
|
only = records[0]
|
||||||
return {
|
return {
|
||||||
@@ -197,6 +211,14 @@ class CloudflareProvider(BaseProvider):
|
|||||||
_contents_for_NS = _contents_for_multiple
|
_contents_for_NS = _contents_for_multiple
|
||||||
_contents_for_SPF = _contents_for_multiple
|
_contents_for_SPF = _contents_for_multiple
|
||||||
|
|
||||||
|
def _contents_for_CAA(self, record):
|
||||||
|
for value in record.values:
|
||||||
|
yield {
|
||||||
|
'flags': value.flags,
|
||||||
|
'tag': value.tag,
|
||||||
|
'value': value.value,
|
||||||
|
}
|
||||||
|
|
||||||
def _contents_for_TXT(self, record):
|
def _contents_for_TXT(self, record):
|
||||||
for value in record.values:
|
for value in record.values:
|
||||||
yield {'content': value.replace('\;', ';')}
|
yield {'content': value.replace('\;', ';')}
|
||||||
|
@@ -91,8 +91,8 @@ class DnsimpleProvider(BaseProvider):
|
|||||||
account: 42
|
account: 42
|
||||||
'''
|
'''
|
||||||
SUPPORTS_GEO = False
|
SUPPORTS_GEO = False
|
||||||
SUPPORTS = set(('A', 'AAAA', 'ALIAS', 'CNAME', 'MX', 'NAPTR', 'NS', 'PTR',
|
SUPPORTS = set(('A', 'AAAA', 'ALIAS', 'CAA', 'CNAME', 'MX', 'NAPTR', 'NS',
|
||||||
'SPF', 'SRV', 'SSHFP', 'TXT'))
|
'PTR', 'SPF', 'SRV', 'SSHFP', 'TXT'))
|
||||||
|
|
||||||
def __init__(self, id, token, account, *args, **kwargs):
|
def __init__(self, id, token, account, *args, **kwargs):
|
||||||
self.log = logging.getLogger('DnsimpleProvider[{}]'.format(id))
|
self.log = logging.getLogger('DnsimpleProvider[{}]'.format(id))
|
||||||
@@ -114,6 +114,21 @@ class DnsimpleProvider(BaseProvider):
|
|||||||
_data_for_SPF = _data_for_multiple
|
_data_for_SPF = _data_for_multiple
|
||||||
_data_for_TXT = _data_for_multiple
|
_data_for_TXT = _data_for_multiple
|
||||||
|
|
||||||
|
def _data_for_CAA(self, _type, records):
|
||||||
|
values = []
|
||||||
|
for record in records:
|
||||||
|
flags, tag, value = record['content'].split(' ')
|
||||||
|
values.append({
|
||||||
|
'flags': flags,
|
||||||
|
'tag': tag,
|
||||||
|
'value': value[1:-1],
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
'ttl': records[0]['ttl'],
|
||||||
|
'type': _type,
|
||||||
|
'values': values
|
||||||
|
}
|
||||||
|
|
||||||
def _data_for_CNAME(self, _type, records):
|
def _data_for_CNAME(self, _type, records):
|
||||||
record = records[0]
|
record = records[0]
|
||||||
return {
|
return {
|
||||||
@@ -275,6 +290,16 @@ class DnsimpleProvider(BaseProvider):
|
|||||||
_params_for_SPF = _params_for_multiple
|
_params_for_SPF = _params_for_multiple
|
||||||
_params_for_TXT = _params_for_multiple
|
_params_for_TXT = _params_for_multiple
|
||||||
|
|
||||||
|
def _params_for_CAA(self, record):
|
||||||
|
for value in record.values:
|
||||||
|
yield {
|
||||||
|
'content': '{} {} "{}"'.format(value.flags, value.tag,
|
||||||
|
value.value),
|
||||||
|
'name': record.name,
|
||||||
|
'ttl': record.ttl,
|
||||||
|
'type': record._type
|
||||||
|
}
|
||||||
|
|
||||||
def _params_for_single(self, record):
|
def _params_for_single(self, record):
|
||||||
yield {
|
yield {
|
||||||
'content': record.value,
|
'content': record.value,
|
||||||
|
@@ -118,14 +118,33 @@
|
|||||||
"meta": {
|
"meta": {
|
||||||
"auto_added": false
|
"auto_added": false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "fc223b34cd5611334422ab3322997667",
|
||||||
|
"type": "CAA",
|
||||||
|
"name": "unit.tests",
|
||||||
|
"content": "ca.unit.tests",
|
||||||
|
"flags": 0,
|
||||||
|
"tag": "issue",
|
||||||
|
"proxiable": false,
|
||||||
|
"proxied": false,
|
||||||
|
"ttl": 3600,
|
||||||
|
"locked": false,
|
||||||
|
"zone_id": "ff12ab34cd5611334422ab3322997650",
|
||||||
|
"zone_name": "unit.tests",
|
||||||
|
"modified_on": "2017-03-11T18:01:42.961566Z",
|
||||||
|
"created_on": "2017-03-11T18:01:42.961566Z",
|
||||||
|
"meta": {
|
||||||
|
"auto_added": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"result_info": {
|
"result_info": {
|
||||||
"page": 2,
|
"page": 2,
|
||||||
"per_page": 10,
|
"per_page": 10,
|
||||||
"total_pages": 2,
|
"total_pages": 2,
|
||||||
"count": 7,
|
"count": 8,
|
||||||
"total_count": 17
|
"total_count": 19
|
||||||
},
|
},
|
||||||
"success": true,
|
"success": true,
|
||||||
"errors": [],
|
"errors": [],
|
||||||
|
18
tests/fixtures/dnsimple-page-2.json
vendored
18
tests/fixtures/dnsimple-page-2.json
vendored
@@ -159,12 +159,28 @@
|
|||||||
"system_record": false,
|
"system_record": false,
|
||||||
"created_at": "2017-03-09T15:55:09Z",
|
"created_at": "2017-03-09T15:55:09Z",
|
||||||
"updated_at": "2017-03-09T15:55:09Z"
|
"updated_at": "2017-03-09T15:55:09Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 12188803,
|
||||||
|
"zone_id": "unit.tests",
|
||||||
|
"parent_id": null,
|
||||||
|
"name": "",
|
||||||
|
"content": "0 issue \"ca.unit.tests\"",
|
||||||
|
"ttl": 3600,
|
||||||
|
"priority": null,
|
||||||
|
"type": "CAA",
|
||||||
|
"regions": [
|
||||||
|
"global"
|
||||||
|
],
|
||||||
|
"system_record": false,
|
||||||
|
"created_at": "2017-03-09T15:55:09Z",
|
||||||
|
"updated_at": "2017-03-09T15:55:09Z"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"pagination": {
|
"pagination": {
|
||||||
"current_page": 2,
|
"current_page": 2,
|
||||||
"per_page": 20,
|
"per_page": 20,
|
||||||
"total_entries": 29,
|
"total_entries": 30,
|
||||||
"total_pages": 2
|
"total_pages": 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -118,7 +118,7 @@ class TestCloudflareProvider(TestCase):
|
|||||||
|
|
||||||
zone = Zone('unit.tests.', [])
|
zone = Zone('unit.tests.', [])
|
||||||
provider.populate(zone)
|
provider.populate(zone)
|
||||||
self.assertEquals(9, len(zone.records))
|
self.assertEquals(10, len(zone.records))
|
||||||
|
|
||||||
changes = self.expected.changes(zone, provider)
|
changes = self.expected.changes(zone, provider)
|
||||||
self.assertEquals(0, len(changes))
|
self.assertEquals(0, len(changes))
|
||||||
@@ -126,7 +126,7 @@ class TestCloudflareProvider(TestCase):
|
|||||||
# re-populating the same zone/records comes out of cache, no calls
|
# re-populating the same zone/records comes out of cache, no calls
|
||||||
again = Zone('unit.tests.', [])
|
again = Zone('unit.tests.', [])
|
||||||
provider.populate(again)
|
provider.populate(again)
|
||||||
self.assertEquals(9, len(again.records))
|
self.assertEquals(10, len(again.records))
|
||||||
|
|
||||||
def test_apply(self):
|
def test_apply(self):
|
||||||
provider = CloudflareProvider('test', 'email', 'token')
|
provider = CloudflareProvider('test', 'email', 'token')
|
||||||
@@ -140,12 +140,12 @@ class TestCloudflareProvider(TestCase):
|
|||||||
'id': 42,
|
'id': 42,
|
||||||
}
|
}
|
||||||
}, # zone create
|
}, # zone create
|
||||||
] + [None] * 16 # individual record creates
|
] + [None] * 17 # individual record creates
|
||||||
|
|
||||||
# non-existant zone, create everything
|
# non-existant zone, create everything
|
||||||
plan = provider.plan(self.expected)
|
plan = provider.plan(self.expected)
|
||||||
self.assertEquals(9, len(plan.changes))
|
self.assertEquals(10, len(plan.changes))
|
||||||
self.assertEquals(9, provider.apply(plan))
|
self.assertEquals(10, provider.apply(plan))
|
||||||
|
|
||||||
provider._request.assert_has_calls([
|
provider._request.assert_has_calls([
|
||||||
# created the domain
|
# created the domain
|
||||||
@@ -170,7 +170,7 @@ class TestCloudflareProvider(TestCase):
|
|||||||
}),
|
}),
|
||||||
], True)
|
], True)
|
||||||
# expected number of total calls
|
# expected number of total calls
|
||||||
self.assertEquals(18, provider._request.call_count)
|
self.assertEquals(19, provider._request.call_count)
|
||||||
|
|
||||||
provider._request.reset_mock()
|
provider._request.reset_mock()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user