From c8a5e689e36e328085782928f85e9e2c6d934ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claes=20N=C3=A4st=C3=A9n?= Date: Fri, 8 Dec 2017 14:10:25 +0100 Subject: [PATCH] Fix issue with setting values in choices (#33574) --- lib/ansible/module_utils/network/nso/nso.py | 11 ++- .../module_utils/network/nso/test_nso.py | 93 +++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/lib/ansible/module_utils/network/nso/nso.py b/lib/ansible/module_utils/network/nso/nso.py index 711c3bb6d52..d6eae6533f8 100644 --- a/lib/ansible/module_utils/network/nso/nso.py +++ b/lib/ansible/module_utils/network/nso/nso.py @@ -407,7 +407,7 @@ class ValueBuilder(object): parent_schema = all_schema['data'] meta = all_schema['meta'] - schema = self._get_child(parent_schema, key) + schema = self._find_child(parent_path, parent_schema, key) if self._is_leaf(schema): path_type = schema['type'] if path_type.get('primitive', False): @@ -443,11 +443,20 @@ class ValueBuilder(object): def _get_choice_child(self, schema, qname): name_key = ':' in qname and 'qname' or 'name' for child_case in schema['cases']: + # look for direct child choice_child_schema = next( (c for c in child_case['children'] if c.get(name_key, None) == qname), None) if choice_child_schema is not None: return choice_child_schema + + # look for nested choice + for child_schema in child_case['children']: + if child_schema['kind'] != 'choice': + continue + choice_child_schema = self._get_choice_child(child_schema, qname) + if choice_child_schema is not None: + return choice_child_schema return None def _is_leaf(self, schema): diff --git a/test/units/module_utils/network/nso/test_nso.py b/test/units/module_utils/network/nso/test_nso.py index bccc9185a9c..10224fb76f0 100644 --- a/test/units/module_utils/network/nso/test_nso.py +++ b/test/units/module_utils/network/nso/test_nso.py @@ -28,6 +28,7 @@ from ansible.module_utils.network.nso import nso MODULE_PREFIX_MAP = ''' { "ansible-nso": "an", + "test": "test", "tailf-ncs": "ncs" } ''' @@ -148,6 +149,67 @@ SCHEMA_DATA = { ] } } +''', + '/test:test': ''' +{ + "meta": {}, + "data": { + "kind": "list", + "name":"test", + "qname":"test:test", + "key":["name"], + "children": [ + { + "kind": "key", + "name": "name", + "qname": "test:name", + "type": {"name":"string","primitive":true} + }, + { + "kind": "choice", + "name": "test-choice", + "qname": "test:test-choice", + "cases": [ + { + "kind": "case", + "name": "direct-child-case", + "qname":"test:direct-child-case", + "children":[ + { + "kind": "leaf", + "name": "direct-child", + "qname": "test:direct-child", + "type": {"name":"string","primitive":true} + } + ] + }, + { + "kind":"case","name":"nested-child-case","qname":"test:nested-child-case", + "children": [ + { + "kind": "choice", + "name": "nested-choice", + "qname": "test:nested-choice", + "cases": [ + { + "kind":"case","name":"nested-child","qname":"test:nested-child", + "children": [ + { + "kind": "leaf", + "name":"nested-child", + "qname":"test:nested-child", + "type":{"name":"string","primitive":true}} + ] + } + ] + } + ] + } + ] + } + ] + } +} ''' } @@ -243,3 +305,34 @@ class TestValueBuilder(unittest.TestCase): self.assertEquals('1', value.value) self.assertEqual(0, len(calls)) + + @patch('ansible.module_utils.network.nso.nso.open_url') + def test_nested_choice(self, open_url_mock): + calls = [ + MockResponse('new_trans', {}, 200, '{"result": {"th": 1}}'), + get_schema_response('/test:test'), + MockResponse('exists', {'path': '/test:test{direct}'}, 200, '{"result": {"exists": true}}'), + MockResponse('exists', {'path': '/test:test{nested}'}, 200, '{"result": {"exists": true}}') + ] + open_url_mock.side_effect = lambda *args, **kwargs: mock_call(calls, *args, **kwargs) + + parent = "/test:test" + schema_data = json.loads( + SCHEMA_DATA['/test:test']) + schema = schema_data['data'] + + vb = nso.ValueBuilder(nso.JsonRpc('http://localhost:8080/jsonrpc')) + vb.build(parent, None, [{'name': 'direct', 'direct-child': 'direct-value'}, + {'name': 'nested', 'nested-child': 'nested-value'}], schema) + self.assertEquals(2, len(vb.values)) + value = vb.values[0] + self.assertEquals('{0}{{direct}}/direct-child'.format(parent), value.path) + self.assertEquals('set', value.state) + self.assertEquals('direct-value', value.value) + + value = vb.values[1] + self.assertEquals('{0}{{nested}}/nested-child'.format(parent), value.path) + self.assertEquals('set', value.state) + self.assertEquals('nested-value', value.value) + + self.assertEqual(0, len(calls))