From 1cc53bfd18149d17a546f76e01b2d0ebaf3273ef Mon Sep 17 00:00:00 2001 From: AlanCoding Date: Sun, 10 Nov 2019 23:00:04 -0500 Subject: [PATCH] Allow customizing display callback, refactor test data Create new integration test data folder this contains folders of runnable content contains example with selective callback contains example not printing skipped hosts Fix bugs combining display callbacks due to call pattern if parent class took var as kwarg, then passing as arg will stop working when another parent is added in the inheritance chain Restructure DOCUMENTATION management better align with user-specified display callback Delete parameterization to test aggregate callback gave false positives and generally did not work replaced with new test and data example --- .gitignore | 2 + ansible_runner/callbacks/awx_display.py | 17 +--- ansible_runner/callbacks/minimal.py | 17 +--- ansible_runner/display_callback/module.py | 36 +++++++- ansible_runner/runner_config.py | 3 + test/data/README.md | 15 ++++ .../aggregate_callback}/inventory/localhost | 0 .../callback_plugins}/other_callback.py | 4 +- .../data/aggregate_callback/project/debug.yml | 6 ++ test/data/callback_options/env/envvars | 2 + test/data/callback_options/inventory/hosts | 9 ++ .../callback_options/project/task_status.yml | 37 ++++++++ test/data/display_callback/env/envvars | 2 + test/data/display_callback/inventory/hosts | 9 ++ .../display_callback/project/task_status.yml | 37 ++++++++ .../data/display_callback_options/env/envvars | 4 + .../display_callback_options/inventory/hosts | 9 ++ .../project/task_status.yml | 37 ++++++++ test/data/misc/inventory/localhost | 2 + .../misc}/project/hello.yml | 0 .../meta/.galaxy_install_info | 0 .../benthomasson.hello_role/meta/main.yml | 0 .../benthomasson.hello_role/tasks/main.yml | 0 .../misc}/project/use_role.yml | 0 test/integration/conftest.py | 9 ++ test/integration/test_display_callback.py | 6 +- test/integration/test_events.py | 58 +++++++++++- test/integration/test_main.py | 89 ++++++++++--------- 28 files changed, 326 insertions(+), 84 deletions(-) create mode 100644 test/data/README.md rename test/{integration => data/aggregate_callback}/inventory/localhost (100%) rename test/{integration/callback => data/aggregate_callback/project/callback_plugins}/other_callback.py (72%) create mode 100644 test/data/aggregate_callback/project/debug.yml create mode 100644 test/data/callback_options/env/envvars create mode 100644 test/data/callback_options/inventory/hosts create mode 100644 test/data/callback_options/project/task_status.yml create mode 100644 test/data/display_callback/env/envvars create mode 100644 test/data/display_callback/inventory/hosts create mode 100644 test/data/display_callback/project/task_status.yml create mode 100644 test/data/display_callback_options/env/envvars create mode 100644 test/data/display_callback_options/inventory/hosts create mode 100644 test/data/display_callback_options/project/task_status.yml create mode 100644 test/data/misc/inventory/localhost rename test/{integration => data/misc}/project/hello.yml (100%) rename test/{integration => data/misc}/project/roles/benthomasson.hello_role/meta/.galaxy_install_info (100%) rename test/{integration => data/misc}/project/roles/benthomasson.hello_role/meta/main.yml (100%) rename test/{integration => data/misc}/project/roles/benthomasson.hello_role/tasks/main.yml (100%) rename test/{integration => data/misc}/project/use_role.yml (100%) diff --git a/.gitignore b/.gitignore index 7c82b09ce..35d776400 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,5 @@ .coverage *,cover .venv + +__pycache__/ diff --git a/ansible_runner/callbacks/awx_display.py b/ansible_runner/callbacks/awx_display.py index cf877d95a..1defe50df 100644 --- a/ansible_runner/callbacks/awx_display.py +++ b/ansible_runner/callbacks/awx_display.py @@ -17,20 +17,6 @@ from __future__ import (absolute_import, division, print_function) - -DOCUMENTATION = ''' - callback: awx_display - short_description: Playbook event dispatcher for ansible-runner - version_added: "2.0" - description: - - This callback is necessary for ansible-runner to work - type: stdout - extends_documentation_fragment: - - default_callback - requirements: - - Set as stdout in config -''' - # Python import os # noqa import sys # noqa @@ -48,3 +34,6 @@ # match "CallbackModule" class CallbackModule(AWXDefaultCallbackModule): pass + + +DOCUMENTATION = CallbackModule.get_documentation() diff --git a/ansible_runner/callbacks/minimal.py b/ansible_runner/callbacks/minimal.py index b170f08ce..50a30d9ac 100644 --- a/ansible_runner/callbacks/minimal.py +++ b/ansible_runner/callbacks/minimal.py @@ -17,20 +17,6 @@ from __future__ import (absolute_import, division, print_function) - -DOCUMENTATION = ''' - callback: minimal - short_description: Ad hoc event dispatcher for ansible-runner - version_added: "2.0" - description: - - This callback is necessary for ansible-runner to work - type: stdout - extends_documentation_fragment: - - default_callback - requirements: - - Set as stdout in config -''' - # Python import os # noqa import sys # noqa @@ -48,3 +34,6 @@ # match "CallbackModule" class CallbackModule(AWXMinimalCallbackModule): pass + + +DOCUMENTATION = CallbackModule.get_documentation() diff --git a/ansible_runner/display_callback/module.py b/ansible_runner/display_callback/module.py index 5eab69255..d5867f530 100644 --- a/ansible_runner/display_callback/module.py +++ b/ansible_runner/display_callback/module.py @@ -21,18 +21,42 @@ import collections import contextlib import sys +import os +import importlib import uuid from copy import copy # Ansible from ansible import constants as C from ansible.plugins.callback import CallbackBase -from ansible.plugins.callback.default import CallbackModule as DefaultCallbackModule # AWX Display Callback from .events import event_context from .minimal import CallbackModule as MinimalCallbackModule + +BASE_DOCUMENTATION = ''' + callback: %s + short_description: Playbook event dispatcher for ansible-runner + version_added: "2.0" + description: + - This callback is necessary for ansible-runner to work + type: stdout + extends_documentation_fragment: + - default_callback + requirements: + - Set as stdout in config +''' + + +if 'RUNNER_STDOUT_CALLBACK_PROXY' in os.environ: + from ansible.plugins.loader import callback_loader + DefaultCallbackModule = callback_loader.get(os.environ['RUNNER_STDOUT_CALLBACK_PROXY']).__class__ + DefaultCallbackModule.PROXY_DOCUMENTATION = importlib.import_module(DefaultCallbackModule.__module__).DOCUMENTATION +else: + from ansible.plugins.callback.default import CallbackModule as DefaultCallbackModule + + CENSORED = "the output has been hidden due to the fact that 'no_log: true' was specified for this result" # noqa @@ -60,6 +84,12 @@ class BaseCallbackModule(CallbackBase): 'playbook_on_no_hosts_remaining', ] + @classmethod + def get_documentation(cls): + if hasattr(cls, 'PROXY_DOCUMENTATION'): + return cls.PROXY_DOCUMENTATION + return BASE_DOCUMENTATION % cls.CALLBACK_NAME + def __init__(self): super(BaseCallbackModule, self).__init__() self.task_uuids = set() @@ -271,7 +301,7 @@ def v2_playbook_on_task_start(self, task, is_conditional): uuid=task_uuid, ) with self.capture_event_data('playbook_on_task_start', **event_data): - super(BaseCallbackModule, self).v2_playbook_on_task_start(task, is_conditional) + super(BaseCallbackModule, self).v2_playbook_on_task_start(task, is_conditional=is_conditional) def v2_playbook_on_cleanup_task_start(self, task): # NOTE: Not used by Ansible 2.x. @@ -374,7 +404,7 @@ def v2_runner_on_failed(self, result, ignore_errors=False): event_loop=self._get_event_loop(result._task), ) with self.capture_event_data('runner_on_failed', **event_data): - super(BaseCallbackModule, self).v2_runner_on_failed(result, ignore_errors) + super(BaseCallbackModule, self).v2_runner_on_failed(result, ignore_errors=ignore_errors) def v2_runner_on_skipped(self, result): event_data = dict( diff --git a/ansible_runner/runner_config.py b/ansible_runner/runner_config.py index 32b0b36a1..a31034530 100644 --- a/ansible_runner/runner_config.py +++ b/ansible_runner/runner_config.py @@ -195,6 +195,9 @@ def prepare(self): if python_path and not python_path.endswith(':'): python_path += ':' self.env['ANSIBLE_CALLBACK_PLUGINS'] = ':'.join(filter(None,(self.env.get('ANSIBLE_CALLBACK_PLUGINS'), callback_dir))) + # If stdout callback specified, pass info for this stdout callback plugin to subclass it + if 'ANSIBLE_STDOUT_CALLBACK' in self.env and self.env['ANSIBLE_STDOUT_CALLBACK'] not in ('awx_display', 'minimal'): + self.env['RUNNER_STDOUT_CALLBACK_PROXY'] = self.env['ANSIBLE_STDOUT_CALLBACK'] if 'AD_HOC_COMMAND_ID' in self.env: self.env['ANSIBLE_STDOUT_CALLBACK'] = 'minimal' else: diff --git a/test/data/README.md b/test/data/README.md new file mode 100644 index 000000000..0d6fcd329 --- /dev/null +++ b/test/data/README.md @@ -0,0 +1,15 @@ +### Ansible Runner Test Data Directories + +Subfolders in this directory should contain test cases in the form of +runner input directories. + +If running from the top level of the ansible-runner directory, several +of these cases should be something which can be manually tested by the CLI +invocation. + +``` +ansible-runner run test/data/misc/ -p use_role.yml +``` + +The `misc` case is intended to hold playbooks and roles that do not require +any environment changes that would interfere with other playbooks. diff --git a/test/integration/inventory/localhost b/test/data/aggregate_callback/inventory/localhost similarity index 100% rename from test/integration/inventory/localhost rename to test/data/aggregate_callback/inventory/localhost diff --git a/test/integration/callback/other_callback.py b/test/data/aggregate_callback/project/callback_plugins/other_callback.py similarity index 72% rename from test/integration/callback/other_callback.py rename to test/data/aggregate_callback/project/callback_plugins/other_callback.py index 79cbb5eae..439382e20 100644 --- a/test/integration/callback/other_callback.py +++ b/test/data/aggregate_callback/project/callback_plugins/other_callback.py @@ -7,8 +7,8 @@ class CallbackModule(CallbackBase): CALLBACK_NAME = 'other_callback' def v2_playbook_on_play_start(self, play): - pass + self._display.display(u"ready_set_play_start") def v2_runner_on_ok(self, result): - pass + self._display.display(u"ready_set_on_ok") diff --git a/test/data/aggregate_callback/project/debug.yml b/test/data/aggregate_callback/project/debug.yml new file mode 100644 index 000000000..e25d320e3 --- /dev/null +++ b/test/data/aggregate_callback/project/debug.yml @@ -0,0 +1,6 @@ +--- +- hosts: all + gather_facts: false + connection: local + tasks: + - debug: msg="hello" diff --git a/test/data/callback_options/env/envvars b/test/data/callback_options/env/envvars new file mode 100644 index 000000000..206b7f56a --- /dev/null +++ b/test/data/callback_options/env/envvars @@ -0,0 +1,2 @@ +--- +ANSIBLE_DISPLAY_SKIPPED_HOSTS: false diff --git a/test/data/callback_options/inventory/hosts b/test/data/callback_options/inventory/hosts new file mode 100644 index 000000000..f75dc72da --- /dev/null +++ b/test/data/callback_options/inventory/hosts @@ -0,0 +1,9 @@ +6_rescued +7_unreachable + +[consolidated] +1_ok +2_skipped +3_changed +4_failed +5_ignored diff --git a/test/data/callback_options/project/task_status.yml b/test/data/callback_options/project/task_status.yml new file mode 100644 index 000000000..ad733ce3f --- /dev/null +++ b/test/data/callback_options/project/task_status.yml @@ -0,0 +1,37 @@ +--- +- hosts: consolidated + gather_facts: false + connection: local + name: Use debug task to produce different status for several hosts + tasks: + - name: This task gives ok/changed/skipped/failed/ignored depending on host + debug: + msg: "Playing {{ ansible_host }}" + when: "'_skipped' not in ansible_host" + changed_when: "'_changed' in ansible_host" + failed_when: "('_failed' in ansible_host) or ('_ignored' in ansible_host)" + ignore_errors: "{{'_ignored' in ansible_host}}" + +- hosts: 6_rescued + gather_facts: false + connection: local + name: Target the rescue host in separate play in order to fail and rescue + tasks: + + - name: Fail so that rescue task will be activated + block: + - fail: + msg: "HALP!!!" + rescue: + - name: This is the rescue task + debug: msg="ε-(´・`) フ" + +- hosts: 7_unreachable + gather_facts: false + name: Target unreachable hosts in order to get unreachable status + tasks: + + - name: Reach out to the unreachable host + ping: + vars: + ansible_host: 'invalid.invalid' diff --git a/test/data/display_callback/env/envvars b/test/data/display_callback/env/envvars new file mode 100644 index 000000000..87ca0112a --- /dev/null +++ b/test/data/display_callback/env/envvars @@ -0,0 +1,2 @@ +--- +ANSIBLE_STDOUT_CALLBACK: selective diff --git a/test/data/display_callback/inventory/hosts b/test/data/display_callback/inventory/hosts new file mode 100644 index 000000000..f75dc72da --- /dev/null +++ b/test/data/display_callback/inventory/hosts @@ -0,0 +1,9 @@ +6_rescued +7_unreachable + +[consolidated] +1_ok +2_skipped +3_changed +4_failed +5_ignored diff --git a/test/data/display_callback/project/task_status.yml b/test/data/display_callback/project/task_status.yml new file mode 100644 index 000000000..ad733ce3f --- /dev/null +++ b/test/data/display_callback/project/task_status.yml @@ -0,0 +1,37 @@ +--- +- hosts: consolidated + gather_facts: false + connection: local + name: Use debug task to produce different status for several hosts + tasks: + - name: This task gives ok/changed/skipped/failed/ignored depending on host + debug: + msg: "Playing {{ ansible_host }}" + when: "'_skipped' not in ansible_host" + changed_when: "'_changed' in ansible_host" + failed_when: "('_failed' in ansible_host) or ('_ignored' in ansible_host)" + ignore_errors: "{{'_ignored' in ansible_host}}" + +- hosts: 6_rescued + gather_facts: false + connection: local + name: Target the rescue host in separate play in order to fail and rescue + tasks: + + - name: Fail so that rescue task will be activated + block: + - fail: + msg: "HALP!!!" + rescue: + - name: This is the rescue task + debug: msg="ε-(´・`) フ" + +- hosts: 7_unreachable + gather_facts: false + name: Target unreachable hosts in order to get unreachable status + tasks: + + - name: Reach out to the unreachable host + ping: + vars: + ansible_host: 'invalid.invalid' diff --git a/test/data/display_callback_options/env/envvars b/test/data/display_callback_options/env/envvars new file mode 100644 index 000000000..9cf9410a8 --- /dev/null +++ b/test/data/display_callback_options/env/envvars @@ -0,0 +1,4 @@ +--- +ANSIBLE_STDOUT_CALLBACK: selective +# Setting the nocolor option should control whether the output is colorized +ANSIBLE_NOCOLOR: true diff --git a/test/data/display_callback_options/inventory/hosts b/test/data/display_callback_options/inventory/hosts new file mode 100644 index 000000000..f75dc72da --- /dev/null +++ b/test/data/display_callback_options/inventory/hosts @@ -0,0 +1,9 @@ +6_rescued +7_unreachable + +[consolidated] +1_ok +2_skipped +3_changed +4_failed +5_ignored diff --git a/test/data/display_callback_options/project/task_status.yml b/test/data/display_callback_options/project/task_status.yml new file mode 100644 index 000000000..ad733ce3f --- /dev/null +++ b/test/data/display_callback_options/project/task_status.yml @@ -0,0 +1,37 @@ +--- +- hosts: consolidated + gather_facts: false + connection: local + name: Use debug task to produce different status for several hosts + tasks: + - name: This task gives ok/changed/skipped/failed/ignored depending on host + debug: + msg: "Playing {{ ansible_host }}" + when: "'_skipped' not in ansible_host" + changed_when: "'_changed' in ansible_host" + failed_when: "('_failed' in ansible_host) or ('_ignored' in ansible_host)" + ignore_errors: "{{'_ignored' in ansible_host}}" + +- hosts: 6_rescued + gather_facts: false + connection: local + name: Target the rescue host in separate play in order to fail and rescue + tasks: + + - name: Fail so that rescue task will be activated + block: + - fail: + msg: "HALP!!!" + rescue: + - name: This is the rescue task + debug: msg="ε-(´・`) フ" + +- hosts: 7_unreachable + gather_facts: false + name: Target unreachable hosts in order to get unreachable status + tasks: + + - name: Reach out to the unreachable host + ping: + vars: + ansible_host: 'invalid.invalid' diff --git a/test/data/misc/inventory/localhost b/test/data/misc/inventory/localhost new file mode 100644 index 000000000..df8b5f69d --- /dev/null +++ b/test/data/misc/inventory/localhost @@ -0,0 +1,2 @@ +[all] +localhost ansible_connection=local diff --git a/test/integration/project/hello.yml b/test/data/misc/project/hello.yml similarity index 100% rename from test/integration/project/hello.yml rename to test/data/misc/project/hello.yml diff --git a/test/integration/project/roles/benthomasson.hello_role/meta/.galaxy_install_info b/test/data/misc/project/roles/benthomasson.hello_role/meta/.galaxy_install_info similarity index 100% rename from test/integration/project/roles/benthomasson.hello_role/meta/.galaxy_install_info rename to test/data/misc/project/roles/benthomasson.hello_role/meta/.galaxy_install_info diff --git a/test/integration/project/roles/benthomasson.hello_role/meta/main.yml b/test/data/misc/project/roles/benthomasson.hello_role/meta/main.yml similarity index 100% rename from test/integration/project/roles/benthomasson.hello_role/meta/main.yml rename to test/data/misc/project/roles/benthomasson.hello_role/meta/main.yml diff --git a/test/integration/project/roles/benthomasson.hello_role/tasks/main.yml b/test/data/misc/project/roles/benthomasson.hello_role/tasks/main.yml similarity index 100% rename from test/integration/project/roles/benthomasson.hello_role/tasks/main.yml rename to test/data/misc/project/roles/benthomasson.hello_role/tasks/main.yml diff --git a/test/integration/project/use_role.yml b/test/data/misc/project/use_role.yml similarity index 100% rename from test/integration/project/use_role.yml rename to test/data/misc/project/use_role.yml diff --git a/test/integration/conftest.py b/test/integration/conftest.py index d6986bc1a..900b9fe5b 100644 --- a/test/integration/conftest.py +++ b/test/integration/conftest.py @@ -1,3 +1,5 @@ +import os + import pytest import pexpect from ansible_runner.runner_config import RunnerConfig @@ -18,3 +20,10 @@ def rc(request, tmpdir): rc.pexpect_timeout = .1 rc.pexpect_use_poll = True return rc + + +@pytest.fixture +def data_directory(): + integration_base = os.path.split(__file__)[0] + test_base = os.path.split(integration_base)[0] + return os.path.join(test_base, 'data') diff --git a/test/integration/test_display_callback.py b/test/integration/test_display_callback.py index fbf8796de..cd3f7a12d 100644 --- a/test/integration/test_display_callback.py +++ b/test/integration/test_display_callback.py @@ -66,11 +66,7 @@ def executor(tmpdir, request): var: results '''}, # noqa ]) -@pytest.mark.parametrize('envvars', [ - {'ANSIBLE_CALLBACK_PLUGINS': os.path.join(HERE, 'callback')}, - {'ANSIBLE_CALLBACK_PLUGINS': ''} -]) -def test_callback_plugin_receives_events(executor, event, playbook, envvars): +def test_callback_plugin_receives_events(executor, event, playbook): executor.run() assert len(list(executor.events)) assert event in [task['event'] for task in executor.events] diff --git a/test/integration/test_events.py b/test/integration/test_events.py index ae4d10181..552f228f7 100644 --- a/test/integration/test_events.py +++ b/test/integration/test_events.py @@ -102,10 +102,11 @@ def test_playbook_on_stats_summary_fields(rc): assert set(fields) >= set(EXPECTED_SUMMARY_FIELDS) -def test_include_role_events(): +def test_include_role_events(data_directory): + data_dir = os.path.join(data_directory, 'misc') try: r = run( - private_data_dir=os.path.abspath('test/integration'), + private_data_dir=data_dir, playbook='use_role.yml' ) role_events = [event for event in r.events if event.get('event_data', {}).get('role', '') == "benthomasson.hello_role"] @@ -116,7 +117,58 @@ def test_include_role_events(): if event['event'] == 'runner_on_ok': assert event_data['res']['msg'] == 'Hello world!' finally: - shutil.rmtree('test/integration/artifacts') + shutil.rmtree(os.path.join(data_dir, 'artifacts')) + + +def test_use_aggregate_callback(data_directory): + data_dir = os.path.join(data_directory, 'aggregate_callback') + try: + r = run( + private_data_dir=data_dir, + playbook='debug.yml' + ) + stdout = '\n'.join([event['stdout'] for event in r.events]) + assert 'ready_set_play_start' in stdout + assert 'ready_set_on_ok' in stdout + finally: + shutil.rmtree(os.path.join(data_dir, 'artifacts')) + + +def test_hide_skipped_tasks(data_directory): + data_dir = os.path.join(data_directory, 'callback_options') + try: + r = run(private_data_dir=data_dir, playbook='task_status.yml') + stdout = '\n'.join([event['stdout'] for event in r.events]) + # skipped tasks should not be shown + assert 'skipping:' not in stdout + finally: + shutil.rmtree(os.path.join(data_dir, 'artifacts')) + + +def test_use_display_callback(data_directory): + data_dir = os.path.join(data_directory, 'display_callback') + try: + r = run(private_data_dir=data_dir, playbook='task_status.yml') + stdout = '\n'.join([event['stdout'] for event in r.events]) + # the task names should not be displayed in output (due to use of "selective" callback) + assert 'Use debug task to produce different status for several hosts' not in stdout + # callback should print stuff in blue color too + assert '\u001b' in stdout or '\x1b' in stdout + finally: + shutil.rmtree(os.path.join(data_dir, 'artifacts')) + + +def test_use_display_callback_with_option(data_directory): + data_dir = os.path.join(data_directory, 'display_callback_options') + try: + r = run(private_data_dir=data_dir, playbook='task_status.yml') + # with this option set, callback should not print anything in blue color + stdout = '\n'.join([event['stdout'] for event in r.events]) + assert 'Use debug task to produce different status for several hosts' not in stdout + assert '\u001b' not in stdout and '\x1b' not in stdout + finally: + shutil.rmtree(os.path.join(data_dir, 'artifacts')) + @pytest.mark.skipif(find_executable('cgexec') is None, reason="cgexec not available") diff --git a/test/integration/test_main.py b/test/integration/test_main.py index 08ee8a26e..0cee741d7 100644 --- a/test/integration/test_main.py +++ b/test/integration/test_main.py @@ -15,8 +15,6 @@ from ansible_runner.exceptions import AnsibleRunnerException -HERE = os.path.abspath(os.path.dirname(__file__)) - def ensure_directory(directory): if not os.path.exists(directory): @@ -113,46 +111,46 @@ def test_module_run_clean(): assert rc == 0 -def test_role_run(): +def test_role_run(data_directory): rc = main(['-r', 'benthomasson.hello_role', '--hosts', 'localhost', '--roles-path', 'test/integration/roles', 'run', - "test/integration"]) + os.path.join(data_directory, 'misc')]) assert rc == 0 ensure_removed("test/integration/artifacts") -def test_role_run_abs(): - with temp_directory() as temp_dir: +def test_role_run_abs(data_directory): + with temp_directory(): rc = main(['-r', 'benthomasson.hello_role', '--hosts', 'localhost', - '--roles-path', os.path.join(HERE, 'project/roles'), + '--roles-path', os.path.join(data_directory, 'misc', 'project/roles'), 'run', - temp_dir]) + os.path.join(data_directory, 'misc')]) assert rc == 0 -def test_role_logfile(): +def test_role_logfile(data_directory): try: rc = main(['-r', 'benthomasson.hello_role', '--hosts', 'localhost', '--roles-path', 'test/integration/project/roles', '--logfile', 'new_logfile', 'run', - 'test/integration']) + os.path.join(data_directory, 'misc')]) assert os.path.exists('new_logfile') assert rc == 0 finally: - ensure_removed("test/integration/artifacts") + ensure_removed(os.path.join(data_directory, 'misc', 'artifacts')) -def test_role_logfile_abs(): +def test_role_logfile_abs(data_directory): try: with temp_directory() as temp_dir: rc = main(['-r', 'benthomasson.hello_role', '--hosts', 'localhost', - '--roles-path', os.path.join(HERE, 'project/roles'), + '--roles-path', os.path.join(data_directory, 'misc', 'project', 'roles'), '--logfile', 'new_logfile', 'run', temp_dir]) @@ -162,7 +160,7 @@ def test_role_logfile_abs(): ensure_removed("new_logfile") -def test_role_bad_project_dir(): +def test_role_bad_project_dir(data_directory): with open("bad_project_dir", 'w') as f: f.write('not a directory') @@ -171,7 +169,7 @@ def test_role_bad_project_dir(): with pytest.raises(OSError): main(['-r', 'benthomasson.hello_role', '--hosts', 'localhost', - '--roles-path', os.path.join(HERE, 'project/roles'), + '--roles-path', os.path.join(data_directory, 'misc', 'project', 'roles'), '--logfile', 'new_logfile', 'run', 'bad_project_dir']) @@ -180,44 +178,44 @@ def test_role_bad_project_dir(): ensure_removed("new_logfile") -def test_role_run_clean(): +def test_role_run_clean(data_directory): rc = main(['-r', 'benthomasson.hello_role', '--hosts', 'localhost', - '--roles-path', 'test/integration/roles', + '--roles-path', os.path.join(data_directory, 'misc', 'project', 'roles'), 'run', - "test/integration"]) + os.path.join(data_directory, 'misc')]) assert rc == 0 - ensure_removed("test/integration/artifacts") + ensure_removed(os.path.join(data_directory, 'misc', 'artifacts')) -def test_role_run_cmd_line_abs(): +def test_role_run_cmd_line_abs(data_directory): with temp_directory() as temp_dir: rc = main(['-r', 'benthomasson.hello_role', '--hosts', 'localhost', - '--roles-path', os.path.join(HERE, 'project/roles'), + '--roles-path', os.path.join(data_directory, 'misc', 'project', 'roles'), 'run', temp_dir]) assert rc == 0 -def test_role_run_artifacts_dir(): +def test_role_run_artifacts_dir(data_directory): rc = main(['-r', 'benthomasson.hello_role', '--hosts', 'localhost', - '--roles-path', 'test/integration/roles', + '--roles-path', os.path.join(data_directory, 'misc', 'project', 'roles'), '--artifact-dir', 'otherartifacts', 'run', - "test/integration"]) + os.path.join(data_directory, 'misc')]) assert rc == 0 - ensure_removed("test/integration/artifacts") + ensure_removed(os.path.join(data_directory, 'misc', 'artifacts')) -def test_role_run_artifacts_dir_abs(): +def test_role_run_artifacts_dir_abs(data_directory): try: with temp_directory() as temp_dir: rc = main(['-r', 'benthomasson.hello_role', '--hosts', 'localhost', - '--roles-path', os.path.join(HERE, 'project/roles'), + '--roles-path', os.path.join(data_directory, 'misc', 'project', 'roles'), '--artifact-dir', 'otherartifacts', 'run', temp_dir]) @@ -234,7 +232,7 @@ def test_role_run_artifacts_dir_abs(): u'蔆㪗輥': u'䉪ቒ칸' } ]) -def test_role_run_env_vars(envvars): +def test_role_run_env_vars(envvars, data_directory): with temp_directory() as temp_dir: ensure_directory(os.path.join(temp_dir, 'env')) @@ -243,82 +241,87 @@ def test_role_run_env_vars(envvars): rc = main(['-r', 'benthomasson.hello_role', '--hosts', 'localhost', - '--roles-path', os.path.join(HERE, 'project/roles'), + '--roles-path', os.path.join(data_directory, 'misc', 'project', 'roles'), 'run', temp_dir]) assert rc == 0 -def test_role_run_args(): +def test_role_run_args(data_directory): with temp_directory() as temp_dir: rc = main(['-r', 'benthomasson.hello_role', '--hosts', 'localhost', - '--roles-path', os.path.join(HERE, 'project/roles'), + '--roles-path', os.path.join(data_directory, 'misc', 'project', 'roles'), '--role-vars', 'msg=hi', 'run', temp_dir]) assert rc == 0 -def test_role_run_inventory(): +def test_role_run_inventory(data_directory): with temp_directory() as temp_dir: ensure_directory(os.path.join(temp_dir, 'inventory')) - shutil.copy(os.path.join(HERE, 'inventory/localhost'), os.path.join(temp_dir, 'inventory/localhost')) + shutil.copy( + os.path.join(data_directory, 'misc', 'inventory', 'localhost'), + os.path.join(temp_dir, 'inventory/localhost')) rc = main(['-r', 'benthomasson.hello_role', '--hosts', 'localhost', - '--roles-path', os.path.join(HERE, 'project/roles'), + '--roles-path', os.path.join(data_directory, 'misc', 'project', 'roles'), '--inventory', 'localhost', 'run', temp_dir]) assert rc == 0 -def test_role_run_inventory_missing(): +def test_role_run_inventory_missing(data_directory): with temp_directory() as temp_dir: ensure_directory(os.path.join(temp_dir, 'inventory')) - shutil.copy(os.path.join(HERE, 'inventory/localhost'), os.path.join(temp_dir, 'inventory/localhost')) + shutil.copy( + os.path.join(data_directory, 'misc', 'inventory/localhost'), + os.path.join(temp_dir, 'inventory/localhost')) with pytest.raises(AnsibleRunnerException): main(['-r', 'benthomasson.hello_role', '--hosts', 'localhost', - '--roles-path', os.path.join(HERE, 'project/roles'), + '--roles-path', os.path.join(data_directory, 'misc', 'project', 'roles'), '--inventory', 'does_not_exist', 'run', temp_dir]) -def test_role_start(): +def test_role_start(data_directory): with temp_directory() as temp_dir: p = multiprocessing.Process(target=main, args=[['-r', 'benthomasson.hello_role', '--hosts', 'localhost', - '--roles-path', os.path.join(HERE, 'project/roles'), + '--roles-path', os.path.join(data_directory, 'misc', 'project', 'roles'), 'start', temp_dir]]) p.start() p.join() -def test_playbook_start(): +def test_playbook_start(data_directory): + data_dir = os.path.join(data_directory, 'misc') with temp_directory() as temp_dir: project_dir = os.path.join(temp_dir, 'project') ensure_directory(project_dir) - shutil.copy(os.path.join(HERE, 'project/hello.yml'), project_dir) + shutil.copy(os.path.join(data_dir, 'project/hello.yml'), project_dir) ensure_directory(os.path.join(temp_dir, 'inventory')) - shutil.copy(os.path.join(HERE, 'inventory/localhost'), os.path.join(temp_dir, 'inventory/localhost')) + shutil.copy(os.path.join(data_dir, 'inventory/localhost'), os.path.join(temp_dir, 'inventory/localhost')) # privateip: removed --hosts command line option from test beause it is # not a supported combination of cli options p = multiprocessing.Process(target=main, args=[['-p', 'hello.yml', - '--inventory', os.path.join(HERE, 'inventory/localhost'), + '--inventory', os.path.join(data_dir, 'inventory/localhost'), #'--hosts', 'localhost', 'start', temp_dir]])