Ansible concat default variable and literal string

Anand Rao picture Anand Rao · Jun 21, 2017 · Viewed 8.9k times · Source

I'm not able to do a very simple thing.

In my task I'm trying to concat two default variables with a literal string to create a path

- name: "Uploading File"
  copy:
    src: "{{ installer_iso_src_location }}"/"{{ installer_version }}"/filename.iso
    dest: /opt/temp/filename.iso

This gives me a error. Any idea how to concatenate a variable and literal strings?

Answer

techraf picture techraf · Jun 25, 2017

Firstly, YAML

  1. Your syntax must conform to YAML:

    Strings (scalars) are ordinarily unquoted, but may be enclosed in double-quotes ("), or single-quotes (').

    So you can either write:

    parameter: value
    

    or

    parameter: 'value'
    

    or

    parameter: "value"
    

    The following is not a valid YAML:

    "{{ installer_iso_src_location }}"/"{{ installer_version }}"/filename.iso
    
  2. If your value starts with a curly brace { Ansible will try to parse it as a dictionary (YAML is a supserset of JSON, so a dictionary/associative array enclosed in curly braces is a valid syntax).

    Associative arrays are represented using the colon space (: ) in the form key: value, either one per line or enclosed in curly braces ({ }) and separated by comma space (, ).

    If it's not a valid JSON array, Ansible will report a syntax error.

Secondly, Jinja2:

  • The majority of parameters in Ansible (the value of when being a notable exception) are Jinja2 templates (strings).

    To refer to an Ansible-variable-value you use a Jinja2 expression delimited by {{ and }} (no quotes involved):

    {{ variable }}
    

    There are two ways to concatenate strings with variable values for your case:

    {{ installer_iso_src_location }}/{{ installer_version }}/filename.iso
    

    or

    {{ installer_iso_src_location + '/' + installer_version + '/filename.iso' }}
    

Now, YAML and Jinja2 combined:

  • Since your parameter (string) starts with { character and it is not a valid YAML/JSON dictionary, the YAML parser will fail (see the point 2. of the above YAML requirements).

    In result, for your value to be considered a string by YAML parser, you must enclose the value (Jinja2 template) in quotes:

    src: "{{ installer_iso_src_location }}/{{ installer_version }}/filename.iso"
    

    or

    src: "{{ installer_iso_src_location + '/' + installer_version + '/filename.iso' }}"
    

    or other combination of single and double quotes.

  • If your parameter value started with a string other than {, you could use it without quotes, as in the first example in the point 1. above.


Lastly, there are two notable exceptions where value is not expected to follow YAML rules:

  • Ansible shorthand syntax for modules with key-value pairs joined by =
  • free-form parameter, as for example in the command or shell modules