problems with with_subelements

Hello,

I am attempting to make my EC2 VPC infrastructure indempotent. I have a list of VPC dictionaries for a region. Each VPC has a list of security_groups. I am having problems using the with_subelements: loop/lookup

My contrived playbook: Two VPCs, each has a sub-list of security_group dictionaries:

`

  • hosts: localhost
    vars:
    vpcs:
  • name: my vpc 1
    cidr_block: 10.0.0.0/16
    subnets:
  • cidr: 10.0.0.0/24
    az: us-west-2a
    security_groups:
  • name: all
    description: all hosts
    rules:
  • proto: tcp
    from_port: 80
    to_port: 80
    cidr_ip: 0.0.0.0/0
    rules_egress:
  • proto: all
    from_port: all
    to_port: all
    cidr_ip: 0.0.0.0/0
  • name: my vpc 2
    cidr_block: 10.10.0.0/16
    subnets:
  • cidr: 10.10.0.0/24
    az: us-west-2a
    security_groups:
  • name: all
    description: all hosts
    rules:
  • proto: tcp
    from_port: 443
    to_port: 443
    cidr_ip: 0.0.0.0/0
    rules_egress:
  • proto: all
    from_port: all
    to_port: all
    cidr_ip: 0.0.0.0/0

tasks:

  • local_action:
    module: ec2_vpc
    resource_tags: { Name: “{{ item.name }}” }
    cidr_block: “{{ item.cidr_block }}”
    subnets: “{{ item.subnets }}”
    state: present
    with_items: vpcs
    register: result_vpcs

  • debug: var=result_vpcs

  • local_action:
    module: ec2_group
    name: “{{ item[1].name }}”
    description: “{{ item[1].description }}”
    rules: “{{ item[1].rules }}”
    rules_egress: “{{ item[1].rules_egress }}”

    58 with_subelements:
    59 - result_vpcs.results
    60 - item

`

For each dictionary in the list result_vpcs.results, I want to get the sub-element of the item.security_groups list as the basis for creating my security groups. This is nuanced but really useful (i.e. idempotent).

`

“result_vpcs”: {
“changed”: false,
“msg”: “All items completed”,
“results”: [
{
“changed”: false,
“invocation”: {
“module_args”: “”,
“module_name”: “ec2_vpc”
},
“item”: {
“cidr_block”: “10.0.0.0/16”,
“name”: “my vpc 1”,
“security_groups”: [
{
“description”: “all hosts”,
“name”: “all”,
“rules”: [
{
“cidr_ip”: “0.0.0.0/0”,
“from_port”: 80,
“proto”: “tcp”,
“to_port”: 80
}
],
“rules_egress”: [
{
“cidr_ip”: “0.0.0.0/0”,
“from_port”: “all”,
“proto”: “all”,
“to_port”: “all”
}
]
}
],
“subnets”: [
{
“az”: “us-west-2a”,
“cidr”: “10.0.0.0/24”
}
]
},
“subnets”: [
{
“az”: “us-west-2a”,
“cidr”: “10.0.0.0/24”,
“id”: “subnet-886eb6ff”,
“resource_tags”: {}
}
],
“vpc”: {
“cidr_block”: “10.0.0.0/16”,
“dhcp_options_id”: “dopt-0ee3056b”,
“id”: “vpc-67f35302”,
“region”: “us-west-2”,
“state”: “available”
},
“vpc_id”: “vpc-67f35302”
},
{
“changed”: false,
“invocation”: {
“module_args”: “”,
“module_name”: “ec2_vpc”
},
“item”: {
“cidr_block”: “10.10.0.0/16”,
“name”: “my vpc 2”,
“security_groups”: [
{
“description”: “all hosts”,
“name”: “all”,
“rules”: [
{
“cidr_ip”: “0.0.0.0/0”,
“from_port”: 443,
“proto”: “tcp”,
“to_port”: 443
}
],
“rules_egress”: [
{
“cidr_ip”: “0.0.0.0/0”,
“from_port”: “all”,
“proto”: “all”,
“to_port”: “all”
}
]
}
],
“subnets”: [
{
“az”: “us-west-2a”,
“cidr”: “10.10.0.0/24”
}
]
},
“subnets”: [
{
“az”: “us-west-2a”,
“cidr”: “10.10.0.0/24”,
“id”: “subnet-746fb703”,
“resource_tags”: {}
}
],
“vpc”: {
“cidr_block”: “10.10.0.0/16”,
“dhcp_options_id”: “dopt-0ee3056b”,
“id”: “vpc-60f35305”,
“region”: “us-west-2”,
“state”: “available”
},
“vpc_id”: “vpc-60f35305”
}
]
}
}

`

The error from using sub_elements:


TASK: [ec2_group] *************************************************************
fatal: [localhost] => the key item should point to a list, got '{‘subnets’: [[{‘cidr’: ‘10.0.0.0/24’, ‘az’: ‘us-west-2a’}], ’
`

`

No surprise there. I read the code and see that it expects a string as the key name to use. Is there a way I can traverse the result_vpcs to create the security_groups like I want? I’ve looked at using with_nested, but that doesn’t do what I want.

Perhaps with_subelements should be changed a bit to allow either a string or an arbitrary list. I.e. so one can use item.security_groups as the second term instead of simply a string.

This seems like what I want: https://github.com/ansible/ansible/pull/6370

Am I overlooking some loop/filter capability in Ansible that can be used in my scenario?

Thanks,
Robb