ansibleyamlfirewalld

Ansible loop list in dictionary and retain the key


I'm trying to create a series of firewalld rules using a variable imported from a yaml file. The yaml file creates a dictionary of service names and the associated ports are a list within each item. A segment of the yaml looks like this:

---
myservice:
  description: My service desc
  ports:
    - 1234/tcp
    - 1235/tcp
another:
  description: Another service
  ports:
    - 2222/tcp
    - 3333/tcp

The Ansible role I have so far is:

- name: Read services from file
  include_vars:
    file: "services.yml"
    name: services

- name: Create firewalld services
  command: >
    firewall-cmd --permanent
      --new-service={{ item.key }}
      --set-description="{{ item.value.description }}"
  register: addserv
  failed_when: addserv.rc != 26 and addserv.rc != 0
  changed_when: not "NAME_CONFLICT" in addserv.stderr
  with_dict: "{{ services }}"
  
- name: Add ports to firewalld service
  command: >
    firewall-cmd --permanent
      --service={{ item.key }} --add-port={{ item.value.ports }}
  register: addport
  changed_when: not "ALREADY_ENABLED" in addport.stderr

The first segment to create the firewalld service works fine but I'm stumped on the second part with how to loop over the list of ports while retaining the dictionary key. I've tried using subelements to extract the ports list and that works but I can't figure out how to retain the service name from the key.


Solution

  • Use subelements. For example

        - debug:
            msg: "{{ item.0.key }} - {{ item.0.value.description }} - {{ item.1 }}"
          with_subelements:
            - "{{ services|dict2items }}"
            - value.ports
    

    gives

        "msg": "myservice - My service desc - 1234/tcp"
        "msg": "myservice - My service desc - 1235/tcp"
        "msg": "another - Another service - 2222/tcp"
        "msg": "another - Another service - 3333/tcp"