Ansible – variable within variable

ansibleansible-playbookjinja2variables

Ansible 1.9.2 version.

Does Ansible supports variable expansion within a variable while evaluating it.

I have a task to download 3 zip files from Artifactory.

Instead of writing 3 separate tasks within the role, I used ansible's loop in the playbook. In Ansible role's default/main.yml, I have all the required variables defined/available to the role i.e. jmeterplugins_extras_artifactory_url and other (standard / webdriver) are visible to perf_tests role.

---
#- Download and install JMeterPlugins
# Use get_url when Ansible is 2.0+ is available on the machine (otherwise, we can't use get_url) thus, using wget.
- name: Download JMeterPlugins-*
  command: wget {{ jmeterplugins_{{ item.plugin }}_artifactory_url }}  
    chdir="{{ common_download_dir }}"
    creates="{{ common_download_dir }}/{{ jmeterplugins_{{ item.plugin }}_file }}"
  with_items:
    - { plugin: 'extras' }
    - { plugin: 'standard' }  
    - { plugin: 'webdriver' }   

But with the above code, I'm getting an error (as shown below):

15:58:57 TASK: [perf_tests | Download JMeterPlugins-*] ********************************* 
15:58:57 <jmeter01.super.fast.jenkins> ESTABLISH CONNECTION FOR USER: cmuser on PORT 22 TO jmeter01.super.fast.jenkins
15:58:57 fatal: [jmeter01.super.fast.jenkins] => Failed to template wget {{ jmeterplugins_{{ item.plugin }}_artifactory_url }} chdir="{{ common_download_dir }}" creates="{{ common_download_dir }}/{{ jmeterplugins_{{ item.plugin }}_file }}": template error while templating string: expected token 'variable_end', got '{'
15:58:57 
15:58:57 FATAL: all hosts have already failed -- aborting
15:58:57 
15:58:57 PLAY RECAP ******************************************************************** 
15:58:57            to retry, use: --limit @/home/cmuser/perf_tests.retry
15:58:57 
15:58:57 jmeter01.super.fast.jenkins : ok=23   changed=6    unreachable=1    failed=0   

Doesn't ansible supports variable expansion/evaluation if a variable contains another variable (especially when I'm using a loop).

I just dont want to expand my simple loop task into 3 different -name tasks for downloading zip files for jmeterplugins_extras, jmeterplugins_standard and jmeterplugins_webdriver separately. It seems like the error is related due to Jinja.

How can I use var's value giga in another variable i.e. if var contains giga, then I should get the value of variable "special_giga_variable" ({{special_{{ var }}_variable}})? where var was defined in defaults/main.yml as:

var: giga

Best Answer

It does.

You can use

set_fact:
  variable: '{{ vars['my_' + variablename + '_variable'] }}'

the only downside of this approach so far is, it won't dynamically expand variables that get the value of another variable. an example:

roles/xxx/defaults/main.yml:

var1: foo
var2: '{{ var1 }}'

This, unfortunately will not work when trying to use the resolved value in var2. Hence,

- debug: msg='{{ vars["var2"] }}'

will output {{ var1 }} instead of foo.

Workaround:

In your vars declaration, instead of using var2: {{ var1 }}, use var2: '{{ vars["var1"] }}'. That way, it will work.