����JFIF��������� Mr.X
  
  __  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

deexcl@216.73.217.71: ~ $
# Copyright (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type


DOCUMENTATION = r'''
---
module: ec2_vpc_vpn
version_added: 1.0.0
short_description: Create, modify, and delete EC2 VPN connections
description:
  - This module creates, modifies, and deletes VPN connections. Idempotence is achieved by using the filters
    option or specifying the VPN connection identifier.
extends_documentation_fragment:
  - amazon.aws.ec2
  - amazon.aws.aws
  - amazon.aws.boto3
  - amazon.aws.tags
author:
  - "Sloane Hertel (@s-hertel)"
options:
  state:
    description:
      - The desired state of the VPN connection.
    choices: ['present', 'absent']
    default: present
    required: false
    type: str
  customer_gateway_id:
    description:
      - The ID of the customer gateway.
    type: str
  connection_type:
    description:
      - The type of VPN connection.
      - At this time only C(ipsec.1) is supported.
    default: ipsec.1
    type: str
  vpn_gateway_id:
    description:
      - The ID of the virtual private gateway.
    type: str
  vpn_connection_id:
    description:
      - The ID of the VPN connection. Required to modify or delete a connection if the filters option does not provide a unique match.
    type: str
  static_only:
    description:
      - Indicates whether the VPN connection uses static routes only. Static routes must be used for devices that don't support BGP.
    default: False
    type: bool
    required: false
  tunnel_options:
    description:
      - An optional list object containing no more than two dict members, each of which may contain I(TunnelInsideCidr)
        and/or I(PreSharedKey) keys with appropriate string values.  AWS defaults will apply in absence of either of
        the aforementioned keys.
    required: false
    type: list
    elements: dict
    default: []
    suboptions:
        TunnelInsideCidr:
            type: str
            description: The range of inside IP addresses for the tunnel.
        PreSharedKey:
            type: str
            description: The pre-shared key (PSK) to establish initial authentication between the virtual private gateway and customer gateway.
  filters:
    description:
      - An alternative to using I(vpn_connection_id). If multiple matches are found, vpn_connection_id is required.
        If one of the following suboptions is a list of items to filter by, only one item needs to match to find the VPN
        that correlates. e.g. if the filter I(cidr) is C(['194.168.2.0/24', '192.168.2.0/24']) and the VPN route only has the
        destination cidr block of C(192.168.2.0/24) it will be found with this filter (assuming there are not multiple
        VPNs that are matched). Another example, if the filter I(vpn) is equal to C(['vpn-ccf7e7ad', 'vpn-cb0ae2a2']) and one
        of of the VPNs has the state deleted (exists but is unmodifiable) and the other exists and is not deleted,
        it will be found via this filter. See examples.
    suboptions:
      cgw-config:
        description:
          - The customer gateway configuration of the VPN as a string (in the format of the return value) or a list of those strings.
      static-routes-only:
        description:
          - The type of routing; C(true) or C(false).
      cidr:
        description:
          - The destination cidr of the VPN's route as a string or a list of those strings.
      bgp:
        description:
          - The BGP ASN number associated with a BGP device. Only works if the connection is attached.
            This filtering option is currently not working.
      vpn:
        description:
          - The VPN connection id as a string or a list of those strings.
      vgw:
        description:
          - The virtual private gateway as a string or a list of those strings.
      tag-keys:
        description:
          - The key of a tag as a string or a list of those strings.
      tag-values:
        description:
          - The value of a tag as a string or a list of those strings.
      tags:
        description:
          - A dict of key value pairs.
      cgw:
        description:
          - The customer gateway id as a string or a list of those strings.
    type: dict
    default: {}
  routes:
    description:
      - Routes to add to the connection.
    type: list
    elements: str
    default: []
  purge_routes:
    description:
      - Whether or not to delete VPN connections routes that are not specified in the task.
    type: bool
    default: false
  wait_timeout:
    description:
      - How long, in seconds, before wait gives up.
    default: 600
    type: int
    required: false
  delay:
    description:
      - The time, in seconds, to wait before checking operation again.
    required: false
    type: int
    default: 15
'''

