From 6e1ab6f89370538f2e97b62c45c194780f5ea6c7 Mon Sep 17 00:00:00 2001 From: Mathieu Bultel Date: Tue, 28 Apr 2020 14:29:21 +0200 Subject: [PATCH] Add asynchronous option to validation libs In order to run ansible on its own and get validations progress and result with the CLI, the review adds an option to run ansible asynchronously Change-Id: Id884c9fd606ba03cb7d7fb02491582f1f88c3857 --- validations_libs/ansible.py | 16 +++++++--------- validations_libs/tests/test_ansible.py | 22 ++++++++++++++++++++++ validations_libs/validation_actions.py | 15 +++++++++------ 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/validations_libs/ansible.py b/validations_libs/ansible.py index 83932f30..9d9f8e9f 100644 --- a/validations_libs/ansible.py +++ b/validations_libs/ansible.py @@ -21,6 +21,7 @@ import os import six import sys import tempfile +import threading import yaml from six.moves import configparser @@ -277,7 +278,7 @@ class Ansible(object): gathering_policy='smart', extra_env_variables=None, parallel_run=False, callback_whitelist=None, ansible_cfg=None, - ansible_timeout=30, ansible_artifact_path=None): + ansible_timeout=30, ansible_artifact_path=None, run_async=False): if not playbook_dir: playbook_dir = workdir @@ -350,20 +351,17 @@ class Ansible(object): if parallel_run: r_opts['directory_isolation_base_path'] = ansible_artifact_path - runner_config = ansible_runner.runner_config.RunnerConfig(**r_opts) runner_config.prepare() - # NOTE(cloudnull): overload the output callback after prepare - # to define the specific format we want. - # This is only required until PR - # https://github.com/ansible/ansible-runner/pull/387 - # is merged and released. After this PR has been - # made available to us, this line should be removed. runner_config.env['ANSIBLE_STDOUT_CALLBACK'] = \ envvars['ANSIBLE_STDOUT_CALLBACK'] if backward_compat: runner_config.env.update(envvars) - runner = ansible_runner.Runner(config=runner_config) + runner = ansible_runner.Runner(config=runner_config) + if run_async: + thr = threading.Thread(target=runner.run) + thr.start() + return playbook, runner.rc, runner.status status, rc = runner.run() return playbook, rc, status diff --git a/validations_libs/tests/test_ansible.py b/validations_libs/tests/test_ansible.py index 59258925..5966700d 100644 --- a/validations_libs/tests/test_ansible.py +++ b/validations_libs/tests/test_ansible.py @@ -129,3 +129,25 @@ class TestAnsible(TestCase): ) self.assertEquals((_playbook, _rc, _status), ('existing.yaml', 0, 'successful')) + + @mock.patch('os.path.exists', return_value=True) + @mock.patch('os.makedirs') + @mock.patch.object(Runner, 'run', + return_value=fakes.fake_ansible_runner_run_return(rc=0)) + @mock.patch('ansible_runner.utils.dump_artifact', autospec=True, + return_value="/foo/inventory.yaml") + @mock.patch('six.moves.builtins.open') + @mock.patch('ansible_runner.runner_config.RunnerConfig') + def test_run_success_run_async(self, mock_config, mock_open, + mock_dump_artifact, mock_run, + mock_mkdirs, mock_exists + ): + _playbook, _rc, _status = self.run.run( + playbook='existing.yaml', + inventory='localhost,', + workdir='/tmp', + connection='local', + run_async=True + ) + self.assertEquals((_playbook, _rc, _status), + ('existing.yaml', None, 'unstarted')) diff --git a/validations_libs/validation_actions.py b/validations_libs/validation_actions.py index bc985f1e..d77798eb 100644 --- a/validations_libs/validation_actions.py +++ b/validations_libs/validation_actions.py @@ -62,7 +62,7 @@ class ValidationActions(object): group=None, extra_vars=None, validations_dir=None, validation_name=None, extra_env_vars=None, ansible_cfg=None, quiet=True, workdir=None, - limit_hosts=None): + limit_hosts=None, run_async=False): self.log = logging.getLogger(__name__ + ".run_validations") playbooks = [] validations_dir = (validations_dir if validations_dir @@ -110,13 +110,16 @@ class ValidationActions(object): extra_env_variables=extra_env_vars, ansible_cfg=ansible_cfg, gathering_policy='explicit', - ansible_artifact_path=artifacts_dir) - results.append({'validation': { - 'playbook': _playbook, + ansible_artifact_path=artifacts_dir, + run_async=run_async) + results.append({'playbook': _playbook, 'rc_code': _rc, 'status': _status, - 'validation_id': _playbook.split('.')[0] - }}) + 'validations': _playbook.split('.')[0], + 'UUID': validation_uuid, + }) + if run_async: + return results # Return log results vlog = ValidationLogs() return vlog.get_results(validation_uuid)