Outils pour utilisateurs

Outils du site


blog

Ansible - DRY - module_defaults

- name: Test AWX create obj
  hosts: localhost
  gather_facts: false

  vars:
    awx_cred:
      controller_host: http://localhost:3000
      controller_username: admin
      controller_password: P@ssw0rd
      # validate_certs: false

  module_defaults:
    awx.awx.credential: "{{ awx_cred }}"
    awx.awx.project: "{{ awx_cred }}"
    awx.awx.inventory: "{{ awx_cred }}"
    awx.awx.inventory_source: "{{ awx_cred }}"
    awx.awx.credential_type: "{{ awx_cred }}"
    awx.awx.execution_environment: "{{ awx_cred }}"
    awx.awx.job_template: "{{ awx_cred }}"
$ ansible_collections/awx/awx/meta/runtime.yml | yq -r '.action_groups | keys[]'
controller
- name: Test AWX create obj
  hosts: localhost
  gather_facts: false

  module_defaults:
    group/awx.awx.controller:
      controller_host: http://localhost:3000
      controller_username: admin
      controller_password: P@ssw0rd
2025/12/04 11:23 · Jean-Baptiste

Bonnes pratiques Ansible - annexes

Principes

Plan

  • Bonnes pratiques propres à Ansible 1
    • Idempotent
    • Ansible-lint
  • Bonnes pratiques propres à Ansible 2
  • Bonnes pratiques IT
    • Logs
    • Proterger les secrets
    • Assert sur les cibles
  • Bonnes pratiques code
    • DRY
    • Ne pas réinventer le roue
    • Pas de code spacelift
    • Controler tous les inputs
    • Faire les contrôle de plus tôt possible.

Fichiers

find . -type f -wholename "*/files/*" -size +100k
find . -type f -wholename "*/files/*" -size -100k -exec file --mime-encoding {} + | awk -F: '/binary/ { print $1 }'
  • Garder une arborescence similaire aux petits textes : le chemin doit contenir le nom de rôles ou du playbook
  • Une référence unique. Un seul rôle (ou un seul playbook) fait appel directement à ce fichier.
  • Si deux roles ou besoin de ce même fichier : créer un 3em rôle et faire un dépendance de rôle.

DRY

Factoriser - Éviter de dupliquer du code - Don't Repeat Yourself (DRY) (RA_GEN_N3) Dans la mesure du possible, seulement se répéter est mieux que d'écrire un code difficilement lisible. Car “à la pureté, privilégie l'aspect pratique.”

  • En créant des rôles en les appelant avec des arguments / variables
  • module_defaults (If you frequently call the same module with the same arguments)
  • En utilisant import* et include* (attention aux notify avec include)
  • En utilsant block