EXAMPLES = r"""
# Note: None of these examples set aws_access_key, aws_secret_key, or region.
# It is assumed that their matching environment variables are set.

- name: create a VPN connection
  community.aws.ec2_vpc_vpn:
    state: present
    vpn_gateway_id: vgw-XXXXXXXX
    customer_gateway_id: cgw-XXXXXXXX

- name: modify VPN connection tags
  community.aws.ec2_vpc_vpn:
    state: present
    vpn_connection_id: vpn-XXXXXXXX
    tags:
      Name: ansible-tag-1
      Other: ansible-tag-2

- name: delete a connection
  community.aws.ec2_vpc_vpn:
    vpn_connection_id: vpn-XXXXXXXX
    state: absent

- name: modify VPN tags (identifying VPN by filters)
  community.aws.ec2_vpc_vpn:
    state: present
    filters:
      cidr: 194.168.1.0/24
      tag-keys:
        - Ansible
        - Other
    tags:
      New: Tag
    purge_tags: true
    static_only: true

- name: set up VPN with tunnel options utilizing 'TunnelInsideCidr' only
  community.aws.ec2_vpc_vpn:
    state: present
    filters:
      vpn: vpn-XXXXXXXX
    static_only: true
    tunnel_options:
      -
        TunnelInsideCidr: '169.254.100.1/30'
      -
        TunnelInsideCidr: '169.254.100.5/30'

- name: add routes and remove any preexisting ones
  community.aws.ec2_vpc_vpn:
    state: present
    filters:
      vpn: vpn-XXXXXXXX
    routes:
      - 195.168.2.0/24
      - 196.168.2.0/24
    purge_routes: true

- name: remove all routes
  community.aws.ec2_vpc_vpn:
    state: present
    vpn_connection_id: vpn-XXXXXXXX
    routes: []
    purge_routes: true

- name: delete a VPN identified by filters
  community.aws.ec2_vpc_vpn:
    state: absent
    filters:
      tags:
        Ansible: Tag
"""

RETURN = r"""
changed:
  description: If the VPN connection has changed.
  type: bool
  returned: always
  sample:
    changed: true
customer_gateway_configuration:
  description: The configuration of the VPN connection.
  returned: I(state=present)
  type: str
customer_gateway_id:
  description: The customer gateway connected via the connection.
  type: str
  returned: I(state=present)
  sample:
    customer_gateway_id: cgw-1220c87b
vpn_gateway_id:
  description: The virtual private gateway connected via the connection.
  type: str
  returned: I(state=present)
  sample:
    vpn_gateway_id: vgw-cb0ae2a2
options:
  description: The VPN connection options (currently only containing static_routes_only).
  type: complex
  returned: I(state=present)
  contains:
    static_routes_only:
      description: If the VPN connection only allows static routes.
      returned: I(state=present)
      type: str
      sample:
        static_routes_only: true
routes:
  description: The routes of the VPN connection.
  type: list
  returned: I(state=present)
  sample:
    routes: [{
              'destination_cidr_block': '192.168.1.0/24',
              'state': 'available'
            }]
state:
  description: The status of the VPN connection.
  type: str
  returned: I(state=present)
  sample:
    state: available
tags:
  description: The tags associated with the connection.
  type: dict
  returned: I(state=present)
  sample:
    tags:
      name: ansible-test
      other: tag
type:
  description: The type of VPN connection (currently only ipsec.1 is available).
  type: str
  returned: I(state=present)
  sample:
    type: "ipsec.1"
vgw_telemetry:
  type: list
  returned: I(state=present)
  description: The telemetry for the VPN tunnel.
  sample:
    vgw_telemetry: [{
                     'outside_ip_address': 'string',
                     'status': 'up',
                     'last_status_change': 'datetime(2015, 1, 1)',
                     'status_message': 'string',
                     'accepted_route_count': 123
                    }]
vpn_connection_id:
  description: The identifier for the VPN connection.
  type: str
  returned: I(state=present)
  sample:
    vpn_connection_id: vpn-781e0e19
"""

from ansible.module_utils._text import to_text
from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_tag_list
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_tag_list_to_ansible_dict
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import compare_aws_tags

try:
    from botocore.exceptions import BotoCoreError, ClientError, WaiterError
except ImportError:
    pass  # Handled by AnsibleAWSModule


class VPNConnectionException(Exception):
    def __init__(self, msg, exception=None):
        super(VPNConnectionException, self).__init__(msg)
        self.msg = msg
        self.exception = exception


# AWS uses VpnGatewayLimitExceeded for both 'Too many VGWs' and 'Too many concurrent changes'
# we need to look at the mesage to tell the difference.
class VPNRetry(AWSRetry):
    @staticmethod
    def status_code_from_exception(error):
        return (error.response['Error']['Code'], error.response['Error']['Message'],)

    @staticmethod
    def found(response_code, catch_extra_error_codes=None):
        retry_on = ['The maximum number of mutating objects has been reached.']

        if catch_extra_error_codes:
            retry_on.extend(catch_extra_error_codes)
        if not isinstance(response_code, tuple):
            response_code = (response_code,)

        for code in response_code:
            if super().found(response_code, catch_extra_error_codes):
                return True

        return False


