diff --git a/CHANGELOG.md b/CHANGELOG.md index ab3ee4f..13fd5ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +## v1.0.0 - 2024-??-?? - ??? + +Noteworthy Changes: + +* Complete removal of SPF record support, records should be transitioned to TXT + values before updating to this version. + +Changes: + +* Address pending octoDNS 2.x deprecations, require minimum of 1.5.x + ## v0.0.7 - 2024-08-20 - DS always come second * Create DS records after their sibling NS records to appease Cloudflare's diff --git a/octodns_cloudflare/__init__.py b/octodns_cloudflare/__init__.py index d4b7e37..aa8321d 100644 --- a/octodns_cloudflare/__init__.py +++ b/octodns_cloudflare/__init__.py @@ -12,7 +12,7 @@ from octodns import __VERSION__ as octodns_version from octodns.idna import IdnaDict -from octodns.provider import ProviderException, SupportsException +from octodns.provider import ProviderException from octodns.provider.base import BaseProvider from octodns.record import Create, Record, Update @@ -68,7 +68,6 @@ class CloudflareProvider(BaseProvider): 'PTR', 'SSHFP', 'SRV', - 'SPF', 'TLSA', 'TXT', ) @@ -511,28 +510,28 @@ def _record_for(self, zone, name, _type, records, lenient): auto_ttl = records[0]['ttl'] == 1 if proxied: self.log.debug('_record_for: proxied=True, auto-ttl=True') - record._octodns['cloudflare'] = {'proxied': True, 'auto-ttl': True} + record.octodns['cloudflare'] = {'proxied': True, 'auto-ttl': True} elif auto_ttl: # auto-ttl can still be set on any record type, signaled by a ttl=1, # even if proxied is false. self.log.debug('_record_for: auto-ttl=True') - record._octodns['cloudflare'] = {'auto-ttl': True} + record.octodns['cloudflare'] = {'auto-ttl': True} # update record comment if records[0].get('comment'): try: - record._octodns['cloudflare']['comment'] = records[0]['comment'] + record.octodns['cloudflare']['comment'] = records[0]['comment'] except KeyError: - record._octodns['cloudflare'] = { + record.octodns['cloudflare'] = { 'comment': records[0]['comment'] } # update record tags if records[0].get('tags'): try: - record._octodns['cloudflare']['tags'] = records[0]['tags'] + record.octodns['cloudflare']['tags'] = records[0]['tags'] except KeyError: - record._octodns['cloudflare'] = {'tags': records[0]['tags']} + record.octodns['cloudflare'] = {'tags': records[0]['tags']} return record @@ -607,9 +606,6 @@ def populate(self, zone, target=False, lenient=False): return exists def _include_change(self, change): - if isinstance(change, Create) and change.new._type == 'SPF': - msg = f'{self.id}: creating new SPF records not supported, use TXT instead' - raise SupportsException(msg) if isinstance(change, Update): new = change.new @@ -853,7 +849,7 @@ def _contents_for_URLFWD(self, record): } def _record_is_proxied(self, record): - return not self.cdn and record._octodns.get('cloudflare', {}).get( + return not self.cdn and record.octodns.get('cloudflare', {}).get( 'proxied', False ) @@ -862,16 +858,16 @@ def _record_is_just_auto_ttl(self, record): return ( not self._record_is_proxied(record) and not self.cdn - and record._octodns.get('cloudflare', {}).get('auto-ttl', False) + and record.octodns.get('cloudflare', {}).get('auto-ttl', False) ) def _record_comment(self, record): 'Returns record comment' - return record._octodns.get('cloudflare', {}).get('comment', '') + return record.octodns.get('cloudflare', {}).get('comment', '') def _record_tags(self, record): 'Returns nonduplicate record tags' - return set(record._octodns.get('cloudflare', {}).get('tags', [])) + return set(record.octodns.get('cloudflare', {}).get('tags', [])) def _gen_data(self, record): name = record.fqdn[:-1] diff --git a/octodns_cloudflare/processor/proxycname.py b/octodns_cloudflare/processor/proxycname.py index 94c4ff9..f9267e8 100644 --- a/octodns_cloudflare/processor/proxycname.py +++ b/octodns_cloudflare/processor/proxycname.py @@ -45,7 +45,7 @@ def process_source_and_target_zones(self, desired, existing, target): # Check the record is NOT Cloudflare proxied OR is a non Cloudflare proxyable record type # https://developers.cloudflare.com/dns/manage-dns-records/reference/proxied-dns-records/#record-types # NOTE: Inclusion of ALIAS as this is generally a CNAME equivalent that can be used at the root - if not record._octodns.get('cloudflare', {}).get( + if not record.octodns.get('cloudflare', {}).get( 'proxied', False ) or record._type not in ['ALIAS', 'A', 'AAAA', 'CNAME']: # Not interested in this record. diff --git a/octodns_cloudflare/processor/ttl.py b/octodns_cloudflare/processor/ttl.py index 301ad14..4268f9f 100644 --- a/octodns_cloudflare/processor/ttl.py +++ b/octodns_cloudflare/processor/ttl.py @@ -35,7 +35,7 @@ def process_source_zone(self, zone, *args, **kwargs): for record in zone.records: if record.ttl == self.ttl: record = record.copy() - record._octodns['cloudflare'] = { + record.octodns['cloudflare'] = { 'proxied': True, 'auto-ttl': True, } diff --git a/pyproject.toml b/pyproject.toml index 6626a84..40e1dd5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,5 @@ sections="FUTURE,STDLIB,THIRDPARTY,OCTODNS,FIRSTPARTY,LOCALFOLDER" [tool.pytest.ini_options] filterwarnings = [ 'error', - # TODO: remove once octodns 2.0 has been released - 'ignore:.*DEPRECATED.*2.0', ] pythonpath = "." diff --git a/setup.py b/setup.py index fb5710e..929ed0e 100755 --- a/setup.py +++ b/setup.py @@ -42,7 +42,7 @@ def version(): ), 'test': tests_require, }, - install_requires=('octodns>=0.9.20', 'requests>=2.27.0'), + install_requires=('octodns>=1.5.0', 'requests>=2.27.0'), license='MIT', long_description=long_description, long_description_content_type='text/markdown', diff --git a/tests/config/unit.tests.yaml b/tests/config/unit.tests.yaml index c7b7712..211c2c7 100644 --- a/tests/config/unit.tests.yaml +++ b/tests/config/unit.tests.yaml @@ -1,19 +1,6 @@ --- ? '' -: - geo: - AF: - - 2.2.3.4 - - 2.2.3.5 - AS-JP: - - 3.2.3.4 - - 3.2.3.5 - NA-US: - - 4.2.3.4 - - 4.2.3.5 - NA-US-CA: - - 5.2.3.4 - - 5.2.3.5 - ttl: 300 +: - ttl: 300 type: A values: - 1.2.3.4 diff --git a/tests/test_octodns_provider_cloudflare.py b/tests/test_octodns_provider_cloudflare.py index 04587ef..de7a1fc 100644 --- a/tests/test_octodns_provider_cloudflare.py +++ b/tests/test_octodns_provider_cloudflare.py @@ -22,36 +22,36 @@ def set_record_proxied_flag(record, proxied): try: - record._octodns['cloudflare']['proxied'] = proxied + record.octodns['cloudflare']['proxied'] = proxied except KeyError: - record._octodns['cloudflare'] = {'proxied': proxied} + record.octodns['cloudflare'] = {'proxied': proxied} return record def set_record_auto_ttl_flag(record, auto_ttl): try: - record._octodns['cloudflare']['auto-ttl'] = auto_ttl + record.octodns['cloudflare']['auto-ttl'] = auto_ttl except KeyError: - record._octodns['cloudflare'] = {'auto-ttl': auto_ttl} + record.octodns['cloudflare'] = {'auto-ttl': auto_ttl} return record def set_record_comment(record, comment): try: - record._octodns['cloudflare']['comment'] = comment + record.octodns['cloudflare']['comment'] = comment except KeyError: - record._octodns['cloudflare'] = {'comment': comment} + record.octodns['cloudflare'] = {'comment': comment} return record def set_record_tags(record, tags): try: - record._octodns['cloudflare']['tags'] = tags + record.octodns['cloudflare']['tags'] = tags except KeyError: - record._octodns['cloudflare'] = {'tags': tags} + record.octodns['cloudflare'] = {'tags': tags} return record @@ -75,7 +75,7 @@ class TestCloudflareProvider(TestCase): ) for record in list(expected.records): if record.name == 'sub' and record._type == 'NS': - expected._remove_record(record) + expected.remove_record(record) break empty = {'result': [], 'result_info': {'count': 0, 'per_page': 0}} @@ -240,17 +240,17 @@ def test_populate(self): zone = Zone('unit.tests.', []) provider.populate(zone) - self.assertEqual(25, len(zone.records)) + self.assertEqual(24, len(zone.records)) changes = self.expected.changes(zone, provider) - # delete a urlfwd, create 3 urlfwd, and create 1 spf, delete 1 NS - self.assertEqual(10, len(changes)) + # delete a urlfwd, create 3 urlfwd, delete 1 NS + self.assertEqual(9, len(changes)) # re-populating the same zone/records comes out of cache, no calls again = Zone('unit.tests.', []) provider.populate(again) - self.assertEqual(25, len(again.records)) + self.assertEqual(24, len(again.records)) def test_apply(self): provider = CloudflareProvider( @@ -1654,8 +1654,8 @@ def test_unproxiabletype_recordfor_returnsrecordwithnocloudflare(self): record = provider._record_for(zone, name, _type, zone_records, False) - self.assertFalse(record._octodns.get('auto-ttl', False)) - self.assertFalse(record._octodns.get('proxied', False)) + self.assertFalse(record.octodns.get('auto-ttl', False)) + self.assertFalse(record.octodns.get('proxied', False)) def test_proxiabletype_recordfor_retrecordwithcloudflareunproxied(self): provider = CloudflareProvider('test', 'email', 'token') @@ -1685,7 +1685,7 @@ def test_proxiabletype_recordfor_retrecordwithcloudflareunproxied(self): record = provider._record_for(zone, name, _type, zone_records, False) self.assertFalse( - record._octodns.get('cloudflare', {}).get('proxied', False) + record.octodns.get('cloudflare', {}).get('proxied', False) ) def test_proxiabletype_recordfor_returnsrecordwithcloudflareproxied(self): @@ -1715,8 +1715,8 @@ def test_proxiabletype_recordfor_returnsrecordwithcloudflareproxied(self): record = provider._record_for(zone, name, _type, zone_records, False) - self.assertTrue(record._octodns['cloudflare']['auto-ttl']) - self.assertTrue(record._octodns['cloudflare']['proxied']) + self.assertTrue(record.octodns['cloudflare']['auto-ttl']) + self.assertTrue(record.octodns['cloudflare']['proxied']) def test_record_for_auto_ttl_no_proxied(self): provider = CloudflareProvider('test', 'email', 'token') @@ -1743,8 +1743,8 @@ def test_record_for_auto_ttl_no_proxied(self): zone = Zone('unit.tests.', []) record = provider._record_for(zone, name, _type, zone_records, False) - self.assertTrue(record._octodns['cloudflare']['auto-ttl']) - self.assertFalse(record._octodns['cloudflare'].get('proxied', False)) + self.assertTrue(record.octodns['cloudflare']['auto-ttl']) + self.assertFalse(record.octodns['cloudflare'].get('proxied', False)) def test_proxiedrecordandnewttl_includechange_returnsfalse(self): provider = CloudflareProvider('test', 'email', 'token') @@ -2099,10 +2099,10 @@ def test_proxify_extrachanges_returnsupdatelist(self): self.assertEqual(1, len(extra_changes)) self.assertFalse( extra_changes[0] - .existing._octodns.get('cloudflare', {}) + .existing.octodns.get('cloudflare', {}) .get('proxied', False) ) - self.assertTrue(extra_changes[0].new._octodns['cloudflare']['proxied']) + self.assertTrue(extra_changes[0].new.octodns['cloudflare']['proxied']) def test_unproxify_extrachanges_returnsupdatelist(self): provider = CloudflareProvider('test', 'email', 'token') @@ -2154,11 +2154,11 @@ def test_unproxify_extrachanges_returnsupdatelist(self): self.assertEqual(1, len(extra_changes)) self.assertTrue( - extra_changes[0].existing._octodns['cloudflare']['proxied'] + extra_changes[0].existing.octodns['cloudflare']['proxied'] ) self.assertFalse( extra_changes[0] - .new._octodns.get('cloudflare', {}) + .new.octodns.get('cloudflare', {}) .get('proxied', False) ) @@ -2298,36 +2298,6 @@ def test_tlsa(self): key = provider._gen_key(cf_data) self.assertEqual('1 1 1 aa424242424242424242424242424242', key) - def test_no_spf_create(self): - provider = CloudflareProvider('test', 'email', 'token', retry_period=0) - - zone = Zone('unit.tests.', []) - a1 = Record.new( - zone, 'a', {'type': 'A', 'ttl': 420, 'value': '1.2.3.4'} - ) - a2 = a1.copy() - a2.ttl += 1 - spf1 = Record.new( - zone, 'spf', {'type': 'SPF', 'ttl': 430, 'value': 'blahblah'} - ) - spf2 = spf1.copy() - spf2.ttl += 1 - - # A is always included - self.assertTrue(provider._include_change(Create(a1))) - self.assertTrue(provider._include_change(Update(a1, a2))) - self.assertTrue(provider._include_change(Delete(a1))) - - # SPF can't be created, updates and deletes are OK - with self.assertRaises(SupportsException) as ctx: - provider._include_change(Create(spf1)) - self.assertEqual( - 'test: creating new SPF records not supported, use TXT instead', - str(ctx.exception), - ) - self.assertTrue(provider._include_change(Update(spf1, spf2))) - self.assertTrue(provider._include_change(Delete(spf1))) - def test_sshfp(self): self.maxDiff = None provider = CloudflareProvider('test', 'email', 'token') @@ -2560,12 +2530,12 @@ def test_add_tags(self): self.assertEqual(1, len(extra_changes)) self.assertEqual( extra_changes[0] - .existing._octodns.get('cloudflare', {}) + .existing.octodns.get('cloudflare', {}) .get('tags', []), [], ) self.assertEqual( - extra_changes[0].new._octodns['cloudflare']['tags'], + extra_changes[0].new.octodns['cloudflare']['tags'], ['testing:abc', 'abc:testing'], ) @@ -2618,12 +2588,12 @@ def test_update_tags(self): self.assertEqual(1, len(extra_changes)) self.assertEqual( extra_changes[0] - .existing._octodns.get('cloudflare', {}) + .existing.octodns.get('cloudflare', {}) .get('tags', []), ["testing:abc", "abc:testing"], ) self.assertEqual( - sorted(extra_changes[0].new._octodns['cloudflare']['tags']), + sorted(extra_changes[0].new.octodns['cloudflare']['tags']), sorted(["one:abc", "abc:testing"]), ) @@ -2689,12 +2659,12 @@ def test_add_comment(self): self.assertEqual(1, len(extra_changes)) self.assertEqual( extra_changes[0] - .existing._octodns.get('cloudflare', {}) + .existing.octodns.get('cloudflare', {}) .get('comment', ''), '', ) self.assertEqual( - extra_changes[0].new._octodns['cloudflare']['comment'], + extra_changes[0].new.octodns['cloudflare']['comment'], 'a new comment', ) @@ -2747,12 +2717,12 @@ def test_update_comment(self): self.assertEqual(1, len(extra_changes)) self.assertEqual( extra_changes[0] - .existing._octodns.get('cloudflare', {}) + .existing.octodns.get('cloudflare', {}) .get('comment', ''), 'an existing comment', ) self.assertEqual( - extra_changes[0].new._octodns['cloudflare']['comment'], + extra_changes[0].new.octodns['cloudflare']['comment'], 'a new comment', ) diff --git a/tests/test_octodns_provider_cloudflare_processor_ttl.py b/tests/test_octodns_provider_cloudflare_processor_ttl.py index 47f442b..04a1fcc 100644 --- a/tests/test_octodns_provider_cloudflare_processor_ttl.py +++ b/tests/test_octodns_provider_cloudflare_processor_ttl.py @@ -43,8 +43,8 @@ def test_ttl_to_proxy(self): good = next(r for r in added_proxy.records if r.name == 'good') self.assertEqual(1, good.ttl) self.assertEqual( - {'cloudflare': {'proxied': True, 'auto-ttl': True}}, good._octodns + {'cloudflare': {'proxied': True, 'auto-ttl': True}}, good.octodns ) bad = next(r for r in added_proxy.records if r.name == 'bad') self.assertEqual(10, bad.ttl) - self.assertFalse('cloudflare' in bad._octodns) + self.assertFalse('cloudflare' in bad.octodns)