From 71113ee291aa51f5363486537b3407204acb5a99 Mon Sep 17 00:00:00 2001 From: Ganesh Nalawade Date: Fri, 4 Jan 2019 16:06:13 +0530 Subject: [PATCH] Fix backup issue in network config modules and network action plugins common code refactor (#50301) * Fix backup issue in network config modules * Fix `get_working_path` not found issue introduced due to backup config code refactor (PR #50208) * Further refactor config related action plugins to minimize duplicate code * Remove unwated imports in config action plugins * Add common network class for action plugin and related code refactor * Fix review comment --- .../module_utils/network/common/backup.py | 50 ---------- lib/ansible/plugins/action/aireos.py | 6 +- lib/ansible/plugins/action/aireos_config.py | 93 ------------------ lib/ansible/plugins/action/aruba.py | 6 +- lib/ansible/plugins/action/aruba_config.py | 93 ------------------ lib/ansible/plugins/action/asa.py | 6 +- lib/ansible/plugins/action/asa_config.py | 93 ------------------ lib/ansible/plugins/action/bigip.py | 6 +- lib/ansible/plugins/action/ce.py | 5 +- lib/ansible/plugins/action/ce_config.py | 93 ------------------ lib/ansible/plugins/action/cli_config.py | 30 ++---- lib/ansible/plugins/action/cnos.py | 6 +- lib/ansible/plugins/action/cnos_config.py | 89 ----------------- lib/ansible/plugins/action/dellos10.py | 5 +- lib/ansible/plugins/action/dellos10_config.py | 95 ------------------- lib/ansible/plugins/action/dellos6.py | 5 +- lib/ansible/plugins/action/dellos6_config.py | 92 ------------------ lib/ansible/plugins/action/dellos9.py | 5 +- lib/ansible/plugins/action/dellos9_config.py | 95 ------------------- lib/ansible/plugins/action/edgeos_config.py | 74 ++------------- lib/ansible/plugins/action/enos.py | 5 +- lib/ansible/plugins/action/enos_config.py | 90 ------------------ lib/ansible/plugins/action/eos.py | 5 +- lib/ansible/plugins/action/eos_config.py | 94 ------------------ lib/ansible/plugins/action/exos_config.py | 71 +------------- lib/ansible/plugins/action/fortios_config.py | 64 +------------ lib/ansible/plugins/action/ios.py | 6 +- lib/ansible/plugins/action/ios_config.py | 93 ------------------ lib/ansible/plugins/action/iosxr.py | 5 +- lib/ansible/plugins/action/iosxr_config.py | 93 ------------------ lib/ansible/plugins/action/ironware.py | 5 +- lib/ansible/plugins/action/ironware_config.py | 93 ------------------ lib/ansible/plugins/action/junos.py | 5 +- lib/ansible/plugins/action/junos_config.py | 93 ------------------ lib/ansible/plugins/action/net_get.py | 27 +----- lib/ansible/plugins/action/net_put.py | 67 +------------ lib/ansible/plugins/action/netconf.py | 6 +- lib/ansible/plugins/action/netconf_config.py | 91 ------------------ .../{bigip_imish_config.py => network.py} | 84 +++++++++++----- lib/ansible/plugins/action/nos_config.py | 70 +------------- lib/ansible/plugins/action/nxos.py | 5 +- lib/ansible/plugins/action/nxos_config.py | 93 ------------------ lib/ansible/plugins/action/onyx_config.py | 69 +------------- lib/ansible/plugins/action/slxos_config.py | 66 +------------ lib/ansible/plugins/action/sros.py | 5 +- lib/ansible/plugins/action/sros_config.py | 93 ------------------ lib/ansible/plugins/action/voss_config.py | 70 +------------- lib/ansible/plugins/action/vyos.py | 5 +- lib/ansible/plugins/action/vyos_config.py | 94 ------------------ test/sanity/code-smell/action-plugin-docs.py | 1 + 50 files changed, 168 insertions(+), 2347 deletions(-) delete mode 100644 lib/ansible/module_utils/network/common/backup.py delete mode 100644 lib/ansible/plugins/action/aireos_config.py delete mode 100644 lib/ansible/plugins/action/aruba_config.py delete mode 100644 lib/ansible/plugins/action/asa_config.py delete mode 100644 lib/ansible/plugins/action/ce_config.py delete mode 100644 lib/ansible/plugins/action/cnos_config.py delete mode 100644 lib/ansible/plugins/action/dellos10_config.py delete mode 100644 lib/ansible/plugins/action/dellos6_config.py delete mode 100644 lib/ansible/plugins/action/dellos9_config.py delete mode 100644 lib/ansible/plugins/action/enos_config.py delete mode 100644 lib/ansible/plugins/action/eos_config.py delete mode 100644 lib/ansible/plugins/action/ios_config.py delete mode 100644 lib/ansible/plugins/action/iosxr_config.py delete mode 100644 lib/ansible/plugins/action/ironware_config.py delete mode 100644 lib/ansible/plugins/action/junos_config.py delete mode 100644 lib/ansible/plugins/action/netconf_config.py rename lib/ansible/plugins/action/{bigip_imish_config.py => network.py} (52%) delete mode 100644 lib/ansible/plugins/action/nxos_config.py delete mode 100644 lib/ansible/plugins/action/sros_config.py delete mode 100644 lib/ansible/plugins/action/vyos_config.py diff --git a/lib/ansible/module_utils/network/common/backup.py b/lib/ansible/module_utils/network/common/backup.py deleted file mode 100644 index 6698daa50c..0000000000 --- a/lib/ansible/module_utils/network/common/backup.py +++ /dev/null @@ -1,50 +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 os -import time -import glob - -from ansible.module_utils._text import to_text - - -def write_backup(module, host, contents, encoding='utf-8'): - cwd = module._loader.get_basedir() - if module._task._role is not None: - cwd = module._task._role._role_path - - backup_path = os.path.join(cwd, 'backup') - if not os.path.exists(backup_path): - os.mkdir(backup_path) - for existing_backup in glob.glob('%s/%s_config.*' % (backup_path, host)): - os.remove(existing_backup) - tstamp = time.strftime("%Y-%m-%d@%H:%M:%S", time.localtime(time.time())) - filename = '%s/%s_config.%s' % (backup_path, host, tstamp) - open(filename, 'w').write(to_text(contents, encoding=encoding)) - - return filename diff --git a/lib/ansible/plugins/action/aireos.py b/lib/ansible/plugins/action/aireos.py index 18bcad695c..36fc0a7134 100644 --- a/lib/ansible/plugins/action/aireos.py +++ b/lib/ansible/plugins/action/aireos.py @@ -25,7 +25,7 @@ import copy from ansible import constants as C from ansible.module_utils._text import to_text from ansible.module_utils.connection import Connection -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.module_utils.network.aireos.aireos import aireos_provider_spec from ansible.module_utils.network.common.utils import load_provider from ansible.utils.display import Display @@ -33,11 +33,13 @@ from ansible.utils.display import Display display = Display() -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'aireos_config' else False + if self._play_context.connection != 'local': return dict( failed=True, diff --git a/lib/ansible/plugins/action/aireos_config.py b/lib/ansible/plugins/action/aireos_config.py deleted file mode 100644 index 860a44f2d4..0000000000 --- a/lib/ansible/plugins/action/aireos_config.py +++ /dev/null @@ -1,93 +0,0 @@ -# -# (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 . -# -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.aireos import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/lib/ansible/plugins/action/aruba.py b/lib/ansible/plugins/action/aruba.py index daf4e64efc..9c246529aa 100644 --- a/lib/ansible/plugins/action/aruba.py +++ b/lib/ansible/plugins/action/aruba.py @@ -25,7 +25,7 @@ import copy from ansible import constants as C from ansible.module_utils._text import to_text from ansible.module_utils.connection import Connection -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.module_utils.network.aruba.aruba import aruba_provider_spec from ansible.module_utils.network.common.utils import load_provider from ansible.utils.display import Display @@ -33,11 +33,13 @@ from ansible.utils.display import Display display = Display() -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'aruba_config' else False + if self._play_context.connection != 'local': return dict( failed=True, diff --git a/lib/ansible/plugins/action/aruba_config.py b/lib/ansible/plugins/action/aruba_config.py deleted file mode 100644 index 137f43c8f8..0000000000 --- a/lib/ansible/plugins/action/aruba_config.py +++ /dev/null @@ -1,93 +0,0 @@ -# -# (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 . -# -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.aruba import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/lib/ansible/plugins/action/asa.py b/lib/ansible/plugins/action/asa.py index 1406b6dc88..2f9a939920 100644 --- a/lib/ansible/plugins/action/asa.py +++ b/lib/ansible/plugins/action/asa.py @@ -24,7 +24,7 @@ import copy import json from ansible import constants as C -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.module_utils.network.asa.asa import asa_provider_spec from ansible.module_utils.network.common.utils import load_provider from ansible.utils.display import Display @@ -32,11 +32,13 @@ from ansible.utils.display import Display display = Display() -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'asa_config' else False + if self._play_context.connection == 'local': provider = load_provider(asa_provider_spec, self._task.args) pc = copy.deepcopy(self._play_context) diff --git a/lib/ansible/plugins/action/asa_config.py b/lib/ansible/plugins/action/asa_config.py deleted file mode 100644 index a2c972d3ac..0000000000 --- a/lib/ansible/plugins/action/asa_config.py +++ /dev/null @@ -1,93 +0,0 @@ -# -# (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 . -# -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.asa import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/lib/ansible/plugins/action/bigip.py b/lib/ansible/plugins/action/bigip.py index 4ccc37865e..c511ccad6e 100644 --- a/lib/ansible/plugins/action/bigip.py +++ b/lib/ansible/plugins/action/bigip.py @@ -27,7 +27,7 @@ from ansible import constants as C from ansible.module_utils._text import to_text from ansible.module_utils.connection import Connection from ansible.module_utils.network.common.utils import load_provider -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.utils.display import Display try: @@ -38,9 +38,11 @@ except Exception: display = Display() -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): + + self._config_module = True if self._task.action == 'bigip_imish_config' else False socket_path = None transport = 'rest' diff --git a/lib/ansible/plugins/action/ce.py b/lib/ansible/plugins/action/ce.py index e289441934..0680d91fc9 100644 --- a/lib/ansible/plugins/action/ce.py +++ b/lib/ansible/plugins/action/ce.py @@ -12,7 +12,7 @@ import copy from ansible import constants as C from ansible.module_utils._text import to_text from ansible.module_utils.connection import Connection -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.module_utils.network.cloudengine.ce import ce_provider_spec from ansible.module_utils.network.common.utils import load_provider from ansible.utils.display import Display @@ -22,11 +22,12 @@ display = Display() CLI_SUPPORTED_MODULES = ['ce_config', 'ce_command'] -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'ce_config' else False socket_path = None if self._play_context.connection == 'local': diff --git a/lib/ansible/plugins/action/ce_config.py b/lib/ansible/plugins/action/ce_config.py deleted file mode 100644 index 8881b74a0b..0000000000 --- a/lib/ansible/plugins/action/ce_config.py +++ /dev/null @@ -1,93 +0,0 @@ -# -# Copyright 2015 Peter Sprygada -# -# 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 . -# -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.ce import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/lib/ansible/plugins/action/cli_config.py b/lib/ansible/plugins/action/cli_config.py index 25f000ab8a..1bf30c584b 100644 --- a/lib/ansible/plugins/action/cli_config.py +++ b/lib/ansible/plugins/action/cli_config.py @@ -19,34 +19,16 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import os -import re - -from ansible.plugins.action.normal import ActionModule as _ActionModule -from ansible.module_utils.network.common.backup import write_backup +from ansible.plugins.action.network import ActionModule as ActionNetworkModule -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): + del tmp # tmp no longer has any effect + + self._config_module = True if self._play_context.connection != 'network_cli': return {'failed': True, 'msg': 'Connection type %s is not valid for cli_config module' % self._play_context.connection} - result = super(ActionModule, self).run(task_vars=task_vars) - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result.keys()): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result + return super(ActionModule, self).run(task_vars=task_vars) diff --git a/lib/ansible/plugins/action/cnos.py b/lib/ansible/plugins/action/cnos.py index 0c62124082..66dc14c8cf 100644 --- a/lib/ansible/plugins/action/cnos.py +++ b/lib/ansible/plugins/action/cnos.py @@ -21,7 +21,7 @@ import sys import copy from ansible import constants as C -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.module_utils.network.cnos.cnos import cnos_provider_spec from ansible.module_utils.network.common.utils import load_provider from ansible.module_utils.connection import Connection @@ -31,12 +31,14 @@ from ansible.utils.display import Display display = Display() -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'cnos_config' else False socket_path = None + if self._play_context.connection == 'local': provider = load_provider(cnos_provider_spec, self._task.args) pc = copy.deepcopy(self._play_context) diff --git a/lib/ansible/plugins/action/cnos_config.py b/lib/ansible/plugins/action/cnos_config.py deleted file mode 100644 index cd693a56fe..0000000000 --- a/lib/ansible/plugins/action/cnos_config.py +++ /dev/null @@ -1,89 +0,0 @@ -# (C) 2017 Red Hat Inc. -# Copyright (C) 2017 Lenovo. -# -# GNU General Public License v3.0+ -# -# This program 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. -# -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -# -# Contains Action Plugin methods for CNOS Config Module -# Lenovo Networking -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.cnos import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/lib/ansible/plugins/action/dellos10.py b/lib/ansible/plugins/action/dellos10.py index b102f884ee..70bf263f7e 100644 --- a/lib/ansible/plugins/action/dellos10.py +++ b/lib/ansible/plugins/action/dellos10.py @@ -27,7 +27,7 @@ import copy from ansible import constants as C from ansible.module_utils._text import to_text from ansible.module_utils.connection import Connection -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.module_utils.network.common.utils import load_provider from ansible.module_utils.network.dellos10.dellos10 import dellos10_provider_spec from ansible.utils.display import Display @@ -35,11 +35,12 @@ from ansible.utils.display import Display display = Display() -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'dellos10_config' else False socket_path = None if self._play_context.connection == 'network_cli': diff --git a/lib/ansible/plugins/action/dellos10_config.py b/lib/ansible/plugins/action/dellos10_config.py deleted file mode 100644 index 1f96b0b715..0000000000 --- a/lib/ansible/plugins/action/dellos10_config.py +++ /dev/null @@ -1,95 +0,0 @@ -# -# Copyright 2015 Peter Sprygada -# -# Copyright (c) 2017 Dell 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 . -# -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.dellos10 import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/lib/ansible/plugins/action/dellos6.py b/lib/ansible/plugins/action/dellos6.py index 84049f14bc..e8194aade1 100644 --- a/lib/ansible/plugins/action/dellos6.py +++ b/lib/ansible/plugins/action/dellos6.py @@ -27,7 +27,7 @@ import copy from ansible import constants as C from ansible.module_utils._text import to_text from ansible.module_utils.connection import Connection -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.module_utils.network.dellos6.dellos6 import dellos6_provider_spec from ansible.module_utils.network.common.utils import load_provider from ansible.utils.display import Display @@ -35,11 +35,12 @@ from ansible.utils.display import Display display = Display() -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'dellos6_config' else False socket_path = None if self._play_context.connection == 'network_cli': diff --git a/lib/ansible/plugins/action/dellos6_config.py b/lib/ansible/plugins/action/dellos6_config.py deleted file mode 100644 index ec4f480e2f..0000000000 --- a/lib/ansible/plugins/action/dellos6_config.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright 2015 Peter Sprygada -# -# 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 . -# -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.dellos6 import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/lib/ansible/plugins/action/dellos9.py b/lib/ansible/plugins/action/dellos9.py index 202061b1df..20b82cf31f 100644 --- a/lib/ansible/plugins/action/dellos9.py +++ b/lib/ansible/plugins/action/dellos9.py @@ -27,7 +27,7 @@ import copy from ansible import constants as C from ansible.module_utils._text import to_text from ansible.module_utils.connection import Connection -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.module_utils.network.common.utils import load_provider from ansible.module_utils.network.dellos9.dellos9 import dellos9_provider_spec from ansible.utils.display import Display @@ -35,11 +35,12 @@ from ansible.utils.display import Display display = Display() -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'dellos9_config' else False socket_path = None if self._play_context.connection == 'network_cli': diff --git a/lib/ansible/plugins/action/dellos9_config.py b/lib/ansible/plugins/action/dellos9_config.py deleted file mode 100644 index 266bb01eec..0000000000 --- a/lib/ansible/plugins/action/dellos9_config.py +++ /dev/null @@ -1,95 +0,0 @@ -# -# Copyright 2015 Peter Sprygada -# -# Copyright (c) 2017 Dell 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 . -# -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.dellos9 import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/lib/ansible/plugins/action/edgeos_config.py b/lib/ansible/plugins/action/edgeos_config.py index 52d2f82a41..22ccf5df5a 100644 --- a/lib/ansible/plugins/action/edgeos_config.py +++ b/lib/ansible/plugins/action/edgeos_config.py @@ -19,77 +19,17 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import os -import re - -from ansible.plugins.action.normal import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit +from ansible.plugins.action.network import ActionModule as ActionNetworkModule -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): + del tmp # tmp no longer has any effect + + self._config_module = True + if self._play_context.connection != 'network_cli': return {'failed': True, 'msg': 'Connection type %s is not valid for this module. Must use network_cli.' % self._play_context.connection} - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result.keys()): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) + return super(ActionModule, self).run(task_vars=task_vars) diff --git a/lib/ansible/plugins/action/enos.py b/lib/ansible/plugins/action/enos.py index 58bd4ca390..25db538af5 100644 --- a/lib/ansible/plugins/action/enos.py +++ b/lib/ansible/plugins/action/enos.py @@ -21,7 +21,7 @@ import sys import copy from ansible import constants as C -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.module_utils.network.enos.enos import enos_provider_spec from ansible.module_utils.network.common.utils import load_provider from ansible.module_utils.connection import Connection @@ -31,11 +31,12 @@ from ansible.utils.display import Display display = Display() -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'enos_config' else False socket_path = None if self._play_context.connection == 'local': provider = load_provider(enos_provider_spec, self._task.args) diff --git a/lib/ansible/plugins/action/enos_config.py b/lib/ansible/plugins/action/enos_config.py deleted file mode 100644 index 669cd15a85..0000000000 --- a/lib/ansible/plugins/action/enos_config.py +++ /dev/null @@ -1,90 +0,0 @@ -# (C) 2017 Red Hat Inc. -# Copyright (C) 2017 Lenovo. -# -# GNU General Public License v3.0+ -# -# This program 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. -# -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -# -# Contains Action Plugin methods for ENOS Config Module -# Lenovo Networking -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.enos import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result.keys()): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/lib/ansible/plugins/action/eos.py b/lib/ansible/plugins/action/eos.py index 218e53d080..cc9fa7cb7b 100644 --- a/lib/ansible/plugins/action/eos.py +++ b/lib/ansible/plugins/action/eos.py @@ -26,18 +26,19 @@ from ansible import constants as C from ansible.module_utils._text import to_text from ansible.module_utils.connection import Connection from ansible.module_utils.network.eos.eos import eos_provider_spec -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.module_utils.network.common.utils import load_provider from ansible.utils.display import Display display = Display() -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'eos_config' else False socket_path = None if self._play_context.connection in ('network_cli', 'httpapi'): diff --git a/lib/ansible/plugins/action/eos_config.py b/lib/ansible/plugins/action/eos_config.py deleted file mode 100644 index 054cd7c874..0000000000 --- a/lib/ansible/plugins/action/eos_config.py +++ /dev/null @@ -1,94 +0,0 @@ -# -# Copyright 2015 Peter Sprygada -# -# 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 . -# -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.eos import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result.keys()): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/lib/ansible/plugins/action/exos_config.py b/lib/ansible/plugins/action/exos_config.py index 731b440052..7d3381232b 100644 --- a/lib/ansible/plugins/action/exos_config.py +++ b/lib/ansible/plugins/action/exos_config.py @@ -19,76 +19,13 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import os -import re - -from ansible.plugins.action.normal import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash +from ansible.plugins.action.network import ActionModule as ActionNetworkModule -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) del tmp # tmp no longer has any effect - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result.keys()): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) + self._config_module = True + return super(ActionModule, self).run(task_vars=task_vars) diff --git a/lib/ansible/plugins/action/fortios_config.py b/lib/ansible/plugins/action/fortios_config.py index 9cac71c55b..03d6f2dd74 100644 --- a/lib/ansible/plugins/action/fortios_config.py +++ b/lib/ansible/plugins/action/fortios_config.py @@ -19,70 +19,14 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import os -import re -import time -import glob -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 - -PRIVATE_KEYS_RE = re.compile('__.+__') +from ansible.plugins.action.network import ActionModule as ActionNetworkModule -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=exc.message) - - result = super(ActionModule, self).run(tmp, task_vars) del tmp # tmp no longer has any effect - return result - - def _get_working_path(self): - cwd = self._loader.get_basedir() - if self._task._role is not None: - cwd = self._task._role._role_path - return cwd - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) + self._config_module = True + return super(ActionModule, self).run(task_vars=task_vars) diff --git a/lib/ansible/plugins/action/ios.py b/lib/ansible/plugins/action/ios.py index 612d27189a..366fbed059 100644 --- a/lib/ansible/plugins/action/ios.py +++ b/lib/ansible/plugins/action/ios.py @@ -22,10 +22,9 @@ __metaclass__ = type import sys import copy -from ansible import constants as C from ansible.module_utils._text import to_text from ansible.module_utils.connection import Connection, ConnectionError -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.module_utils.network.common.utils import load_provider from ansible.module_utils.network.ios.ios import ios_provider_spec from ansible.utils.display import Display @@ -33,11 +32,12 @@ from ansible.utils.display import Display display = Display() -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'ios_config' else False socket_path = None if self._play_context.connection == 'network_cli': diff --git a/lib/ansible/plugins/action/ios_config.py b/lib/ansible/plugins/action/ios_config.py deleted file mode 100644 index 06a69bf9c3..0000000000 --- a/lib/ansible/plugins/action/ios_config.py +++ /dev/null @@ -1,93 +0,0 @@ -# -# (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 . -# -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.ios import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result.keys()): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/lib/ansible/plugins/action/iosxr.py b/lib/ansible/plugins/action/iosxr.py index dac0168f3e..9eecfe844e 100644 --- a/lib/ansible/plugins/action/iosxr.py +++ b/lib/ansible/plugins/action/iosxr.py @@ -26,18 +26,19 @@ from ansible import constants as C from ansible.module_utils._text import to_text from ansible.module_utils.connection import Connection from ansible.module_utils.network.iosxr.iosxr import iosxr_provider_spec -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.module_utils.network.common.utils import load_provider from ansible.utils.display import Display display = Display() -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'iosxr_config' else False socket_path = None force_cli = self._task.action in ('iosxr_netconf', 'iosxr_config', 'iosxr_command', 'iosxr_facts') diff --git a/lib/ansible/plugins/action/iosxr_config.py b/lib/ansible/plugins/action/iosxr_config.py deleted file mode 100644 index fac3910eaa..0000000000 --- a/lib/ansible/plugins/action/iosxr_config.py +++ /dev/null @@ -1,93 +0,0 @@ -# -# (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 . -# -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.iosxr import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result.keys()): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/lib/ansible/plugins/action/ironware.py b/lib/ansible/plugins/action/ironware.py index b1a77b072c..bedaa0ac52 100644 --- a/lib/ansible/plugins/action/ironware.py +++ b/lib/ansible/plugins/action/ironware.py @@ -25,7 +25,7 @@ import copy from ansible import constants as C from ansible.module_utils._text import to_text from ansible.module_utils.connection import Connection, ConnectionError -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.module_utils.network.common.utils import load_provider from ansible.module_utils.network.ironware.ironware import ironware_provider_spec from ansible.utils.display import Display @@ -33,11 +33,12 @@ from ansible.utils.display import Display display = Display() -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'ironware_config' else False socket_path = None if self._play_context.connection == 'network_cli': diff --git a/lib/ansible/plugins/action/ironware_config.py b/lib/ansible/plugins/action/ironware_config.py deleted file mode 100644 index 4d95205205..0000000000 --- a/lib/ansible/plugins/action/ironware_config.py +++ /dev/null @@ -1,93 +0,0 @@ -# -# (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 . -# -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.ironware import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/lib/ansible/plugins/action/junos.py b/lib/ansible/plugins/action/junos.py index e925c9db14..90924f721f 100644 --- a/lib/ansible/plugins/action/junos.py +++ b/lib/ansible/plugins/action/junos.py @@ -28,7 +28,7 @@ from ansible.module_utils.connection import Connection from ansible.module_utils.network.common.utils import load_provider from ansible.module_utils.network.junos.junos import junos_provider_spec from ansible.plugins.loader import connection_loader, module_loader -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.utils.display import Display display = Display() @@ -36,11 +36,12 @@ display = Display() CLI_SUPPORTED_MODULES = ['junos_netconf', 'junos_command'] -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'junos_config' else False module = module_loader._load_module_source(self._task.action, module_loader.find_plugin(self._task.action)) if not getattr(module, 'USE_PERSISTENT_CONNECTION', False): return super(ActionModule, self).run(task_vars=task_vars) diff --git a/lib/ansible/plugins/action/junos_config.py b/lib/ansible/plugins/action/junos_config.py deleted file mode 100644 index 49eaf94595..0000000000 --- a/lib/ansible/plugins/action/junos_config.py +++ /dev/null @@ -1,93 +0,0 @@ -# -# (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 . -# -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.junos import ActionModule as _ActionModule -from ansible.module_utils._text import to_text, to_bytes -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__'], encoding='latin-1') - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/lib/ansible/plugins/action/net_get.py b/lib/ansible/plugins/action/net_get.py index f5f4797213..af421029f0 100644 --- a/lib/ansible/plugins/action/net_get.py +++ b/lib/ansible/plugins/action/net_get.py @@ -19,22 +19,20 @@ __metaclass__ = type import copy import os -import time import re import uuid import hashlib from ansible.module_utils._text import to_text, to_bytes from ansible.module_utils.connection import Connection -from ansible.errors import AnsibleError -from ansible.plugins.action import ActionBase +from ansible.plugins.action.network import ActionModule as NetworkActionModule from ansible.module_utils.six.moves.urllib.parse import urlsplit from ansible.utils.display import Display display = Display() -class ActionModule(ActionBase): +class ActionModule(NetworkActionModule): def run(self, tmp=None, task_vars=None): socket_path = None @@ -111,33 +109,12 @@ class ActionModule(ActionBase): filename_list = re.split('/|:', src_path) return filename_list[-1] - def _get_working_path(self): - cwd = self._loader.get_basedir() - if self._task._role is not None: - cwd = self._task._role._role_path - return cwd - def _get_default_dest(self, src_path): dest_path = self._get_working_path() src_fname = self._get_src_filename_from_path(src_path) filename = '%s/%s' % (dest_path, src_fname) return filename - def _get_network_os(self, task_vars): - if 'network_os' in self._task.args and self._task.args['network_os']: - display.vvvv('Getting network OS from task argument') - network_os = self._task.args['network_os'] - elif self._play_context.network_os: - display.vvvv('Getting network OS from inventory') - network_os = self._play_context.network_os - elif 'network_os' in task_vars.get('ansible_facts', {}) and task_vars['ansible_facts']['network_os']: - display.vvvv('Getting network OS from fact') - network_os = task_vars['ansible_facts']['network_os'] - else: - raise AnsibleError('ansible_network_os must be specified on this host to use platform agnostic modules') - - return network_os - def _handle_existing_file(self, conn, source, dest, proto, timeout): if not os.path.exists(dest): return True diff --git a/lib/ansible/plugins/action/net_put.py b/lib/ansible/plugins/action/net_put.py index 993d81270a..1260e67f39 100644 --- a/lib/ansible/plugins/action/net_put.py +++ b/lib/ansible/plugins/action/net_put.py @@ -27,15 +27,14 @@ import re from ansible.module_utils._text import to_text, to_bytes from ansible.module_utils.connection import Connection -from ansible.errors import AnsibleError -from ansible.plugins.action import ActionBase +from ansible.plugins.action.network import ActionModule as NetworkActionModule from ansible.module_utils.six.moves.urllib.parse import urlsplit from ansible.utils.display import Display display = Display() -class ActionModule(ActionBase): +class ActionModule(NetworkActionModule): def run(self, tmp=None, task_vars=None): changed = True @@ -73,7 +72,7 @@ class ActionModule(ActionBase): if mode == 'text': try: - self._handle_template() + self._handle_template(convert_data=False) except ValueError as exc: return dict(failed=True, msg=to_text(exc)) @@ -182,66 +181,6 @@ class ActionModule(ActionBase): else: return True - def _get_working_path(self): - cwd = self._loader.get_basedir() - if self._task._role is not None: - cwd = self._task._role._role_path - return cwd - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template( - template_data, - convert_data=False - ) - - return dict(failed=False, msg='successfully loaded file') - - def _get_network_os(self, task_vars): - if 'network_os' in self._task.args and self._task.args['network_os']: - display.vvvv('Getting network OS from task argument') - network_os = self._task.args['network_os'] - elif self._play_context.network_os: - display.vvvv('Getting network OS from inventory') - network_os = self._play_context.network_os - elif 'network_os' in task_vars.get('ansible_facts', {}) and task_vars['ansible_facts']['network_os']: - display.vvvv('Getting network OS from fact') - network_os = task_vars['ansible_facts']['network_os'] - else: - raise AnsibleError('ansible_network_os must be specified on this host to use platform agnostic modules') - - return network_os - def _get_binary_src_file(self, src): working_path = self._get_working_path() diff --git a/lib/ansible/plugins/action/netconf.py b/lib/ansible/plugins/action/netconf.py index 73b0cbf334..e44c1d0be8 100644 --- a/lib/ansible/plugins/action/netconf.py +++ b/lib/ansible/plugins/action/netconf.py @@ -22,17 +22,19 @@ __metaclass__ = type import copy import sys -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.utils.display import Display display = Display() -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'netconf_config' else False + if self._play_context.connection not in ['netconf', 'local'] and self._task.action == 'netconf_config': return {'failed': True, 'msg': 'Connection type %s is not valid for netconf_config module. ' 'Valid connection type is netconf or local (deprecated)' % self._play_context.connection} diff --git a/lib/ansible/plugins/action/netconf_config.py b/lib/ansible/plugins/action/netconf_config.py deleted file mode 100644 index e8a91b02a2..0000000000 --- a/lib/ansible/plugins/action/netconf_config.py +++ /dev/null @@ -1,91 +0,0 @@ -# -# Copyright 2016 Peter Sprygada -# -# 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 . -# -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.netconf import ActionModule as _ActionModule -from ansible.module_utils._text import to_text, to_bytes -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__'], encoding='latin-1') - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/lib/ansible/plugins/action/bigip_imish_config.py b/lib/ansible/plugins/action/network.py similarity index 52% rename from lib/ansible/plugins/action/bigip_imish_config.py rename to lib/ansible/plugins/action/network.py index e3d43f02c3..df35b6de4f 100644 --- a/lib/ansible/plugins/action/bigip_imish_config.py +++ b/lib/ansible/plugins/action/network.py @@ -1,5 +1,5 @@ # -# (c) 2017, Red Hat, Inc. +# (c) 2018 Red Hat Inc. # # This file is part of Ansible # @@ -20,41 +20,46 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type import os +import time +import glob import re -from ansible.plugins.action.bigip import ActionModule as _ActionModule +from ansible.errors import AnsibleError from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup from ansible.module_utils.six.moves.urllib.parse import urlsplit - -try: - from library.module_utils.network.f5.common import f5_provider_spec -except Exception: - from ansible.module_utils.network.f5.common import f5_provider_spec - +from ansible.plugins.action.normal import ActionModule as _ActionModule from ansible.utils.display import Display -display = Display() +display = Display() PRIVATE_KEYS_RE = re.compile('__.+__') class ActionModule(_ActionModule): - def run(self, tmp=None, task_vars=None): - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) + def run(self, task_vars=None): + config_module = hasattr(self, '_config_module') and self._config_module + if config_module and self._task.args.get('src'): + self._handle_src_option() - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect + result = super(ActionModule, self).run(task_vars=task_vars) - if self._task.args.get('backup') and result.get('__backup__'): + if config_module and self._task.args.get('backup'): + self._handle_backup_option(result, task_vars['inventory_hostname'], result.get('__backup__', False)) + + return result + + def _handle_src_option(self): + try: + self._handle_template() + except ValueError as exc: + return dict(failed=True, msg=to_text(exc)) + + def _handle_backup_option(self, result, hostname, backup): + if backup: # User requested backup and no error occurred in module. # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) + filepath = self._write_backup(hostname, backup) result['backup_path'] = filepath # strip out any keys that have two leading and two trailing @@ -63,9 +68,27 @@ class ActionModule(_ActionModule): if PRIVATE_KEYS_RE.match(key): del result[key] - return result + def _get_working_path(self): + cwd = self._loader.get_basedir() + if self._task._role is not None: + cwd = self._task._role._role_path + return cwd - def _handle_template(self): + def _write_backup(self, host, contents, encoding='utf-8'): + cwd = self._get_working_path() + + backup_path = os.path.join(cwd, 'backup') + if not os.path.exists(backup_path): + os.mkdir(backup_path) + for existing_backup in glob.glob('%s/%s_config.*' % (backup_path, host)): + os.remove(existing_backup) + tstamp = time.strftime("%Y-%m-%d@%H:%M:%S", time.localtime(time.time())) + filename = '%s/%s_config.%s' % (backup_path, host, tstamp) + open(filename, 'w').write(to_text(contents, encoding=encoding)) + + return filename + + def _handle_template(self, convert_data=True): src = self._task.args.get('src') working_path = self._get_working_path() @@ -97,4 +120,19 @@ class ActionModule(_ActionModule): searchpath.append(role._role_path) searchpath.append(os.path.dirname(source)) self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) + self._task.args['src'] = self._templar.template(template_data, convert_data=convert_data) + + def _get_network_os(self, task_vars): + if 'network_os' in self._task.args and self._task.args['network_os']: + display.vvvv('Getting network OS from task argument') + network_os = self._task.args['network_os'] + elif self._play_context.network_os: + display.vvvv('Getting network OS from inventory') + network_os = self._play_context.network_os + elif 'network_os' in task_vars.get('ansible_facts', {}) and task_vars['ansible_facts']['network_os']: + display.vvvv('Getting network OS from fact') + network_os = task_vars['ansible_facts']['network_os'] + else: + raise AnsibleError('ansible_network_os must be specified on this host') + + return network_os diff --git a/lib/ansible/plugins/action/nos_config.py b/lib/ansible/plugins/action/nos_config.py index 87bc8da13a..80ffdcbc56 100644 --- a/lib/ansible/plugins/action/nos_config.py +++ b/lib/ansible/plugins/action/nos_config.py @@ -19,75 +19,13 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import os -import re - -from ansible.plugins.action.normal import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - -PRIVATE_KEYS_RE = re.compile('__.+__') +from ansible.plugins.action.network import ActionModule as ActionNetworkModule -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) del tmp # tmp no longer has any effect - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result.keys()): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) + self._config_module = True + return super(ActionModule, self).run(task_vars=task_vars) diff --git a/lib/ansible/plugins/action/nxos.py b/lib/ansible/plugins/action/nxos.py index d62391f80f..04d9803050 100644 --- a/lib/ansible/plugins/action/nxos.py +++ b/lib/ansible/plugins/action/nxos.py @@ -26,7 +26,7 @@ import sys from ansible import constants as C from ansible.module_utils._text import to_text from ansible.module_utils.connection import Connection -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.module_utils.network.common.utils import load_provider from ansible.module_utils.network.nxos.nxos import nxos_provider_spec from ansible.utils.display import Display @@ -34,11 +34,12 @@ from ansible.utils.display import Display display = Display() -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'nxos_config' else False socket_path = None if (self._play_context.connection == 'httpapi' or self._task.args.get('provider', {}).get('transport') == 'nxapi') \ diff --git a/lib/ansible/plugins/action/nxos_config.py b/lib/ansible/plugins/action/nxos_config.py deleted file mode 100644 index 5503eae1f1..0000000000 --- a/lib/ansible/plugins/action/nxos_config.py +++ /dev/null @@ -1,93 +0,0 @@ -# -# Copyright 2015 Peter Sprygada -# -# 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 . -# -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.nxos import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result.keys()): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/lib/ansible/plugins/action/onyx_config.py b/lib/ansible/plugins/action/onyx_config.py index a59b3b4afb..4de62452d0 100644 --- a/lib/ansible/plugins/action/onyx_config.py +++ b/lib/ansible/plugins/action/onyx_config.py @@ -19,74 +19,13 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import os -import re - -from ansible.plugins.action.normal import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit - -PRIVATE_KEYS_RE = re.compile('__.+__') +from ansible.plugins.action.network import ActionModule as ActionNetworkModule -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) del tmp # tmp no longer has any effect - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result.keys()): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) + self._config_module = True + return super(ActionModule, self).run(task_vars=task_vars) diff --git a/lib/ansible/plugins/action/slxos_config.py b/lib/ansible/plugins/action/slxos_config.py index 87bc8da13a..3321f59400 100644 --- a/lib/ansible/plugins/action/slxos_config.py +++ b/lib/ansible/plugins/action/slxos_config.py @@ -19,75 +19,19 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import os import re -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash +from ansible.module_utils.network.common.backup import write_backup, handle_template PRIVATE_KEYS_RE = re.compile('__.+__') -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) del tmp # tmp no longer has any effect - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result.keys()): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) + self._config_module = True + return super(ActionModule, self).run(task_vars=task_vars) diff --git a/lib/ansible/plugins/action/sros.py b/lib/ansible/plugins/action/sros.py index 47682eb86a..3ee7f1c9c8 100644 --- a/lib/ansible/plugins/action/sros.py +++ b/lib/ansible/plugins/action/sros.py @@ -23,7 +23,7 @@ import sys import copy from ansible import constants as C -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.module_utils.network.sros.sros import sros_provider_spec from ansible.module_utils.network.common.utils import load_provider from ansible.utils.display import Display @@ -31,11 +31,12 @@ from ansible.utils.display import Display display = Display() -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'sros_config' else False if self._play_context.connection == 'network_cli': provider = self._task.args.get('provider', {}) if any(provider.values()): diff --git a/lib/ansible/plugins/action/sros_config.py b/lib/ansible/plugins/action/sros_config.py deleted file mode 100644 index 6667b8a21b..0000000000 --- a/lib/ansible/plugins/action/sros_config.py +++ /dev/null @@ -1,93 +0,0 @@ -# -# Copyright 2016 Peter Sprygada -# -# 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 . -# -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.sros import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/lib/ansible/plugins/action/voss_config.py b/lib/ansible/plugins/action/voss_config.py index 87bc8da13a..80ffdcbc56 100644 --- a/lib/ansible/plugins/action/voss_config.py +++ b/lib/ansible/plugins/action/voss_config.py @@ -19,75 +19,13 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import os -import re - -from ansible.plugins.action.normal import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - -PRIVATE_KEYS_RE = re.compile('__.+__') +from ansible.plugins.action.network import ActionModule as ActionNetworkModule -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) del tmp # tmp no longer has any effect - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result.keys()): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) + self._config_module = True + return super(ActionModule, self).run(task_vars=task_vars) diff --git a/lib/ansible/plugins/action/vyos.py b/lib/ansible/plugins/action/vyos.py index 624a1259df..ea7dd703c0 100644 --- a/lib/ansible/plugins/action/vyos.py +++ b/lib/ansible/plugins/action/vyos.py @@ -23,7 +23,7 @@ import sys import copy from ansible import constants as C -from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.plugins.action.network import ActionModule as ActionNetworkModule from ansible.module_utils._text import to_text from ansible.module_utils.connection import Connection from ansible.module_utils.network.common.utils import load_provider @@ -33,11 +33,12 @@ from ansible.utils.display import Display display = Display() -class ActionModule(_ActionModule): +class ActionModule(ActionNetworkModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect + self._config_module = True if self._task.action == 'vyos_config' else False socket_path = None if self._play_context.connection == 'network_cli': diff --git a/lib/ansible/plugins/action/vyos_config.py b/lib/ansible/plugins/action/vyos_config.py deleted file mode 100644 index f67bc4ea1f..0000000000 --- a/lib/ansible/plugins/action/vyos_config.py +++ /dev/null @@ -1,94 +0,0 @@ -# -# Copyright 2015 Peter Sprygada -# -# 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 . -# -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import re - -from ansible.plugins.action.vyos import ActionModule as _ActionModule -from ansible.module_utils._text import to_text -from ansible.module_utils.network.common.backup import write_backup -from ansible.module_utils.six.moves.urllib.parse import urlsplit -from ansible.utils.vars import merge_hash - - -PRIVATE_KEYS_RE = re.compile('__.+__') - - -class ActionModule(_ActionModule): - - def run(self, tmp=None, task_vars=None): - - if self._task.args.get('src'): - try: - self._handle_template() - except ValueError as exc: - return dict(failed=True, msg=to_text(exc)) - - result = super(ActionModule, self).run(tmp, task_vars) - del tmp # tmp no longer has any effect - - if self._task.args.get('backup') and result.get('__backup__'): - # User requested backup and no error occurred in module. - # NOTE: If there is a parameter error, _backup key may not be in results. - filepath = write_backup(self, task_vars['inventory_hostname'], result['__backup__']) - result['backup_path'] = filepath - - # strip out any keys that have two leading and two trailing - # underscore characters - for key in list(result.keys()): - if PRIVATE_KEYS_RE.match(key): - del result[key] - - return result - - def _handle_template(self): - src = self._task.args.get('src') - working_path = self._get_working_path() - - if os.path.isabs(src) or urlsplit('src').scheme: - source = src - else: - source = self._loader.path_dwim_relative(working_path, 'templates', src) - if not source: - source = self._loader.path_dwim_relative(working_path, src) - - if not os.path.exists(source): - raise ValueError('path specified in src not found') - - try: - with open(source, 'r') as f: - template_data = to_text(f.read()) - except IOError: - return dict(failed=True, msg='unable to load src file') - - # Create a template search path in the following order: - # [working_path, self_role_path, dependent_role_paths, dirname(source)] - searchpath = [working_path] - if self._task._role is not None: - searchpath.append(self._task._role._role_path) - if hasattr(self._task, "_block:"): - dep_chain = self._task._block.get_dep_chain() - if dep_chain is not None: - for role in dep_chain: - searchpath.append(role._role_path) - searchpath.append(os.path.dirname(source)) - self._templar.environment.loader.searchpath = searchpath - self._task.args['src'] = self._templar.template(template_data) diff --git a/test/sanity/code-smell/action-plugin-docs.py b/test/sanity/code-smell/action-plugin-docs.py index 36d063bb14..db0b853da8 100755 --- a/test/sanity/code-smell/action-plugin-docs.py +++ b/test/sanity/code-smell/action-plugin-docs.py @@ -10,6 +10,7 @@ def main(): '__init__', # action plugin base class, not an actual action plugin 'net_base', # base class for other net_* action plugins which have a matching module 'normal', # default action plugin for modules without a dedicated action plugin + 'network', # base class for network action plugins # The following action plugins existed without modules to document them before this test was put in place. # They should either be removed, have a module added to document them, or have the exception documented here.