def find_connection(connection, module_params, vpn_connection_id=None):
    ''' Looks for a unique VPN connection. Uses find_connection_response() to return the connection found, None,
        or raise an error if there were multiple viable connections. '''

    filters = module_params.get('filters')

    # vpn_connection_id may be provided via module option; takes precedence over any filter values
    if not vpn_connection_id and module_params.get('vpn_connection_id'):
        vpn_connection_id = module_params.get('vpn_connection_id')

    if not isinstance(vpn_connection_id, list) and vpn_connection_id:
        vpn_connection_id = [to_text(vpn_connection_id)]
    elif isinstance(vpn_connection_id, list):
        vpn_connection_id = [to_text(connection) for connection in vpn_connection_id]

    formatted_filter = []
    # if vpn_connection_id is provided it will take precedence over any filters since it is a unique identifier
    if not vpn_connection_id:
        formatted_filter = create_filter(module_params, provided_filters=filters)

    # see if there is a unique matching connection
    try:
        if vpn_connection_id:
            existing_conn = connection.describe_vpn_connections(aws_retry=True,
                                                                VpnConnectionIds=vpn_connection_id,
                                                                Filters=formatted_filter)
        else:
            existing_conn = connection.describe_vpn_connections(aws_retry=True, Filters=formatted_filter)
    except (BotoCoreError, ClientError) as e:
        raise VPNConnectionException(msg="Failed while describing VPN connection.",
                                     exception=e)

    return find_connection_response(connections=existing_conn)


def add_routes(connection, vpn_connection_id, routes_to_add):
    for route in routes_to_add:
        try:
            connection.create_vpn_connection_route(aws_retry=True,
                                                   VpnConnectionId=vpn_connection_id,
                                                   DestinationCidrBlock=route)
        except (BotoCoreError, ClientError) as e:
            raise VPNConnectionException(msg="Failed while adding route {0} to the VPN connection {1}.".format(route, vpn_connection_id),
                                         exception=e)


def remove_routes(connection, vpn_connection_id, routes_to_remove):
    for route in routes_to_remove:
        try:
            connection.delete_vpn_connection_route(aws_retry=True,
                                                   VpnConnectionId=vpn_connection_id,
                                                   DestinationCidrBlock=route)
        except (BotoCoreError, ClientError) as e:
            raise VPNConnectionException(msg="Failed to remove route {0} from the VPN connection {1}.".format(route, vpn_connection_id),
                                         exception=e)


def create_filter(module_params, provided_filters):
    """ Creates a filter using the user-specified parameters and unmodifiable options that may have been specified in the task """
    boto3ify_filter = {'cgw-config': 'customer-gateway-configuration',
                       'static-routes-only': 'option.static-routes-only',
                       'cidr': 'route.destination-cidr-block',
                       'bgp': 'bgp-asn',
                       'vpn': 'vpn-connection-id',
                       'vgw': 'vpn-gateway-id',
                       'tag-keys': 'tag-key',
                       'tag-values': 'tag-value',
                       'tags': 'tag',
                       'cgw': 'customer-gateway-id'}

    # unmodifiable options and their filter name counterpart
    param_to_filter = {"customer_gateway_id": "customer-gateway-id",
                       "vpn_gateway_id": "vpn-gateway-id",
                       "vpn_connection_id": "vpn-connection-id"}

    flat_filter_dict = {}
    formatted_filter = []

    for raw_param in dict(provided_filters):

        # fix filter names to be recognized by boto3
        if raw_param in boto3ify_filter:
            param = boto3ify_filter[raw_param]
            provided_filters[param] = provided_filters.pop(raw_param)
        elif raw_param in list(boto3ify_filter.items()):
            param = raw_param
        else:
            raise VPNConnectionException(msg="{0} is not a valid filter.".format(raw_param))

        # reformat filters with special formats
        if param == 'tag':
            for key in provided_filters[param]:
                formatted_key = 'tag:' + key
                if isinstance(provided_filters[param][key], list):
                    flat_filter_dict[formatted_key] = str(provided_filters[param][key])
                else:
                    flat_filter_dict[formatted_key] = [str(provided_filters[param][key])]
        elif param == 'option.static-routes-only':
            flat_filter_dict[param] = [str(provided_filters[param]).lower()]
        else:
            if isinstance(provided_filters[param], list):
                flat_filter_dict[param] = provided_filters[param]
            else:
                flat_filter_dict[param] = [str(provided_filters[param])]

    # if customer_gateway, vpn_gateway, or vpn_connection was specified in the task but not the filter, add it
    for param in param_to_filter:
        if param_to_filter[param] not in flat_filter_dict and module_params.get(param):
            flat_filter_dict[param_to_filter[param]] = [module_params.get(param)]

    # change the flat dict into something boto3 will understand
    formatted_filter = [{'Name': key, 'Values': value} for key, value in flat_filter_dict.items()]

    return formatted_filter


