From 0e756a1cf9057a441eea1f8d4bfbe79fb966a9b4 Mon Sep 17 00:00:00 2001 From: Ganesh Nalawade Date: Wed, 3 May 2017 22:36:23 +0530 Subject: [PATCH] Add junos unit test case (#24249) * Add junos modules unit test case * Fix CI issues --- .../fixtures/show_chassis_hardware_xml.txt | 26 +++++ .../fixtures/show_interfaces_details_xml.txt | 25 +++++ .../junos/fixtures/show_system_memory_xml.txt | 20 ++++ .../fixtures/show_system_storage_xml.txt | 20 ++++ .../modules/network/junos/junos_module.py | 2 +- .../modules/network/junos/test_junos_facts.py | 102 ++++++++++++++++++ .../network/junos/test_junos_netconf.py | 83 ++++++++++++++ .../network/junos/test_junos_package.py | 82 ++++++++++++++ .../modules/network/junos/test_junos_rpc.py | 88 +++++++++++++++ 9 files changed, 447 insertions(+), 1 deletion(-) create mode 100644 test/units/modules/network/junos/fixtures/show_chassis_hardware_xml.txt create mode 100644 test/units/modules/network/junos/fixtures/show_interfaces_details_xml.txt create mode 100644 test/units/modules/network/junos/fixtures/show_system_memory_xml.txt create mode 100644 test/units/modules/network/junos/fixtures/show_system_storage_xml.txt create mode 100644 test/units/modules/network/junos/test_junos_facts.py create mode 100644 test/units/modules/network/junos/test_junos_netconf.py create mode 100644 test/units/modules/network/junos/test_junos_package.py create mode 100644 test/units/modules/network/junos/test_junos_rpc.py diff --git a/test/units/modules/network/junos/fixtures/show_chassis_hardware_xml.txt b/test/units/modules/network/junos/fixtures/show_chassis_hardware_xml.txt new file mode 100644 index 00000000000..a0853b8cfa0 --- /dev/null +++ b/test/units/modules/network/junos/fixtures/show_chassis_hardware_xml.txt @@ -0,0 +1,26 @@ + + + + Chassis + adc382ed18b0 + VSRX + + Midplane + + + System IO + + + Routing Engine + VSRX RE + + + FPC 0 + Virtual FPC + + + Power Supply 0 + + + + diff --git a/test/units/modules/network/junos/fixtures/show_interfaces_details_xml.txt b/test/units/modules/network/junos/fixtures/show_interfaces_details_xml.txt new file mode 100644 index 00000000000..5ba581bfd94 --- /dev/null +++ b/test/units/modules/network/junos/fixtures/show_interfaces_details_xml.txt @@ -0,0 +1,25 @@ + + + + em0 + up + up + 8 + 17 + 1 + Ethernet + Ethernet + 1514 + 1000mbps + Unspecified + Unspecified + 0 + 0 + 52:54:00:8a:af:30 + 52:54:00:8a:af:30 + Unspecified + Never + Never + + + \ No newline at end of file diff --git a/test/units/modules/network/junos/fixtures/show_system_memory_xml.txt b/test/units/modules/network/junos/fixtures/show_system_memory_xml.txt new file mode 100644 index 00000000000..541b6614c6e --- /dev/null +++ b/test/units/modules/network/junos/fixtures/show_system_memory_xml.txt @@ -0,0 +1,20 @@ + + + + 983500 + 100% + 17844 + 1% + 67284 + 6% + 148268 + 15% + 288908 + 29% + 260500 + 26% + 200684 + 20% + + + \ No newline at end of file diff --git a/test/units/modules/network/junos/fixtures/show_system_storage_xml.txt b/test/units/modules/network/junos/fixtures/show_system_storage_xml.txt new file mode 100644 index 00000000000..ecd29ba1e64 --- /dev/null +++ b/test/units/modules/network/junos/fixtures/show_system_storage_xml.txt @@ -0,0 +1,20 @@ + + + + /dev/vtbd0s1a + 1025132 + 583460 + 359664 + 62 + / + + + devfs + 2 + 2 + 0 + 100 + /dev + + + \ No newline at end of file diff --git a/test/units/modules/network/junos/junos_module.py b/test/units/modules/network/junos/junos_module.py index 26fd98f3281..65c72ccb359 100644 --- a/test/units/modules/network/junos/junos_module.py +++ b/test/units/modules/network/junos/junos_module.py @@ -110,5 +110,5 @@ class TestJunosModule(unittest.TestCase): self.assertEqual(result['changed'], changed, result) return result - def load_fixtures(self, commands=None): + def load_fixtures(self, commands=None, format=None, changed=None): pass diff --git a/test/units/modules/network/junos/test_junos_facts.py b/test/units/modules/network/junos/test_junos_facts.py new file mode 100644 index 00000000000..e0cac9bc977 --- /dev/null +++ b/test/units/modules/network/junos/test_junos_facts.py @@ -0,0 +1,102 @@ +# (c) 2017 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import json + +from ansible.compat.tests.mock import patch, MagicMock +from ansible.modules.network.junos import junos_facts +from .junos_module import TestJunosModule, load_fixture, set_module_args + +RPC_CLI_MAP = { + 'get-software-information': 'show version', + 'get-interface-information': 'show interfaces details', + 'get-system-memory-information': 'show system memory', + 'get-chassis-inventory': 'show chassis hardware', + 'get-system-storage': 'show system storage' +} + + +class TestJunosCommandModule(TestJunosModule): + + module = junos_facts + + def setUp(self): + self.mock_get_config = patch('ansible.modules.network.junos.junos_facts.get_configuration') + self.get_config = self.mock_get_config.start() + + self.mock_send_request = patch('ansible.modules.network.junos.junos_facts.send_request') + self.send_request = self.mock_send_request.start() + + def tearDown(self): + self.mock_send_request.stop() + + def load_fixtures(self, commands=None, format='text', changed=False): + def load_from_file(*args, **kwargs): + module, element = args + + if element.text: + path = str(element.text) + else: + path = RPC_CLI_MAP[str(element.tag)] + + filename = path.replace(' ', '_') + filename = '%s_%s.txt' % (filename, format) + return load_fixture(filename) + + self.send_request.side_effect = load_from_file + + def test_junos_get_facts(self): + set_module_args(dict()) + result = self.execute_module(format='xml') + facts = result['ansible_facts'] + + self.assertEqual(facts['ansible_net_hostname'], 'vsrx01') + self.assertTrue('em0' in facts['ansible_net_interfaces']) + self.assertEqual(facts['ansible_net_interfaces']['em0']['type'], 'Ethernet') + self.assertEqual(facts['ansible_net_memtotal_mb'], 983500) + self.assertEqual(facts['ansible_net_filesystems'][0], '/dev/vtbd0s1a') + self.assertTrue('ansible_net_config' not in facts) + + def test_junos_get_facts_subset_config_set(self): + self.get_config.return_value = load_fixture('get_configuration_rpc_reply.txt') + set_module_args(dict(gather_subset='config', config_format='set')) + result = self.execute_module(format='xml') + facts = result['ansible_facts'] + + self.assertTrue('ansible_net_config' in facts) + self.assertTrue(facts['ansible_net_config'].startswith('set')) + self.assertEqual(facts['ansible_net_hostname'], 'vsrx01') + self.assertTrue('ansible_net_interfaces' not in facts) + + def test_junos_get_facts_subset_list(self): + set_module_args(dict(gather_subset=['hardware', 'interfaces'])) + result = self.execute_module(format='xml') + facts = result['ansible_facts'] + + self.assertTrue('ansible_net_config' not in facts) + self.assertEqual(facts['ansible_net_interfaces']['em0']['oper-status'], 'up') + self.assertEqual(facts['ansible_net_memfree_mb'], 200684) + + def test_junos_get_facts_wrong_subset(self): + set_module_args(dict(gather_subset=['hardware', 'interfaces', 'test'])) + result = self.execute_module(format='xml', failed=True) + + self.assertTrue(result['msg'].startswith('Subset must be one')) diff --git a/test/units/modules/network/junos/test_junos_netconf.py b/test/units/modules/network/junos/test_junos_netconf.py new file mode 100644 index 00000000000..7b192d72b73 --- /dev/null +++ b/test/units/modules/network/junos/test_junos_netconf.py @@ -0,0 +1,83 @@ +# (c) 2017 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import json + +from ansible.compat.tests.mock import patch, MagicMock +from ansible.modules.network.junos import junos_netconf +from .junos_module import TestJunosModule, load_fixture, set_module_args + + +class TestJunosCommandModule(TestJunosModule): + + module = junos_netconf + + def setUp(self): + self.mock_exec_command = patch('ansible.modules.network.junos.junos_netconf.exec_command') + self.exec_command = self.mock_exec_command.start() + + def tearDown(self): + self.mock_exec_command.stop() + + def test_junos_netconf_enable(self): + self.exec_command.return_value = 0, '', None + set_module_args(dict(state='present')) + result = self.execute_module() + self.assertEqual(result['commands'], ['set system services netconf ssh port 830']) + + def test_junos_netconf_disable(self): + out = ''' + ssh { + port 830; + } + ''' + self.exec_command.return_value = 0, out, None + set_module_args(dict(state='absent')) + result = self.execute_module(changed=True) + self.assertEqual(result['commands'], ['delete system services netconf']) + + def test_junos_netconf_port_change(self): + out = ''' + ssh { + port 830; + } + ''' + self.exec_command.return_value = 0, out, None + set_module_args(dict(state='present', netconf_port=22)) + result = self.execute_module(changed=True) + self.assertEqual(result['commands'], ['set system services netconf ssh port 22']) + + def test_junos_netconf_port_error(self): + out = ''' + ssh { + port 22; + } + ''' + self.exec_command.return_value = 0, out, None + set_module_args(dict(state='present', netconf_port=0)) + result = self.execute_module(changed=True, failed=True) + self.assertEqual(result['msg'], 'netconf_port must be between 1 and 65535') + + def test_junos_netconf_config_error(self): + self.exec_command.return_value = 1, None, None + set_module_args(dict(state='present')) + result = self.execute_module(failed=True) + self.assertEqual(result['msg'], 'unable to retrieve current config') diff --git a/test/units/modules/network/junos/test_junos_package.py b/test/units/modules/network/junos/test_junos_package.py new file mode 100644 index 00000000000..c513fdb1f64 --- /dev/null +++ b/test/units/modules/network/junos/test_junos_package.py @@ -0,0 +1,82 @@ +# (c) 2017 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import json + +from ansible.compat.tests.mock import patch, MagicMock +from .junos_module import TestJunosModule, load_fixture, set_module_args +jnpr_mock = MagicMock() + +modules = { + 'jnpr': jnpr_mock, + 'jnpr.junos': jnpr_mock.junos, + 'jnpr.junos.utils': jnpr_mock.junos.utils, + 'jnpr.junos.utils.sw': jnpr_mock.junos.utils.sw, + 'jnpr.junos.exception': jnpr_mock.junos.execption +} +module_patcher = patch.dict('sys.modules', modules) +module_patcher.start() + +from ansible.modules.network.junos import junos_package + + +class TestJunosCommandModule(TestJunosModule): + + module = junos_package + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_junos_package_src(self): + set_module_args(dict(src='junos-vsrx-12.1X46-D10.2-domestic.tgz')) + result = self.execute_module(changed=True) + args, kwargs = jnpr_mock.junos.utils.sw.SW().install.call_args + self.assertEqual(args[0], 'junos-vsrx-12.1X46-D10.2-domestic.tgz') + self.assertEqual(result['changed'], True) + + def test_junos_package_src_fail(self): + jnpr_mock.junos.utils.sw.SW().install.return_value = 0 + set_module_args(dict(src='junos-vsrx-12.1X46-D10.2-domestic.tgz')) + result = self.execute_module(changed=True, failed=True) + self.assertEqual(result['msg'], 'Unable to install package on device') + + def test_junos_package_src_no_copy(self): + jnpr_mock.junos.utils.sw.SW().install.return_value = 1 + set_module_args(dict(src='junos-vsrx-12.1X46-D10.2-domestic.tgz', no_copy=True)) + result = self.execute_module(changed=True) + args, kwargs = jnpr_mock.junos.utils.sw.SW().install.call_args + self.assertEqual(kwargs['no_copy'], True) + + def test_junos_package_device_param(self): + set_module_args(dict(src='junos-vsrx-12.1X46-D10.2-domestic.tgz', + provider={'username': 'unit', 'host': 'test', 'ssh_keyfile': 'path', + 'password': 'test', 'port': 234})) + self.execute_module(changed=True) + args, kwargs = jnpr_mock.junos.Device.call_args + + self.assertEqual(args[0], 'test') + self.assertEqual(kwargs['passwd'], 'test') + self.assertEqual(kwargs['ssh_private_key_file'], 'path') + self.assertEqual(kwargs['port'], 234) + self.assertEqual(kwargs['user'], 'unit') diff --git a/test/units/modules/network/junos/test_junos_rpc.py b/test/units/modules/network/junos/test_junos_rpc.py new file mode 100644 index 00000000000..6650bab2244 --- /dev/null +++ b/test/units/modules/network/junos/test_junos_rpc.py @@ -0,0 +1,88 @@ +# (c) 2017 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import json +from xml.etree.ElementTree import tostring + +from ansible.compat.tests.mock import patch, MagicMock +from ansible.modules.network.junos import junos_rpc +from .junos_module import TestJunosModule, load_fixture, set_module_args +from ansible.module_utils._text import to_text + +RPC_CLI_MAP = { + 'get-software-information': 'show version', + 'get-interface-information': 'show interfaces details', + 'get-system-memory-information': 'show system memory', + 'get-chassis-inventory': 'show chassis hardware', + 'get-system-storage': 'show system storage' +} + + +class TestJunosCommandModule(TestJunosModule): + + module = junos_rpc + + def setUp(self): + self.mock_send_request = patch('ansible.modules.network.junos.junos_rpc.send_request') + self.send_request = self.mock_send_request.start() + + def tearDown(self): + self.mock_send_request.stop() + + def load_fixtures(self, commands=None, format='text', changed=False): + def load_from_file(*args, **kwargs): + module, element = args + if element.text: + path = str(element.text) + else: + tag = str(element.tag) + if tag.startswith('{'): + tag = tag.split('}', 1)[1] + path = RPC_CLI_MAP[tag] + + filename = path.replace(' ', '_') + filename = '%s_%s.txt' % (filename, format) + + return load_fixture(filename) + + self.send_request.side_effect = load_from_file + + def test_junos_rpc_xml(self): + set_module_args(dict(rpc='get-chassis-inventory')) + result = self.execute_module(format='xml') + self.assertTrue(result['xml'].find('\n')) + + def test_junos_rpc_text(self): + set_module_args(dict(rpc='get-software-information', output='text')) + result = self.execute_module(format='text') + self.assertTrue(result['output_lines'][0].startswith('Hostname: vsrx01')) + + def test_junos_rpc_json(self): + set_module_args(dict(rpc='get-software-information', output='json')) + result = self.execute_module(format='json') + self.assertTrue('software-information' in result['output']) + + def test_junos_rpc_args(self): + set_module_args(dict(rpc='get-software-information', args={'interface': 'em0', 'media': True})) + result = self.execute_module(format='xml') + args, kwargs = self.send_request.call_args + reply = tostring(args[1]).decode() + self.assertTrue(reply.find('em0'))