|
|
|
#!/usr/bin/env python
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
import os
|
|
|
|
import pexpect
|
|
|
|
import sys
|
|
|
|
|
|
|
|
from ansible.module_utils.six import PY2
|
|
|
|
|
|
|
|
if PY2:
|
|
|
|
log_buffer = sys.stdout
|
|
|
|
else:
|
|
|
|
log_buffer = sys.stdout.buffer
|
|
|
|
|
|
|
|
env_vars = {
|
|
|
|
'ANSIBLE_ROLES_PATH': './roles',
|
|
|
|
'ANSIBLE_NOCOLOR': 'True',
|
|
|
|
'ANSIBLE_RETRY_FILES_ENABLED': 'False',
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
def run_test(playbook, test_spec, args=None, timeout=10, env=None):
|
|
|
|
|
|
|
|
if not env:
|
|
|
|
env = os.environ.copy()
|
|
|
|
env.update(env_vars)
|
|
|
|
|
|
|
|
if not args:
|
|
|
|
args = sys.argv[1:]
|
|
|
|
|
|
|
|
vars_prompt_test = pexpect.spawn(
|
|
|
|
'ansible-playbook',
|
|
|
|
args=[playbook] + args,
|
|
|
|
timeout=timeout,
|
|
|
|
env=env,
|
|
|
|
)
|
|
|
|
|
|
|
|
vars_prompt_test.logfile = log_buffer
|
|
|
|
for item in test_spec[0]:
|
|
|
|
vars_prompt_test.expect(item[0])
|
|
|
|
if item[1]:
|
|
|
|
vars_prompt_test.send(item[1])
|
|
|
|
vars_prompt_test.expect(test_spec[1])
|
|
|
|
vars_prompt_test.expect(pexpect.EOF)
|
|
|
|
vars_prompt_test.close()
|
|
|
|
|
|
|
|
|
|
|
|
# These are the tests to run. Each test is a playbook and a test_spec.
|
|
|
|
#
|
|
|
|
# The test_spec is a list with two elements.
|
|
|
|
#
|
|
|
|
# The first element is a list of two element tuples. The first is the regexp to look
|
|
|
|
# for in the output, the second is the line to send.
|
|
|
|
#
|
|
|
|
# The last element is the last string of text to look for in the output.
|
|
|
|
#
|
|
|
|
tests = [
|
|
|
|
# Basic vars_prompt
|
|
|
|
{'playbook': 'vars_prompt-1.yml',
|
|
|
|
'test_spec': [
|
|
|
|
[('input:', 'some input\r')],
|
|
|
|
'"input": "some input"']},
|
|
|
|
|
|
|
|
# Custom prompt
|
|
|
|
{'playbook': 'vars_prompt-2.yml',
|
|
|
|
'test_spec': [
|
|
|
|
[('Enter some input:', 'some more input\r')],
|
|
|
|
'"input": "some more input"']},
|
|
|
|
|
|
|
|
# Test confirm, both correct and incorrect
|
|
|
|
{'playbook': 'vars_prompt-3.yml',
|
|
|
|
'test_spec': [
|
|
|
|
[('input:', 'confirm me\r'),
|
|
|
|
('confirm input:', 'confirm me\r')],
|
|
|
|
'"input": "confirm me"']},
|
|
|
|
|
|
|
|
{'playbook': 'vars_prompt-3.yml',
|
|
|
|
'test_spec': [
|
|
|
|
[('input:', 'confirm me\r'),
|
|
|
|
('confirm input:', 'incorrect\r'),
|
|
|
|
(r'\*\*\*\*\* VALUES ENTERED DO NOT MATCH \*\*\*\*', ''),
|
|
|
|
('input:', 'confirm me\r'),
|
|
|
|
('confirm input:', 'confirm me\r')],
|
|
|
|
'"input": "confirm me"']},
|
|
|
|
|
|
|
|
# Test private
|
|
|
|
{'playbook': 'vars_prompt-4.yml',
|
|
|
|
'test_spec': [
|
|
|
|
[('not_secret', 'this is displayed\r'),
|
|
|
|
('this is displayed', '')],
|
|
|
|
'"not_secret": "this is displayed"']},
|
|
|
|
|
|
|
|
# Test hashing
|
|
|
|
{'playbook': 'vars_prompt-5.yml',
|
|
|
|
'test_spec': [
|
|
|
|
[('password', 'Scenic-Improving-Payphone\r'),
|
|
|
|
('confirm password', 'Scenic-Improving-Payphone\r')],
|
|
|
|
r'"password": "\$6\$']},
|
|
|
|
|
|
|
|
# Test variables in prompt field
|
|
|
|
# https://github.com/ansible/ansible/issues/32723
|
|
|
|
{'playbook': 'vars_prompt-6.yml',
|
|
|
|
'test_spec': [
|
|
|
|
[('prompt from variable:', 'input\r')],
|
|
|
|
'']},
|
|
|
|
|
|
|
|
# Test play vars coming from vars_prompt
|
|
|
|
# https://github.com/ansible/ansible/issues/37984
|
|
|
|
{'playbook': 'vars_prompt-7.yml',
|
|
|
|
'test_spec': [
|
|
|
|
[('prompting for host:', 'testhost\r')],
|
|
|
|
r'testhost.*ok=1']},
|
|
|
|
|
|
|
|
# Test play unsafe toggle
|
|
|
|
{'playbook': 'unsafe.yml',
|
|
|
|
'test_spec': [
|
|
|
|
[('prompting for variable:', '{{whole}}\r')],
|
|
|
|
r'testhost.*ok=2']},
|
|
|
|
|
|
|
|
# Test unsupported keys
|
|
|
|
{'playbook': 'unsupported.yml',
|
|
|
|
'test_spec': [
|
|
|
|
[],
|
|
|
|
"Invalid vars_prompt data structure, found unsupported key 'when'"]},
|
|
|
|
]
|
|
|
|
|
|
|
|
for t in tests:
|
|
|
|
run_test(playbook=t['playbook'], test_spec=t['test_spec'])
|