Skip to content

ansible

Please see Ansible playbooks and tasks in here

Ansible get host vars

ansible -i inventory/hosts.yml -m debug -a "var=hostvars[inventory_hostname]" all

Set variable

set_fact: clickhouse_connection_string="clickhouse-client -h 127.0.0.1 --port {{ clickhouse_tcp_secure_port | default(clickhouse_tcp_port) }}{{' --secure' if clickhouse_tcp_secure_port is defined else '' }}"

Get variable for each host in group

ansible Exim_Hosts -m debug -a "var=exim_type"

Jinja expression concatinate hosts with

{% for host in output_hosts %}'{{ lookup('dig', host , 'qtype=A') }}'{{ ":" if not loop.last }}{% endfor %}

would give 'host1':'host2'

Everything between {% for host in output_hosts %} and {% endfor %} becomes a character. So pay attention to the spaces between evaluation expressions like {{ lookup }}

Jinja print evaluation

If you want to check Jinja expression and get the value

  • Create playbook
---
- hosts: localhost
  tasks:
    - name: Set fact
      ansible.builtin.set_fact:
        hosts: {% for host in output_hosts %}'{{ lookup('dig', host , 'qtype=A') }}'{{ ":" if not loop.last }}{% endfor %}
    - name: Print fact
      ansible.builtin.debug:
        msg: "{{ hosts.split('\n') }}"
  • Play playbook
ansible-playbook playbook.yml

Use variable

command: |
{{ clickhouse_connection_string }}
-q 'DROP DATABASE IF EXISTS `{{ item.name }}`
{% if item.cluster is defined %}ON CLUSTER `{{ item.cluster }}`{% endif %}'

Run comand locally

ansible all -i "localhost," -c local -m ansible.builtin.command -a 'echo hello world'

Run command on remote

ansible all -i 12.34.56.78, -u sudo-user -m ansible.builtin.command -a 'cat /etc/sysconfig/network-scripts/ifcfg-eth0' 

Ignore key check

ansible_ssh_common_args: -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no

Access variable from another play

foo variable was defined on localhost play

{{ hostvars['localhost']['foo'] }}

Pause play

- name: Pause play to interact with the servers
  pause:
    prompt: "Playbook paused... hit <enter> to continue or <ctrl-c a> to abort"
- name: Print all groups
  ansible.builtin.debug:
    var: groups
- debug: var=hostvars['clickhouse-01']
- debug: var=hostvars[inventory_hostname]

Run tasks locally

- name: Play name
  hosts: localhost
  connection: local
  gather_facts: no
  tasks:
    - name: ...

How to run Ansible without specifying the inventory but the host directly

Surprisingly, the trick is to append a ,

# Host and IP address
ansible all -i example.com,
ansible all -i 93.184.216.119,

or

# Requires 'hosts: all' in your playbook
ansible-playbook -i example.com, playbook.yml

The host parameter preceding the , can be either a hostname or an IPv4/v6 address.

https://stackoverflow.com/questions/17188147/how-to-run-ansible-without-specifying-the-inventory-but-the-host-directly

Show template results

- name: show templating results
  ansible.builtin.debug:
    msg: "{{ lookup('ansible.builtin.template', './some_template.j2') }}"

Show groups that host is member of

ansible <hostname> -m debug -a var=group_names

Ansible run command on remote host

ansible test.company.com  -u ansible -bKk -m shell -a "echo '<?php phpinfo(); ?>' > /var/www/html/phpinfo.php"

Find module

The issue lies with how the Ansible find module handles symbolic links. Although you have follow: true in your task, which should cause the module to follow symbolic links, it will not include those symbolic links in its output. The files in your sites-enabled directory are symbolic links, hence not listed.

To include symbolic links in the find task you need to use file_type: link option

This will include all symbolic links in the output. If you want not only links, but also regular files, you can use  file_type: any.

Lookup module

The lookup module in Ansible by default does not follow symbolic links.

Ansible find idle disks

A whole disk (not a partition, not removable) that has no partitions, no filesystem/RAID/LVM signature, is not mounted, is not swap, has no device-mapper/RAID holders, and is not currently open by any process.

Manually check:

  • Ceph: ceph-volume lvm list / ceph-volume raw list and pvesm status
  • ZFS: zpool status (a whole-disk vdev can show no FSTYPE)
  • VM passthrough: grep the guest configs — grep -r nvme4n1 /etc/pve/qemu-server/ (a raw disk passed to a VM has no host-side signature)
  • Spare/standby: mdadm --examine /dev/nvme4n1 in case it's a bare hot-spare
ANSIBLE_PYTHON_INTERPRETER=auto_silent ansible Servers_Group -b -m shell -a $'for d in /sys/block/sd* /sys/block/vd* /sys/block/nvme*; do [ -e "$d" ] || continue; n=$(basename "$d"); case "$n" in loop*|sr*|fd*|dm-*) continue;; esac; echo "$n" | grep -qE "^nvme[0-9]+c[0-9]+n[0-9]+" && continue; lsblk -dn "/dev/$n" >/dev/null 2>&1 || continue; [ "$(cat $d/removable 2>/dev/null)" = "1" ] && continue; parts=$(ls "$d" | grep -E "^${n}(p?[0-9]+)$"); holders=$(ls "$d/holders" 2>/dev/null); sig=$(lsblk -no FSTYPE "/dev/$n" 2>/dev/null | grep -v "^$"); mnt=$(lsblk -no MOUNTPOINT "/dev/$n" 2>/dev/null | grep -v "^$"); open=$(lsof "/dev/$n" 2>/dev/null); if [ -z "$parts" ] && [ -z "$holders" ] && [ -z "$sig" ] && [ -z "$mnt" ] && [ -z "$open" ]; then echo "IDLE /dev/$n $(cat $d/size 2>/dev/null | awk "{printf \\"%.2fTB\\",\\$1*512/1e12}") $(cat $d/device/model 2>/dev/null)"; fi; done' 2>/dev/null | awk '/CHANGED|SUCCESS|FAILED|UNREACHABLE/{h=$1} /IDLE/{print h, $0}'