Dirk Hoffmann
Dirk Hoffmann

Reputation: 1563

ansible yaml variable extraction / filter keeping the "parent" names

I have an ansible yaml variable:

tenants:
- tenant_name: ccf_demo
  description: "ccf demo tenant"
  state: present
  segments:
  - segment_name: segment1
    state: present
    ifgroups:
    - ifgroup_name: group1
      tag: untagged
    - ifgroup_name: group2
      tag: untagged
- tenant_name: ccf_demo2
  description: "ccf demo2 tenant"
  state: absent
  segments:
  - segment_name: t2seg1
    state: present
    ifgroups:
    - ifgroup_name: othergroup
      tag: untagged
- tenant_name: ccf_demo3
  description: "ccf demo3 tenant"
  state: present

Now I want to extract/loop over all ifgroups of all segments (if there are any) of each tenant, preserving the name of the tenant and segment.

In the end I want to have a loop body that enables me to write something like:

- debug:
    msg: "name: {{ item.tenant_name }}_{{ item.segment_name }}_{{ item.ifgroup_name }} is {{ item.?...ifgroup_name }}:{{ item.?...tag }}"
  loop: "{{ ??? | json_query('???') | ??? }}"

desired output:

  1. name: ccf_demo_segment1_group1 is group1:untagged
  2. name: ccf_demo_segment1_group2 is group2:untagged
  3. name: ccf_demo2_t2seg1_othergroup is othergroup:untagged

edited ------------------

ideally I'd like to define a new yaml variable with the result e.g. like

resultVar:
  - tenant_name: ccf_demo
    segment_name: segment1
    ifgroup_name: group1
    tag: untagged
  - tenant_name: ccf_demo
    segment_name: segment1
    ifgroup_name: group2
    tag: untagged
  - tenant_name: ccf_demo2
    segment_name: t2seg1
    ifgroup_name: othergroup
    tag: untagged

any help appreciated.

Upvotes: 1

Views: 314

Answers (2)

Dirk Hoffmann
Dirk Hoffmann

Reputation: 1563

This is what I finally ended up with:

---

- hosts: localhost
  connection: local
  gather_facts: no

  tasks:
  - name: include businessVars
    include_vars: ./businessVars/busVars.yml

  - name: "DEBUG3 -> write template variable to file"
    template:
      src: ifgroups.j2
      dest: tmp/ifgroups.yml
      mode: 0600
    tags: DEBUG3

  - name: extract interface data by jinja template
    set_fact: 
      theIfGroups: "{{ lookup('template', 'ifgroups.j2') | from_yaml }}"
    ## theIfGroups:
    ## - tenant_name: ccf_demo
    ##   segment_name: segment1
    ##   ifgroup_name: group1
    ##   tag: untagged

  - name: final output
    debug:
      msg: "{{ item.tenant_name }}__{{ item.segment_name }}__{{ item.ifgroup_name }}: {{ item.ifgroup_name }}:{{ item.tag }}"
    loop: "{{ theIfGroups }}"

./templates/ifgroups.j2

{% for tenant in tenants %}
{%- if tenant.segments is defined -%}{% for segment in tenant.segments %}
{%- if segment.ifgroups is defined -%}{%- for ifgroup in segment.ifgroups -%}
- tenant_name: {{ tenant.tenant_name }}
  segment_name: {{ segment.segment_name }}
  ifgroup_name: {{ ifgroup.ifgroup_name }}
  tag: {{ ifgroup.tag }}
{% endfor %}{% endif %}
{% endfor %}{% endif %}
{% endfor %}

./businessVars/busVars.yml

tenants:
- tenant_name: ccf_demo
  description: "ccf demo tenant"
  state: present
  segments:
  - segment_name: segment1
    state: present
    ifgroups:
    - ifgroup_name: group1
      tag: untagged
    - ifgroup_name: group2
      tag: untagged
- tenant_name: ccf_demo2
  description: "ccf demo2 tenant"
  state: absent
  segments:
  - segment_name: t2seg1
    state: present
    ifgroups:
    - ifgroup_name: group3
      tag: untagged
- tenant_name: ccf_demo3
  description: "ccf demo3 tenant"
  state: absent
  segments:
  - segment_name: t3seg1
    state: present
- tenant_name: ccf_demo3
  description: "ccf demo3 tenant"
  state: present

Upvotes: 0

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

Reputation: 39119

Instead of filtering the list with JMESPath, which won't, in the end, remove your need to loop over the resulting list, a better bet would probably be to use a basic Jinja templating with nested loops.

Given the playbook:

- hosts: localhost
  gather_facts: no

  tasks:
    - debug:
        msg: >-
          {% for segment in item.segments %}
          {%- for ifgroup in segment.ifgroups -%}
            name: {{ item.tenant_name }}_{{ segment.segment_name }}_{{ ifgroup.ifgroup_name }} is {{ ifgroup.ifgroup_name }}:{{ ifgroup.tag }}
          {% endfor %}
          {% endfor %}
      loop: "{{ tenants }}"
      loop_control:
        label: "{{ item.tenant_name }}"
      when: item.segments is defined
      vars:
        tenants:
          - tenant_name: ccf_demo
            description: "ccf demo tenant"
            state: present
            segments:
            - segment_name: segment1
              state: present
              ifgroups:
              - ifgroup_name: group1
                tag: untagged
              - ifgroup_name: group2
                tag: untagged
          - tenant_name: ccf_demo2
            description: "ccf demo2 tenant"
            state: absent
            segments:
            - segment_name: t2seg1
              state: present
              ifgroups:
              - ifgroup_name: othergroup
                tag: untagged
          - tenant_name: ccf_demo3
            description: "ccf demo3 tenant"
            state: present

This yields:

ok: [localhost] => (item=ccf_demo) => 
  msg: |-
    name: ccf_demo_segment1_group1 is group1:untagged
    name: ccf_demo_segment1_group2 is group2:untagged
ok: [localhost] => (item=ccf_demo2) => 
  msg: |-
    name: ccf_demo2_t2seg1_othergroup is othergroup:untagged
skipping: [localhost] => (item=ccf_demo3) 

Upvotes: 2

Related Questions