Classification

  • Ne pas utiliser de module obsolète “Deprecated” (RA_QUA_N2)
  • Les noms de tâche devraient être uniques (RA_QUA_N3)
  • Si pas besoin des facts : mettre gather_facts à false (RA_PERF_N3)
  • Si besoin de facts récuper seulement les facts utiles (RA_PERF_N3)
  • Playbook pouvant fonctionner un Dry-Run (--check) (RA_TEST_N2)
  • Ne pas utilisez ignore_errors: true et encore moins pour un playbook entier. Préferez “failed_when:” (RA_QUA_N1)
  • Éviter d’utiliser delegate_to surtout, dans les rôles (RA_QUA_N1)
  • Pour les templates et les fichiers, systématiquement sauf si non applicable mettre en commentaire que ce fichier est géré par Ansible. (RA_QUA_N1)
  • Ne pas utiliser M(vars_prompt) (remplacé par les “Surveys” et extra-vars) (RA_QUA_N1)
  • Ne pas utiliser M(pause) sans timeout (RA_QUA_N1)
  • Utiliser des inventaires dynamiques (If you have an external source of truth) (RA_QUA_N3)
  • Larger Host Counts - Consider setting “forks” on a job template to larger values to increase parallelism of execution runs. Voir : Strategy, Mitogen, Slicing, Async (Asynchronous) (RA_PERF_N3)
  • Ne pas mettre les facts des nœuds dans la base de données - Ne pas activer “Enable Fact Storage” Le cache des facts doit être sur les managed_hosts et non coté serveur (RA_GEN_N1)
  • Ne pas faire de command: ansible-galaxy ni de shell: ansible-galaxy, mais utiliser la manière native de AAP / AWX (RA_QUA_N1)
  • Pour les facts (facts caching) (RA_PERF_N3)
  • Assert extra_var, controler les inputs des utilisateurs (RA_SEC_N1)
  • Assert sur les cibles (RA_SEC_N2)
  • Utiliser un logiciel de gestion de versions tel que Git (RA_GEN_N1) Use Source Control https://ansible.readthedocs.io/projects/awx/en/24.6.1/userguide/best_practices.html
  • Utiliser SonarQube ou équivalent (RA_GEN_N4)
  • Utiliser l'encodage UTF8 (RA_GEN_N1)
  • Remplacer les tabulations par 2 espaces (A config si ce n'est pas le cas dans l'IDE) (RA_GEN_N1)
  • DRY - Factoriser - Éviter de dupliquer du code - Don't Repeat Yourself (DRY) (RA_GEN_N3) Dans la mesure du possible, seulement se répéter est mieux que d'écrire un code difficilement lisible. Car “à la pureté, privilégie l'aspect pratique.”
  • Mettre les become_user: root que sur les tâches nécessitant les privilèges, et non sur tous le playbook (RA_SEC_N1)
  • Utiliser no_log: true pour les taches utilisant des secrets (RA_SEC_N1)
  • Pour les données sensibles utiliser ansible-vault ou les Crendential AWX (RA_SEC_N1)
  • Mettre en cache les facts (fact_caching) (mais sur les noeuds, pas en DB) (RA_PERF_N3)
  • Eviter de boucler innutilement - vérifier si le module prends des listes (RA_PERF_N2)
  • Nommer les templates Jinja avec l’extension j2 (RA_CONV_REQ)
  • Préférer les variables a plat plutôt que les variables dictionnaires (RA_CONV_OPT)
  • De préférence nommer la variable de boucle (loop_var) à la place d'utiliser le nom par défaut item (RA_CONV_OPT)
  • ? Pour les roles contenants beaucoup de fichiers dans “files/” privilégier une arborescence comme suit (RA_CONV_OPT) (ex files/etc/nginx/sites-available/plop)

Bonnes pratiques IT

Tester les playbooks sur un environnement hors prod.

Mettre en place des tests unitaires :

Utiliser le cache que cela est possible :

  • Pour les facts (facts caching) (RA_PERF_N3)
  • Mais éviter “Enable Fact Storage” qui met les fact dans la base de données
  • Pour les inventaires (cache_plugin, Fact Cache)
[inventory]
cache = True
cache_plugin = memory
cache_timeout = 1800

Idempotence

Si Appel API → Changed (par défaut)

Utiliser les handlers pour redémarrer les services Mais attention avec les modules (import*), les handlers ne sont pas déclenchés par défaut. Faire ansible.builtin.meta: flush_handlers

Fichiers

  • Devraient être dans <role_name>/files/ (ou dans files/ si appelé directement depuis un playbook ?)
2025/11/25 11:08 · Jean-Baptiste

Bonnes pratiques Ansible - temp

Follow Consistent Naming: Use descriptive names for playbooks to indicate their purpose, e.g., deploy_app.yml

Run_once (Pièges)

run_once will be executed at each serial execution in the play. That means, if you choose serial = 1, it will be asked to confirm as many times as the quantity of targets on the play.

Check Ansible docs: https://docs.ansible.com/ansible/latest/user_guide/playbooks_strategies.html#running-on-a-single-machine-with-run-once

When used together with serial, tasks marked as run_once will be run on one host in each serial batch. If the task must run only once regardless of serial mode, use when: inventory_hostname == ansible_play_hosts_all[0] construct.

Attention aux slicing !

https://github.com/ansible/ansible-lint/issues/1026#issuecomment-685849603

Ansible ignores run_once with the free strategy which means your tasks are run many times, once for each valid inventory host

Si run_once, toujours préciser le delegate_to ou when: inventory_hostname ==

Il est aussi possible de faire quelque chose comme :

- command: /opt/application/upgrade_db.py
  when: inventory_hostname == webservers[0]

Les tâches marquées comme run_once seront exécutées sur un hôte dans chaque série de lot. Si la tâche ne doit s'exécuter qu'une seule fois quel que soit le “serial” mode , utilisez

when: inventory_hostname == ansible_play_hosts_all[0] 

Bonnes pratiques AWX

  • Variable Management for Inventory - Keeping variable data along with the hosts and groups definitions (see the inventory editor) is encouraged, rather than using group_vars/ and host_vars/
  • Autoscaling - Using the “callback” feature to allow newly booting instances to request configuration is very useful for auto-scaling scenarios or provisioning integration.
  • Larger Host Counts - Consider setting “forks” on a job template to larger values to increase parallelism of execution runs. Voir : Strategy, Mitogen, Slicing, Async (Asynchronous) (RA_PERF_N3)
  • Ne pas faire de command: ansible-galaxy ni de shell: ansible-galaxy, mais utiliser la manière native de AAP / AWX (RA_QUA_N1)

