# -*- coding: utf-8 -*- import json import os import re import pytest import six import sys try: from unittest.mock import MagicMock except ImportError: from unittest.mock import MagicMock from ansible_runner import Runner from ansible_runner.exceptions import AnsibleRunnerException @pytest.mark.serial def test_password_prompt(rc): rc.command = [sys.executable, '-c' 'import time; print(input("Password: "))'] rc.expect_passwords[re.compile(r'Password:\s*?$', re.M)] = '1234' status, exitcode = Runner(config=rc).run() assert status == 'successful' assert exitcode == 0 with open(os.path.join(rc.artifact_dir, 'stdout')) as f: assert '1234' in f.read() def test_run_command(rc): rc.command = ['sleep', '1'] status, exitcode = Runner(config=rc).run() assert status == 'successful' assert exitcode == 0 with open(os.path.join(rc.artifact_dir, 'command')) as f: data = json.load(f) assert data.get('command') == ['sleep','1'] assert 'cwd' in data assert isinstance(data.get('env'), dict) def test_run_command_with_unicode(rc): expected = '"utf-8-䉪ቒ칸ⱷ?噂폄蔆㪗輥"' if six.PY2: expected = expected.decode('utf-8') rc.command = ['echo', '"utf-8-䉪ቒ칸ⱷ?噂폄蔆㪗輥"'] rc.envvars = {"䉪ቒ칸": "蔆㪗輥"} rc.prepare_env() status, exitcode = Runner(config=rc).run() assert status == 'successful' assert exitcode == 0 with open(os.path.join(rc.artifact_dir, 'command')) as f: data = json.load(f) assert data.get('command') == ['echo', expected] assert 'cwd' in data assert isinstance(data.get('env'), dict) assert u"䉪ቒ칸" in data.get('env') def test_run_command_finished_callback(rc): finished_callback = MagicMock() rc.command = ['sleep','1'] runner = Runner(config=rc, finished_callback=finished_callback) status, exitcode = runner.run() assert status == 'successful' assert exitcode == 0 finished_callback.assert_called_with(runner) def test_run_command_explosive_finished_callback(rc): def boom(*args): raise Exception('boom') rc.command = ['sleep','1'] runner = Runner(config=rc, finished_callback=boom) with pytest.raises(Exception): runner.run() def test_run_command_explosive_cancel_callback(rc): def boom(*args): raise Exception('boom') rc.command = ['sleep','1'] runner = Runner(config=rc, cancel_callback=boom) with pytest.raises(Exception): runner.run() def test_run_command_cancel_callback(rc): def cancel(*args): return True rc.command = ['sleep','1'] runner = Runner(config=rc, cancel_callback=cancel) status, exitcode = runner.run() assert status == 'canceled' assert exitcode == 254 def test_run_command_job_timeout(rc): rc.command = ['sleep', '1'] rc.job_timeout = 0.0000001 runner = Runner(config=rc) status, exitcode = runner.run() assert status == 'timeout' assert exitcode == 254 def test_run_command_idle_timeout(rc): rc.command = ['sleep', '1'] rc.idle_timeout = 0.0000001 runner = Runner(config=rc) status, exitcode = runner.run() assert status == 'timeout' assert exitcode == 254 def test_run_command_failed(rc): rc.command = ['false'] runner = Runner(config=rc) status, exitcode = runner.run() assert status == 'failed' assert exitcode == 1 def test_executable_not_found(rc): rc.command = ['supercalifragilistic'] runner = Runner(config=rc) status, exitcode = runner.run() assert status == 'failed' assert exitcode == 127 events = list(runner.events) assert len(events) == 1 assert 'The command was not found or was not executable: supercalifragilistic' in events[0]['stdout'] # noqa def test_run_command_long_running(rc): rc.command = ['yes'] runner = Runner(config=rc) status, exitcode = runner.run() assert status == 'timeout' assert exitcode == 254 def test_run_command_long_running_children(rc): rc.command = ['bash', '-c', "(yes)"] runner = Runner(config=rc) status, exitcode = runner.run() assert status == 'timeout' assert exitcode == 254 def test_run_command_events_missing(rc): rc.command = ['sleep','1'] runner = Runner(config=rc) status, exitcode = runner.run() assert status == 'successful' assert exitcode == 0 assert list(runner.events) == [] def test_run_command_stdout_missing(rc): rc.command = ['sleep','1'] runner = Runner(config=rc) status, exitcode = runner.run() assert status == 'successful' assert exitcode == 0 os.unlink(os.path.join(runner.config.artifact_dir, 'stdout')) with pytest.raises(AnsibleRunnerException): list(runner.stdout) def test_run_command_no_stats(rc): rc.command = ['sleep','1'] runner = Runner(config=rc) status, exitcode = runner.run() assert status == 'successful' assert exitcode == 0 assert runner.stats is None def test_run_command_ansible(rc): rc.module = "debug" rc.host_pattern = "localhost" rc.prepare() runner = Runner(config=rc) status, exitcode = runner.run() assert status == 'successful' assert exitcode == 0 assert list(runner.events) != [] assert runner.stats != {} assert list(runner.host_events('localhost')) != [] stdout = runner.stdout assert stdout.read() != "" def test_run_command_ansible_event_handler(rc): event_handler = MagicMock() status_handler = MagicMock() rc.module = "debug" rc.host_pattern = "localhost" rc.prepare() runner = Runner(config=rc, event_handler=event_handler, status_handler=status_handler) status, exitcode = runner.run() assert status == 'successful' assert exitcode == 0 event_handler.assert_called() status_handler.assert_called() def test_run_command_ansible_event_handler_failure(rc): def event_handler(*args): raise IOError() rc.module = "debug" rc.host_pattern = "localhost" rc.prepare() runner = Runner(config=rc, event_handler=event_handler) status, exitcode = runner.run() assert status == 'successful' assert exitcode == 0 def test_run_command_ansible_rotate_artifacts(rc): rc.module = "debug" rc.host_pattern = "localhost" rc.prepare() rc.rotate_artifacts = 1 runner = Runner(config=rc) status, exitcode = runner.run() assert status == 'successful' assert exitcode == 0 runner = Runner(config=rc) status, exitcode = runner.run() assert status == 'successful' assert exitcode == 0 def test_get_fact_cache(rc): assert os.path.basename(rc.fact_cache) == 'fact_cache' rc.module = "setup" rc.host_pattern = "localhost" rc.prepare() runner = Runner(config=rc) status, exitcode = runner.run() assert status == 'successful' assert exitcode == 0 print(rc.cwd) assert os.path.exists(os.path.join(rc.artifact_dir, 'fact_cache')) assert os.path.exists(os.path.join(rc.artifact_dir, 'fact_cache', 'localhost')) data = runner.get_fact_cache('localhost') assert data def test_set_fact_cache(rc): assert os.path.basename(rc.fact_cache) == 'fact_cache' rc.module = "debug" rc.module_args = "var=message" rc.host_pattern = "localhost" rc.prepare() runner = Runner(config=rc) runner.set_fact_cache('localhost', dict(message='hello there')) status, exitcode = runner.run() assert status == 'successful' assert exitcode == 0 print(rc.cwd) assert os.path.exists(os.path.join(rc.artifact_dir, 'fact_cache')) assert os.path.exists(os.path.join(rc.artifact_dir, 'fact_cache', 'localhost')) data = runner.get_fact_cache('localhost') assert data['message'] == 'hello there' def test_set_extra_vars(rc): rc.module = "debug" rc.module_args = "var=test_extra_vars" rc.host_pattern = "localhost" rc.extra_vars = dict(test_extra_vars='hello there') rc.prepare() runner = Runner(config=rc) status, exitcode = runner.run() with open(os.path.join(rc.artifact_dir, 'stdout')) as f: assert 'hello there' in f.read()