-
Notifications
You must be signed in to change notification settings - Fork 30
Description
Problem
When running the ansible.playbook
action and passing in "structure" data for extra_vars
, Ansible is not interpreting them properly.
ansible_playbook_linux:
action: ansible.playbook
input:
playbook: "{{ _.playbook }}"
inventory_file: "{{ _.server }},"
extra_vars:
- wait_timeout: 2
wait_sleep: 2
wait_connect_timeout: 2
ansible_user: "user"
ansible_ssh_pass: "xxx"
ansible_ssh_extra_args: "-o StrictHostKeyChecking=no"
Looking at the output of ps -aef | grep ansible
i see the following:
root 12711 2520 0 10:02 pts/0 00:00:00 sudo -E -- bash -c /opt/stackstorm/packs/ansible/actions/ansible_playbook.py --extra_vars='[{u'"'"'wait_sleep'"'"': 2, u'"'"'ansible_ssh_pass'"'"': u'"'"'xxx'"'"', u'"'"'ansible_user'"'"': u'"'"'user'"'"', u'"'"'wait_timeout'"'"': 2, u'"'"'wait_connect_timeout'"'"': 2}]' --inventory_file=host.domain.tld, -vvv /opt/encore/ansible/playbooks/wait_for_connection.yaml
root 12712 12711 0 10:02 pts/0 00:00:00 python /opt/stackstorm/packs/ansible/actions/ansible_playbook.py --extra_vars=[{u'wait_sleep': 2, u'ansible_ssh_pass': u'xxx', u'ansible_user': u'user', u'wait_timeout': 2, u'wait_connect_timeout': 2}] --inventory_file=host.domain.tld, -vvv /opt/encore/ansible/playbooks/wait_for_connection.yaml
root 12713 12712 12 10:02 pts/0 00:00:00 /opt/stackstorm/virtualenvs/ansible/bin/python /opt/stackstorm/virtualenvs/ansible/bin/ansible-playbook --inventory-file=host.domain.tld, -vvv /opt/encore/ansible/playbooks/wait_for_connection.yaml --extra-vars='{"wait_timeout": 2, "wait_connect_timeout": 2, "wait_sleep": 2, "ansible_user": "user", "ansible_ssh_pass": "xxx"}'
root 12726 12713 2 10:02 pts/0 00:00:00 /opt/stackstorm/virtualenvs/ansible/bin/python /opt/stackstorm/virtualenvs/ansible/bin/ansible-playbook --inventory-file=host.domain.tld, -vvv /opt/encore/ansible/playbooks/wait_for_connection.yaml --extra-vars='{"wait_timeout": 2, "wait_connect_timeout": 2, "wait_sleep": 2, "ansible_user": "user", "ansible_ssh_pass": "xxx"}'
This ansible command times out after the default 10 minutes for the playbook.
System Details
$ ansible --version
ansible 2.3.2.0
config file =
configured module search path = Default w/o overrides
python version = 2.7.5 (default, Nov 6 2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]
$ st2 --version
st2 2.4.0
$ st2 pack get ansible
+-------------+--------------------------------------------------+
| Property | Value |
+-------------+--------------------------------------------------+
| name | ansible |
| version | 0.5.2 |
| author | StackStorm, Inc. |
| email | [email protected] |
| keywords | [ |
| | "ansible", |
| | "cfg management", |
| | "configuration management" |
| | ] |
| description | st2 content pack containing ansible integrations |
+-------------+--------------------------------------------------+
Debugging
Manually running the following command executes just, ansible logs in immediately and no timeouts.
/opt/stackstorm/virtualenvs/ansible/bin/python /opt/stackstorm/virtualenvs/ansible/bin/ansible-playbook --inventory-file=host.domain.tld, -vvv /opt/encore/ansible/playbooks/wait_for_connection.yaml --extra-vars='{"wait_timeout": 2, "wait_connect_timeout": 2, "wait_sleep": 2, "ansible_user": "user", "ansible_ssh_pass": "xxx"}'
However, running the following does NOT work (waits forever until a timeout).
sudo -E -- bash -c /opt/stackstorm/packs/ansible/actions/ansible_playbook.py --extra_vars='[{u'"'"'wait_sleep'"'"': 2, u'"'"'ansible_ssh_pass'"'"': u'"'"'xxx'"'"', u'"'"'ansible_user'"'"': u'"'"'user'"'"', u'"'"'wait_timeout'"'"': 2, u'"'"'wait_connect_timeout'"'"': 2}]' --inventory_file=host.domain.tld, -vvv /opt/encore/ansible/playbooks/wait_for_connection.yaml
I next added a print statement to my playbook
pre_tasks:
- name: Display all variables/facts
debug:
msg: "{{ vars | to_nice_json(indent=4) }}"
Now i compared the outputs from the first command to the second command.
Output from the first command that invokes ansible_playbook.py
:
TASK [Display all variables/facts] ************************************************************************************
task path: /opt/encore/ansible/playbooks/wait_for_connection.yaml:13
ok: [host.domain.tld] => {
"msg": {
"_raw_params": "'{\"wait_timeout\": 2, \"wait_connect_timeout\": 2, \"wait_sleep\": 2, \"ansible_user\": \"user\", \"ansible_ssh_pass\": \"xxx\"}'",
"ansible_check_mode": false,
"ansible_play_batch": [
"host.domain.tld"
],
"ansible_play_hosts": [
"host.domain.tld"
],
....
"wait_connect_timeout": 5,
"wait_sleep": 1,
"wait_timeout": 600
}
}
Output from the second command that invoking ansible directly:
TASK [Display all variables/facts] ************************************************************************************
ok: [host.domain.tld] => {
"msg": {
"ansible_check_mode": false,
"ansible_play_batch": [
"host.domain.tld"
],
"ansible_play_hosts": [
"host.domain.tld"
],
"ansible_play_hosts_all": [
"host.domain.tld"
],
"ansible_playbook_python": "/opt/stackstorm/virtualenvs/ansible/bin/python",
"ansible_ssh_pass": "xxx",
"ansible_user": "user",
....
"wait_connect_timeout": 2,
"wait_sleep": 2,
"wait_timeout": 2
}
}
As you can see, when invoking ansible_playbook.py
the variables are are not merged properly into the vars
dict, causing the connection to fail repeatedly until the timeout of 10 minutes (default) occurs.
Conversely, when we invoke it from shell, the --extra-vars
is merged properly with the vars
dict and the connection works as expected.
Proposed Solution
The ansible-playbook
is where the command is being executed here https://github.com/StackStorm-Exchange/stackstorm-ansible/blob/master/actions/lib/ansible_base.py#L105 .
If we change that line to use a shell, and convert the command from a list to a string (see below), then everything works as expected.
exit_code = subprocess.call(' '.join(self.cmd), env=os.environ.copy(), shell=True)