def find_connection_response(connections=None):
    """ Determine if there is a viable unique match in the connections described. Returns the unique VPN connection if one is found,
        returns None if the connection does not exist, raise an error if multiple matches are found. """

    # Found no connections
    if not connections or 'VpnConnections' not in connections:
        return None

    # Too many results
    elif connections and len(connections['VpnConnections']) > 1:
        viable = []
        for each in connections['VpnConnections']:
            # deleted connections are not modifiable
            if each['State'] not in ("deleted", "deleting"):
                viable.append(each)
        if len(viable) == 1:
            # Found one viable result; return unique match
            return viable[0]
        elif len(viable) == 0:
            # Found a result but it was deleted already; since there was only one viable result create a new one
            return None
        else:
            raise VPNConnectionException(msg="More than one matching VPN connection was found. "
                                         "To modify or delete a VPN please specify vpn_connection_id or add filters.")

    # Found unique match
    elif connections and len(connections['VpnConnections']) == 1:
        # deleted connections are not modifiable
        if connections['VpnConnections'][0]['State'] not in ("deleted", "deleting"):
            return connections['VpnConnections'][0]


def create_connection(connection, customer_gateway_id, static_only, vpn_gateway_id, connection_type, max_attempts, delay, tunnel_options=None):
    """ Creates a VPN connection """

    options = {'StaticRoutesOnly': static_only}
    if tunnel_options and len(tunnel_options) <= 2:
        t_opt = []
        for m in tunnel_options:
            # See Boto3 docs regarding 'create_vpn_connection'
            # tunnel options for allowed 'TunnelOptions' keys.
            if not isinstance(m, dict):
                raise TypeError("non-dict list member")
            t_opt.append(m)
        if t_opt:
            options['TunnelOptions'] = t_opt

    if not (customer_gateway_id and vpn_gateway_id):
        raise VPNConnectionException(msg="No matching connection was found. To create a new connection you must provide "
                                     "both vpn_gateway_id and customer_gateway_id.")
    try:
        vpn = connection.create_vpn_connection(Type=connection_type,
                                               CustomerGatewayId=customer_gateway_id,
                                               VpnGatewayId=vpn_gateway_id,
                                               Options=options)
        connection.get_waiter('vpn_connection_available').wait(
            VpnConnectionIds=[vpn['VpnConnection']['VpnConnectionId']],
            WaiterConfig={'Delay': delay, 'MaxAttempts': max_attempts}
        )
    except WaiterError as e:
        raise VPNConnectionException(msg="Failed to wait for VPN connection {0} to be available".format(vpn['VpnConnection']['VpnConnectionId']),
                                     exception=e)
    except (BotoCoreError, ClientError) as e:
        raise VPNConnectionException(msg="Failed to create VPN connection",
                                     exception=e)

    return vpn['VpnConnection']


def delete_connection(connection, vpn_connection_id, delay, max_attempts):
    """ Deletes a VPN connection """
    try:
        connection.delete_vpn_connection(aws_retry=True, VpnConnectionId=vpn_connection_id)
        connection.get_waiter('vpn_connection_deleted').wait(
            VpnConnectionIds=[vpn_connection_id],
            WaiterConfig={'Delay': delay, 'MaxAttempts': max_attempts}
        )
    except WaiterError as e:
        raise VPNConnectionException(msg="Failed to wait for VPN connection {0} to be removed".format(vpn_connection_id),
                                     exception=e)
    except (BotoCoreError, ClientError) as e:
        raise VPNConnectionException(msg="Failed to delete the VPN connection: {0}".format(vpn_connection_id),
                                     exception=e)


def add_tags(connection, vpn_connection_id, add):
    try:
        connection.create_tags(aws_retry=True,
                               Resources=[vpn_connection_id],
                               Tags=add)
    except (BotoCoreError, ClientError) as e:
        raise VPNConnectionException(msg="Failed to add the tags: {0}.".format(add),
                                     exception=e)


def remove_tags(connection, vpn_connection_id, remove):
    # format tags since they are a list in the format ['tag1', 'tag2', 'tag3']
    key_dict_list = [{'Key': tag} for tag in remove]
    try:
        connection.delete_tags(aws_retry=True,
                               Resources=[vpn_connection_id],
                               Tags=key_dict_list)
    except (BotoCoreError, ClientError) as e:
        raise VPNConnectionException(msg="Failed to remove the tags: {0}.".format(remove),
                                     exception=e)


