From 5963c8b89453e51e01d2b983d0421cb707fa1568 Mon Sep 17 00:00:00 2001 From: Mark Tearle Date: Tue, 1 Dec 2020 00:02:49 +0800 Subject: [PATCH] Force order of Delete() -> Create() -> Update() in Cloudflare provider Addresses issues with changing between A, AAAA and CNAME records in both directions with the Cloudflare API See also: github/octodns#507 See also: github/octodns#586 See also: github/octodns#587 --- octodns/provider/cloudflare.py | 10 ++++++++++ tests/test_octodns_provider_cloudflare.py | 10 +++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/octodns/provider/cloudflare.py b/octodns/provider/cloudflare.py index 05fef20..f9d9fd0 100644 --- a/octodns/provider/cloudflare.py +++ b/octodns/provider/cloudflare.py @@ -143,6 +143,11 @@ class CloudflareProvider(BaseProvider): resp.raise_for_status() return resp.json() + def _change_keyer(self, change): + key = change.__class__.__name__ + order = {'Delete': 0, 'Create': 1, 'Update': 2} + return order[key] + @property def zones(self): if self._zones is None: @@ -660,6 +665,11 @@ class CloudflareProvider(BaseProvider): self.zones[name] = zone_id self._zone_records[name] = {} + # Force the operation order to be Delete() -> Create() -> Update() + # This will help avoid problems in updating a CNAME record into an + # A record and vice-versa + changes.sort(key=self._change_keyer) + for change in changes: class_name = change.__class__.__name__ getattr(self, '_apply_{}'.format(class_name))(change) diff --git a/tests/test_octodns_provider_cloudflare.py b/tests/test_octodns_provider_cloudflare.py index 3727e20..127480b 100644 --- a/tests/test_octodns_provider_cloudflare.py +++ b/tests/test_octodns_provider_cloudflare.py @@ -340,6 +340,10 @@ class TestCloudflareProvider(TestCase): self.assertTrue(plan.exists) # creates a the new value and then deletes all the old provider._request.assert_has_calls([ + call('DELETE', '/zones/ff12ab34cd5611334422ab3322997650/' + 'dns_records/fc12ab34cd5611334422ab3322997653'), + call('DELETE', '/zones/ff12ab34cd5611334422ab3322997650/' + 'dns_records/fc12ab34cd5611334422ab3322997654'), call('PUT', '/zones/42/dns_records/' 'fc12ab34cd5611334422ab3322997655', data={ 'content': '3.2.3.4', @@ -347,11 +351,7 @@ class TestCloudflareProvider(TestCase): 'name': 'ttl.unit.tests', 'proxied': False, 'ttl': 300 - }), - call('DELETE', '/zones/ff12ab34cd5611334422ab3322997650/' - 'dns_records/fc12ab34cd5611334422ab3322997653'), - call('DELETE', '/zones/ff12ab34cd5611334422ab3322997650/' - 'dns_records/fc12ab34cd5611334422ab3322997654') + }) ]) def test_update_add_swap(self):