From c848860b1f9286c343849d91178539265e037af4 Mon Sep 17 00:00:00 2001 From: Paul van Brouwershaven Date: Fri, 2 Feb 2018 09:33:02 +0100 Subject: [PATCH] Add SRV support to Cloudflare provider --- README.md | 2 +- octodns/provider/cloudflare.py | 35 ++++++++++-- .../cloudflare-dns_records-page-2.json | 54 ++++++++++++++++++- tests/test_octodns_provider_cloudflare.py | 13 ++--- 4 files changed, 92 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index af8d14f..b99e836 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,7 @@ The above command pulled the existing data out of Route53 and placed the results | Provider | Record Support | GeoDNS Support | Notes | |--|--|--|--| | [AzureProvider](/octodns/provider/azuredns.py) | A, AAAA, CNAME, MX, NS, PTR, SRV, TXT | No | | -| [CloudflareProvider](/octodns/provider/cloudflare.py) | A, AAAA, ALIAS, CAA, CNAME, MX, NS, SPF, TXT | No | CAA tags restricted | +| [CloudflareProvider](/octodns/provider/cloudflare.py) | A, AAAA, ALIAS, CAA, CNAME, MX, NS, SPF, SRV, TXT | No | CAA tags restricted | | [DigitalOceanProvider](/octodns/provider/digitalocean.py) | A, AAAA, CAA, CNAME, MX, NS, TXT, SRV | No | CAA tags restricted | | [DnsMadeEasyProvider](/octodns/provider/dnsmadeeasy.py) | A, AAAA, CAA, CNAME, MX, NS, PTR, SPF, SRV, TXT | No | CAA tags restricted | | [DnsimpleProvider](/octodns/provider/dnsimple.py) | All | No | CAA tags restricted | diff --git a/octodns/provider/cloudflare.py b/octodns/provider/cloudflare.py index 9dfef6d..f76e0aa 100644 --- a/octodns/provider/cloudflare.py +++ b/octodns/provider/cloudflare.py @@ -36,9 +36,8 @@ class CloudflareProvider(BaseProvider): token: foo ''' SUPPORTS_GEO = False - # TODO: support SRV - SUPPORTS = set(('ALIAS', 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'SPF', - 'TXT')) + SUPPORTS = set(('ALIAS', 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'SRV', + 'SPF', 'TXT')) MIN_TTL = 120 TIMEOUT = 15 @@ -147,6 +146,21 @@ class CloudflareProvider(BaseProvider): 'values': ['{}.'.format(r['content']) for r in records], } + def _data_for_SRV(self, _type, records): + values = [] + for r in records: + values.append({ + 'priority': r['data']['priority'], + 'weight': r['data']['weight'], + 'port': r['data']['port'], + 'target': '{}.'.format(r['data']['target']), + }) + return { + 'type': _type, + 'ttl': records[0]['ttl'], + 'values': values + } + def zone_records(self, zone): if zone.name not in self._zone_records: zone_id = self.zones.get(zone.name, False) @@ -241,6 +255,21 @@ class CloudflareProvider(BaseProvider): 'content': value.exchange } + def _contents_for_SRV(self, record): + service, proto = record.name.split('.', 2) + for value in record.values: + yield { + 'data': { + 'service': service, + 'proto': proto, + 'name': record.zone.name, + 'priority': value.priority, + 'weight': value.weight, + 'port': value.port, + 'target': value.target[:-1], + } + } + def _gen_contents(self, record): name = record.fqdn[:-1] _type = record._type diff --git a/tests/fixtures/cloudflare-dns_records-page-2.json b/tests/fixtures/cloudflare-dns_records-page-2.json index de3d760..558aa2c 100644 --- a/tests/fixtures/cloudflare-dns_records-page-2.json +++ b/tests/fixtures/cloudflare-dns_records-page-2.json @@ -156,14 +156,64 @@ "meta": { "auto_added": false } + }, + { + "id": "fc12ab34cd5611334422ab3322997656", + "type": "SRV", + "name": "_srv._tcp.unit.tests", + "data": { + "service": "_srv", + "proto": "_tcp", + "name": "unit.tests", + "priority": 12, + "weight": 20, + "port": 30, + "target": "foo-2.unit.tests" + }, + "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": "_srv._tcp.unit.tests", + "data": { + "service": "_srv", + "proto": "_tcp", + "name": "unit.tests", + "priority": 10, + "weight": 20, + "port": 30, + "target": "foo-1.unit.tests" + }, + "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": { "page": 2, - "per_page": 10, + "per_page": 11, "total_pages": 2, "count": 9, - "total_count": 19 + "total_count": 21 }, "success": true, "errors": [], diff --git a/tests/test_octodns_provider_cloudflare.py b/tests/test_octodns_provider_cloudflare.py index 824af9d..2a71e8f 100644 --- a/tests/test_octodns_provider_cloudflare.py +++ b/tests/test_octodns_provider_cloudflare.py @@ -119,15 +119,16 @@ class TestCloudflareProvider(TestCase): zone = Zone('unit.tests.', []) provider.populate(zone) - self.assertEquals(11, len(zone.records)) + self.assertEquals(12, len(zone.records)) changes = self.expected.changes(zone, provider) + self.assertEquals(0, len(changes)) # re-populating the same zone/records comes out of cache, no calls again = Zone('unit.tests.', []) provider.populate(again) - self.assertEquals(11, len(again.records)) + self.assertEquals(12, len(again.records)) def test_apply(self): provider = CloudflareProvider('test', 'email', 'token') @@ -141,12 +142,12 @@ class TestCloudflareProvider(TestCase): 'id': 42, } }, # zone create - ] + [None] * 18 # individual record creates + ] + [None] * 20 # individual record creates # non-existant zone, create everything plan = provider.plan(self.expected) - self.assertEquals(11, len(plan.changes)) - self.assertEquals(11, provider.apply(plan)) + self.assertEquals(12, len(plan.changes)) + self.assertEquals(12, provider.apply(plan)) provider._request.assert_has_calls([ # created the domain @@ -171,7 +172,7 @@ class TestCloudflareProvider(TestCase): }), ], True) # expected number of total calls - self.assertEquals(20, provider._request.call_count) + self.assertEquals(22, provider._request.call_count) provider._request.reset_mock()