From 3a520dd5443bc1e9928392a745347d4d5069f059 Mon Sep 17 00:00:00 2001 From: Przemyslaw Kaminski Date: Mon, 6 Jul 2015 15:14:44 +0200 Subject: [PATCH] Operations: fix updating of resource data with stage/commit --- run_tests.sh | 2 +- solar/solar/core/actions.py | 2 +- solar/solar/core/resource.py | 11 +++ solar/solar/operations.py | 2 + solar/solar/test/base.py | 4 +- .../solar/test/test_stage_commit_procedure.py | 3 +- .../solar/test/test_update_propagated_data.py | 75 ++++++++++++++++--- 7 files changed, 84 insertions(+), 15 deletions(-) diff --git a/run_tests.sh b/run_tests.sh index fa31e702..f2709cba 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -20,6 +20,6 @@ pip install -r solar/requirements.txt --download-cache=/tmp/$JOB_NAME pushd solar/solar -PYTHONPATH=$WORKSPACE/solar CONFIG_FILE=$CONFIG_FILE py.test test/ +PYTHONPATH=$WORKSPACE/solar CONFIG_FILE=$CONFIG_FILE py.test -s test/ popd diff --git a/solar/solar/core/actions.py b/solar/solar/core/actions.py index eb209f11..98e8618c 100644 --- a/solar/solar/core/actions.py +++ b/solar/solar/core/actions.py @@ -3,7 +3,7 @@ import handlers def resource_action(resource, action): - handler = resource.metadata['handler'] + handler = resource.metadata.get('handler', 'none') with handlers.get(handler)([resource]) as h: return h.action(resource, action) diff --git a/solar/solar/core/resource.py b/solar/solar/core/resource.py index 245b1b9a..f37f1d8f 100644 --- a/solar/solar/core/resource.py +++ b/solar/solar/core/resource.py @@ -67,6 +67,8 @@ class Resource(object): 'Argument {} not implemented for resource {}'.format(k, self) ) + if isinstance(v, dict) and 'value' in v: + v = v['value'] self.metadata['input'][k]['value'] = v db.save(self.name, self.metadata, collection=db.COLLECTIONS.resource) @@ -168,6 +170,15 @@ def wrap_resource(raw_resource): return Resource(name, raw_resource, args, tags=tags, virtual_resource=virtual_resource) +def wrap_resource_no_value(raw_resource): + name = raw_resource['id'] + args = {k: v for k, v in raw_resource['input'].items()} + tags = raw_resource.get('tags', []) + virtual_resource = raw_resource.get('virtual_resource', []) + + return Resource(name, raw_resource, args, tags=tags, virtual_resource=virtual_resource) + + def load(resource_name): raw_resource = db.read(resource_name, collection=db.COLLECTIONS.resource) diff --git a/solar/solar/operations.py b/solar/solar/operations.py index 5a94e42e..e484164c 100644 --- a/solar/solar/operations.py +++ b/solar/solar/operations.py @@ -116,6 +116,8 @@ def commit(li, resources, commited, history): commited[li.res]['metadata']) result_state = execute(commited_res, 'remove') + staged_res.set_args_from_dict(staged_data['input']) + if result_state is state.STATES.success: result_state = execute(staged_res, 'run') else: diff --git a/solar/solar/test/base.py b/solar/solar/test/base.py index 5bb526ef..2a6d4c3d 100644 --- a/solar/solar/test/base.py +++ b/solar/solar/test/base.py @@ -4,7 +4,7 @@ import tempfile import unittest import yaml -from solar.core import resource as xr +from solar.core import virtual_resource as vr from solar.core import signals as xs from solar.interfaces.db import get_db @@ -31,4 +31,4 @@ class BaseResourceTest(unittest.TestCase): return path def create_resource(self, name, src, args): - return xr.create(name, src, args) + return vr.create(name, src, args)[0] diff --git a/solar/solar/test/test_stage_commit_procedure.py b/solar/solar/test/test_stage_commit_procedure.py index 6ac6aba8..3d74273c 100644 --- a/solar/solar/test/test_stage_commit_procedure.py +++ b/solar/solar/test/test_stage_commit_procedure.py @@ -15,7 +15,8 @@ def default_resources(): {'id': 'node1', 'input': {'ip': {'value':'10.0.0.3'}}}) rabbitmq_service1 = resource.wrap_resource( - {'id':'rabbitmq', 'input': { + {'id':'rabbitmq', + 'input': { 'ip' : {'value': ''}, 'image': {'value': 'rabbitmq:3-management'}}}) signals.connect(node1, rabbitmq_service1) diff --git a/solar/solar/test/test_update_propagated_data.py b/solar/solar/test/test_update_propagated_data.py index 007e4109..af3d21f4 100644 --- a/solar/solar/test/test_update_propagated_data.py +++ b/solar/solar/test/test_update_propagated_data.py @@ -11,7 +11,8 @@ def resources(): {'id': 'node1', 'input': {'ip': {'value': '10.0.0.3'}}}) mariadb_service1 = resource.wrap_resource( - {'id': 'mariadb', 'input': { + {'id': 'mariadb', + 'input': { 'port' : {'value': 3306}, 'ip': {'value': ''}}}) keystone_db = resource.wrap_resource( @@ -50,29 +51,85 @@ def test_update_port_on_mariadb(resources): ('change', u'metadata.input.login_port.value', (3306, 4400))] +@pytest.fixture +def simple_input(): + res1 = resource.wrap_resource( + {'id': 'res1', + 'input': {'ip': {'value': '10.10.0.2'}}}) + res2 = resource.wrap_resource( + {'id': 'res2', + 'input': {'ip': {'value': '10.10.0.3'}}}) + + signals.connect(res1, res2) + return resource.load_all() + + +def test_update_simple_resource(simple_input): + operations.stage_changes() + operations.commit_changes() + + res1 = simple_input['res1'] + res1.update({'ip': '10.0.0.3'}) + + log = operations.stage_changes() + + assert len(log) == 2 + + assert log.items[0].diff == [ + ('change', u'input.ip.value', ('10.10.0.2', '10.0.0.3')), + ('change', 'metadata.input.ip.value', ('10.10.0.2', '10.0.0.3')), + ] + assert log.items[1].diff == [ + ('change', u'input.ip.value', ('10.10.0.2', '10.0.0.3')), + ('change', 'metadata.input.ip.value', ('10.10.0.2', '10.0.0.3')), + ] + + operations.commit_changes() + assert simple_input['res1'].args_dict() == { + 'ip': '10.0.0.3', + } + assert simple_input['res2'].args_dict() == { + 'ip': '10.0.0.3', + } + + log_item = operations.rollback_last() + assert log_item.diff == [ + ('change', u'input.ip.value', (u'10.0.0.3', u'10.10.0.2')), + ('change', 'metadata.input.ip.value', ('10.0.0.3', '10.10.0.2')), + ] + + res2 = resource.load('res2') + assert res2.args_dict() == { + 'ip': '10.10.0.2', + } + + @pytest.fixture def list_input(): res1 = resource.wrap_resource( - {'id': 'res1', 'input': {'ip': {'value': '10.10.0.2'}}}) + {'id': 'res1', + 'input': {'ip': {'value': '10.10.0.2'}}}) res2 = resource.wrap_resource( - {'id': 'res2', 'input': {'ip': {'value': '10.10.0.3'}}}) + {'id': 'res2', + 'input': {'ip': {'value': '10.10.0.3'}}}) consumer = resource.wrap_resource( - {'id': 'consumer', 'input': - {'ips': {'value': [], - 'schema': ['str']}}}) + {'id': 'consumer', + 'input': + {'ips': {'value': [], + 'schema': ['str']}}}) signals.connect(res1, consumer, {'ip': 'ips'}) signals.connect(res2, consumer, {'ip': 'ips'}) return resource.load_all() -@pytest.mark.xfail def test_update_list_resource(list_input): operations.stage_changes() operations.commit_changes() res3 = resource.wrap_resource( - {'id': 'res3', 'input': {'ip': {'value': '10.10.0.4'}}}) + {'id': 'res3', + 'input': {'ip': {'value': '10.10.0.4'}}}) signals.connect(res3, list_input['consumer'], {'ip': 'ips'}) log = operations.stage_changes() @@ -110,5 +167,3 @@ def test_update_list_resource(list_input): {u'emitter': u'ip', u'emitter_attached_to': u'res2', u'value': u'10.10.0.3'}]} - -