|
|
|
@ -7,78 +7,7 @@ from __future__ import absolute_import, division, print_function, \ |
|
|
|
|
|
|
|
from ..source.base import BaseSource |
|
|
|
from ..zone import Zone |
|
|
|
from logging import getLogger |
|
|
|
|
|
|
|
|
|
|
|
class UnsafePlan(Exception): |
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
class Plan(object): |
|
|
|
log = getLogger('Plan') |
|
|
|
|
|
|
|
MAX_SAFE_UPDATE_PCENT = .3 |
|
|
|
MAX_SAFE_DELETE_PCENT = .3 |
|
|
|
MIN_EXISTING_RECORDS = 10 |
|
|
|
|
|
|
|
def __init__(self, existing, desired, changes, |
|
|
|
update_pcent_threshold=MAX_SAFE_UPDATE_PCENT, |
|
|
|
delete_pcent_threshold=MAX_SAFE_DELETE_PCENT): |
|
|
|
self.existing = existing |
|
|
|
self.desired = desired |
|
|
|
self.changes = changes |
|
|
|
self.update_pcent_threshold = update_pcent_threshold |
|
|
|
self.delete_pcent_threshold = delete_pcent_threshold |
|
|
|
|
|
|
|
change_counts = { |
|
|
|
'Create': 0, |
|
|
|
'Delete': 0, |
|
|
|
'Update': 0 |
|
|
|
} |
|
|
|
for change in changes: |
|
|
|
change_counts[change.__class__.__name__] += 1 |
|
|
|
self.change_counts = change_counts |
|
|
|
|
|
|
|
try: |
|
|
|
existing_n = len(self.existing.records) |
|
|
|
except AttributeError: |
|
|
|
existing_n = 0 |
|
|
|
|
|
|
|
self.log.debug('__init__: Creates=%d, Updates=%d, Deletes=%d' |
|
|
|
'Existing=%d', |
|
|
|
self.change_counts['Create'], |
|
|
|
self.change_counts['Update'], |
|
|
|
self.change_counts['Delete'], existing_n) |
|
|
|
|
|
|
|
def raise_if_unsafe(self): |
|
|
|
# TODO: what is safe really? |
|
|
|
if self.existing and \ |
|
|
|
len(self.existing.records) >= self.MIN_EXISTING_RECORDS: |
|
|
|
|
|
|
|
existing_record_count = len(self.existing.records) |
|
|
|
update_pcent = self.change_counts['Update'] / existing_record_count |
|
|
|
delete_pcent = self.change_counts['Delete'] / existing_record_count |
|
|
|
|
|
|
|
if update_pcent > self.update_pcent_threshold: |
|
|
|
raise UnsafePlan('Too many updates, {} is over {} percent' |
|
|
|
'({}/{})'.format( |
|
|
|
update_pcent, |
|
|
|
self.MAX_SAFE_UPDATE_PCENT * 100, |
|
|
|
self.change_counts['Update'], |
|
|
|
existing_record_count)) |
|
|
|
if delete_pcent > self.delete_pcent_threshold: |
|
|
|
raise UnsafePlan('Too many deletes, {} is over {} percent' |
|
|
|
'({}/{})'.format( |
|
|
|
delete_pcent, |
|
|
|
self.MAX_SAFE_DELETE_PCENT * 100, |
|
|
|
self.change_counts['Delete'], |
|
|
|
existing_record_count)) |
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
return 'Creates={}, Updates={}, Deletes={}, Existing Records={}' \ |
|
|
|
.format(self.change_counts['Create'], self.change_counts['Update'], |
|
|
|
self.change_counts['Delete'], |
|
|
|
len(self.existing.records)) |
|
|
|
from .plan import Plan |
|
|
|
|
|
|
|
|
|
|
|
class BaseProvider(BaseSource): |
|
|
|
|