class TestParallel(unittest.TestCase): parser_output = { 'platform': { 'name': 'Nexus', 'os': 'NX-OS', 'software': { 'bios_version': '07.33', 'system_version': '9.3(3) [build 9.3(3)IDI9(0.509)]', 'bios_compile_time': '08/04/2015', 'system_image_file': 'bootflash:///system-image-N93_3-00613722415136', 'system_compile_time': '10/22/2019 10:00:00 [10/22/2019 16:57:31]' }, 'hardware': { 'model': 'Nexus9000 C9396PX', 'chassis': 'Nexus9000 C9396PX', 'slots': 'None', 'rp': 'None', 'cpu': 'Intel(R) Core(TM) i3- CPU @ 2.50GHz', 'memory': '16399900 kB', 'processor_board_id': 'SAL1914CNL6', 'device_name': 'N93_3', 'bootflash': '51496280 kB' }, 'kernel_uptime': { 'days': 61, 'hours': 22, 'minutes': 8, 'seconds': 40 }, 'reason': 'Reset Requested by CLI command reload', 'system_version': '9.3(3)' } } execute_output = """ 2020-11-24 12:25:43,769: %UNICON-INFO: +++ N93_3: executing command 'show version' +++ show version Cisco Nexus Operating System (NX-OS) Software TAC support: http://www.cisco.com/tac Copyright (C) 2002-2019, Cisco and/or its affiliates. All rights reserved. The copyrights to certain works contained in this software are owned by other third parties and used and distributed under their own licenses, such as open source. This software is provided "as is," and unless otherwise stated, there is no warranty, express or implied, including but not limited to warranties of merchantability and fitness for a particular purpose. Certain components of this software are licensed under the GNU General Public License (GPL) version 2.0 or GNU General Public License (GPL) version 3.0 or the GNU Lesser General Public License (LGPL) Version 2.1 or Lesser General Public License (LGPL) Version 2.0. A copy of each such license is available at http://www.opensource.org/licenses/gpl-2.0.php and http://opensource.org/licenses/gpl-3.0.html and http://www.opensource.org/licenses/lgpl-2.1.php and http://www.gnu.org/licenses/old-licenses/library.txt. Software BIOS: version 07.33 NXOS: version 9.3(3) [build 9.3(3)IDI9(0.509)] BIOS compile time: 08/04/2015 NXOS image file is: bootflash:///system-image-N93_3-00613722415136 NXOS compile time: 10/22/2019 10:00:00 [10/22/2019 16:57:31] Hardware cisco Nexus9000 C9396PX Chassis Intel(R) Core(TM) i3- CPU @ 2.50GHz with 16399900 kB of memory. Processor Board ID SAL1914CNL6 Device name: N93_3 bootflash: 51496280 kB Kernel uptime is 61 day(s), 22 hour(s), 33 minute(s), 56 second(s) Last reset at 930930 usecs after Wed Sep 23 13:59:45 2020 Reason: Reset Requested by CLI command reload System version: 9.3(3) Service: plugin Core Plugin, Ethernet Plugin Active Package(s): """ yaml1 = """ - configure: command: feature bgp device: PE1 save: - variable_name: conf1 description: expected_failure is True passed as a result - execute: alias: execute_id command: show version device: PE1 exclude: - extreme include: - host - parse: command: command device: PE1 include: - contains('software') - get_values('hardware', 0) """ yaml2 = """ - configure: command: feature bgp device: PE1 save: - variable_name: conf1 description: expected_failure is True passed as a result - execute: alias: execute_id command: show version device: PE1 include: - extreme """ yaml3 = """ - run_condition: if : "%VARIABLES{execute_id} == passed" function: failed actions: - loop: loop_variable_name: var_name value: ['show vrf', 'show version'] loop_until: failed actions: - execute: alias: exec_1 device: PE1 command: "%VARIABLES{var_name}" - execute: alias: exec_2 device: PE2 command: "%VARIABLES{var_name}" - loop: loop_variable_name: var_name value: ['show vrf', 'show version'] actions: - configure: device: PE1 command: feature bgp - execute: device: PE1 command: "%VARIABLES{var_name}" - loop: loop_variable_name: dev_name value: ['PE1','PE2'] loop_until: passed actions: - parse: alias: parse_lopp_w save: - variable_name: parse32 filter: contains('hardware') device: "%VARIABLES{dev_name}" command: show version - execute: alias: id device: "%VARIABLES{dev_name}" command: show vrf - loop: loop_variable_name: dev_name value: ['PE1','PE2'] actions: - execute: device: "%VARIABLES{dev_name}" command: show version - execute: device: "%VARIABLES{dev_name}" command: show version - parse: alias: parse_id command: command device: PE1 include: - contains('software') - get_values('hardware', 0) """ def setUp(self): dir_name = os.path.dirname(os.path.abspath(__file__)) f, self.jobfile = tempfile.mkstemp() init_runtime(runtime) runtime.configuration.load() runtime.job = Job(jobfile=self.jobfile, runtime=runtime, **runtime.configuration.components.job) mgr = runtime.tasks task = mgr.Task(testscript=os.path.join( dir_name, 'mock_yamls/trigger_datafile.yaml'), taskid='awesome') self.testbed = load( os.path.join(dir_name, 'mock_testbeds/testbed.yaml')) self.mock_testbed_devs() Blitz.parameters = ParameterMap() Blitz.uid = 'test.dev' Blitz.parameters['testbed'] = self.testbed self.blitz_obj = Blitz() self.uid = self.blitz_obj.uid self.blitz_obj.parent = self self.blitz_obj.parent.parameters = mock.Mock() self.blitz_obj.parameters['test_sections'] = [{ 'section1': [{ 'parallel': [{ 'action': { 'arg1': 'cmd' } }] }] }] sections = self.blitz_obj._discover() self.kwargs = { 'self': self.blitz_obj, 'testbed': self.testbed, 'section': sections[0].__testcls__(sections[0]), 'name': '' } def mock_testbed_devs(self): side_effects = { 'configure': ['\n'], 'execute': ['host execute output', 'oop', 'oot', 'name'], 'parse': [self.parser_output] } for dev in self.testbed.devices: for action in side_effects.keys(): setattr(self.testbed.devices[dev], action, mock.Mock()) setattr(getattr(self.testbed.devices[dev], action), 'side_effect', side_effects[action]) def test_parallel_actions_pass(self): steps = Steps() data = yaml.safe_load(self.yaml1) self.kwargs.update({'data': data, 'steps': steps}) parallel(**self.kwargs) self.assertIn('execute_id', self.blitz_obj.parameters['save_variable_name']) self.assertEqual(steps.result, Passed) self.assertEqual( self.blitz_obj.parameters['save_variable_name']['execute_id'], 'passed') def test_parallel_actions_fail(self): steps = Steps() data = yaml.safe_load(self.yaml2) self.kwargs.update({'data': data, 'steps': steps}) parallel(**self.kwargs) self.assertEqual(steps.result, Failed) self.assertEqual( self.blitz_obj.parameters['save_variable_name']['execute_id'], 'failed') def test_parallel_loops(self): steps = Steps() data = yaml.safe_load(self.yaml3) self.blitz_obj.parameters['save_variable_name'] = {} self.blitz_obj.parameters['save_variable_name'][ 'execute_id'] = 'passed' self.kwargs.update({ 'self': self.blitz_obj, 'data': data, 'steps': steps }) # TODO alias and saved_vars wont get stored when under loop/run_condition # self.assertIn('exec_1', self.blitz_obj.parameters['save_variable_name']) parallel(**self.kwargs) self.assertIn('parse_id', self.blitz_obj.parameters['save_variable_name']) self.assertEqual(steps.result, Failed) self.assertEqual(steps.details[0].name, 'Executing actions in parallel') self.assertEqual( steps.details[1].name, 'Condition %VARIABLES{execute_id} == passed is met and ' 'the step result is failed') self.assertEqual(steps.details[1].result, Failed)
class TestMarkup(unittest.TestCase): dict_output = {'platform': {'name': 'Nexus', 'os': 'NX-OS', 'software': {'bios_version': '07.33', 'system_version': '9.3(3) [build 9.3(3)IDI9(0.509)]', 'bios_compile_time': '08/04/2015', 'system_image_file': 'bootflash:///system-image-N93_3-00613722415136', 'system_compile_time': '10/22/2019 10:00:00 [10/22/2019 16:57:31]'}, 'hardware': {'model': 'Nexus9000 C9396PX', 'chassis': 'Nexus9000 C9396PX', 'slots': 'None', 'rp': 'None', 'cpu': 'Intel(R) Core(TM) i3- CPU @ 2.50GHz', 'memory': '16399900 kB', 'processor_board_id': 'SAL1914CNL6', 'device_name': 'N93_3', 'bootflash': '51496280 kB'}, 'kernel_uptime': {'days': 61, 'hours': 22, 'minutes': 8, 'seconds': 40}, 'reason': 'Reset Requested by CLI command reload', 'system_version': '9.3(3)'}} str_output = """ 2020-11-24 12:25:43,769: %UNICON-INFO: +++ N93_3: executing command 'show version' +++ show version Cisco Nexus Operating System (NX-OS) Software TAC support: http://www.cisco.com/tac Copyright (C) 2002-2019, Cisco and/or its affiliates. All rights reserved. The copyrights to certain works contained in this software are owned by other third parties and used and distributed under their own licenses, such as open source. This software is provided "as is," and unless otherwise stated, there is no warranty, express or implied, including but not limited to warranties of merchantability and fitness for a particular purpose. Certain components of this software are licensed under the GNU General Public License (GPL) version 2.0 or GNU General Public License (GPL) version 3.0 or the GNU Lesser General Public License (LGPL) Version 2.1 or Lesser General Public License (LGPL) Version 2.0. A copy of each such license is available at http://www.opensource.org/licenses/gpl-2.0.php and http://opensource.org/licenses/gpl-3.0.html and http://www.opensource.org/licenses/lgpl-2.1.php and http://www.gnu.org/licenses/old-licenses/library.txt. Software BIOS: version 07.33 NXOS: version 9.3(3) [build 9.3(3)IDI9(0.509)] BIOS compile time: 08/04/2015 NXOS image file is: bootflash:///system-image-N93_3-00613722415136 NXOS compile time: 10/22/2019 10:00:00 [10/22/2019 16:57:31] Hardware cisco Nexus9000 C9396PX Chassis Intel(R) Core(TM) i3- CPU @ 2.50GHz with 16399900 kB of memory. Processor Board ID SAL1914CNL6 Device name: N93_3 bootflash: 51496280 kB Kernel uptime is 61 day(s), 22 hour(s), 33 minute(s), 56 second(s) Last reset at 930930 usecs after Wed Sep 23 13:59:45 2020 Reason: Reset Requested by CLI command reload System version: 9.3(3) Service: plugin Core Plugin, Ethernet Plugin Active Package(s): """ def setUp(self): dir_name = os.path.dirname(os.path.abspath(__file__)) mfc = MockFuncClass() self.testbed = load(os.path.join(dir_name, 'mock_testbeds/testbed.yaml')) Blitz.parameters = ParameterMap() Blitz.uid = 'test.dev' Blitz.parameters['testbed'] = self.testbed Blitz.parameters['save_variable_name'] = {'dev_name': 'PE2', 'command':'sh version', 'sub_command': 'interface', 'type_k': 1500, 'list_item': [177,24,13,45], 'iter_class': mfc, 'dict1': {'st': "name"}} self.blitz_obj = Blitz() self.uid = self.blitz_obj.uid self.blitz_obj.parent = self self.blitz_obj.parent.parameters = mock.Mock() self.blitz_obj.parameters['test_sections'] = [{'section1': [{'execute': {'command': 'cmd', 'device': 'PE1'}}]}] sections = self.blitz_obj._discover() self.section = sections[0].__testcls__(sections[0]) def test_dq_filter_list_index(self): list_output = [1,2,3,4,6,7,8,9999,854] list_index = 3 filtered_out = apply_list_filter(self.blitz_obj, list_output, list_index=list_index) self.assertEqual(filtered_out, 4) def test_dq_filter_list_slice(self): list_output = [1,2,3,4,6,7,8,9999,854] list_index = "[1:4]" filtered_out = apply_list_filter(self.blitz_obj, list_output, list_index=list_index) self.assertEqual(filtered_out, [2,3,4]) def test_dq_filter_list_regex(self): list_output = ["aba", "yes"] filtered_out = apply_list_filter(self.blitz_obj, list_output, filters='yes') self.assertEqual(filtered_out, ["yes"]) filtered_out = apply_list_filter(self.blitz_obj, list_output, filters='\d') self.assertEqual(filtered_out, []) def test_dq_filter(self): filters = "contains('software')" filtered_out = apply_dictionary_filter(self.blitz_obj, self.dict_output, filters) self.assertEqual(filtered_out, {'platform': {'software': {'bios_version': '07.33', 'system_version': '9.3(3) [build 9.3(3)IDI9(0.509)]', 'bios_compile_time': '08/04/2015', 'system_image_file': 'bootflash:///system-image-N93_3-00613722415136', 'system_compile_time': '10/22/2019 10:00:00 [10/22/2019 16:57:31]'}}}) def test_string_filter(self): filters = r"Device\s+name:\s+(?P<dev>.*)" filtered_out = apply_regex_filter(self.blitz_obj, self.str_output, filters) self.assertEqual(filtered_out, {'dev': 'N93_3'}) filters = r"Device\s+name:\s+(?P<dev>NO MATCH)" filtered_out = apply_regex_filter(self.blitz_obj, self.str_output, filters) self.assertEqual(filtered_out, {}) def test_no_filter(self): # with No filter filtered_out = apply_dictionary_filter(self.blitz_obj, output=self.dict_output) self.assertEqual(filtered_out, self.dict_output) filtered_out = apply_regex_filter(self.blitz_obj, output=self.str_output) self.assertEqual(filtered_out, self.str_output) def test_get_variable_replace(self): kwargs = {'command': r"%VARIABLES{command}", 'device': 'PE2', 'self': self.blitz_obj, 'section': self.section} replaced_kwargs = get_variable(**kwargs) # check if replacement is done self.assertEqual(replaced_kwargs['command'], self.blitz_obj.parameters['save_variable_name']['command']) def test_get_variable_replace_replace_keep_type(self): kwargs = {'self': self.blitz_obj, 'item': {'value': r"%VARIABLES{type_k}", 'val': 11, 'ls': ['a', {'b':1}]}, 'section': self.section} replaced_kwargs = get_variable(**kwargs) # check if type would stay the same self.assertEqual(type(replaced_kwargs['item']['value']), int) def test_get_variable_replace_replace_mid_str(self): kwargs = {'cmd': r"show %VARIABLES{sub_command}", 'self': self.blitz_obj, 'section': self.section} replaced_kwargs = get_variable(**kwargs) self.assertEqual(replaced_kwargs['cmd'], 'show interface') def test_get_variable_replace_replace_list_item(self): kwargs = {'cmd': r"%VARIABLES{list_item[2]}", 'self': self.blitz_obj, 'section': self.section} replaced_kwargs = get_variable(**kwargs) self.assertEqual(replaced_kwargs['cmd'], 13) # TODO check why ._keys and ._values doesnt work def test_get_variable_replace_dict_item(self): pass def test_get_variable_replace_replace_iter_fucnt(self): kwargs = {'a': r"%VARIABLES{iter_class.mock_func}", 'self': self.blitz_obj, 'section': self.section} replaced_kwargs = get_variable(**kwargs) self.assertEqual(replaced_kwargs['a'], 'mock func returned val') def test_save_variable(self): save_variable(self.blitz_obj, self.section, 'var1', 'aa') self.assertEqual( self.blitz_obj.parameters['save_variable_name']['var1'], 'aa') def test_save_variable_append(self): save_variable(self.blitz_obj, self.section, 'sub_command', 'vrf', append=True) self.assertEqual( self.blitz_obj.parameters['save_variable_name']['sub_command'], 'interface\nvrf') def test_save_variable_append_in_empty_list(self): save_variable(self.blitz_obj, self.section, 'new_item', 'VRF1', append_in_list=True) self.assertEqual( self.blitz_obj.parameters['save_variable_name']['new_item'], ['VRF1']) def test_save_variable_append_in_existing_list(self): save_variable(self.blitz_obj, self.section, 'list_item', 9000, append_in_list=True) self.assertEqual( self.blitz_obj.parameters['save_variable_name']['list_item'], [177,24,13,45, 9000])
class TestCondition(unittest.TestCase): parser_output = { 'platform': { 'name': 'Nexus', 'os': 'NX-OS', 'software': { 'bios_version': '07.33', 'system_version': '9.3(3) [build 9.3(3)IDI9(0.509)]', 'bios_compile_time': '08/04/2015', 'system_image_file': 'bootflash:///system-image-N93_3-00613722415136', 'system_compile_time': '10/22/2019 10:00:00 [10/22/2019 16:57:31]' }, 'hardware': { 'model': 'Nexus9000 C9396PX', 'chassis': 'Nexus9000 C9396PX', 'slots': 'None', 'rp': 'None', 'cpu': 'Intel(R) Core(TM) i3- CPU @ 2.50GHz', 'memory': '16399900 kB', 'processor_board_id': 'SAL1914CNL6', 'device_name': 'N93_3', 'bootflash': '51496280 kB' }, 'kernel_uptime': { 'days': 61, 'hours': 22, 'minutes': 8, 'seconds': 40 }, 'reason': 'Reset Requested by CLI command reload', 'system_version': '9.3(3)' } } execute_output = """ 2020-11-24 12:25:43,769: %UNICON-INFO: +++ N93_3: executing command 'show version' +++ show version Cisco Nexus Operating System (NX-OS) Software TAC support: http://www.cisco.com/tac Copyright (C) 2002-2019, Cisco and/or its affiliates. All rights reserved. The copyrights to certain works contained in this software are owned by other third parties and used and distributed under their own licenses, such as open source. This software is provided "as is," and unless otherwise stated, there is no warranty, express or implied, including but not limited to warranties of merchantability and fitness for a particular purpose. Certain components of this software are licensed under the GNU General Public License (GPL) version 2.0 or GNU General Public License (GPL) version 3.0 or the GNU Lesser General Public License (LGPL) Version 2.1 or Lesser General Public License (LGPL) Version 2.0. A copy of each such license is available at http://www.opensource.org/licenses/gpl-2.0.php and http://opensource.org/licenses/gpl-3.0.html and http://www.opensource.org/licenses/lgpl-2.1.php and http://www.gnu.org/licenses/old-licenses/library.txt. Software BIOS: version 07.33 NXOS: version 9.3(3) [build 9.3(3)IDI9(0.509)] BIOS compile time: 08/04/2015 NXOS image file is: bootflash:///system-image-N93_3-00613722415136 NXOS compile time: 10/22/2019 10:00:00 [10/22/2019 16:57:31] Hardware cisco Nexus9000 C9396PX Chassis Intel(R) Core(TM) i3- CPU @ 2.50GHz with 16399900 kB of memory. Processor Board ID SAL1914CNL6 Device name: N93_3 bootflash: 51496280 kB Kernel uptime is 61 day(s), 22 hour(s), 33 minute(s), 56 second(s) Last reset at 930930 usecs after Wed Sep 23 13:59:45 2020 Reason: Reset Requested by CLI command reload System version: 9.3(3) Service: plugin Core Plugin, Ethernet Plugin Active Package(s): """ condition_1 = """ if : "%VARIABLES{execute_id} == id1" function: failed actions: - execute: alias: exec_1 device: PE1 command: cmd - execute: alias: exec_2 device: PE2 command: another - configure: device: PE1 command: feature bgp - execute: device: PE1 command: aa """ condition_2 = """ if : "%VARIABLES{execute_id} == id2" function: failed actions: - execute: alias: exec_1 device: PE1 command: cmd - execute: alias: exec_2 device: PE2 command: another - configure: device: PE1 command: feature bgp - execute: device: PE1 command: aa """ condition_3 = """ if : "%VARIABLES{execute_id} == id1" function: passed actions: - parallel: - execute: alias: exec_1 device: PE1 command: cmd - execute: alias: exec_2 device: PE2 command: another - configure: device: PE1 command: feature bgp - execute: device: PE1 command: aa """ condition_4 = """ if : "%VARIABLES{execute_id} == id1" actions: - parallel: - execute: alias: exec_1 device: PE1 command: cmd - execute: alias: exec_2 device: PE2 command: another - configure: device: PE1 command: feature bgp - execute: device: PE1 command: aa """ condition_5 = """ if : "%VARIABLES{execute_id} == id1" actions: - execute: alias: exec_1 device: PE1 command: cmd - execute: alias: exec_2 device: PE2 command: another - configure: device: PE1 command: feature bgp - execute: device: PE1 command: aa """ condition_6 = """ if : "%VARIABLES{nonexist}" actions: - execute: alias: exec_1 device: PE1 command: cmd - execute: alias: exec_2 device: PE2 command: another - configure: device: PE1 command: feature bgp - execute: device: PE1 command: aa """ condition_7 = """ if : "%VARIABLES{nonexist} == None" actions: - execute: alias: exec_1 device: PE1 command: cmd - execute: alias: exec_2 device: PE2 command: another - configure: device: PE1 command: feature bgp - execute: device: PE1 command: aa """ condition_8 = """ - if : "%VARIABLES{execute_id} == id1" actions: - execute: alias: exec_1 custom_start_step_message: inside if condition device: PE1 command: cmd - elif : "%VARIABLES{execute_id} == id2" actions: - configure: custom_start_step_message: inside first elif condition device: PE1 command: feature bgp - elif : "%VARIABLES{execute_id} == id3" actions: - configure: custom_start_step_message: inside second elif condition device: PE1 command: feature bgp - else : actions: - execute: alias: exec_2 custom_start_step_message: inside else condition device: PE2 command: another """ condition_9 = """ - if : "%VARIABLES{nonexist} == None" actions: - execute: alias: exec_1 device: PE1 command: cmd - execute: alias: exec_2 device: PE2 command: another - configure: device: PE1 command: feature bgp - execute: device: PE1 command: aa """ condition_10 = """ - if : "%VARIABLES{execute_id} == id1" actions: - execute: alias: exec_1 custom_start_step_message: inside if condition device: PE1 command: cmd - else : actions: - execute: alias: exec_2 custom_start_step_message: inside else condition device: PE2 command: another """ condition_11 = """ - elif : "%VARIABLES{execute_id} == id1" actions: - execute: alias: exec_1 custom_start_step_message: inside if condition device: PE1 command: cmd - else : actions: - execute: alias: exec_2 custom_start_step_message: inside else condition device: PE2 command: another """ condition_12 = """ - if : "%VARIABLES{execute_id} == id1" actions: - execute: alias: exec_1 custom_start_step_message: inside if condition device: PE1 command: cmd - if : actions: - execute: alias: exec_2 custom_start_step_message: inside else condition device: PE2 command: another """ condition_13 = """ - else : "%VARIABLES{execute_id} == id1" actions: - execute: alias: exec_1 custom_start_step_message: inside if condition device: PE1 command: cmd - else : actions: - execute: alias: exec_2 custom_start_step_message: inside else condition device: PE2 command: another """ def setUp(self): dir_name = os.path.dirname(os.path.abspath(__file__)) f, self.jobfile = tempfile.mkstemp() init_runtime(runtime) runtime.configuration.load() runtime.job = Job(jobfile=self.jobfile, runtime=runtime, **runtime.configuration.components.job) mgr = runtime.tasks task = mgr.Task(testscript=os.path.join( dir_name, 'mock_yamls/trigger_datafile.yaml'), taskid='awesome') self.testbed = load( os.path.join(dir_name, 'mock_testbeds/testbed.yaml')) self.mock_testbed_devices() Blitz.parameters = ParameterMap() Blitz.uid = 'test.dev' Blitz.parameters['testbed'] = self.testbed self.blitz_obj = Blitz() self.uid = self.blitz_obj.uid self.blitz_obj.parent = self self.blitz_obj.parent.parameters = mock.Mock() self.dev = Device(name='PE1', os='iosxe') self.dev.custom = {'abstraction': {'order': ['os']}} self.blitz_obj.parameters['test_sections'] = [{ 'section1': [{ 'execute': { 'command': 'cmd', 'device': 'PE1' } }] }] sections = self.blitz_obj._discover() self.kwargs = { 'self': self.blitz_obj, 'testbed': self.testbed, 'section': sections[0].__testcls__(sections[0]), 'name': '' } def mock_testbed_devices(self): side_effects = { 'configure': ['\n', 'end'], 'execute': ['host execute output', 'oop', 'oot', 'name'], 'parse': [self.parser_output, 'any output'] } for dev in self.testbed.devices: for action in side_effects: setattr(self.testbed.devices[dev], action, mock.Mock()) setattr(getattr(self.testbed.devices[dev], action), 'side_effect', side_effects[action]) # TODO maybe change the way condition is applied # need discussion def test_condition_pass(self): pass # steps = Steps() # data = yaml.safe_load(self.condition_1) # self.kwargs.update({'steps': steps, 'action_item': data}) # self.blitz_obj.parameters['save_variable_name'] = {} # self.blitz_obj.parameters['save_variable_name']['execute_id'] = 'id1' # out = control(**self.kwargs) def test_condition_fail(self): steps = Steps() data = yaml.safe_load(self.condition_2) self.kwargs.update({'steps': steps, 'action_item': data}) self.blitz_obj.parameters['save_variable_name'] = {'execute_id': 'id1'} run_condition(**self.kwargs) self.assertEqual(steps.result, Passed) func1 = self.testbed.devices['PE1'].configure func1.assert_called_once() func2 = self.testbed.devices['PE1'].execute self.assertEqual(func2.call_count, 2) func3 = self.testbed.devices['PE2'].execute func3.assert_called_once() def test_condition_parallel(self): steps = Steps() data = yaml.safe_load(self.condition_3) self.kwargs.update({'steps': steps, 'action_item': data}) self.blitz_obj.parameters['save_variable_name'] = {'execute_id': 'id1'} run_condition(**self.kwargs) self.assertEqual(steps.result, Passed) def test_condition_no_function_pass(self): steps = Steps() data = yaml.safe_load(self.condition_5) self.kwargs.update({'steps': steps, 'action_item': data}) self.blitz_obj.parameters['save_variable_name'] = {'execute_id': 'id1'} run_condition(**self.kwargs) self.assertEqual(steps.result, Passed) def test_condition_no_function_fail(self): steps = Steps() data = yaml.safe_load(self.condition_5) self.kwargs.update({'steps': steps, 'action_item': data}) self.blitz_obj.parameters['save_variable_name'] = {'execute_id': 'id9'} out = run_condition(**self.kwargs) self.assertEqual(out['substeps'], []) self.assertEqual(out['run_condition_skipped'], True) def test_condition_no_function_parallel(self): steps = Steps() data = yaml.safe_load(self.condition_4) self.kwargs.update({'steps': steps, 'action_item': data}) self.blitz_obj.parameters['save_variable_name'] = {'execute_id': 'id1'} out = run_condition(**self.kwargs) self.assertNotEqual(out['substeps'], []) self.assertEqual(out['run_condition_skipped'], False) def test_condition_no_operator(self): steps = Steps() data = yaml.safe_load(self.condition_6) self.kwargs.update({'steps': steps, 'action_item': data}) self.blitz_obj.parameters['save_variable_name'] = {} out = run_condition(**self.kwargs) self.assertEqual(out['substeps'], []) self.assertEqual(out['run_condition_skipped'], True) def test_condition_eq_none(self): steps = Steps() data = yaml.safe_load(self.condition_7) self.kwargs.update({'steps': steps, 'action_item': data}) self.blitz_obj.parameters['save_variable_name'] = {} out = run_condition(**self.kwargs) self.assertNotEqual(out['substeps'], []) self.assertEqual(out['run_condition_skipped'], False) def test_condition_if(self): steps = Steps() data = yaml.safe_load(self.condition_8) self.kwargs.update({'steps': steps, 'action_item': data}) self.blitz_obj.parameters['save_variable_name'] = {'execute_id': 'id1'} out = run_condition(**self.kwargs) self.assertEqual(steps.result, Passed) self.assertEqual(steps.details[0].name, 'inside if condition') def test_condition_elif_1(self): steps = Steps() data = yaml.safe_load(self.condition_8) self.kwargs.update({'steps': steps, 'action_item': data}) self.blitz_obj.parameters['save_variable_name'] = {'execute_id': 'id2'} out = run_condition(**self.kwargs) self.assertEqual(steps.result, Passed) self.assertEqual(steps.details[0].name, 'inside first elif condition') def test_condition_elif_2(self): steps = Steps() data = yaml.safe_load(self.condition_8) self.kwargs.update({'steps': steps, 'action_item': data}) self.blitz_obj.parameters['save_variable_name'] = {'execute_id': 'id3'} out = run_condition(**self.kwargs) self.assertEqual(steps.result, Passed) self.assertEqual(steps.details[0].name, 'inside second elif condition') def test_condition_else(self): steps = Steps() data = yaml.safe_load(self.condition_8) self.kwargs.update({'steps': steps, 'action_item': data}) self.blitz_obj.parameters['save_variable_name'] = {'execute_id': 'id5'} out = run_condition(**self.kwargs) self.assertEqual(steps.result, Passed) self.assertEqual(steps.details[0].name, 'inside else condition') def test_condition_eq_none_2(self): steps = Steps() data = yaml.safe_load(self.condition_9) self.kwargs.update({'steps': steps, 'action_item': data}) self.blitz_obj.parameters['save_variable_name'] = {} out = run_condition(**self.kwargs) self.assertNotEqual(out['substeps'], []) self.assertEqual(out['run_condition_skipped'], False) def test_condition_if_else(self): steps = Steps() data = yaml.safe_load(self.condition_10) self.kwargs.update({'steps': steps, 'action_item': data}) self.blitz_obj.parameters['save_variable_name'] = {'execute_id': 'id5'} out = run_condition(**self.kwargs) self.assertEqual(steps.result, Passed) self.assertEqual(steps.details[0].name, 'inside else condition') def test_condition_mandatory_if_exception(self): steps = Steps() data = yaml.safe_load(self.condition_11) self.kwargs.update({'steps': steps, 'action_item': data}) self.blitz_obj.parameters['save_variable_name'] = {'execute_id': 'id5'} # To check if the exception is raised when no if condition is passed with self.assertRaises(Exception) as err: out = run_condition(**self.kwargs) self.assertEqual(err.exception.args[0], "At least one if condition should be passed") def test_condition_multiple_if_exception(self): steps = Steps() data = yaml.safe_load(self.condition_12) self.kwargs.update({'steps': steps, 'action_item': data}) self.blitz_obj.parameters['save_variable_name'] = {'execute_id': 'id5'} # To check if the exception is raised when multiple if conditions are passed with self.assertRaises(Exception) as err: out = run_condition(**self.kwargs) self.assertEqual(err.exception.args[0], "Multple if conditions have been passed, "\ "please provide only one if condition") def test_condition_multiple_else_exception(self): steps = Steps() data = yaml.safe_load(self.condition_13) self.kwargs.update({'steps': steps, 'action_item': data}) self.blitz_obj.parameters['save_variable_name'] = {'execute_id': 'id5'} # To check if the exception is raised when multiple else conditions are passed with self.assertRaises(Exception) as err: out = run_condition(**self.kwargs) self.assertEqual(err.exception.args[0], "Multiple else conditions have been passed, "\ "please provide only one else condition")
class TestMaple(unittest.TestCase): plugin_input1 = '{"rule-1": {"type": "cli", "commands": "command:{\\n'\ ' \\"method\\":\\"waitfor\\",\\n '\ ' \\"options\\":[\\n '\ ' {\\"command\\":\\"show module\\"},\\n '\ ' {\\"match\\":\\"Up\\"},\\n '\ '{\\"timeout\\":\\"10\\"}\\n ]}"}}' plugin_input2 = '{"rule-1": {"type": "matcher", "commands": "matcher:{\\n'\ ' \\"package\\":\\"maple.plugins.user.MatcherPlugins\\"'\ ',\\n \\"method\\":\\"populateObjects\\",\\n '\ '\\"command\\":\\"show version\\",\\n \\"type\\":\\"cli\\"\\n }"}}' plugin_input3 = '{"rule-1": {"type": "matcher", "commands": "matcher:{\\n'\ ' \\"package\\":\\"maple.plugins.user.MatcherPlugins\\"'\ ',\\n \\"method\\":\\"populateObjects\\",\\n '\ '\\"type\\":\\"cli\\"\\n }"}}' plugin_input4 = '{"rule-1": {"type": "cli", "commands": "confirm:{\\n '\ ' \\"package\\":\\"maple.plugins.user.ConfirmPlugins\\",\\n'\ ' \\"method\\":\\"checkIfPresent\\",\\n \\"options\\":[\\n'\ ' {\\"count\\":\\"1\\"},\\n {\\"check1\\": \\"192.168.0.4\\"}\\n ]}"}}' plugin_input5 = '{"rule-1": {"type": "cli", "commands": "command:{\\n'\ ' \\"method\\":\\"ixia\\",\\n '\ ' \\"options\\":[\\n '\ ' {\\"command\\":\\"connect\\"}]}"}}' execute_output = ''' Mod Ports Module-Type Model Status --- ----- ------------------------------------------------------------------- 1 48 1/10G SFP+ Ethernet Module N9K-C9396PX active * 2 12 40G Ethernet Expansion Module N9K-M12PQ ok Mod Sw Hw Slot --- ----------------------- ------ ---- 1 9.3(3)IDI9(0.509) 2.2 NA 2 NA 1.2 GEM Mod MAC-Address(es) Serial-Num --- -------------------------------------- ---------- 1 84-b8-02-f0-83-90 to 84-b8-02-f0-83-c7 SAL1914CNL6 2 88-1d-fc-71-de-38 to 88-1d-fc-71-de-43 SAL1928K4EG Mod Online Diag Status --- ------------------ 1 Pass ''' execute_output_1 = """ Legend: (P)=Protected, (F)=FRR active, (*)=more labels in stack. IPV4: In-Label Out-Label FEC name Out-Interface Next-Hop 16005 16005 5.5.5.0/32 Eth1/10 2.3.1.3 16005 16005 5.5.5.0/32 Eth1/12 2.4.1.4 Legend: (P)=Protected, (F)=FRR active, (*)=more labels in stack. IPV4: In-Label Out-Label FEC name Out-Interface Next-Hop VRF default 16002 16002 2.2.2.0/32 Eth1/15 3.5.1.3 16002 16002 2.2.2.0/32 Eth1/10 4.5.1.4 Legend: (P)=Protected, (F)=FRR active, (*)=more labels in stack. IPV4: In-Label Out-Label FEC name Out-Interface Next-Hop VRF default 16002 16002 2.2.2.0/32 Eth1/49 3.6.1.3 16002 16002 2.2.2.0/32 Eth1/51 4.6.1.4 Legend: (P)=Protected, (F)=FRR active, (*)=more labels in stack. IPV4: In-Label Out-Label FEC name Out-Interface Next-Hop 16006 Pop Label 6.6.6.0/32 Eth1/56 6.8.1.6 Legend: (P)=Protected, (F)=FRR active, (*)=more labels in stack. IPV4: In-Label Out-Label FEC name Out-Interface Next-Hop 16006 Pop Label 6.6.6.0/32 Eth1/8 6.7.1.6 """ def setUp(self): dir_name = os.path.dirname(os.path.abspath(__file__)) self.testbed = load(os.path.join(dir_name, 'mock_testbeds/testbed.yaml')) Blitz.parameters = ParameterMap() Blitz.uid = 'test.dev' Blitz.parameters['testbed'] = self.testbed self.blitz_obj = Blitz() self.dev = Device( name='PE1', os='iosxe') self.dev.custom = {'abstraction': {'order': ['os']}} self.blitz_obj.parameters['test_sections'] = [{'section1': [{'action': {'command': 'a'}}]}] sections = self.blitz_obj._discover() self.kwargs = {'self': self.blitz_obj, 'section': sections[0], 'name': ''} def test_default_package_pass(self): steps = Steps() self.kwargs.update({'steps': steps, 'device': self.dev, 'maple_plugin_input': self.plugin_input1, 'maple_action': 'confirm'}) with patch('plugins.system.Commands.waitfor', return_value= {'result': [True],'matchObjs':{'a':'b', 'c':12}}) as func: maple(**self.kwargs) func.assert_called_once() self.assertIn('a', self.blitz_obj.parameters['save_variable_name']) self.assertEqual(steps.result, Passed) def test_default_package_fail(self): steps = Steps() self.kwargs.update({'steps': steps, 'device': self.dev, 'maple_plugin_input': self.plugin_input1, 'maple_action': 'confirm'}) with patch('plugins.system.Commands.waitfor', return_value= {'result': [False],'matchObjs':{'a':'b', 'c':12}}) as func: maple(**self.kwargs) func.assert_called_once() self.assertIn('a', self.blitz_obj.parameters['save_variable_name']) self.assertEqual(steps.result, Failed) def test_matcher_package_with_output(self): steps = Steps() self.dev.execute = Mock(return_value='a string out') self.kwargs.update({'steps': steps, 'device': self.dev, 'maple_plugin_input': self.plugin_input2}) with patch('plugins.user.MatcherPlugins.populateObjects', return_value= {'matchObjs':{'a':'b', 'c':12}}) as func: maple(**self.kwargs) func.assert_called_once() self.assertIn('c', self.blitz_obj.parameters['save_variable_name']) self.assertEqual(steps.result, Passed) def test_matcher_package_without_output(self): steps = Steps() self.dev.execute = Mock(side_effect=Exception) with steps.start("Starting action", continue_=True) as step: self.kwargs.update({'steps': step, 'device': self.dev, 'maple_plugin_input': self.plugin_input2}) maple(**self.kwargs) self.assertEqual(step.result, Failed) def test_matcher_package_bad_command(self): steps = Steps() with steps.start("Starting action", continue_=True) as step: self.kwargs.update({'steps': step, 'device': self.dev, 'maple_plugin_input': self.plugin_input3}) maple(**self.kwargs) self.assertEqual(step.result, Failed) def test_confirm_package(self): steps = Steps() self.kwargs.update({'steps': steps, 'device': self.dev, 'maple_plugin_input': self.plugin_input4, 'output': self.execute_output}) with patch('plugins.user.ConfirmPlugins.checkIfPresent', return_value= {'result': True, 'matchObjs':{'a':'b', 'c':12}}) as func: maple(**self.kwargs) func.assert_called_once() self.assertEqual(steps.result, Passed) def test_default_package_ixia(self): steps = Steps() self.dev.type = 'ixia' self.kwargs.update({'steps': steps, 'device': self.dev, 'maple_plugin_input': self.plugin_input5, 'maple_action': 'confirm'}) with patch('plugins.system.Commands.ixia', return_value= {'result': [True],'ixiaObjs':{'a':'b', 'c':12}}) as func: maple(**self.kwargs) func.assert_called_once() self.assertIn('a', self.blitz_obj.parameters['save_variable_name']) self.assertEqual(steps.result, Passed) def test_maple_search_include_pass(self): steps = Steps() self.kwargs.update({'steps': steps, 'search_string': self.execute_output_1, 'device': self.dev, 'include': ['^(?=.*\b16006\b)(?=.*\bPop Label\b).*$']}) maple_search(**self.kwargs) self.assertEqual(steps.result, Passed) def test_maple_search_include_fail(self): steps = Steps() self.kwargs.update({'steps': steps, 'search_string': self.execute_output_1, 'device': self.dev, 'include': ['\s*\bSel-Num\b.*']}) maple_search(**self.kwargs) self.assertEqual(steps.result, Failed) def test_maple_search_exclude_fail(self): steps = Steps() self.kwargs.update({'steps': steps, 'search_string': self.execute_output_1, 'device': self.dev, 'exclude': ['^(?=.*\b16006\b)(?=.*\bPop Label\b).*$']}) maple_search(**self.kwargs) self.assertEqual(steps.result, Failed) def test_maple_search_exclude_pass(self): steps = Steps() self.kwargs.update({'steps': steps, 'search_string': self.execute_output_1, 'device': self.dev, 'exclude': ['\s*\bSel-Num\b.*']}) maple_search(**self.kwargs) self.assertEqual(steps.result, Passed)
class TestBlitz(unittest.TestCase): actions_dict = {'execute': 'sample output', 'parse': {'a':'b'}, 'learn': {'a':'b'}, 'api': 1500} yaml1 = ''' test: groups: ['test'] description: Modifying the testcase description source: pkg: genie.libs.sdk class: triggers.blitz.blitz.Blitz devices: ['PE1'] test_sections: - section: - description: "section description" - execute: save: - filter: (?P<host>host).* regex: True device: PE1 command: show version ''' yaml2 = ''' test: groups: ['test'] description: Modifying the testcase description source: pkg: genie.libs.sdk class: triggers.blitz.blitz.Blitz devices: ['PE1'] test_sections: - section: - description: "section description" - parse: device: PE1 alias: parse1 description: Mocked action description save: - variable_name: name1 filter: contains('hardware') command: show version ''' yaml3 = ''' test: groups: ['test'] description: Modifying the testcase description source: pkg: genie.libs.sdk class: triggers.blitz.blitz.Blitz devices: ['PE1'] test_sections: - section1: - continue: False - execute: device: PE1 command: show version include: - [0-9] - execute: device: PE1 command: show vrf - section2: - description: "section description" - execute: device: PE1 command: show version ''' yaml4 = ''' test: groups: ['test'] description: Modifying the testcase description source: pkg: genie.libs.sdk class: triggers.blitz.blitz.Blitz devices: ['PE1'] test_sections: - section1: - execute: continue: False device: PE1 command: show version include: - [0-9] - execute: device: PE1 command: show vrf ''' yaml5 = ''' test: groups: ['test'] description: Modifying the testcase description source: pkg: genie.libs.sdk class: triggers.blitz.blitz.Blitz devices: ['PE1'] test_sections: - section: - execute: save: - variable_name: execute_output regex_findall: ([a-z]+) device: PE1 command: show version ''' yaml6 = ''' test: groups: ['test'] description: Modifying the testcase description source: pkg: genie.libs.sdk class: triggers.blitz.blitz.Blitz devices: ['PE1'] test_sections: - section: - description: "section description" - execute: device: PE1 command: show version save: - variable_name: execute_action_output as_dict: rt_2_if2: rt_22: "%VARIABLES{action_output}" ''' bad_yaml1 = ''' test: groups: ['test'] source: pkg: genie.libs.sdk class: triggers.blitz.blitz.Blitz devices: ['PE1'] test_sections: - section: - bad_action: device: PE1 command: show version ''' bad_yaml2 = ''' test: groups: ['test'] source: pkg: genie.libs.sdk class: triggers.blitz.blitz.Blitz devices: ['PE1'] test_sections: - section1: - invalid_action ''' bad_yaml3 = ''' test: groups: ['test'] source: pkg: genie.libs.sdk class: triggers.blitz.blitz.Blitz devices: ['PE1'] test_sections: - section2: - empty_kwargs: ''' bad_yaml4 = ''' test: groups: ['test'] source: pkg: genie.libs.sdk class: triggers.blitz.blitz.Blitz devices: ['PE1'] test_sections: - section3: - parse: device: PE3 command: show version ''' def setUp(self): dir_name = os.path.dirname(os.path.abspath(__file__)) f, self.jobfile = tempfile.mkstemp() init_runtime(runtime) runtime.configuration.load() runtime.job = Job(jobfile = self.jobfile, runtime = runtime, **runtime.configuration.components.job) mgr = runtime.tasks task = mgr.Task(testscript = os.path.join(dir_name, 'mock_yamls/trigger_datafile.yaml'), taskid = 'awesome') self._initiate_blitz_cls(self.yaml1) def test_init(self): self.assertEqual(self.blitz_cls().uid, 'test.PE1') self.assertEqual(self.blitz_cls().description, 'Modifying the testcase description') def test_dispatcher_1(self): blitz_discoverer = self.blitz_cls()._discover() for section in blitz_discoverer: new_section = section.__testcls__(section) steps = Steps() blitz_obj = self.blitz_cls() self.uid = blitz_obj.uid blitz_obj.parent = self blitz_obj.parent.parameters = mock.Mock() output = blitz_obj.dispatcher(steps, self.testbed, new_section, section.parameters['data']) self.assertEqual(output, { 'action': 'execute', 'alias': None, 'continue_': True, 'description': '', 'device': 'PE1', 'saved_vars': {'host': 'host'}, 'filters': '(?P<host>host).*', 'step_result': Passed}) self.assertEqual(new_section.description, "section description") def test_dispatcher_2(self): self._initiate_blitz_cls(self.yaml2) blitz_discoverer = self.blitz_cls()._discover() for section in blitz_discoverer: new_section = section.__testcls__(section) steps = Steps() blitz_obj = self.blitz_cls() self.uid = blitz_obj.uid blitz_obj.parent = self blitz_obj.parent.parameters = mock.Mock() output = blitz_obj.dispatcher(steps, self.testbed, new_section, section.parameters['data']) desc = section.parameters['data'][1]['parse']['description'] self.assertEqual(output['description'], desc) self.assertIn('parse1', blitz_obj.parameters['save_variable_name']) self.assertIn('name1', output['saved_vars']) # TODO might have an issue, in real script it does stop # probably because of dummy steps investigate def test_dispatcher_section_continue_false(self): pass # self._initiate_blitz_cls(self.yaml3) # blitz_discoverer = self.blitz_cls()._discover() # for section in blitz_discoverer: # new_section = section.__testcls__(section) # steps = Steps() # blitz_obj = self.blitz_cls() # new_section.result = Failed # with self.assertRaises(AEtestFailedSignal): # blitz_obj.dispatcher(steps, # self.testbed, # new_section, # section.parameters['data']) def test_bad_action(self): self._initiate_blitz_cls(self.bad_yaml1) blitz_discoverer = self.blitz_cls()._discover() for section in blitz_discoverer: new_section = section.__testcls__(section) steps = Steps() with self.assertRaises(Exception): self.blitz_cls().dispatcher(steps, self.testbed, new_section, section.parameters['data']) def test_invalid_action(self): self._initiate_blitz_cls(self.bad_yaml2) blitz_discoverer = self.blitz_cls()._discover() for section in blitz_discoverer: new_section = section.__testcls__(section) steps = Steps() with self.assertRaises(Exception): self.blitz_cls().dispatcher(steps, self.testbed, new_section, section.parameters['data']) def test_save_findall(self): self._initiate_blitz_cls(self.yaml5) blitz_discoverer = self.blitz_cls()._discover() for section in blitz_discoverer: new_section = section.__testcls__(section) steps = Steps() blitz_obj = self.blitz_cls() self.uid = blitz_obj.uid blitz_obj.parent = self blitz_obj.parent.parameters = mock.Mock() output = blitz_obj.dispatcher(steps, self.testbed, new_section, section.parameters['data']) self.assertEqual(output, { 'action': 'execute', 'device': 'PE1', 'alias': None, 'continue_': True, 'description': '', 'saved_vars': { 'execute_output': [ 'host', 'execute', 'output' ] }, 'step_result': Passed }) def test_save_regex_var(self): self._initiate_blitz_cls(self.yaml1) blitz_discoverer = self.blitz_cls()._discover() for section in blitz_discoverer: new_section = section.__testcls__(section) steps = Steps() blitz_obj = self.blitz_cls() self.uid = blitz_obj.uid blitz_obj.parent = self blitz_obj.parent.parameters = mock.Mock() output = blitz_obj.dispatcher(steps, self.testbed, new_section, section.parameters['data']) self.assertEqual(output['saved_vars'], {'host': 'host'}) self.assertEqual(output['filters'], '(?P<host>host).*') def test_invalid_device(self): self._initiate_blitz_cls(self.bad_yaml4) blitz_discoverer = self.blitz_cls()._discover() for section in blitz_discoverer: new_section = section.__testcls__(section) steps = Steps() with self.assertRaises(Exception): self.blitz_cls().dispatcher(steps, self.testbed, new_section, section.parameters['data']) def _initiate_blitz_cls(self, yaml_file): dir_name = os.path.dirname(os.path.abspath(__file__)) self.blitz_cls = Blitz self.testbed = load(os.path.join(dir_name, 'mock_testbeds/testbed.yaml')) self.blitz_cls.parameters = ParameterMap() self.blitz_cls.parameters['testbed'] = self.testbed self._mock_testbed_devs() self.datafile = yaml.safe_load(yaml_file) for key, value in self.datafile.items(): self.blitz_cls.uid = "{}.{}".format(key, value['devices'][0]) self.blitz_cls.parameters['test_sections'] = value['test_sections'] if value.get('description'): self.blitz_cls.description = value['description'] def _mock_testbed_devs(self): side_effects = {'configure': ['\n'], 'execute': ['host execute output', 'oop', 'oot', 'name'], 'parse': [{'a': '1', 'hardware': 'hardware_name'}]} actions = ['configure', 'execute', 'parse'] for dev in self.testbed.devices: for action in actions: setattr(self.testbed.devices[dev], action, mock.Mock()) setattr(getattr(self.testbed.devices[dev], action), 'side_effect', side_effects[action]) def test_custom_start_step_messsage_with_variable(self): #saved variable Blitz.parameters['save_variable_name'] = {'command': 'sh version'} self.blitz_obj = Blitz() self.blitz_obj.parameters['test_sections'] = [{'section1': [{'action': {'command': 'a'}}]}] sections = self.blitz_obj._discover() self.section = sections[0].__testcls__(sections[0]) self.kwargs = { 'self': self.blitz_obj, 'section': self.section, 'custom_start_step_message': 'test command: %VARIABLES{command}' } #To get the saved variable replaced_kwargs = get_variable(**self.kwargs) self.assertEqual(replaced_kwargs['custom_start_step_message'], 'test command: sh version') def test_save_as_dict(self): self._initiate_blitz_cls(self.yaml6) blitz_discoverer = self.blitz_cls()._discover() for section in blitz_discoverer: new_section = section.__testcls__(section) steps = Steps() blitz_obj = self.blitz_cls() self.uid = blitz_obj.uid blitz_obj.parent = self blitz_obj.parent.parameters = mock.Mock() output = blitz_obj.dispatcher(steps, self.testbed, new_section, section.parameters['data']) self.assertEqual(output['saved_vars']['execute_action_output'], {'rt_2_if2': {'rt_22': 'host execute output'}})
class TestLoop(unittest.TestCase): parser_output = { 'platform': { 'name': 'Nexus', 'os': 'NX-OS', 'software': { 'bios_version': '07.33', 'system_version': '9.3(3) [build 9.3(3)IDI9(0.509)]', 'bios_compile_time': '08/04/2015', 'system_image_file': 'bootflash:///system-image-N93_3-00613722415136', 'system_compile_time': '10/22/2019 10:00:00 [10/22/2019 16:57:31]' }, 'hardware': { 'model': 'Nexus9000 C9396PX', 'chassis': 'Nexus9000 C9396PX', 'slots': 'None', 'rp': 'None', 'cpu': 'Intel(R) Core(TM) i3- CPU @ 2.50GHz', 'memory': '16399900 kB', 'processor_board_id': 'SAL1914CNL6', 'device_name': 'N93_3', 'bootflash': '51496280 kB' }, 'kernel_uptime': { 'days': 61, 'hours': 22, 'minutes': 8, 'seconds': 40 }, 'reason': 'Reset Requested by CLI command reload', 'system_version': '9.3(3)' } } execute_output = """ 2020-11-24 12:25:43,769: %UNICON-INFO: +++ N93_3: executing command 'show version' +++ show version Cisco Nexus Operating System (NX-OS) Software TAC support: http://www.cisco.com/tac Copyright (C) 2002-2019, Cisco and/or its affiliates. All rights reserved. The copyrights to certain works contained in this software are owned by other third parties and used and distributed under their own licenses, such as open source. This software is provided "as is," and unless otherwise stated, there is no warranty, express or implied, including but not limited to warranties of merchantability and fitness for a particular purpose. Certain components of this software are licensed under the GNU General Public License (GPL) version 2.0 or GNU General Public License (GPL) version 3.0 or the GNU Lesser General Public License (LGPL) Version 2.1 or Lesser General Public License (LGPL) Version 2.0. A copy of each such license is available at http://www.opensource.org/licenses/gpl-2.0.php and http://opensource.org/licenses/gpl-3.0.html and http://www.opensource.org/licenses/lgpl-2.1.php and http://www.gnu.org/licenses/old-licenses/library.txt. Software BIOS: version 07.33 NXOS: version 9.3(3) [build 9.3(3)IDI9(0.509)] BIOS compile time: 08/04/2015 NXOS image file is: bootflash:///system-image-N93_3-00613722415136 NXOS compile time: 10/22/2019 10:00:00 [10/22/2019 16:57:31] Hardware cisco Nexus9000 C9396PX Chassis Intel(R) Core(TM) i3- CPU @ 2.50GHz with 16399900 kB of memory. Processor Board ID SAL1914CNL6 Device name: N93_3 bootflash: 51496280 kB Kernel uptime is 61 day(s), 22 hour(s), 33 minute(s), 56 second(s) Last reset at 930930 usecs after Wed Sep 23 13:59:45 2020 Reason: Reset Requested by CLI command reload System version: 9.3(3) Service: plugin Core Plugin, Ethernet Plugin Active Package(s): """ loop_with_val = """ loop_variable_name: var_name value: ['show version', 'show vrf'] actions: - execute: alias: execute_id command: "%VARIABLES{var_name}" device: PE1 exclude: - extreme include: - host - parse: command: "%VARIABLES{var_name}" device: PE1 """ loop_over_device = """ loop_variable_name: dev_name value: ['PE1', 'PE2'] actions: - configure: command: feature bgp device: "%VARIABLES{dev_name}" """ loop_with_until = """ until: "'%VARIABLES{nbc}' == '07.33'" maxtime: 5 actions: - parse: command: "show version" save: - variable_name: nbc filter: get_values('bios_version', 0) device: PE1 """ loop_with_do_until_1 = """ do_until: "'%VARIABLES{nbc}' == '07.33'" max_time: 5 actions: - parse: command: "show version" save: - variable_name: nbc filter: get_values('bios_version', 0) device: PE1 """ loop_with_do_until_2 = """ do_until: "'%VARIABLES{nbc}' == '06.33'" max_time: 2 actions: - parse: command: "show version" save: - variable_name: nbc filter: get_values('bios_version', 0) device: PE1 """ loop_with_dict_val = """ loop_variable_name: var_name value: {'PE1':'show version', 'PE2': 'show version'} actions: - execute: alias: execute_id command: "%VARIABLES{var_name._values}" device: "%VARIABLES{var_name._keys}" exclude: - extreme include: - host """ loop_until = """ loop_variable_name: var_name value: ['cmd', 'amd', 'show vrf'] loop_until: passed actions: - execute: command: "%VARIABLES{var_name}" device: PE1 """ loop_parallel = """ loop_variable_name: dev_name value: ['PE1', 'PE2'] parallel: True actions: - execute: command: show version device: "%VARIABLES{dev_name}" """ loop_parallel_error = """ loop_variable_name: dev_name value: ['PE', 'PE2'] parallel: True actions: - execute: command: show version """ loop_nested = """ range: 2 loop_variable_name: nest_loop actions: - parse: device: PE2 command: show version - loop: loop_variable_name: var_name value: ['show vrf', 'show version'] actions: - execute: device: PE1 command: "%VARIABLES{var_name}" """ loop_range = """ range: 1,5 loop_variable_name: range actions: - execute: device: PE1 command: show version - print: item: value: "%VARIABLES{range}" """ def setUp(self): dir_name = os.path.dirname(os.path.abspath(__file__)) f, self.jobfile = tempfile.mkstemp() init_runtime(runtime) runtime.configuration.load() runtime.job = Job(jobfile=self.jobfile, runtime=runtime, **runtime.configuration.components.job) mgr = runtime.tasks task = mgr.Task(testscript=os.path.join( dir_name, 'mock_yamls/trigger_datafile.yaml'), taskid='awesome') self.testbed = load( os.path.join(dir_name, 'mock_testbeds/testbed.yaml')) self.mock_testbed_devices() Blitz.parameters = ParameterMap() Blitz.uid = 'test.dev' Blitz.parameters['testbed'] = self.testbed self.blitz_obj = Blitz() self.uid = self.blitz_obj.uid self.blitz_obj.parent = self self.blitz_obj.parent.parameters = mock.Mock() self.dev = Device(name='PE1', os='iosxe') self.dev.custom = {'abstraction': {'order': ['os']}} self.blitz_obj.parameters['test_sections'] = [{ 'section1': [{ 'execute': { 'command': 'cmd', 'device': 'PE1' } }] }] sections = self.blitz_obj._discover() self.kwargs = { 'self': self.blitz_obj, 'testbed': self.testbed, 'section': sections[0].__testcls__(sections[0]), 'name': '' } def mock_testbed_devices(self): side_effects = { 'configure': ['\n', 'end'], 'execute': ['host execute output', 'oop', 'oot', 'name'], 'parse': [self.parser_output, 'any output'] } for dev in self.testbed.devices: for action in side_effects.keys(): setattr(self.testbed.devices[dev], action, mock.Mock()) setattr(getattr(self.testbed.devices[dev], action), 'side_effect', side_effects[action]) def test_loop_init(self): steps = Steps() data = yaml.safe_load(self.loop_with_val) self.kwargs.update({'steps': steps, 'action_item': data}) out = loop(**self.kwargs) expected = { "action": "loop", "step_result": Failed, "substeps": [{ "device": "PE1", "continue_": True, "action": "execute", "description": "", "step_result": Passed, "alias": "execute_id", "saved_vars": { "execute_id": "passed" } }, { "device": "PE1", "continue_": True, "action": "parse", "description": "", "step_result": Passed, "alias": None, "saved_vars": {} }, { "device": "PE1", "continue_": True, "action": "execute", "description": "", "step_result": Failed, "alias": "execute_id", "saved_vars": { "execute_id": "failed" } }, { "device": "PE1", "continue_": True, "action": "parse", "description": "", "step_result": Passed, "alias": None, "saved_vars": {} }], "advanced_action": True, "loop_until": None } self.assertEqual(out, expected) self.assertEqual(steps.result, Failed) self.assertEqual(steps.details[2].result, Passed) def test_loop_over_device(self): steps = Steps() data = yaml.safe_load(self.loop_over_device) self.kwargs.update({'steps': steps, 'action_item': data}) out = loop(**self.kwargs) expected = { "action": "loop", "step_result": Passed, "substeps": [{ "device": "PE1", "continue_": True, "action": "configure", "description": "", "step_result": Passed, "alias": None, "saved_vars": {} }, { "device": "PE2", "continue_": True, "action": "configure", "description": "", "step_result": Passed, "alias": None, "saved_vars": {} }], "advanced_action": True, "loop_until": None } self.assertEqual(out, expected) self.assertEqual(steps.result, out['step_result']) def test_until_condition_false(self): steps = Steps() data = yaml.safe_load(self.loop_with_until) self.blitz_obj.parameters.setdefault('save_variable_name', {}) self.blitz_obj.parameters['save_variable_name']['nbc'] = '06.33' self.kwargs.update({'steps': steps, 'action_item': data}) out = loop(**self.kwargs) expected = [{ 'device': 'PE1', 'continue_': True, 'action': 'parse', 'description': '', 'step_result': Passed, 'alias': None, 'saved_vars': { 'nbc': '07.33' }, 'filters': "get_values('bios_version', 0)" }] func = self.testbed.devices['PE1'].parse func.assert_called_once() self.assertEqual(out['substeps'], expected) def test_until_condition_true(self): steps = Steps() data = yaml.safe_load(self.loop_with_until) self.blitz_obj.parameters.setdefault('save_variable_name', {}) self.blitz_obj.parameters['save_variable_name']['nbc'] = '07.33' self.kwargs.update({ 'self': self.blitz_obj, 'steps': steps, 'action_item': data }) out = loop(**self.kwargs) func = self.testbed.devices['PE1'].parse func.assert_not_called() self.assertEqual(out['substeps'], []) def test_do_until_condition_true(self): steps = Steps() data = yaml.safe_load(self.loop_with_do_until_1) self.blitz_obj.parameters.setdefault('save_variable_name', {}) self.blitz_obj.parameters['save_variable_name']['nbc'] = '07.33' self.kwargs.update({ 'self': self.blitz_obj, 'steps': steps, 'action_item': data }) out = loop(**self.kwargs) expected = { "action": "loop", "step_result": Passed, "substeps": [{ "device": "PE1", "continue_": True, "action": "parse", "description": "", "step_result": Passed, "alias": None, "saved_vars": { "nbc": "07.33" }, "filters": "get_values('bios_version', 0)" }], "advanced_action": True, "loop_until": None } func = self.testbed.devices['PE1'].parse func.assert_called_once() self.assertEqual(out, expected) # def test_do_until_condition_false(self): # steps = Steps() # data = yaml.safe_load(self.loop_with_do_until_2) # self.blitz_obj.parameters.setdefault('save_variable_name', {}) # self.blitz_obj.parameters['save_variable_name']['nbc'] = '07.33' # self.kwargs.update({'self': self.blitz_obj, # 'steps': steps, # 'action_item': data}) # out = loop(**self.kwargs) # # TODO - The saved_vars on the second action should be like below, # # But it saves nbc: any_output Investigate # expected = { # "substeps":[ # { # "device":"PE1", # "continue_":True, # "action":"parse", # "description":"", # "step_result":Passed, # "alias":None, # "saved_vars":{ # "nbc":"07.33" # }, # "filters":"get_values('bios_version', 0)" # }, # { # "device":"PE1", # "continue_":True, # "action":"parse", # "description":"", # "step_result":Passed, # "alias":None, # "saved_vars":{}, # "filters":"get_values('bios_version', 0)" # } # ] # } # self.assertEqual(out, expected) def test_loop_with_dict_val(self): steps = Steps() data = yaml.safe_load(self.loop_with_dict_val) self.kwargs.update({'steps': steps, 'action_item': data}) out = loop(**self.kwargs) self.assertEqual(len(out['substeps']), 2) self.assertEqual(out['substeps'][0]['device'], 'PE1') self.assertEqual(out['substeps'][1]['device'], 'PE2') def test_loop_everyseconds(self): steps = Steps() data = yaml.safe_load(self.loop_with_dict_val) self.kwargs.update({'steps': steps, 'action_item': data}) out = loop(**self.kwargs) self.assertEqual(len(out['substeps']), 2) self.assertEqual(out['substeps'][0]['device'], 'PE1') self.assertEqual(out['substeps'][1]['device'], 'PE2') def test_loop_with_loop_until(self): self.testbed.devices['PE1'].side_effect = [Exception, Exception, 'oop'] steps = Steps() data = yaml.safe_load(self.loop_until) self.kwargs.update({'steps': steps, 'action_item': data}) out = loop(**self.kwargs) self.assertEqual(out['substeps'], []) self.assertEqual(steps.result, Passed) def test_loop_with_parallel(self): steps = Steps() data = yaml.safe_load(self.loop_parallel) self.kwargs.update({'steps': steps, 'action_item': data}) out = loop(**self.kwargs) self.assertEqual(steps.result, Passed) def test_loop_with_parallel_errored(self): steps = Steps() data = yaml.safe_load(self.loop_parallel_error) self.kwargs.update({'steps': steps, 'action_item': data}) out = loop(**self.kwargs) self.assertEqual(steps.result, Errored) def test_nested_loop(self): steps = Steps() data = yaml.safe_load(self.loop_nested) self.kwargs.update({'steps': steps, 'action_item': data}) out = loop(**self.kwargs) self.assertEqual(steps.result, Passed) def test_loop_range(self): steps = Steps() data = yaml.safe_load(self.loop_range) self.kwargs.update({'steps': steps, 'action_item': data}) out = loop(**self.kwargs) self.assertEqual(steps.result, Passed)