def check_for_update(connection, module_params, vpn_connection_id):
    """ Determines if there are any tags or routes that need to be updated. Ensures non-modifiable attributes aren't expected to change. """
    tags = module_params.get('tags')
    routes = module_params.get('routes')
    purge_tags = module_params.get('purge_tags')
    purge_routes = module_params.get('purge_routes')

    vpn_connection = find_connection(connection, module_params, vpn_connection_id=vpn_connection_id)
    current_attrs = camel_dict_to_snake_dict(vpn_connection)

    # Initialize changes dict
    changes = {'tags_to_add': [],
               'tags_to_remove': [],
               'routes_to_add': [],
               'routes_to_remove': []}

    # Get changes to tags
    current_tags = boto3_tag_list_to_ansible_dict(current_attrs.get('tags', []), u'key', u'value')
    if tags is None:
        changes['tags_to_remove'] = []
        changes['tags_to_add'] = []
    else:
        tags_to_add, changes['tags_to_remove'] = compare_aws_tags(current_tags, tags, purge_tags)
        changes['tags_to_add'] = ansible_dict_to_boto3_tag_list(tags_to_add)
    # Get changes to routes
    if 'Routes' in vpn_connection:
        current_routes = [route['DestinationCidrBlock'] for route in vpn_connection['Routes']]
        if purge_routes:
            changes['routes_to_remove'] = [old_route for old_route in current_routes if old_route not in routes]
        changes['routes_to_add'] = [new_route for new_route in routes if new_route not in current_routes]

    # Check if nonmodifiable attributes are attempted to be modified
    for attribute in current_attrs:
        if attribute in ("tags", "routes", "state"):
            continue
        elif attribute == 'options':
            will_be = module_params.get('static_only', None)
            is_now = bool(current_attrs[attribute]['static_routes_only'])
            attribute = 'static_only'
        elif attribute == 'type':
            will_be = module_params.get("connection_type", None)
            is_now = current_attrs[attribute]
        else:
            is_now = current_attrs[attribute]
            will_be = module_params.get(attribute, None)

        if will_be is not None and to_text(will_be) != to_text(is_now):
            raise VPNConnectionException(msg="You cannot modify {0}, the current value of which is {1}. Modifiable VPN "
                                         "connection attributes are tags and routes. The value you tried to change it to "
                                         "is {2}.".format(attribute, is_now, will_be))

    return changes


def make_changes(connection, vpn_connection_id, changes):
    """ changes is a dict with the keys 'tags_to_add', 'tags_to_remove', 'routes_to_add', 'routes_to_remove',
        the values of which are lists (generated by check_for_update()).
    """
    changed = False

    if changes['tags_to_add']:
        changed = True
        add_tags(connection, vpn_connection_id, changes['tags_to_add'])

    if changes['tags_to_remove']:
        changed = True
        remove_tags(connection, vpn_connection_id, changes['tags_to_remove'])

    if changes['routes_to_add']:
        changed = True
        add_routes(connection, vpn_connection_id, changes['routes_to_add'])

    if changes['routes_to_remove']:
        changed = True
        remove_routes(connection, vpn_connection_id, changes['routes_to_remove'])

    return changed


def get_check_mode_results(connection, module_params, vpn_connection_id=None, current_state=None):
    """ Returns the changes that would be made to a VPN Connection """
    state = module_params.get('state')
    if state == 'absent':
        if vpn_connection_id:
            return True, {}
        else:
            return False, {}

    changed = False
    results = {'customer_gateway_configuration': '',
               'customer_gateway_id': module_params.get('customer_gateway_id'),
               'vpn_gateway_id': module_params.get('vpn_gateway_id'),
               'options': {'static_routes_only': module_params.get('static_only')},
               'routes': [module_params.get('routes')]}

    # get combined current tags and tags to set
    present_tags = module_params.get('tags')
    if present_tags is None:
        pass
    elif current_state and 'Tags' in current_state:
        current_tags = boto3_tag_list_to_ansible_dict(current_state['Tags'])
        tags_to_add, tags_to_remove = compare_aws_tags(current_tags, present_tags, module_params.get('purge_tags'))
        changed |= bool(tags_to_remove) or bool(tags_to_add)
        if module_params.get('purge_tags'):
            current_tags = {}
        current_tags.update(present_tags)
        results['tags'] = current_tags
    elif module_params.get('tags'):
        changed = True
    if present_tags:
        results['tags'] = present_tags

    # get combined current routes and routes to add
    present_routes = module_params.get('routes')
    if current_state and 'Routes' in current_state:
        current_routes = [route['DestinationCidrBlock'] for route in current_state['Routes']]
        if module_params.get('purge_routes'):
            if set(current_routes) != set(present_routes):
                changed = True
        elif set(present_routes) != set(current_routes):
            if not set(present_routes) < set(current_routes):
                changed = True
            present_routes.extend([route for route in current_routes if route not in present_routes])
    elif module_params.get('routes'):
        changed = True
    results['routes'] = [{"destination_cidr_block": cidr, "state": "available"} for cidr in present_routes]

    # return the vpn_connection_id if it's known
    if vpn_connection_id:
        results['vpn_connection_id'] = vpn_connection_id
    else:
        changed = True
        results['vpn_connection_id'] = 'vpn-XXXXXXXX'

    return changed, results


