5

I want to define an Ansible role and register dynamic variables:

---
- name: Check for {{ package }}
  stat: path=/opt/packages/{{ package }}
  register: "{{ package | regex_replace('-', '_') }}"
- name: Install {{ package }} {{ package_version }}
  command: "custom-package-installer {{ package }} {{ package_version }}"
  when: "not {{ package | regex_replace('-', '_') }}.stat.exists"

Usage looks like this:

- include: install_package.yml package=foo package_version=1.2.3

However, Ansible doesn't recognise the conditional:

TASK: [example | Install foo 1.2.3] *********************************** 
fatal: [my-server] => error while evaluating conditional: not foo.stat.exists

FATAL: all hosts have already failed -- aborting

How can I define variables dynamically, expanding the {{ }}?

Wilfred Hughes
  • 29,846
  • 15
  • 139
  • 192

3 Answers3

8

There is no way to register a dynamic variable. There is no way for a placeholder {{ var }} in register. However there is a much cleaner way to perform what I think you are trying to achieve: Ansible: it's a fact.

Short summary:

You can write a simple script which prints JSON like:

#!/bin/python #or /bin/bash or any other executable
....

print """{ "ansible_facts": {
              "available_packages": ["a", "b", "c"]
               }
          }"""

and put it into your local facts folder on the machine (as executable script with .fact ending):

Your second task would then look like:

- name: Install {{ package }} {{ package_version }}
  command: "custom-package-installer {{ package }} {{ package_version }}"
  when: "not package in ansible_facts['available_packages']"

Ansible docs on facts.

Wilfred Hughes
  • 29,846
  • 15
  • 139
  • 192
ProfHase85
  • 11,763
  • 7
  • 48
  • 66
2

You don't need a dynamic variable in this case, doing:

---
- name: Check for {{ package }}
  stat: path=/opt/packages/{{ package }}
  register: current_package

- name: Install {{ package }} {{ package_version }}
  command: "custom-package-installer {{ package }} {{ package_version }}"
  when: not current_package.stat.exists

is perfectly fine...

Mathias Henze
  • 2,190
  • 1
  • 12
  • 8
0

Like many things, this is possible if you really want to do it, but natively in ansible it is not supported.

That said, ansible is written in python and you can call the playbooks from directly within python code. The way that I do this is to dynamically generate the playbooks and then execute them in a two step process.

In effect, it is like having dynamic playbooks. So to summarise...

  1. Generate playbook using whatever logic is appropriate.
  2. Execute playbook using ansible.
mransley
  • 631
  • 7
  • 16