I have a dictionary that is the exact same structure as below.
Where I am struggling is in Ansible code, how would I go about a user enters apple
, and I identify the type is fruit?
When a user enters spinach
, Ansible identifies it as veggie?
Basically, how do I reverse check the parent in a dictionary?
groups:
- type: fruit
names:
- apple
- oranges
- grapes
- type: veggie
names:
- broccoli
- spinach
CodePudding user response:
You can use selectattr
and the contains
test of Ansible for this.
Important note: do not name your dictionary groups
, as you risk a collision with the special variable of the same name. Here, I named it food_groups
.
So, the task of giving the type of food is as simple as:
- debug:
var: (food_groups | selectattr('names', 'contains', food) | first).type
given that the food you want to assert is in a variable name food
Given the playbook:
- hosts: localhost
gather_facts: no
vars_prompt:
- name: food
prompt: What food to you want to know the group?
private: no
tasks:
- debug:
var: (food_groups | selectattr('names', 'contains', food) | first).type
vars:
food_groups:
- type: fruit
names:
- apple
- oranges
- grapes
- type: veggie
names:
- broccoli
- spinach
This yields:
What food to you want to know the group?: grapes
PLAY [localhost] *******************************************************************
TASK [debug] ***********************************************************************
ok: [localhost] =>
(food_groups | selectattr('names', 'contains', food) | first).type: fruit
CodePudding user response:
Q: "How would I go about a user entering 'apple', and I identify the type is 'fruit'?"
A: Create a dictionary mapping the items to groups, e.g. given the data
my_groups:
- type: fruit
names:
- apple
- oranges
- grapes
- tomato
- type: veggie
names:
- broccoli
- spinach
- tomato
The task below
- set_fact:
my_dict: "{{ my_dict|d({'undef': 'undef'})|
combine({item.1: [item.0.type]}, list_merge='append') }}"
with_subelements:
- "{{ my_groups }}"
- names
gives
my_dict:
apple: [fruit]
broccoli: [veggie]
grapes: [fruit]
oranges: [fruit]
spinach: [veggie]
tomato: [fruit, veggie]
undef: undef
I added 'tomato' to both groups to test the membership in multiple groups. The identification of the item's groups is now trivial, e.g.
- debug:
msg: "{{ my_item|d('undef') }} is {{ my_dict[my_item|d('undef')]|d('none') }}"
gives by default
msg: undef is undef
When you enter an item not present in the dictionary you get
shell> ansible-playbook playbook.yml -e my_item=foo
...
msg: foo is none
and when you enter an item present in the dictionary you get the group(s)
shell> ansible-playbook playbook.yml -e my_item=spinach
...
msg: spinach is ['veggie']