{{tag>Brouillon}}
= Notes Ansible
Voir :
* https://docs.ansible.com/ansible/latest/user_guide/
* http://william.shallum.net/random-notes/random-ansible-tricks
* https://www.youtube.com/watch?v=ZNB1at8mJWY
* http://www.ageekslab.com/ansible/ansible3/ (boucles imbriquées)
* [[https://blog.steamulo.com/booster-vos-pratiques-devops-avec-ansible-awx-9a9c20734a71|Booster vos pratiques DEVOPS avec Ansible AWX]]
* https://github.com/STEAMULO
* http://people.redhat.com/mlessard/mtl/presentations/apr2018/AnsibleF5WorkshopVF.pdf
* https://legacy-controller-docs.ansible.com/automation-controller/latest/html/
Liste des modules Ansible par catégorie : https://docs.ansible.com/ansible/2.9/modules/modules_by_category.html
Glossary
* https://docs.ansible.com/ansible/latest/reference_appendices/glossary.html
Voir mode pull :
* https://blog.octo.com/ansible-pull-killer-feature
Voir aussi :
* https://www.packer.io
Exemples cool :
* https://github.com/ansible/ansible-examples/blob/master/language_features/register_logic.yml
* https://codepoets.co.uk/2014/ansible-random-things/
A lire
* https://docs.ansible.com/ansible/latest/user_guide/playbooks_advanced_syntax.html
* https://docs.w3cub.com/ansible~2.9/user_guide/playbooks_advanced_syntax
* https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html
* https://runebook.dev/fr/docs/ansible/user_guide/playbooks_loops
* https://runebook.dev/fr/docs/ansible/plugins/lookup
* https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html
== 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 :
* https://blog.stephane-robert.info/post/ansible-inventaire-static-precedence-tips/
* https://blog.stephane-robert.info/post/ansible-inventaire-dynamique-vagrant/
* https://linux.goffinet.org/ansible/comprendre-inventaire-ansible/
* https://blog.octo.com/ansible-inventory-du-statique-au-dynamique/
"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 :
* [[Ansible - Accélérer Ansible grâce au module Mitogen]]
* [[Notes commande xargs]]
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
* Découpage "role" un plusieurs morceaux (split role)
* "when when"
* **Include** dans un **role**
* Action si fichier n'existe pas
** Si ''/etc/systemd/system/multi-user.target.wants/rpcbind.service'' n'existe pas faire :
*** ''systemctl add-wants multi-user.target rpcbind.service''
''/roles/nis_client/tasks/main.yml''
---
- include: "{{ 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
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
== 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
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 :
* [[https://linuxfr.org/news/presentation-de-monkeyble-framework-de-test-bout-en-bout-pour-ansible|Monkeyble: Framework de test bout en bout pour Ansible]]
* ansible-test
* Molecule
* bats
* [[https://blog.stephane-robert.info/post/test-role-ansible-kitchenci-serverspec/|Test Kitchen]]
* https://docs.openstack.org/openstack-ansible/latest/contributors/testing.html
ansible-test sanity --list-tests
ansible-test sanity --docker
=== Molecule
[[https://developers.redhat.com/articles/2023/09/13/introducing-ansible-molecule-ansible-automation-platform|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 :
* https://ansible.readthedocs.io/projects/lint/configuring/#specifying-configuration-files
* [[https://github.com/willthames/ansible-lint|Ansible-lint un vérificateur de syntaxe yaml playbook / rôle]]
''.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]
=== Syntax
Voir :
* ''ansible-playbook --syntax-check''
* Ansible-lint
=== 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