CiscoDevNet/ansible-meraki

Problem with using loops within an organization's networks

Clay2905 opened this issue · 7 comments

Hello, I want to create the loop which will check all networks within an Organization one by one and adding/modiyfing SSID's but I have a problem how to build it correctly. I don't know how to make it right because there's no something like meraki collection facts.

Task:
In Orgzanization I have three networks and the script should check these networks one by one and add three following SSID's (guest, corp, mobile).

That's what I have:
`

  • hosts: localhost

    vars:
    api: "{{ lookup('ansible.builtin.env', 'API') }}"
    psk: "{{ lookup('ansible.builtin.env', 'PSK') }}"

    tasks:

    - name: save networks 
      meraki_network:
        auth_key: '{{ api }}' # API key from Meraki dashboard
        org_name: ansible
        state: query
      register: networks     
           
    
    - name: guest   
      meraki_ssid:
        auth_key: '{{ api }}'
        org_name: ansible
        net_name: '{{ item }}'
        name: guest
        auth_mode: psk
        encryption_mode: wpa
        psk: aabbccddeeffkkgggdg
        enabled: true
        visible: true
     
    
    - name: corp   
      meraki_ssid:
        auth_key: '{{ api }}'
        org_name: ansible
        net_name: '{{ item }}' 
        name: corp
        ip_assignment_mode: Bridge mode
        auth_mode: 8021x-radius
        enabled: true
        visible: true
        use_vlan_tagging: true
        radius_coa_enabled: true
        default_vlan_id: 140
        radius_servers:
          - host: xxxxxx
            port: 1812
            secret: '{{ psk }}'
          - host: xxxxxx
            port: 1812
            secret: '{{ psk }}'
       
     
    - name: mobile    
      meraki_ssid:
        auth_key: '{{ api }}'
        org_name: ansible
        net_name: '{{ item }}' 
        name: mobile
        auth_mode: psk
        encryption_mode: wpa
        psk: 1staentertainment
        ip_assignment_mode: Bridge mode
        enabled: true
        visible: false
        use_vlan_tagging: true
        default_vlan_id: 80
    
    `
    
kbreit commented

This is more of an Ansible question than a Meraki module question. However, you'll need to get all the networks (as you do) and create a list of network IDs for all the networks you want to modify. selectattr() could be an option for you and it's described nicely at https://www.middlewareinventory.com/blog/ansible-selectattr-example/. However, it may not pull the ID as a result of the condition so you may need another step which loops over the networks and appends to a list. I've done this in a set_fact task with a loop and conditional.

Do these work?

Thanks for response.

It saves the networks to variable networks but it saves all values - I need only net_name

- name: save networks 
        meraki_network:
          auth_key: '{{ api }}' # API key from Meraki dashboard
          org_name: ansible
        register: networks

In order to mark it, I need just network names to use these instead of static variables ( like in the example below: london, napoli).

- name: guest    
        meraki_ssid:
          auth_key: '{{ api }}'
          org_name: ansible
          net_name: '{{ item }}'
          name: guest
          auth_mode: psk
          encryption_mode: wpa
          psk: xxxxxxxxxxxxxx
          enabled: true
          visible: true
        
        loop: 
         - london
         - napoli

I really appreciate you spend your time on helping me, but unfortunately I need more hints to make it good. These are my first steps in ansible. Regards

I used

tasks:
      - name: get networks
        uri:
          url: "https://api.meraki.com/api/v1/organizations/{{ organization_id }}/networks"
          method: GET
          headers:
            X-Cisco-Meraki-API-Key: "{{ api }}"
          return_content: yes
        register: network_list
      - name: Save network names to variable
        set_fact:
          network_names: "{{ network_list.json | map(attribute='name') | list }}"
      - name: view the networks
        debug:
          var: network_names

and the output seems to be correct, but how to put these values to loop?

ok: [localhost] => {
    "network_names": [
        "london",
        "napoli"
    ]
}
kbreit commented

The meraki_network module will work and you shouldn't need to use the uri module. However, you'd have a task similar to this...

- name: guest    
        meraki_ssid:
          auth_key: '{{ api }}'
          org_name: ansible
          net_name: '{{ item }}'
          name: guest
          auth_mode: psk
          encryption_mode: wpa
          psk: xxxxxxxxxxxxxx
          enabled: true
          visible: true
        
        loop: '{{ network_names }}'

Does this help?

As some general guidance I'd recommend using the network ID instead of network name. When you use the network name it has to translate to a network ID which uses an additional lookup.

Hello,
You are right, it's enough and it works :)
I have one more task to add which will delete all SSID's except the specified ones with contidition with help of ,,when''. I've created again with api module task that saves the SSID's for each network, but I don't know how to save it as variable and then don't know how to construct it. I supposed to use another loop but nested? I don't know how to proceed.

- name: Get SSID list for each network
      uri:
        url: "https://api.meraki.com/api/v0/networks/{{ item }}/ssids"
        method: GET
        headers:
          X-Cisco-Meraki-API-Key: "{{ api }}"
        return_content: yes
      register: ssid_list
      loop: "{{ network_names }}"

Do you maybe have some an idea?

kbreit commented

You would need a list of SSIDs you need to keep. Then do a loop over it and the condition would be:

  when: item.name not in ssids_to_keep

There's other ways to do this but I think it's the most straight forward.

kbreit commented

I'm closing this but if this is still a question, please reopen the issue.