ansible

How to pick certain fields in a loop without tons of "skipping" lines


I'm trying to create an array in Ansible that contains all the AWS regions that are enabled in my account that support FSx for NetApp ONTAP (FSxN).

I know I can use the following to get the list of regions enabled on my account:

    - name: Get all the opted in regions.
      amazon.aws.aws_region_info:
      register: region_info

    - name: Just get region names
      set_fact:
        opted_in_regions: "{{ [item.region_name] + opted_in_regions }}"
      loop: "{{ region_info.regions }}"

But there are times, typically when a new region comes online, that some regions don't support FSxN.

The only way I have found to know which regions support specific services is to download the price guide from https://api.regional-table.region-services.aws.a2z.com/index.json and look for regions that have "Amazon FSx for NetApp ONTAP" as the "aws:serviceName". The format for that file is:

{
  "prices": [
    {
      "attributes": {
        "aws:region": "ap-east-1",
        "aws:serviceName": "Amazon Translate",
        "aws:serviceUrl": "https://aws.amazon.com/translate/"
      },
      "id": "translate:ap-east-1"
    },
    {
      "attributes": {
        "aws:region": "ap-northeast-1",
        "aws:serviceName": "Amazon Translate",
        "aws:serviceUrl": "https://aws.amazon.com/translate/"
      },
      "id": "translate:ap-northeast-1"
    },

So, what I did was create variable with the contents of the file:

    - name: Get the capabilities of all regions.
      set_fact:
        regions_capabilities: "{{lookup('ansible.builtin.url', 'https://api.regional-table.region-services.aws.a2z.com/index.json', split_lines=false)}}"

Then the next "task" is to loop through all the values and add to another array the ones that have the specific string in the aws:serviceName field.

    - name: Get the intersection of opted in regions and regions that support FSxN.
      when: item['attributes']['aws:serviceName'] == "Amazon FSx for NetApp ONTAP" and item['attributes']['aws:region'] in opted_in_regions
      set_fact:
        fsxnRegions: "{{ [item['attributes']['aws:region']] + fsxnRegions }}"
      loop: "{{ regions_capabilities.prices }}"

While works, that when: statements generates a LOT (thousands) of skipping... lines in the output. And, it is painfully slow.

So, the question is, is there a better way to create the array of regions that support FSxN? And if not, how can I suppress that skipping message, but ONLY for this task?

Here is the entire Ansible playbook:

# Title: generate report
---
- hosts: localhost
  collections:
    - amazon.aws
  gather_facts: false
  name: Playbook to generate a report on all the FSxNs
  vars:
    fsxnRegions: []
    opted_in_regions: []

  tasks:
    - name: Get all the opted in regions.
      amazon.aws.aws_region_info:
      register: region_info

    - name: Just get region names
      set_fact:
        opted_in_regions: "{{ [item.region_name] + opted_in_regions }}"
      loop: "{{ region_info.regions }}"

    - name: Get the capabilities of all regions.
      set_fact:
        regions_capabilities: "{{lookup('ansible.builtin.url', 'https://api.regional-table.region-services.aws.a2z.com/index.json', split_lines=false)}}"

    - name: Get the intersection of opted in regions and regions that support FSxN.
      when: item['attributes']['aws:serviceName'] == "Amazon FSx for NetApp ONTAP" and item['attributes']['aws:region'] in opted_in_regions
      set_fact:
        fsxnRegions: "{{ [item['attributes']['aws:region']] + fsxnRegions }}"
      loop: "{{ regions_capabilities.prices }}"

    - name: Output
      debug:
        msg: "fsxnRegions={{ fsxnRegions }}"

Solution

  • If I understand you correctly , you can try using selectattr without using the loop

    # Title: generate report
    ---
    - hosts: localhost
      collections:
        - amazon.aws
      gather_facts: false
      name: Playbook to generate a report on all the FSxNs
      vars:
        fsxnRegions: []
        opted_in_regions: []
    
      tasks:
        - name: Get all the opted-in regions
          amazon.aws.aws_region_info:
          register: region_info
    
        - name: Get region names
          set_fact:
            opted_in_regions: "{{ region_info.regions | map(attribute='region_name') | list }}"
    
        - name: Get the capabilities of all regions
          set_fact:
            regions_capabilities: "{{ lookup('ansible.builtin.url', 'https://api.regional-table.region-services.aws.a2z.com/index.json', split_lines=false) }}"
    
        - name: Filter regions that support FSxN and are opted-in
          set_fact:
            fsxnRegions: >-
              {{
                regions_capabilities.prices
                | selectattr("attributes.aws:serviceName", "equalto", "Amazon FSx for NetApp ONTAP")
                | selectattr("attributes.aws:region", "in", opted_in_regions)
                | map(attribute="attributes.aws:region")
                | list
              }}
    
        - name: Output the FSxN regions
          debug:
            msg: "fsxnRegions={{ fsxnRegions }}"