diff --git a/ansible/action_plugins/rougail.py b/ansible/action_plugins/rougail.py index 6648d5b..dad970c 100644 --- a/ansible/action_plugins/rougail.py +++ b/ansible/action_plugins/rougail.py @@ -1,10 +1,16 @@ #!/usr/bin/python3 -from asyncio import run from os import readlink, walk, chdir, getcwd, makedirs from os.path import join, islink, isdir -from risotto.machine import build_files, INSTALL_DIR, INSTALL_CONFIG_DIR, INSTALL_TMPL_DIR, INSTALL_IMAGES_DIR, INSTALL_TESTS_DIR -from shutil import rmtree +from typing import Dict, Any +from shutil import rmtree, copy2 import tarfile +from ansible.module_utils._text import to_text +from ansible import constants + +from rougail.template import base +from rougail.error import TemplateError +from risotto.machine import build_files, INSTALL_DIR, INSTALL_CONFIG_DIR, INSTALL_TMPL_DIR, INSTALL_IMAGES_DIR, INSTALL_TESTS_DIR +from risotto.utils import custom_filters try: @@ -13,6 +19,7 @@ try: class FakeModule(AnsibleModule): def __init__(self): pass + from ansible.plugins.action.template import ActionModule as TmplActionModule except: class ActionBase(): def __init__(self, *args, **kwargs): @@ -64,15 +71,24 @@ class ActionModule(ActionBase): only_machine = module_args.pop('only_machine') configure_host = module_args.pop('configure_host') copy_tests = module_args.pop('copy_tests') + # define ansible engine + base.ENGINES['ansible'] = Tmpl(task_vars, + self._task, + self._connection, + self._play_context, + self._loader, + self._templar, + self._shared_loader_obj, + ) if 'copy_templates' in module_args: copy_templates = module_args.pop('copy_templates') else: copy_templates = False - directories, certificates = run(build_files(hostname, - only_machine, - False, - copy_tests, - )) + directories, certificates = build_files(hostname, + only_machine, + False, + copy_tests, + ) module_args['directories'] = list(directories.values()) module_args['directories'].append('/var/lib/risotto/images_files') remote = self._execute_module(module_name='compare', @@ -86,17 +102,14 @@ class ActionModule(ActionBase): msg = remote['msg'] raise Exception(f'error in remote action: {msg}') if copy_templates: - run(build_files(hostname, - only_machine, - True, - copy_tests, - )) + build_files(hostname, + only_machine, + True, + copy_tests, + ) machines_changed = [] - tls_machine = None for machine, directory in directories.items(): - if machine.startswith('tls.'): - tls_machine = machine if directory not in remote['directories']: machines_changed.append(machine) continue @@ -150,6 +163,12 @@ class ActionModule(ActionBase): tar_filename = f'{ARCHIVES_DIR}/{INSTALL_IMAGES_DIR}.tar' with tarfile.open(tar_filename, 'w') as archive: archive.add('.') + self._execute_module(module_name='file', + module_args={'path': '/tmp/new_configurations', + 'state': 'directory', + }, + task_vars=task_vars, + ) self._transfer_file(tar_filename, tar_filename) # tests self._execute_module(module_name='file', @@ -190,5 +209,72 @@ class ActionModule(ActionBase): changed=changed, machines_changed=machines, host_changed=self._task.args['hostname'] in machines_changed, - tls_machine=tls_machine, ) + + +class FakeCopy: + def __init__(self, task): + self.task = task + + def run(self, *args, **kwargs): + copy2(self.task.args['src'], self.task.args['dest']) + return {} + + +class FakeGet: + def __init__(self, klass): + self.klass = klass + + def fake_get(self, action, *args, task, **kwargs): + if action == 'ansible.legacy.copy': + return FakeCopy(task) + return self.klass.ori_get(action, *args, task=task, **kwargs) + + +class Tmpl(TmplActionModule): + def __init__(self, task_vars, *args): + super().__init__(*args) + self.task_vars = task_vars + + def _early_needs_tmp_path(self): + # do not create tmp remotely + return False + + def process(self, + filename: str, + source: str, + true_destfilename: str, + destfilename: str, + destdir: str, + variable: Any, + index: int, + rougail_variables_dict: Dict, + eosfunc: Dict, + extra_variables: Any=None, + ): + if source is not None: # pragma: no cover + raise TemplateError(_('source is not supported for ansible')) + task_vars = rougail_variables_dict | self.task_vars + if variable is not None: + task_vars['rougail_variable'] = variable + if index is not None: + task_vars['rougail_index'] = index + if extra_variables: + task_vars['extra_variables'] = extra_variables + task_vars['rougail_filename'] = true_destfilename + task_vars['rougail_destination_dir'] = destdir + self._task.args['src'] = filename + self._task.args['dest'] = destfilename + # add custom filter + custom_filters.update(eosfunc) + # do not copy file in host but stay it locally + self._shared_loader_obj.action_loader.ori_get = self._shared_loader_obj.action_loader.get + self._shared_loader_obj.action_loader.get = FakeGet(self._shared_loader_obj.action_loader).fake_get + # template + ret = self.run(task_vars=task_vars) + # restore get function + self._shared_loader_obj.action_loader.get = self._shared_loader_obj.action_loader.ori_get + # remove custom filter + custom_filters.clear() + if ret.get('failed'): + raise TemplateError(f'error while templating "{filename}": {ret["msg"]}')