Table des matières

Notes Ansible

Voir :

Liste des modules Ansible par catégorie : https://docs.ansible.com/ansible/2.9/modules/modules_by_category.html

Glossary

Voir mode pull :

Voir aussi :

Exemples cool :

A lire

Install et config

Install avec PIP

https://raw.githubusercontent.com/mrlesmithjr/ansible-samba/master/provision.sh

#!/bin/bash
sudo apt-get update
sudo apt-get install -y git python-pip python-dev
sudo pip install jinja2
sudo pip install ansible
sudo ansible-galaxy install -r /vagrant/requirements.yml -f
ansible-playbook -i "localhost," -c local /vagrant/playbook.yml

Doc

Voir ansible-doc. Exemple :

ansible-doc -t keyword -l

Inventaire

Voir :

“inline content” inventory

ansible -m ping all -i 'node1,node2,'

lister toutes les nœuds

ansible-inventory --list -y

config

cp /etc/ansible/ansible.cfg ~/.ansible.cfg
mkdir ~/.ansible
cp /etc/ansible/hosts ~/.ansible/hosts.ini
 
sed -i -e 's%/etc/ansible/hosts%$HOME/.ansible/hosts.ini%' ~/.ansible.cfg
sed -i -e 's%#\(.*$HOME/\.ansible/hosts.ini\)%\1%' ~/.ansible.cfg
 
sed -i -e 's/^remote_port/#remote_port/' ~/.ansible.cfg
 
echo "localhost ansible_connection=local" >>  ~/.ansible/hosts.ini

Ou

/etc/ansible/ansible.cfg

[defaults]
host_key_checking = False
timeout = 60
vault_password_file = /var/lib/plop/ansible/vault/vault_pass.txt
ansible_managed = Ansible managed file, do not edit directly
filter_plugins = /var/lib/plop/ansible/filter_plugins/
lookup_plugins = /var/lib/plop/ansible/lookup_plugins/
library = /var/lib/plop/ansible/library/
remote_tmp = /tmp/.ansible
local_tmp = /tmp/.ansible
#allow_world_readable_tmpfiles = true
 
