mirror of
https://github.com/github/octodns.git
synced 2024-05-11 05:55:00 +00:00
Merge pull request #120 from github/threshold_overrides
add ability to configure update/delete thresholds
This commit is contained in:
@@ -21,10 +21,14 @@ 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):
|
def __init__(self, existing, desired, changes,
|
||||||
|
update_pcent_threshold=MAX_SAFE_UPDATE_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.update_pcent_threshold = update_pcent_threshold
|
||||||
|
self.delete_pcent_threshold = delete_pcent_threshold
|
||||||
|
|
||||||
change_counts = {
|
change_counts = {
|
||||||
'Create': 0,
|
'Create': 0,
|
||||||
@@ -55,14 +59,14 @@ class Plan(object):
|
|||||||
update_pcent = self.change_counts['Update'] / existing_record_count
|
update_pcent = self.change_counts['Update'] / existing_record_count
|
||||||
delete_pcent = self.change_counts['Delete'] / existing_record_count
|
delete_pcent = self.change_counts['Delete'] / existing_record_count
|
||||||
|
|
||||||
if update_pcent > self.MAX_SAFE_UPDATE_PCENT:
|
if update_pcent > self.update_pcent_threshold:
|
||||||
raise UnsafePlan('Too many updates, {} is over {} percent'
|
raise UnsafePlan('Too many updates, {} is over {} percent'
|
||||||
'({}/{})'.format(
|
'({}/{})'.format(
|
||||||
update_pcent,
|
update_pcent,
|
||||||
self.MAX_SAFE_UPDATE_PCENT * 100,
|
self.MAX_SAFE_UPDATE_PCENT * 100,
|
||||||
self.change_counts['Update'],
|
self.change_counts['Update'],
|
||||||
existing_record_count))
|
existing_record_count))
|
||||||
if delete_pcent > self.MAX_SAFE_DELETE_PCENT:
|
if delete_pcent > self.delete_pcent_threshold:
|
||||||
raise UnsafePlan('Too many deletes, {} is over {} percent'
|
raise UnsafePlan('Too many deletes, {} is over {} percent'
|
||||||
'({}/{})'.format(
|
'({}/{})'.format(
|
||||||
delete_pcent,
|
delete_pcent,
|
||||||
@@ -79,11 +83,19 @@ class Plan(object):
|
|||||||
|
|
||||||
class BaseProvider(BaseSource):
|
class BaseProvider(BaseSource):
|
||||||
|
|
||||||
def __init__(self, id, apply_disabled=False):
|
def __init__(self, id, apply_disabled=False,
|
||||||
|
update_pcent_threshold=Plan.MAX_SAFE_UPDATE_PCENT,
|
||||||
|
delete_pcent_threshold=Plan.MAX_SAFE_DELETE_PCENT):
|
||||||
super(BaseProvider, self).__init__(id)
|
super(BaseProvider, self).__init__(id)
|
||||||
self.log.debug('__init__: id=%s, apply_disabled=%s', id,
|
self.log.debug('__init__: id=%s, apply_disabled=%s, '
|
||||||
apply_disabled)
|
'update_pcent_threshold=%d, delete_pcent_threshold=%d',
|
||||||
|
id,
|
||||||
|
apply_disabled,
|
||||||
|
update_pcent_threshold,
|
||||||
|
delete_pcent_threshold)
|
||||||
self.apply_disabled = apply_disabled
|
self.apply_disabled = apply_disabled
|
||||||
|
self.update_pcent_threshold = update_pcent_threshold
|
||||||
|
self.delete_pcent_threshold = delete_pcent_threshold
|
||||||
|
|
||||||
def _include_change(self, change):
|
def _include_change(self, change):
|
||||||
'''
|
'''
|
||||||
@@ -124,7 +136,9 @@ class BaseProvider(BaseSource):
|
|||||||
changes += extra
|
changes += extra
|
||||||
|
|
||||||
if changes:
|
if changes:
|
||||||
plan = Plan(existing, desired, changes)
|
plan = Plan(existing, desired, changes,
|
||||||
|
self.update_pcent_threshold,
|
||||||
|
self.delete_pcent_threshold)
|
||||||
self.log.info('plan: %s', plan)
|
self.log.info('plan: %s', plan)
|
||||||
return plan
|
return plan
|
||||||
self.log.info('plan: No changes')
|
self.log.info('plan: No changes')
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ class HelperProvider(BaseProvider):
|
|||||||
self.__extra_changes = extra_changes
|
self.__extra_changes = extra_changes
|
||||||
self.apply_disabled = apply_disabled
|
self.apply_disabled = apply_disabled
|
||||||
self.include_change_callback = include_change_callback
|
self.include_change_callback = include_change_callback
|
||||||
|
self.update_pcent_threshold = Plan.MAX_SAFE_UPDATE_PCENT
|
||||||
|
self.delete_pcent_threshold = Plan.MAX_SAFE_DELETE_PCENT
|
||||||
|
|
||||||
def populate(self, zone, target=False, lenient=False):
|
def populate(self, zone, target=False, lenient=False):
|
||||||
pass
|
pass
|
||||||
@@ -288,3 +290,59 @@ class TestBaseProvider(TestCase):
|
|||||||
Plan.MAX_SAFE_DELETE_PCENT))]
|
Plan.MAX_SAFE_DELETE_PCENT))]
|
||||||
|
|
||||||
Plan(zone, zone, changes).raise_if_unsafe()
|
Plan(zone, zone, changes).raise_if_unsafe()
|
||||||
|
|
||||||
|
def test_safe_updates_min_existing_override(self):
|
||||||
|
safe_pcent = .4
|
||||||
|
# 40% + 1 fails when more
|
||||||
|
# than MIN_EXISTING_RECORDS exist
|
||||||
|
zone = Zone('unit.tests.', [])
|
||||||
|
record = Record.new(zone, 'a', {
|
||||||
|
'ttl': 30,
|
||||||
|
'type': 'A',
|
||||||
|
'value': '1.2.3.4',
|
||||||
|
})
|
||||||
|
|
||||||
|
for i in range(int(Plan.MIN_EXISTING_RECORDS)):
|
||||||
|
zone.add_record(Record.new(zone, str(i), {
|
||||||
|
'ttl': 60,
|
||||||
|
'type': 'A',
|
||||||
|
'value': '2.3.4.5'
|
||||||
|
}))
|
||||||
|
|
||||||
|
changes = [Update(record, record)
|
||||||
|
for i in range(int(Plan.MIN_EXISTING_RECORDS *
|
||||||
|
safe_pcent) + 1)]
|
||||||
|
|
||||||
|
with self.assertRaises(UnsafePlan) as ctx:
|
||||||
|
Plan(zone, zone, changes,
|
||||||
|
update_pcent_threshold=safe_pcent).raise_if_unsafe()
|
||||||
|
|
||||||
|
self.assertTrue('Too many updates' in ctx.exception.message)
|
||||||
|
|
||||||
|
def test_safe_deletes_min_existing_override(self):
|
||||||
|
safe_pcent = .4
|
||||||
|
# 40% + 1 fails when more
|
||||||
|
# than MIN_EXISTING_RECORDS exist
|
||||||
|
zone = Zone('unit.tests.', [])
|
||||||
|
record = Record.new(zone, 'a', {
|
||||||
|
'ttl': 30,
|
||||||
|
'type': 'A',
|
||||||
|
'value': '1.2.3.4',
|
||||||
|
})
|
||||||
|
|
||||||
|
for i in range(int(Plan.MIN_EXISTING_RECORDS)):
|
||||||
|
zone.add_record(Record.new(zone, str(i), {
|
||||||
|
'ttl': 60,
|
||||||
|
'type': 'A',
|
||||||
|
'value': '2.3.4.5'
|
||||||
|
}))
|
||||||
|
|
||||||
|
changes = [Delete(record)
|
||||||
|
for i in range(int(Plan.MIN_EXISTING_RECORDS *
|
||||||
|
safe_pcent) + 1)]
|
||||||
|
|
||||||
|
with self.assertRaises(UnsafePlan) as ctx:
|
||||||
|
Plan(zone, zone, changes,
|
||||||
|
delete_pcent_threshold=safe_pcent).raise_if_unsafe()
|
||||||
|
|
||||||
|
self.assertTrue('Too many deletes' in ctx.exception.message)
|
||||||
|
|||||||
Reference in New Issue
Block a user