AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible Lookup Plugins: Read Files, Passwords, URLs & More (Complete Guide)

By Luca Berton · Published 2024-01-01 · Category: troubleshooting

How to use Ansible lookup plugins to access external data. Read files, environment variables, passwords, URLs, CSV, DNS.

Ansible Lookup Plugins: Read Files, Passwords, URLs & More (Complete Guide)

Ansible lookup plugins fetch data from external sources during playbook execution — files, environment variables, password stores, URLs, DNS records, and more. They run on the control node (not remote hosts) and return data you can use in variables, templates, and tasks.

See also: 10 Proven Methods to Optimize Ansible Playbook Performance

Basic Syntax

# Jinja2 lookup function
"{{ lookup('plugin_name', 'argument') }}"

# With query (returns list) "{{ query('plugin_name', 'argument') }}"

# With multiple arguments "{{ lookup('plugin_name', 'arg1', 'arg2', key='value') }}"

Essential Lookup Plugins

file — Read Local Files

- name: Read a local file
  ansible.builtin.debug:
    msg: "{{ lookup('ansible.builtin.file', '/etc/hostname') }}"

- name: Read SSH public key ansible.builtin.authorized_key: user: deploy key: "{{ lookup('ansible.builtin.file', '~/.ssh/id_ed25519.pub') }}"

- name: Read multiple files ansible.builtin.debug: msg: "{{ lookup('ansible.builtin.file', 'file1.txt', 'file2.txt') }}"

env — Read Environment Variables

- name: Get environment variable
  ansible.builtin.debug:
    msg: "Home directory is {{ lookup('ansible.builtin.env', 'HOME') }}"

- name: Use env var with default vars: db_host: "{{ lookup('ansible.builtin.env', 'DB_HOST') | default('localhost') }}" ansible.builtin.debug: msg: "Database: {{ db_host }}"

template — Render Jinja2 Templates

- name: Render a template string
  ansible.builtin.debug:
    msg: "{{ lookup('ansible.builtin.template', 'templates/config.j2') }}"

password — Generate or Read Passwords

- name: Generate random password (saved to file)
  vars:
    db_password: "{{ lookup('ansible.builtin.password', '/tmp/dbpassword length=20 chars=ascii_letters,digits') }}"
  ansible.builtin.debug:
    msg: "Password: {{ db_password }}"

- name: Generate password without saving vars: temp_pass: "{{ lookup('ansible.builtin.password', '/dev/null length=16') }}" ansible.builtin.debug: msg: "{{ temp_pass }}"

pipe — Run Shell Commands

- name: Get output of a command
  ansible.builtin.debug:
    msg: "{{ lookup('ansible.builtin.pipe', 'date +%Y-%m-%d') }}"

- name: Get git commit hash vars: git_hash: "{{ lookup('ansible.builtin.pipe', 'git rev-parse --short HEAD') }}" ansible.builtin.debug: msg: "Deploying commit {{ git_hash }}"

url — Fetch Data from URLs

- name: Get data from REST API
  ansible.builtin.debug:
    msg: "{{ lookup('ansible.builtin.url', 'https://api.example.com/config', headers={'Authorization': 'Bearer ' + api_token}) }}"

- name: Read remote JSON vars: remote_config: "{{ lookup('ansible.builtin.url', 'https://config.example.com/app.json') | from_json }}" ansible.builtin.debug: msg: "Version: {{ remote_config.version }}"

csvfile — Read CSV Data

# data.csv:
# hostname,ip,role
# web01,10.0.0.1,webserver
# db01,10.0.0.2,database

- name: Look up IP from CSV ansible.builtin.debug: msg: "{{ lookup('ansible.builtin.csvfile', 'web01 file=data.csv delimiter=, col=1') }}" # Returns: 10.0.0.1

ini — Read INI Files

- name: Read value from INI file
  ansible.builtin.debug:
    msg: "{{ lookup('ansible.builtin.ini', 'port', section='database', file='config.ini') }}"

dict — Iterate Over Dictionaries

- name: Loop over dictionary
  ansible.builtin.debug:
    msg: "{{ item.key }}: {{ item.value }}"
  loop: "{{ lookup('ansible.builtin.dict', my_dict) }}"

