There is a json file (this content is transferring as base64 to playbook):
$ cat json
{
"name": "some_value",
"envs": "ENV_TEST=true ENV_TEXT={{additional_variable}}"
}
Convert to b64 format:
$ cat json | base64 | tr -d "\n"
ewogICJuYW1lIjogInNvbWVfdmFsdWUiLAogICJlbnZzIjogIkVOVl9URVNUPXRydWUgRU5WX1RFWFQ9e3thZGRpdGlvbmFsX3ZhcmlhYmxlfX0iCn0K
Extra vars for playbook (additional_variable and json_props):
-e additional_variable=additionaltext -e json_props=ewogICJuYW1lIjogInNvbWVfdmFsdWUiLAogICJlbnZzIjogIkVOVl9URVNUPXRydWUgRU5WX1RFWFQ9e3thZGRpdGlvbmFsX3ZhcmlhYmxlfX0iCn0K
Playbook:
---
- hosts: test
gather_facts: False
vars:
props: "{{ json_props | b64decode | from_json }}"
prop:
envs: "{{ props.envs }}"
tasks:
- debug:
msg: "{{ additional_variable }}"
- debug:
msg: "{{ prop.envs }}"
Output:
TASK [debug] **********************************************************************
ok: [127.0.0.1] => {
"msg": "additionaltext"
}
TASK [debug] **********************************************************************
ok: [127.0.0.1] => {
"msg": "ENV_TEST=true ENV_TEXT={{additional_variable}}"
}
How to set variable additional_variable from extra vars to the prop.envs string?
Any ideas?
I expect that output will be "ENV_TEST=true ENV_TEXT=additionaltext"
The problem is that the value of the variable props have already been 'templated' in the expression
props: "{{ json_props|b64decode|from_json }}"
You've already found out that given the extra variables
shell> cat evars.yml
additional_variable: additionaltext
json_props: ewogICJuYW1lIjogInNvbWVfdmFsdWUiLAogICJlbnZzIjogIkVOVl9URVNUPXRydWUgRU5WX1RFWFQ9e3thZGRpdGlvbmFsX3ZhcmlhYmxlfX0iCn0K
The playbook
shell> cat pb.yml
- hosts: localhost
vars:
props: "{{ json_props|b64decode|from_json }}"
tasks:
- debug:
var: props
gives
shell> ansible-playbook -e @evars.yml pb.yml
PLAY [localhost] ******************************************************************************
TASK [debug] **********************************************************************************
ok: [localhost] =>
props:
envs: ENV_TEST=true ENV_TEXT={{additional_variable}}
name: some_value
The variable additional_variable was not substituted in the attribute envs and explicit expansion of the attribute doesn't help either. Ansible doesn't provide a tool to 'template' a value of a variable in vars. But, you can create a custom filter on your own
shell> cat plugins/filter/template.py
from jinja2 import Environment, BaseLoader
def template(my_string, my_vars):
rtemplate = Environment(loader=BaseLoader).from_string(my_string)
return(rtemplate.render(my_vars))
class FilterModule(object):
def filters(self):
return {
'template': template,
}
Configure the path to the filter plugins DEFAULT_FILTER_PLUGIN_PATH. For example,
shell> grep filter ansible.cfg
filter_plugins = $PWD/plugins/filter
and use the filter template. As a second argument of the filter you have to provide a dictionary with the variables the template needs for the substitutions
prop:
envs: "{{ props.envs|template(vars) }}"
gives what you want
prop:
envs: ENV_TEST=true ENV_TEXT=additionaltext
shell> cat pb.yml
- hosts: localhost
vars:
props: "{{ json_props|b64decode|from_json }}"
prop:
envs: "{{ props.envs|template(vars) }}"
tasks:
- debug:
var: props
- debug:
var: additional_variable
- debug:
var: prop
- set_fact:
envs: "{{ props.envs|template(my_vars) }}"
vars:
my_vars:
additional_variable: "{{ additional_variable }}"
- debug:
var: envs
gives
shell> ansible-playbook -e @evars.yml pb.yml
PLAY [localhost] ******************************************************************************
TASK [debug] **********************************************************************************
ok: [localhost] =>
props:
envs: ENV_TEST=true ENV_TEXT={{additional_variable}}
name: some_value
TASK [debug] **********************************************************************************
ok: [localhost] =>
additional_variable: additionaltext
TASK [debug] **********************************************************************************
ok: [localhost] =>
prop:
envs: ENV_TEST=true ENV_TEXT=additionaltext
TASK [set_fact] *******************************************************************************
ok: [localhost]
TASK [debug] **********************************************************************************
ok: [localhost] =>
envs: ENV_TEST=true ENV_TEXT=additionaltext
PLAY RECAP ************************************************************************************
localhost: ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
shell> cat /tmp/test.json
{
"name": "some_value",
"envs": "ENV_TEST=true ENV_TEXT={{ additional_variable }}"
}
include the variables from the file into a dictionary by include_vars
shell> cat pb.yml
- hosts: localhost
tasks:
- include_vars:
file: "{{ file_json_props }}"
name: props
- debug:
var: props
This way the expressions are 'templated' (expanded) automatically
shell> ansible-playbook -e additional_variable=additionaltext -e file_json_props=/tmp/test.json pb.yml
PLAY [localhost] ******************************************************************************
TASK [debug] **********************************************************************************
ok: [localhost] =>
additional_variable: additionaltext
TASK [include_vars] ***************************************************************************
ok: [localhost]
TASK [debug] **********************************************************************************
ok: [localhost] =>
props:
envs: ENV_TEST=true ENV_TEXT=additionaltext
name: some_value
PLAY RECAP ************************************************************************************
localhost: ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0