diff --git a/octodns/manager.py b/octodns/manager.py index c3fecf4..eade87a 100644 --- a/octodns/manager.py +++ b/octodns/manager.py @@ -37,6 +37,13 @@ class _AggregateTarget(object): return False return True + @property + def SUPPORTS_DYNAMIC(self): + for target in self.targets: + if not target.SUPPORTS_DYNAMIC: + return False + return True + class MakeThreadFuture(object): diff --git a/octodns/provider/azuredns.py b/octodns/provider/azuredns.py index b3bff6c..fcfc591 100644 --- a/octodns/provider/azuredns.py +++ b/octodns/provider/azuredns.py @@ -239,6 +239,7 @@ class AzureProvider(BaseProvider): possible to also hard-code into the config file: eg, resource_group. ''' SUPPORTS_GEO = False + SUPPORTS_DYNAMIC = False SUPPORTS = set(('A', 'AAAA', 'CNAME', 'MX', 'NS', 'PTR', 'SRV', 'TXT')) def __init__(self, id, client_id, key, directory_id, sub_id, diff --git a/octodns/provider/cloudflare.py b/octodns/provider/cloudflare.py index e4e0a34..7418c29 100644 --- a/octodns/provider/cloudflare.py +++ b/octodns/provider/cloudflare.py @@ -59,6 +59,7 @@ class CloudflareProvider(BaseProvider): value: 1.2.3.4 ''' SUPPORTS_GEO = False + SUPPORTS_DYNAMIC = False SUPPORTS = set(('ALIAS', 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'SRV', 'SPF', 'TXT')) diff --git a/octodns/provider/digitalocean.py b/octodns/provider/digitalocean.py index 84116a0..98a78ad 100644 --- a/octodns/provider/digitalocean.py +++ b/octodns/provider/digitalocean.py @@ -116,6 +116,7 @@ class DigitalOceanProvider(BaseProvider): token: foo ''' SUPPORTS_GEO = False + SUPPORTS_DYNAMIC = False SUPPORTS = set(('A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'TXT', 'SRV')) def __init__(self, id, token, *args, **kwargs): diff --git a/octodns/provider/dnsimple.py b/octodns/provider/dnsimple.py index 18dae68..e3b0a20 100644 --- a/octodns/provider/dnsimple.py +++ b/octodns/provider/dnsimple.py @@ -91,6 +91,7 @@ class DnsimpleProvider(BaseProvider): account: 42 ''' SUPPORTS_GEO = False + SUPPORTS_DYNAMIC = False SUPPORTS = set(('A', 'AAAA', 'ALIAS', 'CAA', 'CNAME', 'MX', 'NAPTR', 'NS', 'PTR', 'SPF', 'SRV', 'SSHFP', 'TXT')) diff --git a/octodns/provider/dnsmadeeasy.py b/octodns/provider/dnsmadeeasy.py index f8cee1c..490359f 100644 --- a/octodns/provider/dnsmadeeasy.py +++ b/octodns/provider/dnsmadeeasy.py @@ -150,6 +150,7 @@ class DnsMadeEasyProvider(BaseProvider): sandbox: true ''' SUPPORTS_GEO = False + SUPPORTS_DYNAMIC = False SUPPORTS = set(('A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'PTR', 'SPF', 'SRV', 'TXT')) diff --git a/octodns/provider/dyn.py b/octodns/provider/dyn.py index 0f487c1..f47f77b 100644 --- a/octodns/provider/dyn.py +++ b/octodns/provider/dyn.py @@ -259,6 +259,11 @@ class DynProvider(BaseProvider): def SUPPORTS_GEO(self): return self.traffic_directors_enabled + @property + def SUPPORTS_DYNAMIC(self): + # TODO: dynamic + return False + def _check_dyn_sess(self): # We don't have to worry about locking for the check since the # underlying pieces are pre-thread. We can check to see if this thread diff --git a/octodns/provider/etc_hosts.py b/octodns/provider/etc_hosts.py index db84ae4..b143fdf 100644 --- a/octodns/provider/etc_hosts.py +++ b/octodns/provider/etc_hosts.py @@ -25,6 +25,7 @@ class EtcHostsProvider(BaseProvider): directory: ./hosts ''' SUPPORTS_GEO = False + SUPPORTS_DYNAMIC = False SUPPORTS = set(('A', 'AAAA', 'ALIAS', 'CNAME')) def __init__(self, id, directory, *args, **kwargs): diff --git a/octodns/provider/googlecloud.py b/octodns/provider/googlecloud.py index 74c17a4..b9999d6 100644 --- a/octodns/provider/googlecloud.py +++ b/octodns/provider/googlecloud.py @@ -40,6 +40,7 @@ class GoogleCloudProvider(BaseProvider): SUPPORTS = set(('A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NAPTR', 'NS', 'PTR', 'SPF', 'SRV', 'TXT')) SUPPORTS_GEO = False + SUPPORTS_DYNAMIC = False CHANGE_LOOP_WAIT = 5 diff --git a/octodns/provider/ns1.py b/octodns/provider/ns1.py index 3ae6889..5fdf5b0 100644 --- a/octodns/provider/ns1.py +++ b/octodns/provider/ns1.py @@ -26,6 +26,7 @@ class Ns1Provider(BaseProvider): api_key: env/NS1_API_KEY ''' SUPPORTS_GEO = True + SUPPORTS_DYNAMIC = False SUPPORTS = set(('A', 'AAAA', 'ALIAS', 'CAA', 'CNAME', 'MX', 'NAPTR', 'NS', 'PTR', 'SPF', 'SRV', 'TXT')) diff --git a/octodns/provider/ovh.py b/octodns/provider/ovh.py index a74a3cd..d968da4 100644 --- a/octodns/provider/ovh.py +++ b/octodns/provider/ovh.py @@ -34,6 +34,7 @@ class OvhProvider(BaseProvider): """ SUPPORTS_GEO = False + SUPPORTS_DYNAMIC = False ZONE_NOT_FOUND_MESSAGE = 'This service does not exist' # This variable is also used in populate method to filter which OVH record diff --git a/octodns/provider/powerdns.py b/octodns/provider/powerdns.py index 30cd01e..8d75163 100644 --- a/octodns/provider/powerdns.py +++ b/octodns/provider/powerdns.py @@ -14,6 +14,7 @@ from .base import BaseProvider class PowerDnsBaseProvider(BaseProvider): SUPPORTS_GEO = False + SUPPORTS_DYNAMIC = False SUPPORTS = set(('A', 'AAAA', 'ALIAS', 'CAA', 'CNAME', 'MX', 'NAPTR', 'NS', 'PTR', 'SPF', 'SSHFP', 'SRV', 'TXT')) TIMEOUT = 5 diff --git a/octodns/provider/rackspace.py b/octodns/provider/rackspace.py index d2b85f3..5038929 100644 --- a/octodns/provider/rackspace.py +++ b/octodns/provider/rackspace.py @@ -38,6 +38,7 @@ def unescape_semicolon(s): class RackspaceProvider(BaseProvider): SUPPORTS_GEO = False + SUPPORTS_DYNAMIC = False SUPPORTS = set(('A', 'AAAA', 'ALIAS', 'CNAME', 'MX', 'NS', 'PTR', 'SPF', 'TXT')) TIMEOUT = 5 diff --git a/octodns/provider/route53.py b/octodns/provider/route53.py index 4b7fe66..ff83cdc 100644 --- a/octodns/provider/route53.py +++ b/octodns/provider/route53.py @@ -232,6 +232,8 @@ class Route53Provider(BaseProvider): In general the account used will need full permissions on Route53. ''' SUPPORTS_GEO = True + # TODO: dynamic + SUPPORTS_DYNAMIC = False SUPPORTS = set(('A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NAPTR', 'NS', 'PTR', 'SPF', 'SRV', 'TXT')) diff --git a/octodns/provider/yaml.py b/octodns/provider/yaml.py index 7c9a915..a9631a0 100644 --- a/octodns/provider/yaml.py +++ b/octodns/provider/yaml.py @@ -31,6 +31,7 @@ class YamlProvider(BaseProvider): enforce_order: True ''' SUPPORTS_GEO = True + SUPPORTS_DYNAMIC = True SUPPORTS = set(('A', 'AAAA', 'ALIAS', 'CAA', 'CNAME', 'MX', 'NAPTR', 'NS', 'PTR', 'SSHFP', 'SPF', 'SRV', 'TXT')) diff --git a/octodns/source/axfr.py b/octodns/source/axfr.py index 715a36b..f35c4b3 100644 --- a/octodns/source/axfr.py +++ b/octodns/source/axfr.py @@ -24,6 +24,7 @@ from .base import BaseSource class AxfrBaseSource(BaseSource): SUPPORTS_GEO = False + SUPPORTS_DYNAMIC = False SUPPORTS = set(('A', 'AAAA', 'CNAME', 'MX', 'NS', 'PTR', 'SPF', 'SRV', 'TXT')) diff --git a/octodns/source/base.py b/octodns/source/base.py index ee33619..1faab7f 100644 --- a/octodns/source/base.py +++ b/octodns/source/base.py @@ -16,6 +16,9 @@ class BaseSource(object): if not hasattr(self, 'SUPPORTS_GEO'): raise NotImplementedError('Abstract base class, SUPPORTS_GEO ' 'property missing') + if not hasattr(self, 'SUPPORTS_DYNAMIC'): + raise NotImplementedError('Abstract base class, SUPPORTS_DYNAMIC ' + 'property missing') if not hasattr(self, 'SUPPORTS'): raise NotImplementedError('Abstract base class, SUPPORTS ' 'property missing') diff --git a/octodns/source/tinydns.py b/octodns/source/tinydns.py index 7b06527..679accb 100644 --- a/octodns/source/tinydns.py +++ b/octodns/source/tinydns.py @@ -19,6 +19,7 @@ from .base import BaseSource class TinyDnsBaseSource(BaseSource): SUPPORTS_GEO = False + SUPPORTS_DYNAMIC = False SUPPORTS = set(('A', 'CNAME', 'MX', 'NS')) split_re = re.compile(r':+') diff --git a/tests/helpers.py b/tests/helpers.py index 632f258..ff7f7cc 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -17,6 +17,7 @@ class SimpleSource(object): class SimpleProvider(object): SUPPORTS_GEO = False + SUPPORTS_DYNAMIC = False SUPPORTS = set(('A',)) id = 'test' @@ -35,6 +36,25 @@ class SimpleProvider(object): class GeoProvider(object): SUPPORTS_GEO = True + SUPPORTS_DYNAMIC = False + id = 'test' + + def __init__(self, id='test'): + pass + + def populate(self, zone, source=False, lenient=False): + pass + + def supports(self, record): + return True + + def __repr__(self): + return self.__class__.__name__ + + +class DynamicProvider(object): + SUPPORTS_GEO = False + SUPPORTS_DYNAMIC = True id = 'test' def __init__(self, id='test'): diff --git a/tests/test_octodns_manager.py b/tests/test_octodns_manager.py index ada54e5..0e14bab 100644 --- a/tests/test_octodns_manager.py +++ b/tests/test_octodns_manager.py @@ -14,8 +14,8 @@ from octodns.manager import _AggregateTarget, MainThreadExecutor, Manager from octodns.yaml import safe_load from octodns.zone import Zone -from helpers import GeoProvider, NoSshFpProvider, SimpleProvider, \ - TemporaryDirectory +from helpers import DynamicProvider, GeoProvider, NoSshFpProvider, \ + SimpleProvider, TemporaryDirectory config_dir = join(dirname(__file__), 'config') @@ -187,6 +187,7 @@ class TestManager(TestCase): def test_aggregate_target(self): simple = SimpleProvider() geo = GeoProvider() + dynamic = DynamicProvider() nosshfp = NoSshFpProvider() self.assertFalse(_AggregateTarget([simple, simple]).SUPPORTS_GEO) @@ -194,6 +195,11 @@ class TestManager(TestCase): self.assertFalse(_AggregateTarget([geo, simple]).SUPPORTS_GEO) self.assertTrue(_AggregateTarget([geo, geo]).SUPPORTS_GEO) + self.assertFalse(_AggregateTarget([simple, simple]).SUPPORTS_DYNAMIC) + self.assertFalse(_AggregateTarget([simple, dynamic]).SUPPORTS_DYNAMIC) + self.assertFalse(_AggregateTarget([dynamic, simple]).SUPPORTS_DYNAMIC) + self.assertTrue(_AggregateTarget([dynamic, dynamic]).SUPPORTS_DYNAMIC) + zone = Zone('unit.tests.', []) record = Record.new(zone, 'sshfp', { 'ttl': 60, diff --git a/tests/test_octodns_provider_base.py b/tests/test_octodns_provider_base.py index 22a0ee6..5a053ee 100644 --- a/tests/test_octodns_provider_base.py +++ b/tests/test_octodns_provider_base.py @@ -61,13 +61,21 @@ class TestBaseProvider(TestCase): class HasSupportsGeo(HasLog): SUPPORTS_GEO = False + with self.assertRaises(NotImplementedError) as ctx: + HasSupportsGeo('hassupportsgeo') + self.assertEquals('Abstract base class, SUPPORTS_DYNAMIC ' + 'property missing', ctx.exception.message) + + class HasSupportsDyanmic(HasSupportsGeo): + SUPPORTS_DYNAMIC = False + zone = Zone('unit.tests.', ['sub']) with self.assertRaises(NotImplementedError) as ctx: - HasSupportsGeo('hassupportsgeo').populate(zone) + HasSupportsDyanmic('hassupportsdynamic').populate(zone) self.assertEquals('Abstract base class, SUPPORTS property missing', ctx.exception.message) - class HasSupports(HasSupportsGeo): + class HasSupports(HasSupportsDyanmic): SUPPORTS = set(('A',)) with self.assertRaises(NotImplementedError) as ctx: HasSupports('hassupports').populate(zone) diff --git a/tests/test_octodns_zone.py b/tests/test_octodns_zone.py index b371590..2fff996 100644 --- a/tests/test_octodns_zone.py +++ b/tests/test_octodns_zone.py @@ -111,6 +111,7 @@ class TestZone(TestCase): class NoAaaaProvider(object): id = 'no-aaaa' SUPPORTS_GEO = False + SUPPORTS_DYNAMIC = False def supports(self, record): return record._type != 'AAAA'