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()
|
@changes.command()
|
||||||
@click.option('-d', default=False, is_flag=True)
|
@click.option('-d', default=False, is_flag=True, help='detailed view')
|
||||||
def stage(d):
|
def stage(d):
|
||||||
log = list(change.stage_changes().reverse())
|
log = list(change.stage_changes().reverse())
|
||||||
for item in log:
|
for item in log:
|
||||||
@ -75,14 +75,28 @@ def commit(uid):
|
|||||||
|
|
||||||
|
|
||||||
@changes.command()
|
@changes.command()
|
||||||
@click.option('-n', default=5)
|
@click.option('-n', default=5, help='number of items to show')
|
||||||
def history(n):
|
@click.option('-d', default=False, is_flag=True, help='detailed view')
|
||||||
commited = list(data.CL().collection(n))
|
@click.option('-s', default=False, is_flag=True, help='short view, only uid')
|
||||||
if not commited:
|
def history(n, d, s):
|
||||||
click.echo('No history.')
|
log = list(data.CL().collection(n))
|
||||||
return
|
for item in log:
|
||||||
commited.reverse()
|
if s:
|
||||||
click.echo(commited)
|
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()
|
@changes.command()
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from dictdiffer import diff
|
import dictdiffer
|
||||||
import networkx as nx
|
import networkx as nx
|
||||||
|
|
||||||
from solar.core.log import log
|
from solar.core.log import log
|
||||||
@ -39,7 +39,15 @@ def guess_action(from_, to):
|
|||||||
|
|
||||||
|
|
||||||
def create_diff(staged, commited):
|
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):
|
def _stage_changes(staged_resources, commited_resources, staged_log):
|
||||||
@ -52,11 +60,7 @@ def _stage_changes(staged_resources, commited_resources, staged_log):
|
|||||||
|
|
||||||
if df:
|
if df:
|
||||||
action = guess_action(commited_data, staged_data)
|
action = guess_action(commited_data, staged_data)
|
||||||
log_item = data.LogItem(
|
log_item = create_logitem(res_uid, action, df)
|
||||||
utils.generate_uuid(),
|
|
||||||
res_uid,
|
|
||||||
'{}.{}'.format(res_uid, action),
|
|
||||||
df)
|
|
||||||
staged_log.append(log_item)
|
staged_log.append(log_item)
|
||||||
return staged_log
|
return staged_log
|
||||||
|
|
||||||
@ -102,3 +106,19 @@ def parameters(res, action, data):
|
|||||||
'type': 'solar_resource',
|
'type': 'solar_resource',
|
||||||
# unique identifier for a node should be passed
|
# unique identifier for a node should be passed
|
||||||
'target': data.get('ip')}
|
'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)
|
self.ordered_log = db.get_ordered_hash(path)
|
||||||
|
|
||||||
def append(self, logitem):
|
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):
|
def pop(self, uid):
|
||||||
item = self.get(uid)
|
item = self.get(uid)
|
||||||
@ -125,7 +125,7 @@ class Log(object):
|
|||||||
return item
|
return item
|
||||||
|
|
||||||
def update(self, logitem):
|
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):
|
def clean(self):
|
||||||
self.ordered_log.clean()
|
self.ordered_log.clean()
|
||||||
|
@ -18,7 +18,7 @@ from dictdiffer import patch
|
|||||||
|
|
||||||
def set_error(log_action, *args, **kwargs):
|
def set_error(log_action, *args, **kwargs):
|
||||||
sl = data.SL()
|
sl = data.SL()
|
||||||
item = sl.get(log_action)
|
item = next((i for i in sl if i.log_action == log_action), None)
|
||||||
if item:
|
if item:
|
||||||
item.state = data.STATES.error
|
item.state = data.STATES.error
|
||||||
sl.update(item)
|
sl.update(item)
|
||||||
@ -26,10 +26,11 @@ def set_error(log_action, *args, **kwargs):
|
|||||||
|
|
||||||
def move_to_commited(log_action, *args, **kwargs):
|
def move_to_commited(log_action, *args, **kwargs):
|
||||||
sl = data.SL()
|
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:
|
if item:
|
||||||
commited = data.CD()
|
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()
|
cl = data.CL()
|
||||||
item.state = data.STATES.success
|
item.state = data.STATES.success
|
||||||
cl.append(item)
|
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