def ensure_present(connection, module_params, check_mode=False):
    """ Creates and adds tags to a VPN connection. If the connection already exists update tags. """
    vpn_connection = find_connection(connection, module_params)
    changed = False
    delay = module_params.get('delay')
    max_attempts = module_params.get('wait_timeout') // delay

    # No match but vpn_connection_id was specified.
    if not vpn_connection and module_params.get('vpn_connection_id'):
        raise VPNConnectionException(msg="There is no VPN connection available or pending with that id. Did you delete it?")

    # Unique match was found. Check if attributes provided differ.
    elif vpn_connection:
        vpn_connection_id = vpn_connection['VpnConnectionId']
        # check_for_update returns a dict with the keys tags_to_add, tags_to_remove, routes_to_add, routes_to_remove
        changes = check_for_update(connection, module_params, vpn_connection_id)
        if check_mode:
            return get_check_mode_results(connection, module_params, vpn_connection_id, current_state=vpn_connection)
        changed = make_changes(connection, vpn_connection_id, changes)

    # No match was found. Create and tag a connection and add routes.
    else:
        changed = True
        if check_mode:
            return get_check_mode_results(connection, module_params)
        vpn_connection = create_connection(connection,
                                           customer_gateway_id=module_params.get('customer_gateway_id'),
                                           static_only=module_params.get('static_only'),
                                           vpn_gateway_id=module_params.get('vpn_gateway_id'),
                                           connection_type=module_params.get('connection_type'),
                                           tunnel_options=module_params.get('tunnel_options'),
                                           max_attempts=max_attempts,
                                           delay=delay)
        changes = check_for_update(connection, module_params, vpn_connection['VpnConnectionId'])
        make_changes(connection, vpn_connection['VpnConnectionId'], changes)

    # get latest version if a change has been made and make tags output nice before returning it
    if vpn_connection:
        vpn_connection = find_connection(connection, module_params, vpn_connection['VpnConnectionId'])
        if 'Tags' in vpn_connection:
            vpn_connection['Tags'] = boto3_tag_list_to_ansible_dict(vpn_connection['Tags'])

    return changed, vpn_connection


def ensure_absent(connection, module_params, check_mode=False):
    """ Deletes a VPN connection if it exists. """
    vpn_connection = find_connection(connection, module_params)

    if check_mode:
        return get_check_mode_results(connection, module_params, vpn_connection['VpnConnectionId'] if vpn_connection else None)

    delay = module_params.get('delay')
    max_attempts = module_params.get('wait_timeout') // delay

    if vpn_connection:
        delete_connection(connection, vpn_connection['VpnConnectionId'], delay=delay, max_attempts=max_attempts)
        changed = True
    else:
        changed = False

    return changed, {}


def main():
    argument_spec = dict(
        state=dict(type='str', default='present', choices=['present', 'absent']),
        filters=dict(type='dict', default={}),
        vpn_gateway_id=dict(type='str'),
        tags=dict(type='dict', aliases=['resource_tags']),
        connection_type=dict(default='ipsec.1', type='str'),
        tunnel_options=dict(no_log=True, type='list', default=[], elements='dict'),
        static_only=dict(default=False, type='bool'),
        customer_gateway_id=dict(type='str'),
        vpn_connection_id=dict(type='str'),
        purge_tags=dict(type='bool', default=True),
        routes=dict(type='list', default=[], elements='str'),
        purge_routes=dict(type='bool', default=False),
        wait_timeout=dict(type='int', default=600),
        delay=dict(type='int', default=15),
    )
    module = AnsibleAWSModule(argument_spec=argument_spec,
                              supports_check_mode=True)
    connection = module.client('ec2', retry_decorator=VPNRetry.jittered_backoff(retries=10))

    state = module.params.get('state')
    parameters = dict(module.params)

    try:
        if state == 'present':
            changed, response = ensure_present(connection, parameters, module.check_mode)
        elif state == 'absent':
            changed, response = ensure_absent(connection, parameters, module.check_mode)
    except VPNConnectionException as e:
        if e.exception:
            module.fail_json_aws(e.exception, msg=e.msg)
        else:
            module.fail_json(msg=e.msg)

    module.exit_json(changed=changed, **camel_dict_to_snake_dict(response))


