Aller au contenu
Infrastructure as Code medium

Lookups Ansible : récupérer des données externes au runtime

11 min de lecture

Logo Ansible

Un lookup Ansible récupère une donnée depuis une source externe au moment de l’évaluation Jinja2. Lire le contenu d’un fichier local, une variable d’environnement, le résultat d’une commande, un secret HashiCorp Vault, une ligne d’un CSV — tout passe par les plugins lookup. Cette page couvre les lookups built-in essentiels : file, env, pipe, password, vars, csvfile, ini, dig. Et la nuance importante : un lookup s’exécute côté control node, pas côté managed node.

C’est l’outil de prédilection pour injecter des secrets depuis un coffre local, paramétrer un playbook depuis un fichier de config, ou parser un CSV de hôtes.

  • La syntaxe lookup('plugin', args) et la différence avec query ;
  • Les lookups built-in essentiels : file, env, pipe, password, vars ;
  • Que les lookups s’exécutent côté control node (pas managed node) ;
  • Combiner plusieurs lookups dans un même template ;
  • Cas pratiques : injection de secret, paramétrage CI/CD, génération de mot de passe.
{{ lookup('plugin_name', 'arg1', 'arg2', option=value) }}

Le plugin_name identifie le lookup, suivi des arguments propres au plugin. Quelques plugins essentiels :

PluginRôleExemple
fileLit le contenu d’un fichier locallookup('file', 'files/secret.txt')
envVariable d’environnement du shell qui a lancé Ansiblelookup('env', 'USER')
pipeExécute une commande locale et retourne stdoutlookup('pipe', 'date +%Y-%m-%d')
passwordGénère et stocke un mot de passelookup('password', '/tmp/.pass length=20')
varsLit une variable Ansible existante (utile en boucle)lookup('vars', 'app_' + env)
csvfileCherche une ligne dans un CSVlookup('csvfile', 'web1 file=hosts.csv col=2')
iniLit une clé d’un fichier INIlookup('ini', 'name section=Owner file=app.ini')
digRésolution DNSlookup('dig', 'web1.lab')
hashi_vaultHashiCorp Vaultlookup('community.hashi_vault.vault_kv2_get', 'secret/data/api')

Point crucial : un lookup s’exécute côté control node (votre poste), pas côté managed node. Conséquences :

  • lookup('file', 'foo.txt') lit foo.txt sur votre poste ;
  • lookup('env', 'USER') lit $USER du shell qui a lancé ansible-playbook ;
  • lookup('pipe', 'hostname -s') retourne le hostname du control node, pas du managed node.

C’est par dessein : un lookup sert souvent à injecter une donnée du dépôt ou de l’environnement de CI/CD dans le playbook.

Cas pratique — combinaison de 3 lookups (lab ecrire-code/lookups)

Section intitulée « Cas pratique — combinaison de 3 lookups (lab ecrire-code/lookups) »

Voici l’exemple validé sur le lab 17-ecrire-code-lookups :

---
- name: Challenge lookups
hosts: db1.lab
become: true
tasks:
- name: Poser un fichier qui combine 3 lookups
ansible.builtin.copy:
dest: /tmp/lookups-challenge.txt
content: |
token={{ lookup('file', 'files/api-token.txt') }}
home={{ lookup('env', 'HOME') }}
host_local={{ lookup('pipe', 'hostname -s') }}
mode: "0644"

Avec files/api-token.txt côté control node contenant MAGIC-TOKEN-RHCE-2026 :

Contenu de /tmp/lookups-challenge.txt sur db1.lab :

token=MAGIC-TOKEN-RHCE-2026
home=/home/bob
host_local=master1

Tous les lookups ont été résolus côté control node (votre poste), puis le copy: a transféré le contenu vers db1.

query est strictement équivalent à lookup mais retourne toujours une liste :

{{ lookup('file', 'a.txt') }} ← retourne le contenu (string ou liste selon plugin)
{{ query('file', 'a.txt') }} ← retourne TOUJOURS une liste

Utile dans une boucle :

- name: Itérer sur les fichiers
ansible.builtin.debug:
msg: "{{ item }}"
loop: "{{ query('fileglob', 'files/*.txt') }}"