Bonnes pratiques code

  • Éviter le code spaghetti
  • Assert sur les cibles (RA_SEC_N2)
  • Faire les contrôle de plus tôt possible.

Exemple : Contrôle avant d'effectuer la connexion : playbook localhost avec gather_facts=false Playbook dédié : ansible.builtin.import_playbook: _assert_extra_vars.yml

Timeout après 5s (async)

---

- name: Test
  hosts: localhost

  tasks:
    - name: Sleep
      ansible.builtin.command: /bin/sleep 60
      async: 10
      # poll: 5

Voir : https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_checkmode.html#check-mode-dry

Éviter command: cat. Préférez :

- name: get actual effective params
  slurp:
    src: /proc/cmdline
  become: true
  register: all_current_activ_params

- name: show effective params
  debug:
    msg: "{{ all_current_activ_params.content | b64decode }}"

Contrôler que la cible correspond bien

Exemple :

  • Bonne version OS
  • Agent pas déjà installé via autre autre procédure…
  • Espace disque et autres ressources disponibles sur la cible

Portée des variables

DEFAULT_PRIVATE_ROLE_VARS

M(ansible.builtin.include_roles) and M(ansible.builtin.import_roles) C(public)

Import vs include

Modules :

  • ansible.builtin.import_playbook
  • ansible.builtin.import_role
  • ansible.builtin.import_tasks
  • ansible.builtin.include_role
  • ansible.builtin.include_tasks
  • ansible.builtin.include_vars
You cannot use loops on 'import_tasks' statements. You should use 'include_tasks' instead.

Sécurité

Mettre les become que sur les tâches nécessitant les privilèges, et non sur tous le playbook (RA_SEC_N1)

Utiliser no_log: true pour les taches utilisant des secrets (RA_SEC_N1)

Pour les données sensibles utiliser ansible-vault ou les Crendential AWX (RA_SEC_N1)

Troubleshooting untrusted templates https://docs.ansible.com/ansible/devel/porting_guides/porting_guide_12.html

export _ANSIBLE_TEMPLAR_UNTRUSTED_TEMPLATE_BEHAVIOR=fail

https://docs.ansible.com/ansible/devel/porting_guides/porting_guide_core_2.19.html#untrusted-templates export ANSIBLE_DISPLAY_TRACEBACK=always

Performance

Voir :

Limiter l'usage des ressources
- name: Installation d'un logiciel sur plusieurs serveurs avec throttle
  ansible.builtin.apt:
    name: nginx
    state: present
  async: 600  # Exécution en mode asynchrone avec un délai maximum de 10 minutes
  poll: 5     # Vérification toutes les 5 secondes
  throttle: 3  # Limite à 3 installations simultanées
  when: inventory_hostname in groups['webservers']

Convention de nommage

Convention pour les variables, il doit être possible de distinguer deux types (fonctionnel) de variables :

  • Entrées utilisateurs
  • Variables internes

Préférer les variables a plat plutôt que les variables dictionnaires (RA_CONV_OPT)

endpoint_url:
endpoint_port:

plutôt que

endpoint:
  url:
  port:

Boucles

De préférence nommer la variable de boucle (loop_var) à la place d'utiliser le nom par défaut item (RA_CONV_OPT) C'est plus lisible, et cela permet un fonctionnement non équivoque en cas de boucles imbriqués.

Il est recommandé de définir une convention de nommage pour la variable de boucle. Par exemple d'avoir toujours un suffixe _item

Utiliser label dans loop_control pour rendre l'affichage plus lisible

Fichiers

  • Devraient être dans <role_name>/files/ (ou dans files/ si appelé directement depuis un playbook ?)

Keep vaulted variables safely visible

You should encrypt sensitive or secret variables with Ansible Vault. However, encrypting the variable names as well as the variable values makes it hard to find the source of the values. To circumvent this, you can encrypt the variables individually using ansible-vault encrypt_string, or add the following layer of indirection to keep the names of your variables accessible (by grep, for example) without exposing any secrets:

  1. Create a group_vars/ subdirectory named after the group.
  2. Inside this subdirectory, create two files named vars and vault.
  3. In the vars file, define all of the variables needed, including any sensitive ones.
  4. Copy all of the sensitive variables over to the vault file and prefix these variables with vault_.
  5. Adjust the variables in the vars file to point to the matching vault_ variables using jinja2 syntax: db_password: “vault_db_password”.
  6. Encrypt the vault file to protect its contents.
  7. Use the variable name from the vars file in your playbooks.

