Home > other >  How to reverse check the parent in a dictionary YAML
How to reverse check the parent in a dictionary YAML

Time:01-27

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']
  •  Tags:  
  • Related