Fix a number of issues around detecting nat gateways, how (#1511)
routes_to_delete is detected, propagating_vgw_ids and checking if gateway_id exists.
This commit is contained in:
parent
140157d86a
commit
2886d3d9ec
1 changed files with 43 additions and 21 deletions
|
@ -40,8 +40,12 @@ options:
|
||||||
default: null
|
default: null
|
||||||
routes:
|
routes:
|
||||||
description:
|
description:
|
||||||
- "List of routes in the route table. Routes are specified as dicts containing the keys 'dest' and one of 'gateway_id', 'instance_id', 'interface_id', or 'vpc_peering_connection_id'. If 'gateway_id' is specified, you can refer to the VPC's IGW by using the value 'igw'."
|
- "List of routes in the route table.
|
||||||
required: true
|
Routes are specified as dicts containing the keys 'dest' and one of 'gateway_id',
|
||||||
|
'instance_id', 'interface_id', or 'vpc_peering_connection_id'.
|
||||||
|
If 'gateway_id' is specified, you can refer to the VPC's IGW by using the value 'igw'. Routes are required for present states."
|
||||||
|
required: false
|
||||||
|
default: None
|
||||||
state:
|
state:
|
||||||
description:
|
description:
|
||||||
- "Create or destroy the VPC route table"
|
- "Create or destroy the VPC route table"
|
||||||
|
@ -281,6 +285,18 @@ def route_spec_matches_route(route_spec, route):
|
||||||
'interface_id': 'interface_id',
|
'interface_id': 'interface_id',
|
||||||
'vpc_peering_connection_id': 'vpc_peering_connection_id',
|
'vpc_peering_connection_id': 'vpc_peering_connection_id',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# This is a workaround to catch managed NAT gateways as they do not show
|
||||||
|
# up in any of the returned values when describing route tables.
|
||||||
|
# The caveat of doing it this way is that if there was an existing
|
||||||
|
# route for another nat gateway in this route table there is not a way to
|
||||||
|
# change to another nat gateway id. Long term solution would be to utilise
|
||||||
|
# boto3 which is a very big task for this module or to update boto.
|
||||||
|
if route_spec.get('gateway_id') and 'nat-' in route_spec['gateway_id']:
|
||||||
|
if route.destination_cidr_block == route_spec['destination_cidr_block']:
|
||||||
|
if all((not route.gateway_id, not route.instance_id, not route.interface_id, not route.vpc_peering_connection_id)):
|
||||||
|
return True
|
||||||
|
|
||||||
for k in key_attr_map.iterkeys():
|
for k in key_attr_map.iterkeys():
|
||||||
if k in route_spec:
|
if k in route_spec:
|
||||||
if route_spec[k] != getattr(route, k):
|
if route_spec[k] != getattr(route, k):
|
||||||
|
@ -316,22 +332,17 @@ def ensure_routes(vpc_conn, route_table, route_specs, propagating_vgw_ids,
|
||||||
# correct than checking whether the route uses a propagating VGW.
|
# correct than checking whether the route uses a propagating VGW.
|
||||||
# The current logic will leave non-propagated routes using propagating
|
# The current logic will leave non-propagated routes using propagating
|
||||||
# VGWs in place.
|
# VGWs in place.
|
||||||
routes_to_delete = [r for r in routes_to_match
|
routes_to_delete = []
|
||||||
if r.gateway_id != 'local'
|
for r in routes_to_match:
|
||||||
and (propagating_vgw_ids is not None
|
if r.gateway_id:
|
||||||
and r.gateway_id not in propagating_vgw_ids)]
|
if r.gateway_id != 'local' and not r.gateway_id.startswith('vpce-'):
|
||||||
|
if not propagating_vgw_ids or r.gateway_id not in propagating_vgw_ids:
|
||||||
|
routes_to_delete.append(r)
|
||||||
|
else:
|
||||||
|
routes_to_delete.append(r)
|
||||||
|
|
||||||
changed = routes_to_delete or route_specs_to_create
|
changed = bool(routes_to_delete or route_specs_to_create)
|
||||||
if changed:
|
if changed:
|
||||||
for route_spec in route_specs_to_create:
|
|
||||||
try:
|
|
||||||
vpc_conn.create_route(route_table.id,
|
|
||||||
dry_run=check_mode,
|
|
||||||
**route_spec)
|
|
||||||
except EC2ResponseError as e:
|
|
||||||
if e.error_code == 'DryRunOperation':
|
|
||||||
pass
|
|
||||||
|
|
||||||
for route in routes_to_delete:
|
for route in routes_to_delete:
|
||||||
try:
|
try:
|
||||||
vpc_conn.delete_route(route_table.id,
|
vpc_conn.delete_route(route_table.id,
|
||||||
|
@ -341,6 +352,15 @@ def ensure_routes(vpc_conn, route_table, route_specs, propagating_vgw_ids,
|
||||||
if e.error_code == 'DryRunOperation':
|
if e.error_code == 'DryRunOperation':
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
for route_spec in route_specs_to_create:
|
||||||
|
try:
|
||||||
|
vpc_conn.create_route(route_table.id,
|
||||||
|
dry_run=check_mode,
|
||||||
|
**route_spec)
|
||||||
|
except EC2ResponseError as e:
|
||||||
|
if e.error_code == 'DryRunOperation':
|
||||||
|
pass
|
||||||
|
|
||||||
return {'changed': bool(changed)}
|
return {'changed': bool(changed)}
|
||||||
|
|
||||||
|
|
||||||
|
@ -462,18 +482,20 @@ def get_route_table_info(route_table):
|
||||||
|
|
||||||
return route_table_info
|
return route_table_info
|
||||||
|
|
||||||
def create_route_spec(connection, routes, vpc_id):
|
|
||||||
|
def create_route_spec(connection, module, vpc_id):
|
||||||
|
routes = module.params.get('routes')
|
||||||
|
|
||||||
for route_spec in routes:
|
for route_spec in routes:
|
||||||
rename_key(route_spec, 'dest', 'destination_cidr_block')
|
rename_key(route_spec, 'dest', 'destination_cidr_block')
|
||||||
|
|
||||||
if 'gateway_id' in route_spec and route_spec['gateway_id'] and \
|
if route_spec.get('gateway_id') and route_spec['gateway_id'].lower() == 'igw':
|
||||||
route_spec['gateway_id'].lower() == 'igw':
|
|
||||||
igw = find_igw(connection, vpc_id)
|
igw = find_igw(connection, vpc_id)
|
||||||
route_spec['gateway_id'] = igw
|
route_spec['gateway_id'] = igw
|
||||||
|
|
||||||
return routes
|
return routes
|
||||||
|
|
||||||
|
|
||||||
def ensure_route_table_present(connection, module):
|
def ensure_route_table_present(connection, module):
|
||||||
|
|
||||||
lookup = module.params.get('lookup')
|
lookup = module.params.get('lookup')
|
||||||
|
@ -483,7 +505,7 @@ def ensure_route_table_present(connection, module):
|
||||||
tags = module.params.get('tags')
|
tags = module.params.get('tags')
|
||||||
vpc_id = module.params.get('vpc_id')
|
vpc_id = module.params.get('vpc_id')
|
||||||
try:
|
try:
|
||||||
routes = create_route_spec(connection, module.params.get('routes'), vpc_id)
|
routes = create_route_spec(connection, module, vpc_id)
|
||||||
except AnsibleIgwSearchException as e:
|
except AnsibleIgwSearchException as e:
|
||||||
module.fail_json(msg=e[0])
|
module.fail_json(msg=e[0])
|
||||||
|
|
||||||
|
@ -564,7 +586,7 @@ def main():
|
||||||
lookup = dict(default='tag', required=False, choices=['tag', 'id']),
|
lookup = dict(default='tag', required=False, choices=['tag', 'id']),
|
||||||
propagating_vgw_ids = dict(default=None, required=False, type='list'),
|
propagating_vgw_ids = dict(default=None, required=False, type='list'),
|
||||||
route_table_id = dict(default=None, required=False),
|
route_table_id = dict(default=None, required=False),
|
||||||
routes = dict(default=None, required=False, type='list'),
|
routes = dict(default=[], required=False, type='list'),
|
||||||
state = dict(default='present', choices=['present', 'absent']),
|
state = dict(default='present', choices=['present', 'absent']),
|
||||||
subnets = dict(default=None, required=False, type='list'),
|
subnets = dict(default=None, required=False, type='list'),
|
||||||
tags = dict(default=None, required=False, type='dict', aliases=['resource_tags']),
|
tags = dict(default=None, required=False, type='dict', aliases=['resource_tags']),
|
||||||
|
|
Loading…
Reference in a new issue