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 83932f3..9d9f8e9 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 5925892..5966700 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 bc985f1..d77798e 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)