You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ansible/test/units/modules/cloud/amazon/test_ec2_vpc_vpn.py

364 lines
15 KiB
Python

# (c) 2017 Red Hat Inc.
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
import pytest
import os
from units.utils.amazon_placebo_fixtures import placeboify, maybe_sleep
from ansible.modules.cloud.amazon import ec2_vpc_vpn
from ansible.module_utils.ec2 import get_aws_connection_info, boto3_conn, boto3_tag_list_to_ansible_dict
class FakeModule(object):
def __init__(self, **kwargs):
self.params = kwargs
def fail_json(self, *args, **kwargs):
self.exit_args = args
self.exit_kwargs = kwargs
raise Exception('FAIL')
def exit_json(self, *args, **kwargs):
self.exit_args = args
self.exit_kwargs = kwargs
def get_vgw(connection):
# see if two vgw exist and return them if so
vgw = connection.describe_vpn_gateways(Filters=[{'Name': 'tag:Ansible_VPN', 'Values': ['Test']}])
if len(vgw['VpnGateways']) >= 2:
return [vgw['VpnGateways'][0]['VpnGatewayId'], vgw['VpnGateways'][1]['VpnGatewayId']]
# otherwise create two and return them
vgw_1 = connection.create_vpn_gateway(Type='ipsec.1')
vgw_2 = connection.create_vpn_gateway(Type='ipsec.1')
for resource in (vgw_1, vgw_2):
connection.create_tags(Resources=[resource['VpnGateway']['VpnGatewayId']], Tags=[{'Key': 'Ansible_VPN', 'Value': 'Test'}])
return [vgw_1['VpnGateway']['VpnGatewayId'], vgw_2['VpnGateway']['VpnGatewayId']]
def get_cgw(connection):
# see if two cgw exist and return them if so
cgw = connection.describe_customer_gateways(DryRun=False, Filters=[{'Name': 'state', 'Values': ['available']},
{'Name': 'tag:Name', 'Values': ['Ansible-CGW']}])
if len(cgw['CustomerGateways']) >= 2:
return [cgw['CustomerGateways'][0]['CustomerGatewayId'], cgw['CustomerGateways'][1]['CustomerGatewayId']]
# otherwise create and return them
cgw_1 = connection.create_customer_gateway(DryRun=False, Type='ipsec.1', PublicIp='9.8.7.6', BgpAsn=65000)
cgw_2 = connection.create_customer_gateway(DryRun=False, Type='ipsec.1', PublicIp='5.4.3.2', BgpAsn=65000)
for resource in (cgw_1, cgw_2):
connection.create_tags(Resources=[resource['CustomerGateway']['CustomerGatewayId']], Tags=[{'Key': 'Ansible-CGW', 'Value': 'Test'}])
return [cgw_1['CustomerGateway']['CustomerGatewayId'], cgw_2['CustomerGateway']['CustomerGatewayId']]
def get_dependencies():
if os.getenv('PLACEBO_RECORD'):
module = FakeModule(**{})
region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True)
connection = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_kwargs)
vgw = get_vgw(connection)
cgw = get_cgw(connection)
else:
vgw = ["vgw-35d70c2b", "vgw-32d70c2c"]
cgw = ["cgw-6113c87f", "cgw-9e13c880"]
return cgw, vgw
def setup_mod_conn(placeboify, params):
conn = placeboify.client('ec2')
m = FakeModule(**params)
return m, conn
def make_params(cgw, vgw, tags=None, filters=None, routes=None):
tags = {} if tags is None else tags
filters = {} if filters is None else filters
routes = [] if routes is None else routes
return {'customer_gateway_id': cgw,
'static_only': True,
'vpn_gateway_id': vgw,
'connection_type': 'ipsec.1',
'purge_tags': True,
'tags': tags,
'filters': filters,
'routes': routes,
'delay': 15,
'wait_timeout': 600}
def make_conn(placeboify, module, connection):
customer_gateway_id = module.params['customer_gateway_id']
static_only = module.params['static_only']
vpn_gateway_id = module.params['vpn_gateway_id']
connection_type = module.params['connection_type']
check_mode = module.params['check_mode']
changed = True
vpn = ec2_vpc_vpn.create_connection(connection, customer_gateway_id, static_only, vpn_gateway_id, connection_type)
return changed, vpn
def tear_down_conn(placeboify, connection, vpn_connection_id):
ec2_vpc_vpn.delete_connection(connection, vpn_connection_id, delay=15, max_attempts=40)
def test_find_connection_vpc_conn_id(placeboify, maybe_sleep):
# setup dependencies for 2 vpn connections
dependencies = setup_req(placeboify, 2)
dep1, dep2 = dependencies[0], dependencies[1]
params1, vpn1, m1, conn1 = dep1['params'], dep1['vpn'], dep1['module'], dep1['connection']
params2, vpn2, m2, conn2 = dep2['params'], dep2['vpn'], dep2['module'], dep2['connection']
# find the connection with a vpn_connection_id and assert it is the expected one
assert vpn1['VpnConnectionId'] == ec2_vpc_vpn.find_connection(conn1, params1, vpn1['VpnConnectionId'])['VpnConnectionId']
tear_down_conn(placeboify, conn1, vpn1['VpnConnectionId'])
tear_down_conn(placeboify, conn2, vpn2['VpnConnectionId'])
def test_find_connection_filters(placeboify, maybe_sleep):
# setup dependencies for 2 vpn connections
dependencies = setup_req(placeboify, 2)
dep1, dep2 = dependencies[0], dependencies[1]
params1, vpn1, m1, conn1 = dep1['params'], dep1['vpn'], dep1['module'], dep1['connection']
params2, vpn2, m2, conn2 = dep2['params'], dep2['vpn'], dep2['module'], dep2['connection']
# update to different tags
params1.update(tags={'Wrong': 'Tag'})
params2.update(tags={'Correct': 'Tag'})
ec2_vpc_vpn.ensure_present(conn1, params1)
ec2_vpc_vpn.ensure_present(conn2, params2)
# create some new parameters for a filter
params = {'filters': {'tags': {'Correct': 'Tag'}}}
# find the connection that has the parameters above
found = ec2_vpc_vpn.find_connection(conn1, params)
# assert the correct connection was found
assert found['VpnConnectionId'] == vpn2['VpnConnectionId']
# delete the connections
tear_down_conn(placeboify, conn1, vpn1['VpnConnectionId'])
tear_down_conn(placeboify, conn2, vpn2['VpnConnectionId'])
def test_find_connection_insufficient_filters(placeboify, maybe_sleep):
# get list of customer gateways and virtual private gateways
cgw, vgw = get_dependencies()
# create two connections with the same tags
params = make_params(cgw[0], vgw[0], tags={'Correct': 'Tag'})
params2 = make_params(cgw[1], vgw[1], tags={'Correct': 'Tag'})
m, conn = setup_mod_conn(placeboify, params)
m2, conn2 = setup_mod_conn(placeboify, params2)
_, vpn1 = ec2_vpc_vpn.ensure_present(conn, m.params)
_, vpn2 = ec2_vpc_vpn.ensure_present(conn2, m2.params)
# reset the parameters so only filtering by tags will occur
m.params = {'filters': {'tags': {'Correct': 'Tag'}}}
# assert that multiple matching connections have been found
with pytest.raises(Exception) as error_message:
ec2_vpc_vpn.find_connection(conn, m.params)
assert error_message == "More than one matching VPN connection was found.To modify or delete a VPN please specify vpn_connection_id or add filters."
# delete the connections
tear_down_conn(placeboify, conn, vpn1['VpnConnectionId'])
tear_down_conn(placeboify, conn, vpn2['VpnConnectionId'])
def test_find_connection_nonexistent(placeboify, maybe_sleep):
# create parameters but don't create a connection with them
params = {'filters': {'tags': {'Correct': 'Tag'}}}
m, conn = setup_mod_conn(placeboify, params)
# try to find a connection with matching parameters and assert None are found
assert ec2_vpc_vpn.find_connection(conn, m.params) is None
def test_create_connection(placeboify, maybe_sleep):
# get list of customer gateways and virtual private gateways
cgw, vgw = get_dependencies()
# create a connection
params = make_params(cgw[0], vgw[0])
m, conn = setup_mod_conn(placeboify, params)
changed, vpn = ec2_vpc_vpn.ensure_present(conn, m.params)
# assert that changed is true and that there is a connection id
assert changed is True
assert 'VpnConnectionId' in vpn
# delete connection
tear_down_conn(placeboify, conn, vpn['VpnConnectionId'])
def test_create_connection_that_exists(placeboify, maybe_sleep):
# setup dependencies for 1 vpn connection
dependencies = setup_req(placeboify, 1)
params, vpn, m, conn = dependencies['params'], dependencies['vpn'], dependencies['module'], dependencies['connection']
# try to recreate the same connection
changed, vpn2 = ec2_vpc_vpn.ensure_present(conn, params)
# nothing should have changed
assert changed is False
assert vpn['VpnConnectionId'] == vpn2['VpnConnectionId']
# delete connection
tear_down_conn(placeboify, conn, vpn['VpnConnectionId'])
def test_modify_deleted_connection(placeboify, maybe_sleep):
# setup dependencies for 1 vpn connection
dependencies = setup_req(placeboify, 1)
params, vpn, m, conn = dependencies['params'], dependencies['vpn'], dependencies['module'], dependencies['connection']
# delete it
tear_down_conn(placeboify, conn, vpn['VpnConnectionId'])
# try to update the deleted connection
m.params.update(vpn_connection_id=vpn['VpnConnectionId'])
with pytest.raises(Exception) as error_message:
ec2_vpc_vpn.ensure_present(conn, m.params)
assert error_message == "There is no VPN connection available or pending with that id. Did you delete it?"
def test_delete_connection(placeboify, maybe_sleep):
# setup dependencies for 1 vpn connection
dependencies = setup_req(placeboify, 1)
params, vpn, m, conn = dependencies['params'], dependencies['vpn'], dependencies['module'], dependencies['connection']
# delete it
changed, vpn = ec2_vpc_vpn.ensure_absent(conn, m.params)
assert changed is True
assert vpn == {}
def test_delete_nonexistent_connection(placeboify, maybe_sleep):
# create parameters and ensure any connection matching (None) is deleted
params = {'filters': {'tags': {'ThisConnection': 'DoesntExist'}}, 'delay': 15, 'wait_timeout': 600}
m, conn = setup_mod_conn(placeboify, params)
changed, vpn = ec2_vpc_vpn.ensure_absent(conn, m.params)
assert changed is False
assert vpn == {}
def test_check_for_update_tags(placeboify, maybe_sleep):
# setup dependencies for 1 vpn connection
dependencies = setup_req(placeboify, 1)
params, vpn, m, conn = dependencies['params'], dependencies['vpn'], dependencies['module'], dependencies['connection']
# add and remove a number of tags
m.params['tags'] = {'One': 'one', 'Two': 'two'}
ec2_vpc_vpn.ensure_present(conn, m.params)
m.params['tags'] = {'Two': 'two', 'Three': 'three', 'Four': 'four'}
changes = ec2_vpc_vpn.check_for_update(conn, m.params, vpn['VpnConnectionId'])
flat_dict_changes = boto3_tag_list_to_ansible_dict(changes['tags_to_add'])
correct_changes = boto3_tag_list_to_ansible_dict([{'Key': 'Three', 'Value': 'three'}, {'Key': 'Four', 'Value': 'four'}])
assert flat_dict_changes == correct_changes
assert changes['tags_to_remove'] == ['One']
# delete connection
tear_down_conn(placeboify, conn, vpn['VpnConnectionId'])
def test_check_for_update_nonmodifiable_attr(placeboify, maybe_sleep):
# setup dependencies for 1 vpn connection
dependencies = setup_req(placeboify, 1)
params, vpn, m, conn = dependencies['params'], dependencies['vpn'], dependencies['module'], dependencies['connection']
current_vgw = params['vpn_gateway_id']
# update a parameter that isn't modifiable
m.params.update(vpn_gateway_id="invalidchange")
err = 'You cannot modify vpn_gateway_id, the current value of which is {0}. Modifiable VPN connection attributes are tags.'.format(current_vgw)
with pytest.raises(Exception) as error_message:
ec2_vpc_vpn.check_for_update(m, conn, vpn['VpnConnectionId'])
assert error_message == err
# delete connection
tear_down_conn(placeboify, conn, vpn['VpnConnectionId'])
def test_add_tags(placeboify, maybe_sleep):
# setup dependencies for 1 vpn connection
dependencies = setup_req(placeboify, 1)
params, vpn, m, conn = dependencies['params'], dependencies['vpn'], dependencies['module'], dependencies['connection']
# add a tag to the connection
ec2_vpc_vpn.add_tags(conn, vpn['VpnConnectionId'], add=[{'Key': 'Ansible-Test', 'Value': 'VPN'}])
# assert tag is there
current_vpn = ec2_vpc_vpn.find_connection(conn, params)
assert current_vpn['Tags'] == [{'Key': 'Ansible-Test', 'Value': 'VPN'}]
# delete connection
tear_down_conn(placeboify, conn, vpn['VpnConnectionId'])
def test_remove_tags(placeboify, maybe_sleep):
# setup dependencies for 1 vpn connection
dependencies = setup_req(placeboify, 1)
params, vpn, m, conn = dependencies['params'], dependencies['vpn'], dependencies['module'], dependencies['connection']
# remove a tag from the connection
ec2_vpc_vpn.remove_tags(conn, vpn['VpnConnectionId'], remove=['Ansible-Test'])
# assert the tag is gone
current_vpn = ec2_vpc_vpn.find_connection(conn, params)
assert 'Tags' not in current_vpn
# delete connection
tear_down_conn(placeboify, conn, vpn['VpnConnectionId'])
def test_add_routes(placeboify, maybe_sleep):
# setup dependencies for 1 vpn connection
dependencies = setup_req(placeboify, 1)
params, vpn, m, conn = dependencies['params'], dependencies['vpn'], dependencies['module'], dependencies['connection']
# create connection with a route
ec2_vpc_vpn.add_routes(conn, vpn['VpnConnectionId'], ['195.168.2.0/24', '196.168.2.0/24'])
# assert both routes are there
current_vpn = ec2_vpc_vpn.find_connection(conn, params)
assert set(each['DestinationCidrBlock'] for each in current_vpn['Routes']) == set(['195.168.2.0/24', '196.168.2.0/24'])
# delete connection
tear_down_conn(placeboify, conn, vpn['VpnConnectionId'])
def setup_req(placeboify, number_of_results=1):
''' returns dependencies for VPN connections '''
assert number_of_results in (1, 2)
results = []
cgw, vgw = get_dependencies()
for each in range(0, number_of_results):
params = make_params(cgw[each], vgw[each])
m, conn = setup_mod_conn(placeboify, params)
_, vpn = ec2_vpc_vpn.ensure_present(conn, params)
results.append({'module': m, 'connection': conn, 'vpn': vpn, 'params': params})
if number_of_results == 1:
return results[0]
else:
return results[0], results[1]