Skip to content

Instantly share code, notes, and snippets.

@savishy
Last active June 25, 2018 06:47
Show Gist options
  • Select an option

  • Save savishy/4febcdfa0ce417b65ea127b13d8ab70b to your computer and use it in GitHub Desktop.

Select an option

Save savishy/4febcdfa0ce417b65ea127b13d8ab70b to your computer and use it in GitHub Desktop.

Ad Hoc ansible Commands

  1. http://docs.ansible.com/ansible/latest/playbooks_variables.html#magic-variables-and-how-to-access-information-about-other-hosts

Test WinRM Connectivity to a Windows Host

One way to do this is to execute a simple Windows Powershell command using Ad-Hoc Ansible.

❗ note that shell does not work for Windows. The equivalent is win_shell.

ansible --vault-password-file ~/.vault_pass --extra-vars @vars/all.yml --extra-vars @vars/vault.yml -i inventories/poc/ all -m "win_shell gci C:"

Output

TESTVM1 | SUCCESS | rc=0 >>


    Directory: C:\Users\azureuser


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-r---        7/16/2016   1:23 PM                Desktop
d-r---         4/3/2018   5:40 AM                Documents
d-r---        7/16/2016   1:23 PM                Downloads
d-r---        7/16/2016   1:23 PM                Favorites
d-r---        7/16/2016   1:23 PM                Links
d-r---        7/16/2016   1:23 PM                Music
d-r---        7/16/2016   1:23 PM                Pictures
d-----        7/16/2016   1:23 PM                Saved Games
d-r---        7/16/2016   1:23 PM                Videos

Ping a Windows Host

ping only works for Linux.

The example below is for pinging a Windows host, while passing in extra vars containing connection credentials, and decrypting vaulted variables.

ansible --vault-password-file ~/.vault_pass --extra-vars @vars/all.yml --extra-vars @vars/vault.yml -i inventories/XYZ/ all -m "win_ping"

List all the groups

  • This is useful especially when you use dynamic inventory. Groups get created automatically by dynamic inventory scripts.
ansible -i inventories/DYN_INVENTORY all -m debug -a 'var=groups.keys()'

List all groups the current host is part of

ansible -i inventories/DYN_INVENTORY all -m debug -a 'var=group_names'

You can use the group_names variable above.

Ansible Tips and Troubleshooting

Specify a play to run on multiple groups

Reference: http://docs.ansible.com/ansible/latest/intro_patterns.html#patterns

Example: you have multiple groups that have similar configuration.

- name: Run on all SP Hosts
  hosts: spapp:spweb
  roles:
  - prereqs

Specify a play to run on all hosts in a group except some hosts

Example: a group called db which has machines DEVDB1, DEVDB2, DEVWS1. And you want to run a play only on DEVDB1, DEVDB2.

- hosts: "db:!*WS*"
  ...
  ...

Specify a task to run on all hosts in a group except some hosts

- debug: msg=some task
  when: 'inventory_hostname != <some condition>'

Performing actions dependent on specific Ubuntu releases

Problem: Sometimes you want to perform an action specific to each Ubuntu release.

For example you want to add a deb for Docker specific to each Ubuntu release i.e xenial, trusty etc.

The solution is as follows:

- name: add Docker repository
  apt_repository:
    filename: docker
    repo: "deb https://apt.dockerproject.org/repo ubuntu-{{ansible_distribution_release}} main"
  when: ansible_distribution == 'Ubuntu'
  become: true

Looping over a list of key-value pairs

Consider the following scenario:

You have a list of key-value items as follows

ec2_ports:
   - { proto: "tcp", from: "80", to: "80" }
   - { proto: "tcp", from: "22", to: "22" }
   - { proto: "tcp", from: "8080", to: "8080" }
   - { proto: "tcp", from: "8081", to: "8081" }

You need to loop over this list:

- name: modify ec2 rules to allow incoming traffic from My IP address
  ec2_group:
    ...
    ...
    rules:
      - proto: "{{ item.proto }}"
        from_port: "{{ item.from }}"
        to_port: "{{ item.to }}"
  with_items: ec2_ports

This might throw an error as follows:

"the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'ansible.vars.unsafe_proxy.AnsibleUnsafeText object' has no attribute 'to'\n\nThe error appears to have been in '/work/ansible-roles/ec2-create-group/tasks/main.yml': line 13, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: modify ec2 rules to allow incoming traffic from My IP address\n  ^ here\n"

What went wrong?

Replace:

  with_items: ec2_ports

