From bc98af024b80690e72e87faa7765eef99048a09c Mon Sep 17 00:00:00 2001 From: zBart Date: Wed, 3 May 2017 12:08:32 +0200 Subject: [PATCH] Handle Cloudflare not escaping semicolons --- octodns/provider/cloudflare.py | 13 ++++++++++-- tests/config/unit.tests.yaml | 1 + .../cloudflare-dns_records-page-1.json | 2 +- .../cloudflare-dns_records-page-2.json | 21 +++++++++++++++++-- tests/fixtures/dnsimple-page-1.json | 2 +- tests/fixtures/dnsimple-page-2.json | 18 +++++++++++++++- tests/fixtures/powerdns-full-data.json | 4 ++++ tests/test_octodns_provider_cloudflare.py | 13 +++++++++--- tests/test_octodns_provider_dnsimple.py | 2 +- 9 files changed, 65 insertions(+), 11 deletions(-) diff --git a/octodns/provider/cloudflare.py b/octodns/provider/cloudflare.py index a67db66..d7af77e 100644 --- a/octodns/provider/cloudflare.py +++ b/octodns/provider/cloudflare.py @@ -99,7 +99,13 @@ class CloudflareProvider(BaseProvider): _data_for_A = _data_for_multiple _data_for_AAAA = _data_for_multiple _data_for_SPF = _data_for_multiple - _data_for_TXT = _data_for_multiple + + def _data_for_TXT(self, _type, records): + return { + 'ttl': records[0]['ttl'], + 'type': _type, + 'values': [r['content'].replace(';', '\;') for r in records], + } def _data_for_CNAME(self, _type, records): only = records[0] @@ -191,7 +197,10 @@ class CloudflareProvider(BaseProvider): _contents_for_AAAA = _contents_for_multiple _contents_for_NS = _contents_for_multiple _contents_for_SPF = _contents_for_multiple - _contents_for_TXT = _contents_for_multiple + + def _contents_for_TXT(self, record): + for value in record.values: + yield {'content': value.replace('\;', ';')} def _contents_for_CNAME(self, record): yield {'content': record.value} diff --git a/tests/config/unit.tests.yaml b/tests/config/unit.tests.yaml index 90604ae..c71638b 100644 --- a/tests/config/unit.tests.yaml +++ b/tests/config/unit.tests.yaml @@ -98,6 +98,7 @@ txt: values: - Bah bah black sheep - have you any wool. + - 'v=DKIM1\;k=rsa\;s=email\;h=sha256\;p=A/kinda+of/long/string+with+numb3rs' www: ttl: 300 type: A diff --git a/tests/fixtures/cloudflare-dns_records-page-1.json b/tests/fixtures/cloudflare-dns_records-page-1.json index d67dfb3..eda4de3 100644 --- a/tests/fixtures/cloudflare-dns_records-page-1.json +++ b/tests/fixtures/cloudflare-dns_records-page-1.json @@ -180,7 +180,7 @@ "per_page": 10, "total_pages": 2, "count": 10, - "total_count": 16 + "total_count": 17 }, "success": true, "errors": [], diff --git a/tests/fixtures/cloudflare-dns_records-page-2.json b/tests/fixtures/cloudflare-dns_records-page-2.json index 4995c51..24c49d5 100644 --- a/tests/fixtures/cloudflare-dns_records-page-2.json +++ b/tests/fixtures/cloudflare-dns_records-page-2.json @@ -101,14 +101,31 @@ "meta": { "auto_added": false } + }, + { + "id": "fc12ab34cd5611334422ab3322997667", + "type": "TXT", + "name": "txt.unit.tests", + "content": "v=DKIM1;k=rsa;s=email;h=sha256;p=A\/kinda+of\/long\/string+with+numb3rs", + "proxiable": false, + "proxied": false, + "ttl": 600, + "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": { "page": 2, "per_page": 10, "total_pages": 2, - "count": 6, - "total_count": 16 + "count": 7, + "total_count": 17 }, "success": true, "errors": [], diff --git a/tests/fixtures/dnsimple-page-1.json b/tests/fixtures/dnsimple-page-1.json index 5418898..3fa3257 100644 --- a/tests/fixtures/dnsimple-page-1.json +++ b/tests/fixtures/dnsimple-page-1.json @@ -308,7 +308,7 @@ "pagination": { "current_page": 1, "per_page": 20, - "total_entries": 27, + "total_entries": 28, "total_pages": 2 } } diff --git a/tests/fixtures/dnsimple-page-2.json b/tests/fixtures/dnsimple-page-2.json index 3f65133..dbc5cd3 100644 --- a/tests/fixtures/dnsimple-page-2.json +++ b/tests/fixtures/dnsimple-page-2.json @@ -127,12 +127,28 @@ "system_record": false, "created_at": "2017-03-09T15:55:11Z", "updated_at": "2017-03-09T15:55:11Z" + }, + { + "id": 11189901, + "zone_id": "unit.tests", + "parent_id": null, + "name": "txt", + "content": "v=DKIM1\\;k=rsa\\;s=email\\;h=sha256\\;p=A/kinda+of/long/string+with+numb3rs", + "ttl": 600, + "priority": null, + "type": "TXT", + "regions": [ + "global" + ], + "system_record": false, + "created_at": "2017-03-09T15:55:09Z", + "updated_at": "2017-03-09T15:55:09Z" } ], "pagination": { "current_page": 2, "per_page": 20, - "total_entries": 27, + "total_entries": 28, "total_pages": 2 } } diff --git a/tests/fixtures/powerdns-full-data.json b/tests/fixtures/powerdns-full-data.json index efb82c2..72ce016 100644 --- a/tests/fixtures/powerdns-full-data.json +++ b/tests/fixtures/powerdns-full-data.json @@ -86,6 +86,10 @@ { "content": "\"have you any wool.\"", "disabled": false + }, + { + "content": "\"v=DKIM1\\;k=rsa\\;s=email\\;h=sha256\\;p=A/kinda+of/long/string+with+numb3rs\"", + "disabled": false } ], "ttl": 600, diff --git a/tests/test_octodns_provider_cloudflare.py b/tests/test_octodns_provider_cloudflare.py index 229ff5a..18987d3 100644 --- a/tests/test_octodns_provider_cloudflare.py +++ b/tests/test_octodns_provider_cloudflare.py @@ -140,7 +140,7 @@ class TestCloudflareProvider(TestCase): 'id': 42, } }, # zone create - ] + [None] * 15 # individual record creates + ] + [None] * 16 # individual record creates # non-existant zone, create everything plan = provider.plan(self.expected) @@ -160,9 +160,16 @@ class TestCloudflareProvider(TestCase): 'name': 'under.unit.tests', 'ttl': 3600 }), - ]) + # make sure semicolons are not escaped when sending data + call('POST', '/zones/42/dns_records', data={ + 'content': 'v=DKIM1;k=rsa;s=email;h=sha256;p=A/kinda+of/long/string+with+numb3rs', + 'type': 'TXT', + 'name': 'txt.unit.tests', + 'ttl': 600 + }), + ], True) # expected number of total calls - self.assertEquals(17, provider._request.call_count) + self.assertEquals(18, provider._request.call_count) provider._request.reset_mock() diff --git a/tests/test_octodns_provider_dnsimple.py b/tests/test_octodns_provider_dnsimple.py index 3de297d..48c1f6a 100644 --- a/tests/test_octodns_provider_dnsimple.py +++ b/tests/test_octodns_provider_dnsimple.py @@ -147,7 +147,7 @@ class TestDnsimpleProvider(TestCase): }), ]) # expected number of total calls - self.assertEquals(25, provider._client._request.call_count) + self.assertEquals(26, provider._client._request.call_count) provider._client._request.reset_mock()