diff --git a/lib/ansible/modules/network/fortios/fortios_config.py b/lib/ansible/modules/network/fortios/fortios_config.py index cc318ef18b3..a7c4e7c40f9 100644 --- a/lib/ansible/modules/network/fortios/fortios_config.py +++ b/lib/ansible/modules/network/fortios/fortios_config.py @@ -25,7 +25,7 @@ extends_documentation_fragment: fortios options: src: description: - - The I(src) argument provides a path to the configuration file + - The I(src) argument provides a path to the configuration template to load into the remote device. filter: description: @@ -57,7 +57,7 @@ EXAMPLES = """ host: 192.168.0.254 username: admin password: password - src: new_configuration.conf + src: new_configuration.conf.j2 """ @@ -144,7 +144,7 @@ def main(): if module.params['src'] is not None: #store config in str try: - conf_str = open(module.params['src'], 'r').read() + conf_str = module.params['src'] f.load_config(in_candidate=True, config_text=conf_str) except: module.fail_json(msg="Can't open configuration file, or configuration invalid") diff --git a/lib/ansible/plugins/action/fortios_config.py b/lib/ansible/plugins/action/fortios_config.py new file mode 100644 index 00000000000..6692569598f --- /dev/null +++ b/lib/ansible/plugins/action/fortios_config.py @@ -0,0 +1,87 @@ +# +# (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 +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('__.+__') + + +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=exc.message) + + result = super(ActionModule, self).run(tmp, task_vars) + + 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)