diff --git a/octodns/provider/cloudflare.py b/octodns/provider/cloudflare.py index 1d7c1b2..50e4b90 100644 --- a/octodns/provider/cloudflare.py +++ b/octodns/provider/cloudflare.py @@ -341,19 +341,26 @@ class CloudflareProvider(BaseProvider): yield content def _gen_key(self, data): - # Note that all CF records have a `content` field the value of which - # appears to be a unique/hashable string for the record's. It includes - # all the "value" bits, but not the secondary stuff like TTL's. E.g. - # for an A it'll include the value, for a CAA it'll include the flags, - # tag, and value, ... We'll take advantage of this to try and match up - # old & new records cleanly. In general when there are multiple records - # for a name & type each will have a distinct/consistent `content` that - # can serve as a unique identifier. - # BUT... there's an exception. For some reason MX doesn't include - # priority in its `content` so it's an odd-ball. I haven't found any - # others so hopefully they don't exist :-( - if data['type'] == 'MX': - return '{} {}'.format(data['priority'], data['content']) + # Note that most CF record data has a `content` field the value of + # which is a unique/hashable string for the record's. It includes all + # the "value" bits, but not the secondary stuff like TTL's. E.g. for + # an A it'll include the value, for a CAA it'll include the flags, tag, + # and value, ... We'll take advantage of this to try and match up old & + # new records cleanly. In general when there are multiple records for a + # name & type each will have a distinct/consistent `content` that can + # serve as a unique identifier. + # BUT... there are exceptions. MX, CAA, and SRV don't have a simple + # content as things are currently implemented so we need to handle + # those explicitly and create unique/hashable strings for them. + _type = data['type'] + if _type == 'MX': + return '{priority} {content}'.format(**data) + elif _type == 'CAA': + data = data['data'] + return '{flags} {tag} {value}'.format(**data) + elif _type == 'SRV': + data = data['data'] + return '{port} {priority} {target} {weight}'.format(**data) return data['content'] def _apply_Create(self, change): diff --git a/tests/test_octodns_provider_cloudflare.py b/tests/test_octodns_provider_cloudflare.py index a04b6d3..0f769a4 100644 --- a/tests/test_octodns_provider_cloudflare.py +++ b/tests/test_octodns_provider_cloudflare.py @@ -539,16 +539,35 @@ class TestCloudflareProvider(TestCase): def test_gen_key(self): provider = CloudflareProvider('test', 'email', 'token') - self.assertEqual('10 foo.bar.com.', provider._gen_key({ - 'content': 'foo.bar.com.', - 'priority': 10, - 'type': 'MX', - })) - - self.assertEqual('foo.bar.com.', provider._gen_key({ - 'content': 'foo.bar.com.', - 'type': 'CNAME', - })) + for expected, data in ( + ('foo.bar.com.', { + 'content': 'foo.bar.com.', + 'type': 'CNAME', + }), + ('10 foo.bar.com.', { + 'content': 'foo.bar.com.', + 'priority': 10, + 'type': 'MX', + }), + ('0 tag some-value', { + 'data': { + 'flags': 0, + 'tag': 'tag', + 'value': 'some-value', + }, + 'type': 'CAA', + }), + ('42 100 thing-were-pointed.at 101', { + 'data': { + 'port': 42, + 'priority': 100, + 'target': 'thing-were-pointed.at', + 'weight': 101, + }, + 'type': 'SRV', + }), + ): + self.assertEqual(expected, provider._gen_key(data)) def test_cdn(self): provider = CloudflareProvider('test', 'email', 'token', True)