250 lines
6.9 KiB
Python
250 lines
6.9 KiB
Python
import os
|
|
import sys
|
|
import uuid
|
|
import json
|
|
import random
|
|
import string
|
|
import tempfile
|
|
import shutil
|
|
|
|
from pytest import raises
|
|
from unittest.mock import patch
|
|
|
|
from ansible_runner.__main__ import main
|
|
|
|
|
|
def random_string():
|
|
return ''.join(random.choice(string.ascii_uppercase + string.digits)
|
|
for _ in range(random.randint(3, 20)))
|
|
|
|
|
|
def random_json(keys=None):
|
|
data = dict()
|
|
if keys:
|
|
for key in keys:
|
|
data[key] = random_string()
|
|
else:
|
|
for _ in range(0, 5):
|
|
data[random_string()] = random_string()
|
|
return json.dumps(data)
|
|
|
|
|
|
def cmdline(command, *args):
|
|
cmdline = ['ansible-runner', command]
|
|
cmdline.extend(args)
|
|
sys.argv = cmdline
|
|
|
|
|
|
def test_main_bad_private_data_dir():
|
|
tmpfile = os.path.join('/tmp', str(uuid.uuid4().hex))
|
|
open(tmpfile, 'w').write(random_string())
|
|
|
|
cmdline('run', tmpfile, '-p', 'fake')
|
|
|
|
try:
|
|
with raises(OSError):
|
|
main()
|
|
finally:
|
|
os.remove(tmpfile)
|
|
|
|
|
|
def run_role(options, private_data_dir=None, expected_rc=0):
|
|
try:
|
|
private_data_dir = private_data_dir or tempfile.mkdtemp()
|
|
args = ['run', private_data_dir]
|
|
args.extend(options)
|
|
|
|
with patch('ansible_runner.interface.run') as mock_run:
|
|
with raises(SystemExit) as exc:
|
|
main()
|
|
assert exc.type == SystemExit
|
|
assert exc.value.code == expected_rc
|
|
|
|
finally:
|
|
shutil.rmtree(private_data_dir)
|
|
return mock_run
|
|
|
|
|
|
def test_cmdline_role_defaults():
|
|
"""Run a role directly with all command line defaults
|
|
"""
|
|
private_data_dir = tempfile.mkdtemp()
|
|
options = ['-r' , 'test']
|
|
|
|
playbook = [{'hosts': 'all', 'gather_facts': True, 'roles': [{'role': 'test'}]}]
|
|
|
|
run_options = {
|
|
'private_data_dir': private_data_dir,
|
|
'playbook': playbook
|
|
}
|
|
|
|
result = run_role(options, private_data_dir)
|
|
result.called_with_args([run_options])
|
|
|
|
|
|
def test_cmdline_role_skip_facts():
|
|
"""Run a role directly and set --role-skip-facts option
|
|
"""
|
|
private_data_dir = tempfile.mkdtemp()
|
|
options = ['-r' , 'test', '--role-skip-facts']
|
|
|
|
playbook = [{'hosts': 'all', 'gather_facts': False, 'roles': [{'role': 'test'}]}]
|
|
|
|
run_options = {
|
|
'private_data_dir': private_data_dir,
|
|
'playbook': playbook
|
|
}
|
|
|
|
result = run_role(options, private_data_dir)
|
|
result.called_with_args([run_options])
|
|
|
|
|
|
def test_cmdline_role_inventory():
|
|
"""Run a role directly and set --inventory option
|
|
"""
|
|
private_data_dir = tempfile.mkdtemp()
|
|
options = ['-r' , 'test', '--inventory hosts']
|
|
|
|
playbook = [{'hosts': 'all', 'gather_facts': False, 'roles': [{'role': 'test'}]}]
|
|
|
|
run_options = {
|
|
'private_data_dir': private_data_dir,
|
|
'playbook': playbook,
|
|
'inventory': 'hosts'
|
|
}
|
|
|
|
result = run_role(options, private_data_dir)
|
|
result.called_with_args([run_options])
|
|
|
|
|
|
def test_cmdline_role_vars():
|
|
"""Run a role directly and set --role-vars option
|
|
"""
|
|
private_data_dir = tempfile.mkdtemp()
|
|
options = ['-r' , 'test', '--role-vars "foo=bar"']
|
|
|
|
playbook = [{
|
|
'hosts': 'all',
|
|
'gather_facts': False,
|
|
'roles': [{
|
|
'role': 'test',
|
|
'vars': {'foo': 'bar'}
|
|
}]
|
|
}]
|
|
|
|
run_options = {
|
|
'private_data_dir': private_data_dir,
|
|
'playbook': playbook
|
|
}
|
|
|
|
result = run_role(options, private_data_dir)
|
|
result.called_with_args([run_options])
|
|
|
|
|
|
def test_cmdline_roles_path():
|
|
"""Run a role directly and set --roles-path option
|
|
"""
|
|
private_data_dir = tempfile.mkdtemp()
|
|
options = ['-r' , 'test', '--roles-path /tmp/roles']
|
|
|
|
playbook = [{'hosts': 'all', 'gather_facts': False, 'roles': [{'role': 'test'}]}]
|
|
|
|
run_options = {
|
|
'private_data_dir': private_data_dir,
|
|
'playbook': playbook,
|
|
'envvars': {'ANSIBLE_ROLES_PATH': '/tmp/roles'}
|
|
}
|
|
|
|
result = run_role(options, private_data_dir)
|
|
result.called_with_args([run_options])
|
|
|
|
|
|
def test_cmdline_role_with_playbook_option():
|
|
"""Test error is raised with invalid command line option '-p'
|
|
"""
|
|
cmdline('run', 'private_data_dir', '-r', 'fake', '-p', 'fake')
|
|
with raises(SystemExit) as exc:
|
|
main()
|
|
assert exc == 1
|
|
|
|
|
|
def test_cmdline_playbook(is_pre_ansible28):
|
|
try:
|
|
private_data_dir = tempfile.mkdtemp()
|
|
play = [{'hosts': 'all', 'tasks': [{'debug': {'msg': random_string()}}]}]
|
|
|
|
path = os.path.join(private_data_dir, 'project')
|
|
os.makedirs(path)
|
|
|
|
playbook = os.path.join(path, 'main.yaml')
|
|
with open(playbook, 'w') as f:
|
|
f.write(json.dumps(play))
|
|
|
|
path = os.path.join(private_data_dir, 'inventory')
|
|
os.makedirs(path)
|
|
|
|
inventory = os.path.join(path, 'hosts')
|
|
with open(inventory, 'w') as f:
|
|
if is_pre_ansible28:
|
|
f.write('[all]\nlocalhost ansible_connection=local ansible_python_interpreter="/usr/bin/env python"')
|
|
else:
|
|
f.write('[all]\nlocalhost ansible_connection=local')
|
|
|
|
cmdline('run', private_data_dir, '-p', playbook, '--inventory', inventory)
|
|
|
|
assert main() == 0
|
|
|
|
with open(playbook) as f:
|
|
assert json.loads(f.read()) == play
|
|
|
|
finally:
|
|
shutil.rmtree(private_data_dir)
|
|
|
|
|
|
def test_cmdline_playbook_hosts():
|
|
"""Test error is raised with trying to pass '--hosts' with '-p'
|
|
"""
|
|
cmdline('run', 'private_data_dir', '-p', 'fake', '--hosts', 'all')
|
|
with raises(SystemExit) as exc:
|
|
main()
|
|
assert exc == 1
|
|
|
|
|
|
def test_cmdline_includes_one_option():
|
|
"""Test error is raised if not '-p', '-m' or '-r'
|
|
"""
|
|
cmdline('run', 'private_data_dir')
|
|
with raises(SystemExit) as exc:
|
|
main()
|
|
assert exc == 1
|
|
|
|
|
|
def test_cmdline_cmdline_override(is_pre_ansible28):
|
|
try:
|
|
private_data_dir = tempfile.mkdtemp()
|
|
play = [{'hosts': 'all', 'tasks': [{'debug': {'msg': random_string()}}]}]
|
|
|
|
path = os.path.join(private_data_dir, 'project')
|
|
os.makedirs(path)
|
|
|
|
playbook = os.path.join(path, 'main.yaml')
|
|
with open(playbook, 'w') as f:
|
|
f.write(json.dumps(play))
|
|
path = os.path.join(private_data_dir, 'inventory')
|
|
os.makedirs(path)
|
|
|
|
inventory = os.path.join(path, 'hosts')
|
|
with open(inventory, 'w') as f:
|
|
if is_pre_ansible28:
|
|
f.write('[all]\nlocalhost ansible_connection=local ansible_python_interpreter="/usr/bin/env python"')
|
|
else:
|
|
f.write('[all]\nlocalhost ansible_connection=local')
|
|
|
|
# privateip: removed --hosts command line option from test beause it is
|
|
# not a supported combination of cli options
|
|
#cmdline('run', private_data_dir, '-p', playbook, '--hosts', 'all', '--cmdline', '-e foo=bar')
|
|
cmdline('run', private_data_dir, '-p', playbook, '--cmdline', '-e foo=bar')
|
|
assert main() == 0
|
|
finally:
|
|
shutil.rmtree(private_data_dir)
|