Merge pull request #190 from dshulyak/revert_support

Add support for revert of a change
This commit is contained in:
Jędrzej Nowak 2015-09-24 09:10:55 +02:00
commit 02bdd23348
5 changed files with 102 additions and 21 deletions

View File

@ -39,7 +39,7 @@ def validate():
@changes.command()
@click.option('-d', default=False, is_flag=True)
@click.option('-d', default=False, is_flag=True, help='detailed view')
def stage(d):
log = list(change.stage_changes().reverse())
for item in log:
@ -75,14 +75,28 @@ def commit(uid):
@changes.command()
@click.option('-n', default=5)
def history(n):
commited = list(data.CL().collection(n))
if not commited:
click.echo('No history.')
return
commited.reverse()
click.echo(commited)
@click.option('-n', default=5, help='number of items to show')
@click.option('-d', default=False, is_flag=True, help='detailed view')
@click.option('-s', default=False, is_flag=True, help='short view, only uid')
def history(n, d, s):
log = list(data.CL().collection(n))
for item in log:
if s:
click.echo(item.uid)
continue
click.echo(item)
if d:
for line in item.details:
click.echo(' '*4+line)
if not log:
click.echo('No history')
@changes.command()
@click.argument('uid')
def revert(uid):
change.revert(uid)
@changes.command()

View File

@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from dictdiffer import diff
import dictdiffer
import networkx as nx
from solar.core.log import log
@ -39,7 +39,15 @@ def guess_action(from_, to):
def create_diff(staged, commited):
return list(diff(commited, staged))
return list(dictdiffer.diff(commited, staged))
def create_logitem(resource, action, diffed):
return data.LogItem(
utils.generate_uuid(),
resource,
'{}.{}'.format(resource, action),
diffed)
def _stage_changes(staged_resources, commited_resources, staged_log):
@ -52,11 +60,7 @@ def _stage_changes(staged_resources, commited_resources, staged_log):
if df:
action = guess_action(commited_data, staged_data)
log_item = data.LogItem(
utils.generate_uuid(),
res_uid,
'{}.{}'.format(res_uid, action),
df)
log_item = create_logitem(res_uid, action, df)
staged_log.append(log_item)
return staged_log
@ -102,3 +106,19 @@ def parameters(res, action, data):
'type': 'solar_resource',
# unique identifier for a node should be passed
'target': data.get('ip')}
def revert_uids(uids):
commited = data.CD()
history = data.CL()
for uid in uids:
item = history.get(uid)
res_db = resource.load(item.res)
args_to_update = dictdiffer.revert(
item.diff, commited.get(item.res, {}))
res_db.update(args_to_update)
def revert(uid):
return revert_uids([uid])

View File

@ -115,7 +115,7 @@ class Log(object):
self.ordered_log = db.get_ordered_hash(path)
def append(self, logitem):
self.ordered_log.add([(logitem.log_action, logitem.to_dict())])
self.ordered_log.add([(logitem.uid, logitem.to_dict())])
def pop(self, uid):
item = self.get(uid)
@ -125,7 +125,7 @@ class Log(object):
return item
def update(self, logitem):
self.ordered_log.update(logitem.log_action, logitem.to_dict())
self.ordered_log.update(logitem.uid, logitem.to_dict())
def clean(self):
self.ordered_log.clean()

View File

@ -18,7 +18,7 @@ from dictdiffer import patch
def set_error(log_action, *args, **kwargs):
sl = data.SL()
item = sl.get(log_action)
item = next((i for i in sl if i.log_action == log_action), None)
if item:
item.state = data.STATES.error
sl.update(item)
@ -26,10 +26,11 @@ def set_error(log_action, *args, **kwargs):
def move_to_commited(log_action, *args, **kwargs):
sl = data.SL()
item = sl.pop(log_action)
item = next((i for i in sl if i.log_action == log_action), None)
sl.pop(item.uid)
if item:
commited = data.CD()
staged_data = patch(item.diff, commited.get(item.log_action, {}))
staged_data = patch(item.diff, commited.get(item.res, {}))
cl = data.CL()
item.state = data.STATES.success
cl.append(item)

View File

@ -0,0 +1,46 @@
# Copyright 2015 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from pytest import fixture
from solar.system_log import change
from solar.system_log import data
from solar.system_log import operations
from solar.core.resource import resource
from solar.interfaces import orm
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))
log.append(logitem)
resource_obj.update(commit)
operations.move_to_commited(logitem.log_action)
assert resource_obj.args == commit
change.revert(logitem.uid)
assert resource_obj.args == previous