fileglob ne renvoie pas une seule entrée mais une liste de fichiers matchant le glob — query ou lookup retournent tous deux ici une liste.

Règle pratique : query quand vous itérez (loop:), lookup quand vous interpolez une seule valeur.

- name: Distribuer un certificat depuis le control node
ansible.builtin.copy:
dest: /etc/ssl/cert.pem
content: "{{ lookup('file', 'files/ca-bundle.pem') }}"
mode: "0644"

Le fichier files/ca-bundle.pem est lu localement ; son contenu est posé côté managed node.

- name: Tag de release fourni par CI
ansible.builtin.debug:
msg: "Tag : {{ lookup('env', 'CI_COMMIT_TAG') }}"

Lit $CI_COMMIT_TAG du shell. Très utilisé en CI/CD.

- name: Récupérer la version Git du repo
ansible.builtin.set_fact:
git_version: "{{ lookup('pipe', 'git -C ' + playbook_dir + ' rev-parse HEAD') }}"

Exécute git rev-parse HEAD côté control node et capture la sortie.

- name: Mot de passe d'un user PostgreSQL
ansible.builtin.user:
name: appuser
password: "{{ lookup('password', '/srv/secrets/appuser.pwd length=24 chars=ascii_letters,digits') }}"

Le lookup génère un mot de passe aléatoire la première fois, le stocke dans /srv/secrets/appuser.pwd côté control node, et le retourne à chaque appel suivant. Idempotent — tant que le fichier existe, le mot de passe ne change pas.

Caractères supportés : ascii_letters, digits, punctuation, ou un set custom.

Utile pour construire dynamiquement le nom d’une variable :

vars:
app_dev: { port: 8000 }
app_prod: { port: 80 }
tasks:
- name: Récupérer la conf dynamiquement
ansible.builtin.debug:
msg: "{{ lookup('vars', 'app_' + env).port }}"

Avec env=prod, vous lisez app_prod.port.

- name: Lire un secret depuis Vault
ansible.builtin.set_fact:
api_key: "{{ lookup('community.hashi_vault.vault_kv2_get', 'secret/data/api', url='https://vault.example.com').data.data.api_key }}"

Demande la collection community.hashi_vault (ansible-galaxy collection install community.hashi_vault).

SymptômeCauseFix
lookup('file', ...) retourne FileNotFoundErrorFichier introuvable depuis le cwd du playbookUtiliser un path absolu ou playbook_dir + '/files/...'
lookup('env', 'X') retourne ''Variable non posée dans le shell qui a lancé ansible-playbookAjouter default('') : `lookup(‘env’, ‘X’)
lookup('pipe', '...') planteLa commande ne s’exécute pas (erreur shell, binaire absent)Tester la commande à la main d’abord ; ajouter 2>/dev/null
Lookup re-exécuté à chaque taskC’est le comportement par défautCapturer dans set_fact une fois, réutiliser
Performance : 1000 lookups dans un loopExécutés à chaque itération côté controlPré-charger via set_fact ou vars_files
  • lookup('plugin', args) = récupération depuis une source externe, exécutée côté control node.
  • Plugins essentiels : file, env, pipe, password, vars, csvfile, hashi_vault.
  • query retourne toujours une liste — préférer pour les boucles.
  • Un lookup ne sait rien des managed nodes — pour lire un fichier distant, utiliser slurp ou command: cat.
  • lookup('password', ...) est idempotent : il génère puis réutilise le mot de passe stocké.

Cette page a un lab d’accompagnement : labs/ecrire-code/lookups/ dans stephrobert/ansible-training. Il contient un README.md guidé, un Makefile (make verify lance les tests), et un challenge final auto-évalué : combiner 3 lookups (file, env, pipe) pour générer un fichier marqueur côté managed node.

Une fois le lab provisionné :

Fenêtre de terminal
cd ~/Projets/ansible-training/labs/ecrire-code/lookups/
cat README.md # tuto pas à pas
cat challenge/README.md # consigne du challenge final
pytest -v challenge/tests/ # lancer les tests testinfra

Si les tests passent, vous maîtrisez les concepts couverts dans ce guide. En cas de blocage, docs/troubleshooting.md à la racine du repo couvre les pièges fréquents (rate-limit SSH, clé absente, collection manquante).

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn