Browse Source

Switch populate to return exists, cleaner setup

pull/177/head
Ross McFarland 8 years ago
parent
commit
94bfb1e507
No known key found for this signature in database GPG Key ID: 61C10C4FC8FE4A89
10 changed files with 34 additions and 27 deletions
  1. +1
    -1
      octodns/manager.py
  2. +7
    -3
      octodns/provider/base.py
  3. +2
    -2
      octodns/provider/plan.py
  4. +4
    -1
      octodns/source/base.py
  5. +2
    -2
      tests/test_octodns_plan.py
  6. +3
    -3
      tests/test_octodns_provider_azuredns.py
  7. +10
    -10
      tests/test_octodns_provider_base.py
  8. +2
    -2
      tests/test_octodns_provider_cloudflare.py
  9. +1
    -1
      tests/test_octodns_provider_dyn.py
  10. +2
    -2
      tests/test_octodns_provider_googlecloud.py

+ 1
- 1
octodns/manager.py View File

@ -361,7 +361,7 @@ class Manager(object):
plan = target.plan(zone) plan = target.plan(zone)
if plan is None: if plan is None:
plan = Plan(zone, zone, [], True)
plan = Plan(zone, zone, [], False)
target.apply(plan) target.apply(plan)
def validate_configs(self): def validate_configs(self):


+ 7
- 3
octodns/provider/base.py View File

@ -45,7 +45,12 @@ class BaseProvider(BaseSource):
self.log.info('plan: desired=%s', desired.name) self.log.info('plan: desired=%s', desired.name)
existing = Zone(desired.name, desired.sub_zones) existing = Zone(desired.name, desired.sub_zones)
self.populate(existing, target=True, lenient=True)
exists = self.populate(existing, target=True, lenient=True)
if exists is None:
# If your code gets this warning see Source.populate for more
# information
self.log.warn('Provider %s used in target mode did not return '
'exists', self.id)
# compute the changes at the zone/record level # compute the changes at the zone/record level
changes = existing.changes(desired, self) changes = existing.changes(desired, self)
@ -64,9 +69,8 @@ class BaseProvider(BaseSource):
.join([str(c) for c in extra])) .join([str(c) for c in extra]))
changes += extra changes += extra
create = False
if changes: if changes:
plan = Plan(existing, desired, changes, create,
plan = Plan(existing, desired, changes, exists,
self.update_pcent_threshold, self.update_pcent_threshold,
self.delete_pcent_threshold) self.delete_pcent_threshold)
self.log.info('plan: %s', plan) self.log.info('plan: %s', plan)


+ 2
- 2
octodns/provider/plan.py View File

@ -21,13 +21,13 @@ class Plan(object):
MAX_SAFE_DELETE_PCENT = .3 MAX_SAFE_DELETE_PCENT = .3
MIN_EXISTING_RECORDS = 10 MIN_EXISTING_RECORDS = 10
def __init__(self, existing, desired, changes, create,
def __init__(self, existing, desired, changes, exists,
update_pcent_threshold=MAX_SAFE_UPDATE_PCENT, update_pcent_threshold=MAX_SAFE_UPDATE_PCENT,
delete_pcent_threshold=MAX_SAFE_DELETE_PCENT): delete_pcent_threshold=MAX_SAFE_DELETE_PCENT):
self.existing = existing self.existing = existing
self.desired = desired self.desired = desired
self.changes = changes self.changes = changes
self.create = create
self.exists = exists
self.update_pcent_threshold = update_pcent_threshold self.update_pcent_threshold = update_pcent_threshold
self.delete_pcent_threshold = delete_pcent_threshold self.delete_pcent_threshold = delete_pcent_threshold


+ 4
- 1
octodns/source/base.py View File

@ -22,7 +22,7 @@ class BaseSource(object):
def populate(self, zone, target=False, lenient=False): def populate(self, zone, target=False, lenient=False):
''' '''
Loads all zones the provider knows about
Loads all records the provider knows about for the provided zone
When `target` is True the populate call is being made to load the When `target` is True the populate call is being made to load the
current state of the provider. current state of the provider.
@ -31,6 +31,9 @@ class BaseSource(object):
do a "best effort" load of data. That will allow through some common, do a "best effort" load of data. That will allow through some common,
but not best practices stuff that we otherwise would reject. E.g. no but not best practices stuff that we otherwise would reject. E.g. no
trailing . or mising escapes for ;. trailing . or mising escapes for ;.
When target is True (loading current state) this method should return
True if the zone exists or False if it does not.
''' '''
raise NotImplementedError('Abstract base class, populate method ' raise NotImplementedError('Abstract base class, populate method '
'missing') 'missing')


+ 2
- 2
tests/test_octodns_plan.py View File

