Since I have found the Ansible documentation to be lacking, and StackOverflow insufficient in this matter, I feel the need to share how you can append to a list using Ansible.
I’ve created a demonstration playbook and published it on GitHub. See: https://github.com/betrcode/ansible-append-list
How to merge two lists together:
- debug: msg="Append list to list, or merge two lists" - name: Setup two lists to be merged set_fact: list_one: - 1 - 2 - 3 list_two: - 4 - 5 - 6 - name: Merge the two lists set_fact: lists_merged: "{{ list_one + list_two }}" - name: Demonstrate merged lists debug: var=lists_merged
The output will be:
TASK [debug] ******************************************************************* ok: [localhost] => { "msg": "Append list to list, or merge two lists" } TASK [Setup two lists to be merged] ******************************************** ok: [localhost] TASK [Merge the two lists] ***************************************************** ok: [localhost] TASK [Demonstrate merged lists] ************************************************ ok: [localhost] => { "lists_merged": [ 1, 2, 3, 4, 5, 6 ] }
Appending a single item to a list is trickier, especially when it’s a string. Here’s how to do it:
- name: Initialize an empty list for our strings set_fact: my_strings: [] - name: Setup a string variable set_fact: my_name: "Max" - name: Append string to list set_fact: my_strings: "{{ my_strings + [ my_name ] }}" - debug: var=my_strings - name: Append another item to the list set_fact: my_strings: "{{ my_strings + [ 'Power' ] }}" - debug: var=my_strings
The output will be:
TASK [Initialize an empty list for our strings] ******************************** ok: [localhost] TASK [Setup a string variable] ************************************************* ok: [localhost] TASK [Append string to list] *************************************************** ok: [localhost] TASK [debug] ******************************************************************* ok: [localhost] => { "my_strings": [ "Max" ] } TASK [Append another item to the list] ***************************************** ok: [localhost] TASK [debug] ******************************************************************* ok: [localhost] => { "my_strings": [ "Max", "Power" ] }
More examples can be found at https://github.com/betrcode/ansible-append-list. Happy provisioning!
Good stuff. Ansible / jinja’s syntax can be mind boggling at times and this was a real help. Although I found I preferred surrounding the whole expression with {{ }} instead of the individual elements. So for strings:
– set_fact:
my_strings: “{{ my_strings + [ my_name ] }}”
– set_fact:
my_strings: “{{ my_strings + [ ‘Power’ ] }}”
This way you know that everything between the {{ }} is jinja so you don’t have to keep mentally switching back and forth between yaml and jinja syntax as you read along the line.
In case any other readers are wondering, here’s how to append a dict created on-the-fly to a list of dicts:
– set_fact:
my_dicts: “{{ my_dicts + [ { ‘name’: ‘fred’, ‘age’: computed_age } ] }}”
You can put quoted strings or variables as keys and values and the variables will be dereferenced properly. Those variables can even be other lists and dicts if you’re assembling some complex data.
Hi,
For some reason your coding worked, but OP’s didn’t.
In my case with Ansible 2.5:
This worked:
my_strings: “{{ my_strings + [ ‘Power’ ] }}”
This did not worked:
my_strings: “{{ my_strings }} + [ ‘{{ my_name }}’ ]”
thank you for your help guys! this post (and it’s answers) were most helpfull!
this was very helpful and accurate. thanks!
Hello,
I have list of servers IPS using dynamic json file , How can i execute command say ping to all servers from list …
blow is sample data from file …
[{“IP”:”192.168.132.166″},{“IP”:”192.168.132.213″},{“IP”:”192.168.132.6″}]
Hi Hemant!
I don’t have the time to write the code right now, but I see two different approaches.
Your list of servers from a json file could be viewed as what Ansible would refer to as a “dynamic inventory”. See: http://docs.ansible.com/ansible/latest/intro_dynamic_inventory.html
The other approach would be to take the json file, parse it into a list, probably using a jinja2 filter, and then iterate on that list using `with_items` and call whatever module you want (like command or ping).
Hi again Hemant!
I decided to try coding it. This is the latter approach above. See: https://github.com/betrcode/ansible-parse-json-and-loop
Thanks for your help on this Max. I agree that Ansible’s documentation is not helpful about this concept.
Thank you a lot for this post. I am a newbie and started to use anslible not much time ago so I don’t know yaml syntax pretty well. Really, it is quite useful for me.
Hi Max i am facing an issue where lets say i have a list [“abc”, “def”] i have to loop through the list & get some data which is also a list of dictionaries [{“name”: “value”},{“name”, “value”}] & concatenate them into a single list.
i am not able to concatenate the lists. can you help me ?
Not sure if I understand your question correctly, but if you have a list of dictionaries and you want to filter out a single attribute (like “name”) from the dictionary and make that a list you could do this:
{{ my_list_of_dicts | map(attribute=’name’) | list }}
Thank you. That made my day!
Am I right aussming the “Max power” exemple is taken from an episode from “the Simpsons”? 🙂
That’s right Alex 😉 Good catch!
Hi, Max. Don’t you want to fix the escaping in these examples? They contain a lot of extra stuff which obscures what’s really happening, and makes it look like you don’t understand the parsing (which you clearly do at this point). For example, “{{ my_strings }} + [ ‘{{ my_name }}’ ]” should be “{{ my_strings + [my_name] }}”.
After all, this page is the first Google result for how to append lists in Ansible. 🙂
Cheers for the useful page!
Thanks for pointing that out Dan!
When I originally wrote the post, I guess I hadn’t figured out the parsing properly. I will update the post with your feedback!
use the list append to string,
use the python code, like this:
=====
– name: set fact for build envs str
set_fact:
build_envs_str: “{{ ‘,’.join(BuildEnvs) }}”
Your code to append elements to a list worked perfectly. Thank you! I am using it to create a list of IP addresses for a specific group of hosts so that I can pass it in as a variable to cfssl to generate a certificate for Kubernetes as I walk through Kubernetes the Hard Way.
This is what I ended up doing:
– name: Initialize Hostname List for kube-apiserver Certificate
set_fact:
kube_apiserver_controller_hostnames_list: []
– name: Append each Controller’s Hostname to hostname String for kube-apiserver Certificate
set_fact:
kube_apiserver_controller_hostnames_list: “{{ kube_apiserver_controller_hostnames_list + [ hostvars[item].internal_ip ] }}”
with_items: “{{ groups[‘controllers’] }}”
Hello guys,
What about to append 2 fact that has json content?
apparently this is converting the json into plain ext..
– name: “Adjust the final_json_fact3 dictionary”
set_fact:
final_json_fact3__to_merge: “{{ final_json_fact3__to_merge }} + {{ final_json_fact2__to_merge }}”
when: final_json_fact2__to_merge.keys()|length > 0
thank you sir for this guide. Helps me a lot 🙂
thank you