[2.6] ec2_group: fix regression for targets that are a list containing strings and lists (#45748)

* Fix targets that may be a list containing strings and lists which worked prior to 2.6.

(cherry picked from commit 450fb9f855ae7090acbdea3e726082d4038994f8)

* Add ec2_group integration tests for lists of nested targets

(cherry picked from commit 14e3399db162c7ddaa9cb9aa6c8a476471a376c2)

* changelog

(cherry picked from commit fb17db0876d75cb629a0ed180ead1058e15a737b)
This commit is contained in:
Sloane Hertel 2018-09-25 18:34:04 -04:00 committed by Matt Clay
parent fe2c9cdf13
commit 0be82f2b08
4 changed files with 263 additions and 2 deletions

View file

@ -0,0 +1,6 @@
---
bugfixes:
- ec2_group - Sanitize the ingress and egress rules before operating on them by flattening any lists
within lists describing the target CIDR(s) into a list of strings. Prior to Ansible 2.6 the ec2_group
module accepted a list of strings, a list of lists, or a combination of strings and lists within a list.
https://github.com/ansible/ansible/pull/45594

View file

@ -290,6 +290,7 @@ owner_id:
import json
import re
from copy import deepcopy
from time import sleep
from collections import namedtuple
from ansible.module_utils.aws.core import AnsibleAWSModule
@ -850,6 +851,27 @@ def verify_rules_with_descriptions_permitted(client, module, rules, rules_egress
module.fail_json(msg="Using rule descriptions requires botocore version >= 1.7.2.")
def flatten_nested_targets(module, rules):
def _flatten(targets):
for target in targets:
if isinstance(target, list):
for t in _flatten(target):
yield t
elif isinstance(target, string_types):
yield target
if rules is not None:
for rule in rules:
target_list_type = None
if isinstance(rule.get('cidr_ip'), list):
target_list_type = 'cidr_ip'
elif isinstance(rule.get('cidr_ipv6'), list):
target_list_type = 'cidr_ipv6'
if target_list_type is not None:
rule[target_list_type] = list(_flatten(rule[target_list_type]))
return rules
def main():
argument_spec = dict(
name=dict(),
@ -875,8 +897,10 @@ def main():
group_id = module.params['group_id']
description = module.params['description']
vpc_id = module.params['vpc_id']
rules = deduplicate_rules_args(rules_expand_sources(rules_expand_ports(module.params['rules'])))
rules_egress = deduplicate_rules_args(rules_expand_sources(rules_expand_ports(module.params['rules_egress'])))
rules = flatten_nested_targets(module, deepcopy(module.params['rules']))
rules_egress = flatten_nested_targets(module, deepcopy(module.params['rules_egress']))
rules = deduplicate_rules_args(rules_expand_sources(rules_expand_ports(rules)))
rules_egress = deduplicate_rules_args(rules_expand_sources(rules_expand_ports(rules_egress)))
state = module.params.get('state')
purge_rules = module.params['purge_rules']
purge_rules_egress = module.params['purge_rules_egress']

View file

@ -45,6 +45,7 @@
- include: ./rule_group_create.yml
- include: ./egress_tests.yml
- include: ./data_validation.yml
- include: ./multi_target.yml
# ============================================================
- name: test state=absent (CHECK MODE)

View file

@ -0,0 +1,230 @@
---
- name: set up aws connection info
set_fact:
aws_connection_info: &aws_connection_info
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
security_token: "{{ security_token }}"
region: "{{ aws_region }}"
no_log: yes
# ============================================================
- name: test state=present for multiple ipv6 and ipv4 targets (expected changed=true) (CHECK MODE)
ec2_group:
name: '{{ ec2_group_name }}'
description: '{{ ec2_group_description }}'
state: present
rules:
- proto: "tcp"
from_port: 8182
to_port: 8182
cidr_ipv6:
- "64:ff9b::/96"
- ["2620::/32"]
- proto: "tcp"
ports: 5665
cidr_ip:
- 172.16.1.0/24
- 172.16.17.0/24
- ["10.0.0.0/24", "20.0.0.0/24"]
<<: *aws_connection_info
check_mode: true
register: result
- name: assert state=present (expected changed=true)
assert:
that:
- 'result.changed'
- name: test state=present for multiple ipv6 and ipv4 targets (expected changed=true)
ec2_group:
name: '{{ ec2_group_name }}'
description: '{{ ec2_group_description }}'
state: present
rules:
- proto: "tcp"
from_port: 8182
to_port: 8182
cidr_ipv6:
- "64:ff9b::/96"
- ["2620::/32"]
- proto: "tcp"
ports: 5665
cidr_ip:
- 172.16.1.0/24
- 172.16.17.0/24
- ["10.0.0.0/24", "20.0.0.0/24"]
<<: *aws_connection_info
register: result
- name: assert state=present (expected changed=true)
assert:
that:
- 'result.changed'
- 'result.ip_permissions | length == 2'
- 'result.ip_permissions[0].ip_ranges | length == 4 or result.ip_permissions[1].ip_ranges | length == 4'
- 'result.ip_permissions[0].ipv6_ranges | length == 2 or result.ip_permissions[1].ipv6_ranges | length == 2'
- name: test state=present for multiple ipv6 and ipv4 targets (expected changed=false) (CHECK MODE)
ec2_group:
name: '{{ ec2_group_name }}'
description: '{{ ec2_group_description }}'
state: present
rules:
- proto: "tcp"
from_port: 8182
to_port: 8182
cidr_ipv6:
- "64:ff9b::/96"
- ["2620::/32"]
- proto: "tcp"
ports: 5665
cidr_ip:
- 172.16.1.0/24
- 172.16.17.0/24
- ["10.0.0.0/24", "20.0.0.0/24"]
<<: *aws_connection_info
check_mode: true
register: result
- name: assert state=present (expected changed=true)
assert:
that:
- 'not result.changed'
- name: test state=present for multiple ipv6 and ipv4 targets (expected changed=false)
ec2_group:
name: '{{ ec2_group_name }}'
description: '{{ ec2_group_description }}'
state: present
rules:
- proto: "tcp"
from_port: 8182
to_port: 8182
cidr_ipv6:
- "64:ff9b::/96"
- ["2620::/32"]
- proto: "tcp"
ports: 5665
cidr_ip:
- 172.16.1.0/24
- 172.16.17.0/24
- ["10.0.0.0/24", "20.0.0.0/24"]
<<: *aws_connection_info
register: result
- name: assert state=present (expected changed=true)
assert:
that:
- 'not result.changed'
- name: test state=present purging a nested ipv4 target (expected changed=true) (CHECK MODE)
ec2_group:
name: '{{ ec2_group_name }}'
description: '{{ ec2_group_description }}'
state: present
rules:
- proto: "tcp"
from_port: 8182
to_port: 8182
cidr_ipv6:
- "64:ff9b::/96"
- ["2620::/32"]
- proto: "tcp"
ports: 5665
cidr_ip:
- 172.16.1.0/24
- 172.16.17.0/24
- ["10.0.0.0/24"]
<<: *aws_connection_info
check_mode: true
register: result
- assert:
that:
- result.changed
- name: test state=present purging a nested ipv4 target (expected changed=true)
ec2_group:
name: '{{ ec2_group_name }}'
description: '{{ ec2_group_description }}'
state: present
rules:
- proto: "tcp"
from_port: 8182
to_port: 8182
cidr_ipv6:
- "64:ff9b::/96"
- ["2620::/32"]
- proto: "tcp"
ports: 5665
cidr_ip:
- 172.16.1.0/24
- 172.16.17.0/24
- ["10.0.0.0/24"]
<<: *aws_connection_info
register: result
- assert:
that:
- result.changed
- 'result.ip_permissions[0].ip_ranges | length == 3 or result.ip_permissions[1].ip_ranges | length == 3'
- 'result.ip_permissions[0].ipv6_ranges | length == 2 or result.ip_permissions[1].ipv6_ranges | length == 2'
- name: test state=present with both associated ipv6 targets nested (expected changed=false)
ec2_group:
name: '{{ ec2_group_name }}'
description: '{{ ec2_group_description }}'
state: present
rules:
- proto: "tcp"
from_port: 8182
to_port: 8182
cidr_ipv6:
- ["2620::/32", "64:ff9b::/96"]
- proto: "tcp"
ports: 5665
cidr_ip:
- 172.16.1.0/24
- 172.16.17.0/24
- ["10.0.0.0/24"]
<<: *aws_connection_info
register: result
- assert:
that:
- not result.changed
- name: test state=present add another nested ipv6 target (expected changed=true)
ec2_group:
name: '{{ ec2_group_name }}'
description: '{{ ec2_group_description }}'
state: present
rules:
- proto: "tcp"
from_port: 8182
to_port: 8182
cidr_ipv6:
- ["2620::/32", "64:ff9b::/96"]
- ["2001:DB8:A0B:12F0::1/64"]
- proto: "tcp"
ports: 5665
cidr_ip:
- 172.16.1.0/24
- 172.16.17.0/24
- ["10.0.0.0/24"]
<<: *aws_connection_info
register: result
- assert:
that:
- result.changed
- 'result.ip_permissions[0].ip_ranges | length == 3 or result.ip_permissions[1].ip_ranges | length == 3'
- 'result.ip_permissions[0].ipv6_ranges | length == 3 or result.ip_permissions[1].ipv6_ranges | length == 3'
- name: delete it
ec2_group:
name: '{{ ec2_group_name }}'
state: absent
<<: *aws_connection_info