@ -52,8 +52,8 @@ update = Update(existing, new)
delete = Delete(new) delete = Delete(new)
changes = [create, delete, update] changes = [create, delete, update]
plans = [ plans = [
(simple, Plan(zone, zone, changes, False)),
(simple, Plan(zone, zone, changes, False)),
(simple, Plan(zone, zone, changes, True)),
(simple, Plan(zone, zone, changes, True)),
] ]


+ 3
- 3
tests/test_octodns_provider_azuredns.py View File

@ -339,9 +339,9 @@ class TestAzureDnsProvider(TestCase):
deletes.append(Delete(i)) deletes.append(Delete(i))
self.assertEquals(13, provider.apply(Plan(None, zone, self.assertEquals(13, provider.apply(Plan(None, zone,
changes, False)))
changes, True)))
self.assertEquals(13, provider.apply(Plan(zone, zone, self.assertEquals(13, provider.apply(Plan(zone, zone,
deletes, False)))
deletes, True)))
def test_create_zone(self): def test_create_zone(self):
provider = self._get_provider() provider = self._get_provider()
@ -357,7 +357,7 @@ class TestAzureDnsProvider(TestCase):
_get.side_effect = CloudError(Mock(status=404), err_msg) _get.side_effect = CloudError(Mock(status=404), err_msg)
self.assertEquals(13, provider.apply(Plan(None, desired, changes, self.assertEquals(13, provider.apply(Plan(None, desired, changes,
False)))
True)))
def test_check_zone_no_create(self): def test_check_zone_no_create(self):
provider = self._get_provider() provider = self._get_provider()


+ 10
- 10
tests/test_octodns_provider_base.py View File

@ -153,7 +153,7 @@ class TestBaseProvider(TestCase):
def test_safe_none(self): def test_safe_none(self):
# No changes is safe # No changes is safe
Plan(None, None, [], False).raise_if_unsafe()
Plan(None, None, [], True).raise_if_unsafe()
def test_safe_creates(self): def test_safe_creates(self):
# Creates are safe when existing records is under MIN_EXISTING_RECORDS # Creates are safe when existing records is under MIN_EXISTING_RECORDS
@ -164,7 +164,7 @@ class TestBaseProvider(TestCase):
'type': 'A', 'type': 'A',
'value': '1.2.3.4', 'value': '1.2.3.4',
}) })
Plan(zone, zone, [Create(record) for i in range(10)], False) \
Plan(zone, zone, [Create(record) for i in range(10)], True) \
.raise_if_unsafe() .raise_if_unsafe()
def test_safe_min_existing_creates(self): def test_safe_min_existing_creates(self):
@ -184,7 +184,7 @@ class TestBaseProvider(TestCase):
'value': '2.3.4.5' 'value': '2.3.4.5'
})) }))
Plan(zone, zone, [Create(record) for i in range(10)], False) \
Plan(zone, zone, [Create(record) for i in range(10)], True) \
.raise_if_unsafe() .raise_if_unsafe()
def test_safe_no_existing(self): def test_safe_no_existing(self):
@ -197,7 +197,7 @@ class TestBaseProvider(TestCase):
}) })
updates = [Update(record, record), Update(record, record)] updates = [Update(record, record), Update(record, record)]
Plan(zone, zone, updates, False).raise_if_unsafe()
Plan(zone, zone, updates, True).raise_if_unsafe()
def test_safe_updates_min_existing(self): def test_safe_updates_min_existing(self):
# MAX_SAFE_UPDATE_PCENT+1 fails when more # MAX_SAFE_UPDATE_PCENT+1 fails when more
@ -221,7 +221,7 @@ class TestBaseProvider(TestCase):
Plan.MAX_SAFE_UPDATE_PCENT) + 1)] Plan.MAX_SAFE_UPDATE_PCENT) + 1)]
with self.assertRaises(UnsafePlan) as ctx: with self.assertRaises(UnsafePlan) as ctx:
Plan(zone, zone, changes, False).raise_if_unsafe()
Plan(zone, zone, changes, True).raise_if_unsafe()
self.assertTrue('Too many updates' in ctx.exception.message) self.assertTrue('Too many updates' in ctx.exception.message)
@ -245,7 +245,7 @@ class TestBaseProvider(TestCase):
for i in range(int(Plan.MIN_EXISTING_RECORDS * for i in range(int(Plan.MIN_EXISTING_RECORDS *
Plan.MAX_SAFE_UPDATE_PCENT))] Plan.MAX_SAFE_UPDATE_PCENT))]
Plan(zone, zone, changes, False).raise_if_unsafe()
Plan(zone, zone, changes, True).raise_if_unsafe()
def test_safe_deletes_min_existing(self): def test_safe_deletes_min_existing(self):
# MAX_SAFE_DELETE_PCENT+1 fails when more # MAX_SAFE_DELETE_PCENT+1 fails when more
@ -269,7 +269,7 @@ class TestBaseProvider(TestCase):
Plan.MAX_SAFE_DELETE_PCENT) + 1)] Plan.MAX_SAFE_DELETE_PCENT) + 1)]
with self.assertRaises(UnsafePlan) as ctx: with self.assertRaises(UnsafePlan) as ctx:
Plan(zone, zone, changes, False).raise_if_unsafe()
Plan(zone, zone, changes, True).raise_if_unsafe()
self.assertTrue('Too many deletes' in ctx.exception.message) self.assertTrue('Too many deletes' in ctx.exception.message)
@ -293,7 +293,7 @@ class TestBaseProvider(TestCase):
for i in range(int(Plan.MIN_EXISTING_RECORDS * for i in range(int(Plan.MIN_EXISTING_RECORDS *
Plan.MAX_SAFE_DELETE_PCENT))] Plan.MAX_SAFE_DELETE_PCENT))]
Plan(zone, zone, changes, False).raise_if_unsafe()
Plan(zone, zone, changes, True).raise_if_unsafe()
def test_safe_updates_min_existing_override(self): def test_safe_updates_min_existing_override(self):
safe_pcent = .4 safe_pcent = .4
@ -318,7 +318,7 @@ class TestBaseProvider(TestCase):
safe_pcent) + 1)] safe_pcent) + 1)]
with self.assertRaises(UnsafePlan) as ctx: with self.assertRaises(UnsafePlan) as ctx:
Plan(zone, zone, changes, False,
Plan(zone, zone, changes, True,
update_pcent_threshold=safe_pcent).raise_if_unsafe() update_pcent_threshold=safe_pcent).raise_if_unsafe()
self.assertTrue('Too many updates' in ctx.exception.message) self.assertTrue('Too many updates' in ctx.exception.message)
@ -346,7 +346,7 @@ class TestBaseProvider(TestCase):
safe_pcent) + 1)] safe_pcent) + 1)]
with self.assertRaises(UnsafePlan) as ctx: with self.assertRaises(UnsafePlan) as ctx:
Plan(zone, zone, changes, False,
Plan(zone, zone, changes, True,
delete_pcent_threshold=safe_pcent).raise_if_unsafe() delete_pcent_threshold=safe_pcent).raise_if_unsafe()
self.assertTrue('Too many deletes' in ctx.exception.message) self.assertTrue('Too many deletes' in ctx.exception.message)