if __name__ == '__main__':
    main()

Filemanager

Name Type Size Permission Actions
__pycache__ Folder 0755
__init__.py File 0 B 0644
accessanalyzer_validate_policy_info.py File 8.57 KB 0644
acm_certificate.py File 21.94 KB 0644
acm_certificate_info.py File 9.61 KB 0644
api_gateway.py File 12.97 KB 0644
api_gateway_domain.py File 12.43 KB 0644
application_autoscaling_policy.py File 22.77 KB 0644
autoscaling_complete_lifecycle_action.py File 2.88 KB 0644
autoscaling_instance_refresh.py File 9.89 KB 0644
autoscaling_instance_refresh_info.py File 7.21 KB 0644
autoscaling_launch_config.py File 24.4 KB 0644
autoscaling_launch_config_find.py File 6.45 KB 0644
autoscaling_launch_config_info.py File 6.78 KB 0644
autoscaling_lifecycle_hook.py File 10.57 KB 0644
autoscaling_policy.py File 23.13 KB 0644
autoscaling_scheduled_action.py File 9.42 KB 0644
aws_region_info.py File 3.06 KB 0644
batch_compute_environment.py File 15.81 KB 0644
batch_job_definition.py File 15.89 KB 0644
batch_job_queue.py File 9.5 KB 0644
cloudformation_exports_info.py File 2.11 KB 0644
cloudformation_stack_set.py File 31.98 KB 0644
cloudfront_distribution.py File 98.71 KB 0644
cloudfront_distribution_info.py File 28.98 KB 0644
cloudfront_invalidation.py File 10 KB 0644
cloudfront_origin_access_identity.py File 9.38 KB 0644
cloudfront_response_headers_policy.py File 10.55 KB 0644
codebuild_project.py File 18.98 KB 0644
codecommit_repository.py File 7.94 KB 0644
codepipeline.py File 10.71 KB 0644
config_aggregation_authorization.py File 5.11 KB 0644
config_aggregator.py File 7.95 KB 0644
config_delivery_channel.py File 7.68 KB 0644
config_recorder.py File 7.7 KB 0644
config_rule.py File 9.85 KB 0644
data_pipeline.py File 20.86 KB 0644
directconnect_confirm_connection.py File 5.47 KB 0644
directconnect_connection.py File 12.34 KB 0644
directconnect_gateway.py File 13.25 KB 0644
directconnect_link_aggregation_group.py File 17.75 KB 0644
directconnect_virtual_interface.py File 17.79 KB 0644
dms_endpoint.py File 22.77 KB 0644
dms_replication_subnet_group.py File 7.58 KB 0644
dynamodb_table.py File 35.98 KB 0644
dynamodb_ttl.py File 4.61 KB 0644
ec2_ami_copy.py File 6.98 KB 0644
ec2_customer_gateway.py File 7.89 KB 0644
ec2_customer_gateway_info.py File 4.59 KB 0644
ec2_launch_template.py File 35.09 KB 0644
ec2_placement_group.py File 7.33 KB 0644
ec2_placement_group_info.py File 3.12 KB 0644
ec2_snapshot_copy.py File 5.41 KB 0644
ec2_transit_gateway.py File 17.24 KB 0644
ec2_transit_gateway_info.py File 8.87 KB 0644
ec2_transit_gateway_vpc_attachment.py File 10.92 KB 0644
ec2_transit_gateway_vpc_attachment_info.py File 5.61 KB 0644
ec2_vpc_egress_igw.py File 6.15 KB 0644
ec2_vpc_nacl.py File 21.18 KB 0644
ec2_vpc_nacl_info.py File 7.17 KB 0644
ec2_vpc_peer.py File 20.84 KB 0644
ec2_vpc_peering_info.py File 8.97 KB 0644
ec2_vpc_vgw.py File 19.07 KB 0644
ec2_vpc_vgw_info.py File 5.68 KB 0644
ec2_vpc_vpn.py File 31.5 KB 0644
ec2_vpc_vpn_info.py File 7.29 KB 0644
ec2_win_password.py File 6.92 KB 0644
ecs_attribute.py File 9.78 KB 0644
ecs_cluster.py File 13.19 KB 0644
ecs_ecr.py File 21.46 KB 0644
ecs_service.py File 52.33 KB 0644
ecs_service_info.py File 8.5 KB 0644
ecs_tag.py File 7.35 KB 0644
ecs_task.py File 17.41 KB 0644
ecs_taskdefinition.py File 52.04 KB 0644
ecs_taskdefinition_info.py File 13.78 KB 0644
efs.py File 28.21 KB 0644
efs_info.py File 12.85 KB 0644
efs_tag.py File 5.45 KB 0644
eks_cluster.py File 9.62 KB 0644
eks_fargate_profile.py File 11.73 KB 0644
eks_nodegroup.py File 26.17 KB 0644
elasticache.py File 19.82 KB 0644
elasticache_info.py File 17.68 KB 0644
elasticache_parameter_group.py File 13.25 KB 0644
elasticache_snapshot.py File 6.82 KB 0644
elasticache_subnet_group.py File 7.56 KB 0644
elasticbeanstalk_app.py File 7.15 KB 0644
elb_classic_lb_info.py File 7.48 KB 0644
elb_instance.py File 14.27 KB 0644
elb_network_lb.py File 19.14 KB 0644
elb_target.py File 11.59 KB 0644
elb_target_group.py File 43.95 KB 0644
elb_target_group_info.py File 11.46 KB 0644
elb_target_info.py File 15.78 KB 0644
glue_connection.py File 15.36 KB 0644
glue_crawler.py File 15.58 KB 0644
glue_job.py File 18.09 KB 0644
iam_access_key.py File 9.94 KB 0644
iam_access_key_info.py File 3.56 KB 0644
iam_group.py File 16.21 KB 0644
iam_managed_policy.py File 14.16 KB 0644
iam_mfa_device_info.py File 2.92 KB 0644
iam_password_policy.py File 7.15 KB 0644
iam_role.py File 29.67 KB 0644
iam_role_info.py File 9.36 KB 0644
iam_saml_federation.py File 9.01 KB 0644
iam_server_certificate.py File 12.14 KB 0644
iam_server_certificate_info.py File 4.85 KB 0644
inspector_target.py File 7.73 KB 0644
kinesis_stream.py File 40.98 KB 0644
lightsail.py File 10.15 KB 0644
lightsail_static_ip.py File 3.89 KB 0644
msk_cluster.py File 31.56 KB 0644
msk_config.py File 9.28 KB 0644
networkfirewall.py File 11.7 KB 0644
networkfirewall_info.py File 7.24 KB 0644
networkfirewall_policy.py File 16.36 KB 0644
networkfirewall_policy_info.py File 8.78 KB 0644
networkfirewall_rule_group.py File 32.96 KB 0644
networkfirewall_rule_group_info.py File 17.8 KB 0644
opensearch.py File 55.85 KB 0644
opensearch_info.py File 19.48 KB 0644
redshift.py File 23.82 KB 0644
redshift_cross_region_snapshots.py File 6.7 KB 0644
redshift_info.py File 10.04 KB 0644
redshift_subnet_group.py File 8.18 KB 0644
s3_bucket_info.py File 20.69 KB 0644
s3_bucket_notification.py File 14.04 KB 0644
s3_cors.py File 4.18 KB 0644
s3_lifecycle.py File 26.91 KB 0644
s3_logging.py File 6.76 KB 0644
s3_metrics_configuration.py File 7.31 KB 0644
s3_sync.py File 18.77 KB 0644
s3_website.py File 11.37 KB 0644
secretsmanager_secret.py File 24.07 KB 0644
ses_identity.py File 22.99 KB 0644
ses_identity_policy.py File 7.39 KB 0644
ses_rule_set.py File 8.17 KB 0644
sns.py File 7.26 KB 0644
sns_topic.py File 27.72 KB 0644
sns_topic_info.py File 6.13 KB 0644
sqs_queue.py File 16.62 KB 0644
ssm_parameter.py File 19.82 KB 0644
stepfunctions_state_machine.py File 7.96 KB 0644
stepfunctions_state_machine_execution.py File 6.59 KB 0644
storagegateway_info.py File 11.46 KB 0644
sts_assume_role.py File 5.69 KB 0644
sts_session_token.py File 4.44 KB 0644
waf_condition.py File 29.29 KB 0644
waf_info.py File 4.27 KB 0644
waf_rule.py File 13.05 KB 0644
waf_web_acl.py File 12.41 KB 0644
wafv2_ip_set.py File 11.29 KB 0644
wafv2_ip_set_info.py File 3.93 KB 0644
wafv2_resources.py File 4.73 KB 0644
wafv2_resources_info.py File 3.11 KB 0644
wafv2_rule_group.py File 13.82 KB 0644
wafv2_rule_group_info.py File 4.64 KB 0644
wafv2_web_acl.py File 19.46 KB 0644
wafv2_web_acl_info.py File 3.95 KB 0644