ansible-runner/test/integration/test_main.py
2021-03-03 11:36:53 +08:00

328 lines
10 KiB
Python

# -*- coding: utf-8 -*-
from __future__ import print_function
from ansible_runner.__main__ import main
import os
import codecs
import multiprocessing
import shutil
import yaml
import tempfile
import time
from contextlib import contextmanager
import pytest
from ansible_runner.exceptions import AnsibleRunnerException
HERE = os.path.abspath(os.path.dirname(__file__))
def ensure_directory(directory):
if not os.path.exists(directory):
os.makedirs(directory)
def ensure_removed(path):
if os.path.exists(path):
if os.path.isfile(path):
os.unlink(path)
elif os.path.isdir(path):
shutil.rmtree(path)
@contextmanager
def temp_directory(files=None):
temp_dir = tempfile.mkdtemp()
print(temp_dir)
try:
yield temp_dir
shutil.rmtree(temp_dir)
except BaseException:
if files is not None:
for file in files:
if os.path.exists(file):
with open(file) as f:
print(f.read())
raise
def test_temp_directory():
context = dict()
def will_fail():
with temp_directory() as temp_dir:
context['saved_temp_dir'] = temp_dir
assert False
def will_pass():
with temp_directory() as temp_dir:
context['saved_temp_dir'] = temp_dir
assert True
with pytest.raises(AssertionError):
will_fail()
assert os.path.exists(context['saved_temp_dir'])
shutil.rmtree(context['saved_temp_dir'])
will_pass()
assert not os.path.exists(context['saved_temp_dir'])
def test_help():
with pytest.raises(SystemExit) as exc:
main([])
assert exc.value.code == 2, 'Should raise SystemExit with return code 2'
def test_module_run():
try:
rc = main(['run', '-m', 'ping',
'--hosts', 'localhost',
'ping'])
assert os.path.exists('./ping')
assert os.path.exists('./ping/artifacts')
assert rc == 0
finally:
if os.path.exists('./ping'):
shutil.rmtree('./ping')
def test_module_run_debug():
try:
rc = main(['run', '-m', 'ping',
'--hosts', 'localhost',
'--debug',
'ping'])
assert os.path.exists('./ping')
assert os.path.exists('./ping/artifacts')
assert rc == 0
finally:
if os.path.exists('./ping'):
shutil.rmtree('./ping')
def test_module_run_clean():
with temp_directory() as temp_dir:
rc = main(['run', '-m', 'ping',
'--hosts', 'localhost',
temp_dir])
assert rc == 0
def test_role_run(skipif_pre_ansible28, clear_integration_artifacts):
rc = main(['run', '-r', 'benthomasson.hello_role',
'--hosts', 'localhost',
'--roles-path', 'test/integration/roles',
"test/integration"])
assert rc == 0
def test_role_run_abs():
with temp_directory() as temp_dir:
rc = main(['run', '-r', 'benthomasson.hello_role',
'--hosts', 'localhost',
'--roles-path', os.path.join(HERE, 'project/roles'),
temp_dir])
assert rc == 0
def test_role_logfile(skipif_pre_ansible28, clear_integration_artifacts):
rc = main(['run', '-r', 'benthomasson.hello_role',
'--hosts', 'localhost',
'--roles-path', 'test/integration/project/roles',
'--logfile', 'new_logfile',
'test/integration'])
assert os.path.exists('new_logfile')
assert rc == 0
def test_role_logfile_abs():
try:
with temp_directory() as temp_dir:
rc = main(['run', '-r', 'benthomasson.hello_role',
'--hosts', 'localhost',
'--roles-path', os.path.join(HERE, 'project/roles'),
'--logfile', 'new_logfile',
temp_dir])
assert os.path.exists('new_logfile')
assert rc == 0
finally:
ensure_removed("new_logfile")
def test_role_bad_project_dir():
with open("bad_project_dir", 'w') as f:
f.write('not a directory')
try:
with pytest.raises(OSError):
main(['run', '-r', 'benthomasson.hello_role',
'--hosts', 'localhost',
'--roles-path', os.path.join(HERE, 'project/roles'),
'--logfile', 'new_logfile',
'bad_project_dir'])
finally:
os.unlink('bad_project_dir')
ensure_removed("new_logfile")
def test_role_run_clean(skipif_pre_ansible28, clear_integration_artifacts):
rc = main(['run', '-r', 'benthomasson.hello_role',
'--hosts', 'localhost',
'--roles-path', 'test/integration/roles',
"test/integration"])
assert rc == 0
def test_role_run_cmd_line_abs():
with temp_directory() as temp_dir:
rc = main(['run', '-r', 'benthomasson.hello_role',
'--hosts', 'localhost',
'--roles-path', os.path.join(HERE, 'project/roles'),
temp_dir])
assert rc == 0
def test_role_run_artifacts_dir(skipif_pre_ansible28, clear_integration_artifacts):
rc = main(['run', '-r', 'benthomasson.hello_role',
'--hosts', 'localhost',
'--roles-path', 'test/integration/roles',
'--artifact-dir', 'otherartifacts',
"test/integration"])
assert rc == 0
def test_role_run_artifacts_dir_abs(skipif_pre_ansible28):
try:
with temp_directory() as temp_dir:
rc = main(['run', '-r', 'benthomasson.hello_role',
'--hosts', 'localhost',
'--roles-path', os.path.join(HERE, 'project/roles'),
'--artifact-dir', 'otherartifacts',
temp_dir])
assert os.path.exists(os.path.join('.', 'otherartifacts'))
assert rc == 0
finally:
shutil.rmtree(os.path.join('.', 'otherartifacts'))
@pytest.mark.parametrize('envvars', [
{'msg': 'hi'},
{
'msg': u'utf-8-䉪ቒ칸ⱷ?噂폄蔆㪗輥',
u'蔆㪗輥': u'䉪ቒ칸'
}],
ids=['regular-text', 'utf-8-text']
)
def test_role_run_env_vars(envvars):
with temp_directory() as temp_dir:
ensure_directory(os.path.join(temp_dir, 'env'))
with codecs.open(os.path.join(temp_dir, 'env/envvars'), 'w', encoding='utf-8') as f:
f.write(yaml.dump(envvars))
rc = main(['run', '-r', 'benthomasson.hello_role',
'--hosts', 'localhost',
'--roles-path', os.path.join(HERE, 'project/roles'),
temp_dir])
assert rc == 0
def test_role_run_args():
with temp_directory() as temp_dir:
rc = main(['run', '-r', 'benthomasson.hello_role',
'--hosts', 'localhost',
'--roles-path', os.path.join(HERE, 'project/roles'),
'--role-vars', 'msg=hi',
temp_dir])
assert rc == 0
def test_role_run_inventory(is_pre_ansible28):
inv = 'inventory/localhost_preansible28' if is_pre_ansible28 else 'inventory/localhost'
with temp_directory() as temp_dir:
ensure_directory(os.path.join(temp_dir, 'inventory'))
shutil.copy(os.path.join(HERE, inv), os.path.join(temp_dir, 'inventory/localhost'))
rc = main(['run', '-r', 'benthomasson.hello_role',
'--hosts', 'localhost',
'--roles-path', os.path.join(HERE, 'project/roles'),
'--inventory', os.path.join(temp_dir, 'inventory/localhost'),
temp_dir])
assert rc == 0
def test_role_run_inventory_missing(is_pre_ansible28):
inv = 'inventory/localhost_preansible28' if is_pre_ansible28 else 'inventory/localhost'
with temp_directory() as temp_dir:
ensure_directory(os.path.join(temp_dir, 'inventory'))
shutil.copy(os.path.join(HERE, inv), os.path.join(temp_dir, 'inventory/localhost'))
with pytest.raises(AnsibleRunnerException):
main(['run', '-r', 'benthomasson.hello_role',
'--hosts', 'localhost',
'--roles-path', os.path.join(HERE, 'project/roles'),
'--inventory', 'does_not_exist',
temp_dir])
def test_role_start():
with temp_directory() as temp_dir:
p = multiprocessing.Process(target=main,
args=[['start', '-r', 'benthomasson.hello_role',
'--hosts', 'localhost',
'--roles-path', os.path.join(HERE, 'project/roles'),
temp_dir]])
p.start()
p.join()
def test_playbook_start(skipif_pre_ansible28):
inv = 'inventory/localhost'
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)
ensure_directory(os.path.join(temp_dir, 'inventory'))
shutil.copy(os.path.join(HERE, inv), 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=[['start', '-p', 'hello.yml',
'--inventory', os.path.join(HERE, 'inventory/localhost'),
#'--hosts', 'localhost',
temp_dir]])
p.start()
time.sleep(5)
assert os.path.exists(os.path.join(temp_dir, 'pid'))
rc = main(['is-alive', temp_dir])
assert rc == 0
rc = main(['stop', temp_dir])
assert rc == 0
time.sleep(1)
rc = main(['is-alive', temp_dir])
assert rc == 1
ensure_removed(os.path.join(temp_dir, 'pid'))
rc = main(['stop', temp_dir])
assert rc == 1