[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=30m -o UserKnownHostsFile=/dev/null
export ANSIBLE_CONFIG=$HOME/.ansible.cfg
ansible -i ~/.ansible/hosts.ini test -m ping

La connexion via SSH doit être configurée via ~/.ssh/config et via ssh-agent. Si besion :

ssh-agent -k
eval $(ssh-agent -s)
ssh-add 

Exemple de conf par variables

export ANSIBLE_ALLOW_EMBEDDED_TEMPLATES=false
export ANSIBLE_NOCOWS=true
export BECOME_ALLOW_SAME_USER=false
export ANSIBLE_PRIVATE_ROLE_VARS=true
export ANSIBLE_DISPLAY_ARGS_TO_STDOUT=true
export ANSIBLE_DISPLAY_TRACEBACK=always
export ANSIBLE_DUPLICATE_YAML_DICT_KEY=error
# export ANSIBLE_ENABLE_TASK_DEBUGGER=true
export ANSIBLE_HOST_PATTERN_MISMATCH=error
export ANSIBLE_INVENTORY_ANY_UNPARSED_IS_FAILED=true
export ANSIBLE_INVENTORY_UNPARSED_FAILED=true

Usage

Sudo / become

ansible-playbook -u user -kKb playbook.yml

Sur les serveurs distants

apt-get install python-minimal libpython-stdlib sudo

Traitements parallèles

Voir :

Exemple 1

ansible.cfg

[defaults]
strategy = free

Exemple 2

ansible -e serial_number=50 

Connexions

[arista]
eos ansible_host=192.168.2.10 ansible_connection=network_cli ansible_network_os=eos
 
[juniper]
junos ansible_host=192.168.2.20 ansible_connection=netconf ansible_network_os=junos

Autres

Lancer une commande

ansible all -a "free -m"

Lancer une commande bash (utilisation Pipe vars etc…)

ansible all -m shell -a "ifconfig | grep inet"

Connaître toutes les variables et les valeurs associées (Nom machine, mémoire, Version noyaux …)

ansible all -m setup

Lancer une commande simultanément sur plusieurs serveurs par lots de 2 machines -s pour sudo

ansible webservers -m service -a "name=nginx state=restarted" --forks=2 -s

Mode “noop” / “dry-run”

--check
ou --check--diff --limit foo.example.com

always_run: True sinon --check n’exécute pas les instructions du module shell,

lineinfile

A la place de lineinfile il existe aussi replace

Dépendance de rôles

Quand un rôle dépend d'un autre. \ Ici foo dépend de bar

roles/foo/meta/main.yml

---
allow_duplicates: no
dependencies:
  - role: bar

Exemple

Exemple

/roles/nis_client/tasks/main.yml

---
- name: Include tasks
  ansible.builtin.include_tasks: "{{ ansible_os_family | lower }}.yml"

/roles/nis_client/tasks/debian.yml

---
  - name: Ubuntu lancer rpcbind avant NIS
    stat: path='/etc/systemd/system/multi-user.target.wants/rpcbind.service'
    register: systemdwants

  - name: DEBUG
    debug: msg="systemdwants = {{ systemdwants }}"

  - name: Ubuntu lancer rpcbind avant NIS 2
    command: systemctl add-wants multi-user.target rpcbind.service
    # when: systemdwants.stat.exists == False
    when: not systemdwants.stat.exists
    notify:
      - restart nis

Vérifier si un paquet deb est déjà installé

Source : http://chaosmail.github.io/programming/2015/03/04/install-deb-packages-in-ansible/

---

- name: Check if my_package is installed
  command: dpkg-query -W my_package
  register: my_package_check_deb
  failed_when: my_package_check_deb.rc > 1
  changed_when: my_package_check_deb.rc == 1
  check_mode: false

- name: copie du paquet my_package
  copy: src=my_package_linux.ubuntu14.04_x86-64.deb dest=/root/my_package_linux.ubuntu14.04_x86-64.deb
  changed_when: my_package_check_deb.rc == 1

- name: installation des dépendances
  apt: name=libacl1 state=present
  changed_when: my_package_check_deb.rc == 1

- name: install du paquet
  apt: deb=/root/my_package_linux.ubuntu14.04_x86-64.deb
  changed_when: my_package_check_deb.rc == 1

Exemple de find shell

- name: /var/log/* readable by user process - find
  shell: 'find /var/log/ -not \( -perm /o=r -o -user process \)  -a -not \( -wholename "/var/log/btmp*" \)'
  changed_when: False
  always_run: True
  register: list_files_var_log_notreadable

- name: /var/log/* readable by user process - set
  file: mode="o+rX" dest={{ item }}
  #file: mode="0755" dest={{ item }}
  with_items:
    - "{{ list_files_var_log_notreadable.stdout.split('\n') }}"
  when: list_files_var_log_notreadable.stdout != ""

Exemples include role conditionnel

Exemple 1

- hosts: webservers
  roles:
     - { role: debian_stock_config, when: ansible_os_family == 'Debian' }

Exemple 2

- name: Enable local cache DNS
  include_role:
    name: acme.dns.enable_local_cache_dns
  vars:
    EVAR_BACKUP_NAME: postinstall
    host_func_excluded:
      - FOO
    # trigramme_appli: "{{ inventory_hostname[5:8] }}"
    trigramme_appli: "{{ ansible_hostname[5:8] }}"
  when: not trigramme_appli | lower in host_func_excluded | lower

Notes Ansible

Lancer l'action même si Check Mode (Dry Run) ''%%--check%%''

always_run is deprecated. Use check_mode = no instead

#always_run: true
check_mode: false

Parfois il est préférable de trouver une solution plus élégante. Par exemple :

- name: mkdir /san/label
  file: dest='/san/{{ item }}' state=directory
  with_items:
    #- '{{ list_label_ext4devs.stdout_lines }}'
    #- '{{ list_label_xfsdevs.stdout_lines }}'
    - '{{ list_label_ext4devs.stdout_lines | default() }}'
    - '{{ list_label_xfsdevs.stdout_lines  | default() }}'

Ici nous utilisons default() pour éviter une erreur à cause d'un champ vide

fatal: [plop1]: FAILED! => {"failed": true, "msg": "'dict object' has no attribute 'stdout_lines'"}

Ignorer si mode check (ne pas tester)

when: not ansible_check_mode

- name: activation service sysstat 1
  lineinfile: dest=/etc/default/sysstat line='ENABLED="false"' state=absent
  when: not ansible_check_mode

Exemple module command ne lancer qu'une seule fois une commande.

- name: newer autolock screen - do conf
  command: dbus-launch gsettings set org.gnome.desktop.lockdown disable-lock-screen true
  become: '{{ autologin_user }}'
  args:
    creates: /root/.ansible-jalon-disable-lock-screen

- name: newer autolock screen - jalon exist ?
  stat: path=/root/.ansible-jalon-disable-lock-screen
  register: p

- name: newer autolock screen - jalon touch
  file: path=/root/.ansible-jalon-disable-lock-screen state=touch
  # when: p.stat.exists == False
  when: not p.stat.exists

Gather_fact partiel

Grâce à gather_subset

play.yml

- name: Test
  hosts: all
  gather_subset: os_family

Copie de fichiers

Une alternative à M(copy)

- name: Download file from a file path
  # ansible.builtin.copy:
  ansible.builtin.get_url:
    url: file:///tmp/a_file.txt
    dest: /tmp/afilecopy.txt

Pb

becoming-an-unprivileged-user Err Failed to set permissions on the temporary...Not owner\nchown

Lors de l’exécution d’un playbook Ansible avec un sudo (become) faisant appel à un utilisateur non privilégié (ici « oracle »)

ansible -m ping -u user01 -i srv1,  all --become-user=oracle -b

Nous avons l’erreur suivante :

srv1 | FAILED! => {
    "msg": "Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged user (rc: 1, err: chown: /var/tmp/ansible-tmp-1685976784.0795348-3077033-272077328342364/: Not owner\nchown: /var/tmp/ansible-tmp-1685976784.0795348-3077033-272077328342364/AnsiballZ_ping.py: Not owner\n}). For information on working around this, see https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user"
}

Apparemment cela concernerait que AIX.

Solution

La solution de contournement la plus simple à mettre en place est de définir à True la variable ansible_shell_allow_world_readable_temp

play1.yml

#!/usr/bin/ansible-playbook
 
#
#  ./play1.yml -u user01 -i srv1,
 
---

- name: test sudo oracle
  hosts: all
  gather_facts: false
  become: true
  become_user: oracle
  vars:
    ansible_shell_allow_world_readable_temp: true

  tasks:
    - name: command id
      command: id
      changed_when: false
      register: cmd_id

    - name: echo id
      debug:
        var: cmd_id

Remote copy does not support recursive copy of directory

Le module copy ne supporte pas les copies de répertoire (mode récursif). \ Le module synchronize est plus approprié. Dans notre exemple nous voulons copier srv1:/mnt/plop/ sur srv1:/tmp/

Note : peut-être que cela marche avec 'directory_mode'

- name: push omniplanar installer
  copy:
    src: /mnt/plop/
    dest: /tmp
    remote_src: True
    #directory_mode: True

Solution

- name: push plop
  synchronize:
    src: /mnt/plop/plop.run
    dest: /usr/local/bin/
    rsync_opts:
      - "--chmod=F755"
      - "--chown=root:staff"
  #delegate_to: "{{ inventory_hostname }}"
  use_ssh_args: true

Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged user

Erreur

fatal: [aws-zbx1]: FAILED! => {"msg": "Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged user (rc: 1, err: chown: changing ownership of '/var/tmp/ansible-tmp-1559124598.47-172527571991348/': Operation not permitted\nchown: changing ownership of '/var/tmp/ansible-tmp-1559124598.47-172527571991348/AnsiballZ_postgresql_db.py': Operation not permitted\n}). For information on working around this, see https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user"

Solution

~/.ansible.cfg

[defaults]
allow_world_readable_tmpfiles = true

ou

  vars:
    ansible_shell_allow_world_readable_temp: true

Voir https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user

sudo: no tty present and no askpass program specified

Solution de contournement (workaround) Source: https://github.com/ansible/ansible/issues/15297

  lineinfile:
    path: /etc/sudoers
    state: present
    insertafter: EOF
    line: '{{ ansible_user }} ALL=NOPASSWD:/usr/bin/rsync'

Solution 2 Source : https://github.com/ansible/ansible/issues/20769

Applique la perte de l'élévation de privilèges

Ajouter rsync_path: /usr/bin/rsync

  tasks:
    - name: Synchronization of src on the control machine to dest on the remote hosts
      synchronize: 
        src: /etc/hostname
        dest: /home/user
        rsync_path: /usr/bin/rsync

Pb No module named 'ansible'

$ ansible --version
Traceback (most recent call last):
  File "/usr/bin/ansible", line 34, in <module>
    from ansible import context
ModuleNotFoundError: No module named 'ansible'

Solution

Test

env PYTHONPATH=/usr/lib/python3/dist-packages ansible --version

Solution si test OK

~/.bashrc

# Fix bug Ansible : No module named 'ansible'
export PYTHONPATH=$PYTHONPATH:/usr/lib/python3/dist-packages

Err template error while templating string: Could not load "search": 'search'.

TASK [dns_update_resolv_conf : Remove immutable attribute] **************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "The conditional check 'stat_resolv_conf.stat.attr_flags | search(\"i\")' failed. The error was: template error while templating string: Could not load \"search\": 'search'. String: {% if stat_resolv_conf.stat.attr_flags | search(\"i\") %} True {% else %} False {% endif %}. Could not load \"search\": 'search'\n\nThe error appears to be in '/home/jean/code/dns_update_resolv_conf/roles/dns_update_resolv_conf/tasks/main.yml': line 147, 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: Remove immutable attribute\n  ^ here\n"}

Solution

Change

when:
    - result | failed

By

when:
    - result is failed

Example :

- name: Remove immutable attribute
  become: true
  ansible.builtin.file:
    path: "{{ resolv_filepath }}"
    attributes: "-i"
  # when: stat_resolv_conf.stat.attr_flags | search("i")
  when: stat_resolv_conf.stat.attr_flags is search("i")

Pb passer un boolean ou des listes en extravars à Ansible

Solution

Passer par du JSON

--extra-vars '{"abc": false}'

--extra-vars '{"abc": ["elm",] }'

Test

Voir :

ansible-test sanity --list-tests
ansible-test sanity --docker

Molecule

Introducing Ansible Molecule with Ansible Automation Platform

Debug

env ANSIBLE_NOCOLOR=1 ansible-playbook -vvvvv

Voir le module debug

env ANSIBLE_DEBUG=1 ansible-playbook

Ansible-lint

Voir :

.ansible-lint

---

profile: null
exclude_paths:
  - test/playbook.yml
---
# Offline mode disables installation of requirements.yml and schema refreshing
offline: true

profile: production
exclude_paths:
  - .git/
  - .github/
  - .gitlab/
  - .cache/
warn_list:
  - var_naming
  - idiom
skip_list:
  - var-naming[no-role-prefix]

.ansible-lint-ignore

roles/agent/defaults/main.yml var-naming[no-role-prefix]

Exeption :

Utiliser skip_ansible_lint

Exemple :

- name: Kustomize get image
  become: true
  become_user: "{{ user_k8s }}"
  ansible.builtin.shell:
    chdir: "{{ myhome }}/awx-operator"
    cmd: "{{ myhome }}/awx-operator/bin/kustomize build config/default"
  changed_when: false
  register: reg_image
  tags: skip_ansible_lint

Syntax

Voir :

Callback plugin

https://beingasysadmin.wordpress.com/2015/06/03/ping-your-ansible-from-slack/

Autres

ansible_python_interpreter=/home/user/network-automation/venv/bin/python