Passing simple strings to an ansible playbook as extra-vars is easy, but what if you want to pass lists or dictionary? Let's see...
Passing variables at runtime
As mentioned in the official docu one can pass variables at runtime using --extra-vars
or -e
. Values passed in using the key=value
syntax are interpreted as string
$ ansible-playbook release.yml \
--extra-vars "version=1.23.45 other_variable=foo"
The above command will define two variables version
and other_variable
. Now if you want to pass dicts
or lists
you can define it in a external json or yaml file
ansible-playbook release.yml --extra-vars "@some_file.json"
This still may be cumbersome sometime, especially the extra vars you choose may change. For [bootstrapping my servers](({ ref “2021-04-what-are-tags-in-ansible-and-how-to-use-them” })) I have a playbook which expects to pass a parameter hcloud_server_labels
which should assign certain labels to the server. This expects a key-value pair i.e. a dictionary.

This can be done using JSON string format. The extra vars for a have to be wrapped in a single quote '
, whereas the dictionary itself is wrapped with curly brackets {
and }
. In case you want to pass a list, you use square brackets [
and ]
, instead the curly brackets
Let’s make a test
This seems simple, so let’s check with this playbooks:
- name: Test passing different types of extra vars
hosts: localhost
tasks:
- name: Show dictionary values
debug:
msg:
- "Key1: {{ key1 }}"
- "Key2: {{ key2 }}"
when: key1 is defined
$ ansible-playbook extra-vars-example.yml \
-e '{"key1":"value1","key2":"value2"}'
...
TASK [Show dictionary values] **********************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
"Key1: value1",
"Key2: value2"
]
}
...
That looks ok, but what if I want to assign the dictionary to a variable? Let’s modify the playbook:
- name: Test passing different types of extra vars
hosts: localhost
tasks:
- name: Show dictionary values
debug:
msg:
- "Key1: {{ key1 }}"
- "Key2: {{ key2 }}"
when: key1 is defined
- block:
- name: Show dictionary assigned to a variable
debug:
msg:
- "{{ sample_dict | from_yaml_all }}"
- " is of type '{{ sample_dict | type_debug }}'"
- name: Show dictionary values
debug:
msg:
- "{{ item.key }}: {{ item.value }}"
with_dict: "{{ sample_dict }}
when: sample_dict is defined
I want the dictionary be accessible as sample_dict
so I do
$ ansible-playbook extra-vars-example.yml \
-e sample_dict='{"key1":"value1","key2":"value2"}'
...
TASK [Show dictionary assigned to a variable] ******************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
[
{
"key1": "value1",
"key2": "value2"
}
],
" is of type 'str'"
]
}
TASK [Show dictionary values] **********************************************************************************************************************************************************************************
ok: [localhost] => (item={'key': 'key1', 'value': 'value1'}) => {
"msg": [
"key1: value1"
]
}
ok: [localhost] => (item={'key': 'key2', 'value': 'value2'}) => {
"msg": [
"key2: value2"
]
}
PLAY RECAP *****************************************************************************************************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Well the variable sample_dict
is considered a str
instead a dict
, however, the iteration seems to work. Still, there must be something wrong. Let’s try
this
$ ansible-playbook extra-vars-example.yml \
-e '{ "sample_dict": {"key1":"value1","key2":"value2"}}'
...
TASK [Show dictionary assigned to a variable] ******************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
{
"key1": "value1",
"key2": "value2"
},
"is of type 'dict'"
]
}
TASK [Show dictionary values] **********************************************************************************************************************************************************************************
ok: [localhost] => (item={'key': 'key1', 'value': 'value1'}) => {
"msg": [
"key1: value1"
]
}
ok: [localhost] => (item={'key': 'key2', 'value': 'value2'}) => {
"msg": [
"key2: value2"
]
}
PLAY RECAP *****************************************************************************************************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Cool, now the same for a list with the modified playbook
- name: Test passing different types of extra-vars
hosts: localhost
tasks:
- block:
- name: Show list assigned to a variable
debug:
msg:
- "{{ sample_list | from_yaml_all }}"
- "is of type '{{ sample_list | type_debug }}'"
- name: Show list values
debug:
msg:
- "{{ item }}"
with_items: "{{ sample_list }}"
when: sample_list is defined
$ ansible-playbook extra-vars-example.yml \
-e '{ "sample_list": [ "list_value_1", "list_value_2", "list_value_3" ]}'
...
TASK [Show list assigned to a variable] ************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
[
"list_value_1",
"list_value_2",
"list_value_3"
],
"is of type 'list'"
]
}
TASK [Show list values] ****************************************************************************************************************************************************************************************
ok: [localhost] => (item=list_value_1) => {
"msg": [
"list_value_1"
]
}
ok: [localhost] => (item=list_value_2) => {
"msg": [
"list_value_2"
]
}
ok: [localhost] => (item=list_value_3) => {
"msg": [
"list_value_3"
]
}
PLAY RECAP *****************************************************************************************************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Obviously I can combine these by either using multiple -e
parameter:
ansible-playbook extra-vars-example.yml \
-e '{ "sample_dict": {"key1":"value1","key2":"value2"}}' \
-e '{ "sample_list": [ "list_value_1", "list_value_2", "list_value_3" ]}' \
-e 'simple_string_1=test simple_string_2="another test"'
or with a single e
parameter
ansible-playbook extra-vars-example.yml \
-e '{ "sample_dict": {"key1":"value1","key2":"value2"}, "sample_list": [ "list_value_1", "list_value_2", "list_value_3" ], "simple_string_1": "test", "simple_string_2": "another test" }'
You can find the complete playbook extra-vars-example.yml
in my ansible-playground
And what about my use case?
Well, for my use case the command I call, would look like this:
ansible-playbook bootstrap-hcloud_servers.yml \
--tags hcloud-server \
-e server_names="dev0001" \
-e '{ "hcloud_server_labels": {"dev":"","k8s":"master" }}'