Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Ansible set_fact to create a dictionary from register results

Tags:

ansible

In Ansible I've used register to save the results of a task in the variable people. Omitting the stuff I don't need, it has this structure:

{     "results": [         {             "item": {                 "name": "Bob"             },             "stdout": "male"         },         {             "item": {                 "name": "Thelma"             },             "stdout": "female"         }     ] } 

I'd like to use a subsequent set_fact task to generate a new variable with a dictionary like this:

{     "Bob": "male",     "Thelma": "female" } 

I guess this might be possible but I'm going round in circles with no luck so far.

like image 527
Phil Gyford Avatar asked Feb 24 '16 15:02

Phil Gyford


People also ask

What does set_fact do in Ansible?

This module allows setting new variables. Variables are set on a host-by-host basis just like facts discovered by the setup module. These variables will be available to subsequent plays during an ansible-playbook run.

What is list and dictionary in Ansible?

For Ansible, nearly every YAML file starts with a list. Each item in the list is a list of key/value pairs, commonly called a “hash” or a “dictionary”. So, we need to know how to write lists and dictionaries in YAML. There's another small quirk to YAML.

What is Dict in Ansible?

Note. This lookup plugin is part of ansible-core and included in all Ansible installations. In most cases, you can use the short plugin name dict even without specifying the collections: keyword.

How do I register variables in Ansible?

Ansible registers are used when you want to capture the output of a task to a variable. You can then use the value of these registers for different scenarios like a conditional statement, logging etc. The variables will contain the value returned by the task. The common return values are documented in Ansible docs.


Video Answer


1 Answers

I think I got there in the end.

The task is like this:

- name: Populate genders   set_fact:     genders: "{{ genders|default({}) | combine( {item.item.name: item.stdout} ) }}"   with_items: "{{ people.results }}" 

It loops through each of the dicts (item) in the people.results array, each time creating a new dict like {Bob: "male"}, and combine()s that new dict in the genders array, which ends up like:

{     "Bob": "male",     "Thelma": "female" } 

It assumes the keys (the name in this case) will be unique.


I then realised I actually wanted a list of dictionaries, as it seems much easier to loop through using with_items:

- name: Populate genders   set_fact:     genders: "{{ genders|default([]) + [ {'name': item.item.name, 'gender': item.stdout} ] }}"   with_items: "{{ people.results }}" 

This keeps combining the existing list with a list containing a single dict. We end up with a genders array like this:

[     {'name': 'Bob', 'gender': 'male'},     {'name': 'Thelma', 'gender': 'female'} ] 
like image 112
Phil Gyford Avatar answered Oct 20 '22 18:10

Phil Gyford