A lookup plug-in is an Ansible extension to the Jinja2 templating language. These plug-ins enable Ansible to use data from external sources, such as files and the shell environment.
You can call lookup plug-ins with one of two Jinja2 template functions, lookup or query.
Both methods have a syntax that is similar to filters.
Specify the name of the function, and in parentheses the name of the lookup plug-in that you want to call and any arguments that the plug-in needs.
For example, the following variable definition uses the file lookup plug-in to put the contents of the /etc/hosts file into the hosts Ansible variable:
vars:
hosts: "{{ lookup('ansible.builtin.file', '/etc/hosts') }}"You can include more than one file name to the file plug-in.
When called with the lookup function, the contents of each file is separated by a comma in the resulting value.
Consider the following Jinja2 template expression:
vars:
hosts: "{{ lookup('ansible.builtin.file', '/etc/hosts', '/etc/issue') }}"This expression results in the following structure (line-wrapped):
hosts: "127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4\n::1 localhost localhost.localdomain localhost6 localhost6.localdomain6\n\n,\\S\nKernel \\r on an \\m (\\l)"In Ansible 2.5 and later, the query function, or its abbreviation q, can be used instead of lookup to call lookup plug-ins.
The difference between the two is that instead of the returned values being comma-separated, query always returns a list, which can be easier to parse and work with.
You can use the following to call the preceding example:
vars:
hosts: "{{ query('ansible.builtin.file', '/etc/hosts', '/etc/issue') }}"The query call returns the following data structure (line-wrapped):
hosts: - "127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4\n::1 localhost localhost.localdomain localhost6 localhost6.localdomain6\n\n" - "\\S\nKernel \\r on an \\m (\\l)"
The default Ansible installation provides numerous plug-ins.
Use the ansible-navigator doc --mode stdout -t lookup -l command to obtain the complete list of available lookup plug-ins.
For details about the purpose of specific plug-ins and how to use them, run the ansible-navigator doc --mode stdout -t lookup command.PLUGIN_NAME
Ansible uses the file plug-in to load the contents of a local file into a variable.
If you provide a relative path, the plug-in looks for files in the playbook's files directory.
The following example reads the contents of the user's public key file and uses the ansible.posix.authorized_key module to add the authorized key to the managed host.
The example uses a loop and the + operator to append strings in the template to look up the files/fred.key.pub and files/naoko.key.pub files.
- name: Add authorized keys
hosts: all
vars:
users:
- fred
- naoko
tasks:
- name: Add authorized keys
ansible.posix.authorized_key:
user: "{{ item }}"
key: "{{ lookup('ansible.builtin.file', item + '.key.pub') }}"
loop: "{{ users }}"In the preceding example, the public key files are included in the Ansible project's files subdirectory, so that they are available inside the execution environment.
The file plug-in can parse YAML and JSON files into properly structured data by using the from_yaml or from_json filters.
my_yaml: "{{ lookup('ansible.builtin.file', '/path/to/my.yaml') | from_yaml }}"The file plug-in reads files that are in the execution environment, not on the control node or managed host.
Execution environments read files that are inside of the execution environment container, not those on the host on which you ran the ansible-navigator command.
If you use the ansible-playbook command, or the ansible-navigator command with the --ee false option, then the execution environment is the same as the control node.
If you need the content of a file that is not in the execution environment or your project directory, then you can use the ansible.builtin.slurp module instead of a lookup plug-in.
The following example sets the pub_key variable using the content of the /home/user/.ssh/id_rsa.pub file on the managed host:
- name: Collect file content
ansible.builtin.slurp:
src: /home/user/.ssh/id_rsa.pub
register: slurped_file
- name: Print returned information
vars:
pub_key: "{{ slurped_file['content'] | b64decode }}"
ansible.builtin.debug:
var: pub_keyLike the file plug-in, the template plug-in returns the contents of files.
The difference is that the template plug-in expects the file contents to be a Jinja2 template, and it evaluates that template before applying the contents.
If you pass a relative path to the template file, the plug-in looks for it within the playbook templates directory.
The following example processes the templates/my.template.j2 template.
{{ lookup('ansible.builtin.template', 'my.template.j2') }}For example, assume that the template contains the following content:
Hello {{ name }}.The following task displays the string "Hello class.".
- name: Print "Hello class."
vars:
name: class
ansible.builtin.debug:
msg: "{{ lookup('ansible.builtin.template', 'my.template.j2') }}"The template plug-in also accepts some extra parameters, such as defining the start and end marking sequences.
In case the output string is a YAML value, the convert_data option parses the string to provide structured data.
Do not confuse the template lookup plug-in with the template module.
The pipe and lines plug-ins both run a command in the execution environment and return the output.
The pipe plug-in returns the raw output generated by the command; the lines plug-in splits the output of that command into lines.
For example, consider the following Jinja2 expression:
{{ query('ansible.builtin.pipe', 'ls files') }}This expression returns the raw output of the ls command as a string.
If you use the lines plug-in, then the expression is as follows:
{{ query('ansible.builtin.lines', 'ls files') }}This command results in a list with each line of output returned by ls as a list item.
You can use this functionality to retrieve the first line (or any specific line) of output from a set of commands:
- name: Prints the first line of some files
ansible.builtin.debug:
msg: "{{ item[0] }}"
loop:
- "{{ query('ansible.builtin.lines', 'cat files/my.file') }}"
- "{{ query('ansible.builtin.lines', 'cat files/my.file.2') }}"Note that this example might not be the most efficient way to do this particular task, given the existence of the head command.
Similar to the way the file plug-in gets content from a file, the url plug-in gets content from a URL.
{{ lookup('ansible.builtin.url', 'https://my.site.com/my.file') }}Many options are available for controlling authentication, selecting web proxies, or splitting the returned content into lines.
However, one advantage of using the url plug-in is that you can use the returned data as values in your variables, possibly processing it first with a filter.
The kubernetes.core.k8s plug-in provides full access to the Kubernetes API through the openshift Python module.
To fetch a Kubernetes object, you must provide the object type by using the kind option.
Providing additional object details, such as the namespace or label_selector option, helps to filter the results:
{{ lookup('kubernetes.core.k8s', kind='Deployment', namespace='ns', resource_name='my_res') }}Be aware that the kubernetes.core.k8s plug-in is a lookup plug-in.
Its primary purpose is to extract information from the Kubernetes cluster, not to update it.
Use the kubernetes.core.k8s
module to manage a Kubernetes cluster.
Plug-ins are Python scripts. You can develop custom plug-ins and use them in your playbooks. For Ansible to find your lookup plug-ins, copy them into one of the following locations:
In a custom Ansible Content Collection, copy the lookup plug-in scripts into the ./plugins/lookup directory.
In a custom role, copy the lookup plug-in scripts into the ./filter_plugins directory.
In an Ansible project, copy the lookup plug-in scripts into the ./lookup_plugins directory in the same directory as the playbooks.
The Ansible team recommends using collections to distribute custom plug-ins. Plug-in development is beyond the scope of this course.
Most Ansible plug-ins are designed to abort the Ansible Playbook in the event of a failure.
However, the lookup function delegates execution to other plug-ins that might not need to abort the Ansible Playbook in such an event.
For example, the file plug-in might not need to abort the Ansible Playbook if the file is not found, but playbook execution might need to continue after recovery.
To adapt to different plug-in needs, the lookup plug-in accepts the errors parameter.
{{ lookup('ansible.builtin.file', 'my.file', errors='warn') }}The default value for the errors option is strict.
This means that the lookup plug-in raises a fatal error if the underlying script fails.
If the errors option has the value warn, then the lookup plug-in logs a warning when the underlying script fails and returns an empty string (or an empty list).
If the errors option has the value ignore, then the lookup plug-in silently ignores the error and returns an empty string or list.