Merge pull request #190 from dshulyak/revert_support
Add support for revert of a change
This commit is contained in:
commit
02bdd23348
@ -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()
|
||||
|
@ -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])
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
46
solar/solar/test/test_system_log_api.py
Normal file
46
solar/solar/test/test_system_log_api.py
Normal 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
|
Loading…
Reference in New Issue
Block a user