+ 2
- 2
tests/test_octodns_provider_cloudflare.py View File

@ -347,7 +347,7 @@ class TestCloudflareProvider(TestCase):
'values': ['2.2.2.2', '3.3.3.3', '4.4.4.4'], 'values': ['2.2.2.2', '3.3.3.3', '4.4.4.4'],
}) })
change = Update(existing, new) change = Update(existing, new)
plan = Plan(zone, zone, [change], False)
plan = Plan(zone, zone, [change], True)
provider._apply(plan) provider._apply(plan)
provider._request.assert_has_calls([ provider._request.assert_has_calls([
@ -432,7 +432,7 @@ class TestCloudflareProvider(TestCase):
'value': 'ns2.foo.bar.', 'value': 'ns2.foo.bar.',
}) })
change = Update(existing, new) change = Update(existing, new)
plan = Plan(zone, zone, [change], False)
plan = Plan(zone, zone, [change], True)
provider._apply(plan) provider._apply(plan)
provider._request.assert_has_calls([ provider._request.assert_has_calls([


+ 1
- 1
tests/test_octodns_provider_dyn.py View File

@ -913,7 +913,7 @@ class TestDynProviderGeo(TestCase):
Delete(geo), Delete(geo),
Delete(regular), Delete(regular),
] ]
plan = Plan(None, desired, changes, False)
plan = Plan(None, desired, changes, True)
provider._apply(plan) provider._apply(plan)
mock.assert_has_calls([ mock.assert_has_calls([
call('/Zone/unit.tests/', 'GET', {}), call('/Zone/unit.tests/', 'GET', {}),


+ 2
- 2
tests/test_octodns_provider_googlecloud.py View File

@ -264,7 +264,7 @@ class TestGoogleCloudProvider(TestCase):
existing=[update_existing_r, delete_r], existing=[update_existing_r, delete_r],
desired=desired, desired=desired,
changes=changes, changes=changes,
create=False
exists=True
)) ))
calls_mock = gcloud_zone_mock.changes.return_value calls_mock = gcloud_zone_mock.changes.return_value
@ -297,7 +297,7 @@ class TestGoogleCloudProvider(TestCase):
existing=[update_existing_r, delete_r], existing=[update_existing_r, delete_r],
desired=desired, desired=desired,
changes=changes, changes=changes,
create=False
exists=True
)) ))
unsupported_change = Mock() unsupported_change = Mock()


Loading…
Cancel
Save