This repository has been archived by the owner on Oct 30, 2018. It is now read-only.
New module ec2_vpc_peering #245
Closed
Closed
Changes from 4 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
64fa905
Module for creating VPC peering connections.
1edac0a
Use update method on peering connection rather than requerying.
a18d9f4
Add support for adding peering connection to route tables.
b5c1d2e
Rename directory to match core modules.
2abdb1e
Merge remote-tracking branch 'upstream/devel' into devel
9cd2678
Change to using HAS_BOTO pattern.
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,238 @@ | ||
#!/usr/bin/python | ||
# | ||
DOCUMENTATION = """ | ||
--- | ||
module: ec2_vpc_peer | ||
short_description: create or remove a peering connection between to ec2 VPCs. | ||
description: | ||
- | ||
options: | ||
vpc_id: | ||
description: | ||
- VPC id of the requesting VPC. | ||
required: true | ||
vpc_peer_id: | ||
description: | ||
- VPC id of the accepting VPC. | ||
required: true | ||
state: | ||
description: | ||
- Create or delete the peering connection. | ||
required: false | ||
default: present | ||
choices: ['present', 'absent'] | ||
wait_timeout: | ||
description: | ||
- How long to wait for peering connection state changes, in seconds | ||
required: false | ||
default: 10 | ||
update_routes: | ||
description: | ||
- Whether to update the VPC route tables to add the peering connection. | ||
required: false | ||
default: true | ||
region: | ||
description: | ||
- The AWS region to use. Must be specified if ec2_url is not used. If not specified then the value of the EC2_REGION environment variable, if any, is used. | ||
required: false | ||
default: null | ||
aliases: ['aws_region', 'ec2_region'] | ||
aws_secret_key: | ||
description: | ||
- AWS secret key. If not set then the value of the AWS_SECRET_KEY environment variable is used. | ||
required: false | ||
default: None | ||
aliases: ['ec2_secret_key', 'secret_key'] | ||
aws_access_key: | ||
description: | ||
- AWS access key. If not set then the value of the AWS_ACCESS_KEY environment variable is used. | ||
required: false | ||
default: None | ||
aliases: ['ec2_access_key', 'access_key'] | ||
|
||
requirements: [ "boto" ] | ||
""" | ||
|
||
import sys | ||
import time | ||
|
||
try: | ||
import boto.ec2 | ||
import boto.vpc | ||
import boto.exception | ||
except ImportError: | ||
print "failed=True msg='boto required for this module'" | ||
sys.exit(1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because back in February this was the standard pattern used by the core modules. :-) Have updated it to use the same pattern that they now use. |
||
|
||
def wait_for_connection_state(peering_conn, status_code, timeout): | ||
""" | ||
Wait until the peering connection has transition into the required state. | ||
Return True if the state is reached before timing out and False if the wait | ||
times out. | ||
""" | ||
wait_end = time.time() + timeout | ||
while wait_end > time.time(): | ||
peering_conn.update() | ||
if peering_conn.status_code == status_code: | ||
return True | ||
time.sleep(1) | ||
return False | ||
|
||
def update_vpc_routes(vpc_conn, peering_conn_id, src_vpc_info, dest_vpc_info): | ||
""" | ||
Update the route tables in the source VPC to point to the destination VPC. | ||
""" | ||
subnet = vpc_conn.get_all_subnets(filters={'cidr': src_vpc_info.cidr_block, | ||
'vpc_id': src_vpc_info.vpc_id}) | ||
if len(subnet) != 1: | ||
return False | ||
|
||
subnet = subnet[0] | ||
rt = vpc_conn.get_all_route_tables(filters= | ||
{'vpc_id': src_vpc_info.vpc_id, | ||
'association.subnet_id': subnet.id}) | ||
if len(rt) != 1: | ||
return False | ||
|
||
rt = rt[0] | ||
replace = False | ||
for route in rt.routes: | ||
if route.destination_cidr_block == dest_vpc_info.cidr_block: | ||
replace = True | ||
break | ||
|
||
if replace: | ||
vpc_conn.replace_route(rt.id, dest_vpc_info.cidr_block, | ||
vpc_peering_connection_id=peering_conn_id) | ||
else: | ||
vpc_conn.create_route(rt.id, dest_vpc_info.cidr_block, | ||
vpc_peering_connection_id=peering_conn_id) | ||
return True | ||
|
||
def update_routes(module, vpc_conn, peering_conn): | ||
""" | ||
Update the route tables to account for the peering connection. | ||
""" | ||
if not module.params.get('update_routes'): | ||
return | ||
|
||
update_vpc_routes(vpc_conn, peering_conn.id, | ||
peering_conn.requester_vpc_info, | ||
peering_conn.accepter_vpc_info) | ||
update_vpc_routes(vpc_conn, peering_conn.id, | ||
peering_conn.accepter_vpc_info, | ||
peering_conn.requester_vpc_info) | ||
|
||
def create_peer_connection(module, vpc_conn): | ||
""" | ||
Creates a VPC peeering connection. | ||
|
||
module: Ansible module object | ||
vpc_conn: authenticated VPCConnection connection object | ||
vpc_id: id of the requesting VPC | ||
vpc_peer_id: id of the accepting VPC | ||
timeout: how long, in seconds, to wait for connection state changes. | ||
|
||
Returns a tuple containing the peering connection id and a boolean | ||
indicating whether any changes were made. | ||
""" | ||
vpc_id = module.params.get('vpc_id') | ||
vpc_peer_id = module.params.get('vpc_peer_id') | ||
timeout = module.params.get('wait_timeout') | ||
|
||
peering_conns = vpc_conn.get_all_vpc_peering_connections(filters=[ | ||
('requester-vpc-info.vpc-id', vpc_id), | ||
('accepter-vpc-info.vpc-id', vpc_peer_id)]) | ||
for peering_conn in peering_conns: | ||
if peering_conn.status_code == 'active': | ||
return (peering_conn.id, False) | ||
if peering_conn.status_code == 'pending-acceptance': | ||
vpc_conn.accept_vpc_peering_connection(peering_conn.id) | ||
result = wait_for_connection_state(peering_conn, 'active', timeout) | ||
if result: | ||
update_routes(module, vpc_conn, peering_conn) | ||
return (peering_conn.id, True) | ||
else: | ||
module.fail_json(msg='VPC peering connection with id ' + | ||
peering_conn.id + ' could not be ' + | ||
'accepted.') | ||
|
||
peering_conn = vpc_conn.create_vpc_peering_connection(vpc_id, vpc_peer_id) | ||
wait_for_connection_state(peering_conn, 'pending-acceptance', timeout) | ||
|
||
vpc_conn.accept_vpc_peering_connection(peering_conn.id) | ||
wait_for_connection_state(peering_conn, 'active', timeout) | ||
|
||
update_routes(module, vpc_conn, peering_conn) | ||
return (peering_conn.id, True) | ||
|
||
def delete_peer_connection(module, vpc_conn): | ||
""" | ||
Deletes a VPC peering connection | ||
|
||
module: Ansible module object | ||
vpc_conn: authenticated VPCConnection connection object | ||
vpc_id: id of the requesting VPC | ||
vpc_peer_id: id of the accepting VPC | ||
|
||
Returns a list of the peering connections that have been deleted. | ||
""" | ||
vpc_id = module.params.get('vpc_id') | ||
vpc_peer_id = module.params.get('vpc_peer_id') | ||
|
||
peering_conns = vpc_conn.get_all_vpc_peering_connections(filters=[ | ||
('requester-vpc-info.vpc-id', vpc_id), | ||
('accepter-vpc-info.vpc-id', vpc_peer_id)]) | ||
removed_conns = [] | ||
for peering_conn in peering_conns: | ||
if peering_conn.status_code == 'active': | ||
if vpc_conn.delete_vpc_peering_connection(peering_conn.id): | ||
removed_conns.append(peering_conn.id) | ||
else: | ||
module.fail_json(msg="VPC peering connection with id " + | ||
peering_conn.id + " could not be " + | ||
"deleted") | ||
return removed_conns | ||
|
||
def main(): | ||
""" | ||
Module entry point. | ||
""" | ||
arguent_spec = ec2_argument_spec() | ||
arguent_spec.update(dict( | ||
vpc_id=dict(required=True), | ||
vpc_peer_id=dict(required=True), | ||
state=dict(choices=['present', 'absent'], default='present'), | ||
wait_timeout=dict(type='int', default=15), | ||
update_routes=dict(type='bool', default=True) | ||
)) | ||
module = AnsibleModule( | ||
argument_spec=arguent_spec, | ||
) | ||
|
||
state = module.params.get('state') | ||
_, aws_access_key, aws_secret_key, region = get_ec2_creds(module) | ||
|
||
if region: | ||
try: | ||
vpc_conn = boto.vpc.connect_to_region( | ||
region, | ||
aws_access_key_id=aws_access_key, | ||
aws_secret_access_key=aws_secret_key | ||
) | ||
except boto.exception.NoAuthHandlerFound, ex: | ||
module.fail_json(msg=str(ex)) | ||
else: | ||
module.fail_json(msg="region must be specified") | ||
|
||
if state == 'present': | ||
(connection, changed) = create_peer_connection(module, vpc_conn) | ||
module.exit_json(changed=changed, connection_id=connection) | ||
elif state == 'absent': | ||
removed = delete_peer_connection(module, vpc_conn) | ||
changed = (len(removed) > 0) | ||
module.exit_json(peering_connections=removed, changed=changed) | ||
|
||
from ansible.module_utils.basic import * | ||
from ansible.module_utils.ec2 import * | ||
main() |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
between two ec2 VPCs