When running a playbook, Ansible finds the variables in the unencrypted file, which pulls the sensitive variable values from the encrypted file. There is no limit to the number of variable and vault files or their names.

Note that using this strategy in your inventory still requires all vault passwords to be available (for example for ansible-playbook or AWX/Ansible Tower) when run with that inventory.

Update in batches

Use the serial keyword to control how many machines you update at once in the batch.

Voir : https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_delegation.html#playbooks-delegation

2025/11/25 11:07 · Jean-Baptiste

Pb awxkit - err helpfulargumentparser parse known args takes 3 positional arguments but 4 were given

$ awx
/home/jean/venv/awxkit/lib64/python3.12/site-packages/awxkit/cli/client.py:5: UserWarning: 
  pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html.
  The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.
  import pkg_resources
Traceback (most recent call last):
  File "/data/k8s/venv/awxkit/lib64/python3.12/site-packages/awxkit/cli/__init__.py", line 23, in run
    cli.parse_args(argv or sys.argv)
  File "/data/k8s/venv/awxkit/lib64/python3.12/site-packages/awxkit/cli/client.py", line 296, in parse_args
    self.args = self.parser.parse_known_args(self.argv)[0]
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.12/argparse.py", line 1914, in parse_known_args
    return self._parse_known_args2(args, namespace, intermixed=False)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.12/argparse.py", line 1943, in _parse_known_args2
    namespace, args = self._parse_known_args(args, namespace, intermixed)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: HelpfulArgumentParser._parse_known_args() takes 3 positional arguments but 4 were given

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/jean/venv/awxkit/bin/awx", line 7, in <module>
    sys.exit(run())
             ^^^^^
  File "/data/k8s/venv/awxkit/lib64/python3.12/site-packages/awxkit/cli/__init__.py", line 65, in run
    if cli.verbose:
       ^^^^^^^^^^^
AttributeError: 'CLI' object has no attribute 'verbose'

Solution

Source : https://github.com/ansible/awx/pull/15692

diff --git a/awxkit/awxkit/cli/utils.py b/awxkit/awxkit/cli/utils.py
index 61c2fe8f5e..9e6b5d38ff 100644
--- a/awxkit/awxkit/cli/utils.py
+++ b/awxkit/awxkit/cli/utils.py
@@ -40,14 +40,6 @@ class HelpfulArgumentParser(ArgumentParser):
         self._print_message('\n')
         self.exit(2, '%s: %s\n' % (self.prog, message))
 
-    def _parse_known_args(self, args, ns):
-        for arg in ('-h', '--help'):
-            # the -h argument is extraneous; if you leave it off,
-            # awx-cli will just print usage info
-            if arg in args:
-                args.remove(arg)
-        return super(HelpfulArgumentParser, self)._parse_known_args(args, ns)
-
 
 def color_enabled():
     return _color.enabled

FIXME

2025/11/25 09:47 · Jean-Baptiste

Créer une présentation type slides

Présentation type slides

Marp
Config

.marprc.yml

#allowLocalFiles: true
options:
  looseYAML: false
  markdown:
    breaks: false
  author: Auteur
#pdf: true
 

theme: default
 
#style: |
#  section {
#    background-color: #ccc;
#  }
#paginate: true
 
# https://git.nicco.io/cupcakearmy/marp-template/src/commit/ae39d54269bb868d151b45f70be40ad0b7cf0e3b/theme.css
theme: ./theme.css

Diapos

---
title: Titre
description: Description
#author: Auteur
keywords: kw1,kw2
#url: https://marp.app/
#image: https://marp.app/og-image.jpg
---

# Titre diapo 1

* Point 1
* Point 2
* Point 3

---

# Titre diapo 2


---

# Titre diapo 3
Themes

theming

Our core engine has 3 built-in themes called default, gaia, and uncover.

https://github.com/marp-team/marp-core/tree/main/themes/

https://rnd195.github.io/marp-community-themes/
beam
	<!-- _class: title --> needs to be specified for the first slide
border
uncover (pas terrible)
academic (marche pas sur demo.marpeditor.com)
graph_paper
rose-pine
rose-pine-moon
gaia

class: 
  - invert
  # - lead
  
<!-- _class: invert -->

<!-- _class: tinytext -->
Autres

Présentation Web

2025/11/18 14:42 · Jean-Baptiste
blog.txt · Dernière modification : de 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki