def move_to_commited(log_action, *args, **kwargs): sl = data.SL() item = next((i for i in sl if i.log_action == log_action), None) if item: resource_obj = resource.load(item.resource) commited = CommitedResource.get_or_create(item.resource) updated = resource_obj.db_obj.updated if item.action == CHANGES.remove.name: resource_obj.delete() commited.state = resource.RESOURCE_STATE.removed.name else: resource_obj.set_operational() commited.state = resource.RESOURCE_STATE.operational.name commited.base_path = item.base_path updated = resource_obj.db_obj.updated # required to update `updated` field resource_obj.db_obj.save() commited.inputs = patch(item.diff, commited.inputs) # TODO fix TagsWrp to return list # commited.tags = resource_obj.tags sorted_connections = sorted(commited.connections) commited.connections = patch(item.connections_diff, sorted_connections) commited.save() item.log = 'history' item.state = 'success' item.updated = updated item.save()
def test_revert_removal(): res = orm.DBResource(id='test1', name='test1', base_path='x') res.save() res.add_input('a', 'str', '9') res.add_input('location_id', 'str', '1') res.add_input('transports_id', 'str', '1') commited = orm.DBCommitedState.get_or_create('test1') commited.inputs = {'a': '9', 'location_id': '1', 'transports_id': '1'} commited.save() logitem =change.create_logitem( res.name, 'remove', change.create_diff({}, {'a': '9'}), [], base_path=res.base_path) log = data.SL() log.append(logitem) resource_obj = resource.load(res.name) resource_obj.remove() operations.move_to_commited(logitem.log_action) resources = orm.DBResource.load_all() assert resources == [] assert logitem.diff == [('remove', '', [('a', '9')])] with mock.patch.object(resource, 'read_meta') as mread: mread.return_value = {'input': {'a': {'schema': 'str!'}}, 'id': 'mocked'} change.revert(logitem.uid) resource_obj = resource.load('test1') assert resource_obj.args == {'a': '9', 'location_id': '1', 'transports_id': '1'}
def test_revert_update(): commit = {'a': '10'} previous = {'a': '9'} res = DBResource.from_dict('test1', {'name': 'test1', 'base_path': 'x', 'meta_inputs': {'a': {'value': None, 'schema': 'str'}}}) res.save() action = 'update' res.inputs['a'] = '9' resource_obj = resource.load(res.name) assert resource_obj.args == previous log = data.SL() logitem = change.create_logitem(res.name, action, change.create_diff(commit, previous), [], base_path=res.base_path) log.append(logitem) resource_obj.update(commit) operations.move_to_commited(logitem.log_action) assert logitem.diff == [('change', 'a', ('9', '10'))] assert resource_obj.args == commit change.revert(logitem.uid) assert resource_obj.args == previous
def test_revert_update(): commit = {'a': '10'} previous = {'a': '9'} res = orm.DBResource(id='test1', name='test1', base_path='x') res.save() res.add_input('a', 'str', '9') action = 'update' resource_obj = resource.load(res.name) assert resource_obj.args == previous log = data.SL() logitem =change.create_logitem( res.name, action, change.create_diff(commit, previous), [], base_path=res.base_path) log.append(logitem) resource_obj.update(commit) operations.move_to_commited(logitem.log_action) assert logitem.diff == [('change', 'a', ('9', '10'))] assert resource_obj.args == commit change.revert(logitem.uid) assert resource_obj.args == previous
def staged_item(log_action): item = data.SL().get(log_action) if not item: click.echo('No staged changes for {}'.format(log_action)) else: click.echo(item) for line in item.details: click.echo(' '*4+line)
def set_error(log_action, *args, **kwargs): sl = data.SL() item = next((i for i in sl if i.log_action == log_action), None) if item: resource_obj = resource.load(item.res) resource_obj.set_error() item.state = data.STATES.error sl.update(item)
def set_error(log_action, *args, **kwargs): sl = data.SL() item = next((i for i in sl if i.log_action == log_action), None) if item: resource_obj = resource.load(item.resource) resource_obj.set_error() item.state = 'error' item.delete()
def stage_changes(): for li in data.SL(): li.delete() last = LogItem.history_last() since = StrInt.greater(last.updated) if last else None staged_log = utils.solar_map(make_single_stage_item, resource.load_updated(since), concurrency=10) staged_log = filter(None, staged_log) return staged_log
def discard_uids(uids): staged_log = data.SL() check_uids_present(staged_log, uids) for uid in uids: item = staged_log.get(uid) if item.action == CHANGES.update.name: _discard_update(item) elif item.action == CHANGES.remove.name: _discard_remove(item) elif item.action == CHANGES.run.name: _discard_run(item) else: log.debug('Action %s for resource %s is a side' ' effect of another action', item.action, item.res) staged_log.pop(uid)
def send_to_orchestration(): dg = nx.MultiDiGraph() events = {} changed_nodes = [] for logitem in data.SL(): events[logitem.res] = evapi.all_events(logitem.res) changed_nodes.append(logitem.res) state_change = evapi.StateChange(logitem.res, logitem.action) state_change.insert(changed_nodes, dg) evapi.build_edges(dg, events) # what `name` should be? dg.graph['name'] = 'system_log' return graph.create_plan_from_graph(dg)
def send_to_orchestration(tags=None): dg = nx.MultiDiGraph() events = {} changed_nodes = [] if tags: staged_log = LogItem.log_items_by_tags(tags) else: staged_log = data.SL() for logitem in staged_log: events[logitem.resource] = evapi.all_events(logitem.resource) changed_nodes.append(logitem.resource) state_change = StateChange(logitem.resource, logitem.action) state_change.insert(changed_nodes, dg) evapi.build_edges(dg, events) # what `name` should be? dg.graph['name'] = 'system_log' return graph.create_plan_from_graph(dg)
def staged_log(populate_with_changes=True): """Staging procedure takes manually created log items, populate them with diff and connections diff Current implementation prevents from several things to occur: - same log_action (resource.action pair) cannot not be staged multiple times - child will be staged only if diff or connections_diff is changed, and we can execute *run* action to apply that diff - in all other cases child should be staged explicitly """ log_actions = set() resources_names = set() staged_log = data.SL() without_duplicates = [] for log_item in staged_log: if log_item.log_action in log_actions: log_item.delete() continue resources_names.add(log_item.resource) log_actions.add(log_item.log_action) without_duplicates.append(log_item) utils.solar_map(lambda li: populate_log_item(li), without_duplicates, concurrency=10) # this is backward compatible change, there might better way # to "guess" child actions childs = filter(lambda child: child.name not in resources_names, resource.load_childs(list(resources_names))) child_log_items = filter( lambda li: li.diff or li.connections_diff, utils.solar_map(create_run, [c.name for c in childs], concurrency=10)) for log_item in child_log_items + without_duplicates: log_item.save_lazy() return without_duplicates + child_log_items
def move_to_commited(log_action, *args, **kwargs): sl = data.SL() item = next((i for i in sl if i.log_action == log_action), None) if item: sl.pop(item.uid) resource_obj = resource.load(item.res) commited = orm.DBCommitedState.get_or_create(item.res) if item.action == CHANGES.remove.name: resource_obj.delete() commited.state = resource.RESOURCE_STATE.removed.name else: resource_obj.set_operational() commited.state = resource.RESOURCE_STATE.operational.name commited.inputs = patch(item.diff, commited.inputs) commited.tags = resource_obj.tags sorted_connections = sorted(commited.connections) commited.connections = patch(item.signals_diff, sorted_connections) commited.base_path = item.base_path commited.save() cl = data.CL() item.state = data.STATES.success cl.append(item)
def stage_changes(): log = data.SL() log.clean() for resouce_obj in resource.load_all(): commited = resouce_obj.load_commited() base_path = resouce_obj.base_path if resouce_obj.to_be_removed(): resource_args = {} resource_connections = [] else: resource_args = resouce_obj.args resource_connections = resouce_obj.connections if commited.state == RESOURCE_STATE.removed.name: commited_args = {} commited_connections = [] else: commited_args = commited.inputs commited_connections = commited.connections inputs_diff = create_diff(resource_args, commited_args) connections_diff = create_sorted_diff( resource_connections, commited_connections) # if new connection created it will be reflected in inputs # but using inputs to reverse connections is not possible if inputs_diff: log_item = create_logitem( resouce_obj.name, guess_action(commited_args, resource_args), inputs_diff, connections_diff, base_path=base_path) log.append(log_item) return log
def commit_all(): """Helper mainly for ease of testing""" from solar.system_log.operations import move_to_commited for item in data.SL(): move_to_commited(item.log_action)
def discard_all(): staged_log = data.SL() return discard_uids([l.key for l in staged_log])
def move_to_commited(log_action, *args, **kwargs): sl = data.SL() item = next((i for i in sl if i.log_action == log_action), None) if item: commit_log_item(item)