From b47cde9d4c9962b4d8f4ab48505b008dad8b70e7 Mon Sep 17 00:00:00 2001 From: rajaspachipulusu17 Date: Wed, 12 Dec 2018 19:03:01 +0530 Subject: [PATCH] Pluribus Networks pn access list ip module with unit test cases (#49604) * Pluribus Networks pn access list ip module with unit test cases * Changes according to ansibot standards in unit test modules * Remove unwanted variables * Removed unwanted super call --- .../network/netvisor/pn_access_list_ip.py | 163 ++++++++++++++++++ .../modules/network/netvisor/__init__.py | 0 .../modules/network/netvisor/nvos_module.py | 109 ++++++++++++ .../netvisor/test_pn_access_list_ip.py | 61 +++++++ 4 files changed, 333 insertions(+) create mode 100644 lib/ansible/modules/network/netvisor/pn_access_list_ip.py create mode 100644 test/units/modules/network/netvisor/__init__.py create mode 100644 test/units/modules/network/netvisor/nvos_module.py create mode 100644 test/units/modules/network/netvisor/test_pn_access_list_ip.py diff --git a/lib/ansible/modules/network/netvisor/pn_access_list_ip.py b/lib/ansible/modules/network/netvisor/pn_access_list_ip.py new file mode 100644 index 00000000000..95ad4cb27fd --- /dev/null +++ b/lib/ansible/modules/network/netvisor/pn_access_list_ip.py @@ -0,0 +1,163 @@ +#!/usr/bin/python +# Copyright: (c) 2018, Pluribus Networks +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + + +DOCUMENTATION = """ +--- +module: pn_access_list_ip +author: "Pluribus Networks (@rajaspachipulusu17)" +version_added: "2.8" +short_description: CLI command to add/remove access-list-ip +description: + - This modules can be used to add and remove IPs associated with access list. +options: + pn_cliswitch: + description: + - Target switch to run the CLI on. + required: False + type: str + state: + description: + - State the action to perform. Use 'present' to add access-list-ip and + 'absent' to remove access-list-ip. + required: True + choices: ["present", "absent"] + pn_ip: + description: + - IP associated with the access list. + required: False + default: '::' + type: str + pn_name: + description: + - Access List Name. + required: False + type: str +""" + +EXAMPLES = """ +- name: access list ip functionality + pn_access_list_ip: + pn_cliswitch: "sw01" + pn_name: "foo" + pn_ip: "172.16.3.1" + state: "present" + +- name: access list ip functionality + pn_access_list_ip: + pn_cliswitch: "sw01" + pn_name: "foo" + pn_ip: "172.16.3.1" + state: "absent" +""" + +RETURN = """ +command: + description: the CLI command run on the target node. + returned: always + type: string +stdout: + description: set of responses from the access-list-ip command. + returned: always + type: list +stderr: + description: set of error responses from the access-list-ip command. + returned: on error + type: list +changed: + description: indicates whether the CLI caused changes on the target. + returned: always + type: bool +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli + + +def check_cli(module, cli): + """ + This method checks for idempotency using the access-list-ip-show command. + If ip exists, return True else False. + :param module: The Ansible module to fetch input parameters + :param cli: The CLI string + """ + name = module.params['pn_name'] + ip = module.params['pn_ip'] + cli += ' access-list-ip-show name %s format ip no-show-headers' % name + + out = module.run_command(cli.split(), use_unsafe_shell=True)[1] + + out = out.split() + + return True if ip in out else False + + +def main(): + """ This section is for arguments parsing """ + + global state_map + state_map = dict( + present='access-list-ip-add', + absent='access-list-ip-remove', + ) + + module = AnsibleModule( + argument_spec=dict( + pn_cliswitch=dict(required=False, type='str'), + state=dict(required=True, type='str', + choices=state_map.keys()), + pn_ip=dict(required=False, type='str', default='::'), + pn_name=dict(required=False, type='str'), + ), + required_if=( + ["state", "present", ["pn_name"]], + ["state", "absent", ["pn_name", "pn_ip"]], + ), + ) + + # Accessing the arguments + cliswitch = module.params['pn_cliswitch'] + state = module.params['state'] + ip = module.params['pn_ip'] + name = module.params['pn_name'] + + command = state_map[state] + + # Building the CLI command string + cli = pn_cli(module, cliswitch) + + IP_EXISTS = check_cli(module, cli) + cli += ' %s name %s ' % (command, name) + + if command == 'access-list-ip-remove': + if IP_EXISTS is False: + module.exit_json( + skipped=True, + msg='access-list with ip %s does not exist' % ip + ) + if ip: + cli += ' ip ' + ip + else: + if command == 'access-list-ip-add': + if IP_EXISTS is True: + module.exit_json( + skipped=True, + msg='access list with ip %s already exists' % ip + ) + if ip: + cli += ' ip ' + ip + + run_cli(module, cli, state_map) + + +if __name__ == '__main__': + main() diff --git a/test/units/modules/network/netvisor/__init__.py b/test/units/modules/network/netvisor/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/units/modules/network/netvisor/nvos_module.py b/test/units/modules/network/netvisor/nvos_module.py new file mode 100644 index 00000000000..cef888a2552 --- /dev/null +++ b/test/units/modules/network/netvisor/nvos_module.py @@ -0,0 +1,109 @@ +# Copyright: (c) 2018, Pluribus Networks +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os +import json +import tempfile + +from units.compat import unittest +from units.compat.mock import patch +from ansible.module_utils import basic +from ansible.module_utils._text import to_bytes + + +fixture_path = os.path.join(os.path.dirname(__file__), 'fixtures') +fixture_data = {} + + +def load_fixture(name): + path = os.path.join(fixture_path, name) + + if path in fixture_data: + return fixture_data[path] + + with open(path) as f: + data = f.read() + + try: + data = json.loads(data) + except: + pass + + fixture_data[path] = data + return data + + +class AnsibleExitJson(Exception): + pass + + +class AnsibleFailJson(Exception): + pass + + +class TestNvosModule(unittest.TestCase): + def setUp(self): + super(TestNvosModule, self).setUp() + + self.test_log = tempfile.mkstemp(prefix='ansible-test-nvos-module-', suffix='.log')[1] + + def tearDown(self): + super(TestNvosModule, self).tearDown() + + os.remove(self.test_log) + + def execute_module(self, failed=False, changed=False, commands=None, + sort=True, defaults=False, state=None): + + self.load_fixtures(commands, state) + + if failed: + result = self.failed() + self.assertTrue(result['failed'], result) + else: + result = self.changed(changed) + self.assertEqual(result['changed'], changed, result) + + if commands is not None: + if sort: + self.assertEqual(sorted(commands), sorted(result['commands']), + result['commands']) + else: + self.assertEqual(commands, result['commands'], + result['commands']) + + return result + + def failed(self): + def fail_json(*args, **kwargs): + kwargs['failed'] = True + raise AnsibleFailJson(kwargs) + + with patch.object(basic.AnsibleModule, 'fail_json', fail_json): + with self.assertRaises(AnsibleFailJson) as exc: + self.module.main() + + result = exc.exception.args[0] + self.assertTrue(result['failed'], result) + return result + + def changed(self, changed=False): + def exit_json(*args, **kwargs): + if 'changed' not in kwargs: + kwargs['changed'] = False + raise AnsibleExitJson(kwargs) + + with patch.object(basic.AnsibleModule, 'exit_json', exit_json): + with self.assertRaises(AnsibleExitJson) as exc: + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], changed, result) + return result + + def load_fixtures(self, commands=None): + pass diff --git a/test/units/modules/network/netvisor/test_pn_access_list_ip.py b/test/units/modules/network/netvisor/test_pn_access_list_ip.py new file mode 100644 index 00000000000..09fecd99369 --- /dev/null +++ b/test/units/modules/network/netvisor/test_pn_access_list_ip.py @@ -0,0 +1,61 @@ +# Copyright: (c) 2018, Pluribus Networks +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import json + +from units.compat.mock import patch +from ansible.modules.network.netvisor import pn_access_list_ip +from units.modules.utils import set_module_args +from .nvos_module import TestNvosModule, load_fixture + + +class TestAccessListIpModule(TestNvosModule): + + module = pn_access_list_ip + + def setUp(self): + self.mock_run_nvos_commands = patch('ansible.modules.network.netvisor.pn_access_list_ip.run_cli') + self.run_nvos_commands = self.mock_run_nvos_commands.start() + + self.mock_run_check_cli = patch('ansible.modules.network.netvisor.pn_access_list_ip.check_cli') + self.run_check_cli = self.mock_run_check_cli.start() + + def tearDown(self): + self.mock_run_nvos_commands.stop() + + def run_cli_patch(self, module, cli, state_map): + if state_map['present'] == 'access-list-ip-add': + results = dict( + changed=True, + cli_cmd=cli + ) + elif state_map['absent'] == 'access-list-ip-remove': + results = dict( + changed=True, + cli_cmd=cli + ) + module.exit_json(**results) + + def load_fixtures(self, commands=None, state=None, transport='cli'): + self.run_nvos_commands.side_effect = self.run_cli_patch + if state == 'present': + self.run_check_cli.return_value = False + if state == 'absent': + self.run_check_cli.return_value = True + + def test_access_list_ip_add(self): + set_module_args({'pn_cliswitch': 'sw01', 'pn_name': 'foo', + 'pn_ip': '172.16.3.1', 'state': 'present'}) + result = self.execute_module(changed=True, state='present') + expected_cmd = '/usr/bin/cli --quiet -e --no-login-prompt switch sw01 access-list-ip-add name foo ip 172.16.3.1' + self.assertEqual(result['cli_cmd'], expected_cmd) + + def test_access_list_ip_remove(self): + set_module_args({'pn_cliswitch': 'sw01', 'pn_name': 'foo', + 'pn_ip': '172.16.3.1', 'state': 'absent'}) + result = self.execute_module(changed=True, state='absent') + expected_cmd = '/usr/bin/cli --quiet -e --no-login-prompt switch sw01 access-list-ip-remove name foo ip 172.16.3.1' + self.assertEqual(result['cli_cmd'], expected_cmd)