{{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