sequence — Generate Number Sequences

- name: Create users with sequence
  ansible.builtin.user:
    name: "user{{ item }}"
    state: present
  loop: "{{ query('ansible.builtin.sequence', 'start=1 end=5') }}"

lines — Read File Line by Line

- name: Process each line
  ansible.builtin.debug:
    msg: "Line: {{ item }}"
  loop: "{{ lookup('ansible.builtin.lines', 'cat /etc/hosts') }}"

together / zip — Combine Lists

- name: Combine two lists
  ansible.builtin.debug:
    msg: "{{ item.0 }} → {{ item.1 }}"
  loop: "{{ query('ansible.builtin.together', ['web', 'db', 'cache'], ['nginx', 'postgresql', 'redis']) }}"

first_found — Use First Existing File

- name: Include OS-specific vars
  ansible.builtin.include_vars:
    file: "{{ lookup('ansible.builtin.first_found', params) }}"
  vars:
    params:
      files:
        - "{{ ansible_distribution }}.yml"
        - "{{ ansible_os_family }}.yml"
        - default.yml
      paths:
        - vars/

See also: Maximize Ansible Efficiency with Callback Plugins for Resource Monitoring

lookup vs query

# lookup — returns comma-separated string (for backward compatibility)
"{{ lookup('ansible.builtin.file', 'a.txt', 'b.txt') }}"
# Returns: "contents_a,contents_b"

# query — always returns a list "{{ query('ansible.builtin.file', 'a.txt', 'b.txt') }}" # Returns: ["contents_a", "contents_b"]

Best practice: Use query() when looping, lookup() when you need a single value.

Error Handling

# Default: lookup fails if source is missing
# Use errors='ignore' or errors='warn'
- name: Graceful lookup
  vars:
    config: "{{ lookup('ansible.builtin.file', '/opt/config.yml', errors='ignore') | default('not found') }}"
  ansible.builtin.debug:
    msg: "Config: {{ config }}"

# With wantlist for safe iteration - name: Safe list lookup ansible.builtin.debug: msg: "{{ item }}" loop: "{{ lookup('ansible.builtin.file', maybe_missing, errors='ignore', wantlist=True) | default([]) }}"

See also: Publishing Ansible Collections to Ansible Galaxy and Automation Hub

Custom Lookup Plugins

# plugins/lookup/my_lookup.py
from ansible.plugins.lookup import LookupBase

class LookupModule(LookupBase): def run(self, terms, variables=None, **kwargs): results = [] for term in terms: results.append(f"processed: {term}") return results

- name: Use custom lookup
  ansible.builtin.debug:
    msg: "{{ lookup('my_lookup', 'test') }}"

FAQ

What are Ansible lookup plugins?

Lookup plugins fetch data from external sources (files, environment variables, URLs, databases) during playbook execution. They run on the control node and return data for use in variables, templates, and task parameters.

What is the difference between lookup and query in Ansible?

lookup() returns results as a comma-separated string for backward compatibility. query() always returns a list. Use query() when looping over results and lookup() when you need a single string value.

How do I read a file in Ansible?

Use lookup('ansible.builtin.file', '/path/to/file') to read a local file on the control node. For remote files, use the ansible.builtin.slurp module instead.

Can lookup plugins access remote hosts?

No. Lookup plugins run only on the Ansible control node. To read data from remote hosts, use modules like ansible.builtin.slurp, ansible.builtin.fetch, or ansible.builtin.command.

How do I handle errors in lookup plugins?

Pass errors='ignore' to suppress errors and return an empty string, or errors='warn' to log a warning. Combine with | default('fallback') for safe defaults.

Conclusion

Lookup plugins are essential for dynamic playbooks that pull data from files, environment variables, APIs, and other sources. Use FQCN (ansible.builtin.file) for clarity and query() when you need list results.

Related Articles

Ansible Variables: Complete GuideAnsible set_fact: Create Runtime VariablesAnsible Jinja2 Filters: Complete Reference

Category: troubleshooting

Browse all Ansible tutorials · AnsiblePilot Home