defaulting on undefined nested dictionaries

1,813 views
Skip to first unread message

Patrick McMahon

unread,
Aug 12, 2015, 10:33:04 AM8/12/15
to Ansible Project
Hi all,

I have a dictionary with a nested dictionary defined in defaults/main.yml of my role:

file_system_system_vg:
  name
: "A Name"
  lv
: {}

where lv is the nested dictionary.

I can use the nested dictionary in a task like this:

- name: Create Logicals Volumes on primary VG
  lvol
: vg={{ file_system_system_vg.name }} lv={{ item.value.name }} size={{ item.value.size }}
  with_dict
: file_system_system_vg.lv

This all works fine when file_system_system_vg is defined, but i would like to remove it from defaults/main.yml and only run the task when file_system_system_vg.lv is defined elsewhere, so I have tried this:

- name: Create Logicals Volumes on primary VG
  lvol
: vg={{ file_system_system_vg.name }} lv={{ item.value.name }} size={{ item.value.size }}
  with_dict
: file_system_system_vg.lv | default ({})

but it throws an error:

TASK: [file_system | Create Logicals Volumes on primary VG] *******************
fatal
: [dsdptgfc06v.devqa.exch.int] => with_dict expects a dict

Please note that file_system_system_vg is not defined here and neither is file_system_system_vg.lv. Does this make sense?
How can I make ansible skip this task when both file_system_system_vg and file_system_system_vg.lv are undefined?
N.B when I run the task I need to use the dictionaries within file_system_system_vg.lv

Thanks in advance
Paddy




Brian Coca

unread,
Aug 12, 2015, 10:40:32 AM8/12/15
to Ansible Project
have you tried:

with_dict: "{{ file_system_system_vg is
defined|ternary(file_system_system_vg.lv|default({}), {})}}"

?

--
Brian Coca

Patrick McMahon

unread,
Aug 12, 2015, 11:06:18 AM8/12/15
to Ansible Project
Hi Brian,

so in my defaults/main.yml if I define only this:

file_system_system_vg:

It works! so we are nearly there. If I remove file_system_system_vg from defaults/main.yml it throws an error again:


TASK
: [file_system | Create Logicals Volumes on primary VG] *******************
fatal
: [dsdptgfc06v.devqa.exch.int] =>
with_dict expects a dict

PLAY RECAP
*******************************************************************

So is it possible to remove file_system_system_vg completely from defaults/main.yml?

Thanks
Patrick
Message has been deleted

Patrick McMahon

unread,
Aug 12, 2015, 11:54:12 AM8/12/15
to Ansible Project
I made a simple playbook to show the issue. It seems ansible evalutes all variables regardless of the conditional result before ternary.
If you run the playbook twice, once with "simpleDictdefined, and again with it commented out.

---
#TESTING: ternary behaviour
- name: Run - Testing ternary
  sudo
: yes
  hosts
: "{{hosts}}"
  gather_facts
: no

  vars
:
    simpleDict
:
   
#  name: 'A simple dictionary'
   
#  nestedDict: {}

  tasks
:
   
- set_fact: foo="{{ simpleDict is defined | ternary(simpleDict.nestedDict|default({}),"simpleDict not defined") }}"

   
- debug: var=foo

Thanks
Patrick

Christian Thiemann

unread,
Aug 12, 2015, 4:13:26 PM8/12/15
to Ansible Project
You can specify default values for both the dictionary in which you are trying to look something up, and the key you are looking up:

  with_dict: (file_system_system_vg|default({})).lv|default({})

The parentheses are important!

Patrick McMahon

unread,
Aug 12, 2015, 5:43:08 PM8/12/15
to Ansible Project
It works, exactly what I was after! Thanks Christian

Patrick
Reply all
Reply to author
Forward
0 new messages