diff options
author | Peter Sprygada <privateip@users.noreply.github.com> | 2017-02-15 12:46:30 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-15 12:46:30 -0500 |
commit | 48b02336abcd74ad2a24e4bbf7905d3ccd608a0c (patch) | |
tree | 8580aade3c7b3c35823eca8343cb3f16a2528c5d | |
parent | 2d14cdc5ac40e30359aca303a3e0299dfc3e9752 (diff) | |
download | ansible-48b02336abcd74ad2a24e4bbf7905d3ccd608a0c.tar.gz |
code clean of old code from network modules updates (#21469)
* removes unused code
* removes module_utils/local.py
* removes plugins/action/network.py
* removes action_handler from connection plugins
* removes code to use action_handler in task_executor
* updates action plugins to subclass from normal
-rw-r--r-- | lib/ansible/executor/task_executor.py | 3 | ||||
-rw-r--r-- | lib/ansible/module_utils/local.py | 80 | ||||
-rw-r--r-- | lib/ansible/modules/network/basics/net_command.py | 133 | ||||
-rw-r--r-- | lib/ansible/plugins/action/net_config.py | 23 | ||||
-rw-r--r-- | lib/ansible/plugins/action/net_template.py | 2 | ||||
-rw-r--r-- | lib/ansible/plugins/action/network.py | 66 | ||||
-rw-r--r-- | lib/ansible/plugins/connection/__init__.py | 1 | ||||
-rw-r--r-- | lib/ansible/plugins/connection/network_cli.py | 1 | ||||
-rw-r--r-- | test/units/modules/network/basics/test_net_command.py | 108 |
9 files changed, 4 insertions, 413 deletions
diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py index 6c74f5d87b..99d611417b 100644 --- a/lib/ansible/executor/task_executor.py +++ b/lib/ansible/executor/task_executor.py @@ -768,8 +768,7 @@ class TaskExecutor: elif all((module_prefix in network_group_modules, module_prefix in self._shared_loader_obj.action_loader)): handler_name = module_prefix else: - pc_conn = self._shared_loader_obj.connection_loader.get(self._play_context.connection, class_only=True) - handler_name = getattr(pc_conn, 'action_handler', 'normal') + handler_name = 'normal' handler = self._shared_loader_obj.action_loader.get( handler_name, diff --git a/lib/ansible/module_utils/local.py b/lib/ansible/module_utils/local.py deleted file mode 100644 index b9aa39b17b..0000000000 --- a/lib/ansible/module_utils/local.py +++ /dev/null @@ -1,80 +0,0 @@ -# -# This code is part of Ansible, but is an independent component. -# This particular file snippet, and this file snippet only, is BSD licensed. -# Modules you write using this snippet, which is embedded dynamically by Ansible -# still belong to the author of the module, and may assign their own license -# to the complete work. -# -# (c) 2016 Red Hat Inc. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -import json - -import ansible.module_utils.basic - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.basic import remove_values -from ansible.module_utils._text import to_bytes - -from ansible.errors import AnsibleModuleExit - -_ANSIBLE_CONNECTION = None - -def _modify_module(task_args, connection): - params = {'ANSIBLE_MODULE_ARGS': task_args} - params = json.dumps(params) - ansible.module_utils.basic._ANSIBLE_ARGS = to_bytes(params) - - global _ANSIBLE_CONNECTION - _ANSIBLE_CONNECTION = connection - -class LocalAnsibleModule(AnsibleModule): - - @property - def connection(self): - return _ANSIBLE_CONNECTION - - def exec_command(self, args, check_rc=False): - ''' - Execute a command, returns rc, stdout, and stderr. - ''' - rc, out, err = self.connection.exec_command(args) - if check_rc and rc != 0: - self.fail_json(msg='command %s failed' % args, rc=rc, stderr=err, stdout=out) - return rc, out, err - - def exit_json(self, **kwargs): - ''' return from the module, without error ''' - if not 'changed' in kwargs: - kwargs['changed'] = False - if 'invocation' not in kwargs: - kwargs['invocation'] = {'module_args': self.params} - kwargs = remove_values(kwargs, self.no_log_values) - raise AnsibleModuleExit(kwargs) - - def fail_json(self, **kwargs): - ''' return from the module, with an error message ''' - assert 'msg' in kwargs, "implementation error -- msg to explain the error is required" - kwargs['failed'] = True - if 'invocation' not in kwargs: - kwargs['invocation'] = {'module_args': self.params} - kwargs = remove_values(kwargs, self.no_log_values) - raise AnsibleModuleExit(kwargs) diff --git a/lib/ansible/modules/network/basics/net_command.py b/lib/ansible/modules/network/basics/net_command.py deleted file mode 100644 index 34d20b4b42..0000000000 --- a/lib/ansible/modules/network/basics/net_command.py +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/python -# -# 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 <http://www.gnu.org/licenses/>. -# - -ANSIBLE_METADATA = { - 'status': ['preview'], - 'supported_by': 'core', - 'version': '1.0' -} - -DOCUMENTATION = """ ---- -module: net_command -version_added: "2.3" -author: "Peter Sprygada (@privateip)" -short_description: Executes a command on a remote network device -description: - - This module will take the command and execute it on the remote - device in a CLI shell. The command will output will be returned - via the stdout return key. If an error is detected, the command - will return the error via the stderr key. -options: - free_form: - description: - - A free form command to run on the remote host. There is no - parameter actually named 'free_form'. See the examples. - required: true -notes: - - This module requires setting the Ansible C(connection) type to C(network_cli). - - This module will always set the changed return key to C(True) -""" - -EXAMPLES = """ -# Note: These examples assume 'connection' has been set to 'network_cli'. - -- name: execute show version - net_command: show version - -- name: run a series of commands - net_command: "{{ item }}" - with_items: - - show interfaces - - show ip route - - show version -""" - -RETURN = """ -rc: - description: The command return code (0 means success) - returned: always - type: int - sample: 0 -stdout: - description: The command standard output - returned: always - type: string - sample: "Hostname: ios01\nFQDN: ios01.example.net" -stderr: - description: The command standard error - returned: always - type: string - sample: "shw hostname\r\n% Invalid input\r\nios01>" -stdout_lines: - description: The command standard output split in lines - returned: always - type: list - sample: ["Hostname: ios01", "FQDN: ios01.example.net"] -start: - description: The time the job started - returned: always - type: str - sample: "2016-11-16 10:38:15.126146" -end: - description: The time the job ended - returned: always - type: str - sample: "2016-11-16 10:38:25.595612" -delta: - description: The time elapsed to perform all operations - returned: always - type: str - sample: "0:00:10.469466" -""" -from ansible.module_utils.local import LocalAnsibleModule - -def main(): - """ main entry point for module execution - """ - argument_spec = dict( - _raw_params=dict() - ) - - module = LocalAnsibleModule(argument_spec=argument_spec, - supports_check_mode=False) - - if str(module.params['_raw_params']).strip() == '': - module.fail_json(rc=256, msg='no command given') - - result = {'changed': True} - - rc, out, err = module.exec_command(module.params['_raw_params']) - - try: - out = module.from_json(out) - except ValueError: - if out: - out = str(out).strip() - result['stdout_lines'] = out.split('\n') - - result.update({ - 'rc': rc, - 'stdout': out, - 'stderr': str(err).strip() - }) - - module.exit_json(**result) - -if __name__ == '__main__': - main() diff --git a/lib/ansible/plugins/action/net_config.py b/lib/ansible/plugins/action/net_config.py index 93b8f700a0..a643728629 100644 --- a/lib/ansible/plugins/action/net_config.py +++ b/lib/ansible/plugins/action/net_config.py @@ -24,7 +24,7 @@ import re import time import glob -from ansible.plugins.action.network import ActionModule as _ActionModule +from ansible.plugins.action.normal import ActionModule as _ActionModule from ansible.module_utils._text import to_text from ansible.module_utils.six.moves.urllib.parse import urlsplit from ansible.utils.vars import merge_hash @@ -43,10 +43,7 @@ class ActionModule(_ActionModule): except ValueError as exc: return dict(failed=True, msg=exc.message) - if self._play_context.connection == 'local': - result = self.normal(tmp, task_vars) - else: - result = super(ActionModule, self).run(tmp, task_vars) + result = super(ActionModule, self).run(tmp, task_vars) if self._task.args.get('backup') and result.get('__backup__'): # User requested backup and no error occurred in module. @@ -64,22 +61,6 @@ class ActionModule(_ActionModule): return result - def normal(self, tmp=None, task_vars=None): - if task_vars is None: - task_vars = dict() - - #results = super(ActionModule, self).run(tmp, task_vars) - # remove as modules might hide due to nolog - #del results['invocation']['module_args'] - - results = {} - results = merge_hash(results, self._execute_module(tmp=tmp, task_vars=task_vars)) - - # hack to keep --verbose from showing all the setup module results - if self._task.action == 'setup': - results['_ansible_verbose_override'] = True - - return results def _get_working_path(self): cwd = self._loader.get_basedir() if self._task._role is not None: diff --git a/lib/ansible/plugins/action/net_template.py b/lib/ansible/plugins/action/net_template.py index 88047dec56..6d50135d31 100644 --- a/lib/ansible/plugins/action/net_template.py +++ b/lib/ansible/plugins/action/net_template.py @@ -25,7 +25,7 @@ import glob import urlparse from ansible.module_utils._text import to_text -from ansible.plugins.action.network import ActionModule as _ActionModule +from ansible.plugins.action.normal import ActionModule as _ActionModule class ActionModule(_ActionModule): diff --git a/lib/ansible/plugins/action/network.py b/lib/ansible/plugins/action/network.py deleted file mode 100644 index c0bf8e0b55..0000000000 --- a/lib/ansible/plugins/action/network.py +++ /dev/null @@ -1,66 +0,0 @@ -# -# (c) 2016 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 <http://www.gnu.org/licenses/>. -# -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import datetime - -from ansible.plugins.action import ActionBase, display -from ansible.module_utils.local import _modify_module -from ansible.errors import AnsibleModuleExit - -class ActionModule(ActionBase): - - def run(self, tmp=None, task_vars=None): - result = super(ActionModule, self).run(tmp, task_vars) - if result.get('invocation', {}).get('module_args'): - del result['invocation']['module_args'] - - self._update_module_args(self._task.action, self._task.args, task_vars) - - try: - _modify_module(self._task.args, self._connection) - path = self._shared_loader_obj.module_loader.find_plugin(self._task.action) - pkg = '.'.join(['ansible', 'modules', self._task.action]) - module = self._shared_loader_obj.module_loader._load_module_source(pkg, path) - start_time = datetime.datetime.now() - module.main() - - except AnsibleModuleExit as exc: - result.update(exc.result) - for field in ('_ansible_notify',): - if field in result: - result.pop(field) - - except Exception as exc: - if display.verbosity > 2: - raise - result.update(dict(failed=True, msg=str(exc))) - - end_time = datetime.datetime.now() - delta = end_time - start_time - - result.update({ - 'start': str(start_time), - 'end': str(end_time), - 'delta': str(delta) - }) - - return result - diff --git a/lib/ansible/plugins/connection/__init__.py b/lib/ansible/plugins/connection/__init__.py index 439bb70cde..77b8dcd8fc 100644 --- a/lib/ansible/plugins/connection/__init__.py +++ b/lib/ansible/plugins/connection/__init__.py @@ -67,7 +67,6 @@ class ConnectionBase(with_metaclass(ABCMeta, object)): # language means any language. module_implementation_preferences = ('',) allow_executable = True - action_handler = 'normal' def __init__(self, play_context, new_stdin, *args, **kwargs): # All these hasattrs allow subclasses to override these parameters diff --git a/lib/ansible/plugins/connection/network_cli.py b/lib/ansible/plugins/connection/network_cli.py index d74c77eb0c..1a283cb87a 100644 --- a/lib/ansible/plugins/connection/network_cli.py +++ b/lib/ansible/plugins/connection/network_cli.py @@ -42,7 +42,6 @@ class Connection(_Connection): transport = 'network_cli' has_pipelining = False - action_handler = 'network' def __init__(self, play_context, new_stdin, *args, **kwargs): super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs) diff --git a/test/units/modules/network/basics/test_net_command.py b/test/units/modules/network/basics/test_net_command.py deleted file mode 100644 index 8286480cb2..0000000000 --- a/test/units/modules/network/basics/test_net_command.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python -# -# (c) 2016 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 <http://www.gnu.org/licenses/>. - -# Make coding more python3-ish -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import json - -from ansible.compat.tests import unittest -from ansible.compat.tests.mock import patch, MagicMock -from ansible.errors import AnsibleModuleExit -from ansible.modules.network.basics import net_command -from ansible.module_utils import basic -from ansible.module_utils.local import LocalAnsibleModule -from ansible.module_utils._text import to_bytes - - -def set_module_args(args): - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) - -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 TestNetCommandModule(unittest.TestCase): - - def execute_module(self, command_response=None, failed=False, changed=True): - - if not command_response: - command_response = (256, '', 'no command response provided in test case') - - with patch.object(LocalAnsibleModule, 'exec_command') as mock_exec_command: - mock_exec_command.return_value = command_response - - with self.assertRaises(AnsibleModuleExit) as exc: - net_command.main() - - result = exc.exception.result - - if failed: - self.assertTrue(result.get('failed'), result) - else: - self.assertEqual(result.get('changed'), changed, result) - - return result - - def test_net_command_string(self): - """ - Test for all keys in the response - """ - set_module_args({'_raw_params': 'show version'}) - result = self.execute_module((0, 'ok', '')) - for key in ['rc', 'stdout', 'stderr', 'stdout_lines']: - self.assertIn(key, result) - - def test_net_command_json(self): - """ - The stdout_lines key should not be present when the return - string is a json data structure - """ - set_module_args({'_raw_params': 'show version'}) - result = self.execute_module((0, '{"key": "value"}', '')) - for key in ['rc', 'stdout', 'stderr']: - self.assertIn(key, result) - self.assertNotIn('stdout_lines', result) - - def test_net_command_missing_command(self): - """ - Test failure on missing command - """ - set_module_args({'_raw_params': ''}) - self.execute_module(failed=True) |