With:

  with_items: "{{ec2_ports}}"

Troubleshooting

Error connecting to remote hosts: too long for Unix domain socket

Symptom: Ansible errors out when connecting to remote hosts and throws an SSH error. This error message has the line too long for Unix domain socket.

Solution:

reference

The following needs to be added to your ansible.cfg to make this work. (read the link above, it has more suggestions!)

[ssh_connection]
control_path = %(directory)s/%%h-%%p-%%r

A file was supposed to be changed by Ansible, but did not change

Typical Symptom: You change a file (say a templated properties file) in your playbook directory and expect Ansible to deploy the file and report a "Changed" status for that file. Instead, the file isn't deployed and the status is "OK" i.e no changes.

Possible Causes:

  1. Check whether your control_path is set properly - reference

timeout (12s) waiting for privilege escalation prompt

fatal: [some_host_name]: FAILED! => {
    "failed": true,
    "msg": "Timeout (12s) waiting for privilege escalation prompt: "
}

Symptoms

Sometimes, a certain step fails with the error message above. This is a sporadic error, isn't reproduced 100% of the time on successive reruns of playbook.

reference

Possible Cause and Solution

One solution is to simply rerun the playbook. Often this is a one-off error (see link below) and may go away during a rerun.

A cause and permanent fix is documented here. But this hasn't been tested.

(Advanced) Debugging Ansible Python Scripts

When Ansible runs modules, it essentially creates temporary python scripts and runs them. For example, you might see output such as the following when you run Ansible Playbooks:

/usr/bin/python /home/vish/.ansible/tmp/ansible-tmp-1522308398.51-188123304239203/azure_rm_networkinterface.py

If there is a really bad problem and you want to dig into the Python code for the module, the best way is to

  • Run the Playbook once, and tell ansible to retain the above python script (export ANSIBLE_KEEP_REMOTE_FILES=1)
  • Then run the python script.

reference

Ansible on Windows

For Windows Specific stuff

Known Issue

  • Ansible on Windows, via WinRM, fails with a mysterious message winrm_connection_timeout and winrm_send_input_failed, if you use Linux-specific modules on Windows.
  • For example the output below was from using get_file module instead of win_get_file for Windows hosts.
TASK [prereqs : download MSI] ********************************************************************************************************************************
Using module file /usr/lib/python2.7/dist-packages/ansible/modules/net_tools/basics/get_url.py
<XXXX> ESTABLISH WINRM CONNECTION FOR USER: azureuser on PORT 5986 TO XXXX
checking if winrm_host XXXX is an IPv6 address
Using module file /usr/lib/python2.7/dist-packages/ansible/modules/net_tools/basics/get_url.py
<XXXX> ESTABLISH WINRM CONNECTION FOR USER: azureuser on PORT 5986 TO XXXX
checking if winrm_host XXXX is an IPv6 address
EXEC (via pipeline wrapper)
EXEC (via pipeline wrapper)
 [WARNING]: FATAL ERROR DURING FILE TRANSFER: Traceback (most recent call last):   File "/usr/lib/python2.7/dist-
packages/ansible/plugins/connection/winrm.py", line 294, in _winrm_exec     self._winrm_send_input(self.protocol, self.shell_id, command_id, data,
eof=is_last)   File "/usr/lib/python2.7/dist-packages/ansible/plugins/connection/winrm.py", line 274, in _winrm_send_input
protocol.send_message(xmltodict.unparse(rq))   File "/usr/local/lib/python2.7/dist-packages/winrm/protocol.py", line 256, in send_message     raise
WinRMOperationTimeoutError() WinRMOperationTimeoutError

fatal: [AZRSPPOCAPPVM1]: FAILED! => {
    "msg": "winrm send_input failed"
}
 [WARNING]: FATAL ERROR DURING FILE TRANSFER: Traceback (most recent call last):   File "/usr/lib/python2.7/dist-
packages/ansible/plugins/connection/winrm.py", line 294, in _winrm_exec     self._winrm_send_input(self.protocol, self.shell_id, command_id, data,
eof=is_last)   File "/usr/lib/python2.7/dist-packages/ansible/plugins/connection/winrm.py", line 274, in _winrm_send_input
protocol.send_message(xmltodict.unparse(rq))   File "/usr/local/lib/python2.7/dist-packages/winrm/protocol.py", line 256, in send_message     raise
WinRMOperationTimeoutError() WinRMOperationTimeoutError

fatal: [XXXXXXXX]: FAILED! => {
    "msg": "winrm send_input failed"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment