divij_o
divij_o

Reputation: 135

Supply task parameters using a dictionary variable (Ansible)

I'm trying to supply all task parameters using a dictionary in Ansible. Earlier, the args module (now deprecated) was a handy way of doing this. Some tasks that I'm trying to put in a loop have fewer parameters than the rest, and since I don't want any variables to be exposed in my plays, I'm looking for a solution that closely matches the args approach.

The dictionary variable (note: the last element doesn't have an 'opts' key/parameter):

lvm_vars:
    - {vg: {{ lvm_names.data_vol_group }} , lv: {{ lvm_names.index_lv }} , size: 5G, opts: -i 3 -I 256}
    - {vg: {{ lvm_names.data_vol_group }} , lv: {{ lvm_names.data_lv }} , size: 5G, opts: -i 3 -I 256}
    - {vg: {{ lvm_names.data_vol_group }} , lv: {{ lvm_names.wal_lv }} , size: 5G, opts: -i 3 -I 256}
    - {vg: {{ lvm_names.data_vol_group }} , lv: {{ lvm_names.tblspc_lv }} , size: 5G, opts: -i 3 -I 256}
    - {vg: {{ lvm_names.backup_vol_group }} , lv: {{ lvm_names.backup_lv }} , size: 5G}

The args solution:

- name: Create LVs ({{ item.lv }})
  lvol:
  args: "{{ item }}"
  with_items: "{{ lvm_vars }}"

What the final unrolled tasks should look like:

- name: Create LVs
  lvol:
    vg: {{ lvm_names.data_vol_group }}
    lv: {{ lvm_names.index_lv }}
    size: 5G
    opts: -i 3 -I 256
- name: Create LVs
  lvol:
    vg: {{ lvm_names.data_vol_group }}
    lv: {{ lvm_names.data_lv }}
    size: 5G
    opts: -i 3 -I 256
- name: Create LVs
  lvol:
    vg: {{ lvm_names.data_vol_group }}
    lv: {{ lvm_names.wal_lv }}
    size: 5G
    opts: -i 3 -I 256
- name: Create tblspc LV
  lvol:
    vg: {{ lvm_names.data_vol_group }}
    lv: {{ lvm_names.tblspc_lv }}
    size: 5G
    opts: -i 3 -I 256
- name: Create LVs
  lvol:
    vg: {{ lvm_names.backup_vol_group }}
    lv: {{ lvm_names.backup_lv }}
    size: 5G

I'm also okay with supplying only the parameter values from the dictionary, but this is problematic because the last item in my dictionary doesn't use the "opts" parameter. So if I try doing something like this:

- name: Create LVs ({{ item.lv }})
  lvol:
    vg: "{{ item.vg }}"
    lv: "{{ item.lv }}"
    size: "{{ item.size }}"
    opts: "{{ item.opts }}"
  with_items: "{{ lvm_vars }}"

I obviously get an error because 'item.opts' is undefined for the last item.

Upvotes: 1

Views: 563

Answers (1)

β.εηοιτ.βε
β.εηοιτ.βε

Reputation: 39264

What you are looking for is the default filter with the special value omit.

By default Ansible requires values for all variables in a templated expression. However, you can make specific variables optional. For example, you might want to use a system default for some items and control the value for others. To make a variable optional, set the default value to the special variable omit

Source: https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#making-variables-optional

- name: Create LVs ({{ item.lv }})
  lvol:
    vg: "{{ item.vg }}"
    lv: "{{ item.lv }}"
    size: "{{ item.size }}"
    opts: "{{ item.opts | default(omit) }}"
  with_items: "{{ lvm_vars }}"

With this, if your item dictionary does not contains the opts key, the whole opts key of lvol will be removed out of the dictionary, so resulting in your last loop being:

- name: Create LVs (lvm_names.backup_lv)
  lvol:
    vg: lvm_names.backup_vol_group
    lv: lvm_names.backup_lv
    size: 5G

Upvotes: 2

Related Questions